Passed
Push — master ( 6d3a7a...482b77 )
by Julito
12:08 queued 02:23
created

checkCourseRequirements()   B

Complexity

Conditions 6
Paths 6

Size

Total Lines 41
Code Lines 25

Duplication

Lines 0
Ratio 0 %

Importance

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

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