Passed
Push — master ( 43f231...6078d3 )
by Julito
08:55
created

ResourceRepository::create()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

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