Passed
Push — master ( 4f3b5b...268dc8 )
by Julito
10:04
created

ResourceRepository::addFile()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 22
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

Changes 3
Bugs 0 Features 0
Metric Value
cc 3
eloc 13
c 3
b 0
f 0
nc 3
nop 2
dl 0
loc 22
rs 9.8333
1
<?php
2
3
/* For licensing terms, see /license.txt */
4
5
namespace Chamilo\CoreBundle\Repository;
6
7
use APY\DataGridBundle\Grid\Action\RowAction;
8
use APY\DataGridBundle\Grid\Row;
9
use Chamilo\CoreBundle\Component\Utils\ResourceSettings;
10
use Chamilo\CoreBundle\Entity\Course;
11
use Chamilo\CoreBundle\Entity\Resource\AbstractResource;
12
use Chamilo\CoreBundle\Entity\Resource\ResourceFile;
13
use Chamilo\CoreBundle\Entity\Resource\ResourceInterface;
14
use Chamilo\CoreBundle\Entity\Resource\ResourceLink;
15
use Chamilo\CoreBundle\Entity\Resource\ResourceNode;
16
use Chamilo\CoreBundle\Entity\Resource\ResourceRight;
17
use Chamilo\CoreBundle\Entity\Resource\ResourceType;
18
use Chamilo\CoreBundle\Entity\Session;
19
use Chamilo\CoreBundle\Entity\Usergroup;
20
use Chamilo\CoreBundle\Security\Authorization\Voter\ResourceNodeVoter;
21
use Chamilo\CoreBundle\ToolChain;
22
use Chamilo\CourseBundle\Entity\CDocument;
23
use Chamilo\CourseBundle\Entity\CGroupInfo;
24
use Chamilo\UserBundle\Entity\User;
25
use Cocur\Slugify\SlugifyInterface;
26
use Doctrine\ORM\EntityManager;
27
use Doctrine\ORM\EntityRepository;
28
use Doctrine\ORM\EntityRepository as BaseEntityRepository;
29
use Doctrine\ORM\Query\Expr\Join;
30
use Doctrine\ORM\QueryBuilder;
31
use League\Flysystem\FilesystemInterface;
32
use League\Flysystem\MountManager;
33
use Symfony\Component\Filesystem\Exception\FileNotFoundException;
34
use Symfony\Component\Form\FormFactory;
35
use Symfony\Component\Form\FormInterface;
36
use Symfony\Component\HttpFoundation\File\UploadedFile;
37
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
38
use Symfony\Component\Routing\RouterInterface;
39
use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
40
use Vich\UploaderBundle\Storage\FlysystemStorage;
41
42
/**
43
 * Class ResourceRepository.
44
 * Extends EntityRepository is needed to process settings.
45
 */
46
class ResourceRepository extends BaseEntityRepository
47
{
48
    /**
49
     * @var EntityRepository
50
     */
51
    protected $repository;
52
53
    /**
54
     * @var FilesystemInterface
55
     */
56
    protected $fs;
57
58
    /**
59
     * @var EntityManager
60
     */
61
    protected $entityManager;
62
63
    /**
64
     * The entity class FQN.
65
     *
66
     * @var string
67
     */
68
    protected $className;
69
70
    /** @var RouterInterface */
71
    protected $router;
72
73
    /** @var ResourceNodeRepository */
74
    protected $resourceNodeRepository;
75
76
    /**
77
     * @var AuthorizationCheckerInterface
78
     */
79
    protected $authorizationChecker;
80
81
    /** @var MountManager */
82
    protected $mountManager;
83
84
    /** @var SlugifyInterface */
85
    protected $slugify;
86
87
    /** @var ToolChain */
88
    protected $toolChain;
89
90
    /** @var FlysystemStorage */
91
    protected $storage;
92
93
    /**
94
     * ResourceRepository constructor.
95
     */
96
    public function __construct(
97
        AuthorizationCheckerInterface $authorizationChecker,
98
        EntityManager $entityManager,
99
        MountManager $mountManager,
100
        RouterInterface $router,
101
        SlugifyInterface $slugify,
102
        ToolChain $toolChain,
103
        FlysystemStorage $storage,
104
        string $className
105
    ) {
106
        $this->authorizationChecker = $authorizationChecker;
107
        $this->repository = $entityManager->getRepository($className);
108
109
        // Flysystem mount name is saved in config/packages/oneup_flysystem.yaml @todo add it as a service.
110
        $this->fs = $mountManager->getFilesystem('resources_fs');
111
        $this->storage = $storage;
112
        $this->mountManager = $mountManager;
113
        $this->router = $router;
114
        $this->resourceNodeRepository = $entityManager->getRepository('ChamiloCoreBundle:Resource\ResourceNode');
115
        $this->slugify = $slugify;
116
        $this->toolChain = $toolChain;
117
    }
118
119
    public function getAuthorizationChecker(): AuthorizationCheckerInterface
120
    {
121
        return $this->authorizationChecker;
122
    }
123
124
    public function create()
125
    {
126
        return new $this->className();
127
    }
128
129
    public function getRouter(): RouterInterface
130
    {
131
        return $this->router;
132
    }
133
134
    /**
135
     * @return ResourceNodeRepository
136
     */
137
    public function getResourceNodeRepository()
138
    {
139
        return $this->resourceNodeRepository;
140
    }
141
142
    /**
143
     * @return FilesystemInterface
144
     */
145
    public function getFileSystem()
146
    {
147
        return $this->fs;
148
    }
149
150
    public function getEntityManager(): EntityManager
151
    {
152
        return $this->getRepository()->getEntityManager();
153
    }
154
155
    /**
156
     * @return EntityRepository
157
     */
158
    public function getRepository()
159
    {
160
        return $this->repository;
161
    }
162
163
    /**
164
     * @return FormInterface
165
     */
166
    public function getForm(FormFactory $formFactory, AbstractResource $resource = null, $options = [])
167
    {
168
        $className = $this->repository->getClassName();
169
        $shortName = (new \ReflectionClass($className))->getShortName();
170
171
        // @todo remove hardcode class loading
172
        $formType = 'Chamilo\CoreBundle\Form\Resource\\'.$shortName.'Type';
173
        if (null === $resource) {
174
            $resource = new $className();
175
        }
176
177
        return $formFactory->create($formType, $resource, $options);
178
    }
179
180
    /**
181
     * @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...
182
     * @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...
183
     *
184
     * @return ResourceInterface
185
     */
186
    public function find($id, $lockMode = null, $lockVersion = null)
187
    {
188
        return $this->getRepository()->find($id);
189
    }
190
191
    public function findOneBy(array $criteria, array $orderBy = null)
192
    {
193
        return $this->getRepository()->findOneBy($criteria, $orderBy);
194
    }
195
196
    public function updateNodeForResource(ResourceInterface $resource): ResourceNode
197
    {
198
        $em = $this->getEntityManager();
199
200
        $resourceNode = $resource->getResourceNode();
201
        $resourceName = $resource->getResourceName();
202
203
        if ($resourceNode->hasResourceFile()) {
204
            $resourceFile = $resourceNode->getResourceFile();
205
            if ($resourceFile) {
0 ignored issues
show
introduced by
$resourceFile is of type Chamilo\CoreBundle\Entity\Resource\ResourceFile, thus it always evaluated to true.
Loading history...
206
                $originalName = $resourceFile->getOriginalName();
207
                $originalExtension = pathinfo($originalName, PATHINFO_EXTENSION);
208
209
                $originalBasename = \basename($resourceName, $originalExtension);
210
                $slug = sprintf(
211
                    '%s.%s',
212
                    $this->slugify->slugify($originalBasename),
213
                    $this->slugify->slugify($originalExtension)
214
                );
215
216
                $newOriginalName = sprintf('%s.%s', $resourceName, $originalExtension);
217
                $resourceFile->setOriginalName($newOriginalName);
218
219
                $em->persist($resourceFile);
220
            }
221
        } else {
222
            $slug = $this->slugify->slugify($resourceName);
223
        }
224
225
        $resourceNode->setSlug($slug);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $slug does not seem to be defined for all execution paths leading up to this point.
Loading history...
226
227
        $em->persist($resourceNode);
228
        $em->persist($resource);
229
230
        $em->flush();
231
232
        return $resourceNode;
233
    }
234
235
    public function addFile(ResourceInterface $resource, UploadedFile $file): ?ResourceFile
236
    {
237
        $resourceNode = $resource->getResourceNode();
238
239
        if (null === $resourceNode) {
240
            throw new \LogicException('Resource node is null');
241
        }
242
243
        $resourceFile = $resourceNode->getResourceFile();
244
        if (null === $resourceFile) {
245
            $resourceFile = new ResourceFile();
246
        }
247
248
        $em = $this->getEntityManager();
249
        $resourceFile->setFile($file);
250
        $resourceFile->setName($resource->getResourceName());
251
        $em->persist($resourceFile);
252
253
        $resourceNode->setResourceFile($resourceFile);
254
        $em->persist($resourceNode);
255
256
        return $resourceFile;
257
    }
258
259
    public function addResourceNode(AbstractResource $resource, User $creator, AbstractResource $parent = null): ResourceNode
260
    {
261
        if (null !== $parent) {
262
            $parent = $parent->getResourceNode();
263
        }
264
265
        return $this->createNodeForResource($resource, $creator, $parent);
266
    }
267
268
    public function addResourceToCourse(AbstractResource $resource, int $visibility, User $creator, Course $course, Session $session = null, CGroupInfo $group = null, UploadedFile $file = null)
269
    {
270
        $node = $this->createNodeForResource($resource, $creator, $course->getResourceNode(), $file);
271
272
        $this->addResourceNodeToCourse($node, $visibility, $course, $session, $group);
273
    }
274
275
    public function addResourceToCourseWithParent(AbstractResource $resource, ResourceNode $parentNode, int $visibility, User $creator, Course $course, Session $session = null, CGroupInfo $group = null, UploadedFile $file = null)
276
    {
277
        $node = $this->createNodeForResource($resource, $creator, $parentNode, $file);
278
279
        $this->addResourceNodeToCourse($node, $visibility, $course, $session, $group);
280
    }
281
282
    public function addResourceNodeToCourse(ResourceNode $resourceNode, int $visibility, Course $course, Session $session = null, CGroupInfo $group = null, User $toUser = null): void
283
    {
284
        if (empty($visibility)) {
285
            $visibility = ResourceLink::VISIBILITY_PUBLISHED;
286
        }
287
288
        $link = new ResourceLink();
289
        $link
290
            ->setCourse($course)
291
            ->setSession($session)
292
            ->setGroup($group)
293
            ->setUser($toUser)
294
            ->setResourceNode($resourceNode)
295
            ->setVisibility($visibility)
296
        ;
297
298
        $rights = [];
299
        switch ($visibility) {
300
            case ResourceLink::VISIBILITY_PENDING:
301
            case ResourceLink::VISIBILITY_DRAFT:
302
                $editorMask = ResourceNodeVoter::getEditorMask();
303
                $resourceRight = new ResourceRight();
304
                $resourceRight
305
                    ->setMask($editorMask)
306
                    ->setRole(ResourceNodeVoter::ROLE_CURRENT_COURSE_TEACHER)
307
                ;
308
                $rights[] = $resourceRight;
309
310
                break;
311
        }
312
313
        if (!empty($rights)) {
314
            foreach ($rights as $right) {
315
                $link->addResourceRight($right);
316
            }
317
        }
318
319
        $em = $this->getEntityManager();
320
        $em->persist($link);
321
    }
322
323
    public function addResourceToMe(ResourceNode $resourceNode): ResourceLink
324
    {
325
        $resourceLink = new ResourceLink();
326
        $resourceLink
327
            ->setResourceNode($resourceNode)
328
        ;
329
330
        $this->getEntityManager()->persist($resourceLink);
331
        $this->getEntityManager()->flush();
332
333
        return $resourceLink;
334
    }
335
336
    public function addResourceToEveryone(ResourceNode $resourceNode, ResourceRight $right): ResourceLink
337
    {
338
        $resourceLink = new ResourceLink();
339
        $resourceLink
340
            ->setResourceNode($resourceNode)
341
            ->addResourceRight($right)
342
        ;
343
344
        $this->getEntityManager()->persist($resourceLink);
345
        $this->getEntityManager()->flush();
346
347
        return $resourceLink;
348
    }
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
    public function addResourceNodeToUser(ResourceNode $resourceNode, User $toUser): ResourceLink
359
    {
360
        $resourceLink = new ResourceLink();
361
        $resourceLink
362
            ->setResourceNode($resourceNode)
363
            ->setVisibility(ResourceLink::VISIBILITY_PUBLISHED)
364
            ->setUser($toUser);
365
366
        return $resourceLink;
367
    }
368
369
    public function addResourceToCourseGroup(
370
        ResourceNode $resourceNode,
371
        CGroupInfo $group
372
    ) {
373
        $exists = $resourceNode->getResourceLinks()->exists(function ($key, $element) use ($group) {
374
            if ($element->getGroup()) {
375
                return $group->getIid() == $element->getGroup()->getIid();
376
            }
377
        });
378
379
        if (false === $exists) {
380
            $resourceLink = new ResourceLink();
381
            $resourceLink
382
                ->setResourceNode($resourceNode)
383
                ->setGroup($group)
384
                ->setVisibility(ResourceLink::VISIBILITY_PUBLISHED)
385
            ;
386
            $this->getEntityManager()->persist($resourceLink);
387
388
            return $resourceLink;
389
        }
390
    }
391
392
    /*public function addResourceToSession(
393
        ResourceNode $resourceNode,
394
        Course $course,
395
        Session $session,
396
        ResourceRight $right
397
    ) {
398
        $resourceLink = $this->addResourceToCourse(
399
            $resourceNode,
400
            $course,
401
            $right
402
        );
403
        $resourceLink->setSession($session);
404
        $this->getEntityManager()->persist($resourceLink);
405
406
        return $resourceLink;
407
    }*/
408
409
    /**
410
     * @return ResourceLink
411
     */
412
    public function addResourceToGroup(
413
        ResourceNode $resourceNode,
414
        Usergroup $group,
415
        ResourceRight $right
416
    ) {
417
        $resourceLink = new ResourceLink();
418
        $resourceLink
419
            ->setResourceNode($resourceNode)
420
            ->setUserGroup($group)
421
            ->addResourceRight($right);
422
423
        return $resourceLink;
424
    }
425
426
    /**
427
     * @param array $userList User id list
428
     */
429
    public function addResourceToUserList(ResourceNode $resourceNode, array $userList)
430
    {
431
        $em = $this->getEntityManager();
432
433
        if (!empty($userList)) {
434
            $userRepo = $em->getRepository('ChamiloUserBundle:User');
435
            foreach ($userList as $userId) {
436
                $toUser = $userRepo->find($userId);
437
                $resourceLink = $this->addResourceNodeToUser($resourceNode, $toUser);
438
                $em->persist($resourceLink);
439
            }
440
        }
441
    }
442
443
    /**
444
     * @return ResourceType
445
     */
446
    public function getResourceType()
447
    {
448
        $em = $this->getEntityManager();
449
        $service = get_class($this);
450
        $name = $this->toolChain->getResourceTypeNameFromRepository($service);
451
        $repo = $em->getRepository('ChamiloCoreBundle:Resource\ResourceType');
452
453
        return $repo->findOneBy(['name' => $name]);
454
    }
455
456
    public function getResourcesByCourse(Course $course, Session $session = null, CGroupInfo $group = null, ResourceNode $parentNode = null): QueryBuilder
457
    {
458
        $repo = $this->getRepository();
459
        $className = $repo->getClassName();
460
        $checker = $this->getAuthorizationChecker();
461
        $reflectionClass = $repo->getClassMetadata()->getReflectionClass();
462
463
        // Check if this resource type requires to load the base course resources when using a session
464
        $loadBaseSessionContent = $reflectionClass->hasProperty('loadCourseResourcesInSession');
465
466
        $type = $this->getResourceType();
467
468
        $qb = $repo->getEntityManager()->createQueryBuilder()
469
            ->select('resource')
470
            ->from($className, 'resource')
471
            ->innerJoin(
472
                ResourceNode::class,
473
                'node',
474
                Join::WITH,
475
                'resource.resourceNode = node.id'
476
            )
477
            ->innerJoin('node.resourceLinks', 'links')
478
            ->where('node.resourceType = :type')
479
            ->setParameter('type', $type);
480
        $qb
481
            ->andWhere('links.course = :course')
482
            ->setParameter('course', $course)
483
        ;
484
485
        $isAdmin = $checker->isGranted('ROLE_ADMIN') ||
486
            $checker->isGranted('ROLE_CURRENT_COURSE_TEACHER');
487
488
        // Do not show deleted resources
489
        $qb
490
            ->andWhere('links.visibility != :visibilityDeleted')
491
            ->setParameter('visibilityDeleted', ResourceLink::VISIBILITY_DELETED)
492
        ;
493
494
        if (false === $isAdmin) {
495
            $qb
496
                ->andWhere('links.visibility = :visibility')
497
                ->setParameter('visibility', ResourceLink::VISIBILITY_PUBLISHED)
498
            ;
499
            // @todo Add start/end visibility restrictrions
500
        }
501
502
        if (null === $session) {
503
            //$qb->andWhere('links.session IS NULL');
504
            $qb->andWhere(
505
                $qb->expr()->orX(
506
                    $qb->expr()->isNull('links.session'),
507
                    $qb->expr()->eq('links.session', 0)
508
                )
509
            );
510
        } else {
511
            if ($loadBaseSessionContent) {
512
                // Load course base content.
513
                $qb->andWhere('links.session = :session OR links.session IS NULL');
514
                $qb->setParameter('session', $session);
515
            } else {
516
                // Load only session resources.
517
                $qb->andWhere('links.session = :session');
518
                $qb->setParameter('session', $session);
519
            }
520
        }
521
522
        if (null !== $parentNode) {
523
            $qb->andWhere('node.parent = :parentNode');
524
            $qb->setParameter('parentNode', $parentNode);
525
        }
526
527
        if (null === $group) {
528
            $qb->andWhere(
529
                $qb->expr()->orX(
530
                    $qb->expr()->isNull('links.group'),
531
                    $qb->expr()->eq('links.group', 0)
532
                )
533
            );
534
        } else {
535
            $qb->andWhere('links.group = :group');
536
            $qb->setParameter('group', $group);
537
        }
538
539
        return $qb;
540
    }
541
542
    public function getResourcesByCourseOnly(Course $course, ResourceNode $parentNode = null)
543
    {
544
        $repo = $this->getRepository();
545
        $className = $repo->getClassName();
546
        $checker = $this->getAuthorizationChecker();
547
        $type = $this->getResourceType();
548
549
        $qb = $repo->getEntityManager()->createQueryBuilder()
550
            ->select('resource')
551
            ->from($className, 'resource')
552
            ->innerJoin(
553
                ResourceNode::class,
554
                'node',
555
                Join::WITH,
556
                'resource.resourceNode = node.id'
557
            )
558
            ->innerJoin('node.resourceLinks', 'links')
559
            ->where('node.resourceType = :type')
560
            ->setParameter('type', $type);
561
        $qb
562
            ->andWhere('links.course = :course')
563
            ->setParameter('course', $course)
564
        ;
565
566
        $isAdmin = $checker->isGranted('ROLE_ADMIN') ||
567
            $checker->isGranted('ROLE_CURRENT_COURSE_TEACHER');
568
569
        // Do not show deleted resources
570
        $qb
571
            ->andWhere('links.visibility != :visibilityDeleted')
572
            ->setParameter('visibilityDeleted', ResourceLink::VISIBILITY_DELETED)
573
        ;
574
575
        if (false === $isAdmin) {
576
            $qb
577
                ->andWhere('links.visibility = :visibility')
578
                ->setParameter('visibility', ResourceLink::VISIBILITY_PUBLISHED)
579
            ;
580
            // @todo Add start/end visibility restrictrions
581
        }
582
583
        if (null !== $parentNode) {
584
            $qb->andWhere('node.parent = :parentNode');
585
            $qb->setParameter('parentNode', $parentNode);
586
        }
587
588
        return $qb;
589
    }
590
591
    /**
592
     * @return QueryBuilder
593
     */
594
    public function getResourcesByCreator(User $user, ResourceNode $parentNode = null)
595
    {
596
        $repo = $this->getRepository();
597
        $className = $repo->getClassName();
598
599
        $qb = $repo->getEntityManager()->createQueryBuilder()
600
            ->select('resource')
601
            ->from($className, 'resource')
602
            ->innerJoin(
603
                ResourceNode::class,
604
                'node',
605
                Join::WITH,
606
                'resource.resourceNode = node.id'
607
            )
608
            //->innerJoin('node.resourceLinks', 'links')
609
            //->where('node.resourceType = :type')
610
            //->setParameter('type',$type)
611
            ;
612
        /*$qb
613
            ->andWhere('links.visibility = :visibility')
614
            ->setParameter('visibility', ResourceLink::VISIBILITY_PUBLISHED)
615
        ;*/
616
617
        if (null !== $parentNode) {
618
            $qb->andWhere('node.parent = :parentNode');
619
            $qb->setParameter('parentNode', $parentNode);
620
        }
621
622
        $qb->andWhere('node.creator = :creator');
623
        $qb->setParameter('creator', $user);
624
        //var_dump($qb->getQuery()->getSQL(), $parentNode->getId());exit;
625
626
        return $qb;
627
    }
628
629
    public function getResourcesByCourseLinkedToUser(User $user, Course $course, Session $session = null, CGroupInfo $group = null, ResourceNode $parentNode = null): QueryBuilder
630
    {
631
        $qb = $this->getResourcesByCourse($course, $session, $group, $parentNode);
632
633
        $qb
634
            ->andWhere('links.user = :user')
635
            ->setParameter('user', $user);
636
637
        return $qb;
638
    }
639
640
    public function getResourcesByLinkedUser(User $user, ResourceNode $parentNode = null): QueryBuilder
641
    {
642
        $repo = $this->getRepository();
643
        $className = $repo->getClassName();
644
        $checker = $this->getAuthorizationChecker();
645
        $type = $this->getResourceType();
646
647
        $qb = $repo->getEntityManager()->createQueryBuilder()
648
            ->select('resource')
649
            ->from($className, 'resource')
650
            ->innerJoin(
651
                ResourceNode::class,
652
                'node',
653
                Join::WITH,
654
                'resource.resourceNode = node.id'
655
            )
656
            ->innerJoin('node.resourceLinks', 'links')
657
            ->where('node.resourceType = :type')
658
            ->setParameter('type', $type);
659
        $qb
660
            ->andWhere('links.user = :user')
661
            ->setParameter('user', $user)
662
        ;
663
664
        $isAdmin = $checker->isGranted('ROLE_ADMIN') ||
665
            $checker->isGranted('ROLE_CURRENT_COURSE_TEACHER');
666
667
        // Do not show deleted resources
668
        $qb
669
            ->andWhere('links.visibility != :visibilityDeleted')
670
            ->setParameter('visibilityDeleted', ResourceLink::VISIBILITY_DELETED)
671
        ;
672
673
        if (false === $isAdmin) {
674
            $qb
675
                ->andWhere('links.visibility = :visibility')
676
                ->setParameter('visibility', ResourceLink::VISIBILITY_PUBLISHED)
677
            ;
678
            // @todo Add start/end visibility restrictrions
679
        }
680
681
        if (null !== $parentNode) {
682
            $qb->andWhere('node.parent = :parentNode');
683
            $qb->setParameter('parentNode', $parentNode);
684
        }
685
686
        return $qb;
687
    }
688
689
    public function getResourceFromResourceNode(int $resourceNodeId): ?AbstractResource
690
    {
691
        return $this->getRepository()->findOneBy(['resourceNode' => $resourceNodeId]);
692
    }
693
694
    public function rowCanBeEdited(RowAction $action, Row $row, Session $session = null): ?RowAction
695
    {
696
        if (null !== $session) {
697
            /** @var AbstractResource $entity */
698
            $entity = $row->getEntity();
699
            $hasSession = $entity->getResourceNode()->hasSession($session);
700
            if ($hasSession->count() > 0) {
701
                return $action;
702
            }
703
704
            return null;
705
        }
706
707
        return $action;
708
    }
709
710
    public function delete(AbstractResource $resource)
711
    {
712
        $children = $resource->getResourceNode()->getChildren();
713
        foreach ($children as $child) {
714
            $this->getEntityManager()->remove($child);
715
        }
716
        $this->getEntityManager()->remove($resource->getResourceNode());
717
        $this->getEntityManager()->flush();
718
    }
719
720
    /**
721
     * Deletes several entities: AbstractResource (Ex: CDocument, CQuiz), ResourceNode,
722
     * ResourceLinks and ResourceFile (including files via Flysystem).
723
     */
724
    public function hardDelete(AbstractResource $resource)
725
    {
726
        $em = $this->getEntityManager();
727
        $em->remove($resource);
728
        $em->flush();
729
    }
730
731
    public function getResourceFileContent(AbstractResource $resource): string
732
    {
733
        try {
734
            $resourceNode = $resource->getResourceNode();
735
            if ($resourceNode->hasResourceFile()) {
736
                $resourceFile = $resourceNode->getResourceFile();
737
                $fileName = $this->getFilename($resourceFile);
738
739
                return $this->getFileSystem()->read($fileName);
740
            }
741
742
            return '';
743
        } catch (\Throwable $exception) {
744
            throw new FileNotFoundException($resource);
745
        }
746
    }
747
748
    public function getResourceNodeFileContent(ResourceNode $resourceNode): string
749
    {
750
        try {
751
            if ($resourceNode->hasResourceFile()) {
752
                $resourceFile = $resourceNode->getResourceFile();
753
                $fileName = $this->getFilename($resourceFile);
754
755
                return $this->getFileSystem()->read($fileName);
756
            }
757
758
            return '';
759
        } catch (\Throwable $exception) {
760
            throw new FileNotFoundException($resourceNode);
761
        }
762
    }
763
764
    public function getResourceNodeFileStream(ResourceNode $resourceNode)
765
    {
766
        try {
767
            if ($resourceNode->hasResourceFile()) {
768
                $resourceFile = $resourceNode->getResourceFile();
769
                $fileName = $this->getFilename($resourceFile);
770
771
                return $this->getFileSystem()->readStream($fileName);
772
            }
773
774
            return '';
775
        } catch (\Throwable $exception) {
776
            throw new FileNotFoundException($resourceNode);
777
        }
778
    }
779
780
    public function getFilename(ResourceFile $resourceFile)
781
    {
782
        return $this->storage->resolveUri($resourceFile);
783
    }
784
785
    public function getResourceFileUrl(AbstractResource $resource, array $extraParams = [], $referenceType = null): string
786
    {
787
        try {
788
            $resourceNode = $resource->getResourceNode();
789
            if ($resourceNode->hasResourceFile()) {
790
                $params = [
791
                    'tool' => $resourceNode->getResourceType()->getTool(),
792
                    'type' => $resourceNode->getResourceType(),
793
                    'id' => $resourceNode->getId(),
794
                ];
795
796
                if (!empty($extraParams)) {
797
                    $params = array_merge($params, $extraParams);
798
                }
799
800
                $referenceType = $referenceType ?? UrlGeneratorInterface::ABSOLUTE_PATH;
801
802
                return $this->router->generate('chamilo_core_resource_view', $params, $referenceType);
803
            }
804
805
            return '';
806
        } catch (\Throwable $exception) {
807
            throw new FileNotFoundException($resource);
808
        }
809
    }
810
811
    public function getResourceSettings(): ResourceSettings
812
    {
813
        $settings = new ResourceSettings();
814
        $settings
815
            ->setAllowNodeCreation(false)
816
            ->setAllowResourceCreation(false)
817
            ->setAllowResourceUpload(false)
818
        ;
819
820
        return $settings;
821
    }
822
823
    /**
824
     * @param string $content
825
     *
826
     * @return bool
827
     */
828
    public function updateResourceFileContent(AbstractResource $resource, $content)
829
    {
830
        try {
831
            $resourceNode = $resource->getResourceNode();
832
            if ($resourceNode->hasResourceFile()) {
833
                $resourceFile = $resourceNode->getResourceFile();
834
                if ($resourceFile) {
0 ignored issues
show
introduced by
$resourceFile is of type Chamilo\CoreBundle\Entity\Resource\ResourceFile, thus it always evaluated to true.
Loading history...
835
                    $fileName = $this->getFilename($resourceFile);
836
                    $this->getFileSystem()->update($fileName, $content);
837
                    $size = $this->getFileSystem()->getSize($fileName);
838
839
                    if ($resource instanceof CDocument) {
840
                        $resource->setSize($size);
841
                    }
842
                    $this->entityManager->persist($resource);
843
844
                    return true;
845
                }
846
            }
847
848
            return false;
849
        } catch (\Throwable $exception) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
850
        }
851
    }
852
853
    /**
854
     * Change all links visibility to DELETED.
855
     */
856
    public function softDelete(AbstractResource $resource)
857
    {
858
        $this->setLinkVisibility($resource, ResourceLink::VISIBILITY_DELETED);
859
    }
860
861
    public function setVisibilityPublished(AbstractResource $resource)
862
    {
863
        $this->setLinkVisibility($resource, ResourceLink::VISIBILITY_PUBLISHED);
864
    }
865
866
    public function setVisibilityDraft(AbstractResource $resource)
867
    {
868
        $this->setLinkVisibility($resource, ResourceLink::VISIBILITY_DRAFT);
869
    }
870
871
    public function setVisibilityPending(AbstractResource $resource)
872
    {
873
        $this->setLinkVisibility($resource, ResourceLink::VISIBILITY_PENDING);
874
    }
875
876
    public function createNodeForResource(ResourceInterface $resource, User $creator, ResourceNode $parentNode = null, UploadedFile $file = null): ResourceNode
877
    {
878
        $em = $this->getEntityManager();
879
880
        $resourceType = $this->getResourceType();
881
        $resourceNode = new ResourceNode();
882
        $resourceName = $resource->getResourceName();
883
        $extension = $this->slugify->slugify(pathinfo($resourceName, PATHINFO_EXTENSION));
884
885
        if (empty($extension)) {
886
            $slug = $this->slugify->slugify($resourceName);
887
        } else {
888
            $originalExtension = pathinfo($resourceName, PATHINFO_EXTENSION);
889
            $originalBasename = \basename($resourceName, $originalExtension);
890
            $slug = sprintf('%s.%s', $this->slugify->slugify($originalBasename), $originalExtension);
891
        }
892
893
        $resourceNode
894
            ->setSlug($slug)
895
            ->setCreator($creator)
896
            ->setResourceType($resourceType)
897
        ;
898
899
        if (null !== $parentNode) {
900
            $resourceNode->setParent($parentNode);
901
        }
902
903
        $resource->setResourceNode($resourceNode);
904
        $em->persist($resourceNode);
905
        $em->persist($resource);
906
907
        if (null !== $file) {
908
            $this->addFile($resource, $file);
909
        }
910
911
        return $resourceNode;
912
    }
913
914
    private function setLinkVisibility(AbstractResource $resource, int $visibility, bool $recursive = true): bool
915
    {
916
        $resourceNode = $resource->getResourceNode();
917
918
        if (null === $resourceNode) {
919
            return false;
920
        }
921
922
        $em = $this->getEntityManager();
923
        if ($recursive) {
924
            $children = $resourceNode->getChildren();
925
            if (!empty($children)) {
926
                /** @var ResourceNode $child */
927
                foreach ($children as $child) {
928
                    $criteria = ['resourceNode' => $child];
929
                    $childDocument = $this->getRepository()->findOneBy($criteria);
930
                    if ($childDocument) {
931
                        $this->setLinkVisibility($childDocument, $visibility);
932
                    }
933
                }
934
            }
935
        }
936
937
        $links = $resourceNode->getResourceLinks();
938
939
        if (!empty($links)) {
940
            /** @var ResourceLink $link */
941
            foreach ($links as $link) {
942
                $link->setVisibility($visibility);
943
                if (ResourceLink::VISIBILITY_DRAFT === $visibility) {
944
                    $editorMask = ResourceNodeVoter::getEditorMask();
945
                    $rights = [];
946
                    $resourceRight = new ResourceRight();
947
                    $resourceRight
948
                        ->setMask($editorMask)
949
                        ->setRole(ResourceNodeVoter::ROLE_CURRENT_COURSE_TEACHER)
950
                        ->setResourceLink($link)
951
                    ;
952
                    $rights[] = $resourceRight;
953
954
                    if (!empty($rights)) {
955
                        $link->setResourceRight($rights);
956
                    }
957
                } else {
958
                    $link->setResourceRight([]);
959
                }
960
                $em->persist($link);
961
            }
962
        }
963
        $em->flush();
964
965
        return true;
966
    }
967
}
968