Completed
Push — master ( 2d4e5c...386374 )
by Julito
15:19
created

ResourceRepository::rowCanBeEdited()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 14
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

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

296
            ->/** @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...
297
298
        $this->getEntityManager()->persist($resourceLink);
299
        $this->getEntityManager()->flush();
300
301
        return $resourceLink;
302
    }
303
304
    /**
305
     * @param ResourceNode  $resourceNode
306
     * @param ResourceRight $right
307
     *
308
     * @return ResourceLink
309
     */
310
    public function addResourceToEveryone(ResourceNode $resourceNode, ResourceRight $right): ResourceLink
311
    {
312
        $resourceLink = new ResourceLink();
313
        $resourceLink
314
            ->setResourceNode($resourceNode)
315
            ->addResourceRight($right)
316
        ;
317
318
        $this->getEntityManager()->persist($resourceLink);
319
        $this->getEntityManager()->flush();
320
321
        return $resourceLink;
322
    }
323
324
    /**
325
     * @param ResourceNode  $resourceNode
326
     * @param Course        $course
327
     * @param ResourceRight $right
328
     *
329
     * @return ResourceLink
330
     */
331
    public function addResourceToCourse2(ResourceNode $resourceNode, Course $course, ResourceRight $right): ResourceLink
332
    {
333
        $resourceLink = new ResourceLink();
334
        $resourceLink
335
            ->setResourceNode($resourceNode)
336
            ->setCourse($course)
337
            ->addResourceRight($right);
338
        $this->getEntityManager()->persist($resourceLink);
339
        $this->getEntityManager()->flush();
340
341
        return $resourceLink;
342
    }
343
344
    /**
345
     * @param ResourceNode $resourceNode
346
     * @param User         $toUser
347
     *
348
     * @return ResourceLink
349
     */
350
    public function addResourceToUser(ResourceNode $resourceNode, User $toUser): ResourceLink
351
    {
352
        $resourceLink = $this->addResourceNodeToUser($resourceNode, $toUser);
353
        $this->getEntityManager()->persist($resourceLink);
354
355
        return $resourceLink;
356
    }
357
358
    /**
359
     * @param ResourceNode $resourceNode
360
     * @param User         $toUser
361
     *
362
     * @return ResourceLink
363
     */
364
    public function addResourceNodeToUser(ResourceNode $resourceNode, User $toUser): ResourceLink
365
    {
366
        $resourceLink = new ResourceLink();
367
        $resourceLink
368
            ->setResourceNode($resourceNode)
369
            ->setUser($toUser);
370
371
        return $resourceLink;
372
    }
373
374
    /**
375
     * @param ResourceNode  $resourceNode
376
     * @param Course        $course
377
     * @param Session       $session
378
     * @param ResourceRight $right
379
     *
380
     */
381
    public function addResourceToSession(
382
        ResourceNode $resourceNode,
383
        Course $course,
384
        Session $session,
385
        ResourceRight $right
386
    ) {
387
        $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

387
        /** @scrutinizer ignore-call */ 
388
        $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...
388
            $resourceNode,
389
            $course,
390
            $right
391
        );
392
        $resourceLink->setSession($session);
393
        $this->getEntityManager()->persist($resourceLink);
394
395
        return $resourceLink;
396
    }
397
398
    /**
399
     * @param ResourceNode  $resourceNode
400
     * @param Course        $course
401
     * @param CGroupInfo    $group
402
     * @param ResourceRight $right
403
     *
404
     * @return ResourceLink
405
     */
406
    public function addResourceToCourseGroup(
407
        ResourceNode $resourceNode,
408
        Course $course,
409
        CGroupInfo $group,
410
        ResourceRight $right
411
    ) {
412
        $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

412
        /** @scrutinizer ignore-call */ 
413
        $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...
413
            $resourceNode,
414
            $course,
415
            $right
416
        );
417
        $resourceLink->setGroup($group);
418
        $this->getEntityManager()->persist($resourceLink);
419
420
        return $resourceLink;
421
    }
422
423
    /**
424
     * @param ResourceNode  $resourceNode
425
     * @param Usergroup     $group
426
     * @param ResourceRight $right
427
     *
428
     * @return ResourceLink
429
     */
430
    public function addResourceToGroup(
431
        ResourceNode $resourceNode,
432
        Usergroup $group,
433
        ResourceRight $right
434
    ) {
435
        $resourceLink = new ResourceLink();
436
        $resourceLink
437
            ->setResourceNode($resourceNode)
438
            ->setUserGroup($group)
439
            ->addResourceRight($right);
440
441
        return $resourceLink;
442
    }
443
444
    /**
445
     * @param ResourceNode $resourceNode
446
     * @param array        $userList     User id list
447
     */
448
    public function addResourceToUserList(ResourceNode $resourceNode, array $userList)
449
    {
450
        $em = $this->getEntityManager();
451
452
        if (!empty($userList)) {
453
            foreach ($userList as $userId) {
454
                $toUser = $em->getRepository('ChamiloUserBundle:User')->find($userId);
455
456
                $resourceLink = $this->addResourceNodeToUser($resourceNode, $toUser);
457
                $em->persist($resourceLink);
458
            }
459
        }
460
    }
461
462
    /**
463
     * @param Course          $course
464
     * @param Session|null    $session
465
     * @param CGroupInfo|null $group
466
     *
467
     * @return QueryBuilder
468
     */
469
    public function getResourcesByCourse(Course $course, Session $session = null, CGroupInfo $group = null)
470
    {
471
        $repo = $this->getRepository();
472
        $className = $repo->getClassName();
473
474
        // Check if this resource type requires to load the base course resources when using a session
475
        $loadBaseSessionContent = $repo->getClassMetadata()->getReflectionClass()->hasProperty(
476
            'loadCourseResourcesInSession'
477
        );
478
        $type = $this->getResourceType();
479
480
        $qb = $repo->getEntityManager()->createQueryBuilder()
481
            ->select('resource')
482
            ->from($className, 'resource')
483
            ->innerJoin(
484
                ResourceNode::class,
485
                'node',
486
                Join::WITH,
487
                'resource.resourceNode = node.id'
488
            )
489
            ->innerJoin('node.resourceLinks', 'links')
490
            ->where('node.resourceType = :type')
491
            ->andWhere('resource.course = links.course')
492
            ->andWhere('links.course = :course')
493
            //->where('link.cId = ?', $course->getId())
494
            //->where('node.cId = 0')
495
            //->orderBy('node');
496
            ->setParameters(
497
                [
498
                    'type' => $type,
499
                    'course' => $course,
500
                ]
501
            );
502
503
        if ($session === null) {
504
            $qb->andWhere('links.session IS NULL');
505
        } else {
506
            if ($loadBaseSessionContent) {
507
                // Load course base content.
508
                $qb->andWhere('links.session = :session OR links.session IS NULL');
509
                $qb->setParameter('session', $session);
510
            } else {
511
                // Load only session resources.
512
                $qb->andWhere('links.session = :session');
513
                $qb->setParameter('session', $session);
514
            }
515
        }
516
517
        if ($group === null) {
518
            $qb->andWhere('links.group IS NULL');
519
        }
520
521
        /*if ($parent !== null) {
522
            $qb->andWhere('node.parent = :parentId');
523
            $qb->setParameter('parentId', $parent->getResourceNode()->getId());
524
        } else {
525
            $qb->andWhere('node.parent = :parentId');
526
            $qb->setParameter('parentId', $course->getResourceNode());
527
        }*/
528
529
        /*$qb->setFirstResult();
530
        $qb->setMaxResults();
531
        $qb->orderBy();*/
532
533
        return $qb;
534
535
        $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...
536
        //var_dump($qb->getSQL());
537
538
        /*$qb = $this->getEntityManager()->createQueryBuilder()
539
            ->select('notebook')
540
            ->from('ChamiloNotebookBundle:CNotebook', 'notebook')
541
            ->innerJoin('notebook.resourceNodes', 'node')
542
            //->innerJoin('node.links', 'link')
543
            ->where('node.tool = :tool')
544
            //->where('link.cId = ?', $course->getId())
545
            //->where('node.cId = 0')
546
            //->orderBy('node');
547
            ->setParameters(array(
548
                    'tool'=> 'notebook'
549
                )
550
            )
551
            ->getQuery()
552
        ;*/
553
        return $qb->getResult();
554
    }
555
556
    public function rowCanBeEdited($session, RowAction $action, Row $row)
557
    {
558
        if (!empty($session)) {
559
            /** @var \Chamilo\CoreBundle\Entity\Resource\AbstractResource $entity */
560
            $entity = $row->getEntity();
561
            $hasSession = $entity->getResourceNode()->hasSession($session);
562
            if ($hasSession->count() > 0) {
563
564
                return $action;
565
            }
566
567
            return null;
568
        }
569
        return $action;
570
    }
571
572
    /**
573
     * @param string $tool
574
     *
575
     * @return Tool|null
576
     */
577
    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...
578
    {
579
        return $this
580
            ->getEntityManager()
581
            ->getRepository('ChamiloCoreBundle:Tool')
582
            ->findOneBy(['name' => $tool]);
583
    }
584
585
    /**
586
     * @param AbstractResource $resource
587
     * @param int              $visibility
588
     * @param bool             $recursive
589
     */
590
    private function setLinkVisibility(AbstractResource $resource, $visibility, $recursive = true)
591
    {
592
        $resourceNode = $resource->getResourceNode();
593
594
        $em = $this->getEntityManager();
595
        if ($recursive) {
596
            $children = $resourceNode->getChildren();
597
            if (!empty($children)) {
598
                /** @var ResourceNode $child */
599
                foreach ($children as $child) {
600
                    $criteria = ['resourceNode' => $child];
601
                    $childDocument = $this->getRepository()->findOneBy($criteria);
602
                    if ($childDocument) {
603
                        $this->setLinkVisibility($childDocument, $visibility);
604
                    }
605
                }
606
            }
607
        }
608
609
        $links = $resourceNode->getResourceLinks();
610
611
        if (!empty($links)) {
612
            /** @var ResourceLink $link */
613
            foreach ($links as $link) {
614
                $link->setVisibility($visibility);
615
                if ($visibility === ResourceLink::VISIBILITY_DRAFT) {
616
                    $editorMask = ResourceNodeVoter::getEditorMask();
617
                    $rights = [];
618
                    $resourceRight = new ResourceRight();
619
                    $resourceRight
620
                        ->setMask($editorMask)
621
                        ->setRole(ResourceNodeVoter::ROLE_CURRENT_COURSE_TEACHER)
622
                        ->setResourceLink($link)
623
                    ;
624
                    $rights[] = $resourceRight;
625
626
                    if (!empty($rights)) {
627
                        $link->setResourceRight($rights);
628
                    }
629
                } else {
630
                    $link->setResourceRight([]);
631
                }
632
                $em->merge($link);
633
            }
634
        }
635
        $em->flush();
636
    }
637
638
    /**
639
     * Deletes several entities: AbstractResource (Ex: CDocument, CQuiz), ResourceNode,
640
     * ResourceLinks and ResourceFile (including files via Flysystem)
641
     *
642
     * @param AbstractResource $resource
643
     */
644
    public function hardDelete(AbstractResource $resource)
645
    {
646
        $em = $this->getEntityManager();
647
        $em->remove($resource);
648
        $em->flush();
649
    }
650
651
    /**
652
     * Change all links visibility to DELETED.
653
     *
654
     * @param AbstractResource $resource
655
     */
656
    public function softDelete(AbstractResource $resource)
657
    {
658
        $this->setLinkVisibility($resource, ResourceLink::VISIBILITY_DELETED);
659
    }
660
}
661