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

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

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

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

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

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

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

983
            stream_copy_to_stream($stream, /** @scrutinizer ignore-type */ fopen('php://output', 'wb'));
Loading history...
984
        });
985
        $disposition = $response->headers->makeDisposition(
986
            $forceDownload ? ResponseHeaderBag::DISPOSITION_ATTACHMENT : ResponseHeaderBag::DISPOSITION_INLINE,
987
            $fileName
988
            //Transliterator::transliterate($fileName)
989
        );
990
        $response->headers->set('Content-Disposition', $disposition);
991
        $response->headers->set('Content-Type', $mimeType ?: 'application/octet-stream');
992
993
        return $response;
994
    }
995
996
    /**
997
     * @param Request $request
998
     * @param string  $fileType
999
     *
1000
     * @return RedirectResponse|Response
1001
     */
1002
    private function createResource(Request $request, $fileType = 'file')
1003
    {
1004
        $tool = $request->get('tool');
1005
        $type = $request->get('type');
1006
        $resourceNodeParentId = $request->get('id');
1007
1008
        $repository = $this->getRepositoryFromRequest($request);
1009
1010
        $form = $repository->getForm($this->container->get('form.factory'));
1011
1012
        if ($fileType === 'file') {
1013
            $form->add(
1014
                'content',
1015
                CKEditorType::class,
1016
                [
1017
                    'mapped' => false,
1018
                    'config' => [
1019
                        'filebrowserImageBrowseRoute' => 'editor_filemanager',
1020
                        'filebrowserImageBrowseRouteParameters' => array(
1021
                            'tool' => $tool,
1022
                            'type' => $type,
1023
                            'cidReq' => $this->getCourse()->getCode(),
1024
                            'id_session' => $this->getSessionId(),
1025
                            'id' => $resourceNodeParentId
1026
                        )
1027
                    ],
1028
                ]
1029
            );
1030
        }
1031
1032
        $course = $this->getCourse();
1033
        $session = $this->getSession();
1034
        // Default parent node is course.
1035
        $parentNode = $course->getResourceNode();
1036
        if (!empty($resourceNodeParentId)) {
1037
            // Get parent node.
1038
            $parentNode = $repository->getResourceNodeRepository()->find($resourceNodeParentId);
1039
        }
1040
1041
        $form->handleRequest($request);
1042
        if ($form->isSubmitted() && $form->isValid()) {
1043
            $em = $this->getDoctrine()->getManager();
1044
1045
            /** @var CDocument $newResource */
1046
            $newResource = $form->getData();
1047
1048
            $newResource
1049
                ->setCourse($course)
1050
                ->setSession($session)
1051
                ->setFiletype($fileType)
1052
                //->setTitle($title) // already added in $form->getData()
1053
                ->setReadonly(false)
1054
            ;
1055
1056
            $file = null;
1057
            if ($fileType === 'file') {
1058
                $content = $form->get('content')->getViewData();
1059
                $newResource->setTitle($newResource->getTitle().'.html');
1060
                $fileName = $newResource->getTitle();
1061
1062
                $handle = tmpfile();
1063
                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

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

1064
                $meta = stream_get_meta_data(/** @scrutinizer ignore-type */ $handle);
Loading history...
1065
                $file = new UploadedFile($meta['uri'], $fileName, null, null, true);
1066
                $em->persist($newResource);
1067
            }
1068
1069
            $resourceNode = $repository->createNodeForResource($newResource, $this->getUser(), $parentNode, $file);
1070
            $em->persist($resourceNode);
1071
1072
            $repository->addResourceNodeToCourse(
1073
                $resourceNode,
1074
                ResourceLink::VISIBILITY_PUBLISHED,
1075
                $course,
1076
                $session,
1077
                null
1078
            );
1079
1080
            $em->flush();
1081
1082
            // Loops all sharing options
1083
            /*foreach ($shareList as $share) {
1084
                $idList = [];
1085
                if (isset($share['search'])) {
1086
                    $idList = explode(',', $share['search']);
1087
                }
1088
1089
                $resourceRight = null;
1090
                if (isset($share['mask'])) {
1091
                    $resourceRight = new ResourceRight();
1092
                    $resourceRight
1093
                        ->setMask($share['mask'])
1094
                        ->setRole($share['role'])
1095
                    ;
1096
                }
1097
1098
                // Build links
1099
                switch ($share['sharing']) {
1100
                    case 'everyone':
1101
                        $repository->addResourceToEveryone(
1102
                            $resourceNode,
1103
                            $resourceRight
1104
                        );
1105
                        break;
1106
                    case 'course':
1107
                        $repository->addResourceToCourse(
1108
                            $resourceNode,
1109
                            $course,
1110
                            $resourceRight
1111
                        );
1112
                        break;
1113
                    case 'session':
1114
                        $repository->addResourceToSession(
1115
                            $resourceNode,
1116
                            $course,
1117
                            $session,
1118
                            $resourceRight
1119
                        );
1120
                        break;
1121
                    case 'user':
1122
                        // Only for me
1123
                        if (isset($share['only_me'])) {
1124
                            $repository->addResourceOnlyToMe($resourceNode);
1125
                        } else {
1126
                            // To other users
1127
                            $repository->addResourceToUserList($resourceNode, $idList);
1128
                        }
1129
                        break;
1130
                    case 'group':
1131
                        // @todo
1132
                        break;
1133
                }*/
1134
            //}
1135
            $em->flush();
1136
            $this->addFlash('success', $this->trans('Saved'));
1137
1138
            return $this->redirectToRoute(
1139
                'chamilo_core_resource_list',
1140
                [
1141
                    'id' => $resourceNodeParentId,
1142
                    'tool' => $tool,
1143
                    'type' => $type,
1144
                    'cidReq' => $this->getCourse()->getCode(),
1145
                    'id_session' => $this->getSessionId(),
1146
                ]
1147
            );
1148
        }
1149
1150
        switch ($fileType) {
1151
            case 'folder':
1152
                $template = '@ChamiloTheme/Resource/new_folder.html.twig';
1153
                break;
1154
            case 'file':
1155
                $template = '@ChamiloTheme/Resource/new.html.twig';
1156
                break;
1157
        }
1158
1159
        return $this->render(
1160
            $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...
1161
            [
1162
                'form' => $form->createView(),
1163
                'parent' => $resourceNodeParentId,
1164
                'file_type' => $fileType,
1165
            ]
1166
        );
1167
    }
1168
1169
    /**
1170
     * @param Request $request
1171
     */
1172
    public function setBreadCrumb(Request $request)
1173
    {
1174
        $tool = $request->get('tool');
1175
        $type = $request->get('type');
1176
        $resourceNodeId = $request->get('id');
1177
        $courseCode = $request->get('cidReq');
1178
        $sessionId = $request->get('id_session');
1179
1180
        if (!empty($resourceNodeId)) {
1181
            $breadcrumb = $this->breadcrumbBlockService;
1182
1183
            // Root tool link
1184
            $breadcrumb->addChild(
1185
                $this->translator->trans('Documents'),
1186
                [
1187
                    'uri' => $this->generateUrl(
1188
                        'chamilo_core_resource_index',
1189
                        ['tool' => $tool, 'type' => $type, 'cidReq' => $courseCode, 'id_session' => $sessionId]
1190
                    ),
1191
                ]
1192
            );
1193
1194
            $repo = $this->getRepositoryFromRequest($request);
1195
1196
            /** @var AbstractResource $parent */
1197
            $originalResource = $repo->findOneBy(['resourceNode' => $resourceNodeId]);
1198
            if ($originalResource === null) {
1199
                return;
1200
            }
1201
            $parent = $originalParent = $originalResource->getResourceNode();
1202
1203
            $parentList = [];
1204
            while ($parent !== null) {
1205
                if ($type !== $parent->getResourceType()->getName()) {
1206
                    break;
1207
                }
1208
                $parent = $parent->getParent();
1209
                if ($parent) {
1210
                    $resource = $repo->findOneBy(['resourceNode' => $parent->getId()]);
1211
                    if ($resource) {
1212
                        $parentList[] = $resource;
1213
                    }
1214
                }
1215
            }
1216
1217
            $parentList = array_reverse($parentList);
1218
            /** @var AbstractResource $item */
1219
            foreach ($parentList as $item) {
1220
                $breadcrumb->addChild(
1221
                    $item->getResourceName(),
1222
                    [
1223
                        'uri' => $this->generateUrl(
1224
                            'chamilo_core_resource_list',
1225
                            [
1226
                                'tool' => $tool,
1227
                                'type' => $type,
1228
                                'id' => $item->getResourceNode()->getId(),
1229
                                'cidReq' => $courseCode,
1230
                                'id_session' => $sessionId,
1231
                            ]
1232
                        ),
1233
                    ]
1234
                );
1235
            }
1236
1237
            $breadcrumb->addChild(
1238
                $originalResource->getResourceName(),
1239
                [
1240
                    'uri' => $this->generateUrl(
1241
                        'chamilo_core_resource_list',
1242
                        [
1243
                            'tool' => $tool,
1244
                            'type' => $type,
1245
                            'id' => $originalParent->getId(),
1246
                            'cidReq' => $courseCode,
1247
                            'id_session' => $sessionId,
1248
                        ]
1249
                    ),
1250
                ]
1251
            );
1252
        }
1253
    }
1254
}
1255