Passed
Push — master ( ccbe5e...c19a4d )
by Julito
09:19
created

SequenceResourceRepository::deleteResource()   A

Complexity

Conditions 6
Paths 4

Size

Total Lines 25
Code Lines 18

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 6
eloc 18
nc 4
nop 2
dl 0
loc 25
rs 9.0444
c 0
b 0
f 0
1
<?php
2
3
/* For licensing terms, see /license.txt */
4
5
namespace Chamilo\CoreBundle\Repository;
6
7
use Chamilo\CoreBundle\Entity\Course;
8
use Chamilo\CoreBundle\Entity\GradebookCategory;
9
use Chamilo\CoreBundle\Entity\SequenceResource;
10
use Chamilo\CoreBundle\Entity\Session;
11
use Chamilo\CoreBundle\Entity\SessionRelUser;
12
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
13
use Doctrine\Persistence\ManagerRegistry;
14
use Fhaculty\Graph\Set\Vertices;
15
use Fhaculty\Graph\Vertex;
16
17
/**
18
 * Class SequenceResourceRepository.
19
 */
20
class SequenceResourceRepository extends ServiceEntityRepository
21
{
22
    /**
23
     * CourseCategoryRepository constructor.
24
     */
25
    public function __construct(ManagerRegistry $registry)
26
    {
27
        parent::__construct($registry, SequenceResource::class);
28
    }
29
30
    /**
31
     * Find the SequenceResource based in the resourceId and type.
32
     *
33
     * @param int $resourceId
34
     * @param int $type
35
     *
36
     * @return SequenceResource
37
     */
38
    public function findRequirementForResource($resourceId, $type)
39
    {
40
        return $this->findOneBy(['resourceId' => $resourceId, 'type' => $type]);
41
    }
42
43
    /**
44
     * @todo implement for all types only work for sessions
45
     *
46
     * @param int $resourceId
47
     * @param int $type
48
     *
49
     * @return array
50
     */
51
    public function getRequirementAndDependencies($resourceId, $type)
52
    {
53
        $sequence = $this->findRequirementForResource($resourceId, $type);
54
        $result = ['requirements' => [], 'dependencies' => []];
55
        if ($sequence && $sequence->hasGraph()) {
56
            $graph = $sequence->getSequence()->getUnSerializeGraph();
57
            $vertex = $graph->getVertex($resourceId);
58
            $from = $vertex->getVerticesEdgeFrom();
59
60
            foreach ($from as $subVertex) {
61
                $vertexId = $subVertex->getId();
62
                $sessionInfo = api_get_session_info($vertexId);
63
                $sessionInfo['admin_link'] = '<a href="'.\SessionManager::getAdminPath($vertexId).'">'.$sessionInfo['name'].'</a>';
0 ignored issues
show
Bug introduced by
Are you sure SessionManager::getAdminPath($vertexId) of type false|string can be used in concatenation? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

63
                $sessionInfo['admin_link'] = '<a href="'./** @scrutinizer ignore-type */ \SessionManager::getAdminPath($vertexId).'">'.$sessionInfo['name'].'</a>';
Loading history...
64
                $result['requirements'][] = $sessionInfo;
65
            }
66
67
            $to = $vertex->getVerticesEdgeTo();
68
            foreach ($to as $subVertex) {
69
                $vertexId = $subVertex->getId();
70
                $sessionInfo = api_get_session_info($vertexId);
71
                $sessionInfo['admin_link'] = '<a href="'.\SessionManager::getAdminPath($vertexId).'">'.$sessionInfo['name'].'</a>';
72
                $result['dependencies'][] = $sessionInfo;
73
            }
74
        }
75
76
        return $result;
77
    }
78
79
    /**
80
     * Deletes a node and check in all the dependencies if the node exists in
81
     * order to deleted.
82
     *
83
     * @param int $resourceId
84
     * @param int $type
85
     */
86
    public function deleteSequenceResource($resourceId, $type)
87
    {
88
        $sequence = $this->findRequirementForResource($resourceId, $type);
89
        if ($sequence && $sequence->hasGraph()) {
90
            $em = $this->getEntityManager();
91
            $graph = $sequence->getSequence()->getUnSerializeGraph();
92
            $mainVertex = $graph->getVertex($resourceId);
93
            $vertices = $graph->getVertices();
94
95
            /** @var Vertex $vertex */
96
            foreach ($vertices as $vertex) {
97
                $subResourceId = $vertex->getId();
98
                $subSequence = $this->findRequirementForResource($subResourceId, $type);
99
                if ($sequence && $subSequence->hasGraph()) {
100
                    $graph = $subSequence->getSequence()->getUnSerializeGraph();
101
                    $subMainVertex = $graph->getVertex($resourceId);
102
                    $subMainVertex->destroy();
103
                    $subSequence->getSequence()->setGraphAndSerialize($graph);
104
                    $em->persist($subSequence);
105
                }
106
            }
107
108
            $mainVertex->destroy();
109
            $em->remove($sequence);
110
            $em->flush();
111
        }
112
    }
113
114
    /**
115
     * Get the requirements for a resource only.
116
     *
117
     * @param int $resourceId The resource ID
118
     * @param int $type       The type of sequence resource
119
     *
120
     * @return array
121
     */
122
    public function getRequirements($resourceId, $type)
123
    {
124
        $sequencesResource = $this->findBy(['resourceId' => $resourceId, 'type' => $type]);
125
        $em = $this->getEntityManager();
126
        $result = [];
127
        /** @var SequenceResource $sequenceResource */
128
        foreach ($sequencesResource as $sequenceResource) {
129
            if (!$sequenceResource->hasGraph()) {
130
                continue;
131
            }
132
133
            $sequence = $sequenceResource->getSequence();
134
            $graph = $sequence->getUnSerializeGraph();
135
            $vertex = $graph->getVertex($resourceId);
136
            $from = $vertex->getVerticesEdgeFrom();
137
138
            $sequenceInfo = [
139
                'name' => $sequence->getName(),
140
                'requirements' => [],
141
            ];
142
143
            foreach ($from as $subVertex) {
144
                $vertexId = $subVertex->getId();
145
                $resource = null;
146
                switch ($type) {
147
                    case SequenceResource::SESSION_TYPE:
148
                        $repo = $em->getRepository(Session::class);
149
                        $resource = $repo->find($vertexId);
150
151
                        break;
152
                    case SequenceResource::COURSE_TYPE:
153
                        $repo = $em->getRepository(Course::class);
154
                        $resource = $repo->find($vertexId);
155
156
                        break;
157
                }
158
159
                if (null === $resource) {
160
                    continue;
161
                }
162
163
                $sequenceInfo['requirements'][$vertexId] = $resource;
164
            }
165
166
            $result[$sequence->getId()] = $sequenceInfo;
167
        }
168
169
        return $result;
170
    }
171
172
    /**
173
     * Get the requirements and dependencies within a sequence for a resource.
174
     *
175
     * @param int $resourceId The resource ID
176
     * @param int $type       The type of sequence resource
177
     *
178
     * @return array
179
     */
180
    public function getRequirementsAndDependenciesWithinSequences($resourceId, $type)
181
    {
182
        $sequencesResource = $this->findBy([
183
            'resourceId' => $resourceId,
184
            'type' => $type,
185
        ]);
186
187
        $result = [];
188
189
        /** @var SequenceResource $sequenceResource */
190
        foreach ($sequencesResource as $sequenceResource) {
191
            if (!$sequenceResource->hasGraph()) {
192
                continue;
193
            }
194
195
            $sequence = $sequenceResource->getSequence();
196
            $graph = $sequence->getUnSerializeGraph();
197
            $vertex = $graph->getVertex($resourceId);
198
            $from = $vertex->getVerticesEdgeFrom();
199
            $to = $vertex->getVerticesEdgeTo();
200
201
            $requirements = $this->findVerticesEdges($from, $type);
202
            $dependencies = $this->findVerticesEdges($to, $type);
203
204
            $result[$sequence->getId()] = [
205
                'name' => $sequence->getName(),
206
                'requirements' => $requirements,
207
                'dependencies' => $dependencies,
208
            ];
209
        }
210
211
        return $result;
212
    }
213
214
    /**
215
     * Check if the ser has completed the requirements for the sequences.
216
     *
217
     * @param array $sequences The sequences
218
     * @param int   $type      The type of sequence resource
219
     * @param int   $userId
220
     *
221
     * @return array
222
     */
223
    public function checkRequirementsForUser(array $sequences, $type, $userId)
224
    {
225
        $sequenceList = [];
226
        $em = $this->getEntityManager();
227
        $gradebookCategoryRepo = $em->getRepository(GradebookCategory::class);
228
229
        $sessionUserList = [];
230
        if (SequenceResource::COURSE_TYPE == $type) {
231
            $criteria = ['user' => $userId];
232
            $sessions = $em->getRepository(SessionRelUser::class)->findBy($criteria);
233
            if ($sessions) {
234
                foreach ($sessions as $sessionRelUser) {
235
                    $sessionUserList[] = $sessionRelUser->getSession()->getId();
236
                }
237
            }
238
        }
239
240
        foreach ($sequences as $sequenceId => $sequence) {
241
            $item = [
242
                'name' => $sequence['name'],
243
                'requirements' => [],
244
            ];
245
            $resourceItem = null;
246
247
            foreach ($sequence['requirements'] as $resource) {
248
                switch ($type) {
249
                    case SequenceResource::SESSION_TYPE:
250
                        $id = $resource->getId();
251
                        $resourceItem = [
252
                            'name' => $resource->getName(),
253
                            'status' => true,
254
                        ];
255
256
                        $sessionsCourses = $resource->getCourses();
257
258
                        foreach ($sessionsCourses as $sessionCourse) {
259
                            $course = $sessionCourse->getCourse();
260
261
                            $gradebooks = $gradebookCategoryRepo->findBy(
262
                                [
263
                                    'courseCode' => $course->getCode(),
264
                                    'sessionId' => $resource->getId(),
265
                                    'isRequirement' => true,
266
                                ]
267
                            );
268
269
                            foreach ($gradebooks as $gradebook) {
270
                                $category = \Category::createCategoryObjectFromEntity($gradebook);
271
272
                                if (!empty($userId)) {
273
                                    $resourceItem['status'] = $resourceItem['status'] && \Category::userFinishedCourse(
274
                                        $userId,
275
                                        $category
276
                                    );
277
                                }
278
                            }
279
                        }
280
281
                        break;
282
283
                    case SequenceResource::COURSE_TYPE:
284
                        $id = $resource->getId();
285
                        $status = $this->checkCourseRequirements($userId, $resource, 0);
286
287
                        if (false === $status) {
288
                            $sessionsInCourse = \SessionManager::get_session_by_course($id);
289
                            foreach ($sessionsInCourse as $session) {
290
                                if (in_array($session['id'], $sessionUserList)) {
291
                                    $status = $this->checkCourseRequirements($userId, $resource, $session['id']);
292
                                    if (true === $status) {
293
                                        break;
294
                                    }
295
                                }
296
                            }
297
                        }
298
299
                        $resourceItem = [
300
                            'name' => $resource->getTitle(),
301
                            'status' => $status,
302
                        ];
303
304
                        break;
305
                }
306
307
                if (empty($id)) {
308
                    continue;
309
                }
310
311
                $item['requirements'][$id] = $resourceItem;
312
            }
313
            $sequenceList[$sequenceId] = $item;
314
        }
315
316
        return $sequenceList;
317
    }
318
319
    public function checkCourseRequirements($userId, Course $course, $sessionId)
320
    {
321
        $em = $this->getEntityManager();
322
        $sessionId = (int) $sessionId;
323
324
        $gradebookCategoryRepo = $em->getRepository(GradebookCategory::class);
325
        $gradebooks = $gradebookCategoryRepo->findBy(
326
            [
327
                'courseCode' => $course->getCode(),
328
                'sessionId' => $sessionId,
329
                'isRequirement' => true,
330
            ]
331
        );
332
333
        if (empty($gradebooks)) {
334
            return false;
335
        }
336
337
        $status = true;
338
        foreach ($gradebooks as $gradebook) {
339
            $category = \Category::createCategoryObjectFromEntity($gradebook);
340
            $userFinishedCourse = \Category::userFinishedCourse(
341
                $userId,
342
                $category,
343
                true
344
            );
345
346
            if (0 === $sessionId) {
347
                if (false === $userFinishedCourse) {
348
                    $status = false;
349
350
                    break;
351
                }
352
            } else {
353
                if (false === $userFinishedCourse) {
354
                    $status = false;
355
356
                    break;
357
                }
358
            }
359
        }
360
361
        return $status;
362
    }
363
364
    /**
365
     * Check if at least one sequence are completed.
366
     *
367
     * @param array $sequences The sequences
368
     *
369
     * @return bool
370
     */
371
    public function checkSequenceAreCompleted(array $sequences)
372
    {
373
        foreach ($sequences as $sequence) {
374
            $status = true;
375
376
            foreach ($sequence['requirements'] as $item) {
377
                $status = $status && $item['status'];
378
            }
379
380
            if ($status) {
381
                return true;
382
            }
383
        }
384
385
        return false;
386
    }
387
388
    /**
389
     * Get sessions from vertices.
390
     *
391
     * @param Vertices $verticesEdges The vertices
392
     * @param int      $type
393
     *
394
     * @return array
395
     */
396
    protected function findVerticesEdges(Vertices $verticesEdges, $type)
397
    {
398
        $sessionVertices = [];
399
        $em = $this->getEntityManager();
400
401
        foreach ($verticesEdges as $supVertex) {
402
            $vertexId = $supVertex->getId();
403
            switch ($type) {
404
                case SequenceResource::SESSION_TYPE:
405
                    $resource = $em->getRepository(Session::class)->find($vertexId);
406
407
                    break;
408
                case SequenceResource::COURSE_TYPE:
409
                    $resource = $em->getRepository(Course::class)->find($vertexId);
410
411
                    break;
412
            }
413
414
            if (empty($resource)) {
415
                continue;
416
            }
417
418
            $sessionVertices[$vertexId] = $resource;
419
        }
420
421
        return $sessionVertices;
422
    }
423
}
424