Issues (2128)

main/inc/ajax/sequence.ajax.php (2 issues)

1
<?php
2
3
/* For licensing terms, see /license.txt */
4
5
use Chamilo\CoreBundle\Entity\Repository\SequenceRepository;
6
use Chamilo\CoreBundle\Entity\Repository\SequenceResourceRepository;
7
use Chamilo\CoreBundle\Entity\Sequence;
8
use Chamilo\CoreBundle\Entity\SequenceResource;
9
use ChamiloSession as Session;
10
use Fhaculty\Graph\Graph;
11
use Fhaculty\Graph\Vertex;
12
use Graphp\GraphViz\GraphViz;
13
14
/**
15
 * Responses to AJAX calls.
16
 */
17
require_once __DIR__.'/../global.inc.php';
18
19
$action = $_REQUEST['a'] ?? null;
20
$id = (int) ($_REQUEST['id'] ?? null);
21
$type = (int) ($_REQUEST['type'] ?? null);
22
$sequenceId = $_REQUEST['sequence_id'] ?? 0;
23
24
$em = Database::getManager();
25
/** @var SequenceRepository $sequenceRepository */
26
$sequenceRepository = $em->getRepository(Sequence::class);
27
/** @var SequenceResourceRepository $sequenceResourceRepository */
28
$sequenceResourceRepository = $em->getRepository(SequenceResource::class);
29
30
switch ($action) {
31
    case 'graph':
32
        api_block_anonymous_users();
33
34
        /** @var Sequence $sequence */
35
        $sequence = $sequenceRepository->find($sequenceId);
36
37
        if (null === $sequence) {
38
            exit;
39
        }
40
41
        if ($sequence->hasGraph()) {
42
            $graph = $sequence->getUnSerializeGraph();
43
            $graph->setAttribute('graphviz.node.fontname', 'arial');
44
            $graphviz = new GraphViz();
45
            $graphImage = '';
46
            try {
47
                $graphImage = $graphviz->createImageSrc($graph);
48
                echo Display::img(
49
                    $graphImage,
50
                    get_lang('GraphDependencyTree'),
51
                    ['class' => 'center-block img-responsive'],
52
                    false
53
                );
54
            } catch (UnexpectedValueException $e) {
55
                error_log(
56
                    $e->getMessage()
57
                    .' - Graph could not be rendered in resources sequence'
58
                    .' because GraphViz command "dot" could not be executed '
59
                    .'- Make sure graphviz is installed.'
60
                );
61
                echo '<p class="text-center"><small>'.get_lang('MissingChartLibraryPleaseCheckLog')
62
                    .'</small></p>';
63
            }
64
        }
65
66
        break;
67
    case 'get_icon':
68
        api_block_anonymous_users();
69
        api_protect_admin_script();
70
71
        $showDelete = $_REQUEST['show_delete'] ?? false;
72
        $image = Display::return_icon('item-sequence.png', null, null, ICON_SIZE_LARGE);
73
74
        if (empty($id)) {
75
            exit;
76
        }
77
78
        $link = '';
79
        $linkDelete = $linkUndo = '';
80
        $resourceName = '';
81
        switch ($type) {
82
            case SequenceResource::SESSION_TYPE:
83
                $resourceData = api_get_session_info($id);
84
                if ($resourceData) {
85
                    $resourceName = $resourceData['name'];
86
                }
87
                break;
88
            case SequenceResource::COURSE_TYPE:
89
                $resourceData = api_get_course_info_by_id($id);
90
                if ($resourceData) {
91
                    $resourceName = $resourceData['name'];
92
                }
93
                break;
94
        }
95
96
        if (empty($resourceData)) {
97
            exit;
98
        }
99
100
        if ($showDelete) {
101
            $linkDelete = Display::toolbarButton(
102
                get_lang('Delete'),
103
                '#',
104
                'trash',
105
                'default',
106
                [
107
                    'class' => 'delete_vertex btn btn-block btn-xs',
108
                    'data-id' => $id,
109
                ]
110
            );
111
112
            $linkUndo = Display::toolbarButton(
113
                get_lang('Undo'),
114
                '#',
115
                'undo',
116
                'default',
117
                [
118
                    'class' => 'undo_delete btn btn-block btn-xs',
119
                    'style' => 'display: none;',
120
                    'data-id' => $id,
121
                ]
122
            );
123
        }
124
125
        $link = '<div class="parent" data-id="'.$id.'">';
126
        $link .= '<div class="big-icon">';
127
        $link .= $image;
128
        $link .= '<div class="sequence-course">'.$resourceName.'</div>';
129
        $link .= Display::tag(
130
            'button',
131
            $resourceName,
132
            [
133
                'class' => 'sequence-id',
134
                'title' => get_lang('UseAsReference'),
135
                'type' => 'button',
136
            ]
137
        );
138
        $link .= $linkDelete;
139
        $link .= $linkUndo;
140
        $link .= '</div></div>';
141
142
        echo $link;
143
        break;
144
    case 'delete_vertex':
145
        api_block_anonymous_users();
146
        api_protect_admin_script();
147
148
        $vertexId = $_REQUEST['vertex_id'] ?? null;
149
150
        /** @var Sequence $sequence */
151
        $sequence = $sequenceRepository->find($sequenceId);
152
153
        if (null === $sequence) {
154
            exit;
155
        }
156
157
        /** @var SequenceResource $sequenceResource */
158
        $sequenceResource = $sequenceResourceRepository->findOneBy(
159
            ['resourceId' => $id, 'type' => $type, 'sequence' => $sequence]
160
        );
161
162
        if (null === $sequenceResource) {
163
            exit;
164
        }
165
166
        if ($sequenceResource->getSequence()->hasGraph()) {
167
            $graph = $sequenceResource->getSequence()->getUnSerializeGraph();
168
            if ($graph->hasVertex($vertexId)) {
169
                $edgeIterator = $graph->getEdges()->getIterator();
170
                $edgeToDelete = null;
171
                foreach ($edgeIterator as $edge) {
172
                    if ($edge->getVertexStart()->getId() == $vertexId && $edge->getVertexEnd()->getId() == $id) {
173
                        $edgeToDelete = $edge;
174
                        $vertexFromTo = null;
175
                        $vertexToFrom = null;
176
                        foreach ($edgeIterator as $edges) {
177
                            if ((int) $edges->getVertexEnd()->getId() === (int) $id) {
178
                                $vertexFromTo = $edges;
179
                            }
180
181
                            if ((int) $edges->getVertexStart()->getId() === (int) $vertexId) {
182
                                $vertexToFrom = $edges;
183
                            }
184
                        }
185
186
                        if ($vertexFromTo && !$vertexToFrom) {
187
                            Session::write('sr_vertex', true);
188
                            $vertex = $graph->getVertex($id);
189
                            $vertex->destroy();
190
                            $em->remove($sequenceResource);
191
                        }
192
193
                        if ($vertexToFrom && $vertexFromTo) {
194
                            $vertex = $graph->getVertex($vertexId);
195
                            $edgeToDelete->destroy();
196
                        }
197
198
                        if ($vertexToFrom && !$vertexFromTo) {
199
                            $vertex = $graph->getVertex($vertexId);
200
                            $vertex->destroy();
201
                            $sequenceResourceToDelete = $sequenceResourceRepository->findOneBy(
202
                                [
203
                                    'resourceId' => $vertexId,
204
                                    'type' => $type,
205
                                    'sequence' => $sequence,
206
                                ]
207
                            );
208
                            $em->remove($sequenceResourceToDelete);
209
                        }
210
211
                        if (!$vertexToFrom && !$vertexFromTo) {
212
                            Session::write('sr_vertex', true);
213
                            $vertexTo = $graph->getVertex($id);
214
                            $vertexFrom = $graph->getVertex($vertexId);
215
                            if ($vertexTo->getVerticesEdgeFrom()->count() > 1) {
216
                                $vertexFrom->destroy();
217
                                $sequenceResourceToDelete = $sequenceResourceRepository->findOneBy(
218
                                    [
219
                                        'resourceId' => $vertexId,
220
                                        'type' => $type,
221
                                        'sequence' => $sequence,
222
                                    ]
223
                                );
224
                                $em->remove($sequenceResourceToDelete);
225
                            } else {
226
                                $vertexTo->destroy();
227
                                $vertexFrom->destroy();
228
                                $sequenceResourceToDelete = $sequenceResourceRepository->findOneBy(
229
                                    [
230
                                        'resourceId' => $vertexId,
231
                                        'type' => $type,
232
                                        'sequence' => $sequence,
233
                                    ]
234
                                );
235
                                $em->remove($sequenceResource);
236
                                $em->remove($sequenceResourceToDelete);
237
                            }
238
                        }
239
                    }
240
                }
241
242
                $sequence->setGraphAndSerialize($graph);
243
                $em->merge($sequence);
244
                $em->flush();
245
            }
246
        }
247
248
        break;
249
    case 'load_resource':
250
        api_block_anonymous_users();
251
        api_protect_admin_script();
252
253
        // children or parent
254
        $loadResourceType = $_REQUEST['load_resource_type'] ?? null;
255
256
        /** @var Sequence $sequence */
257
        $sequence = $sequenceRepository->find($sequenceId);
258
259
        if (empty($sequence)) {
260
            exit;
261
        }
262
263
        /** @var SequenceResource $sequenceResource */
264
        $sequenceResource = $sequenceResourceRepository->findOneBy(
265
            ['resourceId' => $id, 'type' => $type, 'sequence' => $sequence]
266
        );
267
268
        if (null === $sequenceResource) {
269
            exit;
270
        }
271
272
        if ($sequenceResource->hasGraph()) {
273
            $graph = $sequenceResource->getSequence()->getUnSerializeGraph();
274
275
            /** @var Vertex $mainVertice */
276
            if ($graph->hasVertex($id)) {
277
                $mainVertex = $graph->getVertex($id);
278
279
                if (!empty($mainVertex)) {
280
                    $vertexList = null;
281
                    switch ($loadResourceType) {
282
                        case 'parent':
283
                            $vertexList = $mainVertex->getVerticesEdgeFrom();
284
285
                            break;
286
                        case 'children':
287
                            $vertexList = $mainVertex->getVerticesEdgeTo();
288
                            break;
289
                    }
290
291
                    $list = [];
292
                    if (!empty($vertexList)) {
293
                        foreach ($vertexList as $vertex) {
294
                            $list[] = $vertex->getId();
295
                        }
296
                    }
297
298
                    if (!empty($list)) {
299
                        echo implode(',', $list);
300
                    }
301
                }
302
            }
303
        }
304
        break;
305
    case 'save_resource':
306
        api_block_anonymous_users();
307
        api_protect_admin_script();
308
309
        $parents = $_REQUEST['parents'] ?? '';
310
311
        if (empty($parents) || empty($sequenceId) || empty($type)) {
312
            exit;
313
        }
314
315
        /** @var Sequence $sequence */
316
        $sequence = $sequenceRepository->find($sequenceId);
317
318
        if (null === $sequence) {
319
            exit;
320
        }
321
322
        /*$vertexFromSession = Session::read('sr_vertex');
323
        if ($vertexFromSession) {
324
            Session::erase('sr_vertex');
325
            echo Display::return_message(get_lang('Saved'), 'success');
326
            break;
327
        }*/
328
329
        $parents = str_replace($id, '', $parents);
330
        $parents = explode(',', $parents);
331
        $parents = array_filter($parents);
332
333
        if ($sequence->hasGraph()) {
334
            $graph = $sequence->getUnSerializeGraph();
335
        } else {
336
            $graph = new Graph();
337
        }
338
339
        if ($graph->hasVertex($id)) {
340
            $main = $graph->getVertex($id);
341
        } else {
342
            $main = $graph->createVertex($id);
343
        }
344
345
        $item = $sequenceRepository->getItem($id, $type);
346
        $main->setAttribute('graphviz.shape', 'record');
347
        $main->setAttribute('graphviz.label', $item->getName());
348
349
        foreach ($parents as $parentId) {
350
            $item = $sequenceRepository->getItem($parentId, $type);
351
            if ($graph->hasVertex($parentId)) {
352
                $parent = $graph->getVertex($parentId);
353
                if (!$parent->hasEdgeTo($main)) {
354
                    $newEdge = $parent->createEdgeTo($main);
355
                }
356
            } else {
357
                $parent = $graph->createVertex($parentId);
358
                $newEdge = $parent->createEdgeTo($main);
359
            }
360
361
            $parent->setAttribute('graphviz.shape', 'record');
362
            $parent->setAttribute('graphviz.label', $item->getName());
363
        }
364
365
        foreach ($parents as $parentId) {
0 ignored issues
show
Comprehensibility Bug introduced by
$parentId is overwriting a variable from outer foreach loop.
Loading history...
366
            $sequenceResourceParent = $sequenceResourceRepository->findOneBy(
367
                ['resourceId' => $parentId, 'type' => $type, 'sequence' => $sequence]
368
            );
369
370
            if (empty($sequenceResourceParent)) {
371
                $sequenceResourceParent = new SequenceResource();
372
                $sequenceResourceParent
373
                    ->setSequence($sequence)
374
                    ->setType($type)
375
                    ->setResourceId($parentId);
376
                $em->persist($sequenceResourceParent);
377
            }
378
        }
379
380
        /** @var SequenceResource $sequenceResource */
381
        $sequenceResource = $sequenceResourceRepository->findOneBy(
382
            ['resourceId' => $id, 'type' => $type, 'sequence' => $sequence]
383
        );
384
385
        if (null === $sequenceResource) {
386
            // Create
387
            $sequence->setGraphAndSerialize($graph);
388
            $sequenceResource = new SequenceResource();
389
            $sequenceResource
390
                ->setSequence($sequence)
391
                ->setType($type)
392
                ->setResourceId($id);
393
        } else {
394
            // Update
395
            $sequenceResource->getSequence()->setGraphAndSerialize($graph);
396
        }
397
        $em->persist($sequenceResource);
398
        $em->flush();
399
400
        echo Display::return_message(get_lang('Saved'), 'success');
401
402
        break;
403
    case 'get_requirements':
404
    case 'get_dependents':
405
        $sessionId = isset($_REQUEST['sid']) ? (int) $_REQUEST['sid'] : 0;
406
        $userId = api_get_user_id();
407
        $resourceName = '';
408
        $template = '';
409
        switch ($type) {
410
            case SequenceResource::SESSION_TYPE:
411
                $resourceData = api_get_session_info($id);
412
413
                $resourceName = $resourceData['name'];
414
                $template = 'session_requirements.tpl';
415
                break;
416
            case SequenceResource::COURSE_TYPE:
417
                $resourceData = api_get_course_info_by_id($id);
418
                $resourceName = $resourceData['title'];
419
                $template = 'course_requirements.tpl';
420
                break;
421
        }
422
423
        if (empty($resourceData) || empty($template)) {
424
            exit;
425
        }
426
427
        if ('get_requirements' === $action) {
428
            $sequences = $sequenceResourceRepository->getRequirements($id, $type);
429
            $sequenceList = $sequenceResourceRepository->checkRequirementsForUser($sequences, $type, $userId, $sessionId);
430
431
            $allowSubscription = $sequenceResourceRepository->checkSequenceAreCompleted($sequenceList);
432
        } else {
433
            $sequences = $sequenceResourceRepository->getDependents($id, $type);
434
            $sequenceList = $sequenceResourceRepository->checkDependentsForUser($sequences, $type, $userId, $sessionId);
435
436
            $allowSubscription = $sequenceResourceRepository->checkSequenceAreCompleted(
437
                $sequenceList,
438
                SequenceResourceRepository::VERTICES_TYPE_DEP
439
            );
440
        }
441
442
        $view = new Template(null, false, false, false, false, false);
443
        $view->assign('sequences', $sequenceList);
444
        $view->assign('sequence_type', $type);
445
        $view->assign('allow_subscription', $allowSubscription);
446
        $view->assign(
447
            'item_type',
448
            'get_requirements' === $action
449
                ? SequenceResourceRepository::VERTICES_TYPE_REQ
450
                : SequenceResourceRepository::VERTICES_TYPE_DEP
451
        );
452
        $course = api_get_course_entity();
453
        if ($course) {
0 ignored issues
show
$course is of type Chamilo\CoreBundle\Entity\Course, thus it always evaluated to true.
Loading history...
454
            $view->assign(
455
                'current_requirement_is_completed',
456
                $sequenceResourceRepository->checkCourseRequirements($userId, $course, $sessionId)
457
            );
458
        }
459
460
        if ($allowSubscription) {
461
            $view->assign(
462
                'subscribe_button',
463
                CoursesAndSessionsCatalog::getRegisteredInSessionButton(
464
                    $id,
465
                    $resourceName,
466
                    false
467
                )
468
            );
469
        }
470
471
        $view->display($view->get_template('sequence_resource/'.$template));
472
473
        break;
474
}
475