raphael 3 years ago
parent
commit
9336faee56

+ 34
- 15
Controller/LearningSpace/JupyterVirtualClassroomController.php View File

@@ -29,12 +29,13 @@ use Logipro\Phoenix\Entity\Track;
29 29
 use Logipro\Phoenix\Entity\Session\Session;
30 30
 use Logipro\Bundle\PhoenixJupyterBundle\Entity\JupyterSubmission;
31 31
 use Logipro\Bundle\PhoenixJupyterBundle\Services\PhoenixServices;
32
+use Symfony\Bundle\FrameworkBundle\Routing\Router;
32 33
 
33 34
 class JupyterVirtualClassroomController extends LearningSpaceController
34 35
 {
35 36
 	private $layoutPath = '@LogiproPhoenixJupyter/learning_space/';
36 37
 
37
-	public function openStudentJupyterVirtualClassroom(int $jupyterVirtualClassroomId,PhoenixServices $service)
38
+	public function openStudentJupyterVirtualClassroom(int $jupyterVirtualClassroomId, PhoenixServices $service)
38 39
 	{
39 40
 		// ignore l'interruption utilisateur
40 41
 		ignore_user_abort(true);
@@ -45,13 +46,13 @@ class JupyterVirtualClassroomController extends LearningSpaceController
45 46
 		$person = $this->getCurrentLearner();
46 47
 
47 48
 		// demarre le serveur apprenant
48
-		$url = $service->startStudentServer($sequenceItem,$person);
49
+		$url = $service->startStudentServer($sequenceItem, $person);
49 50
 
50 51
 		// récupère l'inscription
51 52
 		$session = $sequenceItem->getSession();
52 53
 
53 54
 		// enregistre une trace
54
-		$this->recordTrack($person,$sequenceItem);
55
+		$this->recordTrack($person, $sequenceItem);
55 56
 
56 57
 		// retourne le résultat
57 58
 		$response['result'] = true;
@@ -69,8 +70,7 @@ class JupyterVirtualClassroomController extends LearningSpaceController
69 70
 	protected function recordTrack(Person $learner, JupyterVirtualClassroom $sequenceItem)
70 71
 	{
71 72
 		$track = $this->retrieveTrack($learner, $sequenceItem);
72
-		if (!$track)
73
-		{
73
+		if (!$track) {
74 74
 			$track = new Track($learner, $sequenceItem);
75 75
 
76 76
 			//@TODO
@@ -84,7 +84,7 @@ class JupyterVirtualClassroomController extends LearningSpaceController
84 84
 		return $track;
85 85
 	}
86 86
 
87
-	
87
+
88 88
 	/**
89 89
 	 *
90 90
 	 * @param Person $learner
@@ -110,7 +110,7 @@ class JupyterVirtualClassroomController extends LearningSpaceController
110 110
 	 * 
111 111
 	 * @return void
112 112
 	 */
113
-	public function sendStudentJupyterNotebook(Request $request,$jupyterVirtualClassroomId,PhoenixServices $service)
113
+	public function sendStudentJupyterNotebook(Request $request, $jupyterVirtualClassroomId, PhoenixServices $service)
114 114
 	{
115 115
 		// uniquement ajax
116 116
 		/*if (!$request->isXmlHttpRequest())
@@ -121,35 +121,54 @@ class JupyterVirtualClassroomController extends LearningSpaceController
121 121
 
122 122
 		$repository = $this->getRepository(JupyterVirtualClassroom::class);
123 123
 		$sequenceItem = $repository->find($jupyterVirtualClassroomId);
124
-		if (!$sequenceItem || !$sequenceItem->getIsAssesment())
125
-		{
124
+		if (!$sequenceItem || !$sequenceItem->getIsAssesment()) {
126 125
 			// erreur
127 126
 			throw $this->createNotFoundException();
128 127
 		}
129 128
 
130 129
 		// retour ajax
131 130
 		$response['result'] = true;
132
-		$response['score'] = $service->sendStudentNotebookAndGetScore($sequenceItem,$person);
131
+		$response['score'] = $service->sendStudentNotebookAndGetScore($sequenceItem, $person);
132
+
133
+		$forwardResponse = $this->forward('Logipro\Phoenix\Controller\LearningSpace\LearningSpaceController::getSessionTrackInfos', [
134
+			'id'  => $sequenceItem->getSession()->getSessionId(),
135
+		]);
136
+
137
+		$forwardDecode = json_decode($forwardResponse->getContent(),true);
138
+		$response['html'] = $forwardDecode['html'];
133 139
 
134 140
 		return $this->json($response);
135 141
 	}
136 142
 
137
-    public function drawNotebookLoadingPage(Request $request,int $jupyterVirtualClassroomId)
138
-    {
143
+	public function drawNotebookLoadingPage(Request $request, int $jupyterVirtualClassroomId)
144
+	{
139 145
 		return $this->phxRender('@LogiproPhoenixJupyter/learning_space/notebookLoading.html.twig', array('sequenceItemId' => $jupyterVirtualClassroomId));
140 146
 	}
141 147
 
142
-	public function resetNotebook(Request $request,$jupyterVirtualClassroomId,PhoenixServices $service)
148
+	public function resetNotebook(Request $request, $jupyterVirtualClassroomId, PhoenixServices $service)
143 149
 	{
144 150
 		$repository = $this->getRepository(JupyterVirtualClassroom::class);
145 151
 		$sequenceItem = $repository->find($jupyterVirtualClassroomId);
146 152
 
147 153
 		$person = $this->getCurrentLearner();
148
-		$result = $service->resetNotebook($sequenceItem,$person);
149
-
154
+		$result = $service->resetNotebook($sequenceItem, $person);
150 155
 
151 156
 		// retour ajax
152 157
 		$response['result'] = $result;
158
+
159
+		$forwardResponse = $this->forward('Logipro\Phoenix\Controller\LearningSpace\LearningSpaceController::getSessionTrackInfos', [
160
+			'id'  => $sequenceItem->getSession()->getSessionId(),
161
+		]);
162
+
163
+		$forwardDecode = json_decode($forwardResponse->getContent(),true);
164
+		$response['html'] = $forwardDecode['html'];
153 165
 		return $this->json($response);
154 166
 	}
167
+
168
+	public function getJupyterSubmissionLog(JupyterSubmission $submission)
169
+	{
170
+		return $this->json([
171
+			'log' => $submission->getLog()
172
+		]);
173
+	}
155 174
 }

+ 17
- 1
Entity/JupyterSubmission.php View File

@@ -15,12 +15,18 @@ class JupyterSubmission
15 15
 	private $maxScore;
16 16
 	private $date;
17 17
 	private $classroomRegistration;
18
+	private $log;
18 19
 
19 20
 	public function __construct()
20 21
 	{
21 22
 		$this->date = new \DateTime();
22 23
 	}
23 24
 
25
+	public function getJupyterSubmissionId()
26
+	{
27
+		return $this->jupyterSubmissionId;
28
+	}
29
+
24 30
 	public function setScore($score)
25 31
 	{
26 32
 		$this->score = $score;
@@ -39,7 +45,7 @@ class JupyterSubmission
39 45
 
40 46
 		return $this;
41 47
 	}
42
-	
48
+
43 49
 	public function getMaxScore()
44 50
 	{
45 51
 		return $this->maxScore;
@@ -66,4 +72,14 @@ class JupyterSubmission
66 72
 	{
67 73
 		return $this->date;
68 74
 	}
75
+
76
+	public function setLog($log)
77
+	{
78
+		$this->log = $log;
79
+	}
80
+
81
+	public function getLog()
82
+	{
83
+		return $this->log;
84
+	}
69 85
 }

+ 17
- 8
Repository/JupyterClassroomRegistrationRepository.php View File

@@ -1,4 +1,5 @@
1 1
 <?php
2
+
2 3
 namespace Logipro\Bundle\PhoenixJupyterBundle\Repository;
3 4
 
4 5
 use Symfony\Bridge\Doctrine\RegistryInterface;
@@ -9,23 +10,31 @@ use Logipro\Bundle\PhoenixJupyterBundle\Entity\JupyterClassroomRegistration;
9 10
 class JupyterClassroomRegistrationRepository extends ServiceEntityRepository
10 11
 {
11 12
     public function __construct(RegistryInterface $registry)
12
-	{
13
-		parent::__construct($registry, JupyterClassroomRegistration::class);
13
+    {
14
+        parent::__construct($registry, JupyterClassroomRegistration::class);
14 15
     }
15 16
 
16
-    public function getLastClassroomRegistration($sequenceItem,$person)
17
+    public function getLastClassroomRegistration($sequenceItem, $person, $includeUrl = true)
17 18
     {
18 19
         $qb = $this->createQueryBuilder('classroom');
19 20
 
20 21
         $qb->andWhere('classroom.person = :person');
21 22
         $qb->andWhere('classroom.jupyterVirtualClassroom = :jupyterVirtualClassroom');
22
-        $qb->andWhere('classroom.url is not null');
23
-        
24
-		$qb->setParameter('person', $person);
25
-		$qb->setParameter('jupyterVirtualClassroom', $sequenceItem);
23
+        if ($includeUrl) {
24
+            $qb->andWhere('classroom.url is not null');
25
+        } else {
26
+            $qb->orderBy("classroom.jupyterClassroomRegistrationId", "DESC");
27
+            $qb->setMaxResults(1);
28
+        }
29
+
30
+
31
+
32
+
33
+        $qb->setParameter('person', $person);
34
+        $qb->setParameter('jupyterVirtualClassroom', $sequenceItem);
26 35
 
27 36
         $query = $qb->getQuery();
28 37
 
29 38
         return $query->getOneOrNullResult();
30 39
     }
31
-}
40
+}

+ 16
- 0
Repository/JupyterSubmissionRepository.php View File

@@ -0,0 +1,16 @@
1
+<?php
2
+
3
+namespace Logipro\Bundle\PhoenixJupyterBundle\Repository;
4
+
5
+use Symfony\Bridge\Doctrine\RegistryInterface;
6
+
7
+use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
8
+use Logipro\Bundle\PhoenixJupyterBundle\Entity\JupyterSubmission;
9
+
10
+class JupyterSubmissionRepository extends ServiceEntityRepository
11
+{
12
+    public function __construct(RegistryInterface $registry)
13
+    {
14
+        parent::__construct($registry, JupyterSubmission::class);
15
+    }
16
+}

+ 0
- 1
Resources/assets/Js/learning-space-loader.js View File

@@ -1,4 +1,3 @@
1
-// toto
2 1
 $(document).ready(function()
3 2
 {
4 3
     $.post($('[name="url"]').val(),function(result)

+ 96
- 10
Resources/assets/Js/learning-space.js View File

@@ -1,4 +1,5 @@
1
-// toto
1
+"use strict";
2
+//import { showInScroll } from './../../../../../../assets/exclusive/js/init_learning_space.js';
2 3
 $(document).ready(function()
3 4
 {
4 5
     $(document).on('logiprodocumentloaded',function(){
@@ -9,6 +10,57 @@ $(document).ready(function()
9 10
 
10 11
 function initBundle()
11 12
 {
13
+    $('.modal-ajax').on('click',function(event)
14
+    {
15
+        event.preventDefault();
16
+
17
+        $(document).phxLock();
18
+        $.get($(this).attr('href'),function(result)
19
+        {
20
+            $(document).phxUnlock();
21
+
22
+            let modal = $('<div>',
23
+            {
24
+                'class': 'modal fade',
25
+                'tabindex': '-1',
26
+                'role':'dialog',
27
+                'aria-hidden':'true'
28
+            })
29
+            .append(
30
+                $('<div>',
31
+                {
32
+                    'class':'modal-dialog'
33
+                }).append(
34
+                    $('<div>',{
35
+                        class: 'modal-content'
36
+                    }).append(
37
+                        $('<p>').text(result.log)
38
+                    )
39
+                )
40
+            );
41
+            
42
+
43
+           /* .append(
44
+                $('<div>',
45
+                {
46
+                    'class':'modal-dialog modal-lg'
47
+                }).append(
48
+                    $('<div>',{
49
+                        class: 'modal-content'
50
+                    })
51
+                    .append(
52
+                        $('p').text(result.log)
53
+                    )
54
+                )
55
+            );*/
56
+
57
+            $('.ali-LSContainer').append(modal);
58
+            modal.modal();
59
+        });
60
+
61
+        
62
+    });
63
+       
12 64
 
13 65
     $('.ali-LSSequenceItem-li').each(function()
14 66
     {
@@ -30,16 +82,21 @@ function initBundle()
30 82
                 $.post(_$this.attr('href'), '', function (response) {
31 83
                     if (response.result)
32 84
                     {
33
-                        window.location.reload();
34
-                        /*
35
-                        let div = _$this.next();
36
-                        div.removeClass('d-none');
37
-                        div.find('.score-value').text(response.score);
38
-    
39
-                        _$this.remove();*/
85
+                        $.phoenix.addToast("Le notebook a été évalué",'success');
86
+
87
+                        $(".ali-LSSession").replaceWith(response.html);
88
+
89
+                        $(document).trigger('logiprodocumentloaded');
90
+
91
+                        showInScroll(0,1,function(){
92
+                            $(document).phxUnlock();
93
+                        });
94
+                    }
95
+                    else
96
+                    {
97
+                        $.phoenix.addToast("L'évaluation du notebook a échoué'",'danger');
40 98
                     }
41 99
                     
42
-                    $(document).phxUnlock();
43 100
                 });
44 101
             }
45 102
             return false;
@@ -81,15 +138,26 @@ function initBundle()
81 138
                 $.post(link,function(response)
82 139
                 {
83 140
                     clone.modal('hide');
141
+                    setTimeout(function(){
142
+                        clone.remove();
143
+                    },1000);
84 144
                     if (response.result == true)
85 145
                     {
86 146
                         $.phoenix.addToast("Le notebook a été réinitialisé",'success');
147
+
148
+                        $(".ali-LSSession").replaceWith(response.html);
149
+
150
+                        $(document).trigger('logiprodocumentloaded');
151
+
152
+                        showInScroll(0,1,function(){
153
+                            $(document).phxUnlock();
154
+                        });
87 155
                     }
88 156
                     else
89 157
                     {
90 158
                         $.phoenix.addToast("Le notebook n'a pas été réinitialisé",'danger');
91 159
                     }
92
-                    $(document).phxUnlock();
160
+                    
93 161
                 });
94 162
             });
95 163
             // ouvre la modal
@@ -97,4 +165,22 @@ function initBundle()
97 165
         });
98 166
     });
99 167
     
168
+}
169
+function showInScroll(margin,timeout = 100,callback = function(){}) {
170
+    var limit = $(window).scrollTop() + $(window).height() - margin;
171
+    var numElemShow = 0;
172
+    // Parcourir tout les éléments devant être affichés au scrool et pas encore visible.
173
+    let collection = $(".ali-LSShowInScrool:not(.ali-LSShowInScroolDone)");
174
+    collection.each(function () {
175
+        var elem = $(this);
176
+        var eTop = elem.offset().top;
177
+        if (limit > eTop) {
178
+                setTimeout(function () { 
179
+                    elem.addClass('ali-LSShowInScroolDone'); 
180
+
181
+                }, timeout * numElemShow);
182
+                numElemShow++;
183
+        }
184
+    });
185
+    callback();
100 186
 }

+ 1
- 0
Resources/config/doctrine/JupyterSubmission.orm.xml View File

@@ -13,6 +13,7 @@
13 13
 	<field name="score" column="score" type="decimal" nullable="true" />
14 14
 	<field name="maxScore" column="maxscore" type="decimal" nullable="true" />
15 15
 	<field name="date" column="date" type="datetimetz" />
16
+	<field name="log" column="log" type="text" />
16 17
 
17 18
 	<many-to-one field="classroomRegistration" target-entity="Logipro\Bundle\PhoenixJupyterBundle\Entity\JupyterClassroomRegistration">
18 19
 		<join-column name="jupyter_classroom_registration_fk" referenced-column-name="phx_jupyter_classroom_registration_id" nullable="false" />

+ 8
- 0
Resources/config/routes.yaml View File

@@ -2,6 +2,7 @@
2 2
 # Test des templates
3 3
 #-------------------------------------------------------------------------------
4 4
 open_trainer_jupyter_classroom:
5
+  
5 6
   path: /jupyter/trainer/open/{jupyterVirtualClassroomId}
6 7
   controller: Logipro\Bundle\PhoenixJupyterBundle\Controller\BackOffice\JupyterVirtualClassroomController::openTrainerJupyterVirtualClassroom
7 8
   requirements:
@@ -31,3 +32,10 @@ reset_notebook:
31 32
   controller: Logipro\Bundle\PhoenixJupyterBundle\Controller\LearningSpace\JupyterVirtualClassroomController::resetNotebook
32 33
   requirements:
33 34
     jupyterVirtualClassroomId: '\d+'
35
+
36
+get_submission_log:
37
+  methods:  [GET]
38
+  path: /learning-space/jupyter/student/submission/{jupyterSubmissionId}
39
+  controller: Logipro\Bundle\PhoenixJupyterBundle\Controller\LearningSpace\JupyterVirtualClassroomController::getJupyterSubmissionLog
40
+  requirements:
41
+    submissionId: '\d+'

+ 5
- 6
Resources/views/learning_space/blocBottom.html.twig View File

@@ -5,7 +5,7 @@
5 5
 {% set lastRegistration = null %}
6 6
 
7 7
 {% for currentRegistration in registrations %}
8
-    {% if currentRegistration.person == learner and currentRegistration.url is null %}
8
+    {% if currentRegistration.person == learner %}
9 9
         {% if firstRegistration is null %}
10 10
             {% set firstRegistration = currentRegistration %}
11 11
         {% else %}
@@ -20,9 +20,9 @@
20 20
 
21 21
         {% set submissions = firstRegistration.getSubmissions() %}
22 22
         {% if submissions|length > 0 %}
23
-            {% set submission = submissions|first %}
23
+            {% set firstSubmission = submissions|first %}
24 24
             <li>
25
-                Première soumission :&nbsp;<b>{{ submission.getDate()|date("d/m/Y  H:i") }}</b>, note :&nbsp;<b>{{ submission.getScoreFormat() }}</b>
25
+                <a class="modal-ajax" href="{{ path('get_submission_log',{'jupyterSubmissionId':firstSubmission.jupyterSubmissionId }) }}">Première soumission</a> :&nbsp;<b>{{ firstSubmission.getDate()|date("d/m/Y  H:i") }}</b>, note :&nbsp;<b>{{ firstSubmission.getScoreFormat() }}</b>
26 26
             </li>
27 27
         {% endif %}
28 28
 
@@ -30,13 +30,12 @@
30 30
         {% if lastRegistration %}
31 31
             {% set submissions = lastRegistration.getSubmissions() %}
32 32
             {% if submissions|length > 0 %}
33
-                {% set submission = submissions|last %}
33
+                {% set lastSubmission = submissions|last %}
34 34
                 <li>
35
-                    Dernière soumission :&nbsp;<b>{{ submission.getDate()|date("d/m/Y  H:i") }}</b>, note :&nbsp;<b>{{ submission.getScoreFormat() }}</b>
35
+                   <a class="modal-ajax" href="{{ path('get_submission_log',{'jupyterSubmissionId':lastSubmission.jupyterSubmissionId }) }}">Dernière soumission</a> :&nbsp;<b>{{ lastSubmission.getDate()|date("d/m/Y  H:i") }}</b>, note :&nbsp;<b>{{ lastSubmission.getScoreFormat() }}</b>
36 36
                 </li>
37 37
             {% endif %}
38 38
         {% endif %}
39 39
         </ul>
40 40
     </div>
41
-
42 41
 {% endif %}

+ 4
- 2
Resources/views/learning_space/blocMiddle.html.twig View File

@@ -5,6 +5,7 @@
5 5
 </p>
6 6
 {% endif %}
7 7
 <div class="ali-LSSequenceItemContentActions ali-LSSequenceItemType{{bundleData['type']}}">
8
+    {% if bundleData['replay'] %}
8 9
     <a data-name="start-notebook" class="mb-2 ali-LSButton ali-LSSequenceItemContent-button {% if completion == 100 %}review{% endif %}" href="{{ path('draw_loading_jupyter_notebook',{'jupyterVirtualClassroomId': sequenceItem.sequenceItemId }) }}" target="_blank">{# 'open_student_jupyter_classroom' #}
9 10
         {% if completion == 100 and infosLocked['locked'] == false %}
10 11
             {{ 'ls__sequence_item_action_review'|trans }}
@@ -14,6 +15,7 @@
14 15
             {{ 'ls__sequence_item_action_continue'|trans }}
15 16
         {% endif %}
16 17
     </a>
18
+    {% endif %}
17 19
 
18 20
     {% set registrations = sequenceItem.getClassroomRegistration() %}
19 21
     {% set registration = null %}
@@ -52,7 +54,7 @@
52 54
 
53 55
     <a data-toggle-bundle="modalConfirmReset{{ sequenceItem.sequenceItemId }}" class="ml-2 mb-2{% if registration == null %} disable{% endif %}" data-name="reset-notebook" href="{{ path('reset_notebook',{'jupyterVirtualClassroomId': sequenceItem.sequenceItemId }) }}">Réinitialiser</a>
54 56
    
55
-    {% if sequenceItem.getIsAssesment() %}
56
-            <a class="ml-2 mb-2 ali-LSButton ali-LSSequenceItemContent-button disable" href="{{ path('send_student_jupyter_notebook',{'jupyterVirtualClassroomId': sequenceItem.sequenceItemId }) }}" data-name="send-notebook" data-toggle="tooltip" title="Veuillez réaliser l'activité pour pouvoir soumettre votre code">Envoyer mon code</a>
57
+    {% if sequenceItem.getIsAssesment() and bundleData['replay'] %}
58
+            <a class="ml-2 mb-2 ali-LSButton ali-LSSequenceItemContent-button" href="{{ path('send_student_jupyter_notebook',{'jupyterVirtualClassroomId': sequenceItem.sequenceItemId }) }}" data-name="send-notebook" data-toggle="tooltip" title="Veuillez réaliser l'activité pour pouvoir soumettre votre code">Envoyer mon code</a>
57 59
     {% endif %}
58 60
 </div>

+ 11
- 0
Resources/views/learning_space/modalLog.html.twig View File

@@ -0,0 +1,11 @@
1
+{% extends 'learning_space/popup_messages/popup_message_layout.html.twig' %}
2
+
3
+{% block MessageContent %}
4
+<div class="ali-PopupMessageBox text-white">
5
+    <div class="d-flex justify-content-center align-items-center flex-column flex-xl-row text-center text-xl-left">
6
+        <i class="material-icons ali-TextSize-8 mr-0 mr-xl-3">warning</i>
7
+        <span class="ali-TextSize-2-5">{{ 'warning_duration_not_save'|trans }}<br/>
8
+        </span>
9
+    </div>
10
+</div>
11
+{% endblock %}

+ 170
- 192
Services/ApiLayer/ApiLayerService.php View File

@@ -1,4 +1,5 @@
1 1
 <?php
2
+
2 3
 namespace Logipro\Bundle\PhoenixJupyterBundle\Services\ApiLayer;
3 4
 
4 5
 use Symfony\Component\HttpClient\HttpClient;
@@ -13,7 +14,7 @@ use Logipro\Phoenix\Component\PhxFileGuesser;
13 14
 class ApiLayerService
14 15
 {
15 16
     private static $instance = null;
16
-    
17
+
17 18
     /**
18 19
      * url du jupyterhub
19 20
      */
@@ -24,7 +25,7 @@ class ApiLayerService
24 25
      */
25 26
     private $notebookApiUrl = null;
26 27
 
27
-     /**
28
+    /**
28 29
      * url de l'api jupyterhub notebook
29 30
      */
30 31
     private $notebookUrl = null;
@@ -41,12 +42,12 @@ class ApiLayerService
41 42
 
42 43
     public function __construct()
43 44
     {
44
-        $server = $_SERVER['JUPYTER_URL'].trim('/');
45
+        $server = $_SERVER['JUPYTER_URL'] . trim('/');
45 46
 
46
-        $this->hubUrl = $server . $this->buildPath(array('hub','api'));
47
-        $this->notebookApiUrl = $server . $this->buildPath(array('user','%s','api'));
48
-        $this->notebookUrl = $server . $this->buildPath(array('user','%s','notebooks'));
49
-        $this->apiUrl = $_SERVER['JUPYTER_API_URL'].trim('/') . '/';
47
+        $this->hubUrl = $server . $this->buildPath(array('hub', 'api'));
48
+        $this->notebookApiUrl = $server . $this->buildPath(array('user', '%s', 'api'));
49
+        $this->notebookUrl = $server . $this->buildPath(array('user', '%s', 'notebooks'));
50
+        $this->apiUrl = $_SERVER['JUPYTER_API_URL'] . trim('/') . '/';
50 51
         $this->token = $_SERVER['JUPYTER_API_TOKEN'];
51 52
     }
52 53
 
@@ -60,41 +61,35 @@ class ApiLayerService
60 61
      * 
61 62
      * @return array
62 63
      */
63
-    private function doQuery($url,$method,$path,$code = 200,$options = array())
64
+    private function doQuery($url, $method, $path, $code = 200, $options = array())
64 65
     {
65
-        if (!is_array($code))
66
-        {
66
+        if (!is_array($code)) {
67 67
             $code = array($code);
68 68
         }
69 69
 
70
-        $serviceUrl = trim($url,'/');
71
-        if ($path != '')
72
-        {
70
+        $serviceUrl = trim($url, '/');
71
+        if ($path != '') {
73 72
             $serviceUrl .= '/' . $path;
74 73
         }
75 74
 
76 75
         $httpClient = HttpClient::create();
77
-        try
78
-        {
76
+        try {
79 77
             /*if (!empty($parameters))
80 78
             {
81 79
                 $options['query'] = $parameters;
82 80
             }*/
83 81
 
84 82
             $options['timeout'] = 2000000;
85
-            $this->response = $httpClient->request($method,$serviceUrl,$options);
86
-            if (!in_array($this->response->getStatusCode(),$code))
87
-            {
83
+            $this->response = $httpClient->request($method, $serviceUrl, $options);
84
+            if (!in_array($this->response->getStatusCode(), $code)) {
88 85
                 /*echo 'erreur :';
89 86
                 dump($response->getContent());*/
90 87
                 // FIXME peut être mettre une erreur
91 88
                 return null;
92 89
             }
93
-            return \json_decode($this->response->getContent(),true);
90
+            return \json_decode($this->response->getContent(), true);
94 91
             //return $response->toArray();
95
-        }
96
-        catch (\Exception $exp)
97
-        {
92
+        } catch (\Exception $exp) {
98 93
             return null;
99 94
         }
100 95
     }
@@ -107,14 +102,13 @@ class ApiLayerService
107 102
      * @param int $code
108 103
      * @param array $options
109 104
      */
110
-    private function doApiQuery($method,$path,$code = 200,$options = array())
105
+    private function doApiQuery($method, $path, $code = 200, $options = array())
111 106
     {
112
-        if (!isset($options['headers']['Authorization']))
113
-        {
107
+        if (!isset($options['headers']['Authorization'])) {
114 108
             $options['headers']['Authorization'] = 'token ' . $_SERVER['JUPYTER_API_TOKEN'];
115 109
         }
116
-        
117
-        return $this->doQuery($this->apiUrl,$method,$path,$code,$options);
110
+
111
+        return $this->doQuery($this->apiUrl, $method, $path, $code, $options);
118 112
     }
119 113
 
120 114
     /**
@@ -126,9 +120,9 @@ class ApiLayerService
126 120
      * 
127 121
      * @return array
128 122
      */
129
-    private function doApiGet($path,$returnCode = 200,$parameters = array())
123
+    private function doApiGet($path, $returnCode = 200, $parameters = array())
130 124
     {
131
-        return $this->doApiQuery('GET',$path,$returnCode,$parameters);
125
+        return $this->doApiQuery('GET', $path, $returnCode, $parameters);
132 126
     }
133 127
 
134 128
     /**
@@ -140,9 +134,9 @@ class ApiLayerService
140 134
      * 
141 135
      * @return array
142 136
      */
143
-    private function doApiPost($path,$returnCode = 200,$parameters = array())
137
+    private function doApiPost($path, $returnCode = 200, $parameters = array())
144 138
     {
145
-        return $this->doApiQuery('POST',$path,$returnCode,$parameters);
139
+        return $this->doApiQuery('POST', $path, $returnCode, $parameters);
146 140
     }
147 141
 
148 142
     /**
@@ -155,14 +149,13 @@ class ApiLayerService
155 149
      * 
156 150
      * @return array
157 151
      */
158
-    private function doHubQuery($method,$path,$code = 200,$options = array())
152
+    private function doHubQuery($method, $path, $code = 200, $options = array())
159 153
     {
160
-        if (!isset($options['headers']['Authorization']))
161
-        {
154
+        if (!isset($options['headers']['Authorization'])) {
162 155
             $options['headers']['Authorization'] = 'token ' . $_SERVER['JUPYTER_API_TOKEN'];
163 156
         }
164
-        
165
-        return $this->doQuery($this->hubUrl,$method,$path,$code,$options);
157
+
158
+        return $this->doQuery($this->hubUrl, $method, $path, $code, $options);
166 159
     }
167 160
 
168 161
     /**
@@ -174,9 +167,9 @@ class ApiLayerService
174 167
      * 
175 168
      * @return array
176 169
      */
177
-    private function doHubGet($path,$returnCode = 200,$parameters = array())
170
+    private function doHubGet($path, $returnCode = 200, $parameters = array())
178 171
     {
179
-        return $this->doHubQuery('GET',$path,$returnCode,$parameters);
172
+        return $this->doHubQuery('GET', $path, $returnCode, $parameters);
180 173
     }
181 174
 
182 175
     /**
@@ -188,9 +181,9 @@ class ApiLayerService
188 181
      * 
189 182
      * @return array
190 183
      */
191
-    private function doHubPost($path,$returnCode = 200,$parameters = array())
184
+    private function doHubPost($path, $returnCode = 200, $parameters = array())
192 185
     {
193
-        return $this->doHubQuery('POST',$path,$returnCode,$parameters);
186
+        return $this->doHubQuery('POST', $path, $returnCode, $parameters);
194 187
     }
195 188
 
196 189
     /**
@@ -204,13 +197,12 @@ class ApiLayerService
204 197
      * 
205 198
      * @return array
206 199
      */
207
-    private function doNotebookQuery(JupyterToken $token,$method,$path,$code = 200,$options = array())
200
+    private function doNotebookQuery(JupyterToken $token, $method, $path, $code = 200, $options = array())
208 201
     {
209
-        if (!isset($options['headers']['Authorization']))
210
-        {
202
+        if (!isset($options['headers']['Authorization'])) {
211 203
             $options['headers']['Authorization'] = 'token ' . $token->getToken();
212 204
         }
213
-        return $this->doQuery($this->getUserNotebookUrl($token),$method,$path,$code,$options);
205
+        return $this->doQuery($this->getUserNotebookUrl($token), $method, $path, $code, $options);
214 206
     }
215 207
 
216 208
     /**
@@ -222,7 +214,7 @@ class ApiLayerService
222 214
      */
223 215
     private function getUserNotebookUrl($token)
224 216
     {
225
-        return str_replace('%s',$token->getUuid(),$this->notebookApiUrl);
217
+        return str_replace('%s', $token->getUuid(), $this->notebookApiUrl);
226 218
     }
227 219
 
228 220
 
@@ -236,9 +228,9 @@ class ApiLayerService
236 228
      * 
237 229
      * @return array
238 230
      */
239
-    private function doNotebookGet(JupyterToken $token,$path,$returnCode = 200,$parameters = array())
231
+    private function doNotebookGet(JupyterToken $token, $path, $returnCode = 200, $parameters = array())
240 232
     {
241
-        return $this->doNotebookQuery($token,'GET',$path,$returnCode,$parameters);
233
+        return $this->doNotebookQuery($token, 'GET', $path, $returnCode, $parameters);
242 234
     }
243 235
 
244 236
     /**
@@ -251,9 +243,9 @@ class ApiLayerService
251 243
      * 
252 244
      * @return array
253 245
      */
254
-    private function doNotebookPost(JupyterToken $token,$path,$returnCode = 200,$parameters = array())
246
+    private function doNotebookPost(JupyterToken $token, $path, $returnCode = 200, $parameters = array())
255 247
     {
256
-        return $this->doNotebookQuery($token,'POST',$path,$returnCode,$parameters);
248
+        return $this->doNotebookQuery($token, 'POST', $path, $returnCode, $parameters);
257 249
     }
258 250
 
259 251
     /**
@@ -266,9 +258,9 @@ class ApiLayerService
266 258
      * 
267 259
      * @return array
268 260
      */
269
-    private function doNotebookPatch(JupyterToken $token,$path,$returnCode = 200,$parameters = array())
261
+    private function doNotebookPatch(JupyterToken $token, $path, $returnCode = 200, $parameters = array())
270 262
     {
271
-        return $this->doNotebookQuery($token,'PATCH',$path,$returnCode,$parameters);
263
+        return $this->doNotebookQuery($token, 'PATCH', $path, $returnCode, $parameters);
272 264
     }
273 265
 
274 266
     /**
@@ -281,9 +273,9 @@ class ApiLayerService
281 273
      * 
282 274
      * @return array
283 275
      */
284
-    private function doNotebookPut(JupyterToken $token,$path,$returnCode = 200,$parameters = array())
276
+    private function doNotebookPut(JupyterToken $token, $path, $returnCode = 200, $parameters = array())
285 277
     {
286
-        return $this->doNotebookQuery($token,'PUT',$path,$returnCode,$parameters);
278
+        return $this->doNotebookQuery($token, 'PUT', $path, $returnCode, $parameters);
287 279
     }
288 280
 
289 281
     /**
@@ -293,14 +285,13 @@ class ApiLayerService
293 285
      */
294 286
     public function serviceIsAvalaible()
295 287
     {
296
-        $response = $this->doApiGet('phoenix/',200);
297
-        if (!is_null($response) && $response['result'] == 'true')
298
-        {
288
+        $response = $this->doApiGet('phoenix/', 200);
289
+        if (!is_null($response) && $response['result'] == 'true') {
299 290
             return true;
300 291
         }
301 292
         return false;
302 293
     }
303
-    
294
+
304 295
     /**
305 296
      * échappe le texte
306 297
      * et retourne le contenu échappé
@@ -324,14 +315,12 @@ class ApiLayerService
324 315
      */
325 316
     private function buildPath(array $params)
326 317
     {
327
-        foreach ($params as $key => $param)
328
-        {
329
-            if ($param != "")
330
-            {
318
+        foreach ($params as $key => $param) {
319
+            if ($param != "") {
331 320
                 $params[$key] = $this->sanitizeUrlParamPath($param);
332 321
             }
333 322
         }
334
-        return implode('/',$params);
323
+        return implode('/', $params);
335 324
     }
336 325
 
337 326
     private function sanitize($name)
@@ -348,7 +337,7 @@ class ApiLayerService
348 337
      * 
349 338
      * @return null/string
350 339
      */
351
-    public function createTrainerServerIfNoneAndSetContent(JupyterVirtualClassroom $classroom,JupyterToken $token,$fromurl = null,$notebookContent = null,$useUrl = true)
340
+    public function createTrainerServerIfNoneAndSetContent(JupyterVirtualClassroom $classroom, JupyterToken $token, $fromurl = null, $notebookContent = null, $useUrl = true)
352 341
     {
353 342
         $notebookName = $this->getNoteBookName($classroom);
354 343
         $path = $this->buildPath(
@@ -356,36 +345,33 @@ class ApiLayerService
356 345
                 'phoenix',
357 346
                 'trainer',
358 347
                 $token->getUuid(),
359
-                $this->getFolderName($classroom,$useUrl),
360
-                $this->getNoteBookNameByString($classroom->getSequenceItemId(),$classroom->getTitle(),true,$useUrl)
348
+                $this->getFolderName($classroom, $useUrl),
349
+                $this->getNoteBookNameByString($classroom->getSequenceItemId(), $classroom->getTitle(), true, $useUrl)
361 350
             )
362 351
         );
363 352
 
364 353
         $contentData = array();
365
-        if (!is_null($notebookContent))
366
-        {
354
+        if (!is_null($notebookContent)) {
367 355
             $contentData['content'] = $notebookContent;
368 356
         }
369 357
         $contentData['fromurl'] = $fromurl;
370 358
 
371 359
         $options['headers']['Content-Type'] = 'application/json';
372
-        $options['body'] = json_encode($contentData);//'{"toto":"content"}';
360
+        $options['body'] = json_encode($contentData); //'{"toto":"content"}';
373 361
 
374
-        $response = $this->doApiPost($path,200,$options);
362
+        $response = $this->doApiPost($path, 200, $options);
375 363
 
376
-        if ($response['result'] == 'true' && isset($response['url']))
377
-        {
364
+        if ($response['result'] == 'true' && isset($response['url'])) {
378 365
             // url du notebook
379 366
             $url = $response['url'];
380 367
             $classroom->setUrl($url);
381 368
 
382 369
             // met à jour le token dans le cas d'une création de compte
383
-            if (isset($response['token']))
384
-            {
370
+            if (isset($response['token'])) {
385 371
                 $token->setToken($response['token']);
386 372
                 $token->setApiId($response['tokenId']);
387 373
             }
388
-           
374
+
389 375
 
390 376
             return $url;
391 377
         }
@@ -401,7 +387,7 @@ class ApiLayerService
401 387
      * 
402 388
      * @return string url du notebook
403 389
      */
404
-    public function createStudentServerIfNoneAndSetContent(JupyterVirtualClassroom $classroom,JupyterToken $trainerToken,JupyterToken $studentToken,$useUrl = true)
390
+    public function createStudentServerIfNoneAndSetContent(JupyterVirtualClassroom $classroom, JupyterToken $trainerToken, JupyterToken $studentToken, $useUrl = true)
405 391
     {
406 392
         $path = $this->buildPath(
407 393
             array(
@@ -409,8 +395,8 @@ class ApiLayerService
409 395
                 'student',
410 396
                 $trainerToken->getUuid(),
411 397
                 $studentToken->getUuid(),
412
-                $this->getFolderName($classroom,$useUrl),
413
-                $this->getNoteBookNameByString($classroom->getSequenceItemId(),$classroom->getTitle(),true,$useUrl)
398
+                $this->getFolderName($classroom, $useUrl),
399
+                $this->getNoteBookNameByString($classroom->getSequenceItemId(), $classroom->getTitle(), true, $useUrl)
414 400
             )
415 401
         );
416 402
 
@@ -423,20 +409,18 @@ class ApiLayerService
423 409
         $options['headers']['Content-Type'] = 'application/json';
424 410
         $options['body'] = json_encode($contentData);
425 411
 
426
-        $response = $this->doApiPost($path,200,$options);
427
-        if ($response['result'] == 'true' && isset($response['url']))
428
-        {
412
+        $response = $this->doApiPost($path, 200, $options);
413
+        if ($response['result'] == 'true' && isset($response['url'])) {
429 414
             // url du notebook
430 415
             $url = $response['url'];
431 416
             //$classroom->setUrl($url);
432 417
 
433 418
             // met à jour le token dans le cas d'une création de compte
434
-            if (isset($response['token']))
435
-            {
419
+            if (isset($response['token'])) {
436 420
                 $studentToken->setToken($response['token']);
437 421
                 $studentToken->setApiId($response['tokenId']);
438 422
             }
439
-           
423
+
440 424
 
441 425
             return $url;
442 426
         }
@@ -453,7 +437,7 @@ class ApiLayerService
453 437
      * 
454 438
      * @return string url du notebook
455 439
      */
456
-    public function createStudentAssesmentServerIfNone(JupyterVirtualClassroom $classroom,JupyterToken $trainerToken,JupyterToken $studentToken,$useUrl = true)
440
+    public function createStudentAssesmentServerIfNone(JupyterVirtualClassroom $classroom, JupyterToken $trainerToken, JupyterToken $studentToken, $useUrl = true)
457 441
     {
458 442
         $path = $this->buildPath(
459 443
             array(
@@ -462,27 +446,26 @@ class ApiLayerService
462 446
                 'student',
463 447
                 $trainerToken->getUuid(),
464 448
                 $studentToken->getUuid(),
465
-                $this->getFolderName($classroom,$useUrl),
466
-                $this->getNoteBookNameByString($classroom->getSequenceItemId(),$classroom->getTitle(),true,$useUrl)
449
+                $this->getFolderName($classroom, $useUrl),
450
+                $this->getNoteBookNameByString($classroom->getSequenceItemId(), $classroom->getTitle(), true, $useUrl)
467 451
             )
468 452
         );
469 453
 
470 454
         $options['headers']['Content-Type'] = 'application/json';
471 455
 
472
-        $response = $this->doApiPost($path,200,$options);
473
-        if ($response['result'] == 'true' && isset($response['url']))
474
-        {
456
+        $response = $this->doApiPost($path, 200, $options);
457
+
458
+        if ($response['result'] == 'true' && isset($response['url'])) {
475 459
             // url du notebook
476 460
             $url = $response['url'];
477
-           //$classroom->setUrl($url);
461
+
462
+            //$classroom->setUrl($url);
478 463
 
479 464
             // met à jour le token dans le cas d'une création de compte
480
-            if (isset($response['token']))
481
-            {
465
+            if (isset($response['token'])) {
482 466
                 $studentToken->setToken($response['token']);
483 467
                 $studentToken->setApiId($response['tokenId']);
484 468
             }
485
-           
486 469
 
487 470
             return $url;
488 471
         }
@@ -499,7 +482,7 @@ class ApiLayerService
499 482
      * 
500 483
      * @return string score
501 484
      */
502
-    public function sendStudentNotebook(JupyterToken $trainerToken,JupyterToken $studentToken,JupyterVirtualclassroom $classroom,$useUrl = true)
485
+    public function sendStudentNotebook(JupyterToken $trainerToken, JupyterToken $studentToken, JupyterVirtualclassroom $classroom, $useUrl = true)
503 486
     {
504 487
         $path = $this->buildPath(
505 488
             array(
@@ -508,18 +491,13 @@ class ApiLayerService
508 491
                 'send',
509 492
                 $trainerToken->getUuid(),
510 493
                 $studentToken->getUuid(),
511
-                $this->getFolderName($classroom,$useUrl)
494
+                $this->getFolderName($classroom, $useUrl)
512 495
             )
513 496
         );
514 497
 
515 498
         $options['headers']['Content-Type'] = 'application/json';
516 499
 
517
-        $response = $this->doApiPost($path,200,$options);
518
-        if ($response['result'] == 'true' && isset($response['score']))
519
-        {
520
-            return array('score' => $response['score'],'max-score' => $response['max-score']);
521
-        }
522
-        return array('score' => '','max-score' => '');
500
+        return  $this->doApiPost($path, 200, $options);
523 501
     }
524 502
 
525 503
     /**
@@ -549,10 +527,9 @@ class ApiLayerService
549 527
                 $token->getToken()
550 528
             )
551 529
         );
552
-        $response = $this->doApiGet($path,200);
530
+        $response = $this->doApiGet($path, 200);
553 531
 
554
-        if ($response['result'] == 'true')
555
-        {
532
+        if ($response['result'] == 'true') {
556 533
             return true;
557 534
         }
558 535
         return null;
@@ -571,10 +548,9 @@ class ApiLayerService
571 548
                 $token->getToken()
572 549
             )
573 550
         );
574
-        $response = $this->doApiPost($path,200);
551
+        $response = $this->doApiPost($path, 200);
575 552
 
576
-        if ($response['result'] == 'true' && isset($response['token']))
577
-        {
553
+        if ($response['result'] == 'true' && isset($response['token'])) {
578 554
             $token->setToken($response['token']);
579 555
             return true;
580 556
         }
@@ -598,9 +574,9 @@ class ApiLayerService
598 574
             )
599 575
         );
600 576
 
601
-        $response = $this->doHubPost($path,array(201,202,400));
577
+        $response = $this->doHubPost($path, array(201, 202, 400));
602 578
 
603
-        return array('isStarted' => true,'result' => true);
579
+        return array('isStarted' => true, 'result' => true);
604 580
     }
605 581
 
606 582
     /**
@@ -627,7 +603,7 @@ class ApiLayerService
627 603
      * 
628 604
      * @return string nouvel url
629 605
      */
630
-    public function renameNotebook(JupyterToken $token,JupyterVirtualClassroom $jupyter,$newname)
606
+    public function renameNotebook(JupyterToken $token, JupyterVirtualClassroom $jupyter, $newname)
631 607
     {
632 608
         // vieux
633 609
         $oldName = $this->getNotebookName($jupyter);
@@ -639,7 +615,7 @@ class ApiLayerService
639 615
         );
640 616
 
641 617
         // nouveau
642
-        $newname = $this->getNoteBookNameByString($jupyter->getSequenceItemId(),$newname);
618
+        $newname = $this->getNoteBookNameByString($jupyter->getSequenceItemId(), $newname);
643 619
         $newPath = $this->buildPath(
644 620
             array(
645 621
                 $newname
@@ -647,11 +623,10 @@ class ApiLayerService
647 623
         );
648 624
 
649 625
         $options["body"] = json_encode(array('path' => $newPath));
650
-       
651
-        $response = $this->doNotebookPatch($token,$path,array(200,400),$options);
652
-        if (isset($response['name']))
653
-        {
654
-            return str_replace($oldName,$newname,$jupyter->getUrl());
626
+
627
+        $response = $this->doNotebookPatch($token, $path, array(200, 400), $options);
628
+        if (isset($response['name'])) {
629
+            return str_replace($oldName, $newname, $jupyter->getUrl());
655 630
         }
656 631
         return null;
657 632
     }
@@ -664,7 +639,7 @@ class ApiLayerService
664 639
      * 
665 640
      * @return string
666 641
      */
667
-    public function getNotebookContent(JupyterToken $token,JupyterVirtualClassroom $jupyter)
642
+    public function getNotebookContent(JupyterToken $token, JupyterVirtualClassroom $jupyter)
668 643
     {
669 644
         $path = $this->buildPath(
670 645
             array(
@@ -675,7 +650,7 @@ class ApiLayerService
675 650
                 $this->getNotebookName($jupyter)
676 651
             )
677 652
         );
678
-        $this->doApiGet($path,array(200,404));
653
+        $this->doApiGet($path, array(200, 404));
679 654
         return $this->response->getContent();
680 655
         /*$path = $this->buildPath(
681 656
             array(
@@ -702,7 +677,7 @@ class ApiLayerService
702 677
      * 
703 678
      * @return bool
704 679
      */
705
-    public function setNotebookContent(JupyterToken $token,JupyterVirtualClassroom $jupyter,$content)
680
+    public function setNotebookContent(JupyterToken $token, JupyterVirtualClassroom $jupyter, $content)
706 681
     {
707 682
         $path = $this->buildPath(
708 683
             array(
@@ -712,7 +687,7 @@ class ApiLayerService
712 687
             )
713 688
         );
714 689
 
715
-        return $this->setNotebookContentByPath($path,$token,$jupyter,$content);
690
+        return $this->setNotebookContentByPath($path, $token, $jupyter, $content);
716 691
     }
717 692
 
718 693
     /**
@@ -725,16 +700,15 @@ class ApiLayerService
725 700
      * 
726 701
      * @return bool
727 702
      */
728
-    private function setNotebookContentByPath($path,JupyterToken $token,JupyterVirtualClassroom $jupyter,$content)
703
+    private function setNotebookContentByPath($path, JupyterToken $token, JupyterVirtualClassroom $jupyter, $content)
729 704
     {
730 705
         $data['content'] = ($content);
731 706
         $data['type'] = 'file';
732 707
         $data['format'] = 'text';
733 708
         $options['body'] = json_encode($data);
734 709
 
735
-        $response = $this->doNotebookPut($token,$path,array(201,400,404),$options);
736
-        if (isset($response['name']))
737
-        {
710
+        $response = $this->doNotebookPut($token, $path, array(201, 400, 404), $options);
711
+        if (isset($response['name'])) {
738 712
             return true;
739 713
         }
740 714
         return false;
@@ -748,7 +722,7 @@ class ApiLayerService
748 722
      * 
749 723
      * @return 
750 724
      */
751
-    public function deleteNotebook(JupyterToken $token,JupyterVirtualClassroom $jupyter)
725
+    public function deleteNotebook(JupyterToken $token, JupyterVirtualClassroom $jupyter)
752 726
     {
753 727
         // suppression du fichier
754 728
         $path = $this->buildPath(
@@ -760,7 +734,7 @@ class ApiLayerService
760 734
             )
761 735
         );
762 736
 
763
-        $response = $this->doApiQuery('DELETE',$path,array(201,404));
737
+        $response = $this->doApiQuery('DELETE', $path, array(201, 404));
764 738
 
765 739
         return $response;
766 740
     }
@@ -774,16 +748,13 @@ class ApiLayerService
774 748
      * 
775 749
      * @return string
776 750
      */
777
-    private function getNoteBookName(JupyterVirtualClassroom $jupyter,$withExt = true,$useUrl = true)
751
+    private function getNoteBookName(JupyterVirtualClassroom $jupyter, $withExt = true, $useUrl = true)
778 752
     {
779 753
         $url = $jupyter->getUrl();
780
-        if ($useUrl && $url)
781
-        {
782
-           return $this->getNoteBookNameByUrl($url);
783
-        }
784
-        else
785
-        {
786
-            $name = $this->getNoteBookNameByString($jupyter->getSequenceItemId(),$jupyter->getTitle(),$withExt);
754
+        if ($useUrl && $url) {
755
+            return $this->getNoteBookNameByUrl($url);
756
+        } else {
757
+            $name = $this->getNoteBookNameByString($jupyter->getSequenceItemId(), $jupyter->getTitle(), $withExt);
787 758
             return $name;
788 759
         }
789 760
     }
@@ -796,14 +767,13 @@ class ApiLayerService
796 767
      * 
797 768
      * @return string
798 769
      */
799
-    private function getNoteBookNameByUrl($url,$withExt = true)
770
+    private function getNoteBookNameByUrl($url, $withExt = true)
800 771
     {
801 772
         $mask = PATHINFO_FILENAME;
802
-        if ($withExt)
803
-        {
773
+        if ($withExt) {
804 774
             $mask = PATHINFO_BASENAME;
805 775
         }
806
-        return pathinfo($url,$mask);
776
+        return pathinfo($url, $mask);
807 777
     }
808 778
 
809 779
     /**
@@ -815,7 +785,7 @@ class ApiLayerService
815 785
      */
816 786
     private function getIdMask($id)
817 787
     {
818
-        return hash('crc32',$id);
788
+        return hash('crc32', $id);
819 789
     }
820 790
 
821 791
     /**
@@ -824,40 +794,33 @@ class ApiLayerService
824 794
      * @param JupyterVirtualClassroom $jupyter
825 795
      * @return bool $useUrl
826 796
      */
827
-    public function getFolderName(JupyterVirtualClassroom $jupyter,$useUrl = true)
797
+    public function getFolderName(JupyterVirtualClassroom $jupyter, $useUrl = true)
828 798
     {
829 799
         $url = $jupyter->getUrl();
830
-        if (!$useUrl || !$url)
831
-        {
800
+        if (!$useUrl || !$url) {
832 801
             $learningPath = $jupyter->getLearningPath();
833
-            if ($learningPath->isTemplate())
834
-            {
835
-                $title = substr($learningPath->getTitle() . " - " . $jupyter->getTitle(),0,70);
836
-                return sprintf('%s-%s',$this->getIdMask($jupyter->getSequenceItemId()),$title);
837
-            }
838
-            else
839
-            {
802
+            if ($learningPath->isTemplate()) {
803
+                $title = substr($learningPath->getTitle() . " - " . $jupyter->getTitle(), 0, 70);
804
+                return sprintf('%s-%s', $this->getIdMask($jupyter->getSequenceItemId()), $title);
805
+            } else {
840 806
                 $session = $jupyter->getSession();
841
-                $title = substr($session->getTitle() . " - " . $jupyter->getTitle(),0,70);
842
-                return sprintf('%s-%s',$this->getIdMask($jupyter->getSequenceItemId()),$title);
807
+                $title = substr($session->getTitle() . " - " . $jupyter->getTitle(), 0, 70);
808
+                return sprintf('%s-%s', $this->getIdMask($jupyter->getSequenceItemId()), $title);
843 809
             }
844
-        }
845
-        else
846
-        {
847
-            return $this->getFolderNameByUrl($url,true);
810
+        } else {
811
+            return $this->getFolderNameByUrl($url, true);
848 812
         }
849 813
     }
850 814
 
851
-    private function getFolderNameByUrl($url,$sanitize = true)
815
+    private function getFolderNameByUrl($url, $sanitize = true)
852 816
     {
853
-        $parts = explode('/',$url);
817
+        $parts = explode('/', $url);
854 818
 
855 819
         $result = $parts[count($parts) - 2];
856 820
 
857 821
         //  normalement pas de sanitize, car à ce niveau la, si le nom du dossier est incorrecte
858 822
         // c'est que le problème s'est produit en amon
859
-        if ($sanitize)
860
-        {
823
+        if ($sanitize) {
861 824
             return $this->sanitize($result);
862 825
         }
863 826
         return $result;
@@ -872,11 +835,10 @@ class ApiLayerService
872 835
      * 
873 836
      * @return string
874 837
      */
875
-    private function getNoteBookNameByString($id,$string,$withExt = true)
838
+    private function getNoteBookNameByString($id, $string, $withExt = true)
876 839
     {
877
-        $name = substr($this->sanitize($string),0,70);//sprintf('%s-%s',$this->getIdMask($id),$string));
878
-        if ($withExt)
879
-        {
840
+        $name = substr($this->sanitize($string), 0, 70); //sprintf('%s-%s',$this->getIdMask($id),$string));
841
+        if ($withExt) {
880 842
             $name .= '.ipynb';
881 843
         }
882 844
 
@@ -892,16 +854,16 @@ class ApiLayerService
892 854
      * 
893 855
      * @return void
894 856
      */
895
-    public function copyNotebookUser(JupyterToken $tokenIn,JupyterToken $tokenOut,JupyterVirtualClassroom $jupyter)
857
+    public function copyNotebookUser(JupyterToken $tokenIn, JupyterToken $tokenOut, JupyterVirtualClassroom $jupyter)
896 858
     {
897 859
         // récupère le contenu
898 860
         // get
899
-        $content = $this->getNotebookContent($tokenIn,$jupyter);
861
+        $content = $this->getNotebookContent($tokenIn, $jupyter);
900 862
 
901 863
 
902 864
         // upload le contenu
903 865
         // post
904
-        $this->setNotebookContent($tokenOut,$jupyter,json_encode($content));
866
+        $this->setNotebookContent($tokenOut, $jupyter, json_encode($content));
905 867
     }
906 868
 
907 869
     /**
@@ -913,25 +875,23 @@ class ApiLayerService
913 875
      * 
914 876
      * @return void
915 877
      */
916
-    public function changeNotebookUser(JupyterToken $tokenIn,JupyterToken $tokenOut,JupyterVirtualClassroom $jupyter)
878
+    public function changeNotebookUser(JupyterToken $tokenIn, JupyterToken $tokenOut, JupyterVirtualClassroom $jupyter)
917 879
     {
918 880
         $inResponse = $this->startServer($tokenIn);
919 881
         $outResponse = $this->startServer($tokenOut);
920 882
 
921 883
         // copie le notebook d'un utilisateur à l'autre
922
-        $this->copyNotebookUser($tokenIn,$tokenOut,$jupyter);
884
+        $this->copyNotebookUser($tokenIn, $tokenOut, $jupyter);
923 885
 
924 886
         // supprime le fichier
925 887
         // delete
926
-        $this->deleteNotebook($tokenIn,$jupyter);
888
+        $this->deleteNotebook($tokenIn, $jupyter);
927 889
 
928 890
         // stop les serveurs s'il étaient pas démarrés
929
-        if (!$inResponse['isStarted'])
930
-        {
891
+        if (!$inResponse['isStarted']) {
931 892
             $this->stopServer($tokenIn);
932 893
         }
933
-        if (!$outResponse['isStarted'])
934
-        {
894
+        if (!$outResponse['isStarted']) {
935 895
             $this->stopServer($tokenOut);
936 896
         }
937 897
     }
@@ -944,10 +904,10 @@ class ApiLayerService
944 904
      * 
945 905
      * @return void
946 906
      */
947
-    public function cloneNotebook(JupyterToken $token,JupyterVirtualClassroom $fromClassroom)
907
+    public function cloneNotebook(JupyterToken $token, JupyterVirtualClassroom $fromClassroom)
948 908
     {
949
-        $folderFrom = $this->getFolderNameByUrl($fromClassroom->getUrl(),false);
950
-        $folderTo = $this->getFolderName($fromClassroom,false);
909
+        $folderFrom = $this->getFolderNameByUrl($fromClassroom->getUrl(), false);
910
+        $folderTo = $this->getFolderName($fromClassroom, false);
951 911
         $path = $this->buildPath(
952 912
             array(
953 913
                 'phoenix',
@@ -960,10 +920,9 @@ class ApiLayerService
960 920
             )
961 921
         );
962 922
 
963
-        $response = $this->doApiPost($path,array(200,404));
964
-        if (isset($response['result']) && $response['result'] == 'True')
965
-        {
966
-            $fromClassroom->setUrl(str_replace($folderFrom,$response['folder'],$fromClassroom->getUrl()));
923
+        $response = $this->doApiPost($path, array(200, 404));
924
+        if (isset($response['result']) && $response['result'] == 'true') {
925
+            $fromClassroom->setUrl(str_replace($folderFrom, $response['folder'], $fromClassroom->getUrl()));
967 926
 
968 927
             return true;
969 928
         }
@@ -977,7 +936,7 @@ class ApiLayerService
977 936
      * 
978 937
      * @return bool
979 938
      */
980
-    public function notebookExist(JupyterToken $token,$url)
939
+    public function notebookExist(JupyterToken $token, $url)
981 940
     {
982 941
         $path = $this->buildPath(
983 942
             array(
@@ -989,9 +948,8 @@ class ApiLayerService
989 948
             )
990 949
         );
991 950
 
992
-        $response = $this->doApiGet($path,array(200,404));
993
-        if (isset($response['result']) && $response['result'] == 'True')
994
-        {
951
+        $response = $this->doApiGet($path, array(200, 404));
952
+        if (isset($response['result']) && $response['result'] == 'true') {
995 953
             return true;
996 954
         }
997 955
         return false;
@@ -1007,12 +965,12 @@ class ApiLayerService
1007 965
     public function getFolderUrlByNotebookUrl($url)
1008 966
     {
1009 967
         // redirige l'utilisateur sur le dossier du notebook
1010
-        $urlParts = explode('/',$url);
968
+        $urlParts = explode('/', $url);
1011 969
         array_pop($urlParts);
1012
-        return join('/',$urlParts);
970
+        return join('/', $urlParts);
1013 971
     }
1014 972
 
1015
-    public function resetNotebook(JupyterToken $trainerToken,JupyterToken $studentToken,$urlFrom,$urlTo)
973
+    public function resetNotebook(JupyterToken $trainerToken, JupyterToken $studentToken, $urlFrom, $urlTo)
1016 974
     {
1017 975
         $path = $this->buildPath(
1018 976
             array(
@@ -1020,17 +978,37 @@ class ApiLayerService
1020 978
                 'clone',
1021 979
                 $trainerToken->getUuid(),
1022 980
                 $studentToken->getUuid(),
1023
-                $this->getFolderNameByUrl($urlFrom,false),
981
+                $this->getFolderNameByUrl($urlFrom, false),
1024 982
                 $this->getFolderNameByUrl($urlTo),
1025 983
                 true
1026 984
             )
1027 985
         );
1028 986
 
1029
-        $response = $this->doApiPost($path,array(200,404));
1030
-        if (isset($response['result']) && $response['result'] == 'True')
1031
-        {
987
+        $response = $this->doApiPost($path, array(200, 404));
988
+        if (isset($response['result']) && $response['result'] == 'true') {
1032 989
             return true;
1033 990
         }
1034 991
         return false;
1035 992
     }
1036
-}
993
+
994
+    public function resetAssesmentNotebook(JupyterVirtualClassroom $sequenceItem,JupyterToken $trainerToken, JupyterToken $studentToken, $urlFrom): string
995
+    {
996
+        $path = $this->buildPath(
997
+            array(
998
+                'phoenix',
999
+                'fetch',
1000
+                $trainerToken->getUuid(),
1001
+                $studentToken->getUuid(),
1002
+                $this->getFolderNameByUrl($urlFrom, false),
1003
+                $this->getNoteBookName($sequenceItem)
1004
+            )
1005
+        );
1006
+
1007
+        $response = $this->doApiPost($path, array(200, 404));
1008
+
1009
+        if (isset($response['result']) && $response['result'] == 'true') {
1010
+            return $response['url'];
1011
+        }
1012
+        return '';
1013
+    }
1014
+}

+ 39
- 5
Services/PhoenixServices.php View File

@@ -25,24 +25,29 @@ use Logipro\Bundle\PhoenixJupyterBundle\Services\Uploader\NotebookUploader;
25 25
 use Symfony\Component\HttpFoundation\JsonResponse;
26 26
 use Logipro\Bundle\PhoenixJupyterBundle\Entity\JupyterSubmission;
27 27
 use Logipro\Phoenix\Entity\Sequence;
28
+use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
28 29
 
29 30
 class PhoenixServices extends Services
30 31
 {
31 32
 	private $layer;
32 33
 	private $isAvalaible;
33 34
 	private $layoutPath = '@LogiproPhoenixJupyter/back-office/';
35
+	private $tokenStorage;
34 36
 
35 37
 	public function __construct(
36 38
 		FormFactoryInterface $formFactory,
37 39
 		EntityManagerInterface $manager,
38 40
 		RouterInterface $router,
39 41
 		ApiLayerService $layer,
40
-		NotebookUploader $uploader
42
+		NotebookUploader $uploader,
43
+		TokenStorageInterface $tokenStorage
41 44
 	) {
42 45
 		parent::__construct($formFactory, $manager, $router);
43 46
 
44 47
 		$this->layer = $layer;
45 48
 		$this->uploader = $uploader;
49
+		$this->dirname = basename(realpath(__DIR__ . '/../'));
50
+		$this->tokenStorage = $tokenStorage;
46 51
 	}
47 52
 
48 53
 	/**
@@ -288,8 +293,15 @@ class PhoenixServices extends Services
288 293
 		);
289 294
 	}
290 295
 
291
-	public function getLearningSpaceBlocVariables($item)
296
+	public function getLearningSpaceBlocVariables($item): array
292 297
 	{
298
+		$jupyterClassroomRegistrationRepository = $this->getRepository(JupyterClassroomRegistration::class);
299
+		$currentUser = $this->tokenStorage->getToken()->getUser();;
300
+		$jupyterClassroomRegistration = $jupyterClassroomRegistrationRepository->getLastClassroomRegistration($item, $currentUser->getPerson(), false);
301
+		$replay = true;
302
+		if ($jupyterClassroomRegistration && is_null($jupyterClassroomRegistration->getUrl())) {
303
+			$replay = false;
304
+		}
293 305
 		return array(
294 306
 			'middle_layout' => '@LogiproPhoenixJupyter/learning_space/blocMiddle.html.twig',
295 307
 			'bottom_layout' => '@LogiproPhoenixJupyter/learning_space/blocBottom.html.twig',
@@ -298,6 +310,7 @@ class PhoenixServices extends Services
298 310
 			'type' => ($item->getIsAssesment()) ? 'JupyterEval' : 'Jupyter',
299 311
 			'type_name' => ($item->getIsAssesment()) ? 'Évaluation' : 'Jupyter',
300 312
 			'notebookname' => basename($item->getUrl()),
313
+			'replay' => $replay
301 314
 		);
302 315
 	}
303 316
 
@@ -423,7 +436,7 @@ class PhoenixServices extends Services
423 436
 
424 437
 	public function getManifestPath()
425 438
 	{
426
-		return 'vendor/logipro/PhoenixJupyterBundle/Resources/public/bundles/logiprophoenixjupyter/manifest.json';
439
+		return 'vendor/logipro/' . $this->dirname . '/Resources/public/bundles/logiprophoenixjupyter/manifest.json';
427 440
 	}
428 441
 
429 442
 
@@ -488,6 +501,11 @@ class PhoenixServices extends Services
488 501
 			$url = $layer->createStudentServerIfNoneAndSetContent($sequenceItem, $trainerToken, $personToken, true);
489 502
 		}
490 503
 
504
+		if (is_null($url)) {
505
+			throw new \Exception();
506
+		}
507
+
508
+
491 509
 		// persist le token s'il vient d'être créé
492 510
 		$manager = $this->getManager();
493 511
 		if (!$personToken->getTokenId()) {
@@ -586,7 +604,8 @@ class PhoenixServices extends Services
586 604
 
587 605
 			$submission = new JupyterSubmission();
588 606
 			$submission->setScore($data['score']);
589
-			$submission->setMaxScore($data['max-score']);
607
+			$submission->setMaxScore($data['max_score']);
608
+			$submission->setLog($data['log']);
590 609
 			$submission->setClassroomRegistration($jupyterClassroomRegistration);
591 610
 			$manager->persist($submission);
592 611
 		}
@@ -608,8 +627,23 @@ class PhoenixServices extends Services
608 627
 
609 628
 		$trainerToken = $this->getToken($sequenceItem->getTrainer());
610 629
 
611
-		// recherche l'url pour l'apprenant de l'inscription
612 630
 		$jupyterClassroomRegistrationRepository = $this->getRepository(JupyterClassroomRegistration::class);
631
+		if ($sequenceItem->getIsAssesment()) {
632
+			$url = $layer->resetAssesmentNotebook($sequenceItem,$trainerToken, $personToken, $sequenceItem->getUrl());
633
+			if ($url != "") {
634
+				$jupyterClassroomRegistration = $jupyterClassroomRegistrationRepository->getLastClassroomRegistration($sequenceItem, $person, false);
635
+				$jupyterClassroomRegistration->setUrl($url);
636
+
637
+				$manager = $this->getManager();
638
+				$manager->flush();
639
+
640
+				return true;
641
+			}
642
+			return false;
643
+		}
644
+
645
+		// recherche l'url pour l'apprenant de l'inscription
646
+
613 647
 		$jupyterClassroomRegistration = $jupyterClassroomRegistrationRepository->getLastClassroomRegistration($sequenceItem, $person);
614 648
 		if (!$jupyterClassroomRegistration) {
615 649
 			return false;

+ 21
- 0
Twig/PhxJupyterExtension.php View File

@@ -0,0 +1,21 @@
1
+<?php
2
+
3
+namespace Logipro\Bundle\PhoenixJupyterBundle\Twig;
4
+
5
+use Twig\Extension\AbstractExtension;
6
+use Twig\TwigFilter;
7
+
8
+class PhxJupyterExtension extends AbstractExtension
9
+{
10
+    public function getFilters()
11
+    {
12
+        return [
13
+            new TwigFilter('phxRenderLog', [$this, 'renderLog']),
14
+        ];
15
+    }
16
+
17
+    public function renderLog(string $log): string
18
+    {
19
+        return $log;
20
+    }
21
+}

Loading…
Cancel
Save