Passed
Push — master ( 268a91...5c5401 )
by Julito
11:54 queued 04:18
created

ResourceController::newFolderAction()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

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

217
            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...
218
                /** @var CDocument $entity */
219
                $entity = $row->getEntity();
220
                $resourceNode = $entity->getResourceNode();
221
222
                if ($resourceNode->hasResourceFile()) {
223
                    $file = $resourceNode->getResourceFile();
224
                    return $file->getMimeType();
225
                }
226
227
                return $this->trans('Folder');
228
            }
229
        );
230
231
        $grid->setHiddenColumns(['iid']);
232
233
        // Delete mass action.
234
        if ($this->isGranted(ResourceNodeVoter::DELETE, $this->getCourse())) {
235
            $deleteMassAction = new MassAction(
236
                'Delete',
237
                'ChamiloCoreBundle:Resource:deleteMass',
238
                true,
239
                $routeParams
240
            );
241
            $grid->addMassAction($deleteMassAction);
242
        }
243
244
        // Show resource action.
245
        $myRowAction = new RowAction(
246
            $translation->trans('Info'),
247
            'chamilo_core_resource_show',
248
            false,
249
            '_self',
250
            ['class' => 'btn btn-secondary', 'icon' => 'fa-info-circle']
251
        );
252
253
        $setNodeParameters = function (RowAction $action, Row $row) use ($routeParams) {
254
            $id = $row->getEntity()->getResourceNode()->getId();
255
            $routeParams['id'] = $id;
256
            $action->setRouteParameters($routeParams);
257
258
            return $action;
259
        };
260
261
        $myRowAction->addManipulateRender($setNodeParameters);
262
        $grid->addRowAction($myRowAction);
263
264
        if ($this->isGranted(ResourceNodeVoter::EDIT, $this->getCourse())) {
265
            // Enable/Disable
266
            $myRowAction = new RowAction(
267
                '',
268
                'chamilo_core_resource_change_visibility',
269
                false,
270
                '_self'
271
            );
272
273
            $setVisibleParameters = function (RowAction $action, Row $row) use ($routeParams) {
274
                /** @var CDocument $resource */
275
                $resource = $row->getEntity();
276
                $id = $resource->getResourceNode()->getId();
277
278
                $icon = 'fa-eye-slash';
279
                if ($resource->getCourseSessionResourceLink()->getVisibility() === ResourceLink::VISIBILITY_PUBLISHED) {
280
                    $icon = 'fa-eye';
281
                }
282
                $routeParams['id'] = $id;
283
                $action->setRouteParameters($routeParams);
284
                $attributes = [
285
                    'class' => 'btn btn-secondary change_visibility',
286
                    'data-id' => $id,
287
                    'icon' => $icon,
288
                ];
289
                $action->setAttributes($attributes);
290
291
                return $action;
292
            };
293
294
            $myRowAction->addManipulateRender($setVisibleParameters);
295
            $grid->addRowAction($myRowAction);
296
297
            // Edit action.
298
            $myRowAction = new RowAction(
299
                $translation->trans('Edit'),
300
                'chamilo_core_resource_edit',
301
                false,
302
                '_self',
303
                ['class' => 'btn btn-secondary']
304
            );
305
            $myRowAction->addManipulateRender($setNodeParameters);
306
            $grid->addRowAction($myRowAction);
307
308
            // Delete action.
309
            $myRowAction = new RowAction(
310
                $translation->trans('Delete'),
311
                'chamilo_core_resource_delete',
312
                true,
313
                '_self',
314
                ['class' => 'btn btn-danger']
315
            );
316
            $myRowAction->addManipulateRender($setNodeParameters);
317
            $grid->addRowAction($myRowAction);
318
        }
319
320
        /*$grid->addExport(new CSVExport($translation->trans('CSV export'), 'export', ['course' => $courseIdentifier]));
321
        $grid->addExport(
322
            new ExcelExport(
323
                $translation->trans('Excel export'),
324
                'export',
325
                ['course' => $courseIdentifier]
326
            )
327
        );*/
328
329
        return $grid;
330
    }
331
332
    /**
333
     * @Route("/{tool}/{type}/{id}/list", name="chamilo_core_resource_list")
334
     *
335
     * If node has children show it
336
     *
337
     * @param Request $request
338
     *
339
     * @return Response
340
     */
341
    public function listAction(Request $request, Grid $grid): Response
342
    {
343
        $tool = $request->get('tool');
344
        $type = $request->get('type');
345
        $resourceNodeId = $request->get('id');
346
347
        $grid = $this->getGrid( $request, $grid,$resourceNodeId);
348
349
        $this->setBreadCrumb($request);
350
351
        return $grid->getGridResponse(
352
            '@ChamiloTheme/Resource/index.html.twig',
353
            ['parent_id' => $resourceNodeId, 'tool' => $tool, 'type' => $type, 'id' => $resourceNodeId]
354
        );
355
    }
356
357
    /**
358
     * @Route("/{tool}/{type}/{id}/new_folder", methods={"GET", "POST"}, name="chamilo_core_resource_new_folder")
359
     *
360
     * @param Request $request
361
     *
362
     * @return Response
363
     */
364
    public function newFolderAction(Request $request): Response
365
    {
366
        $this->setBreadCrumb($request);
367
368
        return $this->createResource($request, 'folder');
369
    }
370
371
    /**
372
     * @Route("/{tool}/{type}/{id}/new", methods={"GET", "POST"}, name="chamilo_core_resource_new")
373
     *
374
     * @param Request $request
375
     *
376
     * @return Response
377
     */
378
    public function newAction(Request $request): Response
379
    {
380
        $this->setBreadCrumb($request);
381
382
        return $this->createResource($request, 'file');
383
    }
384
385
    /**
386
     * @Route("/{tool}/{type}/{id}/edit", methods={"GET", "POST"})
387
     *
388
     * @param Request $request
389
     *
390
     * @return Response
391
     */
392
    public function editAction(Request $request): Response
393
    {
394
        $tool = $request->get('tool');
395
        $type = $request->get('type');
396
        $nodeId = $request->get('id');
397
398
        $this->setBreadCrumb($request);
399
400
        $repository = $this->getRepositoryFromRequest($request);
401
        /** @var AbstractResource $resource */
402
        $resource = $repository->getRepository()->findOneBy(['resourceNode' => $nodeId]);
403
        $node = $resource->getResourceNode();
404
        $resourceNodeParentId = $node->getId();
405
406
        $form = $repository->getForm($this->container->get('form.factory'), $resource);
407
408
        if ($node->isEditable()) {
409
            $form->add(
410
                'content',
411
                CKEditorType::class,
412
                [
413
                    'mapped' => false,
414
                    'config' => [
415
                        'filebrowserImageBrowseRoute' => 'editor_filemanager',
416
                        'filebrowserImageBrowseRouteParameters' => array(
417
                            'tool' => $tool,
418
                            'type' => $type,
419
                            'cidReq' => $this->getCourse()->getCode(),
420
                            'id' => $resourceNodeParentId
421
                        )
422
                    ],
423
                ]
424
            );
425
            $content = $repository->getResourceFileContent($resource);
426
            $form->get('content')->setData($content);
427
        }
428
429
        $form->handleRequest($request);
430
431
        if ($form->isSubmitted() && $form->isValid()) {
432
            /** @var CDocument $newResource */
433
            $newResource = $form->getData();
434
435
            if ($form->has('content')) {
436
                $data = $form->get('content')->getData();
437
                $repository->updateResourceFileContent($newResource, $data);
438
            }
439
440
            $newResource->setTitle($form->get('title')->getData());
441
            $repository->updateNodeForResource($newResource);
442
443
            /*$em->persist($newResource);
444
            $em->flush();*/
445
446
            $this->addFlash('success', $this->trans('Updated'));
447
448
            if ($newResource->getResourceNode()->hasResourceFile()) {
449
                $resourceNodeParentId = $newResource->getResourceNode()->getParent()->getId();
450
            }
451
452
            return $this->redirectToRoute(
453
                'chamilo_core_resource_list',
454
                [
455
                    'id' => $resourceNodeParentId,
456
                    'tool' => $tool,
457
                    'type' => $type,
458
                    'cidReq' => $this->getCourse()->getCode(),
459
                ]
460
            );
461
        }
462
463
        return $this->render(
464
            '@ChamiloTheme/Resource/edit.html.twig',
465
            [
466
                'form' => $form->createView(),
467
                'parent' => $resourceNodeParentId,
468
            ]
469
        );
470
    }
471
472
    /**
473
     * Shows a resource.
474
     *
475
     * @Route("/{tool}/{type}/{id}/show", methods={"GET"}, name="chamilo_core_resource_show")
476
     *
477
     * @param Request $request
478
     *
479
     * @return Response
480
     */
481
    public function showAction(Request $request): Response
482
    {
483
        $this->setBreadCrumb($request);
484
        $nodeId = $request->get('id');
485
486
        $repository = $this->getRepositoryFromRequest($request);
487
488
        /** @var AbstractResource $resource */
489
        $resource = $repository->getRepository()->findOneBy(['resourceNode' => $nodeId]);
490
491
        if (null === $resource) {
492
            throw new NotFoundHttpException();
493
        }
494
495
        $resourceNode = $resource->getResourceNode();
496
497
        if (null === $resourceNode) {
498
            throw new NotFoundHttpException();
499
        }
500
501
        $this->denyAccessUnlessGranted(
502
            ResourceNodeVoter::VIEW,
503
            $resourceNode,
504
            $this->trans('Unauthorised access to resource')
505
        );
506
507
        $tool = $request->get('tool');
508
        $type = $request->get('type');
509
510
        $params = [
511
            'resource' => $resource,
512
            'tool' => $tool,
513
            'type' => $type,
514
        ];
515
516
        return $this->render('@ChamiloTheme/Resource/show.html.twig', $params);
517
    }
518
519
    /**
520
     * @Route("/{tool}/{type}/{id}/change_visibility", name="chamilo_core_resource_change_visibility")
521
     *
522
     * @param Request $request
523
     *
524
     * @return Response
525
     */
526
    public function changeVisibilityAction(Request $request): Response
527
    {
528
        $em = $this->getDoctrine()->getManager();
529
530
        $id = $request->get('id');
531
532
        $repository = $this->getRepositoryFromRequest($request);
533
534
        /** @var AbstractResource $resource */
535
        $resource = $repository->getRepository()->findOneBy(['resourceNode' => $id]);
536
537
        if (null === $resource) {
538
            throw new NotFoundHttpException();
539
        }
540
541
        $resourceNode = $resource->getResourceNode();
542
543
        $this->denyAccessUnlessGranted(
544
            ResourceNodeVoter::EDIT,
545
            $resourceNode,
546
            $this->trans('Unauthorised access to resource')
547
        );
548
        /** @var ResourceLink $link */
549
        $link = $resource->getCourseSessionResourceLink();
550
551
        $newVisibility = ResourceLink::VISIBILITY_PUBLISHED;
552
        $icon = 'fa-eye';
553
        if ($link->getVisibility() === ResourceLink::VISIBILITY_PUBLISHED) {
554
            $newVisibility = ResourceLink::VISIBILITY_DRAFT;
555
            $icon = 'fa-eye-slash';
556
        }
557
558
        $link->setVisibility($newVisibility);
559
        $em->persist($link);
560
        $em->flush();
561
562
        $result = ['icon' => $icon];
563
564
        return new JsonResponse($result);
565
    }
566
567
568
    /**
569
     * @Route("/{tool}/{type}/{id}", name="chamilo_core_resource_delete")
570
     *
571
     * @param Request $request
572
     *
573
     * @return Response
574
     */
575
    public function deleteAction(Request $request): Response
576
    {
577
        $tool = $request->get('tool');
578
        $type = $request->get('type');
579
580
        $em = $this->getDoctrine()->getManager();
581
582
        $id = $request->get('id');
583
        $resourceNode = $this->getDoctrine()->getRepository('ChamiloCoreBundle:Resource\ResourceNode')->find($id);
584
        $parentId = $resourceNode->getParent()->getId();
585
586
        if (null === $resourceNode) {
587
            throw new NotFoundHttpException();
588
        }
589
590
        $this->denyAccessUnlessGranted(
591
            ResourceNodeVoter::DELETE,
592
            $resourceNode,
593
            $this->trans('Unauthorised access to resource')
594
        );
595
596
        $em->remove($resourceNode);
597
        $this->addFlash('success', $this->trans('Deleted'));
598
        $em->flush();
599
600
        return $this->redirectToRoute(
601
            'chamilo_core_resource_list',
602
            [
603
                'id' => $parentId,
604
                'tool' => $tool,
605
                'type' => $type,
606
                'cidReq' => $this->getCourse()->getCode(),
607
            ]
608
        );
609
    }
610
611
    /**
612
     * @Route("/{tool}/{type}/{id}", methods={"DELETE"}, name="chamilo_core_resource_delete_mass")
613
     *
614
     * @param Request $request
615
     *
616
     * @return Response
617
     */
618
    public function deleteMassAction($primaryKeys, $allPrimaryKeys, Request $request): Response
619
    {
620
        $tool = $request->get('tool');
621
        $type = $request->get('type');
622
        $em = $this->getDoctrine()->getManager();
623
        $repo = $this->getRepositoryFromRequest($request);
624
625
        $parentId = 0;
626
        foreach ($primaryKeys as $id) {
627
            $resource = $repo->find($id);
628
            $resourceNode = $resource->getResourceNode();
629
630
            if (null === $resourceNode) {
631
                continue;
632
            }
633
634
            $this->denyAccessUnlessGranted(
635
                ResourceNodeVoter::DELETE,
636
                $resourceNode,
637
                $this->trans('Unauthorised access to resource')
638
            );
639
640
            $parentId = $resourceNode->getParent()->getId();
641
            $em->remove($resource);
642
        }
643
644
        $this->addFlash('success', $this->trans('Deleted'));
645
        $em->flush();
646
647
        return $this->redirectToRoute(
648
            'chamilo_core_resource_list',
649
            [
650
                'id' => $parentId,
651
                'tool' => $tool,
652
                'type' => $type,
653
                'cidReq' => $this->getCourse()->getCode(),
654
            ]
655
        );
656
    }
657
658
    /**
659
     * @Route("/{tool}/{type}/{id}/file", methods={"GET"}, name="chamilo_core_resource_file")
660
     *
661
     * @param Request $request
662
     * @param Glide   $glide
663
     *
664
     * @return Response
665
     */
666
    public function getResourceFileAction(Request $request, Glide $glide): Response
667
    {
668
        $id = $request->get('id');
669
        $filter = $request->get('filter');
670
        $mode = $request->get('mode');
671
        $em = $this->getDoctrine();
672
        $resourceNode = $em->getRepository('ChamiloCoreBundle:Resource\ResourceNode')->find($id);
673
674
        if ($resourceNode === null) {
675
            throw new FileNotFoundException('Resource not found');
676
        }
677
678
        return $this->showFile($request, $resourceNode, $glide, $mode, $filter);
679
    }
680
681
    /**
682
     * Gets a document when calling route resources_document_get_file.
683
     *
684
     * @param Request             $request
685
     * @param CDocumentRepository $documentRepo
686
     * @param Glide               $glide
687
     *
688
     * @return Response
689
     * @throws \League\Flysystem\FileNotFoundException
690
     */
691
    public function getDocumentAction(Request $request, Glide $glide): Response
692
    {
693
        $file = $request->get('file');
694
        $mode = $request->get('mode');
695
696
        // see list of filters in config/services.yaml
697
        $filter = $request->get('filter');
698
        $mode = !empty($mode) ? $mode : 'show';
699
700
        $repository = $this->getRepository('document', 'files');
701
        $nodeRepository = $repository->getResourceNodeRepository();
702
703
        $title = basename($file);
704
        // @todo improve criteria to avoid giving the wrong file.
705
        $criteria = ['slug' => $title];
706
707
        $resourceNode = $nodeRepository->findOneBy($criteria);
708
709
        if (null === $resourceNode) {
710
            throw new NotFoundHttpException();
711
        }
712
713
        $this->denyAccessUnlessGranted(
714
            ResourceNodeVoter::VIEW,
715
            $resourceNode,
716
            $this->trans('Unauthorised access to resource')
717
        );
718
719
        return $this->showFile($request, $resourceNode, $glide, $mode, $filter);
720
    }
721
722
    /**
723
     * Downloads a folder.
724
     *
725
     * @param Request             $request
726
     * @param CDocumentRepository $documentRepo
727
     *
728
     * @return Response
729
     */
730
    public function downloadFolderAction(Request $request, CDocumentRepository $documentRepo)
731
    {
732
        $folderId = (int) $request->get('folderId');
733
        $courseNode = $this->getCourse()->getResourceNode();
734
735
        if (empty($folderId)) {
736
            $resourceNode = $courseNode;
737
        } else {
738
            $document = $documentRepo->find($folderId);
739
            $resourceNode = $document->getResourceNode();
740
        }
741
742
        $type = $documentRepo->getResourceType();
743
744
        if (null === $resourceNode || null === $courseNode) {
745
            throw new NotFoundHttpException();
746
        }
747
748
        $this->denyAccessUnlessGranted(
749
            ResourceNodeVoter::VIEW,
750
            $resourceNode,
751
            $this->trans('Unauthorised access to resource')
752
        );
753
754
        $zipName = $resourceNode->getName().'.zip';
755
        $rootNodePath = $resourceNode->getPathForDisplay();
756
757
        /** @var Filesystem $fileSystem */
758
        $fileSystem = $this->get('oneup_flysystem.resources_filesystem');
759
760
        $resourceNodeRepo = $documentRepo->getResourceNodeRepository();
761
762
        $criteria = Criteria::create()
763
            ->where(Criteria::expr()->neq('resourceFile', null))
764
            ->andWhere(Criteria::expr()->eq('resourceType', $type))
765
        ;
766
767
        /** @var ArrayCollection|ResourceNode[] $children */
768
        /** @var QueryBuilder $children */
769
        $qb = $resourceNodeRepo->getChildrenQueryBuilder($resourceNode);
770
        $qb->addCriteria($criteria);
771
        $children = $qb->getQuery()->getResult();
772
773
        /** @var ResourceNode $node */
774
        foreach ($children as $node) {
775
            /*if ($node->hasResourceFile()) {
776
                $resourceFile = $node->getResourceFile();
777
                $systemName = $resourceFile->getFile()->getPathname();
778
                $stream = $fileSystem->readStream($systemName);
779
                //error_log($node->getPathForDisplay());
780
                $fileToDisplay = str_replace($rootNodePath, '', $node->getPathForDisplay());
781
                var_dump($fileToDisplay);
782
            }*/
783
            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...
784
            //var_dump($node['path']);
785
        }
786
787
        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...
788
789
790
        $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...
791
        {
792
            // Define suitable options for ZipStream Archive.
793
            $options = new Archive();
794
            $options->setContentType('application/octet-stream');
795
            //initialise zipstream with output zip filename and options.
796
            $zip = new ZipStream($zipName, $options);
797
798
            /** @var ResourceNode $node */
799
            foreach ($children as $node) {
800
                $resourceFile = $node->getResourceFile();
801
                $systemName = $resourceFile->getFile()->getPathname();
802
                $stream = $fileSystem->readStream($systemName);
803
                //error_log($node->getPathForDisplay());
804
                $fileToDisplay = str_replace($rootNodePath, '', $node->getPathForDisplay());
805
                $zip->addFileFromStream($fileToDisplay, $stream);
806
            }
807
            //$data = $repo->getDocumentContent($not_deleted_file['id']);
808
            //$zip->addFile($not_deleted_file['path'], $data);
809
            $zip->finish();
810
        });
811
812
        $disposition = $response->headers->makeDisposition(
813
            ResponseHeaderBag::DISPOSITION_ATTACHMENT,
814
            Transliterator::transliterate($zipName)
815
        );
816
        $response->headers->set('Content-Disposition', $disposition);
817
        $response->headers->set('Content-Type', 'application/octet-stream');
818
819
        return $response;
820
    }
821
822
    /**
823
     * Upload form.
824
     *
825
     * @Route("/{tool}/{type}/{id}/upload", name="chamilo_core_resource_upload", methods={"GET", "POST"},
826
     *                                      options={"expose"=true})
827
     */
828
    public function uploadAction(Request $request, $tool, $type, $id): Response
829
    {
830
        $this->setBreadCrumb( $request);
831
        //$helper = $this->container->get('oneup_uploader.templating.uploader_helper');
832
        //$endpoint = $helper->endpoint('courses');
833
        $sessionId = $this->getSessionId();
834
835
        return $this->render(
836
            '@ChamiloTheme/Resource/upload.html.twig',
837
            [
838
                'id' => $id,
839
                'type' => $type,
840
                'tool' => $tool,
841
                'cidReq' => $this->getCourse()->getCode(),
842
                'id_session' => $sessionId,
843
            ]
844
        );
845
    }
846
847
    /**
848
     * @param Request      $request
849
     * @param ResourceNode $resourceNode
850
     * @param Glide        $glide
851
     * @param string       $mode show or download
852
     * @param string       $filter
853
     *
854
     * @return mixed|StreamedResponse
855
     */
856
    private function showFile(Request $request, ResourceNode $resourceNode, Glide $glide, $mode = 'show', $filter = '')
857
    {
858
        $this->denyAccessUnlessGranted(
859
            ResourceNodeVoter::VIEW,
860
            $resourceNode,
861
            $this->trans('Unauthorised access to resource')
862
        );
863
        $resourceFile = $resourceNode->getResourceFile();
864
865
        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...
866
            throw new NotFoundHttpException();
867
        }
868
869
        //$fileName = $resourceFile->getOriginalName();
870
        $fileName = $resourceNode->getSlug();
871
        $filePath = $resourceFile->getFile()->getPathname();
872
        $mimeType = $resourceFile->getMimeType();
873
874
        switch ($mode) {
875
            case 'download':
876
                $forceDownload = true;
877
                break;
878
            case 'show':
879
            default:
880
                $forceDownload = false;
881
                // If it's an image then send it to Glide.
882
                if (strpos($mimeType, 'image') !== false) {
883
                    $server = $glide->getServer();
884
                    $params = $request->query->all();
885
886
                    // The filter overwrites the params from get
887
                    if (!empty($filter)) {
888
                        $params = $glide->getFilters()[$filter] ?? [];
889
                    }
890
891
                    // The image was cropped manually by the user, so we force to render this version,
892
                    // no matter other crop parameters.
893
                    $crop = $resourceFile->getCrop();
894
                    if (!empty($crop)) {
895
                        $params['crop'] = $crop;
896
                    }
897
898
                    return $server->getImageResponse($filePath, $params);
899
                }
900
                break;
901
        }
902
903
        $stream = $this->fs->readStream($filePath);
904
        $response = new StreamedResponse(function () use ($stream): void {
905
            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

905
            stream_copy_to_stream($stream, /** @scrutinizer ignore-type */ fopen('php://output', 'wb'));
Loading history...
906
        });
907
        $disposition = $response->headers->makeDisposition(
908
            $forceDownload ? ResponseHeaderBag::DISPOSITION_ATTACHMENT : ResponseHeaderBag::DISPOSITION_INLINE,
909
            $fileName
910
            //Transliterator::transliterate($fileName)
911
        );
912
        $response->headers->set('Content-Disposition', $disposition);
913
        $response->headers->set('Content-Type', $mimeType ?: 'application/octet-stream');
914
915
        return $response;
916
    }
917
918
    /**
919
     * @param Request $request
920
     * @param string  $fileType
921
     *
922
     * @return RedirectResponse|Response
923
     */
924
    private function createResource(Request $request, $fileType = 'file')
925
    {
926
        $tool = $request->get('tool');
927
        $type = $request->get('type');
928
        $resourceNodeParentId = $request->get('id');
929
930
        $repository = $this->getRepositoryFromRequest($request);
931
932
        $form = $repository->getForm($this->container->get('form.factory'));
933
934
        if ($fileType === 'file') {
935
            $form->add(
936
                'content',
937
                CKEditorType::class,
938
                [
939
                    'mapped' => false,
940
                    'config' => [
941
                        'filebrowserImageBrowseRoute' => 'editor_filemanager',
942
                        'filebrowserImageBrowseRouteParameters' => array(
943
                            'tool' => $tool,
944
                            'type' => $type,
945
                            'cidReq' => $this->getCourse()->getCode(),
946
                            'id' => $resourceNodeParentId
947
                        )
948
                    ],
949
                ]
950
            );
951
        }
952
953
        $course = $this->getCourse();
954
        $session = $this->getSession();
955
        // Default parent node is course.
956
        $parentNode = $course->getResourceNode();
957
        if (!empty($resourceNodeParentId)) {
958
            // Get parent node.
959
            $parentNode = $repository->getResourceNodeRepository()->find($resourceNodeParentId);
960
        }
961
962
        $form->handleRequest($request);
963
        if ($form->isSubmitted() && $form->isValid()) {
964
            $em = $this->getDoctrine()->getManager();
965
966
            /** @var CDocument $newResource */
967
            $newResource = $form->getData();
968
969
            $newResource
970
                ->setCourse($course)
971
                ->setSession($session)
972
                ->setFiletype($fileType)
973
                //->setTitle($title) // already added in $form->getData()
974
                ->setReadonly(false)
975
            ;
976
977
            $file = null;
978
            if ($fileType === 'file') {
979
                $content = $form->get('content')->getViewData();
980
                $newResource->setTitle($newResource->getTitle().'.html');
981
                $fileName = $newResource->getTitle();
982
983
                $handle = tmpfile();
984
                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

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

985
                $meta = stream_get_meta_data(/** @scrutinizer ignore-type */ $handle);
Loading history...
986
                $file = new UploadedFile($meta['uri'], $fileName, null, null, true);
987
                $em->persist($newResource);
988
            }
989
990
            $resourceNode = $repository->createNodeForResource($newResource, $this->getUser(), $parentNode, $file);
991
            $em->persist($resourceNode);
992
993
            $repository->addResourceNodeToCourse(
994
                $resourceNode,
995
                ResourceLink::VISIBILITY_PUBLISHED,
996
                $course,
997
                $session,
998
                null
999
            );
1000
1001
            $em->flush();
1002
1003
            // Loops all sharing options
1004
            /*foreach ($shareList as $share) {
1005
                $idList = [];
1006
                if (isset($share['search'])) {
1007
                    $idList = explode(',', $share['search']);
1008
                }
1009
1010
                $resourceRight = null;
1011
                if (isset($share['mask'])) {
1012
                    $resourceRight = new ResourceRight();
1013
                    $resourceRight
1014
                        ->setMask($share['mask'])
1015
                        ->setRole($share['role'])
1016
                    ;
1017
                }
1018
1019
                // Build links
1020
                switch ($share['sharing']) {
1021
                    case 'everyone':
1022
                        $repository->addResourceToEveryone(
1023
                            $resourceNode,
1024
                            $resourceRight
1025
                        );
1026
                        break;
1027
                    case 'course':
1028
                        $repository->addResourceToCourse(
1029
                            $resourceNode,
1030
                            $course,
1031
                            $resourceRight
1032
                        );
1033
                        break;
1034
                    case 'session':
1035
                        $repository->addResourceToSession(
1036
                            $resourceNode,
1037
                            $course,
1038
                            $session,
1039
                            $resourceRight
1040
                        );
1041
                        break;
1042
                    case 'user':
1043
                        // Only for me
1044
                        if (isset($share['only_me'])) {
1045
                            $repository->addResourceOnlyToMe($resourceNode);
1046
                        } else {
1047
                            // To other users
1048
                            $repository->addResourceToUserList($resourceNode, $idList);
1049
                        }
1050
                        break;
1051
                    case 'group':
1052
                        // @todo
1053
                        break;
1054
                }*/
1055
            //}
1056
            $em->flush();
1057
            $this->addFlash('success', $this->trans('Saved'));
1058
1059
            return $this->redirectToRoute(
1060
                'chamilo_core_resource_list',
1061
                [
1062
                    'id' => $resourceNodeParentId,
1063
                    'tool' => $tool,
1064
                    'type' => $type,
1065
                    'cidReq' => $this->getCourse()->getCode(),
1066
                    'id_session' => $this->getSessionId(),
1067
                ]
1068
            );
1069
        }
1070
1071
        switch ($fileType) {
1072
            case 'folder':
1073
                $template = '@ChamiloTheme/Resource/new_folder.html.twig';
1074
                break;
1075
            case 'file':
1076
                $template = '@ChamiloTheme/Resource/new.html.twig';
1077
                break;
1078
        }
1079
1080
        return $this->render(
1081
            $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...
1082
            [
1083
                'form' => $form->createView(),
1084
                'parent' => $resourceNodeParentId,
1085
                'file_type' => $fileType,
1086
            ]
1087
        );
1088
    }
1089
1090
1091
    /**
1092
     * @param Request $request
1093
     */
1094
    public function setBreadCrumb(Request $request)
1095
    {
1096
        $tool = $request->get('tool');
1097
        $type = $request->get('type');
1098
        $resourceNodeId = $request->get('id');
1099
        $courseCode = $request->get('cidReq');
1100
        $sessionId = $request->get('id_session');
1101
1102
        if (!empty($resourceNodeId)) {
1103
            $breadcrumb = $this->breadcrumbBlockService;
1104
1105
            // Root tool link
1106
            $breadcrumb->addChild(
1107
                $this->translator->trans('Documents'),
1108
                [
1109
                    'uri' => $this->generateUrl(
1110
                        'chamilo_core_resource_index',
1111
                        ['tool' => $tool, 'type' => $type, 'cidReq' => $courseCode, 'id_session' => $sessionId]
1112
                    ),
1113
                ]
1114
            );
1115
1116
            $repo = $this->getRepositoryFromRequest($request);
1117
1118
            /** @var AbstractResource $parent */
1119
            $originalResource = $repo->findOneBy(['resourceNode' => $resourceNodeId]);
1120
            if ($originalResource === null) {
1121
                return;
1122
            }
1123
            $parent = $originalParent = $originalResource->getResourceNode();
1124
1125
            $parentList = [];
1126
            while ($parent !== null) {
1127
                if ($type !== $parent->getResourceType()->getName()) {
1128
                    break;
1129
                }
1130
                $parent = $parent->getParent();
1131
                if ($parent) {
1132
                    $resource = $repo->findOneBy(['resourceNode' => $parent->getId()]);
1133
                    if ($resource) {
1134
                        $parentList[] = $resource;
1135
                    }
1136
                }
1137
            }
1138
1139
            $parentList = array_reverse($parentList);
1140
            /** @var AbstractResource $item */
1141
            foreach ($parentList as $item) {
1142
                $breadcrumb->addChild(
1143
                    $item->getResourceName(),
1144
                    [
1145
                        'uri' => $this->generateUrl(
1146
                            'chamilo_core_resource_list',
1147
                            [
1148
                                'tool' => $tool,
1149
                                'type' => $type,
1150
                                'id' => $item->getResourceNode()->getId(),
1151
                                'cidReq' => $courseCode,
1152
                                'id_session' => $sessionId,
1153
                            ]
1154
                        ),
1155
                    ]
1156
                );
1157
            }
1158
1159
            $breadcrumb->addChild(
1160
                $originalResource->getResourceName(),
1161
                [
1162
                    'uri' => $this->generateUrl(
1163
                        'chamilo_core_resource_list',
1164
                        [
1165
                            'tool' => $tool,
1166
                            'type' => $type,
1167
                            'id' => $originalParent->getId(),
1168
                            'cidReq' => $courseCode,
1169
                            'id_session' => $sessionId,
1170
                        ]
1171
                    ),
1172
                ]
1173
            );
1174
        }
1175
    }
1176
}
1177