Passed
Push — master ( 75b021...57eded )
by Julito
07:40
created

ResourceRepository::copyVisibilityToChildren()   B

Complexity

Conditions 9
Paths 8

Size

Total Lines 32
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Importance

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