Completed
Push — master ( 8578c1...3a76aa )
by Julito
09:38
created

ResourceRepository::getRepository()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 3
rs 10
c 0
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\Resource\AbstractResource;
8
use Chamilo\CoreBundle\Entity\Resource\ResourceFile;
9
use Chamilo\CoreBundle\Entity\Resource\ResourceLink;
10
use Chamilo\CoreBundle\Entity\Resource\ResourceNode;
11
use Chamilo\CoreBundle\Entity\Resource\ResourceRight;
12
use Chamilo\CoreBundle\Entity\Resource\ResourceType;
13
use Chamilo\CoreBundle\Entity\Session;
14
use Chamilo\CoreBundle\Entity\Tool;
15
use Chamilo\CoreBundle\Entity\Usergroup;
16
use Chamilo\CoreBundle\Security\Authorization\Voter\ResourceNodeVoter;
17
use Chamilo\CourseBundle\Entity\CGroupInfo;
18
use Chamilo\UserBundle\Entity\User;
19
use Doctrine\ORM\EntityManager;
20
use Doctrine\ORM\Query\Expr\Join;
21
use League\Flysystem\FilesystemInterface;
22
use League\Flysystem\MountManager;
23
use Sylius\Bundle\ResourceBundle\Doctrine\ORM\EntityRepository;
24
use Symfony\Component\HttpFoundation\File\UploadedFile;
25
use Symfony\Component\Routing\RouterInterface;
26
27
/**
28
 * Class ResourceRepository.
29
 */
30
class ResourceRepository extends EntityRepository
31
{
32
    /**
33
     * @var EntityRepository
34
     */
35
    protected $repository;
36
37
    /**
38
     * @var FilesystemInterface
39
     */
40
    protected $fs;
41
42
    /**
43
     * @var EntityManager
44
     */
45
    protected $entityManager;
46
47
    /**
48
     * The entity class FQN.
49
     *
50
     * @var string
51
     */
52
    protected $className;
53
54
    /** @var RouterInterface */
55
    protected $router;
56
57
    protected $resourceNodeRepository;
58
59
    /**
60
     * ResourceRepository constructor.
61
     *
62
     * @param EntityManager   $entityManager
63
     * @param MountManager    $mountManager
64
     * @param RouterInterface $router
65
     * @param string          $className
66
     */
67
    public function __construct(EntityManager $entityManager, MountManager $mountManager, RouterInterface $router, string $className)
68
    {
69
        $this->repository = $entityManager->getRepository($className);
70
        // Flysystem mount name is saved in config/packages/oneup_flysystem.yaml @todo add it as a service.
71
        $this->fs = $mountManager->getFilesystem('resources_fs');
72
        $this->router = $router;
73
        $this->resourceNodeRepository = $entityManager->getRepository('ChamiloCoreBundle:Resource\ResourceNode');
74
    }
75
76
    /**
77
     * @return mixed
78
     */
79
    public function create()
80
    {
81
        return new $this->className();
82
    }
83
84
    /**
85
     * @return RouterInterface
86
     */
87
    public function getRouter(): RouterInterface
88
    {
89
        return $this->router;
90
    }
91
92
    /**
93
     * @return EntityRepository
94
     */
95
    public function getResourceNodeRepository()
96
    {
97
        return $this->resourceNodeRepository;
98
    }
99
100
    /**
101
     * @return FilesystemInterface
102
     */
103
    public function getFileSystem()
104
    {
105
        return $this->fs;
106
    }
107
108
    /**
109
     * @return EntityManager
110
     */
111
    public function getEntityManager(): EntityManager
112
    {
113
        return $this->getRepository()->getEntityManager();
114
    }
115
116
    /**
117
     * @return EntityRepository
118
     */
119
    public function getRepository()
120
    {
121
        return $this->repository;
122
    }
123
124
    /**
125
     * @param mixed $id
126
     * @param null  $lockMode
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $lockMode is correct as it would always require null to be passed?
Loading history...
127
     * @param null  $lockVersion
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $lockVersion is correct as it would always require null to be passed?
Loading history...
128
     *
129
     * @return AbstractResource|null
130
     */
131
    public function find($id, $lockMode = null, $lockVersion = null): ?AbstractResource
132
    {
133
        return $this->getRepository()->find($id);
134
    }
135
136
    /**
137
     * @param array      $criteria
138
     * @param array|null $orderBy
139
     *
140
     * @return AbstractResource
141
     */
142
    public function findOneBy(array $criteria, array $orderBy = null): ?AbstractResource
143
    {
144
        return $this->getRepository()->findOneBy($criteria, $orderBy);
145
    }
146
147
    /**
148
     * @param ResourceNode $resourceNode
149
     * @param UploadedFile $file
150
     *
151
     * @return ResourceFile
152
     */
153
    public function addFile(ResourceNode $resourceNode, UploadedFile $file): ?ResourceFile
154
    {
155
        $resourceFile = $resourceNode->getResourceFile();
156
        if ($resourceFile === null) {
157
            $resourceFile = new ResourceFile();
158
        }
159
160
        $em = $this->getEntityManager();
161
162
        $resourceFile->setFile($file);
163
        $resourceFile->setName($resourceNode->getName());
164
        $em->persist($resourceFile);
165
        $resourceNode->setResourceFile($resourceFile);
166
        $em->persist($resourceNode);
167
        $em->flush();
168
169
        return $resourceFile;
170
    }
171
172
    /**
173
     * Creates a ResourceNode.
174
     *
175
     * @param AbstractResource $resource
176
     * @param User             $creator
177
     * @param AbstractResource $parent
178
     *
179
     * @return ResourceNode
180
     */
181
    public function addResourceNode(AbstractResource $resource, User $creator, AbstractResource $parent = null): ResourceNode
182
    {
183
        $em = $this->getEntityManager();
184
185
        $resourceType = $this->getResourceType();
186
187
        $resourceNode = new ResourceNode();
188
        $resourceNode
189
            ->setName($resource->getResourceName())
190
            ->setCreator($creator)
191
            ->setResourceType($resourceType)
192
        ;
193
194
        if ($parent !== null) {
195
            $resourceNode->setParent($parent->getResourceNode());
196
        }
197
198
        $resource->setResourceNode($resourceNode);
199
200
        $em->persist($resourceNode);
201
        $em->persist($resource);
202
        $em->flush();
203
204
        return $resourceNode;
205
    }
206
207
    /**
208
     * @param AbstractResource $resource
209
     * @param int              $visibility
210
     * @param User             $creator
211
     * @param Course           $course
212
     * @param Session          $session
213
     * @param CGroupInfo       $group
214
     */
215
    public function addResourceToCourse(AbstractResource $resource, int $visibility, User $creator, Course $course, Session $session = null, CGroupInfo $group = null)
216
    {
217
        $node = $this->addResourceNode($resource, $creator, $course);
218
        $this->addResourceNodeToCourse($node, $visibility, $course, $session, $group);
219
    }
220
221
    /**
222
     * @param ResourceNode $resourceNode
223
     * @param int          $visibility
224
     * @param Course       $course
225
     * @param Session      $session
226
     * @param CGroupInfo   $group
227
     */
228
    public function addResourceNodeToCourse(ResourceNode $resourceNode, $visibility, $course, $session, $group): void
229
    {
230
        $visibility = (int) $visibility;
231
        if (empty($visibility)) {
232
            $visibility = ResourceLink::VISIBILITY_PUBLISHED;
233
        }
234
235
        $link = new ResourceLink();
236
        $link
237
            ->setCourse($course)
238
            ->setSession($session)
239
            ->setGroup($group)
240
            //->setUser($toUser)
241
            ->setResourceNode($resourceNode)
242
            ->setVisibility($visibility)
243
        ;
244
245
        $rights = [];
246
        switch ($visibility) {
247
            case ResourceLink::VISIBILITY_PENDING:
248
            case ResourceLink::VISIBILITY_DRAFT:
249
                $editorMask = ResourceNodeVoter::getEditorMask();
250
                $resourceRight = new ResourceRight();
251
                $resourceRight
252
                    ->setMask($editorMask)
253
                    ->setRole(ResourceNodeVoter::ROLE_CURRENT_COURSE_TEACHER)
254
                ;
255
                $rights[] = $resourceRight;
256
                break;
257
        }
258
259
        if (!empty($rights)) {
260
            foreach ($rights as $right) {
261
                $link->addResourceRight($right);
262
            }
263
        }
264
265
        $em = $this->getEntityManager();
266
        $em->persist($link);
267
        $em->flush();
268
    }
269
270
    /**
271
     * @return ResourceType
272
     */
273
    public function getResourceType()
274
    {
275
        $em = $this->getEntityManager();
276
        $entityName = $this->getRepository()->getClassMetadata()->getReflectionClass()->getShortName();
277
278
        return $em->getRepository('ChamiloCoreBundle:Resource\ResourceType')->findOneBy(
279
            ['name' => $entityName]
280
        );
281
    }
282
283
    /**
284
     * @param ResourceNode $resourceNode
285
     *
286
     * @return ResourceLink
287
     */
288
    public function addResourceToMe(ResourceNode $resourceNode): ResourceLink
289
    {
290
        $resourceLink = new ResourceLink();
291
        $resourceLink
292
            ->setResourceNode($resourceNode)
293
            ->setPrivate(true);
0 ignored issues
show
Bug introduced by
The method setPrivate() does not exist on Chamilo\CoreBundle\Entity\Resource\ResourceLink. ( Ignorable by Annotation )

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

293
            ->/** @scrutinizer ignore-call */ setPrivate(true);

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
294
295
        $this->getEntityManager()->persist($resourceLink);
296
        $this->getEntityManager()->flush();
297
298
        return $resourceLink;
299
    }
300
301
    /**
302
     * @param ResourceNode  $resourceNode
303
     * @param ResourceRight $right
304
     *
305
     * @return ResourceLink
306
     */
307
    public function addResourceToEveryone(ResourceNode $resourceNode, ResourceRight $right): ResourceLink
308
    {
309
        $resourceLink = new ResourceLink();
310
        $resourceLink
311
            ->setResourceNode($resourceNode)
312
            ->addResourceRight($right)
313
        ;
314
315
        $this->getEntityManager()->persist($resourceLink);
316
        $this->getEntityManager()->flush();
317
318
        return $resourceLink;
319
    }
320
321
    /**
322
     * @param ResourceNode  $resourceNode
323
     * @param Course        $course
324
     * @param ResourceRight $right
325
     *
326
     * @return ResourceLink
327
     */
328
    public function addResourceToCourse2(ResourceNode $resourceNode, Course $course, ResourceRight $right): ResourceLink
329
    {
330
        $resourceLink = new ResourceLink();
331
        $resourceLink
332
            ->setResourceNode($resourceNode)
333
            ->setCourse($course)
334
            ->addResourceRight($right);
335
        $this->getEntityManager()->persist($resourceLink);
336
        $this->getEntityManager()->flush();
337
338
        return $resourceLink;
339
    }
340
341
    /**
342
     * @param ResourceNode $resourceNode
343
     * @param User         $toUser
344
     *
345
     * @return ResourceLink
346
     */
347
    public function addResourceToUser(ResourceNode $resourceNode, User $toUser): ResourceLink
348
    {
349
        $resourceLink = $this->addResourceNodeToUser($resourceNode, $toUser);
350
        $this->getEntityManager()->persist($resourceLink);
351
352
        return $resourceLink;
353
    }
354
355
    /**
356
     * @param ResourceNode $resourceNode
357
     * @param User         $toUser
358
     *
359
     * @return ResourceLink
360
     */
361
    public function addResourceNodeToUser(ResourceNode $resourceNode, User $toUser): ResourceLink
362
    {
363
        $resourceLink = new ResourceLink();
364
        $resourceLink
365
            ->setResourceNode($resourceNode)
366
            ->setUser($toUser);
367
368
        return $resourceLink;
369
    }
370
371
    /**
372
     * @param ResourceNode  $resourceNode
373
     * @param Course        $course
374
     * @param Session       $session
375
     * @param ResourceRight $right
376
     *
377
     */
378
    public function addResourceToSession(
379
        ResourceNode $resourceNode,
380
        Course $course,
381
        Session $session,
382
        ResourceRight $right
383
    ) {
384
        $resourceLink = $this->addResourceToCourse(
0 ignored issues
show
Bug introduced by
Are you sure the assignment to $resourceLink is correct as $this->addResourceToCour...eNode, $course, $right) targeting Chamilo\CoreBundle\Repos...::addResourceToCourse() seems to always return null.

This check looks for function or method calls that always return null and whose return value is assigned to a variable.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
$object = $a->getObject();

The method getObject() can return nothing but null, so it makes no sense to assign that value to a variable.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
Bug introduced by
The call to Chamilo\CoreBundle\Repos...::addResourceToCourse() has too few arguments starting with course. ( Ignorable by Annotation )

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

384
        /** @scrutinizer ignore-call */ 
385
        $resourceLink = $this->addResourceToCourse(

This check compares calls to functions or methods with their respective definitions. If the call has less arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
385
            $resourceNode,
386
            $course,
387
            $right
388
        );
389
        $resourceLink->setSession($session);
390
        $this->getEntityManager()->persist($resourceLink);
391
392
        return $resourceLink;
393
    }
394
395
    /**
396
     * @param ResourceNode  $resourceNode
397
     * @param Course        $course
398
     * @param CGroupInfo    $group
399
     * @param ResourceRight $right
400
     *
401
     * @return ResourceLink
402
     */
403
    public function addResourceToCourseGroup(
404
        ResourceNode $resourceNode,
405
        Course $course,
406
        CGroupInfo $group,
407
        ResourceRight $right
408
    ) {
409
        $resourceLink = $this->addResourceToCourse(
0 ignored issues
show
Bug introduced by
Are you sure the assignment to $resourceLink is correct as $this->addResourceToCour...eNode, $course, $right) targeting Chamilo\CoreBundle\Repos...::addResourceToCourse() seems to always return null.

This check looks for function or method calls that always return null and whose return value is assigned to a variable.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
$object = $a->getObject();

The method getObject() can return nothing but null, so it makes no sense to assign that value to a variable.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
Bug introduced by
The call to Chamilo\CoreBundle\Repos...::addResourceToCourse() has too few arguments starting with course. ( Ignorable by Annotation )

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

409
        /** @scrutinizer ignore-call */ 
410
        $resourceLink = $this->addResourceToCourse(

This check compares calls to functions or methods with their respective definitions. If the call has less arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
410
            $resourceNode,
411
            $course,
412
            $right
413
        );
414
        $resourceLink->setGroup($group);
415
        $this->getEntityManager()->persist($resourceLink);
416
417
        return $resourceLink;
418
    }
419
420
    /**
421
     * @param ResourceNode  $resourceNode
422
     * @param Usergroup     $group
423
     * @param ResourceRight $right
424
     *
425
     * @return ResourceLink
426
     */
427
    public function addResourceToGroup(
428
        ResourceNode $resourceNode,
429
        Usergroup $group,
430
        ResourceRight $right
431
    ) {
432
        $resourceLink = new ResourceLink();
433
        $resourceLink
434
            ->setResourceNode($resourceNode)
435
            ->setUserGroup($group)
436
            ->addResourceRight($right);
437
438
        return $resourceLink;
439
    }
440
441
    /**
442
     * @param ResourceNode $resourceNode
443
     * @param array        $userList     User id list
444
     */
445
    public function addResourceToUserList(ResourceNode $resourceNode, array $userList)
446
    {
447
        $em = $this->getEntityManager();
448
449
        if (!empty($userList)) {
450
            foreach ($userList as $userId) {
451
                $toUser = $em->getRepository('ChamiloUserBundle:User')->find($userId);
452
453
                $resourceLink = $this->addResourceNodeToUser($resourceNode, $toUser);
454
                $em->persist($resourceLink);
455
            }
456
        }
457
    }
458
459
    /**
460
     * @param Course          $course
461
     * @param Session|null    $session
462
     * @param CGroupInfo|null $group
463
     *
464
     * @return array
465
     */
466
    public function getResourcesByCourse(Course $course, Session $session = null, CGroupInfo $group = null)
467
    {
468
        $repo = $this->getRepository();
469
        $className = $repo->getClassName();
470
471
        // Check if this resource type requires to load the base course resources when using a session
472
        $loadBaseSessionContent = $repo->getClassMetadata()->getReflectionClass()->hasProperty(
473
            'loadBaseCourseResourcesFromSession'
474
        );
475
        $type = $this->getResourceType();
476
477
        $qb = $this->getEntityManager()->createQueryBuilder()
478
            ->select('resource')
479
            ->from(ResourceNode::class, 'node')
480
            ->innerJoin('node.resourceLinks', 'links')
481
            ->innerJoin(
482
                $className,
483
                'resource',
484
                Join::WITH,
485
                'resource.course = links.course AND resource.resourceNode = node.id'
486
            )
487
            ->where('node.resourceType = :type')
488
            ->andWhere('links.course = :course')
489
            //->where('link.cId = ?', $course->getId())
490
            //->where('node.cId = 0')
491
            //->orderBy('node');
492
            ->setParameters(
493
                [
494
                    'type' => $type,
495
                    'course' => $course,
496
                ]
497
            );
498
499
        if ($session === null) {
500
            $qb->andWhere('links.session IS NULL');
501
        } else {
502
            if ($loadBaseSessionContent) {
503
                $qb->andWhere('links.session = :session OR links.session IS NULL');
504
                $qb->setParameter('session', $session);
505
            } else {
506
                $qb->andWhere('links.session = :session');
507
                $qb->setParameter('session', $session);
508
            }
509
        }
510
511
        if ($group === null) {
512
            $qb->andWhere('links.group IS NULL');
513
        }
514
515
        /*if ($parent !== null) {
516
            $qb->andWhere('node.parent = :parentId');
517
            $qb->setParameter('parentId', $parent->getResourceNode()->getId());
518
        } else {
519
            $qb->andWhere('node.parent = :parentId');
520
            $qb->setParameter('parentId', $course->getResourceNode());
521
        }*/
522
523
        /*$qb->setFirstResult();
524
        $qb->setMaxResults();
525
        $qb->orderBy();*/
526
527
        return $qb;
528
529
        $qb = $qb->getQuery();
0 ignored issues
show
Unused Code introduced by
$qb = $qb->getQuery() is not reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
530
        //var_dump($qb->getSQL());
531
532
        /*$qb = $this->getEntityManager()->createQueryBuilder()
533
            ->select('notebook')
534
            ->from('ChamiloNotebookBundle:CNotebook', 'notebook')
535
            ->innerJoin('notebook.resourceNodes', 'node')
536
            //->innerJoin('node.links', 'link')
537
            ->where('node.tool = :tool')
538
            //->where('link.cId = ?', $course->getId())
539
            //->where('node.cId = 0')
540
            //->orderBy('node');
541
            ->setParameters(array(
542
                    'tool'=> 'notebook'
543
                )
544
            )
545
            ->getQuery()
546
        ;*/
547
        return $qb->getResult();
548
    }
549
550
    /**
551
     * @param string $tool
552
     *
553
     * @return Tool|null
554
     */
555
    private function getTool($tool)
0 ignored issues
show
Unused Code introduced by
The method getTool() is not used, and could be removed.

This check looks for private methods that have been defined, but are not used inside the class.

Loading history...
556
    {
557
        return $this
558
            ->getEntityManager()
559
            ->getRepository('ChamiloCoreBundle:Tool')
560
            ->findOneBy(['name' => $tool]);
561
    }
562
563
    /**
564
     * @param AbstractResource $resource
565
     * @param int              $visibility
566
     * @param bool             $recursive
567
     */
568
    private function setLinkVisibility(AbstractResource $resource, $visibility, $recursive = true)
569
    {
570
        $resourceNode = $resource->getResourceNode();
571
572
        $em = $this->getEntityManager();
573
        if ($recursive) {
574
            $children = $resourceNode->getChildren();
575
            if (!empty($children)) {
576
                /** @var ResourceNode $child */
577
                foreach ($children as $child) {
578
                    $criteria = ['resourceNode' => $child];
579
                    $childDocument = $this->getRepository()->findOneBy($criteria);
580
                    if ($childDocument) {
581
                        $this->setLinkVisibility($childDocument, $visibility);
582
                    }
583
                }
584
            }
585
        }
586
587
        $links = $resourceNode->getResourceLinks();
588
589
        if (!empty($links)) {
590
            /** @var ResourceLink $link */
591
            foreach ($links as $link) {
592
                $link->setVisibility($visibility);
593
                if ($visibility === ResourceLink::VISIBILITY_DRAFT) {
594
                    $editorMask = ResourceNodeVoter::getEditorMask();
595
                    $rights = [];
596
                    $resourceRight = new ResourceRight();
597
                    $resourceRight
598
                        ->setMask($editorMask)
599
                        ->setRole(ResourceNodeVoter::ROLE_CURRENT_COURSE_TEACHER)
600
                        ->setResourceLink($link)
601
                    ;
602
                    $rights[] = $resourceRight;
603
604
                    if (!empty($rights)) {
605
                        $link->setResourceRight($rights);
606
                    }
607
                } else {
608
                    $link->setResourceRight([]);
609
                }
610
                $em->merge($link);
611
            }
612
        }
613
        $em->flush();
614
    }
615
616
    /**
617
     * Deletes several entities: AbstractResource (Ex: CDocument, CQuiz), ResourceNode,
618
     * ResourceLinks and ResourceFile (including files via Flysystem)
619
     *
620
     * @param AbstractResource $resource
621
     */
622
    public function hardDelete(AbstractResource $resource)
623
    {
624
        $em = $this->getEntityManager();
625
        $em->remove($resource);
626
        $em->flush();
627
    }
628
629
    /**
630
     * Change all links visibility to DELETED.
631
     *
632
     * @param AbstractResource $resource
633
     */
634
    public function softDelete(AbstractResource $resource)
635
    {
636
        $this->setLinkVisibility($resource, ResourceLink::VISIBILITY_DELETED);
637
    }
638
}
639