Completed
Push — master ( 0a6a4f...5b557d )
by Julito
12:14
created

ResourceRepository::setVisibilityDraft()   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
c 0
b 0
f 0
nc 1
nop 1
dl 0
loc 3
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
    public function __construct(EntityManager $entityManager, MountManager $mountManager, RouterInterface $router, string $className)
66
    {
67
        $this->repository = $entityManager->getRepository($className);
68
        // Flysystem mount name is saved in config/packages/oneup_flysystem.yaml @todo add it as a service.
69
        $this->fs = $mountManager->getFilesystem('resources_fs');
70
        $this->router = $router;
71
        $this->resourceNodeRepository = $entityManager->getRepository('ChamiloCoreBundle:Resource\ResourceNode');
72
    }
73
74
    /**
75
     * @return mixed
76
     */
77
    public function create()
78
    {
79
        return new $this->className();
80
    }
81
82
    /**
83
     * @return RouterInterface
84
     */
85
    public function getRouter(): RouterInterface
86
    {
87
        return $this->router;
88
    }
89
90
    /**
91
     * @return EntityRepository
92
     */
93
    public function getResourceNodeRepository()
94
    {
95
        return $this->resourceNodeRepository;
96
    }
97
98
    /**
99
     * @return FilesystemInterface
100
     */
101
    public function getFileSystem()
102
    {
103
        return $this->fs;
104
    }
105
106
    /**
107
     * @return EntityManager
108
     */
109
    public function getEntityManager(): EntityManager
110
    {
111
        return $this->getRepository()->getEntityManager();
112
    }
113
114
    /**
115
     * @return EntityRepository
116
     */
117
    public function getRepository()
118
    {
119
        return $this->repository;
120
    }
121
122
    /**
123
     * @param mixed $id
124
     * @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...
125
     * @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...
126
     */
127
    public function find($id, $lockMode = null, $lockVersion = null): ?AbstractResource
128
    {
129
        return $this->getRepository()->find($id);
130
    }
131
132
    /**
133
     * @return AbstractResource
134
     */
135
    public function findOneBy(array $criteria, array $orderBy = null): ?AbstractResource
136
    {
137
        return $this->getRepository()->findOneBy($criteria, $orderBy);
138
    }
139
140
    /**
141
     * @return ResourceFile
142
     */
143
    public function addFile(ResourceNode $resourceNode, UploadedFile $file): ?ResourceFile
144
    {
145
        $resourceFile = $resourceNode->getResourceFile();
146
        if ($resourceFile === null) {
147
            $resourceFile = new ResourceFile();
148
        }
149
150
        $em = $this->getEntityManager();
151
152
        $resourceFile->setFile($file);
153
        $resourceFile->setName($resourceNode->getName());
154
        $em->persist($resourceFile);
155
        $resourceNode->setResourceFile($resourceFile);
156
        $em->persist($resourceNode);
157
        $em->flush();
158
159
        return $resourceFile;
160
    }
161
162
    /**
163
     * Creates a ResourceNode.
164
     *
165
     * @param AbstractResource $parent
166
     */
167
    public function addResourceNode(AbstractResource $resource, User $creator, AbstractResource $parent = null): ResourceNode
168
    {
169
        $em = $this->getEntityManager();
170
171
        $resourceType = $this->getResourceType();
172
173
        $resourceNode = new ResourceNode();
174
        $resourceNode
175
            ->setName($resource->getResourceName())
176
            ->setCreator($creator)
177
            ->setResourceType($resourceType)
178
        ;
179
180
        if ($parent !== null) {
181
            $resourceNode->setParent($parent->getResourceNode());
182
        }
183
184
        $resource->setResourceNode($resourceNode);
185
186
        $em->persist($resourceNode);
187
        $em->persist($resource);
188
        $em->flush();
189
190
        return $resourceNode;
191
    }
192
193
    /**
194
     * @param Session    $session
195
     * @param CGroupInfo $group
196
     */
197
    public function addResourceToCourse(AbstractResource $resource, int $visibility, User $creator, Course $course, Session $session = null, CGroupInfo $group = null)
198
    {
199
        $node = $this->addResourceNode($resource, $creator, $course);
200
        $this->addResourceNodeToCourse($node, $visibility, $course, $session, $group);
201
    }
202
203
    /**
204
     * @param int        $visibility
205
     * @param Course     $course
206
     * @param Session    $session
207
     * @param CGroupInfo $group
208
     */
209
    public function addResourceNodeToCourse(ResourceNode $resourceNode, $visibility, $course, $session, $group): void
210
    {
211
        $visibility = (int) $visibility;
212
        if (empty($visibility)) {
213
            $visibility = ResourceLink::VISIBILITY_PUBLISHED;
214
        }
215
216
        $link = new ResourceLink();
217
        $link
218
            ->setCourse($course)
219
            ->setSession($session)
220
            ->setGroup($group)
221
            //->setUser($toUser)
222
            ->setResourceNode($resourceNode)
223
            ->setVisibility($visibility)
224
        ;
225
226
        $rights = [];
227
        switch ($visibility) {
228
            case ResourceLink::VISIBILITY_PENDING:
229
            case ResourceLink::VISIBILITY_DRAFT:
230
                $editorMask = ResourceNodeVoter::getEditorMask();
231
                $resourceRight = new ResourceRight();
232
                $resourceRight
233
                    ->setMask($editorMask)
234
                    ->setRole(ResourceNodeVoter::ROLE_CURRENT_COURSE_TEACHER)
235
                ;
236
                $rights[] = $resourceRight;
237
                break;
238
        }
239
240
        if (!empty($rights)) {
241
            foreach ($rights as $right) {
242
                $link->addResourceRight($right);
243
            }
244
        }
245
246
        $em = $this->getEntityManager();
247
        $em->persist($link);
248
        $em->flush();
249
    }
250
251
    /**
252
     * @return ResourceType
253
     */
254
    public function getResourceType()
255
    {
256
        $em = $this->getEntityManager();
257
        $entityName = $this->getRepository()->getClassMetadata()->getReflectionClass()->getShortName();
258
259
        return $em->getRepository('ChamiloCoreBundle:Resource\ResourceType')->findOneBy(
260
            ['name' => $entityName]
261
        );
262
    }
263
264
    public function addResourceToMe(ResourceNode $resourceNode): ResourceLink
265
    {
266
        $resourceLink = new ResourceLink();
267
        $resourceLink
268
            ->setResourceNode($resourceNode)
269
            ->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

269
            ->/** @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...
270
271
        $this->getEntityManager()->persist($resourceLink);
272
        $this->getEntityManager()->flush();
273
274
        return $resourceLink;
275
    }
276
277
    public function addResourceToEveryone(ResourceNode $resourceNode, ResourceRight $right): ResourceLink
278
    {
279
        $resourceLink = new ResourceLink();
280
        $resourceLink
281
            ->setResourceNode($resourceNode)
282
            ->addResourceRight($right)
283
        ;
284
285
        $this->getEntityManager()->persist($resourceLink);
286
        $this->getEntityManager()->flush();
287
288
        return $resourceLink;
289
    }
290
291
    public function addResourceToCourse2(ResourceNode $resourceNode, Course $course, ResourceRight $right): ResourceLink
292
    {
293
        $resourceLink = new ResourceLink();
294
        $resourceLink
295
            ->setResourceNode($resourceNode)
296
            ->setCourse($course)
297
            ->addResourceRight($right);
298
        $this->getEntityManager()->persist($resourceLink);
299
        $this->getEntityManager()->flush();
300
301
        return $resourceLink;
302
    }
303
304
    public function addResourceToUser(ResourceNode $resourceNode, User $toUser): ResourceLink
305
    {
306
        $resourceLink = $this->addResourceNodeToUser($resourceNode, $toUser);
307
        $this->getEntityManager()->persist($resourceLink);
308
309
        return $resourceLink;
310
    }
311
312
    public function addResourceNodeToUser(ResourceNode $resourceNode, User $toUser): ResourceLink
313
    {
314
        $resourceLink = new ResourceLink();
315
        $resourceLink
316
            ->setResourceNode($resourceNode)
317
            ->setUser($toUser);
318
319
        return $resourceLink;
320
    }
321
322
    public function addResourceToSession(
323
        ResourceNode $resourceNode,
324
        Course $course,
325
        Session $session,
326
        ResourceRight $right
327
    ) {
328
        $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

328
        /** @scrutinizer ignore-call */ 
329
        $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...
329
            $resourceNode,
330
            $course,
331
            $right
332
        );
333
        $resourceLink->setSession($session);
334
        $this->getEntityManager()->persist($resourceLink);
335
336
        return $resourceLink;
337
    }
338
339
    /**
340
     * @return ResourceLink
341
     */
342
    public function addResourceToCourseGroup(
343
        ResourceNode $resourceNode,
344
        Course $course,
345
        CGroupInfo $group,
346
        ResourceRight $right
347
    ) {
348
        $resourceLink = $this->addResourceToCourse(
0 ignored issues
show
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

348
        /** @scrutinizer ignore-call */ 
349
        $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...
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...
349
            $resourceNode,
350
            $course,
351
            $right
352
        );
353
        $resourceLink->setGroup($group);
354
        $this->getEntityManager()->persist($resourceLink);
355
356
        return $resourceLink;
357
    }
358
359
    /**
360
     * @return ResourceLink
361
     */
362
    public function addResourceToGroup(
363
        ResourceNode $resourceNode,
364
        Usergroup $group,
365
        ResourceRight $right
366
    ) {
367
        $resourceLink = new ResourceLink();
368
        $resourceLink
369
            ->setResourceNode($resourceNode)
370
            ->setUserGroup($group)
371
            ->addResourceRight($right);
372
373
        return $resourceLink;
374
    }
375
376
    /**
377
     * @param array $userList User id list
378
     */
379
    public function addResourceToUserList(ResourceNode $resourceNode, array $userList)
380
    {
381
        $em = $this->getEntityManager();
382
383
        if (!empty($userList)) {
384
            foreach ($userList as $userId) {
385
                $toUser = $em->getRepository('ChamiloUserBundle:User')->find($userId);
386
387
                $resourceLink = $this->addResourceNodeToUser($resourceNode, $toUser);
388
                $em->persist($resourceLink);
389
            }
390
        }
391
    }
392
393
    /**
394
     * @param Course          $course
395
     * @param Session|null    $session
396
     * @param CGroupInfo|null $group
397
     *
398
     * @return QueryBuilder
399
     */
400
    public function getResourcesByCourse(Course $course, Session $session = null, CGroupInfo $group = null)
401
    {
402
        $repo = $this->getRepository();
403
        $className = $repo->getClassName();
404
405
        // Check if this resource type requires to load the base course resources when using a session
406
        $loadBaseSessionContent = $repo->getClassMetadata()->getReflectionClass()->hasProperty(
407
            'loadCourseResourcesInSession'
408
        );
409
        $type = $this->getResourceType();
410
411
        $qb = $repo->getEntityManager()->createQueryBuilder()
412
            ->select('resource')
413
            ->from($className, 'resource')
414
            ->innerJoin(
415
                ResourceNode::class,
416
                'node',
417
                Join::WITH,
418
                'resource.resourceNode = node.id'
419
            )
420
            ->innerJoin('node.resourceLinks', 'links')
421
            ->where('node.resourceType = :type')
422
            //->andWhere('resource.course = links.course')
423
            ->andWhere('links.course = :course')
424
            //->where('link.cId = ?', $course->getId())
425
            //->where('node.cId = 0')
426
            //->orderBy('node');
427
            ->setParameters(
428
                [
429
                    'type' => $type,
430
                    'course' => $course,
431
                ]
432
            );
433
434
        if ($session === null) {
435
            $qb->andWhere('links.session IS NULL');
436
        } else {
437
            if ($loadBaseSessionContent) {
438
                // Load course base content.
439
                $qb->andWhere('links.session = :session OR links.session IS NULL');
440
                $qb->setParameter('session', $session);
441
            } else {
442
                // Load only session resources.
443
                $qb->andWhere('links.session = :session');
444
                $qb->setParameter('session', $session);
445
            }
446
        }
447
448
        if ($group === null) {
449
            $qb->andWhere('links.group IS NULL');
450
        }
451
452
        /*if ($parent !== null) {
453
            $qb->andWhere('node.parent = :parentId');
454
            $qb->setParameter('parentId', $parent->getResourceNode()->getId());
455
        } else {
456
            $qb->andWhere('node.parent = :parentId');
457
            $qb->setParameter('parentId', $course->getResourceNode());
458
        }*/
459
460
        /*$qb->setFirstResult();
461
        $qb->setMaxResults();
462
        $qb->orderBy();*/
463
464
        return $qb;
465
466
        $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...
467
        //var_dump($qb->getSQL());
468
469
        /*$qb = $this->getEntityManager()->createQueryBuilder()
470
            ->select('notebook')
471
            ->from('ChamiloNotebookBundle:CNotebook', 'notebook')
472
            ->innerJoin('notebook.resourceNodes', 'node')
473
            //->innerJoin('node.links', 'link')
474
            ->where('node.tool = :tool')
475
            //->where('link.cId = ?', $course->getId())
476
            //->where('node.cId = 0')
477
            //->orderBy('node');
478
            ->setParameters(array(
479
                    'tool'=> 'notebook'
480
                )
481
            )
482
            ->getQuery()
483
        ;*/
484
        return $qb->getResult();
485
    }
486
487
    /**
488
     * @param RowAction $action
489
     * @param Row       $row
490
     * @param Session   $session
491
     *
492
     * @return RowAction|null
493
     */
494
    public function rowCanBeEdited(RowAction $action, Row $row, Session $session = null)
495
    {
496
        if (!empty($session)) {
497
            /** @var AbstractResource $entity */
498
            $entity = $row->getEntity();
499
            $hasSession = $entity->getResourceNode()->hasSession($session);
500
            if ($hasSession->count() > 0) {
501
                return $action;
502
            }
503
504
            return null;
505
        }
506
507
        return $action;
508
    }
509
510
    /**
511
     * @param string $tool
512
     *
513
     * @return Tool|null
514
     */
515
    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...
516
    {
517
        return $this
518
            ->getEntityManager()
519
            ->getRepository('ChamiloCoreBundle:Tool')
520
            ->findOneBy(['name' => $tool]);
521
    }
522
523
    /**
524
     * Deletes several entities: AbstractResource (Ex: CDocument, CQuiz), ResourceNode,
525
     * ResourceLinks and ResourceFile (including files via Flysystem).
526
     */
527
    public function hardDelete(AbstractResource $resource)
528
    {
529
        $em = $this->getEntityManager();
530
        $em->remove($resource);
531
        $em->flush();
532
    }
533
534
    /**
535
     * Change all links visibility to DELETED.
536
     */
537
    public function softDelete(AbstractResource $resource)
538
    {
539
        $this->setLinkVisibility($resource, ResourceLink::VISIBILITY_DELETED);
540
    }
541
542
    /**
543
     * @param AbstractResource $resource
544
     */
545
    public function setVisibilityPublished(AbstractResource $resource)
546
    {
547
        $this->setLinkVisibility($resource, ResourceLink::VISIBILITY_PUBLISHED);
548
    }
549
550
    /**
551
     * @param AbstractResource $resource
552
     */
553
    public function setVisibilityDraft(AbstractResource $resource)
554
    {
555
        $this->setLinkVisibility($resource, ResourceLink::VISIBILITY_DRAFT);
556
    }
557
558
    /**
559
     * @param AbstractResource $resource
560
     */
561
    public function setVisibilityPending(AbstractResource $resource)
562
    {
563
        $this->setLinkVisibility($resource, ResourceLink::VISIBILITY_PENDING);
564
    }
565
566
    /**
567
     * @param AbstractResource $resource
568
     * @param                  $visibility
569
     * @param bool             $recursive
570
     *
571
     * @return bool
572
     */
573
    private function setLinkVisibility(AbstractResource $resource, $visibility, $recursive = true)
574
    {
575
        $resourceNode = $resource->getResourceNode();
576
577
        if ($resourceNode === null){
578
            return false;
579
        }
580
581
        $em = $this->getEntityManager();
582
        if ($recursive) {
583
            $children = $resourceNode->getChildren();
584
            if (!empty($children)) {
585
                /** @var ResourceNode $child */
586
                foreach ($children as $child) {
587
                    $criteria = ['resourceNode' => $child];
588
                    $childDocument = $this->getRepository()->findOneBy($criteria);
589
                    if ($childDocument) {
590
                        $this->setLinkVisibility($childDocument, $visibility);
591
                    }
592
                }
593
            }
594
        }
595
596
        $links = $resourceNode->getResourceLinks();
597
598
        if (!empty($links)) {
599
            /** @var ResourceLink $link */
600
            foreach ($links as $link) {
601
                $link->setVisibility($visibility);
602
                if ($visibility === ResourceLink::VISIBILITY_DRAFT) {
603
                    $editorMask = ResourceNodeVoter::getEditorMask();
604
                    $rights = [];
605
                    $resourceRight = new ResourceRight();
606
                    $resourceRight
607
                        ->setMask($editorMask)
608
                        ->setRole(ResourceNodeVoter::ROLE_CURRENT_COURSE_TEACHER)
609
                        ->setResourceLink($link)
610
                    ;
611
                    $rights[] = $resourceRight;
612
613
                    if (!empty($rights)) {
614
                        $link->setResourceRight($rights);
615
                    }
616
                } else {
617
                    $link->setResourceRight([]);
618
                }
619
                $em->merge($link);
620
            }
621
        }
622
        $em->flush();
623
624
        return true;
625
    }
626
}
627