Passed
Push — master ( cc68cc...50453a )
by Julito
09:11
created

ResourceRepository::updateResource()   B

Complexity

Conditions 7
Paths 2

Size

Total Lines 41
Code Lines 26

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 7
eloc 26
c 0
b 0
f 0
nc 2
nop 1
dl 0
loc 41
rs 8.5706
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) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $links of type Chamilo\CoreBundle\Entity\ResourceLink[] is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

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