Passed
Push — master ( 84ebef...fea75d )
by Julito
09:38
created

ResourceRepository::isGranted()   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 2
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 updateResource(AbstractResource $resource)
196
    {
197
        $em = $this->getEntityManager();
198
199
        $resourceNode = $resource->getResourceNode();
200
        $resourceNode->setTitle($resource->getResourceName());
201
202
        $links = $resource->getResourceLinkEntityList();
203
        if ($links) {
204
            foreach ($links as $link) {
205
                $link->setResourceNode($resourceNode);
206
207
                $rights = [];
208
                switch ($link->getVisibility()) {
209
                    case ResourceLink::VISIBILITY_PENDING:
210
                    case ResourceLink::VISIBILITY_DRAFT:
211
                        $editorMask = ResourceNodeVoter::getEditorMask();
212
                        $resourceRight = new ResourceRight();
213
                        $resourceRight
214
                            ->setMask($editorMask)
215
                            ->setRole(ResourceNodeVoter::ROLE_CURRENT_COURSE_TEACHER)
216
                        ;
217
                        $rights[] = $resourceRight;
218
219
                        break;
220
                }
221
222
                if (!empty($rights)) {
223
                    foreach ($rights as $right) {
224
                        $link->addResourceRight($right);
225
                    }
226
                }
227
                $em->persist($link);
228
            }
229
        }
230
231
        $em->persist($resourceNode);
232
        $em->persist($resource);
233
        $em->flush();
234
    }*/
235
236
    public function updateNodeForResource(ResourceInterface $resource): ResourceNode
237
    {
238
        $em = $this->getEntityManager();
239
240
        $resourceNode = $resource->getResourceNode();
241
        $resourceName = $resource->getResourceName();
242
243
        if ($resourceNode->hasResourceFile()) {
244
            $resourceFile = $resourceNode->getResourceFile();
245
            if ($resourceFile) {
0 ignored issues
show
introduced by
$resourceFile is of type Chamilo\CoreBundle\Entity\ResourceFile, thus it always evaluated to true.
Loading history...
246
                $originalName = $resourceFile->getOriginalName();
247
                $originalExtension = pathinfo($originalName, PATHINFO_EXTENSION);
248
249
                //$originalBasename = \basename($resourceName, $originalExtension);
250
                /*$slug = sprintf(
251
                    '%s.%s',
252
                    $this->slugify->slugify($originalBasename),
253
                    $this->slugify->slugify($originalExtension)
254
                );*/
255
256
                $newOriginalName = sprintf('%s.%s', $resourceName, $originalExtension);
257
                $resourceFile->setOriginalName($newOriginalName);
258
259
                $em->persist($resourceFile);
260
            }
261
        } else {
262
            //$slug = $this->slugify->slugify($resourceName);
263
        }
264
265
        $resourceNode->setTitle($resourceName);
266
        //$resourceNode->setSlug($slug);
267
268
        $em->persist($resourceNode);
269
        $em->persist($resource);
270
271
        $em->flush();
272
273
        return $resourceNode;
274
    }
275
276
    public function addFile(ResourceInterface $resource, UploadedFile $file): ?ResourceFile
277
    {
278
        $resourceNode = $resource->getResourceNode();
279
280
        if (null === $resourceNode) {
281
            throw new \LogicException('Resource node is null');
282
        }
283
284
        $resourceFile = $resourceNode->getResourceFile();
285
        if (null === $resourceFile) {
286
            $resourceFile = new ResourceFile();
287
        }
288
289
        $em = $this->getEntityManager();
290
        $resourceFile->setFile($file);
291
        $resourceFile->setName($resource->getResourceName());
292
        $em->persist($resourceFile);
293
294
        $resourceNode->setResourceFile($resourceFile);
295
        $em->persist($resourceNode);
296
297
        return $resourceFile;
298
    }
299
300
    public function addResourceNode(AbstractResource $resource, User $creator, AbstractResource $parent = null): ResourceNode
301
    {
302
        if (null !== $parent) {
303
            $parent = $parent->getResourceNode();
304
        }
305
306
        return $this->createNodeForResource($resource, $creator, $parent);
307
    }
308
309
    /**
310
     * @return ResourceType
311
     */
312
    public function getResourceType()
313
    {
314
        $name = $this->getResourceTypeName();
315
        $repo = $this->getEntityManager()->getRepository(ResourceType::class);
316
        $this->resourceType = $repo->findOneBy(['name' => $name]);
317
318
        return $this->resourceType;
319
    }
320
321
    public function getResourceTypeName(): string
322
    {
323
        return $this->toolChain->getResourceTypeNameFromRepository(get_class($this));
324
    }
325
326
    public function getResourcesByCourse(Course $course, Session $session = null, CGroup $group = null, ResourceNode $parentNode = null): QueryBuilder
327
    {
328
        $repo = $this->getRepository();
329
        $className = $repo->getClassName();
330
        $checker = $this->getAuthorizationChecker();
331
        $reflectionClass = $repo->getClassMetadata()->getReflectionClass();
332
333
        // Check if this resource type requires to load the base course resources when using a session
334
        $loadBaseSessionContent = $reflectionClass->hasProperty('loadCourseResourcesInSession');
335
        $resourceTypeName = $this->getResourceTypeName();
336
337
        $qb = $repo->getEntityManager()->createQueryBuilder()
338
            ->select('resource')
339
            ->from($className, 'resource')
340
            ->innerJoin('resource.resourceNode', 'node')
341
            ->innerJoin('node.resourceLinks', 'links')
342
            ->innerJoin('node.resourceType', 'type')
343
            ->leftJoin('node.resourceFile', 'file')
344
345
            ->where('type.name = :type')
346
            ->setParameter('type', $resourceTypeName)
347
            ->andWhere('links.course = :course')
348
            ->setParameter('course', $course)
349
            ->addSelect('node')
350
            ->addSelect('links')
351
            //->addSelect('course')
352
            ->addSelect('type')
353
            ->addSelect('file')
354
        ;
355
356
        $isAdmin =
357
            $checker->isGranted('ROLE_ADMIN') ||
358
            $checker->isGranted('ROLE_CURRENT_COURSE_TEACHER');
359
360
        // Do not show deleted resources.
361
        $qb
362
            ->andWhere('links.visibility != :visibilityDeleted')
363
            ->setParameter('visibilityDeleted', ResourceLink::VISIBILITY_DELETED)
364
        ;
365
366
        if (false === $isAdmin) {
367
            $qb
368
                ->andWhere('links.visibility = :visibility')
369
                ->setParameter('visibility', ResourceLink::VISIBILITY_PUBLISHED)
370
            ;
371
            // @todo Add start/end visibility restrictions.
372
        }
373
374
        if (null === $session) {
375
            $qb->andWhere(
376
                $qb->expr()->orX(
377
                    $qb->expr()->isNull('links.session'),
378
                    $qb->expr()->eq('links.session', 0)
379
                )
380
            );
381
        } else {
382
            if ($loadBaseSessionContent) {
383
                // Load course base content.
384
                $qb->andWhere('links.session = :session OR links.session IS NULL');
385
                $qb->setParameter('session', $session);
386
            } else {
387
                // Load only session resources.
388
                $qb->andWhere('links.session = :session');
389
                $qb->setParameter('session', $session);
390
            }
391
        }
392
393
        if (null !== $parentNode) {
394
            $qb->andWhere('node.parent = :parentNode');
395
            $qb->setParameter('parentNode', $parentNode);
396
        }
397
398
        if (null === $group) {
399
            $qb->andWhere(
400
                $qb->expr()->orX(
401
                    $qb->expr()->isNull('links.group'),
402
                    $qb->expr()->eq('links.group', 0)
403
                )
404
            );
405
        } else {
406
            $qb->andWhere('links.group = :group');
407
            $qb->setParameter('group', $group);
408
        }
409
410
        return $qb;
411
    }
412
413
    public function getResourcesByCourseOnly(Course $course, ResourceNode $parentNode = null)
414
    {
415
        $repo = $this->getRepository();
416
        $className = $repo->getClassName();
417
        $checker = $this->getAuthorizationChecker();
418
        $resourceTypeName = $this->getResourceTypeName();
419
420
        $qb = $repo->getEntityManager()->createQueryBuilder()
421
            ->select('resource')
422
            ->from($className, 'resource')
423
            ->innerJoin(
424
                'resource.resourceNode',
425
                'node'
426
            )
427
            ->innerJoin('node.resourceLinks', 'links')
428
            ->innerJoin('node.resourceType', 'type')
429
            ->where('type.name = :type')
430
            ->setParameter('type', $resourceTypeName)
431
            ->andWhere('links.course = :course')
432
            ->setParameter('course', $course)
433
        ;
434
435
        $isAdmin = $checker->isGranted('ROLE_ADMIN') ||
436
            $checker->isGranted('ROLE_CURRENT_COURSE_TEACHER');
437
438
        // Do not show deleted resources
439
        $qb
440
            ->andWhere('links.visibility != :visibilityDeleted')
441
            ->setParameter('visibilityDeleted', ResourceLink::VISIBILITY_DELETED)
442
        ;
443
444
        if (false === $isAdmin) {
445
            $qb
446
                ->andWhere('links.visibility = :visibility')
447
                ->setParameter('visibility', ResourceLink::VISIBILITY_PUBLISHED)
448
            ;
449
            // @todo Add start/end visibility restrictions
450
        }
451
452
        if (null !== $parentNode) {
453
            $qb->andWhere('node.parent = :parentNode');
454
            $qb->setParameter('parentNode', $parentNode);
455
        }
456
457
        return $qb;
458
    }
459
460
    /**
461
     * @return QueryBuilder
462
     */
463
    public function getResourcesByCreator(User $user, ResourceNode $parentNode = null)
464
    {
465
        $repo = $this->getRepository();
466
        $className = $repo->getClassName();
467
468
        $qb = $repo->getEntityManager()->createQueryBuilder()
469
            ->select('resource')
470
            ->from($className, 'resource')
471
            ->innerJoin(
472
                'resource.resourceNode',
473
                'node'
474
            )
475
            //->innerJoin('node.resourceLinks', 'links')
476
            //->where('node.resourceType = :type')
477
            //->setParameter('type',$type)
478
            ;
479
        /*$qb
480
            ->andWhere('links.visibility = :visibility')
481
            ->setParameter('visibility', ResourceLink::VISIBILITY_PUBLISHED)
482
        ;*/
483
484
        if (null !== $parentNode) {
485
            $qb->andWhere('node.parent = :parentNode');
486
            $qb->setParameter('parentNode', $parentNode);
487
        }
488
489
        $qb->andWhere('node.creator = :creator');
490
        $qb->setParameter('creator', $user);
491
492
        return $qb;
493
    }
494
495
    public function getResourcesByCourseLinkedToUser(
496
        User $user,
497
        Course $course,
498
        Session $session = null,
499
        CGroup $group = null,
500
        ResourceNode $parentNode = null
501
    ): QueryBuilder {
502
        $qb = $this->getResourcesByCourse($course, $session, $group, $parentNode);
503
504
        $qb->andWhere('links.user = :user OR links.user IS NULL');
505
        $qb->setParameter('user', $user);
506
507
        return $qb;
508
    }
509
510
    public function getResourcesByLinkedUser(User $user, ResourceNode $parentNode = null): QueryBuilder
511
    {
512
        $repo = $this->getRepository();
513
        $className = $repo->getClassName();
514
        $checker = $this->getAuthorizationChecker();
515
        $resourceTypeName = $this->getResourceTypeName();
516
517
        $qb = $repo->getEntityManager()->createQueryBuilder()
518
            ->select('resource')
519
            ->from($className, 'resource')
520
            ->innerJoin(
521
                'resource.resourceNode',
522
                'node'
523
            )
524
            ->innerJoin('node.resourceLinks', 'links')
525
            ->innerJoin('node.resourceType', 'type')
526
            ->where('type.name = :type')
527
            ->setParameter('type', $resourceTypeName)
528
            ->andWhere('links.user = :user')
529
            ->setParameter('user', $user)
530
        ;
531
532
        $isAdmin = $checker->isGranted('ROLE_ADMIN') ||
533
            $checker->isGranted('ROLE_CURRENT_COURSE_TEACHER');
534
535
        // Do not show deleted resources
536
        $qb
537
            ->andWhere('links.visibility != :visibilityDeleted')
538
            ->setParameter('visibilityDeleted', ResourceLink::VISIBILITY_DELETED)
539
        ;
540
541
        if (false === $isAdmin) {
542
            $qb
543
                ->andWhere('links.visibility = :visibility')
544
                ->setParameter('visibility', ResourceLink::VISIBILITY_PUBLISHED)
545
            ;
546
            // @todo Add start/end visibility restrictrions
547
        }
548
549
        if (null !== $parentNode) {
550
            $qb->andWhere('node.parent = :parentNode');
551
            $qb->setParameter('parentNode', $parentNode);
552
        }
553
554
        return $qb;
555
    }
556
557
    public function getResourceFromResourceNode(int $resourceNodeId): ?AbstractResource
558
    {
559
        // Include links
560
        $qb = $this->getRepository()->createQueryBuilder('resource')
561
            ->select('resource')
562
            ->addSelect('node')
563
            ->addSelect('links')
564
            ->innerJoin('resource.resourceNode', 'node')
565
        //    ->innerJoin('node.creator', 'userCreator')
566
            ->innerJoin('node.resourceLinks', 'links')
567
//            ->leftJoin('node.resourceFile', 'file')
568
            ->where('node.id = :id')
569
            ->setParameters(['id' => $resourceNodeId])
570
            //->addSelect('node')
571
        ;
572
573
        return $qb->getQuery()->getOneOrNullResult();
574
    }
575
576
    public function delete(AbstractResource $resource)
577
    {
578
        $children = $resource->getResourceNode()->getChildren();
579
        foreach ($children as $child) {
580
            if ($child->hasResourceFile()) {
581
                $this->getEntityManager()->remove($child->getResourceFile());
582
            }
583
            $resourceNode = $this->getResourceFromResourceNode($child->getId());
584
            if ($resourceNode) {
585
                $this->delete($resourceNode);
586
            }
587
        }
588
        $this->getEntityManager()->remove($resource);
589
        $this->getEntityManager()->flush();
590
    }
591
592
    /**
593
     * Deletes several entities: AbstractResource (Ex: CDocument, CQuiz), ResourceNode,
594
     * ResourceLinks and ResourceFile (including files via Flysystem).
595
     */
596
    public function hardDelete(AbstractResource $resource)
597
    {
598
        $em = $this->getEntityManager();
599
        $em->remove($resource);
600
        $em->flush();
601
    }
602
603
    public function getResourceFileContent(AbstractResource $resource): string
604
    {
605
        try {
606
            $resourceNode = $resource->getResourceNode();
607
608
            return $this->resourceNodeRepository->getResourceNodeFileContent($resourceNode);
609
        } catch (\Throwable $exception) {
610
            throw new FileNotFoundException($resource);
611
        }
612
    }
613
614
    public function getResourceNodeFileContent(ResourceNode $resourceNode): string
615
    {
616
        return $this->resourceNodeRepository->getResourceNodeFileContent($resourceNode);
617
    }
618
619
    public function getResourceNodeFileStream(ResourceNode $resourceNode)
620
    {
621
        return $this->resourceNodeRepository->getResourceNodeFileStream($resourceNode);
622
    }
623
624
    public function getResourceFileDownloadUrl(AbstractResource $resource, array $extraParams = [], $referenceType = null): string
625
    {
626
        $extraParams['mode'] = 'download';
627
628
        return $this->getResourceFileUrl($resource, $extraParams, $referenceType);
629
    }
630
631
    public function getResourceFileUrl(AbstractResource $resource, array $extraParams = [], $referenceType = null): string
632
    {
633
        try {
634
            $resourceNode = $resource->getResourceNode();
635
            if ($resourceNode->hasResourceFile()) {
636
                $params = [
637
                    'tool' => $resourceNode->getResourceType()->getTool(),
638
                    'type' => $resourceNode->getResourceType(),
639
                    'id' => $resourceNode->getId(),
640
                ];
641
642
                if (!empty($extraParams)) {
643
                    $params = array_merge($params, $extraParams);
644
                }
645
646
                $referenceType = $referenceType ?? UrlGeneratorInterface::ABSOLUTE_PATH;
647
648
                return $this->router->generate('chamilo_core_resource_view', $params, $referenceType);
649
            }
650
651
            return '';
652
        } catch (\Throwable $exception) {
653
            throw new FileNotFoundException($resource);
654
        }
655
    }
656
657
    public function getResourceSettings(): Settings
658
    {
659
        return $this->settings;
660
    }
661
662
    public function getTemplates(): Template
663
    {
664
        return $this->templates;
665
    }
666
667
    /**
668
     * @param string $content
669
     *
670
     * @return bool
671
     */
672
    public function updateResourceFileContent(AbstractResource $resource, $content)
673
    {
674
        error_log('updateResourceFileContent');
675
676
        $resourceNode = $resource->getResourceNode();
677
        if ($resourceNode->hasResourceFile()) {
678
            error_log('has file');
679
            $resourceFile = $resourceNode->getResourceFile();
680
            if ($resourceFile) {
0 ignored issues
show
introduced by
$resourceFile is of type Chamilo\CoreBundle\Entity\ResourceFile, thus it always evaluated to true.
Loading history...
681
                error_log('$resourceFile');
682
                $title = $resource->getResourceName();
683
                $handle = tmpfile();
684
                fwrite($handle, $content);
685
                error_log($title);
686
                error_log($content);
687
                $meta = stream_get_meta_data($handle);
688
                $file = new UploadedFile($meta['uri'], $title, 'text/html', null, true);
689
                $resource->setUploadFile($file);
690
691
                return true;
692
            }
693
        }
694
        error_log('false');
695
696
        return false;
697
    }
698
699
    public function setResourceName(AbstractResource $resource, $title)
700
    {
701
        $resource->setResourceName($title);
702
        $resourceNode = $resource->getResourceNode();
703
        $resourceNode->setTitle($title);
704
        if ($resourceNode->hasResourceFile()) {
705
            //$resourceNode->getResourceFile()->getFile()->
706
            //$resourceNode->getResourceFile()->setName($title);
707
            //$resourceFile->setName($title);
708
709
            /*$fileName = $this->getResourceNodeRepository()->getFilename($resourceFile);
710
            error_log('$fileName');
711
            error_log($fileName);
712
            error_log($title);
713
            $this->getResourceNodeRepository()->getFileSystem()->rename($fileName, $title);
714
            $resourceFile->setName($title);
715
            $resourceFile->setOriginalName($title);*/
716
        }
717
    }
718
719
    /**
720
     * Change all links visibility to DELETED.
721
     */
722
    public function softDelete(AbstractResource $resource)
723
    {
724
        $this->setLinkVisibility($resource, ResourceLink::VISIBILITY_DELETED);
725
    }
726
727
    public function setVisibilityPublished(AbstractResource $resource)
728
    {
729
        $this->setLinkVisibility($resource, ResourceLink::VISIBILITY_PUBLISHED);
730
    }
731
732
    public function setVisibilityDeleted(AbstractResource $resource)
733
    {
734
        $this->setLinkVisibility($resource, ResourceLink::VISIBILITY_DELETED);
735
    }
736
737
    public function setVisibilityDraft(AbstractResource $resource)
738
    {
739
        $this->setLinkVisibility($resource, ResourceLink::VISIBILITY_DRAFT);
740
    }
741
742
    public function setVisibilityPending(AbstractResource $resource)
743
    {
744
        $this->setLinkVisibility($resource, ResourceLink::VISIBILITY_PENDING);
745
    }
746
747
    public function createNodeForResource(ResourceInterface $resource, User $creator, ResourceNode $parentNode = null, UploadedFile $file = null): ResourceNode
748
    {
749
        $em = $this->getEntityManager();
750
751
        $resourceType = $this->getResourceType();
752
        $resourceName = $resource->getResourceName();
753
        $extension = $this->slugify->slugify(pathinfo($resourceName, PATHINFO_EXTENSION));
754
755
        if (empty($extension)) {
756
            $slug = $this->slugify->slugify($resourceName);
757
        } else {
758
            $originalExtension = pathinfo($resourceName, PATHINFO_EXTENSION);
759
            $originalBasename = \basename($resourceName, $originalExtension);
760
            $slug = sprintf('%s.%s', $this->slugify->slugify($originalBasename), $originalExtension);
761
        }
762
763
        $resourceNode = new ResourceNode();
764
        $resourceNode
765
            ->setTitle($resourceName)
766
            ->setSlug($slug)
767
            ->setCreator($creator)
768
            ->setResourceType($resourceType)
769
        ;
770
771
        if (null !== $parentNode) {
772
            $resourceNode->setParent($parentNode);
773
        }
774
775
        $resource->setResourceNode($resourceNode);
776
        $em->persist($resourceNode);
777
        $em->persist($resource);
778
779
        if (null !== $file) {
780
            $this->addFile($resource, $file);
781
        }
782
783
        return $resourceNode;
784
    }
785
786
    public function getTotalSpaceByCourse(Course $course, CGroup $group = null, Session $session = null): int
787
    {
788
        $repo = $this->getRepository();
789
790
        $qb = $repo->createQueryBuilder('resource');
791
        $qb
792
            ->select('SUM(file.size) as total')
793
            ->innerJoin('resource.resourceNode', 'node')
794
            ->innerJoin('node.resourceLinks', 'l')
795
            ->innerJoin('node.resourceFile', 'file')
796
            ->where('l.course = :course')
797
            ->andWhere('l.visibility <> :visibility')
798
            ->andWhere('file IS NOT NULL')
799
            ->setParameters(
800
                [
801
                    'course' => $course,
802
                    'visibility' => ResourceLink::VISIBILITY_DELETED,
803
                ]
804
            );
805
806
        if (null === $group) {
807
            $qb->andWhere('l.group IS NULL');
808
        } else {
809
            $qb
810
                ->andWhere('l.group = :group')
811
                ->setParameter('group', $group);
812
        }
813
814
        if (null === $session) {
815
            $qb->andWhere('l.session IS NULL');
816
        } else {
817
            $qb
818
                ->andWhere('l.session = :session')
819
                ->setParameter('session', $session);
820
        }
821
822
        $query = $qb->getQuery();
823
824
        return (int) $query->getSingleScalarResult();
825
    }
826
827
    private function setLinkVisibility(AbstractResource $resource, int $visibility, bool $recursive = true): bool
828
    {
829
        $resourceNode = $resource->getResourceNode();
830
831
        if (null === $resourceNode) {
832
            return false;
833
        }
834
835
        $em = $this->getEntityManager();
836
        if ($recursive) {
837
            $children = $resourceNode->getChildren();
838
            if (!empty($children)) {
839
                /** @var ResourceNode $child */
840
                foreach ($children as $child) {
841
                    $criteria = ['resourceNode' => $child];
842
                    $childDocument = $this->getRepository()->findOneBy($criteria);
843
                    if ($childDocument) {
844
                        $this->setLinkVisibility($childDocument, $visibility);
845
                    }
846
                }
847
            }
848
        }
849
850
        $links = $resourceNode->getResourceLinks();
851
852
        if (!empty($links)) {
853
            /** @var ResourceLink $link */
854
            foreach ($links as $link) {
855
                $link->setVisibility($visibility);
856
                if (ResourceLink::VISIBILITY_DRAFT === $visibility) {
857
                    $editorMask = ResourceNodeVoter::getEditorMask();
858
                    $rights = [];
859
                    $resourceRight = new ResourceRight();
860
                    $resourceRight
861
                        ->setMask($editorMask)
862
                        ->setRole(ResourceNodeVoter::ROLE_CURRENT_COURSE_TEACHER)
863
                        ->setResourceLink($link)
864
                    ;
865
                    $rights[] = $resourceRight;
866
867
                    if (!empty($rights)) {
868
                        $link->setResourceRight($rights);
869
                    }
870
                } else {
871
                    $link->setResourceRight([]);
872
                }
873
                $em->persist($link);
874
            }
875
        }
876
        $em->flush();
877
878
        return true;
879
    }
880
881
    public function isGranted(string $subject, AbstractResource $resource): bool
882
    {
883
        return $this->getAuthorizationChecker()->isGranted($subject, $resource->getResourceNode());
884
    }
885
}
886