Completed
Push — master ( 8f0a09...1a8186 )
by Julito
24:55
created

ResourceRepository::getResourceByResourceNode()   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
3
/* For licensing terms, see /license.txt */
4
5
namespace Chamilo\CoreBundle\Repository;
6
7
use Chamilo\CoreBundle\Component\Resource\Settings;
8
use Chamilo\CoreBundle\Component\Resource\Template;
9
use Chamilo\CoreBundle\Entity\AbstractResource;
10
use Chamilo\CoreBundle\Entity\Course;
11
use Chamilo\CoreBundle\Entity\ResourceFile;
12
use Chamilo\CoreBundle\Entity\ResourceInterface;
13
use Chamilo\CoreBundle\Entity\ResourceLink;
14
use Chamilo\CoreBundle\Entity\ResourceNode;
15
use Chamilo\CoreBundle\Entity\ResourceRight;
16
use Chamilo\CoreBundle\Entity\ResourceType;
17
use Chamilo\CoreBundle\Entity\Session;
18
use Chamilo\CoreBundle\Entity\User;
19
use Chamilo\CoreBundle\Security\Authorization\Voter\ResourceNodeVoter;
20
use Chamilo\CoreBundle\ToolChain;
21
use Chamilo\CourseBundle\Entity\CGroup;
22
use Cocur\Slugify\SlugifyInterface;
23
use Doctrine\ORM\EntityManager;
24
use Doctrine\ORM\EntityRepository;
25
use Doctrine\ORM\QueryBuilder;
26
use League\Flysystem\FilesystemInterface;
27
use Symfony\Component\Filesystem\Exception\FileNotFoundException;
28
use Symfony\Component\Form\FormFactory;
29
use Symfony\Component\Form\FormInterface;
30
use Symfony\Component\HttpFoundation\File\UploadedFile;
31
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
32
use Symfony\Component\Routing\RouterInterface;
33
use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
34
35
/**
36
 * Class ResourceRepository.
37
 * Extends EntityRepository is needed to process settings.
38
 */
39
class ResourceRepository extends EntityRepository
40
{
41
    /**
42
     * @var EntityRepository
43
     */
44
    protected $repository;
45
46
    /**
47
     * @var FilesystemInterface
48
     */
49
    protected $fs;
50
51
    /**
52
     * @var EntityManager
53
     */
54
    protected $entityManager;
55
56
    /**
57
     * The entity class FQN.
58
     *
59
     * @var string
60
     */
61
    protected $className;
62
63
    /** @var RouterInterface */
64
    protected $router;
65
66
    /** @var ResourceNodeRepository */
67
    protected $resourceNodeRepository;
68
69
    /**
70
     * @var AuthorizationCheckerInterface
71
     */
72
    protected $authorizationChecker;
73
74
    /** @var SlugifyInterface */
75
    protected $slugify;
76
77
    /** @var ToolChain */
78
    protected $toolChain;
79
    protected $settings;
80
    protected $templates;
81
    protected $resourceType;
82
83
    /**
84
     * ResourceRepository constructor.
85
     */
86
    public function __construct(
87
        AuthorizationCheckerInterface $authorizationChecker,
88
        EntityManager $entityManager,
89
        RouterInterface $router,
90
        SlugifyInterface $slugify,
91
        ToolChain $toolChain,
92
        ResourceNodeRepository $resourceNodeRepository
93
    ) {
94
        $className = $this->getClassName();
95
        $this->repository = $entityManager->getRepository($className);
96
        $this->authorizationChecker = $authorizationChecker;
97
        $this->router = $router;
98
        $this->resourceNodeRepository = $resourceNodeRepository;
99
        $this->slugify = $slugify;
100
        $this->toolChain = $toolChain;
101
        $this->settings = new Settings();
102
        $this->templates = new Template();
103
    }
104
105
    public function getClassName()
106
    {
107
        $class = get_class($this);
108
        //Chamilo\CoreBundle\Repository\IllustrationRepository
109
        $class = str_replace('\\Repository\\', '\\Entity\\', $class);
110
        $class = str_replace('Repository', '', $class);
111
        if (false === class_exists($class)) {
112
            throw new \Exception("Repo: $class not found ");
113
        }
114
115
        return $class;
116
    }
117
118
    public function getAuthorizationChecker(): AuthorizationCheckerInterface
119
    {
120
        return $this->authorizationChecker;
121
    }
122
123
    /**
124
     * @return AbstractResource
125
     */
126
    public function create()
127
    {
128
        $class = $this->repository->getClassName();
129
130
        return new $class();
131
    }
132
133
    public function getRouter(): RouterInterface
134
    {
135
        return $this->router;
136
    }
137
138
    /**
139
     * @return ResourceNodeRepository
140
     */
141
    public function getResourceNodeRepository()
142
    {
143
        return $this->resourceNodeRepository;
144
    }
145
146
    public function getEntityManager(): EntityManager
147
    {
148
        return $this->getRepository()->getEntityManager();
149
    }
150
151
    /**
152
     * @return EntityRepository
153
     */
154
    public function getRepository()
155
    {
156
        return $this->repository;
157
    }
158
159
    /**
160
     * @return FormInterface
161
     */
162
    public function getForm(FormFactory $formFactory, AbstractResource $resource = null, $options = [])
163
    {
164
        $formType = $this->getResourceFormType();
165
166
        if (null === $resource) {
167
            $className = $this->repository->getClassName();
168
            $resource = new $className();
169
        }
170
171
        return $formFactory->create($formType, $resource, $options);
172
    }
173
174
    /**
175
     * @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...
176
     * @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...
177
     *
178
     * @return ResourceInterface
179
     */
180
    public function find($id, $lockMode = null, $lockVersion = null)
181
    {
182
        return $this->getRepository()->find($id, $lockMode, $lockVersion);
183
    }
184
185
    public function getResourceByResourceNode(ResourceNode $resourceNode)
186
    {
187
        return $this->getRepository()->findOneBy(['resourceNode' => $resourceNode]);
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\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->setTitle($resourceName);
225
        //$resourceNode->setSlug($slug);
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
    /**
269
     * @return ResourceType
270
     */
271
    public function getResourceType()
272
    {
273
        $name = $this->getResourceTypeName();
274
        $repo = $this->getEntityManager()->getRepository(ResourceType::class);
275
        $this->resourceType = $repo->findOneBy(['name' => $name]);
276
277
        return $this->resourceType;
278
    }
279
280
    public function getResourceTypeName(): string
281
    {
282
        return $this->toolChain->getResourceTypeNameFromRepository(get_class($this));
283
    }
284
285
    public function getResourcesByCourse(Course $course, Session $session = null, CGroup $group = null, ResourceNode $parentNode = null): QueryBuilder
286
    {
287
        $repo = $this->getRepository();
288
        $className = $repo->getClassName();
289
        $checker = $this->getAuthorizationChecker();
290
        $reflectionClass = $repo->getClassMetadata()->getReflectionClass();
291
292
        // Check if this resource type requires to load the base course resources when using a session
293
        $loadBaseSessionContent = $reflectionClass->hasProperty('loadCourseResourcesInSession');
294
        $resourceTypeName = $this->getResourceTypeName();
295
296
        $qb = $repo->getEntityManager()->createQueryBuilder()
297
            ->select('resource')
298
            ->from($className, 'resource')
299
            ->innerJoin('resource.resourceNode', 'node')
300
            ->innerJoin('node.resourceLinks', 'links')
301
            ->innerJoin('node.resourceType', 'type')
302
            //->innerJoin('links.course', 'course')
303
            ->leftJoin('node.resourceFile', 'file')
304
305
            ->where('type.name = :type')
306
            ->setParameter('type', $resourceTypeName)
307
            ->andWhere('links.course = :course')
308
            ->setParameter('course', $course)
309
            ->addSelect('node')
310
            ->addSelect('links')
311
            //->addSelect('course')
312
            ->addSelect('type')
313
            ->addSelect('file')
314
        ;
315
316
        $isAdmin = $checker->isGranted('ROLE_ADMIN') ||
317
            $checker->isGranted('ROLE_CURRENT_COURSE_TEACHER');
318
319
        // Do not show deleted resources
320
        $qb
321
            ->andWhere('links.visibility != :visibilityDeleted')
322
            ->setParameter('visibilityDeleted', ResourceLink::VISIBILITY_DELETED)
323
        ;
324
325
        if (false === $isAdmin) {
326
            $qb
327
                ->andWhere('links.visibility = :visibility')
328
                ->setParameter('visibility', ResourceLink::VISIBILITY_PUBLISHED)
329
            ;
330
            // @todo Add start/end visibility restrictions.
331
        }
332
333
        if (null === $session) {
334
            $qb->andWhere(
335
                $qb->expr()->orX(
336
                    $qb->expr()->isNull('links.session'),
337
                    $qb->expr()->eq('links.session', 0)
338
                )
339
            );
340
        } else {
341
            if ($loadBaseSessionContent) {
342
                // Load course base content.
343
                $qb->andWhere('links.session = :session OR links.session IS NULL');
344
                $qb->setParameter('session', $session);
345
            } else {
346
                // Load only session resources.
347
                $qb->andWhere('links.session = :session');
348
                $qb->setParameter('session', $session);
349
            }
350
        }
351
352
        if (null !== $parentNode) {
353
            $qb->andWhere('node.parent = :parentNode');
354
            $qb->setParameter('parentNode', $parentNode);
355
        }
356
357
        if (null === $group) {
358
            $qb->andWhere(
359
                $qb->expr()->orX(
360
                    $qb->expr()->isNull('links.group'),
361
                    $qb->expr()->eq('links.group', 0)
362
                )
363
            );
364
        } else {
365
            $qb->andWhere('links.group = :group');
366
            $qb->setParameter('group', $group);
367
        }
368
369
        return $qb;
370
    }
371
372
    public function getResourcesByCourseOnly(Course $course, ResourceNode $parentNode = null)
373
    {
374
        $repo = $this->getRepository();
375
        $className = $repo->getClassName();
376
        $checker = $this->getAuthorizationChecker();
377
        $resourceTypeName = $this->getResourceTypeName();
378
379
        $qb = $repo->getEntityManager()->createQueryBuilder()
380
            ->select('resource')
381
            ->from($className, 'resource')
382
            ->innerJoin(
383
                'resource.resourceNode',
384
                'node'
385
            )
386
            ->innerJoin('node.resourceLinks', 'links')
387
            ->innerJoin('node.resourceType', 'type')
388
            ->where('type.name = :type')
389
            ->setParameter('type', $resourceTypeName)
390
            ->andWhere('links.course = :course')
391
            ->setParameter('course', $course)
392
        ;
393
394
        $isAdmin = $checker->isGranted('ROLE_ADMIN') ||
395
            $checker->isGranted('ROLE_CURRENT_COURSE_TEACHER');
396
397
        // Do not show deleted resources
398
        $qb
399
            ->andWhere('links.visibility != :visibilityDeleted')
400
            ->setParameter('visibilityDeleted', ResourceLink::VISIBILITY_DELETED)
401
        ;
402
403
        if (false === $isAdmin) {
404
            $qb
405
                ->andWhere('links.visibility = :visibility')
406
                ->setParameter('visibility', ResourceLink::VISIBILITY_PUBLISHED)
407
            ;
408
            // @todo Add start/end visibility restrictrions
409
        }
410
411
        if (null !== $parentNode) {
412
            $qb->andWhere('node.parent = :parentNode');
413
            $qb->setParameter('parentNode', $parentNode);
414
        }
415
416
        return $qb;
417
    }
418
419
    /**
420
     * @return QueryBuilder
421
     */
422
    public function getResourcesByCreator(User $user, ResourceNode $parentNode = null)
423
    {
424
        $repo = $this->getRepository();
425
        $className = $repo->getClassName();
426
427
        $qb = $repo->getEntityManager()->createQueryBuilder()
428
            ->select('resource')
429
            ->from($className, 'resource')
430
            ->innerJoin(
431
                'resource.resourceNode',
432
                'node'
433
            )
434
            //->innerJoin('node.resourceLinks', 'links')
435
            //->where('node.resourceType = :type')
436
            //->setParameter('type',$type)
437
            ;
438
        /*$qb
439
            ->andWhere('links.visibility = :visibility')
440
            ->setParameter('visibility', ResourceLink::VISIBILITY_PUBLISHED)
441
        ;*/
442
443
        if (null !== $parentNode) {
444
            $qb->andWhere('node.parent = :parentNode');
445
            $qb->setParameter('parentNode', $parentNode);
446
        }
447
448
        $qb->andWhere('node.creator = :creator');
449
        $qb->setParameter('creator', $user);
450
451
        return $qb;
452
    }
453
454
    public function getResourcesByCourseLinkedToUser(
455
        User $user,
456
        Course $course,
457
        Session $session = null,
458
        CGroup $group = null,
459
        ResourceNode $parentNode = null
460
    ): QueryBuilder {
461
        $qb = $this->getResourcesByCourse($course, $session, $group, $parentNode);
462
463
        $qb
464
            ->andWhere('links.user = :user')
465
            ->setParameter('user', $user);
466
467
        return $qb;
468
    }
469
470
    public function getResourcesByLinkedUser(User $user, ResourceNode $parentNode = null): QueryBuilder
471
    {
472
        $repo = $this->getRepository();
473
        $className = $repo->getClassName();
474
        $checker = $this->getAuthorizationChecker();
475
        $resourceTypeName = $this->getResourceTypeName();
476
477
        $qb = $repo->getEntityManager()->createQueryBuilder()
478
            ->select('resource')
479
            ->from($className, 'resource')
480
            ->innerJoin(
481
                'resource.resourceNode',
482
                'node'
483
            )
484
            ->innerJoin('node.resourceLinks', 'links')
485
            ->innerJoin('node.resourceType', 'type')
486
            ->where('type.name = :type')
487
            ->setParameter('type', $resourceTypeName)
488
            ->andWhere('links.user = :user')
489
            ->setParameter('user', $user)
490
        ;
491
492
        $isAdmin = $checker->isGranted('ROLE_ADMIN') ||
493
            $checker->isGranted('ROLE_CURRENT_COURSE_TEACHER');
494
495
        // Do not show deleted resources
496
        $qb
497
            ->andWhere('links.visibility != :visibilityDeleted')
498
            ->setParameter('visibilityDeleted', ResourceLink::VISIBILITY_DELETED)
499
        ;
500
501
        if (false === $isAdmin) {
502
            $qb
503
                ->andWhere('links.visibility = :visibility')
504
                ->setParameter('visibility', ResourceLink::VISIBILITY_PUBLISHED)
505
            ;
506
            // @todo Add start/end visibility restrictrions
507
        }
508
509
        if (null !== $parentNode) {
510
            $qb->andWhere('node.parent = :parentNode');
511
            $qb->setParameter('parentNode', $parentNode);
512
        }
513
514
        return $qb;
515
    }
516
517
    public function getResourceFromResourceNode(int $resourceNodeId): ?AbstractResource
518
    {
519
        //return $this->getRepository()->findOneBy(['resourceNode' => $resourceNodeId]);
520
        //$className = $this->getClassName();
521
        /*var_dump(get_class($this->repository));
522
        var_dump(get_class($this->getRepository()));
523
        var_dump(get_class($this));*/
524
        //var_dump($className);
525
        // Include links
526
        $qb = $this->getRepository()->createQueryBuilder('resource')
527
            ->select('resource')
528
            ->addSelect('node')
529
            ->addSelect('links')
530
            //->addSelect('file')
531
            //->from($className, 'resource')
532
            ->innerJoin('resource.resourceNode', 'node')
533
        //    ->innerJoin('node.creator', 'userCreator')
534
            ->innerJoin('node.resourceLinks', 'links')
535
//            ->leftJoin('node.resourceFile', 'file')
536
            ->where('node.id = :id')
537
            ->setParameters(['id' => $resourceNodeId])
538
            //->addSelect('node')
539
        ;
540
541
        return $qb->getQuery()->getOneOrNullResult();
542
    }
543
544
    public function delete(AbstractResource $resource)
545
    {
546
        $children = $resource->getResourceNode()->getChildren();
547
        foreach ($children as $child) {
548
            if ($child->hasResourceFile()) {
549
                $this->getEntityManager()->remove($child->getResourceFile());
550
            }
551
            $resourceNode = $this->getResourceFromResourceNode($child->getId());
552
            if ($resourceNode) {
553
                $this->delete($resourceNode);
554
            }
555
        }
556
        $this->getEntityManager()->remove($resource);
557
        $this->getEntityManager()->flush();
558
    }
559
560
    /**
561
     * Deletes several entities: AbstractResource (Ex: CDocument, CQuiz), ResourceNode,
562
     * ResourceLinks and ResourceFile (including files via Flysystem).
563
     */
564
    public function hardDelete(AbstractResource $resource)
565
    {
566
        $em = $this->getEntityManager();
567
        $em->remove($resource);
568
        $em->flush();
569
    }
570
571
    public function getResourceFileContent(AbstractResource $resource): string
572
    {
573
        try {
574
            $resourceNode = $resource->getResourceNode();
575
576
            return $this->resourceNodeRepository->getResourceNodeFileContent($resourceNode);
577
        } catch (\Throwable $exception) {
578
            throw new FileNotFoundException($resource);
579
        }
580
    }
581
582
    public function getResourceNodeFileContent(ResourceNode $resourceNode): string
583
    {
584
        return $this->resourceNodeRepository->getResourceNodeFileContent($resourceNode);
585
    }
586
587
    public function getResourceNodeFileStream(ResourceNode $resourceNode)
588
    {
589
        return $this->resourceNodeRepository->getResourceNodeFileStream($resourceNode);
590
    }
591
592
    public function getResourceFileDownloadUrl(AbstractResource $resource, array $extraParams = [], $referenceType = null): string
593
    {
594
        $extraParams['mode'] = 'download';
595
596
        return $this->getResourceFileUrl($resource, $extraParams, $referenceType);
597
    }
598
599
    public function getResourceFileUrl(AbstractResource $resource, array $extraParams = [], $referenceType = null): string
600
    {
601
        try {
602
            $resourceNode = $resource->getResourceNode();
603
            if ($resourceNode->hasResourceFile()) {
604
                $params = [
605
                    'tool' => $resourceNode->getResourceType()->getTool(),
606
                    'type' => $resourceNode->getResourceType(),
607
                    'id' => $resourceNode->getId(),
608
                ];
609
610
                if (!empty($extraParams)) {
611
                    $params = array_merge($params, $extraParams);
612
                }
613
614
                $referenceType = $referenceType ?? UrlGeneratorInterface::ABSOLUTE_PATH;
615
616
                return $this->router->generate('chamilo_core_resource_view_file', $params, $referenceType);
617
            }
618
619
            return '';
620
        } catch (\Throwable $exception) {
621
            throw new FileNotFoundException($resource);
622
        }
623
    }
624
625
    public function getResourceSettings(): Settings
626
    {
627
        return $this->settings;
628
    }
629
630
    public function getTemplates(): Template
631
    {
632
        return $this->templates;
633
    }
634
635
    /**
636
     * @param string $content
637
     *
638
     * @return bool
639
     */
640
    public function updateResourceFileContent(AbstractResource $resource, $content)
641
    {
642
        error_log('updateResourceFileContent');
643
644
        $resourceNode = $resource->getResourceNode();
645
        if ($resourceNode->hasResourceFile()) {
646
            error_log('has file');
647
            $resourceFile = $resourceNode->getResourceFile();
648
            if ($resourceFile) {
0 ignored issues
show
introduced by
$resourceFile is of type Chamilo\CoreBundle\Entity\ResourceFile, thus it always evaluated to true.
Loading history...
649
                error_log('$resourceFile');
650
                $title = $resource->getResourceName();
651
                $handle = tmpfile();
652
                fwrite($handle, $content);
653
                error_log($title);
654
                error_log($content);
655
                $meta = stream_get_meta_data($handle);
656
                $file = new UploadedFile($meta['uri'], $title, 'text/html', null, true);
657
                $resource->setUploadFile($file);
658
659
                return true;
660
            }
661
        }
662
        error_log('false');
663
664
        return false;
665
    }
666
667
    public function setResourceName(AbstractResource $resource, $title)
668
    {
669
        $resource->setResourceName($title);
670
        $resourceNode = $resource->getResourceNode();
671
        $resourceNode->setTitle($title);
672
        if ($resourceNode->hasResourceFile()) {
673
            //$resourceNode->getResourceFile()->getFile()->
674
            //$resourceNode->getResourceFile()->setName($title);
675
            //$resourceFile->setName($title);
676
677
            /*$fileName = $this->getResourceNodeRepository()->getFilename($resourceFile);
678
            error_log('$fileName');
679
            error_log($fileName);
680
            error_log($title);
681
            $this->getResourceNodeRepository()->getFileSystem()->rename($fileName, $title);
682
            $resourceFile->setName($title);
683
            $resourceFile->setOriginalName($title);*/
684
        }
685
    }
686
687
    /**
688
     * Change all links visibility to DELETED.
689
     */
690
    public function softDelete(AbstractResource $resource)
691
    {
692
        $this->setLinkVisibility($resource, ResourceLink::VISIBILITY_DELETED);
693
    }
694
695
    public function setVisibilityPublished(AbstractResource $resource)
696
    {
697
        $this->setLinkVisibility($resource, ResourceLink::VISIBILITY_PUBLISHED);
698
    }
699
700
    public function setVisibilityDraft(AbstractResource $resource)
701
    {
702
        $this->setLinkVisibility($resource, ResourceLink::VISIBILITY_DRAFT);
703
    }
704
705
    public function setVisibilityPending(AbstractResource $resource)
706
    {
707
        $this->setLinkVisibility($resource, ResourceLink::VISIBILITY_PENDING);
708
    }
709
710
    public function createNodeForResource(ResourceInterface $resource, User $creator, ResourceNode $parentNode = null, UploadedFile $file = null): ResourceNode
711
    {
712
        $em = $this->getEntityManager();
713
714
        $resourceType = $this->getResourceType();
715
        $resourceName = $resource->getResourceName();
716
        $extension = $this->slugify->slugify(pathinfo($resourceName, PATHINFO_EXTENSION));
717
718
        if (empty($extension)) {
719
            $slug = $this->slugify->slugify($resourceName);
720
        } else {
721
            $originalExtension = pathinfo($resourceName, PATHINFO_EXTENSION);
722
            $originalBasename = \basename($resourceName, $originalExtension);
723
            $slug = sprintf('%s.%s', $this->slugify->slugify($originalBasename), $originalExtension);
724
        }
725
726
        $resourceNode = new ResourceNode();
727
        $resourceNode
728
            ->setTitle($resourceName)
729
            ->setSlug($slug)
730
            ->setCreator($creator)
731
            ->setResourceType($resourceType)
732
        ;
733
734
        if (null !== $parentNode) {
735
            $resourceNode->setParent($parentNode);
736
        }
737
738
        $resource->setResourceNode($resourceNode);
739
        $em->persist($resourceNode);
740
        $em->persist($resource);
741
742
        if (null !== $file) {
743
            $this->addFile($resource, $file);
744
        }
745
746
        return $resourceNode;
747
    }
748
749
    private function setLinkVisibility(AbstractResource $resource, int $visibility, bool $recursive = true): bool
750
    {
751
        $resourceNode = $resource->getResourceNode();
752
753
        if (null === $resourceNode) {
754
            return false;
755
        }
756
757
        $em = $this->getEntityManager();
758
        if ($recursive) {
759
            $children = $resourceNode->getChildren();
760
            if (!empty($children)) {
761
                /** @var ResourceNode $child */
762
                foreach ($children as $child) {
763
                    $criteria = ['resourceNode' => $child];
764
                    $childDocument = $this->getRepository()->findOneBy($criteria);
765
                    if ($childDocument) {
766
                        $this->setLinkVisibility($childDocument, $visibility);
767
                    }
768
                }
769
            }
770
        }
771
772
        $links = $resourceNode->getResourceLinks();
773
774
        if (!empty($links)) {
775
            /** @var ResourceLink $link */
776
            foreach ($links as $link) {
777
                $link->setVisibility($visibility);
778
                if (ResourceLink::VISIBILITY_DRAFT === $visibility) {
779
                    $editorMask = ResourceNodeVoter::getEditorMask();
780
                    $rights = [];
781
                    $resourceRight = new ResourceRight();
782
                    $resourceRight
783
                        ->setMask($editorMask)
784
                        ->setRole(ResourceNodeVoter::ROLE_CURRENT_COURSE_TEACHER)
785
                        ->setResourceLink($link)
786
                    ;
787
                    $rights[] = $resourceRight;
788
789
                    if (!empty($rights)) {
790
                        $link->setResourceRight($rights);
791
                    }
792
                } else {
793
                    $link->setResourceRight([]);
794
                }
795
                $em->persist($link);
796
            }
797
        }
798
        $em->flush();
799
800
        return true;
801
    }
802
}
803