Passed
Push — master ( b5ff3f...de0fbe )
by Julito
09:48
created

ResourceRepository::hardDelete()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

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