Completed
Push — master ( 76efa7...03cf40 )
by Julito
12:18
created

ResourceController::viewAction()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 13
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 8
c 0
b 0
f 0
nc 2
nop 2
dl 0
loc 13
rs 10
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\Export\CSVExport;
9
use APY\DataGridBundle\Grid\Export\ExcelExport;
10
use APY\DataGridBundle\Grid\Grid;
11
use APY\DataGridBundle\Grid\Row;
12
use APY\DataGridBundle\Grid\Source\Entity;
13
use Chamilo\CoreBundle\Component\Utils\Glide;
14
use Chamilo\CoreBundle\Entity\Resource\AbstractResource;
15
use Chamilo\CoreBundle\Entity\Resource\ResourceLink;
16
use Chamilo\CoreBundle\Entity\Resource\ResourceNode;
17
use Chamilo\CoreBundle\Security\Authorization\Voter\ResourceNodeVoter;
18
use Chamilo\CourseBundle\Controller\CourseControllerInterface;
19
use Chamilo\CourseBundle\Controller\CourseControllerTrait;
20
use Chamilo\CourseBundle\Entity\CDocument;
21
use Chamilo\CourseBundle\Repository\CDocumentRepository;
22
use Doctrine\Common\Collections\ArrayCollection;
23
use Doctrine\Common\Collections\Criteria;
24
use Doctrine\ORM\QueryBuilder;
25
use FOS\CKEditorBundle\Form\Type\CKEditorType;
26
use League\Flysystem\Filesystem;
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 Vich\UploaderBundle\Util\Transliterator;
39
use ZipStream\Option\Archive;
40
use ZipStream\ZipStream;
41
42
/**
43
 * Class ResourceController.
44
 *
45
 * @Route("/resources")
46
 *
47
 * @author Julio Montoya <[email protected]>.
48
 */
49
class ResourceController extends AbstractResourceController implements CourseControllerInterface
50
{
51
    use CourseControllerTrait;
52
53
    /**
54
     * @Route("/{tool}/{type}", name="chamilo_core_resource_index")
55
     *
56
     * Example: /document/files
57
     * For the tool value check the Tool entity.
58
     * For the type value check the ResourceType entity.
59
     */
60
    public function indexAction(Request $request, Grid $grid): Response
61
    {
62
        $tool = $request->get('tool');
63
        $type = $request->get('type');
64
65
        $grid = $this->getGrid($request, $grid);
66
67
        $breadcrumb = $this->breadcrumbBlockService;
68
        $breadcrumb->addChild(
69
            $this->trans('Documents'),
70
            [
71
                'uri' => '#',
72
            ]
73
        );
74
75
        // The base resource node is the course.
76
        $id = $this->getCourse()->getResourceNode()->getId();
77
78
        return $grid->getGridResponse(
79
            '@ChamiloTheme/Resource/index.html.twig',
80
            ['tool' => $tool, 'type' => $type, 'id' => $id]
81
        );
82
    }
83
84
    /**
85
     * @param int $resourceNodeId
86
     *
87
     * @return Grid
88
     */
89
    public function getGrid(Request $request, Grid $grid, $resourceNodeId = 0)
90
    {
91
        $tool = $request->get('tool');
92
        $type = $request->get('type');
93
        $id = (int) $request->get('id');
94
95
        $repository = $this->getRepositoryFromRequest($request);
96
        $class = $repository->getRepository()->getClassName();
97
        $source = new Entity($class);
98
99
        $course = $this->getCourse();
100
        $session = $this->getSession();
101
102
        $parent = $course->getResourceNode();
103
        if (!empty($resourceNodeId)) {
104
            $parent = $repository->getResourceNodeRepository()->find($resourceNodeId);
105
        }
106
107
        $qb = $repository->getResourcesByCourse($course, $session, null, $parent);
108
109
        // 3. Set QueryBuilder to the source.
110
        $source->initQueryBuilder($qb);
111
        $grid->setSource($source);
112
113
        $grid->setRouteUrl(
114
            $this->generateUrl(
115
                'chamilo_core_resource_list',
116
                [
117
                    'tool' => $tool,
118
                    'type' => $type,
119
                    'cidReq' => $this->getCourse()->getCode(),
120
                    'id_session' => $this->getSessionId(),
121
                    'id' => $id,
122
                ]
123
            )
124
        );
125
126
        $title = $grid->getColumn('title');
127
        $title->setSafe(false); // allows links in the title
128
129
        //$grid->hideFilters();
130
        //$grid->setLimits(20);
131
        //$grid->isReadyForRedirect();
132
        //$grid->setMaxResults(1);
133
        //$grid->setLimits(2);
134
135
        $translation = $this->translator;
136
        $courseIdentifier = $course->getCode();
137
138
        $routeParams = [
139
            'tool' => $tool,
140
            'type' => $type,
141
            'cidReq' => $courseIdentifier,
142
            'id_session' => $this->getSessionId(),
143
            'id',
144
        ];
145
146
        // Title link.
147
        $grid->getColumn('title')->setTitle($this->trans('Name'));
148
        $grid->getColumn('filetype')->setTitle($this->trans('Type'));
149
150
        $grid->getColumn('title')->manipulateRenderCell(
151
            function ($value, Row $row, $router) use ($routeParams) {
152
                /** @var Router $router */
153
                /** @var CDocument $entity */
154
                $entity = $row->getEntity();
155
                $resourceNode = $entity->getResourceNode();
156
                $id = $resourceNode->getId();
157
158
                $myParams = $routeParams;
159
                $myParams['id'] = $id;
160
                unset($myParams[0]);
161
162
                $icon = $resourceNode->getIcon().' &nbsp;';
163
                if ($resourceNode->hasResourceFile()) {
164
                    /*$url = $router->generate(
165
                        'chamilo_core_resource_show',
166
                        $myParams
167
                    );*/
168
169
                    if ($resourceNode->isResourceFileAnImage()) {
170
                        $url = $router->generate(
171
                            'chamilo_core_resource_view',
172
                            $myParams
173
                        );
174
175
                        return $icon.'<a data-fancybox="gallery" href="'.$url.'">'.$value.'</a>';
176
                    }
177
178
                    if ($resourceNode->isResourceFileAVideo()) {
179
                        $url = $router->generate(
180
                            'chamilo_core_resource_view',
181
                            $myParams
182
                        );
183
184
                        return '
185
                        <video width="640" height="320" controls id="video'.$id.'" controls preload="metadata" style="display:none;">
186
                            <source src="'.$url.'" type="video/mp4">
187
                            Your browser doesn\'t support HTML5 video tag.
188
                        </video>
189
                        '.$icon.' <a data-fancybox="gallery"  data-width="640" data-height="360" href="#video'.$id.'">'.$value.'</a>';
190
                    }
191
192
                    $url = $router->generate(
193
                        'chamilo_core_resource_preview',
194
                        $myParams
195
                    );
196
197
                    return $icon.'<a data-fancybox="gallery" data-type="iframe" data-src="'.$url.'" href="javascript:;" >'.$value.'</a>';
198
                } else {
199
                    $url = $router->generate(
200
                        'chamilo_core_resource_list',
201
                        $myParams
202
                    );
203
204
                    return $icon.'<a href="'.$url.'">'.$value.'</a>';
205
                }
206
            }
207
        );
208
209
        $grid->getColumn('filetype')->manipulateRenderCell(
210
            function ($value, Row $row, $router) use ($routeParams) {
0 ignored issues
show
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...
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

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

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
817
818
        $response = new StreamedResponse(function () use ($rootNodePath, $zipName, $children, $fileSystem) {
0 ignored issues
show
Unused Code introduced by
$response = new Symfony\...ion(...) { /* ... */ }) is not reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
819
            // Define suitable options for ZipStream Archive.
820
            $options = new Archive();
821
            $options->setContentType('application/octet-stream');
822
            //initialise zipstream with output zip filename and options.
823
            $zip = new ZipStream($zipName, $options);
824
825
            /** @var ResourceNode $node */
826
            foreach ($children as $node) {
827
                $resourceFile = $node->getResourceFile();
828
                $systemName = $resourceFile->getFile()->getPathname();
829
                $stream = $fileSystem->readStream($systemName);
830
                //error_log($node->getPathForDisplay());
831
                $fileToDisplay = str_replace($rootNodePath, '', $node->getPathForDisplay());
832
                $zip->addFileFromStream($fileToDisplay, $stream);
833
            }
834
            //$data = $repo->getDocumentContent($not_deleted_file['id']);
835
            //$zip->addFile($not_deleted_file['path'], $data);
836
            $zip->finish();
837
        });
838
839
        $disposition = $response->headers->makeDisposition(
840
            ResponseHeaderBag::DISPOSITION_ATTACHMENT,
841
            Transliterator::transliterate($zipName)
842
        );
843
        $response->headers->set('Content-Disposition', $disposition);
844
        $response->headers->set('Content-Type', 'application/octet-stream');
845
846
        return $response;
847
    }
848
849
    /**
850
     * Upload form.
851
     *
852
     * @Route("/{tool}/{type}/{id}/upload", name="chamilo_core_resource_upload", methods={"GET", "POST"},
853
     *                                      options={"expose"=true})
854
     */
855
    public function uploadAction(Request $request, $tool, $type, $id): Response
856
    {
857
        $repository = $this->getRepositoryFromRequest($request);
858
        $resourceNode = $repository->getResourceNodeRepository()->find($id);
859
860
        $this->denyAccessUnlessGranted(
861
            ResourceNodeVoter::EDIT,
862
            $resourceNode,
863
            $this->trans('Unauthorised access to resource')
864
        );
865
866
        $this->setBreadCrumb($request);
867
        //$helper = $this->container->get('oneup_uploader.templating.uploader_helper');
868
        //$endpoint = $helper->endpoint('courses');
869
870
        return $this->render(
871
            '@ChamiloTheme/Resource/upload.html.twig',
872
            [
873
                'id' => $id,
874
                'type' => $type,
875
                'tool' => $tool,
876
                'cidReq' => $this->getCourse()->getCode(),
877
                'id_session' => $this->getSessionId(),
878
            ]
879
        );
880
    }
881
882
    public function setBreadCrumb(Request $request)
883
    {
884
        $tool = $request->get('tool');
885
        $type = $request->get('type');
886
        $resourceNodeId = $request->get('id');
887
        $courseCode = $request->get('cidReq');
888
        $sessionId = $request->get('id_session');
889
890
        if (!empty($resourceNodeId)) {
891
            $breadcrumb = $this->breadcrumbBlockService;
892
893
            // Root tool link
894
            $breadcrumb->addChild(
895
                $this->translator->trans('Documents'),
896
                [
897
                    'uri' => $this->generateUrl(
898
                        'chamilo_core_resource_index',
899
                        ['tool' => $tool, 'type' => $type, 'cidReq' => $courseCode, 'id_session' => $sessionId]
900
                    ),
901
                ]
902
            );
903
904
            $repo = $this->getRepositoryFromRequest($request);
905
906
            /** @var AbstractResource $parent */
907
            $originalResource = $repo->findOneBy(['resourceNode' => $resourceNodeId]);
908
            if ($originalResource === null) {
909
                return;
910
            }
911
            $parent = $originalParent = $originalResource->getResourceNode();
912
913
            $parentList = [];
914
            while ($parent !== null) {
915
                if ($type !== $parent->getResourceType()->getName()) {
916
                    break;
917
                }
918
                $parent = $parent->getParent();
919
                if ($parent) {
920
                    $resource = $repo->findOneBy(['resourceNode' => $parent->getId()]);
921
                    if ($resource) {
922
                        $parentList[] = $resource;
923
                    }
924
                }
925
            }
926
927
            $parentList = array_reverse($parentList);
928
            /** @var AbstractResource $item */
929
            foreach ($parentList as $item) {
930
                $breadcrumb->addChild(
931
                    $item->getResourceName(),
932
                    [
933
                        'uri' => $this->generateUrl(
934
                            'chamilo_core_resource_list',
935
                            [
936
                                'tool' => $tool,
937
                                'type' => $type,
938
                                'id' => $item->getResourceNode()->getId(),
939
                                'cidReq' => $courseCode,
940
                                'id_session' => $sessionId,
941
                            ]
942
                        ),
943
                    ]
944
                );
945
            }
946
947
            $breadcrumb->addChild(
948
                $originalResource->getResourceName(),
949
                [
950
                    'uri' => $this->generateUrl(
951
                        'chamilo_core_resource_list',
952
                        [
953
                            'tool' => $tool,
954
                            'type' => $type,
955
                            'id' => $originalParent->getId(),
956
                            'cidReq' => $courseCode,
957
                            'id_session' => $sessionId,
958
                        ]
959
                    ),
960
                ]
961
            );
962
        }
963
    }
964
965
    /**
966
     * @param string $mode   show or download
967
     * @param string $filter
968
     *
969
     * @return mixed|StreamedResponse
970
     */
971
    private function showFile(Request $request, ResourceNode $resourceNode, Glide $glide, $mode = 'show', $filter = '')
972
    {
973
        $this->denyAccessUnlessGranted(
974
            ResourceNodeVoter::VIEW,
975
            $resourceNode,
976
            $this->trans('Unauthorised access to resource')
977
        );
978
        $resourceFile = $resourceNode->getResourceFile();
979
980
        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...
981
            throw new NotFoundHttpException();
982
        }
983
984
        //$fileName = $resourceFile->getOriginalName();
985
        $fileName = $resourceNode->getSlug();
986
        $filePath = $resourceFile->getFile()->getPathname();
987
        $mimeType = $resourceFile->getMimeType();
988
989
        switch ($mode) {
990
            case 'download':
991
                $forceDownload = true;
992
                break;
993
            case 'show':
994
            default:
995
                $forceDownload = false;
996
                // If it's an image then send it to Glide.
997
                if (strpos($mimeType, 'image') !== false) {
998
                    $server = $glide->getServer();
999
                    $params = $request->query->all();
1000
1001
                    // The filter overwrites the params from get
1002
                    if (!empty($filter)) {
1003
                        $params = $glide->getFilters()[$filter] ?? [];
1004
                    }
1005
1006
                    // The image was cropped manually by the user, so we force to render this version,
1007
                    // no matter other crop parameters.
1008
                    $crop = $resourceFile->getCrop();
1009
                    if (!empty($crop)) {
1010
                        $params['crop'] = $crop;
1011
                    }
1012
1013
                    return $server->getImageResponse($filePath, $params);
1014
                }
1015
                break;
1016
        }
1017
1018
        $stream = $this->fs->readStream($filePath);
1019
        $response = new StreamedResponse(function () use ($stream): void {
1020
            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

1020
            stream_copy_to_stream($stream, /** @scrutinizer ignore-type */ fopen('php://output', 'wb'));
Loading history...
1021
        });
1022
        $disposition = $response->headers->makeDisposition(
1023
            $forceDownload ? ResponseHeaderBag::DISPOSITION_ATTACHMENT : ResponseHeaderBag::DISPOSITION_INLINE,
1024
            $fileName
1025
            //Transliterator::transliterate($fileName)
1026
        );
1027
        $response->headers->set('Content-Disposition', $disposition);
1028
        $response->headers->set('Content-Type', $mimeType ?: 'application/octet-stream');
1029
1030
        return $response;
1031
    }
1032
1033
    /**
1034
     * @param string $fileType
1035
     *
1036
     * @return RedirectResponse|Response
1037
     */
1038
    private function createResource(Request $request, $fileType = 'file')
1039
    {
1040
        $tool = $request->get('tool');
1041
        $type = $request->get('type');
1042
        $resourceNodeParentId = $request->get('id');
1043
1044
        $repository = $this->getRepositoryFromRequest($request);
1045
1046
        $form = $repository->getForm($this->container->get('form.factory'));
1047
1048
        if ($fileType === 'file') {
1049
            $form->add(
1050
                'content',
1051
                CKEditorType::class,
1052
                [
1053
                    'mapped' => false,
1054
                    'config' => [
1055
                        'filebrowserImageBrowseRoute' => 'editor_filemanager',
1056
                        'filebrowserImageBrowseRouteParameters' => [
1057
                            'tool' => $tool,
1058
                            'type' => $type,
1059
                            'cidReq' => $this->getCourse()->getCode(),
1060
                            'id_session' => $this->getSessionId(),
1061
                            'id' => $resourceNodeParentId,
1062
                        ],
1063
                    ],
1064
                ]
1065
            );
1066
        }
1067
1068
        $course = $this->getCourse();
1069
        $session = $this->getSession();
1070
        // Default parent node is course.
1071
        $parentNode = $course->getResourceNode();
1072
        if (!empty($resourceNodeParentId)) {
1073
            // Get parent node.
1074
            $parentNode = $repository->getResourceNodeRepository()->find($resourceNodeParentId);
1075
        }
1076
1077
        $form->handleRequest($request);
1078
        if ($form->isSubmitted() && $form->isValid()) {
1079
            $em = $this->getDoctrine()->getManager();
1080
1081
            /** @var CDocument $newResource */
1082
            $newResource = $form->getData();
1083
1084
            $newResource
1085
                ->setCourse($course)
1086
                ->setSession($session)
1087
                ->setFiletype($fileType)
1088
                //->setTitle($title) // already added in $form->getData()
1089
                ->setReadonly(false)
1090
            ;
1091
1092
            $file = null;
1093
            if ($fileType === 'file') {
1094
                $content = $form->get('content')->getViewData();
1095
                $newResource->setTitle($newResource->getTitle().'.html');
1096
                $fileName = $newResource->getTitle();
1097
1098
                $handle = tmpfile();
1099
                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

1099
                fwrite(/** @scrutinizer ignore-type */ $handle, $content);
Loading history...
1100
                $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

1100
                $meta = stream_get_meta_data(/** @scrutinizer ignore-type */ $handle);
Loading history...
1101
                $file = new UploadedFile($meta['uri'], $fileName, null, null, true);
1102
                $em->persist($newResource);
1103
            }
1104
1105
            $resourceNode = $repository->createNodeForResource($newResource, $this->getUser(), $parentNode, $file);
1106
            $em->persist($resourceNode);
1107
1108
            $repository->addResourceNodeToCourse(
1109
                $resourceNode,
1110
                ResourceLink::VISIBILITY_PUBLISHED,
1111
                $course,
1112
                $session,
1113
                null
1114
            );
1115
1116
            $em->flush();
1117
1118
            // Loops all sharing options
1119
            /*foreach ($shareList as $share) {
1120
                $idList = [];
1121
                if (isset($share['search'])) {
1122
                    $idList = explode(',', $share['search']);
1123
                }
1124
1125
                $resourceRight = null;
1126
                if (isset($share['mask'])) {
1127
                    $resourceRight = new ResourceRight();
1128
                    $resourceRight
1129
                        ->setMask($share['mask'])
1130
                        ->setRole($share['role'])
1131
                    ;
1132
                }
1133
1134
                // Build links
1135
                switch ($share['sharing']) {
1136
                    case 'everyone':
1137
                        $repository->addResourceToEveryone(
1138
                            $resourceNode,
1139
                            $resourceRight
1140
                        );
1141
                        break;
1142
                    case 'course':
1143
                        $repository->addResourceToCourse(
1144
                            $resourceNode,
1145
                            $course,
1146
                            $resourceRight
1147
                        );
1148
                        break;
1149
                    case 'session':
1150
                        $repository->addResourceToSession(
1151
                            $resourceNode,
1152
                            $course,
1153
                            $session,
1154
                            $resourceRight
1155
                        );
1156
                        break;
1157
                    case 'user':
1158
                        // Only for me
1159
                        if (isset($share['only_me'])) {
1160
                            $repository->addResourceOnlyToMe($resourceNode);
1161
                        } else {
1162
                            // To other users
1163
                            $repository->addResourceToUserList($resourceNode, $idList);
1164
                        }
1165
                        break;
1166
                    case 'group':
1167
                        // @todo
1168
                        break;
1169
                }*/
1170
            //}
1171
            $em->flush();
1172
            $this->addFlash('success', $this->trans('Saved'));
1173
1174
            return $this->redirectToRoute(
1175
                'chamilo_core_resource_list',
1176
                [
1177
                    'id' => $resourceNodeParentId,
1178
                    'tool' => $tool,
1179
                    'type' => $type,
1180
                    'cidReq' => $this->getCourse()->getCode(),
1181
                    'id_session' => $this->getSessionId(),
1182
                ]
1183
            );
1184
        }
1185
1186
        switch ($fileType) {
1187
            case 'folder':
1188
                $template = '@ChamiloTheme/Resource/new_folder.html.twig';
1189
                break;
1190
            case 'file':
1191
                $template = '@ChamiloTheme/Resource/new.html.twig';
1192
                break;
1193
        }
1194
1195
        return $this->render(
1196
            $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...
1197
            [
1198
                'form' => $form->createView(),
1199
                'parent' => $resourceNodeParentId,
1200
                'file_type' => $fileType,
1201
            ]
1202
        );
1203
    }
1204
}
1205