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

addResourceToCourseWithParent()   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 8
dl 0
loc 5
rs 10
c 0
b 0
f 0

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

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