Passed
Push — master ( ec308f...430c19 )
by Julito
08:35 queued 11s
created

getResourcesByCourseLinkedToUser()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 12
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 4
c 0
b 0
f 0
nc 1
nop 5
dl 0
loc 12
rs 10
1
<?php
2
3
declare(strict_types=1);
4
5
/* For licensing terms, see /license.txt */
6
7
namespace Chamilo\CoreBundle\Repository;
8
9
use Chamilo\CoreBundle\Component\Resource\Settings;
10
use Chamilo\CoreBundle\Component\Resource\Template;
11
use Chamilo\CoreBundle\Entity\AbstractResource;
12
use Chamilo\CoreBundle\Entity\Course;
13
use Chamilo\CoreBundle\Entity\ResourceFile;
14
use Chamilo\CoreBundle\Entity\ResourceInterface;
15
use Chamilo\CoreBundle\Entity\ResourceLink;
16
use Chamilo\CoreBundle\Entity\ResourceNode;
17
use Chamilo\CoreBundle\Entity\ResourceRight;
18
use Chamilo\CoreBundle\Entity\ResourceType;
19
use Chamilo\CoreBundle\Entity\Session;
20
use Chamilo\CoreBundle\Entity\User;
21
use Chamilo\CoreBundle\Security\Authorization\Voter\ResourceNodeVoter;
22
use Chamilo\CoreBundle\Traits\NonResourceRepository;
23
use Chamilo\CoreBundle\Traits\Repository\RepositoryQueryBuilderTrait;
24
use Chamilo\CourseBundle\Entity\CGroup;
25
use DateTime;
26
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
27
use Doctrine\Common\Collections\ArrayCollection;
28
use Doctrine\DBAL\Types\Types;
29
use Doctrine\ORM\EntityRepository;
30
use Doctrine\ORM\QueryBuilder;
31
use Exception;
32
use LogicException;
33
use Symfony\Component\Filesystem\Exception\FileNotFoundException;
34
use Symfony\Component\Form\FormFactory;
35
use Symfony\Component\Form\FormInterface;
36
use Symfony\Component\HttpFoundation\File\UploadedFile;
37
use Throwable;
38
39
/**
40
 * Extends EntityRepository is needed to process settings.
41
 */
42
abstract class ResourceRepository extends ServiceEntityRepository
43
{
44
    use NonResourceRepository;
45
    use RepositoryQueryBuilderTrait;
46
47
    protected Settings $settings;
48
    protected Template $templates;
49
    protected ?ResourceType $resourceType = null;
50
51
    public function setSettings(Settings $settings): self
52
    {
53
        $this->settings = $settings;
54
55
        return $this;
56
    }
57
58
    public function setTemplates(Template $templates): self
59
    {
60
        $this->templates = $templates;
61
62
        return $this;
63
    }
64
65
    public function getResourceSettings(): Settings
66
    {
67
        return $this->settings;
68
    }
69
70
    public function getTemplates(): Template
71
    {
72
        return $this->templates;
73
    }
74
75
    public function getClassName(): string
76
    {
77
        $class = static::class;
78
        //Chamilo\CoreBundle\Repository\Node\IllustrationRepository
79
        $class = str_replace('\\Repository\\', '\\Entity\\', $class);
80
        $class = str_replace('Repository', '', $class);
81
        if (!class_exists($class)) {
82
            throw new Exception(sprintf('Repo: %s not found ', $class));
83
        }
84
85
        return $class;
86
    }
87
88
    public function getCount(QueryBuilder $qb): int
89
    {
90
        $qb->select('count(resource)');
91
        $qb->setMaxResults(1);
92
93
        return (int) $qb->getQuery()->getSingleScalarResult();
94
    }
95
96
    /**
97
     * @return FormInterface
98
     */
99
    public function getForm(FormFactory $formFactory, ResourceInterface $resource = null, array $options = [])
100
    {
101
        $formType = $this->getResourceFormType();
102
103
        if (null === $resource) {
104
            $className = $this->repository->getClassName();
105
            $resource = new $className();
106
        }
107
108
        return $formFactory->create($formType, $resource, $options);
109
    }
110
111
    public function getResourceByResourceNode(ResourceNode $resourceNode): ?ResourceInterface
112
    {
113
        return $this->findOneBy([
114
            'resourceNode' => $resourceNode,
115
        ]);
116
    }
117
118
    public function create(AbstractResource $resource): void
119
    {
120
        $this->getEntityManager()->persist($resource);
121
        $this->getEntityManager()->flush();
122
    }
123
124
    public function update(AbstractResource | User $resource, bool $andFlush = true): void
125
    {
126
        if (!$resource->hasResourceNode()) {
127
            throw new Exception('Resource needs a resource node');
128
        }
129
130
        $resource->getResourceNode()->setUpdatedAt(new DateTime());
131
        $resource->getResourceNode()->setTitle($resource->getResourceName());
132
        $this->getEntityManager()->persist($resource);
133
134
        if ($andFlush) {
135
            $this->getEntityManager()->flush();
136
        }
137
    }
138
139
    public function updateNodeForResource(ResourceInterface $resource): ResourceNode
140
    {
141
        $em = $this->getEntityManager();
142
143
        $resourceNode = $resource->getResourceNode();
144
        $resourceName = $resource->getResourceName();
145
146
        if ($resourceNode->hasResourceFile()) {
147
            $resourceFile = $resourceNode->getResourceFile();
148
            if (null !== $resourceFile) {
149
                $originalName = $resourceFile->getOriginalName();
150
                $originalExtension = pathinfo($originalName, PATHINFO_EXTENSION);
151
152
                //$originalBasename = \basename($resourceName, $originalExtension);
153
                /*$slug = sprintf(
154
                    '%s.%s',
155
                    $this->slugify->slugify($originalBasename),
156
                    $this->slugify->slugify($originalExtension)
157
                );*/
158
159
                $newOriginalName = sprintf('%s.%s', $resourceName, $originalExtension);
160
                $resourceFile->setOriginalName($newOriginalName);
161
162
                $em->persist($resourceFile);
163
            }
164
        }
165
        //$slug = $this->slugify->slugify($resourceName);
166
167
        $resourceNode->setTitle($resourceName);
168
        //$resourceNode->setSlug($slug);
169
170
        $em->persist($resourceNode);
171
        $em->persist($resource);
172
173
        $em->flush();
174
175
        return $resourceNode;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $resourceNode could return the type null which is incompatible with the type-hinted return Chamilo\CoreBundle\Entity\ResourceNode. Consider adding an additional type-check to rule them out.
Loading history...
176
    }
177
178
    public function findCourseResourceByTitle(
179
        string $title,
180
        ResourceNode $parentNode,
181
        Course $course,
182
        Session $session = null,
183
        CGroup $group = null
184
    ): ?ResourceInterface {
185
        $qb = $this->getResourcesByCourse($course, $session, $group, $parentNode);
186
        $this->addTitleQueryBuilder($title, $qb);
187
        $qb->setMaxResults(1);
188
189
        return $qb->getQuery()->getOneOrNullResult();
190
    }
191
192
    /**
193
     * @return ResourceInterface[]
194
     */
195
    public function findCourseResourcesByTitle(
196
        string $title,
197
        ResourceNode $parentNode,
198
        Course $course,
199
        Session $session = null,
200
        CGroup $group = null
201
    ) {
202
        $qb = $this->getResourcesByCourse($course, $session, $group, $parentNode);
203
        $this->addTitleQueryBuilder($title, $qb);
204
205
        return $qb->getQuery()->getResult();
206
    }
207
208
    /**
209
     * @todo clean path
210
     */
211
    public function addFileFromPath(ResourceInterface $resource, string $fileName, string $path, bool $flush = true): ?ResourceFile
212
    {
213
        if (!empty($path) && file_exists($path) && !is_dir($path)) {
214
            $mimeType = mime_content_type($path);
215
            $file = new UploadedFile($path, $fileName, $mimeType, null, true);
216
217
            return $this->addFile($resource, $file, '', $flush);
218
        }
219
220
        return null;
221
    }
222
223
    public function createTempUploadedFile(string $fileName, string $mimeType, string $content): UploadedFile
224
    {
225
        /*$handle = tmpfile();
226
        fwrite($handle, $content);
227
        $meta = stream_get_meta_data($handle);*/
228
229
        $tmpFilename = tempnam(sys_get_temp_dir(), 'resource_file_');
230
        file_put_contents($tmpFilename, $content);
231
232
        return new UploadedFile($tmpFilename, $fileName, $mimeType, null, true);
233
    }
234
235
    public function addFileFromString(ResourceInterface $resource, string $fileName, string $mimeType, string $content, bool $flush = true): ?ResourceFile
236
    {
237
        $file = $this->createTempUploadedFile($fileName, $mimeType, $content);
238
239
        return $this->addFile($resource, $file, '', $flush);
240
    }
241
242
    public function addFileFromFileRequest(ResourceInterface $resource, string $fileKey, bool $flush = true): ?ResourceFile
243
    {
244
        $request = $this->getRequest();
245
        if ($request->files->has($fileKey)) {
246
            $file = $request->files->get($fileKey);
247
            if (null !== $file) {
248
                $resourceFile = $this->addFile($resource, $file);
249
                if ($flush) {
250
                    $this->getEntityManager()->flush();
251
                }
252
253
                return $resourceFile;
254
            }
255
        }
256
257
        return null;
258
    }
259
260
    public function addFile(ResourceInterface $resource, UploadedFile $file, string $description = '', bool $flush = false): ?ResourceFile
261
    {
262
        $resourceNode = $resource->getResourceNode();
263
264
        if (null === $resourceNode) {
265
            throw new LogicException('Resource node is null');
266
        }
267
268
        $resourceFile = $resourceNode->getResourceFile();
269
        if (null === $resourceFile) {
270
            $resourceFile = new ResourceFile();
271
        }
272
273
        $em = $this->getEntityManager();
274
        $resourceFile
275
            ->setFile($file)
276
            ->setDescription($description)
277
            ->setName($resource->getResourceName())
278
            ->setResourceNode($resourceNode)
279
        ;
280
        $em->persist($resourceFile);
281
        $resourceNode->setResourceFile($resourceFile);
282
        $em->persist($resourceNode);
283
284
        if ($flush) {
285
            $em->flush();
286
        }
287
288
        return $resourceFile;
289
    }
290
291
    public function getResourceType(): ?ResourceType
292
    {
293
        $name = $this->getResourceTypeName();
294
        $repo = $this->getEntityManager()->getRepository(ResourceType::class);
295
        $this->resourceType = $repo->findOneBy([
296
            'name' => $name,
297
        ]);
298
299
        return $this->resourceType;
300
    }
301
302
    public function getResourceTypeName(): string
303
    {
304
        return $this->toolChain->getResourceTypeNameFromRepository(static::class);
0 ignored issues
show
Bug introduced by
The method getResourceTypeNameFromRepository() does not exist on null. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

304
        return $this->toolChain->/** @scrutinizer ignore-call */ getResourceTypeNameFromRepository(static::class);

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
305
    }
306
307
    public function addVisibilityQueryBuilder(QueryBuilder $qb = null): QueryBuilder
308
    {
309
        $qb = $this->getOrCreateQueryBuilder($qb);
310
311
        $checker = $this->getAuthorizationChecker();
312
        $isAdmin =
313
            $checker->isGranted('ROLE_ADMIN') ||
314
            $checker->isGranted('ROLE_CURRENT_COURSE_TEACHER');
315
316
        // Do not show deleted resources.
317
        $qb
318
            ->andWhere('links.visibility != :visibilityDeleted')
319
            ->setParameter('visibilityDeleted', ResourceLink::VISIBILITY_DELETED, Types::INTEGER)
320
        ;
321
322
        if (!$isAdmin) {
323
            $qb
324
                ->andWhere('links.visibility = :visibility')
325
                ->setParameter('visibility', ResourceLink::VISIBILITY_PUBLISHED, Types::INTEGER)
326
            ;
327
            // @todo Add start/end visibility restrictions.
328
        }
329
330
        return $qb;
331
    }
332
333
    public function addCourseQueryBuilder(Course $course, QueryBuilder $qb): QueryBuilder
334
    {
335
        $qb
336
            ->andWhere('links.course = :course')
337
            ->setParameter('course', $course)
338
        ;
339
340
        return $qb;
341
    }
342
343
    public function addCourseSessionGroupQueryBuilder(Course $course, Session $session = null, CGroup $group = null, QueryBuilder $qb = null): QueryBuilder
344
    {
345
        $reflectionClass = $this->getClassMetadata()->getReflectionClass();
346
347
        // Check if this resource type requires to load the base course resources when using a session
348
        $loadBaseSessionContent = $reflectionClass->hasProperty('loadCourseResourcesInSession');
349
350
        $this->addCourseQueryBuilder($course, $qb);
351
352
        if (null === $session) {
353
            $qb->andWhere(
354
                $qb->expr()->orX(
0 ignored issues
show
Bug introduced by
The method expr() does not exist on null. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

354
                $qb->/** @scrutinizer ignore-call */ 
355
                     expr()->orX(

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
355
                    $qb->expr()->isNull('links.session'),
356
                    $qb->expr()->eq('links.session', 0)
357
                )
358
            );
359
        } elseif ($loadBaseSessionContent) {
360
            // Load course base content.
361
            $qb->andWhere('links.session = :session OR links.session IS NULL');
362
            $qb->setParameter('session', $session);
363
        } else {
364
            // Load only session resources.
365
            $qb->andWhere('links.session = :session');
366
            $qb->setParameter('session', $session);
367
        }
368
369
        if (null === $group) {
370
            $qb->andWhere(
371
                $qb->expr()->orX(
372
                    $qb->expr()->isNull('links.group'),
373
                    $qb->expr()->eq('links.group', 0)
374
                )
375
            );
376
        } else {
377
            $qb->andWhere('links.group = :group');
378
            $qb->setParameter('group', $group);
379
        }
380
381
        return $qb;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $qb could return the type null which is incompatible with the type-hinted return Doctrine\ORM\QueryBuilder. Consider adding an additional type-check to rule them out.
Loading history...
382
    }
383
384
    public function getResources(ResourceNode $parentNode = null): QueryBuilder
385
    {
386
        $resourceTypeName = $this->getResourceTypeName();
387
388
        $qb = $this->createQueryBuilder('resource')
389
            ->select('resource')
390
            ->innerJoin('resource.resourceNode', 'node')
391
            ->innerJoin('node.resourceLinks', 'links')
392
            ->innerJoin('node.resourceType', 'type')
393
            ->leftJoin('node.resourceFile', 'file')
394
            ->where('type.name = :type')
395
            ->setParameter('type', $resourceTypeName, Types::STRING)
396
            ->addSelect('node')
397
            ->addSelect('links')
398
            ->addSelect('type')
399
            ->addSelect('file')
400
        ;
401
402
        if (null !== $parentNode) {
403
            $qb->andWhere('node.parent = :parentNode');
404
            $qb->setParameter('parentNode', $parentNode);
405
        }
406
407
        return $qb;
408
    }
409
410
    public function getResourcesByCourse(Course $course, Session $session = null, CGroup $group = null, ResourceNode $parentNode = null): QueryBuilder
411
    {
412
        $qb = $this->getResources($parentNode);
413
        $this->addVisibilityQueryBuilder($qb);
414
        $this->addCourseSessionGroupQueryBuilder($course, $session, $group, $qb);
415
416
        return $qb;
417
    }
418
419
    /**
420
     * Get resources only from the base course.
421
     */
422
    public function getResourcesByCourseOnly(Course $course, ResourceNode $parentNode = null): QueryBuilder
423
    {
424
        $qb = $this->getResources($parentNode);
425
        $this->addCourseQueryBuilder($course, $qb);
426
        $this->addVisibilityQueryBuilder($qb);
427
428
        return $qb;
429
    }
430
431
    public function getResourceByCreatorFromTitle(
432
        string $title,
433
        User $user,
434
        ResourceNode $parentNode
435
    ): ?ResourceInterface {
436
        $qb = $this->getResourcesByCreator($user, $parentNode);
437
        $this->addTitleQueryBuilder($title, $qb);
438
        $qb->setMaxResults(1);
439
440
        return $qb->getQuery()->getOneOrNullResult();
441
    }
442
443
    public function getResourcesByCreator(User $user, ResourceNode $parentNode = null): QueryBuilder
444
    {
445
        $qb = $this->createQueryBuilder('resource')
446
            ->select('resource')
447
            ->innerJoin('resource.resourceNode', 'node')
448
        ;
449
450
        if (null !== $parentNode) {
451
            $qb->andWhere('node.parent = :parentNode');
452
            $qb->setParameter('parentNode', $parentNode);
453
        }
454
455
        $this->addCreatorQueryBuilder($user, $qb);
456
457
        return $qb;
458
    }
459
460
    public function getResourcesByCourseLinkedToUser(
461
        User $user,
462
        Course $course,
463
        Session $session = null,
464
        CGroup $group = null,
465
        ResourceNode $parentNode = null
466
    ): QueryBuilder {
467
        $qb = $this->getResourcesByCourse($course, $session, $group, $parentNode);
468
        $qb->andWhere('node.creator = :user OR (links.user = :user OR links.user IS NULL)');
469
        $qb->setParameter('user', $user);
470
471
        return $qb;
472
    }
473
474
    public function getResourcesByLinkedUser(User $user, ResourceNode $parentNode = null): QueryBuilder
475
    {
476
        $qb = $this->getResources($parentNode);
477
        $qb
478
            ->andWhere('links.user = :user')
479
            ->setParameter('user', $user)
480
        ;
481
482
        $this->addVisibilityQueryBuilder($qb);
483
484
        return $qb;
485
    }
486
487
    public function getResourceFromResourceNode(int $resourceNodeId): ?ResourceInterface
488
    {
489
        $qb = $this->createQueryBuilder('resource')
490
            ->select('resource')
491
            ->addSelect('node')
492
            ->addSelect('links')
493
            ->innerJoin('resource.resourceNode', 'node')
494
        //    ->innerJoin('node.creator', 'userCreator')
495
            ->innerJoin('node.resourceLinks', 'links')
496
//            ->leftJoin('node.resourceFile', 'file')
497
            ->where('node.id = :id')
498
            ->setParameters([
499
                'id' => $resourceNodeId,
500
            ])
501
            //->addSelect('node')
502
        ;
503
504
        return $qb->getQuery()->getOneOrNullResult();
505
    }
506
507
    public function delete(ResourceInterface $resource): void
508
    {
509
        $children = $resource->getResourceNode()->getChildren();
510
        foreach ($children as $child) {
511
            if ($child->hasResourceFile()) {
512
                $this->getEntityManager()->remove($child->getResourceFile());
513
            }
514
            $resourceNode = $this->getResourceFromResourceNode($child->getId());
515
            if (null !== $resourceNode) {
516
                $this->delete($resourceNode);
517
            }
518
        }
519
        $this->getEntityManager()->remove($resource);
520
        $this->getEntityManager()->flush();
521
    }
522
523
    /**
524
     * Deletes several entities: AbstractResource (Ex: CDocument, CQuiz), ResourceNode,
525
     * ResourceLinks and ResourceFile (including files via Flysystem).
526
     */
527
    public function hardDelete(AbstractResource $resource): void
528
    {
529
        $em = $this->getEntityManager();
530
        $em->remove($resource);
531
        $em->flush();
532
    }
533
534
    public function getResourceFileContent(AbstractResource $resource): string
535
    {
536
        try {
537
            $resourceNode = $resource->getResourceNode();
538
539
            return $this->resourceNodeRepository->getResourceNodeFileContent($resourceNode);
0 ignored issues
show
Bug introduced by
The method getResourceNodeFileContent() does not exist on null. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

539
            return $this->resourceNodeRepository->/** @scrutinizer ignore-call */ getResourceNodeFileContent($resourceNode);

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
540
        } catch (Throwable $throwable) {
541
            throw new FileNotFoundException($resource->getResourceName());
542
        }
543
    }
544
545
    public function getResourceNodeFileContent(ResourceNode $resourceNode): string
546
    {
547
        return $this->resourceNodeRepository->getResourceNodeFileContent($resourceNode);
548
    }
549
550
    /**
551
     * @return false|resource
552
     */
553
    public function getResourceNodeFileStream(ResourceNode $resourceNode)
554
    {
555
        return $this->resourceNodeRepository->getResourceNodeFileStream($resourceNode);
556
    }
557
558
    public function getResourceFileDownloadUrl(AbstractResource $resource, array $extraParams = [], ?int $referenceType = null): string
559
    {
560
        $extraParams['mode'] = 'download';
561
562
        return $this->getResourceFileUrl($resource, $extraParams, $referenceType);
563
    }
564
565
    public function getResourceFileUrl(AbstractResource $resource, array $extraParams = [], ?int $referenceType = null): string
566
    {
567
        return $this->getResourceNodeRepository()->getResourceFileUrl(
568
            $resource->getResourceNode(),
569
            $extraParams,
570
            $referenceType
571
        );
572
    }
573
574
    /**
575
     * @return bool
576
     */
577
    public function updateResourceFileContent(AbstractResource $resource, string $content)
578
    {
579
        error_log('updateResourceFileContent');
580
581
        $resourceNode = $resource->getResourceNode();
582
        if ($resourceNode->hasResourceFile()) {
583
            $resourceNode->setContent($content);
584
            $resourceNode->getResourceFile()->setSize(\strlen($content));
585
        }
586
587
        return false;
588
    }
589
590
    public function setResourceName(AbstractResource $resource, $title): void
591
    {
592
        if (!empty($title)) {
593
            $resource->setResourceName($title);
594
            $resourceNode = $resource->getResourceNode();
595
            $resourceNode->setTitle($title);
596
        }
597
598
        //if ($resourceNode->hasResourceFile()) {
599
            //$resourceNode->getResourceFile()->getFile()->
600
            //$resourceNode->getResourceFile()->setName($title);
601
            //$resourceFile->setName($title);
602
603
            /*$fileName = $this->getResourceNodeRepository()->getFilename($resourceFile);
604
            error_log('$fileName');
605
            error_log($fileName);
606
            error_log($title);
607
            $this->getResourceNodeRepository()->getFileSystem()->rename($fileName, $title);
608
            $resourceFile->setName($title);
609
            $resourceFile->setOriginalName($title);*/
610
        //}
611
    }
612
613
    /**
614
     * Change all links visibility to DELETED.
615
     */
616
    public function softDelete(AbstractResource $resource): void
617
    {
618
        $this->setLinkVisibility($resource, ResourceLink::VISIBILITY_DELETED);
619
    }
620
621
    public function setVisibilityPublished(AbstractResource $resource): void
622
    {
623
        $this->setLinkVisibility($resource, ResourceLink::VISIBILITY_PUBLISHED);
624
    }
625
626
    public function setVisibilityDeleted(AbstractResource $resource): void
627
    {
628
        $this->setLinkVisibility($resource, ResourceLink::VISIBILITY_DELETED);
629
    }
630
631
    public function setVisibilityDraft(AbstractResource $resource): void
632
    {
633
        $this->setLinkVisibility($resource, ResourceLink::VISIBILITY_DRAFT);
634
    }
635
636
    public function setVisibilityPending(AbstractResource $resource): void
637
    {
638
        $this->setLinkVisibility($resource, ResourceLink::VISIBILITY_PENDING);
639
    }
640
641
    public function addResourceNode(ResourceInterface $resource, User $creator, ResourceInterface $parentResource): ResourceNode
642
    {
643
        $parentResourceNode = $parentResource->getResourceNode();
644
645
        return $this->createNodeForResource($resource, $creator, $parentResourceNode);
646
    }
647
648
    /**
649
     * @todo remove this function and merge it with addResourceNode()
650
     */
651
    public function createNodeForResource(ResourceInterface $resource, User $creator, ResourceNode $parentNode, UploadedFile $file = null): ResourceNode
652
    {
653
        $em = $this->getEntityManager();
654
655
        $resourceType = $this->getResourceType();
656
        $resourceName = $resource->getResourceName();
657
        $extension = $this->slugify->slugify(pathinfo($resourceName, PATHINFO_EXTENSION));
0 ignored issues
show
Bug introduced by
The method slugify() does not exist on null. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

657
        /** @scrutinizer ignore-call */ 
658
        $extension = $this->slugify->slugify(pathinfo($resourceName, PATHINFO_EXTENSION));

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
658
659
        if (empty($extension)) {
660
            $slug = $this->slugify->slugify($resourceName);
661
        } else {
662
            $originalExtension = pathinfo($resourceName, PATHINFO_EXTENSION);
663
            $originalBasename = basename($resourceName, $originalExtension);
664
            $slug = sprintf('%s.%s', $this->slugify->slugify($originalBasename), $originalExtension);
665
        }
666
667
        $resourceNode = new ResourceNode();
668
        $resourceNode
669
            ->setTitle($resourceName)
670
            ->setSlug($slug)
671
            ->setCreator($creator)
672
            ->setResourceType($resourceType)
673
        ;
674
675
        if (null !== $parentNode) {
676
            $resourceNode->setParent($parentNode);
677
        }
678
679
        $resource->setResourceNode($resourceNode);
680
        $em->persist($resourceNode);
681
        $em->persist($resource);
682
683
        if (null !== $file) {
684
            $this->addFile($resource, $file);
685
        }
686
687
        return $resourceNode;
688
    }
689
690
    /**
691
     * This is only used during installation for the special nodes (admin and AccessUrl).
692
     */
693
    public function createNodeForResourceWithNoParent(ResourceInterface $resource, User $creator): ResourceNode
694
    {
695
        $em = $this->getEntityManager();
696
697
        $resourceType = $this->getResourceType();
698
        $resourceName = $resource->getResourceName();
699
        $slug = $this->slugify->slugify($resourceName);
700
        $resourceNode = new ResourceNode();
701
        $resourceNode
702
            ->setTitle($resourceName)
703
            ->setSlug($slug)
704
            ->setCreator($creator)
705
            ->setResourceType($resourceType)
706
        ;
707
        $resource->setResourceNode($resourceNode);
708
        $em->persist($resourceNode);
709
        $em->persist($resource);
710
711
        return $resourceNode;
712
    }
713
714
    public function getTotalSpaceByCourse(Course $course, CGroup $group = null, Session $session = null): int
715
    {
716
        $qb = $this->createQueryBuilder('resource');
717
        $qb
718
            ->select('SUM(file.size) as total')
719
            ->innerJoin('resource.resourceNode', 'node')
720
            ->innerJoin('node.resourceLinks', 'l')
721
            ->innerJoin('node.resourceFile', 'file')
722
            ->where('l.course = :course')
723
            ->andWhere('l.visibility <> :visibility')
724
            ->andWhere('file IS NOT NULL')
725
            ->setParameters(
726
                [
727
                    'course' => $course,
728
                    'visibility' => ResourceLink::VISIBILITY_DELETED,
729
                ]
730
            )
731
        ;
732
733
        if (null === $group) {
734
            $qb->andWhere('l.group IS NULL');
735
        } else {
736
            $qb
737
                ->andWhere('l.group = :group')
738
                ->setParameter('group', $group)
739
            ;
740
        }
741
742
        if (null === $session) {
743
            $qb->andWhere('l.session IS NULL');
744
        } else {
745
            $qb
746
                ->andWhere('l.session = :session')
747
                ->setParameter('session', $session)
748
            ;
749
        }
750
751
        $query = $qb->getQuery();
752
753
        return (int) $query->getSingleScalarResult();
754
    }
755
756
    public function addTitleDecoration(AbstractResource $resource, Course $course, Session $session = null): string
757
    {
758
        if (null === $session) {
759
            return '';
760
        }
761
762
        $link = $resource->getFirstResourceLinkFromCourseSession($course, $session);
763
        if (null === $link) {
764
            return '';
765
        }
766
767
        return '<img title="'.$session->getName().'" src="/img/icons/22/star.png" />';
768
    }
769
770
    public function isGranted(string $subject, AbstractResource $resource): bool
771
    {
772
        return $this->getAuthorizationChecker()->isGranted($subject, $resource->getResourceNode());
773
    }
774
775
    /**
776
     * Changes the visibility of the children that matches the exact same link.
777
     */
778
    public function copyVisibilityToChildren(ResourceNode $resourceNode, ResourceLink $link): bool
779
    {
780
        $children = $resourceNode->getChildren();
781
782
        if (0 === $children->count()) {
783
            return false;
784
        }
785
786
        $em = $this->getEntityManager();
787
788
        /** @var ResourceNode $child */
789
        foreach ($children as $child) {
790
            if ($child->getChildren()->count() > 0) {
791
                $this->copyVisibilityToChildren($child, $link);
792
            }
793
794
            $links = $child->getResourceLinks();
795
            foreach ($links as $linkItem) {
796
                if ($linkItem->getUser() === $link->getUser() &&
797
                    $linkItem->getSession() === $link->getSession() &&
798
                    $linkItem->getCourse() === $link->getCourse() &&
799
                    $linkItem->getUserGroup() === $link->getUserGroup()
800
                ) {
801
                    $linkItem->setVisibility($link->getVisibility());
802
                    $em->persist($linkItem);
803
                }
804
            }
805
        }
806
807
        $em->flush();
808
809
        return true;
810
    }
811
812
    public function saveUpload(UploadedFile $file): ResourceInterface
813
    {
814
        throw new Exception('Implement saveUpload');
815
    }
816
817
    public function getResourceFormType(): string
818
    {
819
        throw new Exception('Implement getResourceFormType');
820
    }
821
822
    protected function addTitleQueryBuilder(?string $title, QueryBuilder $qb = null): QueryBuilder
823
    {
824
        $qb = $this->getOrCreateQueryBuilder($qb);
825
        if (null === $title) {
826
            return $qb;
827
        }
828
829
        $qb
830
            ->andWhere('node.title = :title')
831
            ->setParameter('title', $title)
832
        ;
833
834
        return $qb;
835
    }
836
837
    protected function addCreatorQueryBuilder(?User $user, QueryBuilder $qb = null): QueryBuilder
838
    {
839
        $qb = $this->getOrCreateQueryBuilder($qb);
840
        if (null === $user) {
841
            return $qb;
842
        }
843
844
        $qb
845
            ->andWhere('node.creator = :creator')
846
            ->setParameter('creator', $user)
847
        ;
848
849
        return $qb;
850
    }
851
852
    private function setLinkVisibility(AbstractResource $resource, int $visibility, bool $recursive = true): bool
853
    {
854
        $resourceNode = $resource->getResourceNode();
855
856
        if (null === $resourceNode) {
857
            return false;
858
        }
859
860
        $em = $this->getEntityManager();
861
        if ($recursive) {
862
            $children = $resourceNode->getChildren();
863
            if (!empty($children)) {
864
                /** @var ResourceNode $child */
865
                foreach ($children as $child) {
866
                    $criteria = [
867
                        'resourceNode' => $child,
868
                    ];
869
                    $childDocument = $this->findOneBy($criteria);
870
                    if ($childDocument) {
871
                        $this->setLinkVisibility($childDocument, $visibility);
872
                    }
873
                }
874
            }
875
        }
876
877
        $links = $resourceNode->getResourceLinks();
878
879
        if (!empty($links)) {
880
            /** @var ResourceLink $link */
881
            foreach ($links as $link) {
882
                $link->setVisibility($visibility);
883
                if (ResourceLink::VISIBILITY_DRAFT === $visibility) {
884
                    $editorMask = ResourceNodeVoter::getEditorMask();
885
                    //$rights = [];
886
                    $resourceRight = new ResourceRight();
887
                    $resourceRight
888
                        ->setMask($editorMask)
889
                        ->setRole(ResourceNodeVoter::ROLE_CURRENT_COURSE_TEACHER)
890
                        ->setResourceLink($link)
891
                    ;
892
                    $link->addResourceRight($resourceRight);
893
                } else {
894
                    $link->setResourceRights(new ArrayCollection());
895
                }
896
                $em->persist($link);
897
            }
898
        }
899
        $em->flush();
900
901
        return true;
902
    }
903
}
904