Completed
Push — master ( a34f18...c6c5e0 )
by Julito
15:01
created

ResourceController::getGrid()   D

Complexity

Conditions 15
Paths 24

Size

Total Lines 312
Code Lines 165

Duplication

Lines 0
Ratio 0 %

Importance

Changes 3
Bugs 0 Features 0
Metric Value
cc 15
eloc 165
nc 24
nop 4
dl 0
loc 312
rs 4.7333
c 3
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/* For licensing terms, see /license.txt */
3
4
namespace Chamilo\CoreBundle\Controller;
5
6
use APY\DataGridBundle\Grid\Action\MassAction;
7
use APY\DataGridBundle\Grid\Action\RowAction;
8
use APY\DataGridBundle\Grid\Column\Column;
9
use APY\DataGridBundle\Grid\Export\CSVExport;
10
use APY\DataGridBundle\Grid\Export\ExcelExport;
11
use APY\DataGridBundle\Grid\Grid;
12
use APY\DataGridBundle\Grid\Row;
13
use APY\DataGridBundle\Grid\Source\Entity;
14
use Chamilo\CoreBundle\Component\Utils\Glide;
15
use Chamilo\CoreBundle\Entity\Resource\AbstractResource;
16
use Chamilo\CoreBundle\Entity\Resource\ResourceLink;
17
use Chamilo\CoreBundle\Entity\Resource\ResourceNode;
18
use Chamilo\CoreBundle\Repository\ResourceRepository;
19
use Chamilo\CoreBundle\Security\Authorization\Voter\ResourceNodeVoter;
20
use Chamilo\CourseBundle\Controller\CourseControllerInterface;
21
use Chamilo\CourseBundle\Controller\CourseControllerTrait;
22
use Chamilo\UserBundle\Entity\User;
23
use Doctrine\Common\Collections\ArrayCollection;
24
use Doctrine\Common\Collections\Criteria;
25
use Doctrine\ORM\QueryBuilder;
26
use FOS\CKEditorBundle\Form\Type\CKEditorType;
27
use Symfony\Component\Filesystem\Exception\FileNotFoundException;
28
use Symfony\Component\HttpFoundation\File\UploadedFile;
29
use Symfony\Component\HttpFoundation\JsonResponse;
30
use Symfony\Component\HttpFoundation\RedirectResponse;
31
use Symfony\Component\HttpFoundation\Request;
32
use Symfony\Component\HttpFoundation\Response;
33
use Symfony\Component\HttpFoundation\ResponseHeaderBag;
34
use Symfony\Component\HttpFoundation\StreamedResponse;
35
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
36
use Symfony\Component\Routing\Annotation\Route;
37
use Symfony\Component\Routing\Router;
38
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
39
use Vich\UploaderBundle\Util\Transliterator;
40
use ZipStream\Option\Archive;
41
use ZipStream\ZipStream;
42
43
/**
44
 * Class ResourceController.
45
 *
46
 * @todo improve/refactor $this->denyAccessUnlessGranted
47
 * @Route("/resources")
48
 *
49
 * @author Julio Montoya <[email protected]>.
50
 */
51
class ResourceController extends AbstractResourceController implements CourseControllerInterface
52
{
53
    use CourseControllerTrait;
54
55
    /**
56
     * @Route("/{tool}/{type}", name="chamilo_core_resource_index")
57
     *
58
     * Example: /document/files (See the 'tool' and the 'resource_type' DB tables.)
59
     * For the tool value check the Tool entity.
60
     * For the type value check the ResourceType entity.
61
     */
62
    public function indexAction(Request $request, Grid $grid): Response
63
    {
64
        $tool = $request->get('tool');
65
        $type = $request->get('type');
66
67
        $parentResourceNode = $this->getParentResourceNode($request);
68
        $repository = $this->getRepositoryFromRequest($request);
69
        $settings = $repository->getResourceSettings();
70
71
        $grid = $this->getGrid($request, $repository, $grid, $parentResourceNode->getId());
72
73
        $breadcrumb = $this->getBreadCrumb();
74
        $breadcrumb->addChild(
75
            $this->trans($tool),
76
            [
77
                'uri' => '#',
78
            ]
79
        );
80
81
        // The base resource node is the course.
82
        $id = $parentResourceNode->getId();
83
84
        return $grid->getGridResponse(
85
            '@ChamiloTheme/Resource/index.html.twig',
86
            [
87
                'tool' => $tool,
88
                'type' => $type,
89
                'id' => $id,
90
                'parent_resource_node' => $parentResourceNode,
91
                'resource_settings' => $settings,
92
            ]
93
        );
94
    }
95
96
    /**
97
     * @Route("/{tool}/{type}/{id}/list", name="chamilo_core_resource_list")
98
     *
99
     * If node has children show it
100
     */
101
    public function listAction(Request $request, Grid $grid): Response
102
    {
103
        $tool = $request->get('tool');
104
        $type = $request->get('type');
105
        $resourceNodeId = $request->get('id');
106
107
        $repository = $this->getRepositoryFromRequest($request);
108
        $settings = $repository->getResourceSettings();
109
110
        $grid = $this->getGrid($request, $repository, $grid, $resourceNodeId);
111
112
        $this->setBreadCrumb($request);
113
        $parentResourceNode = $this->getParentResourceNode($request);
114
115
        return $grid->getGridResponse(
116
            '@ChamiloTheme/Resource/index.html.twig',
117
            [
118
                'parent_id' => $resourceNodeId,
119
                'tool' => $tool,
120
                'type' => $type,
121
                'id' => $resourceNodeId,
122
                'parent_resource_node' => $parentResourceNode,
123
                'resource_settings' => $settings,
124
            ]
125
        );
126
    }
127
128
    public function getGrid(Request $request, ResourceRepository $repository, Grid $grid, $resourceNodeId): Grid
129
    {
130
        $class = $repository->getRepository()->getClassName();
131
132
        // The group 'resource' is set in the @GRID\Source annotation in the entity.
133
        $source = new Entity($class, 'resource');
134
        /** @var ResourceNode $parentNode */
135
        $parentNode = $repository->getResourceNodeRepository()->find($resourceNodeId);
136
137
        $this->denyAccessUnlessGranted(
138
            ResourceNodeVoter::VIEW,
139
            $parentNode,
140
            $this->trans('Unauthorised access to resource')
141
        );
142
143
        $settings = $repository->getResourceSettings();
144
145
        $course = $this->getCourse();
146
        $session = $this->getSession();
147
148
        $qb = $repository->getResources($this->getUser(), $parentNode, $course, $session, null);
149
150
        // 3. Set QueryBuilder to the source.
151
        $source->initQueryBuilder($qb);
152
        $grid->setSource($source);
153
154
        $resourceParams = $this->getResourceParams($request);
155
156
        $grid->setRouteUrl($this->generateUrl('chamilo_core_resource_list', $resourceParams));
157
158
        //$grid->hideFilters();
159
        //$grid->setLimits(20);
160
        //$grid->isReadyForRedirect();
161
        //$grid->setMaxResults(1);
162
        //$grid->setLimits(2);
163
        //$grid->setColumns($columns);
164
        $routeParams = $resourceParams;
165
        $routeParams['id'] = null;
166
167
        /** @var Column $titleColumn */
168
        $titleColumn = $repository->getTitleColumn($grid);
169
        $titleColumn->setSafe(false); // allows links in the title
170
171
        // Title link.
172
        $titleColumn->setTitle($this->trans('Name'));
173
174
        //$repository->formatGrid();
175
        /*if ($grid->hasColumn('filetype')) {
176
            $grid->getColumn('filetype')->setTitle($this->trans('Type'));
177
        }*/
178
179
        $titleColumn->manipulateRenderCell(
180
            function ($value, Row $row, $router) use ($routeParams) {
181
                /** @var Router $router */
182
                /** @var AbstractResource $entity */
183
                $entity = $row->getEntity();
184
                $resourceNode = $entity->getResourceNode();
185
                $id = $resourceNode->getId();
186
187
                $myParams = $routeParams;
188
                $myParams['id'] = $id;
189
                unset($myParams[0]);
190
191
                $icon = $resourceNode->getIcon().' &nbsp;';
192
                if ($resourceNode->hasResourceFile()) {
193
                    if ($resourceNode->isResourceFileAnImage()) {
194
                        $url = $router->generate(
195
                            'chamilo_core_resource_view',
196
                            $myParams
197
                        );
198
199
                        return $icon.'<a data-fancybox="gallery" href="'.$url.'">'.$value.'</a>';
200
                    }
201
202
                    if ($resourceNode->isResourceFileAVideo()) {
203
                        $url = $router->generate(
204
                            'chamilo_core_resource_view',
205
                            $myParams
206
                        );
207
208
                        return '
209
                        <video width="640" height="320" controls id="video'.$id.'" controls preload="metadata" style="display:none;">
210
                            <source src="'.$url.'" type="video/mp4">
211
                            Your browser doesn\'t support HTML5 video tag.
212
                        </video>
213
                        '.$icon.' <a data-fancybox="gallery"  data-width="640" data-height="360" href="#video'.$id.'">'.$value.'</a>';
214
                    }
215
216
                    $url = $router->generate(
217
                        'chamilo_core_resource_preview',
218
                        $myParams
219
                    );
220
221
                    return $icon.'<a data-fancybox="gallery" data-type="iframe" data-src="'.$url.'" href="javascript:;" >'.$value.'</a>';
222
                } else {
223
                    $url = $router->generate(
224
                        'chamilo_core_resource_list',
225
                        $myParams
226
                    );
227
228
                    return $icon.'<a href="'.$url.'">'.$value.'</a>';
229
                }
230
            }
231
        );
232
233
        if ($grid->hasColumn('filetype')) {
234
            $grid->getColumn('filetype')->manipulateRenderCell(
235
                function ($value, Row $row, $router) use ($routeParams) {
0 ignored issues
show
Unused Code introduced by
The parameter $router is not used and could be removed. ( Ignorable by Annotation )

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

235
                function ($value, Row $row, /** @scrutinizer ignore-unused */ $router) use ($routeParams) {

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The import $routeParams is not used and could be removed.

This check looks for imports that have been defined, but are not used in the scope.

Loading history...
236
                    /** @var AbstractResource $entity */
237
                    $entity = $row->getEntity();
238
                    $resourceNode = $entity->getResourceNode();
239
240
                    if ($resourceNode->hasResourceFile()) {
241
                        $file = $resourceNode->getResourceFile();
242
243
                        return $file->getMimeType();
244
                    }
245
246
                    return $this->trans('Folder');
247
                }
248
            );
249
        }
250
251
        if ($grid->hasColumn('iid')) {
252
            $grid->setHiddenColumns(['iid']);
253
        }
254
255
        // Delete mass action.
256
        if ($this->isGranted(ResourceNodeVoter::DELETE, $parentNode)) {
257
            $deleteMassAction = new MassAction(
258
                'Delete',
259
                'ChamiloCoreBundle:Resource:deleteMass',
260
                true,
261
                $routeParams
262
            );
263
            $grid->addMassAction($deleteMassAction);
264
        }
265
266
        // Info action.
267
        $myRowAction = new RowAction(
268
            $this->trans('Info'),
269
            'chamilo_core_resource_info',
270
            false,
271
            '_self',
272
            [
273
                'class' => 'btn btn-secondary info_action',
274
                'icon' => 'fa-info-circle',
275
                'iframe' => false,
276
            ]
277
        );
278
279
        $setNodeParameters = function (RowAction $action, Row $row) use ($routeParams) {
280
            $id = $row->getEntity()->getResourceNode()->getId();
281
            $routeParams['id'] = $id;
282
            $action->setRouteParameters($routeParams);
283
            $attributes = $action->getAttributes();
284
            $attributes['data-action'] = $action->getRoute();
285
            $attributes['data-action-id'] = $action->getRoute().'_'.$id;
286
            $attributes['data-node-id'] = $id;
287
288
            $action->setAttributes($attributes);
289
290
            return $action;
291
        };
292
293
        $myRowAction->addManipulateRender($setNodeParameters);
294
        $grid->addRowAction($myRowAction);
295
296
        // Download action
297
        $myRowAction = new RowAction(
298
            $this->trans('Download'),
299
            'chamilo_core_resource_download',
300
            false,
301
            '_self',
302
            [
303
                'class' => 'btn btn-secondary download_action',
304
                'icon' => 'fa-download',
305
            ]
306
        );
307
308
        $setNodeDownloadParameters = function (RowAction $action, Row $row) use ($routeParams) {
309
            $id = $row->getEntity()->getResourceNode()->getId();
310
            $routeParams['id'] = $id;
311
            $action->setRouteParameters($routeParams);
312
            $attributes = $action->getAttributes();
313
            $action->setAttributes($attributes);
314
315
            return $action;
316
        };
317
        $myRowAction->addManipulateRender($setNodeDownloadParameters);
318
        $grid->addRowAction($myRowAction);
319
320
        // Set EDIT/DELETE
321
        $setNodeParameters = function (RowAction $action, Row $row) use ($routeParams) {
322
            $id = $row->getEntity()->getResourceNode()->getId();
323
324
            $allowedEdit = $this->isGranted(ResourceNodeVoter::EDIT, $row->getEntity()->getResourceNode());
325
326
            if ($allowedEdit === false) {
327
                return null;
328
            }
329
330
            $routeParams['id'] = $id;
331
332
            $action->setRouteParameters($routeParams);
333
            $attributes = $action->getAttributes();
334
            //$attributes['data-action'] = $action->getRoute();
335
            //$attributes['data-action-id'] = $action->getRoute().'_'.$id;
336
            //$attributes['data-node-id'] = $id;
337
            $action->setAttributes($attributes);
338
339
            return $action;
340
        };
341
342
        if ($this->isGranted(ResourceNodeVoter::EDIT, $parentNode)) {
343
            // Enable/Disable
344
            $myRowAction = new RowAction(
345
                '',
346
                'chamilo_core_resource_change_visibility',
347
                false,
348
                '_self'
349
            );
350
351
            $setVisibleParameters = function (RowAction $action, Row $row) use ($routeParams) {
352
                /** @var AbstractResource $resource */
353
                $resource = $row->getEntity();
354
                $allowedEdit = $this->isGranted(ResourceNodeVoter::EDIT, $resource->getResourceNode());
355
356
                if ($allowedEdit === false) {
357
                    return null;
358
                }
359
360
                $id = $resource->getResourceNode()->getId();
361
362
                $icon = 'fa-eye-slash';
363
                if ($this->hasCourse()) {
364
                    $link = $resource->getCourseSessionResourceLink($this->getCourse(), $this->getSession());
365
                } else {
366
                    $link = $resource->getFirstResourceLink();
367
                }
368
369
                if ($link === null) {
370
                    return null;
371
                }
372
                if ($link->getVisibility() === ResourceLink::VISIBILITY_PUBLISHED) {
373
                    $icon = 'fa-eye';
374
                }
375
                $routeParams['id'] = $id;
376
                $action->setRouteParameters($routeParams);
377
                $attributes = [
378
                    'class' => 'btn btn-secondary change_visibility',
379
                    'data-id' => $id,
380
                    'icon' => $icon,
381
                ];
382
                $action->setAttributes($attributes);
383
384
                return $action;
385
            };
386
387
            $myRowAction->addManipulateRender($setVisibleParameters);
388
            $grid->addRowAction($myRowAction);
389
390
            if ($settings->isAllowResourceEdit()) {
391
                // Edit action.
392
                $myRowAction = new RowAction(
393
                    $this->trans('Edit'),
394
                    'chamilo_core_resource_edit',
395
                    false,
396
                    '_self',
397
                    ['class' => 'btn btn-secondary', 'icon' => 'fa fa-pen']
398
                );
399
                $myRowAction->addManipulateRender($setNodeParameters);
400
                $grid->addRowAction($myRowAction);
401
            }
402
403
            // More action.
404
            /*$myRowAction = new RowAction(
405
                $this->trans('More'),
406
                'chamilo_core_resource_preview',
407
                false,
408
                '_self',
409
                ['class' => 'btn btn-secondary edit_resource', 'icon' => 'fa fa-ellipsis-h']
410
            );
411
412
            $myRowAction->addManipulateRender($setNodeParameters);
413
            $grid->addRowAction($myRowAction);*/
414
415
            // Delete action.
416
            $myRowAction = new RowAction(
417
                $this->trans('Delete'),
418
                'chamilo_core_resource_delete',
419
                true,
420
                '_self',
421
                [
422
                    'class' => 'btn btn-danger',
423
                    //'data_hidden' => true,
424
                ]
425
            );
426
            $myRowAction->addManipulateRender($setNodeParameters);
427
            $grid->addRowAction($myRowAction);
428
        }
429
430
        /*$grid->addExport(new CSVExport($this->trans('CSV export'), 'export', ['course' => $courseIdentifier]));
431
        $grid->addExport(
432
            new ExcelExport(
433
                $this->trans('Excel export'),
434
                'export',
435
                ['course' => $courseIdentifier]
436
            )
437
        );*/
438
439
        return $grid;
440
    }
441
442
    /**
443
     * @Route("/{tool}/{type}/{id}/new_folder", methods={"GET", "POST"}, name="chamilo_core_resource_new_folder")
444
     */
445
    public function newFolderAction(Request $request): Response
446
    {
447
        $this->setBreadCrumb($request);
448
449
        return $this->createResource($request, 'folder');
450
    }
451
452
    /**
453
     * @Route("/{tool}/{type}/{id}/new", methods={"GET", "POST"}, name="chamilo_core_resource_new")
454
     */
455
    public function newAction(Request $request): Response
456
    {
457
        $this->setBreadCrumb($request);
458
459
        return $this->createResource($request, 'file');
460
    }
461
462
    /**
463
     * @Route("/{tool}/{type}/{id}/edit", methods={"GET", "POST"})
464
     */
465
    public function editAction(Request $request): Response
466
    {
467
        $resourceNodeId = $request->get('id');
468
469
        $this->setBreadCrumb($request);
470
        $repository = $this->getRepositoryFromRequest($request);
471
        /** @var AbstractResource $resource */
472
        $resource = $repository->getRepository()->findOneBy(['resourceNode' => $resourceNodeId]);
473
        $resourceNode = $resource->getResourceNode();
474
475
        $this->denyAccessUnlessGranted(
476
            ResourceNodeVoter::EDIT,
477
            $resourceNode,
478
            $this->trans('Unauthorised access to resource')
479
        );
480
481
        $resourceNodeParentId = $resourceNode->getId();
482
483
        $routeParams = $this->getResourceParams($request);
484
        $routeParams['id'] = $resourceNodeParentId;
485
486
        $form = $repository->getForm($this->container->get('form.factory'), $resource);
487
488
        if ($resourceNode->hasEditableContent()) {
489
            $form->add(
490
                'content',
491
                CKEditorType::class,
492
                [
493
                    'mapped' => false,
494
                    'config' => [
495
                        'filebrowserImageBrowseRoute' => 'resources_filemanager',
496
                        'filebrowserImageBrowseRouteParameters' => $routeParams,
497
                    ],
498
                ]
499
            );
500
            $content = $repository->getResourceNodeFileContent($resourceNode);
501
            $form->get('content')->setData($content);
502
        }
503
504
        $form->handleRequest($request);
505
506
        if ($form->isSubmitted() && $form->isValid()) {
507
            /** @var AbstractResource $newResource */
508
            $newResource = $form->getData();
509
510
            if ($form->has('content')) {
511
                $data = $form->get('content')->getData();
512
                $repository->updateResourceFileContent($newResource, $data);
513
            }
514
515
            //$newResource->setTitle($form->get('title')->getData()); // already set in $form->getData()
516
            $repository->updateNodeForResource($newResource);
517
518
            $this->addFlash('success', $this->trans('Updated'));
519
520
            //if ($newResource->getResourceNode()->hasResourceFile()) {
521
                $resourceNodeParentId = $newResource->getResourceNode()->getParent()->getId();
522
            //}
523
            $routeParams['id'] = $resourceNodeParentId;
524
525
            return $this->redirectToRoute('chamilo_core_resource_list', $routeParams);
526
        }
527
528
        return $this->render(
529
            '@ChamiloTheme/Resource/edit.html.twig',
530
            [
531
                'form' => $form->createView(),
532
                'parent' => $resourceNodeParentId,
533
            ]
534
        );
535
    }
536
537
    /**
538
     * Shows a resource information.
539
     *
540
     * @Route("/{tool}/{type}/{id}/info", methods={"GET"}, name="chamilo_core_resource_info")
541
     */
542
    public function infoAction(Request $request): Response
543
    {
544
        $this->setBreadCrumb($request);
545
        $nodeId = $request->get('id');
546
547
        $repository = $this->getRepositoryFromRequest($request);
548
549
        /** @var AbstractResource $resource */
550
        $resource = $repository->getRepository()->findOneBy(['resourceNode' => $nodeId]);
551
552
        if (null === $resource) {
553
            throw new NotFoundHttpException();
554
        }
555
556
        $resourceNode = $resource->getResourceNode();
557
558
        if (null === $resourceNode) {
559
            throw new NotFoundHttpException();
560
        }
561
562
        $this->denyAccessUnlessGranted(
563
            ResourceNodeVoter::VIEW,
564
            $resourceNode,
565
            $this->trans('Unauthorised access to resource')
566
        );
567
568
        $tool = $request->get('tool');
569
        $type = $request->get('type');
570
571
        $params = [
572
            'resource' => $resource,
573
            'tool' => $tool,
574
            'type' => $type,
575
        ];
576
577
        return $this->render('@ChamiloTheme/Resource/show.html.twig', $params);
578
    }
579
580
    /**
581
     * Preview a file. Mostly used when using a modal.
582
     *
583
     * @Route("/{tool}/{type}/{id}/preview", methods={"GET"}, name="chamilo_core_resource_preview")
584
     */
585
    public function previewAction(Request $request): Response
586
    {
587
        $this->setBreadCrumb($request);
588
        $nodeId = $request->get('id');
589
590
        $repository = $this->getRepositoryFromRequest($request);
591
592
        /** @var AbstractResource $resource */
593
        $resource = $repository->getRepository()->findOneBy(['resourceNode' => $nodeId]);
594
595
        if (null === $resource) {
596
            throw new NotFoundHttpException();
597
        }
598
599
        $resourceNode = $resource->getResourceNode();
600
601
        if (null === $resourceNode) {
602
            throw new NotFoundHttpException();
603
        }
604
605
        $this->denyAccessUnlessGranted(
606
            ResourceNodeVoter::VIEW,
607
            $resourceNode,
608
            $this->trans('Unauthorised access to resource')
609
        );
610
611
        $tool = $request->get('tool');
612
        $type = $request->get('type');
613
614
        $params = [
615
            'resource' => $resource,
616
            'tool' => $tool,
617
            'type' => $type,
618
        ];
619
620
        return $this->render('@ChamiloTheme/Resource/preview.html.twig', $params);
621
    }
622
623
    /**
624
     * @Route("/{tool}/{type}/{id}/change_visibility", name="chamilo_core_resource_change_visibility")
625
     */
626
    public function changeVisibilityAction(Request $request): Response
627
    {
628
        $id = $request->get('id');
629
630
        $repository = $this->getRepositoryFromRequest($request);
631
632
        /** @var AbstractResource $resource */
633
        $resource = $repository->getRepository()->findOneBy(['resourceNode' => $id]);
634
635
        if (null === $resource) {
636
            throw new NotFoundHttpException();
637
        }
638
639
        $resourceNode = $resource->getResourceNode();
640
641
        $this->denyAccessUnlessGranted(
642
            ResourceNodeVoter::EDIT,
643
            $resourceNode,
644
            $this->trans('Unauthorised access to resource')
645
        );
646
647
        /** @var ResourceLink $link */
648
        if ($this->hasCourse()) {
649
            $link = $resource->getCourseSessionResourceLink($this->getCourse(), $this->getSession());
650
        } else {
651
            $link = $resource->getFirstResourceLink();
652
        }
653
654
        $icon = 'fa-eye';
655
        // Use repository to change settings easily.
656
        if ($link && $link->getVisibility() === ResourceLink::VISIBILITY_PUBLISHED) {
657
            $repository->setVisibilityDraft($resource);
658
            $icon = 'fa-eye-slash';
659
        } else {
660
            $repository->setVisibilityPublished($resource);
661
        }
662
663
        $result = ['icon' => $icon];
664
665
        return new JsonResponse($result);
666
    }
667
668
    /**
669
     * @Route("/{tool}/{type}/{id}", name="chamilo_core_resource_delete")
670
     */
671
    public function deleteAction(Request $request): Response
672
    {
673
        $em = $this->getDoctrine()->getManager();
674
675
        $id = $request->get('id');
676
        $resourceNode = $this->getDoctrine()->getRepository('ChamiloCoreBundle:Resource\ResourceNode')->find($id);
677
        $parentId = $resourceNode->getParent()->getId();
678
679
        if (null === $resourceNode) {
680
            throw new NotFoundHttpException();
681
        }
682
683
        $this->denyAccessUnlessGranted(
684
            ResourceNodeVoter::DELETE,
685
            $resourceNode,
686
            $this->trans('Unauthorised access to resource')
687
        );
688
689
        $em->remove($resourceNode);
690
        $this->addFlash('success', $this->trans('Deleted'));
691
        $em->flush();
692
693
        $routeParams = $this->getResourceParams($request);
694
        $routeParams['id'] = $parentId;
695
696
        return $this->redirectToRoute(
697
            'chamilo_core_resource_list',
698
            $routeParams
699
        );
700
    }
701
702
    /**
703
     * @Route("/{tool}/{type}/{id}", methods={"DELETE"}, name="chamilo_core_resource_delete_mass")
704
     */
705
    public function deleteMassAction($primaryKeys, $allPrimaryKeys, Request $request): Response
706
    {
707
        $em = $this->getDoctrine()->getManager();
708
        $repo = $this->getRepositoryFromRequest($request);
709
710
        $parentId = 0;
711
        foreach ($primaryKeys as $id) {
712
            $resource = $repo->find($id);
713
            $resourceNode = $resource->getResourceNode();
714
715
            if (null === $resourceNode) {
716
                continue;
717
            }
718
719
            $this->denyAccessUnlessGranted(
720
                ResourceNodeVoter::DELETE,
721
                $resourceNode,
722
                $this->trans('Unauthorised access to resource')
723
            );
724
725
            $parentId = $resourceNode->getParent()->getId();
726
            $em->remove($resource);
727
        }
728
729
        $this->addFlash('success', $this->trans('Deleted'));
730
        $em->flush();
731
732
        $routeParams = $this->getResourceParams($request);
733
        $routeParams['id'] = $parentId;
734
735
        return $this->redirectToRoute('chamilo_core_resource_list', $routeParams);
736
    }
737
738
    /**
739
     * Shows the associated resource file.
740
     *
741
     * @Route("/{tool}/{type}/{id}/view", methods={"GET"}, name="chamilo_core_resource_view")
742
     */
743
    public function viewAction(Request $request, Glide $glide): Response
744
    {
745
        $id = $request->get('id');
746
        $filter = $request->get('filter');
747
        $mode = $request->get('mode');
748
        $em = $this->getDoctrine();
749
        $resourceNode = $em->getRepository('ChamiloCoreBundle:Resource\ResourceNode')->find($id);
750
751
        if ($resourceNode === null) {
752
            throw new FileNotFoundException('Resource not found');
753
        }
754
755
        return $this->showFile($request, $resourceNode, $mode, $glide, $filter);
756
    }
757
758
    /**
759
     * Gets a document when calling route resources_document_get_file.
760
1     *
761
     * @deprecated
762
     *
763
     * @throws \League\Flysystem\FileNotFoundException
764
     */
765
    public function getDocumentAction(Request $request, Glide $glide): Response
766
    {
767
        /*$file = $request->get('file');
768
        $mode = $request->get('mode');
769
770
        // see list of filters in config/services.yaml
771
        $filter = $request->get('filter');
772
        $mode = !empty($mode) ? $mode : 'show';
773
774
        $repository = $this->getRepository('document', 'files');
775
        $nodeRepository = $repository->getResourceNodeRepository();
776
777
        $title = basename($file);
778
        // @todo improve criteria to avoid giving the wrong file.
779
        $criteria = ['slug' => $title];
780
781
        $resourceNode = $nodeRepository->findOneBy($criteria);
782
783
        if (null === $resourceNode) {
784
            throw new NotFoundHttpException();
785
        }
786
787
        return $this->showFile($request, $resourceNode, $mode, $glide,$filter);*/
788
    }
0 ignored issues
show
Bug Best Practice introduced by
In this branch, the function will implicitly return null which is incompatible with the type-hinted return Symfony\Component\HttpFoundation\Response. Consider adding a return statement or allowing null as return value.

For hinted functions/methods where all return statements with the correct type are only reachable via conditions, ?null? gets implicitly returned which may be incompatible with the hinted type. Let?s take a look at an example:

interface ReturnsInt {
    public function returnsIntHinted(): int;
}

class MyClass implements ReturnsInt {
    public function returnsIntHinted(): int
    {
        if (foo()) {
            return 123;
        }
        // here: null is implicitly returned
    }
}
Loading history...
789
790
    /**
791
     * @Route("/{tool}/{type}/{id}/download", methods={"GET"}, name="chamilo_core_resource_download")
792
     */
793
    public function downloadAction(Request $request)
794
    {
795
        $resourceNodeId = (int) $request->get('id');
796
        $courseNode = $this->getCourse()->getResourceNode();
797
798
        $repo = $this->getRepositoryFromRequest($request);
799
800
        if (empty($resourceNodeId)) {
801
            $resourceNode = $courseNode;
802
        } else {
803
            $resourceNode = $repo->getResourceNodeRepository()->find($resourceNodeId);
804
        }
805
806
        $type = $repo->getResourceType();
807
808
        if (null === $resourceNode) {
809
            throw new NotFoundHttpException();
810
        }
811
812
        $this->denyAccessUnlessGranted(
813
            ResourceNodeVoter::VIEW,
814
            $resourceNode,
815
            $this->trans('Unauthorised access to resource')
816
        );
817
818
        // If resource node has a file just download it. Don't download the children.
819
        if ($resourceNode->hasResourceFile()) {
820
            // Redirect to download single file.
821
            return $this->showFile($request, $resourceNode, 'download');
822
        }
823
824
        $zipName = $resourceNode->getSlug().'.zip';
825
        $rootNodePath = $resourceNode->getPathForDisplay();
826
827
        $resourceNodeRepo = $repo->getResourceNodeRepository();
828
829
        $criteria = Criteria::create()
830
            ->where(Criteria::expr()->neq('resourceFile', null)) // must have a file
831
           // ->andWhere(Criteria::expr()->eq('resourceType', $type))
832
        ;
833
834
        /** @var ArrayCollection|ResourceNode[] $children */
835
        /** @var QueryBuilder $children */
836
        $qb = $resourceNodeRepo->getChildrenQueryBuilder($resourceNode);
837
        $qb->addCriteria($criteria);
838
        $children = $qb->getQuery()->getResult();
839
840
        $response = new StreamedResponse(function () use ($rootNodePath, $zipName, $children, $repo) {
841
            // Define suitable options for ZipStream Archive.
842
            $options = new Archive();
843
            $options->setContentType('application/octet-stream');
844
            //initialise zipstream with output zip filename and options.
845
            $zip = new ZipStream($zipName, $options);
846
847
            /** @var ResourceNode $node */
848
            foreach ($children as $node) {
849
                $resourceFile = $node->getResourceFile();
850
                $systemName = $resourceFile->getFile()->getPathname();
851
                $stream = $repo->getResourceNodeFileStream($node);
852
                //error_log($node->getPathForDisplay());
853
                $fileToDisplay = str_replace($rootNodePath, '', $node->getPathForDisplay());
854
                $zip->addFileFromStream($fileToDisplay, $stream);
855
            }
856
            $zip->finish();
857
        });
858
859
        $disposition = $response->headers->makeDisposition(
860
            ResponseHeaderBag::DISPOSITION_ATTACHMENT,
861
            Transliterator::transliterate($zipName)
862
        );
863
        $response->headers->set('Content-Disposition', $disposition);
864
        $response->headers->set('Content-Type', 'application/octet-stream');
865
866
        return $response;
867
    }
868
869
    /**
870
     * Upload form.
871
     *
872
     * @Route("/{tool}/{type}/{id}/upload", name="chamilo_core_resource_upload", methods={"GET", "POST"},
873
     *                                      options={"expose"=true})
874
     */
875
    public function uploadAction(Request $request, $tool, $type, $id): Response
876
    {
877
        $repository = $this->getRepositoryFromRequest($request);
878
        $resourceNode = $repository->getResourceNodeRepository()->find($id);
879
880
        $this->denyAccessUnlessGranted(
881
            ResourceNodeVoter::EDIT,
882
            $resourceNode,
883
            $this->trans('Unauthorised access to resource')
884
        );
885
886
        $this->setBreadCrumb($request);
887
888
        $routeParams = $this->getResourceParams($request);
889
        $routeParams['tool'] = $tool;
890
        $routeParams['type'] = $type;
891
        $routeParams['id'] = $id;
892
893
        return $this->render(
894
            '@ChamiloTheme/Resource/upload.html.twig',
895
            $routeParams
896
        );
897
    }
898
899
    public function setBreadCrumb(Request $request)
900
    {
901
        $tool = $request->get('tool');
902
        $type = $request->get('type');
903
        $resourceNodeId = $request->get('id');
904
905
        $routeParams = $this->getResourceParams($request);
906
907
        if (!empty($resourceNodeId)) {
908
            $breadcrumb = $this->getBreadCrumb();
909
            $toolParams = $routeParams;
910
            $toolParams['id'] = null;
911
912
            // Root tool link
913
            $breadcrumb->addChild(
914
                $this->trans($tool),
915
                [
916
                    'uri' => $this->generateUrl(
917
                        'chamilo_core_resource_index',
918
                        $toolParams
919
                    ),
920
                ]
921
            );
922
923
            $repo = $this->getRepositoryFromRequest($request);
924
925
            /** @var AbstractResource $parent */
926
            $originalResource = $repo->findOneBy(['resourceNode' => $resourceNodeId]);
927
            if ($originalResource === null) {
928
                return;
929
            }
930
            $parent = $originalParent = $originalResource->getResourceNode();
931
932
            $parentList = [];
933
            while ($parent !== null) {
934
                if ($type !== $parent->getResourceType()->getName()) {
935
                    break;
936
                }
937
                $parent = $parent->getParent();
938
                if ($parent) {
939
                    $resource = $repo->findOneBy(['resourceNode' => $parent->getId()]);
940
                    if ($resource) {
941
                        $parentList[] = $resource;
942
                    }
943
                }
944
            }
945
946
            $parentList = array_reverse($parentList);
947
            /** @var AbstractResource $item */
948
            foreach ($parentList as $item) {
949
                $params = $routeParams;
950
                $params['id'] = $item->getResourceNode()->getId();
951
                $breadcrumb->addChild(
952
                    $item->getResourceName(),
953
                    [
954
                        'uri' => $this->generateUrl(
955
                            'chamilo_core_resource_list',
956
                            $params
957
                        ),
958
                    ]
959
                );
960
            }
961
962
            $params = $routeParams;
963
            $params['id'] = $originalParent->getId();
964
965
            $breadcrumb->addChild(
966
                $originalResource->getResourceName(),
0 ignored issues
show
Bug introduced by
The method getResourceName() does not exist on Chamilo\CoreBundle\Entit...source\AbstractResource. Did you maybe mean getResourceNode()? ( Ignorable by Annotation )

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

966
                $originalResource->/** @scrutinizer ignore-call */ 
967
                                   getResourceName(),

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...
967
                [
968
                    'uri' => $this->generateUrl(
969
                        'chamilo_core_resource_list',
970
                        $params
971
                    ),
972
                ]
973
            );
974
        }
975
    }
976
977
    private function getParentResourceNode(Request $request): ResourceNode
978
    {
979
        $parentNodeId = $request->get('id');
980
981
        $parentResourceNode = null;
982
983
        if (empty($parentNodeId)) {
984
            if ($this->hasCourse()) {
985
                $parentResourceNode = $this->getCourse()->getResourceNode();
986
            } else {
987
                if ($this->isGranted('IS_AUTHENTICATED_REMEMBERED')) {
988
                    /** @var User $user */
989
                    $parentResourceNode = $this->getUser()->getResourceNode();
990
                }
991
            }
992
        } else {
993
            $repo = $this->getDoctrine()->getRepository('ChamiloCoreBundle:Resource\ResourceNode');
994
            $parentResourceNode = $repo->find($parentNodeId);
995
        }
996
997
        if (null === $parentResourceNode) {
998
            throw new AccessDeniedException();
999
        }
1000
1001
        return $parentResourceNode;
1002
    }
1003
1004
    /**
1005
     * @param string $mode
1006
     * @param string $filter
1007
     *
1008
     * @return mixed|StreamedResponse
1009
     */
1010
    private function showFile(Request $request, ResourceNode $resourceNode, $mode = 'show', Glide $glide = null, $filter = '')
1011
    {
1012
        $this->denyAccessUnlessGranted(
1013
            ResourceNodeVoter::VIEW,
1014
            $resourceNode,
1015
            $this->trans('Unauthorised access to resource')
1016
        );
1017
1018
        $repo = $this->getRepositoryFromRequest($request);
1019
        $resourceFile = $resourceNode->getResourceFile();
1020
1021
        if (!$resourceFile) {
0 ignored issues
show
introduced by
$resourceFile is of type Chamilo\CoreBundle\Entity\Resource\ResourceFile, thus it always evaluated to true.
Loading history...
1022
            throw new NotFoundHttpException($this->trans('File not found for resource'));
1023
        }
1024
1025
        //$fileName = $resourceFile->getOriginalName();
1026
        $fileName = $resourceNode->getSlug();
1027
        $filePath = $resourceFile->getFile()->getPathname();
1028
        $mimeType = $resourceFile->getMimeType();
1029
1030
        switch ($mode) {
1031
            case 'download':
1032
                $forceDownload = true;
1033
                break;
1034
            case 'show':
1035
            default:
1036
                $forceDownload = false;
1037
                // If it's an image then send it to Glide.
1038
                if (strpos($mimeType, 'image') !== false) {
1039
                    $server = $glide->getServer();
0 ignored issues
show
Bug introduced by
The method getServer() 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

1039
                    /** @scrutinizer ignore-call */ 
1040
                    $server = $glide->getServer();

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...
1040
                    $params = $request->query->all();
1041
1042
                    // The filter overwrites the params from get
1043
                    if (!empty($filter)) {
1044
                        $params = $glide->getFilters()[$filter] ?? [];
1045
                    }
1046
1047
                    // The image was cropped manually by the user, so we force to render this version,
1048
                    // no matter other crop parameters.
1049
                    $crop = $resourceFile->getCrop();
1050
                    if (!empty($crop)) {
1051
                        $params['crop'] = $crop;
1052
                    }
1053
1054
                    return $server->getImageResponse($filePath, $params);
1055
                }
1056
                break;
1057
        }
1058
1059
        $stream = $repo->getResourceNodeFileStream($resourceNode);
1060
1061
        //$stream = $this->fs->readStream($resourceNode);
1062
        $response = new StreamedResponse(function () use ($stream): void {
1063
            stream_copy_to_stream($stream, fopen('php://output', 'wb'));
0 ignored issues
show
Bug introduced by
It seems like fopen('php://output', 'wb') can also be of type false; however, parameter $dest of stream_copy_to_stream() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

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

1063
            stream_copy_to_stream($stream, /** @scrutinizer ignore-type */ fopen('php://output', 'wb'));
Loading history...
Bug introduced by
It seems like $stream can also be of type string; however, parameter $source of stream_copy_to_stream() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

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

1063
            stream_copy_to_stream(/** @scrutinizer ignore-type */ $stream, fopen('php://output', 'wb'));
Loading history...
1064
        });
1065
        $disposition = $response->headers->makeDisposition(
1066
            $forceDownload ? ResponseHeaderBag::DISPOSITION_ATTACHMENT : ResponseHeaderBag::DISPOSITION_INLINE,
1067
            $fileName
1068
            //Transliterator::transliterate($fileName)
1069
        );
1070
        $response->headers->set('Content-Disposition', $disposition);
1071
        $response->headers->set('Content-Type', $mimeType ?: 'application/octet-stream');
1072
1073
        return $response;
1074
    }
1075
1076
    /**
1077
     * @param string $fileType
1078
     *
1079
     * @return RedirectResponse|Response
1080
     */
1081
    private function createResource(Request $request, $fileType = 'file')
1082
    {
1083
        $resourceNodeParentId = $request->get('id');
1084
1085
        $repository = $this->getRepositoryFromRequest($request);
1086
1087
        // Default parent node is course.
1088
        $parentNode = $this->getParentResourceNode($request);
1089
        //var_dump($parentNode->getPath());
1090
1091
        $this->denyAccessUnlessGranted(
1092
            ResourceNodeVoter::CREATE,
1093
            $parentNode,
1094
            $this->trans('Unauthorised access to resource')
1095
        );
1096
1097
        $form = $repository->getForm($this->container->get('form.factory'), null);
1098
1099
        if ($fileType === 'file') {
1100
            $resourceParams = $this->getResourceParams($request);
1101
            $form->add(
1102
                'content',
1103
                CKEditorType::class,
1104
                [
1105
                    'mapped' => false,
1106
                    'config' => [
1107
                        'filebrowserImageBrowseRoute' => 'resources_filemanager',
1108
                        'filebrowserImageBrowseRouteParameters' => $resourceParams,
1109
                        'fullPage' => true,
1110
                    ],
1111
                ]
1112
            );
1113
        }
1114
1115
        $form->handleRequest($request);
1116
        if ($form->isSubmitted() && $form->isValid()) {
1117
            $em = $this->getDoctrine()->getManager();
1118
1119
            $course = $this->getCourse();
1120
            $session = $this->getSession();
1121
1122
            /** @var AbstractResource $newResource */
1123
            $newResource = $repository->saveResource($form, $course, $session, $fileType);
1124
1125
            $file = null;
1126
            if ($fileType === 'file') {
1127
                $content = $form->get('content')->getViewData();
1128
                $newResource->setTitle($newResource->getTitle().'.html');
0 ignored issues
show
Bug introduced by
The method setTitle() does not exist on Chamilo\CoreBundle\Entit...source\AbstractResource. It seems like you code against a sub-type of Chamilo\CoreBundle\Entit...source\AbstractResource such as Chamilo\CoreBundle\Entity\Course or Chamilo\CourseBundle\Entity\CLink or Chamilo\CourseBundle\Entity\CAnnouncement or Chamilo\CourseBundle\Entity\CQuiz or Chamilo\CourseBundle\Entity\CDocument or Chamilo\CourseBundle\Entity\CQuizQuestionCategory. ( Ignorable by Annotation )

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

1128
                $newResource->/** @scrutinizer ignore-call */ 
1129
                              setTitle($newResource->getTitle().'.html');
Loading history...
Bug introduced by
The method getTitle() does not exist on Chamilo\CoreBundle\Entit...source\AbstractResource. It seems like you code against a sub-type of Chamilo\CoreBundle\Entit...source\AbstractResource such as Chamilo\CoreBundle\Entity\Course or Chamilo\CourseBundle\Entity\CLink or Chamilo\CourseBundle\Entity\CAnnouncement or Chamilo\CourseBundle\Entity\CQuiz or Chamilo\CourseBundle\Entity\CDocument or Chamilo\CourseBundle\Entity\CQuizQuestionCategory. ( Ignorable by Annotation )

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

1128
                $newResource->setTitle($newResource->/** @scrutinizer ignore-call */ getTitle().'.html');
Loading history...
1129
                $fileName = $newResource->getTitle();
1130
1131
                $handle = tmpfile();
1132
                fwrite($handle, $content);
0 ignored issues
show
Bug introduced by
It seems like $handle can also be of type false; however, parameter $handle of fwrite() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

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

1132
                fwrite(/** @scrutinizer ignore-type */ $handle, $content);
Loading history...
1133
                $meta = stream_get_meta_data($handle);
0 ignored issues
show
Bug introduced by
It seems like $handle can also be of type false; however, parameter $stream of stream_get_meta_data() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

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

1133
                $meta = stream_get_meta_data(/** @scrutinizer ignore-type */ $handle);
Loading history...
1134
                $file = new UploadedFile($meta['uri'], $fileName, 'text/html', null, true);
1135
                $em->persist($newResource);
1136
            }
1137
1138
            $resourceNode = $repository->createNodeForResource($newResource, $this->getUser(), $parentNode, $file);
1139
            $em->persist($resourceNode);
1140
1141
            $repository->addResourceNodeToCourse(
1142
                $resourceNode,
1143
                ResourceLink::VISIBILITY_PUBLISHED,
1144
                $course,
1145
                $session,
1146
                null
1147
            );
1148
1149
            $em->flush();
1150
1151
            // Loops all sharing options
1152
            /*foreach ($shareList as $share) {
1153
                $idList = [];
1154
                if (isset($share['search'])) {
1155
                    $idList = explode(',', $share['search']);
1156
                }
1157
1158
                $resourceRight = null;
1159
                if (isset($share['mask'])) {
1160
                    $resourceRight = new ResourceRight();
1161
                    $resourceRight
1162
                        ->setMask($share['mask'])
1163
                        ->setRole($share['role'])
1164
                    ;
1165
                }
1166
1167
                // Build links
1168
                switch ($share['sharing']) {
1169
                    case 'everyone':
1170
                        $repository->addResourceToEveryone(
1171
                            $resourceNode,
1172
                            $resourceRight
1173
                        );
1174
                        break;
1175
                    case 'course':
1176
                        $repository->addResourceToCourse(
1177
                            $resourceNode,
1178
                            $course,
1179
                            $resourceRight
1180
                        );
1181
                        break;
1182
                    case 'session':
1183
                        $repository->addResourceToSession(
1184
                            $resourceNode,
1185
                            $course,
1186
                            $session,
1187
                            $resourceRight
1188
                        );
1189
                        break;
1190
                    case 'user':
1191
                        // Only for me
1192
                        if (isset($share['only_me'])) {
1193
                            $repository->addResourceOnlyToMe($resourceNode);
1194
                        } else {
1195
                            // To other users
1196
                            $repository->addResourceToUserList($resourceNode, $idList);
1197
                        }
1198
                        break;
1199
                    case 'group':
1200
                        // @todo
1201
                        break;
1202
                }*/
1203
            //}
1204
            $em->flush();
1205
            $this->addFlash('success', $this->trans('Saved'));
1206
1207
            $params = $this->getResourceParams($request);
1208
            $params['id'] = $resourceNodeParentId;
1209
1210
            return $this->redirectToRoute(
1211
                'chamilo_core_resource_list',
1212
                $params
1213
            );
1214
        }
1215
1216
        switch ($fileType) {
1217
            case 'folder':
1218
                $template = '@ChamiloTheme/Resource/new_folder.html.twig';
1219
                break;
1220
            case 'file':
1221
                $template = '@ChamiloTheme/Resource/new.html.twig';
1222
                break;
1223
        }
1224
1225
        return $this->render(
1226
            $template,
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $template does not seem to be defined for all execution paths leading up to this point.
Loading history...
1227
            [
1228
                'form' => $form->createView(),
1229
                'parent' => $resourceNodeParentId,
1230
                'file_type' => $fileType,
1231
            ]
1232
        );
1233
    }
1234
}
1235