Completed
Push — master ( cf4f4c...f3c478 )
by Julito
36:36
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
/* For licensing terms, see /license.txt */
3
4
namespace Chamilo\CoreBundle\Repository;
5
6
use Chamilo\CoreBundle\Entity\Course;
7
use Chamilo\CoreBundle\Entity\Resource\AbstractResource;
8
use Chamilo\CoreBundle\Entity\Resource\ResourceFile;
9
use Chamilo\CoreBundle\Entity\Resource\ResourceLink;
10
use Chamilo\CoreBundle\Entity\Resource\ResourceNode;
11
use Chamilo\CoreBundle\Entity\Resource\ResourceRight;
12
use Chamilo\CoreBundle\Entity\Resource\ResourceType;
13
use Chamilo\CoreBundle\Entity\Session;
14
use Chamilo\CoreBundle\Entity\Tool;
15
use Chamilo\CoreBundle\Entity\Usergroup;
16
use Chamilo\CoreBundle\Security\Authorization\Voter\ResourceNodeVoter;
17
use Chamilo\CourseBundle\Entity\CGroupInfo;
18
use Chamilo\UserBundle\Entity\User;
19
use Doctrine\ORM\EntityManager;
20
use Doctrine\ORM\Query\Expr\Join;
21
use League\Flysystem\FilesystemInterface;
22
use League\Flysystem\MountManager;
23
use Sylius\Bundle\ResourceBundle\Doctrine\ORM\EntityRepository;
24
use Symfony\Component\HttpFoundation\File\UploadedFile;
25
use Symfony\Component\Routing\RouterInterface;
26
27
/**
28
 * Class ResourceRepository.
29
 */
30
class ResourceRepository extends EntityRepository
31
{
32
    /**
33
     * @var EntityRepository
34
     */
35
    protected $repository;
36
37
    /**
38
     * @var FilesystemInterface
39
     */
40
    protected $fs;
41
42
    /**
43
     * @var EntityManager
44
     */
45
    protected $entityManager;
46
47
    /**
48
     * The entity class FQN.
49
     *
50
     * @var string
51
     */
52
    protected $className;
53
54
    /** @var RouterInterface */
55
    protected $router;
56
57
    protected $resourceNodeRepository;
58
59
    /**
60
     * ResourceRepository constructor.
61
     *
62
     * @param EntityManager   $entityManager
63
     * @param MountManager    $mountManager
64
     * @param RouterInterface $router
65
     * @param string          $className
66
     */
67
    public function __construct(EntityManager $entityManager, MountManager $mountManager, RouterInterface $router, string $className)
68
    {
69
        $this->repository = $entityManager->getRepository($className);
70
        // Flysystem mount name is saved in config/packages/oneup_flysystem.yaml
71
        $this->fs = $mountManager->getFilesystem('resources_fs');
72
        $this->router = $router;
73
        $this->resourceNodeRepository = $entityManager->getRepository('ChamiloCoreBundle:Resource\ResourceNode');
74
    }
75
76
    /**
77
     * @return mixed
78
     */
79
    public function create()
80
    {
81
        return new $this->className();
82
    }
83
84
    /**
85
     * @return EntityRepository
86
     */
87
    public function getResourceNodeRepository()
88
    {
89
        return $this->resourceNodeRepository;
90
    }
91
92
    /**
93
     * @return FilesystemInterface
94
     */
95
    public function getFileSystem()
96
    {
97
        return $this->fs;
98
    }
99
100
    /**
101
     * @return EntityManager
102
     */
103
    public function getEntityManager(): EntityManager
104
    {
105
        return $this->getRepository()->getEntityManager();
106
    }
107
108
    /**
109
     * @return EntityRepository
110
     */
111
    public function getRepository()
112
    {
113
        return $this->repository;
114
    }
115
116
    /**
117
     * @param mixed $id
118
     * @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...
119
     * @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...
120
     *
121
     * @return AbstractResource|null
122
     */
123
    public function find($id, $lockMode = null, $lockVersion = null)
124
    {
125
        return $this->getRepository()->find($id);
126
    }
127
128
    /**
129
     * @param array      $criteria
130
     * @param array|null $orderBy
131
     *
132
     * @return AbstractResource
133
     */
134
    public function findOneBy(array $criteria, array $orderBy = null)
135
    {
136
        return $this->getRepository()->findOneBy($criteria, $orderBy);
137
    }
138
139
    /**
140
     * @param ResourceNode $resourceNode
141
     * @param UploadedFile $file
142
     *
143
     * @return ResourceFile
144
     */
145
    public function addFile(ResourceNode $resourceNode, UploadedFile $file)
146
    {
147
        $resourceFile = $resourceNode->getResourceFile();
148
        if ($resourceFile === null) {
149
            $resourceFile = new ResourceFile();
150
        }
151
152
        $em = $this->getEntityManager();
153
154
        $resourceFile->setFile($file);
155
        $resourceFile->setName($resourceNode->getName());
156
        $em->persist($resourceFile);
157
        $resourceNode->setResourceFile($resourceFile);
158
        $em->persist($resourceNode);
159
        $em->flush();
160
161
        return $resourceFile;
162
    }
163
164
    /**
165
     * Creates a ResourceNode.
166
     *
167
     * @param AbstractResource $resource
168
     * @param User             $creator
169
     * @param AbstractResource $parent
170
     *
171
     * @return ResourceNode
172
     */
173
    public function addResourceNode(
174
        AbstractResource $resource,
175
        User $creator,
176
        AbstractResource $parent = null
177
    ): ResourceNode {
178
        $em = $this->getEntityManager();
179
180
        $resourceType = $this->getResourceType();
181
182
        $resourceNode = new ResourceNode();
183
        $resourceNode
184
            ->setName($resource->getResourceName())
185
            ->setCreator($creator)
186
            ->setResourceType($resourceType)
187
        ;
188
189
        if ($parent !== null) {
190
            $resourceNode->setParent($parent->getResourceNode());
191
        }
192
193
        $resource->setResourceNode($resourceNode);
194
195
        $em->persist($resourceNode);
196
        $em->persist($resource);
197
        $em->flush();
198
199
        return $resourceNode;
200
    }
201
202
    public function addResourceToCourse(AbstractResource $resource, $visibility, User $creator, Course $course, $session = null, $group = null)
203
    {
204
        $node = $this->addResourceNode($resource, $creator, $course);
205
        $this->addResourceNodeToCourse($node, $visibility, $course, $session, $group);
206
    }
207
208
    /**
209
     * @param ResourceNode $resourceNode
210
     * @param int          $visibility
211
     * @param Course       $course
212
     * @param Session      $session
213
     * @param CGroupInfo   $group
214
     */
215
    public function addResourceNodeToCourse(ResourceNode $resourceNode, $visibility, $course, $session, $group): void
216
    {
217
        $visibility = (int) $visibility;
218
        if (empty($visibility)) {
219
            $visibility = ResourceLink::VISIBILITY_PUBLISHED;
220
        }
221
222
        $link = new ResourceLink();
223
        $link
224
            ->setCourse($course)
225
            ->setSession($session)
226
            ->setGroup($group)
227
            //->setUser($toUser)
228
            ->setResourceNode($resourceNode)
229
            ->setVisibility($visibility)
230
        ;
231
232
        $rights = [];
233
        switch ($visibility) {
234
            case ResourceLink::VISIBILITY_PENDING:
235
            case ResourceLink::VISIBILITY_DRAFT:
236
                $editorMask = ResourceNodeVoter::getEditorMask();
237
                $resourceRight = new ResourceRight();
238
                $resourceRight
239
                    ->setMask($editorMask)
240
                    ->setRole(ResourceNodeVoter::ROLE_CURRENT_COURSE_TEACHER)
241
                ;
242
                $rights[] = $resourceRight;
243
                break;
244
        }
245
246
        if (!empty($rights)) {
247
            foreach ($rights as $right) {
248
                $link->addResourceRight($right);
249
            }
250
        }
251
252
        $em = $this->getEntityManager();
253
        $em->persist($link);
254
        $em->flush();
255
    }
256
257
    /**
258
     * @return ResourceType
259
     */
260
    public function getResourceType()
261
    {
262
        $em = $this->getEntityManager();
263
        $entityName = $this->getRepository()->getClassMetadata()->getReflectionClass()->getShortName();
264
265
        return $em->getRepository('ChamiloCoreBundle:Resource\ResourceType')->findOneBy(
266
            ['name' => $entityName]
267
        );
268
    }
269
270
    /**
271
     * @param ResourceNode $resourceNode
272
     *
273
     * @return ResourceLink
274
     */
275
    public function addResourceToMe(ResourceNode $resourceNode): ResourceLink
276
    {
277
        $resourceLink = new ResourceLink();
278
        $resourceLink
279
            ->setResourceNode($resourceNode)
280
            ->setPrivate(true);
0 ignored issues
show
Bug introduced by
The method setPrivate() does not exist on Chamilo\CoreBundle\Entity\Resource\ResourceLink. ( Ignorable by Annotation )

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

280
            ->/** @scrutinizer ignore-call */ setPrivate(true);

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...
281
282
        $this->getEntityManager()->persist($resourceLink);
283
        $this->getEntityManager()->flush();
284
285
        return $resourceLink;
286
    }
287
288
    /**
289
     * @param ResourceNode  $resourceNode
290
     * @param ResourceRight $right
291
     *
292
     * @return ResourceLink
293
     */
294
    public function addResourceToEveryone(ResourceNode $resourceNode, ResourceRight $right): ResourceLink
295
    {
296
        $resourceLink = new ResourceLink();
297
        $resourceLink
298
            ->setResourceNode($resourceNode)
299
            ->addResourceRight($right)
300
        ;
301
302
        $this->getEntityManager()->persist($resourceLink);
303
        $this->getEntityManager()->flush();
304
305
        return $resourceLink;
306
    }
307
308
309
310
    /**
311
     * @param ResourceNode  $resourceNode
312
     * @param Course        $course
313
     * @param ResourceRight $right
314
     *
315
     * @return ResourceLink
316
     */
317
    public function addResourceToCourse2(ResourceNode $resourceNode, Course $course, ResourceRight $right): ResourceLink
318
    {
319
        $resourceLink = new ResourceLink();
320
        $resourceLink
321
            ->setResourceNode($resourceNode)
322
            ->setCourse($course)
323
            ->addResourceRight($right);
324
        $this->getEntityManager()->persist($resourceLink);
325
        $this->getEntityManager()->flush();
326
327
        return $resourceLink;
328
    }
329
330
    /**
331
     * @param ResourceNode $resourceNode
332
     * @param User         $toUser
333
     *
334
     * @return ResourceLink
335
     */
336
    public function addResourceToUser(ResourceNode $resourceNode, User $toUser): ResourceLink
337
    {
338
        $resourceLink = $this->addResourceNodeToUser($resourceNode, $toUser);
339
        $this->getEntityManager()->persist($resourceLink);
340
341
        return $resourceLink;
342
    }
343
344
    /**
345
     * @param ResourceNode $resourceNode
346
     * @param User         $toUser
347
     *
348
     * @return ResourceLink
349
     */
350
    public function addResourceNodeToUser(ResourceNode $resourceNode, User $toUser): ResourceLink
351
    {
352
        $resourceLink = new ResourceLink();
353
        $resourceLink
354
            ->setResourceNode($resourceNode)
355
            ->setUser($toUser);
356
357
        return $resourceLink;
358
    }
359
360
    /**
361
     * @param ResourceNode  $resourceNode
362
     * @param Course        $course
363
     * @param Session       $session
364
     * @param ResourceRight $right
365
     *
366
     */
367
    public function addResourceToSession(
368
        ResourceNode $resourceNode,
369
        Course $course,
370
        Session $session,
371
        ResourceRight $right
372
    ) {
373
        $resourceLink = $this->addResourceToCourse(
0 ignored issues
show
Bug introduced by
Are you sure the assignment to $resourceLink is correct as $this->addResourceToCour...eNode, $course, $right) targeting Chamilo\CoreBundle\Repos...::addResourceToCourse() seems to always return null.

This check looks for function or method calls that always return null and whose return value is assigned to a variable.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
$object = $a->getObject();

The method getObject() can return nothing but null, so it makes no sense to assign that value to a variable.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
Bug introduced by
The call to Chamilo\CoreBundle\Repos...::addResourceToCourse() has too few arguments starting with course. ( Ignorable by Annotation )

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

373
        /** @scrutinizer ignore-call */ 
374
        $resourceLink = $this->addResourceToCourse(

This check compares calls to functions or methods with their respective definitions. If the call has less arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
374
            $resourceNode,
375
            $course,
376
            $right
377
        );
378
        $resourceLink->setSession($session);
379
        $this->getEntityManager()->persist($resourceLink);
380
381
        return $resourceLink;
382
    }
383
384
    /**
385
     * @param ResourceNode  $resourceNode
386
     * @param Course        $course
387
     * @param CGroupInfo    $group
388
     * @param ResourceRight $right
389
     *
390
     * @return ResourceLink
391
     */
392
    public function addResourceToCourseGroup(
393
        ResourceNode $resourceNode,
394
        Course $course,
395
        CGroupInfo $group,
396
        ResourceRight $right
397
    ) {
398
        $resourceLink = $this->addResourceToCourse(
0 ignored issues
show
Bug introduced by
Are you sure the assignment to $resourceLink is correct as $this->addResourceToCour...eNode, $course, $right) targeting Chamilo\CoreBundle\Repos...::addResourceToCourse() seems to always return null.

This check looks for function or method calls that always return null and whose return value is assigned to a variable.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
$object = $a->getObject();

The method getObject() can return nothing but null, so it makes no sense to assign that value to a variable.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
Bug introduced by
The call to Chamilo\CoreBundle\Repos...::addResourceToCourse() has too few arguments starting with course. ( Ignorable by Annotation )

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

398
        /** @scrutinizer ignore-call */ 
399
        $resourceLink = $this->addResourceToCourse(

This check compares calls to functions or methods with their respective definitions. If the call has less arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
399
            $resourceNode,
400
            $course,
401
            $right
402
        );
403
        $resourceLink->setGroup($group);
404
        $this->getEntityManager()->persist($resourceLink);
405
406
        return $resourceLink;
407
    }
408
409
    /**
410
     * @param ResourceNode  $resourceNode
411
     * @param Usergroup     $group
412
     * @param ResourceRight $right
413
     *
414
     * @return ResourceLink
415
     */
416
    public function addResourceToGroup(
417
        ResourceNode $resourceNode,
418
        Usergroup $group,
419
        ResourceRight $right
420
    ) {
421
        $resourceLink = new ResourceLink();
422
        $resourceLink
423
            ->setResourceNode($resourceNode)
424
            ->setUserGroup($group)
425
            ->addResourceRight($right);
426
427
        return $resourceLink;
428
    }
429
430
    /**
431
     * @param ResourceNode $resourceNode
432
     * @param array        $userList     User id list
433
     */
434
    public function addResourceToUserList(ResourceNode $resourceNode, array $userList)
435
    {
436
        $em = $this->getEntityManager();
437
438
        if (!empty($userList)) {
439
            foreach ($userList as $userId) {
440
                $toUser = $em->getRepository('ChamiloUserBundle:User')->find($userId);
441
442
                $resourceLink = $this->addResourceNodeToUser($resourceNode, $toUser);
443
                $em->persist($resourceLink);
444
            }
445
        }
446
    }
447
448
    /**
449
     * @param Course          $course
450
     * @param Session|null    $session
451
     * @param CGroupInfo|null $group
452
     *
453
     * @return array
454
     */
455
    public function getResourcesByCourse(Course $course, Session $session = null, CGroupInfo $group = null)
456
    {
457
        $repo = $this->getRepository();
458
        $className = $repo->getClassName();
459
460
        // Check if this resource type requires to load the base course resources when using a session
461
        $loadBaseSessionContent = $repo->getClassMetadata()->getReflectionClass()->hasProperty(
462
            'loadBaseCourseResourcesFromSession'
463
        );
464
        $type = $this->getResourceType();
465
466
        $query = $this->getEntityManager()->createQueryBuilder()
467
            ->select('resource')
468
            ->from(ResourceNode::class, 'node')
469
            ->innerJoin('node.resourceLinks', 'links')
470
            ->innerJoin(
471
                $className,
472
                'resource',
473
                Join::WITH,
474
                'resource.course = links.course AND resource.resourceNode = node.id'
475
            )
476
            ->where('node.resourceType = :type')
477
            ->andWhere('links.course = :course')
478
            //->where('link.cId = ?', $course->getId())
479
            //->where('node.cId = 0')
480
            //->orderBy('node');
481
            ->setParameters(
482
                [
483
                    'type' => $type,
484
                    'course' => $course,
485
                ]
486
            );
487
488
        if ($session === null) {
489
            $query->andWhere('links.session IS NULL');
490
        } else {
491
            if ($loadBaseSessionContent) {
492
                $query->andWhere('links.session = :session OR links.session IS NULL');
493
                $query->setParameter('session', $session);
494
            } else {
495
                $query->andWhere('links.session = :session');
496
                $query->setParameter('session', $session);
497
            }
498
        }
499
500
        if ($group === null) {
501
            $query->andWhere('links.group IS NULL');
502
        }
503
504
        /*if ($parent !== null) {
505
            $query->andWhere('node.parent = :parentId');
506
            $query->setParameter('parentId', $parent->getResourceNode()->getId());
507
        } else {
508
            $query->andWhere('node.parent = :parentId');
509
            $query->setParameter('parentId', $course->getResourceNode());
510
        }*/
511
512
        /*$query->setFirstResult();
513
        $query->setMaxResults();
514
        $query->orderBy();*/
515
516
        $query = $query->getQuery();
517
        //var_dump($query->getSQL());
518
519
        /*$query = $this->getEntityManager()->createQueryBuilder()
520
            ->select('notebook')
521
            ->from('ChamiloNotebookBundle:CNotebook', 'notebook')
522
            ->innerJoin('notebook.resourceNodes', 'node')
523
            //->innerJoin('node.links', 'link')
524
            ->where('node.tool = :tool')
525
            //->where('link.cId = ?', $course->getId())
526
            //->where('node.cId = 0')
527
            //->orderBy('node');
528
            ->setParameters(array(
529
                    'tool'=> 'notebook'
530
                )
531
            )
532
            ->getQuery()
533
        ;*/
534
        return $query->getResult();
535
    }
536
537
    /**
538
     * @param string $tool
539
     *
540
     * @return Tool|null
541
     */
542
    private function getTool($tool)
0 ignored issues
show
Unused Code introduced by
The method getTool() is not used, and could be removed.

This check looks for private methods that have been defined, but are not used inside the class.

Loading history...
543
    {
544
        return $this
545
            ->getEntityManager()
546
            ->getRepository('ChamiloCoreBundle:Tool')
547
            ->findOneBy(['name' => $tool]);
548
    }
549
550
    /**
551
     * @param AbstractResource $resource
552
     * @param int              $visibility
553
     * @param bool             $recursive
554
     */
555
    private function setLinkVisibility(AbstractResource $resource, $visibility, $recursive = true)
556
    {
557
        $resourceNode = $resource->getResourceNode();
558
559
        $em = $this->getEntityManager();
560
        if ($recursive) {
561
            $children = $resourceNode->getChildren();
562
            if (!empty($children)) {
563
                /** @var ResourceNode $child */
564
                foreach ($children as $child) {
565
                    $criteria = ['resourceNode' => $child];
566
                    $childDocument = $this->getRepository()->findOneBy($criteria);
567
                    if ($childDocument) {
568
                        $this->setLinkVisibility($childDocument, $visibility);
569
                    }
570
                }
571
            }
572
        }
573
574
        $links = $resourceNode->getResourceLinks();
575
576
        if (!empty($links)) {
577
            /** @var ResourceLink $link */
578
            foreach ($links as $link) {
579
                $link->setVisibility($visibility);
580
                if ($visibility === ResourceLink::VISIBILITY_DRAFT) {
581
                    $editorMask = ResourceNodeVoter::getEditorMask();
582
                    $rights = [];
583
                    $resourceRight = new ResourceRight();
584
                    $resourceRight
585
                        ->setMask($editorMask)
586
                        ->setRole(ResourceNodeVoter::ROLE_CURRENT_COURSE_TEACHER)
587
                        ->setResourceLink($link)
588
                    ;
589
                    $rights[] = $resourceRight;
590
591
                    if (!empty($rights)) {
592
                        $link->setResourceRight($rights);
593
                    }
594
                } else {
595
                    $link->setResourceRight([]);
596
                }
597
                $em->merge($link);
598
            }
599
        }
600
        $em->flush();
601
    }
602
603
    /**
604
     * Deletes several entities: AbstractResource (Ex: CDocument, CQuiz), ResourceNode,
605
     * ResourceLinks and ResourceFile (including files via Flysystem)
606
     *
607
     * @param AbstractResource $resource
608
     */
609
    public function hardDelete(AbstractResource $resource)
610
    {
611
        $em = $this->getEntityManager();
612
        $em->remove($resource);
613
        $em->flush();
614
    }
615
616
    /**
617
     * Change all links visibility to DELETED.
618
     *
619
     * @param AbstractResource $resource
620
     */
621
    public function softDelete(AbstractResource $resource)
622
    {
623
        $this->setLinkVisibility($resource, ResourceLink::VISIBILITY_DELETED);
624
    }
625
}
626