Completed
Push — master ( 15a37f...4874d1 )
by Julito
14:42 queued 02:51
created

ResourceController::deleteAction()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 32
Code Lines 21

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 21
nc 2
nop 1
dl 0
loc 32
rs 9.584
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\Block\BreadcrumbBlockService;
14
use Chamilo\CoreBundle\Component\Utils\Glide;
15
use Chamilo\CoreBundle\Entity\Resource\AbstractResource;
16
use Chamilo\CoreBundle\Entity\Resource\ResourceFile;
17
use Chamilo\CoreBundle\Entity\Resource\ResourceLink;
18
use Chamilo\CoreBundle\Entity\Resource\ResourceNode;
19
use Chamilo\CoreBundle\Security\Authorization\Voter\ResourceNodeVoter;
20
use Chamilo\CourseBundle\Controller\CourseControllerInterface;
21
use Chamilo\CourseBundle\Controller\CourseControllerTrait;
22
use Chamilo\CourseBundle\Entity\CDocument;
23
use Chamilo\CourseBundle\Repository\CDocumentRepository;
24
use Doctrine\Common\Collections\ArrayCollection;
25
use Doctrine\Common\Collections\Criteria;
26
use Doctrine\ORM\QueryBuilder;
27
use FOS\CKEditorBundle\Form\Type\CKEditorType;
28
use FOS\RestBundle\View\View;
29
use League\Flysystem\Filesystem;
30
use Oneup\UploaderBundle\Uploader\Response\EmptyResponse;
31
use Sylius\Bundle\ResourceBundle\Event\ResourceControllerEvent;
32
use Sylius\Component\Resource\Exception\UpdateHandlingException;
33
use Sylius\Component\Resource\ResourceActions;
34
use Symfony\Component\Filesystem\Exception\FileNotFoundException;
35
use Symfony\Component\HttpFoundation\File\Exception\UploadException;
36
use Symfony\Component\HttpFoundation\File\UploadedFile;
37
use Symfony\Component\HttpFoundation\JsonResponse;
38
use Symfony\Component\HttpFoundation\RedirectResponse;
39
use Symfony\Component\HttpFoundation\Request;
40
use Symfony\Component\HttpFoundation\Response;
41
use Symfony\Component\HttpFoundation\ResponseHeaderBag;
42
use Symfony\Component\HttpFoundation\StreamedResponse;
43
use Symfony\Component\HttpKernel\Exception\HttpException;
44
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
45
use Symfony\Component\Routing\Annotation\Route;
46
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
47
use Symfony\Component\Routing\RouterInterface;
48
use Vich\UploaderBundle\Util\Transliterator;
49
use ZipStream\Option\Archive;
50
use ZipStream\ZipStream;
51
52
/**
53
 * Class ResourceController.
54
 *
55
 * @Route("/resources")
56
 *
57
 * @author Julio Montoya <[email protected]>.
58
 */
59
class ResourceController extends AbstractResourceController implements CourseControllerInterface
60
{
61
    use CourseControllerTrait;
62
63
    /**
64
     * @Route("/{tool}/{type}", name="chamilo_core_resource_index")
65
     *
66
     * Example: /document/files
67
     * For the tool value check the Tool entity.
68
     * For the type value check the ResourceType entity.
69
     *
70
     * @param Request $request
71
     *
72
     * @return Response
73
     */
74
    public function indexAction(Request $request, Grid $grid): Response
75
    {
76
        $tool = $request->get('tool');
77
        $type = $request->get('type');
78
79
        $grid = $this->getGrid( $request, $grid);
80
81
        $breadcrumb = $this->breadcrumbBlockService;
82
        $breadcrumb->addChild(
83
            $this->trans('Documents'),
84
            [
85
                'uri' => '#',
86
            ]
87
        );
88
89
        // The base resource node is the course.
90
        $id = $this->getCourse()->getResourceNode()->getId();
91
92
        return $grid->getGridResponse(
93
            '@ChamiloTheme/Resource/index.html.twig',
94
            ['tool' => $tool, 'type' => $type, 'id' => $id]
95
        );
96
    }
97
98
    /**
99
     * @param Request $request
100
     * @param Grid    $grid
101
     * @param int     $resourceNodeId
102
     *
103
     * @return Grid
104
     */
105
    public function getGrid(Request $request, Grid $grid, $resourceNodeId = 0)
106
    {
107
        $tool = $request->get('tool');
108
        $type = $request->get('type');
109
110
        $repository = $this->getRepositoryFromRequest($request);
111
        $class = $repository->getRepository()->getClassName();
112
        $source = new Entity($class);
113
114
        /*$tableAlias = $source->getTableAlias();
115
        $source->manipulateQuery(function (QueryBuilder $query) use ($tableAlias, $course) {
116
                $query->andWhere($tableAlias . '.cId = '.$course->getId());
117
                //$query->resetDQLPart('orderBy');
118
            }
119
        );*/
120
121
        $course = $this->getCourse();
122
        $session = $this->getSession();
123
124
        $parent = $course->getResourceNode();
125
        if (!empty($resourceNodeId)) {
126
            $parent = $repository->getResourceNodeRepository()->find($resourceNodeId);
127
        }
128
129
        $qb = $repository->getResourcesByCourse($course, $session, null, $parent);
130
131
        // 3. Set QueryBuilder to the source.
132
        $source->initQueryBuilder($qb);
133
        $grid->setSource($source);
134
135
        $title = $grid->getColumn('title');
136
        $title->setSafe(false);
137
138
        //$grid->hideFilters();
139
        $grid->setLimits(20);
140
        //$grid->isReadyForRedirect();
141
        //$grid->setMaxResults(1);
142
        //$grid->setLimits(2);
143
144
        $translation = $this->translator;
145
        $courseIdentifier = $course->getCode();
146
147
        $routeParams = ['tool' => $tool, 'type' => $type, 'cidReq' => $courseIdentifier, 'id'];
148
149
        $grid->getColumn('title')->manipulateRenderCell(
150
            function ($value, Row $row, $router) use ($routeParams) {
151
                /** @var CDocument $entity */
152
                $entity = $row->getEntity();
153
                $resourceNode = $entity->getResourceNode();
154
                $id = $resourceNode->getId();
155
156
                $myParams = $routeParams;
157
                $myParams['id'] = $id;
158
                unset($myParams[0]);
159
160
                if ($resourceNode->hasResourceFile()) {
161
                    $url = $router->generate(
162
                        'chamilo_core_resource_show',
163
                        $myParams
164
                    );
165
                } else {
166
                    $url = $router->generate(
167
                        'chamilo_core_resource_list',
168
                        $myParams
169
                    );
170
                }
171
172
                return '<a href="'.$url.'">'.$value.'</a>';
173
            }
174
        );
175
176
        if ($this->isGranted(ResourceNodeVoter::ROLE_CURRENT_COURSE_TEACHER)) {
177
            $deleteMassAction = new MassAction(
178
                'Delete',
179
                'ChamiloCoreBundle:Resource:deleteMass',
180
                true,
181
                $routeParams
182
            );
183
            $grid->addMassAction($deleteMassAction);
184
        }
185
186
        // Show resource data
187
        $myRowAction = new RowAction(
188
            $translation->trans('View'),
189
            'chamilo_core_resource_show',
190
            false,
191
            '_self',
192
            ['class' => 'btn btn-secondary']
193
        );
194
        $myRowAction->setRouteParameters($routeParams);
195
196
        $setNodeParameters = function (RowAction $action, Row $row) use ($routeParams) {
197
            $id = $row->getEntity()->getResourceNode()->getId();
198
            $routeParams['id'] = $id;
199
            $action->setRouteParameters($routeParams);
200
            return $action;
201
        };
202
        $myRowAction->addManipulateRender($setNodeParameters);
203
204
        $grid->addRowAction($myRowAction);
205
206
        if ($this->isGranted(ResourceNodeVoter::ROLE_CURRENT_COURSE_TEACHER)) {
207
            // Edit
208
            $myRowAction = new RowAction(
209
                $translation->trans('Edit'),
210
                'chamilo_core_resource_edit',
211
                false,
212
                '_self',
213
                ['class' => 'btn btn-secondary']
214
            );
215
            $myRowAction->setRouteParameters($routeParams);
216
            $myRowAction->addManipulateRender($setNodeParameters);
217
218
            $grid->addRowAction($myRowAction);
219
220
            // Delete
221
            $myRowAction = new RowAction(
222
                $translation->trans('Delete'),
223
                'chamilo_core_resource_delete',
224
                false,
225
                '_self',
226
                ['class' => 'btn btn-danger', 'form_delete' => true]
227
            );
228
            $myRowAction->setRouteParameters($routeParams);
229
            $myRowAction->addManipulateRender($setNodeParameters);
230
            $grid->addRowAction($myRowAction);
231
        }
232
233
        /*$grid->addExport(new CSVExport($translation->trans('CSV export'), 'export', ['course' => $courseIdentifier]));
234
        $grid->addExport(
235
            new ExcelExport(
236
                $translation->trans('Excel export'),
237
                'export',
238
                ['course' => $courseIdentifier]
239
            )
240
        );*/
241
242
        return $grid;
243
    }
244
245
    /**
246
     * @Route("/{tool}/{type}/{id}/list", name="chamilo_core_resource_list")
247
     *
248
     * If node has children show it
249
     *
250
     * @param Request $request
251
     *
252
     * @return Response
253
     */
254
    public function listAction(Request $request, Grid $grid): Response
255
    {
256
        $tool = $request->get('tool');
257
        $type = $request->get('type');
258
        $resourceNodeId = $request->get('id');
259
260
        $grid = $this->getGrid( $request, $grid,$resourceNodeId);
261
262
        $this->setBreadCrumb($request);
263
264
        return $grid->getGridResponse(
265
            '@ChamiloTheme/Resource/index.html.twig',
266
            ['parent_id' => $resourceNodeId, 'tool' => $tool, 'type' => $type, 'id' => $resourceNodeId]
267
        );
268
    }
269
270
    /**
271
     * @Route("/{tool}/{type}/{id}/new_folder", methods={"GET", "POST"}, name="chamilo_core_resource_new_folder")
272
     *
273
     * @param Request $request
274
     *
275
     * @return Response
276
     */
277
    public function newFolderAction(Request $request): Response
278
    {
279
        $this->setBreadCrumb($request);
280
281
        return $this->createResource($request, 'folder');
282
    }
283
284
    /**
285
     * @Route("/{tool}/{type}/{id}/new", methods={"GET", "POST"}, name="chamilo_core_resource_new")
286
     *
287
     * @param Request $request
288
     *
289
     * @return Response
290
     */
291
    public function newAction(Request $request): Response
292
    {
293
        $this->setBreadCrumb($request);
294
295
        return $this->createResource($request, 'file');
296
    }
297
298
    /**
299
     * @Route("/{tool}/{type}/{id}/edit", methods={"GET", "POST"})
300
     *
301
     * @param Request $request
302
     *
303
     * @return Response
304
     */
305
    public function editAction(Request $request): Response
306
    {
307
        $tool = $request->get('tool');
308
        $type = $request->get('type');
309
        $nodeId = $request->get('id');
310
311
        $repository = $this->getRepositoryFromRequest($request);
312
        $resource = $repository->getRepository()->findOneBy(['resourceNode' => $nodeId]);
313
        $resourceNodeParentId = $resource->getResourceNode()->getId();
314
315
        $form = $repository->getForm($this->container->get('form.factory'), $resource);
316
317
        $form->handleRequest($request);
318
319
        if ($form->isSubmitted() && $form->isValid()) {
320
            /** @var CDocument $newResource */
321
            $newResource = $form->getData();
322
            $em = $this->getDoctrine()->getManager();
323
            $em->persist($newResource);
324
            $em->flush();
325
            $this->addFlash('success', $this->trans('Updated'));
326
327
            if ($newResource->getResourceNode()->hasResourceFile()) {
328
                $resourceNodeParentId = $newResource->getResourceNode()->getParent()->getId();
329
            }
330
331
            return $this->redirectToRoute(
332
                'chamilo_core_resource_list',
333
                [
334
                    'id' => $resourceNodeParentId,
335
                    'tool' => $tool,
336
                    'type' => $type,
337
                    'cidReq' => $this->getCourse()->getCode(),
338
                ]
339
            );
340
        }
341
342
        return $this->render(
343
            '@ChamiloTheme/Resource/edit.html.twig',
344
            [
345
                'form' => $form->createView(),
346
                'parent' => $resourceNodeParentId,
347
            ]
348
        );
349
350
351
    }
352
353
    /**
354
     * Shows a resource.
355
     *
356
     * @Route("/{tool}/{type}/{id}/show", methods={"GET"}, name="chamilo_core_resource_show")
357
     *
358
     * @param Request $request
359
     *
360
     * @return Response
361
     */
362
    public function showAction(Request $request): Response
363
    {
364
        $this->setBreadCrumb($request);
365
366
        $em = $this->getDoctrine();
367
368
        $id = $request->get('id');
369
        $resourceNode = $em->getRepository('ChamiloCoreBundle:Resource\ResourceNode')->find($id);
370
371
        if (null === $resourceNode) {
372
            throw new NotFoundHttpException();
373
        }
374
375
        $this->denyAccessUnlessGranted(
376
            ResourceNodeVoter::VIEW,
377
            $resourceNode,
378
            'Unauthorised access to resource'
379
        );
380
381
        $tool = $request->get('tool');
382
        $type = $request->get('type');
383
384
        $params = [
385
            'resource_node' => $resourceNode,
386
            'tool' => $tool,
387
            'type' => $type,
388
        ];
389
390
        return $this->render('@ChamiloTheme/Resource/show.html.twig', $params);
391
    }
392
393
    /**
394
     * @Route("/{tool}/{type}/{id}", methods={"DELETE"}, name="chamilo_core_resource_delete")
395
     *
396
     * @param Request $request
397
     *
398
     * @return Response
399
     */
400
    public function deleteAction(Request $request): Response
401
    {
402
        $tool = $request->get('tool');
403
        $type = $request->get('type');
404
405
        $em = $this->getDoctrine()->getManager();
406
407
        $id = $request->get('id');
408
        $resourceNode = $this->getDoctrine()->getRepository('ChamiloCoreBundle:Resource\ResourceNode')->find($id);
409
        $parentId = $resourceNode->getParent()->getId();
410
411
        if (null === $resourceNode) {
412
            throw new NotFoundHttpException();
413
        }
414
415
        $this->denyAccessUnlessGranted(
416
            ResourceNodeVoter::DELETE,
417
            $resourceNode,
418
            'Unauthorised access to resource'
419
        );
420
421
        $em->remove($resourceNode);
422
        $this->addFlash('success', $this->trans('Deleted'));
423
        $em->flush();
424
425
        return $this->redirectToRoute(
426
            'chamilo_core_resource_list',
427
            [
428
                'id' => $parentId,
429
                'tool' => $tool,
430
                'type' => $type,
431
                'cidReq' => $this->getCourse()->getCode(),
432
            ]
433
        );
434
    }
435
436
    /**
437
     * @Route("/{tool}/{type}/{id}", methods={"DELETE"}, name="chamilo_core_resource_delete_mass")
438
     *
439
     * @param Request $request
440
     *
441
     * @return Response
442
     */
443
    public function deleteMassAction($primaryKeys, $allPrimaryKeys, Request $request): Response
444
    {
445
        $tool = $request->get('tool');
446
        $type = $request->get('type');
447
        $em = $this->getDoctrine()->getManager();
448
        $repo = $this->getRepositoryFromRequest($request);
449
450
        $parentId = 0;
451
        foreach ($primaryKeys as $id) {
452
            $resource = $repo->find($id);
453
            $resourceNode = $resource->getResourceNode();
454
455
            if (null === $resourceNode) {
456
                continue;
457
            }
458
459
            $this->denyAccessUnlessGranted(
460
                ResourceNodeVoter::DELETE,
461
                $resourceNode,
462
                'Unauthorised access to resource'
463
            );
464
465
            $parentId = $resourceNode->getParent()->getId();
466
            $em->remove($resource);
467
        }
468
469
        $this->addFlash('success', $this->trans('Deleted'));
470
        $em->flush();
471
472
        return $this->redirectToRoute(
473
            'chamilo_core_resource_list',
474
            [
475
                'id' => $parentId,
476
                'tool' => $tool,
477
                'type' => $type,
478
                'cidReq' => $this->getCourse()->getCode(),
479
            ]
480
        );
481
    }
482
483
    /**
484
     * @Route("/{tool}/{type}/{id}/file", methods={"GET"}, name="chamilo_core_resource_file")
485
     *
486
     * @param Request $request
487
     * @param Glide   $glide
488
     *
489
     * @return Response
490
     */
491
    public function getResourceFileAction(Request $request, Glide $glide): Response
492
    {
493
        $id = $request->get('id');
494
        $filter = $request->get('filter');
495
        $mode = $request->get('mode');
496
        $em = $this->getDoctrine();
497
        $resourceNode = $em->getRepository('ChamiloCoreBundle:Resource\ResourceNode')->find($id);
498
499
        if ($resourceNode === null) {
500
            throw new FileNotFoundException('Not found');
501
        }
502
503
        return $this->showFile($request, $resourceNode, $glide, $mode, $filter);
504
    }
505
506
    /**
507
     * Gets a document when calling route resources_document_get_file.
508
     *
509
     * @param Request             $request
510
     * @param CDocumentRepository $documentRepo
511
     * @param Glide               $glide
512
     *
513
     * @return Response
514
     * @throws \League\Flysystem\FileNotFoundException
515
     */
516
    public function getDocumentAction(Request $request, CDocumentRepository $documentRepo, Glide $glide): Response
517
    {
518
        $file = $request->get('file');
519
        $mode = $request->get('mode');
520
        // see list of filters in config/services.yaml
521
        $filter = $request->get('filter');
522
        $mode = !empty($mode) ? $mode : 'show';
523
        $criteria = [
524
            'path' => "/$file",
525
            'course' => $this->getCourse(),
526
        ];
527
528
        $document = $documentRepo->findOneBy($criteria);
529
530
        if (null === $document) {
531
            throw new NotFoundHttpException();
532
        }
533
        /** @var ResourceNode $resourceNode */
534
        $resourceNode = $document->getResourceNode();
535
536
        return $this->showFile($request, $resourceNode, $glide, $mode, $filter);
537
    }
538
539
    /**
540
     * Downloads a folder.
541
     *
542
     * @param Request             $request
543
     * @param CDocumentRepository $documentRepo
544
     *
545
     * @return Response
546
     */
547
    public function downloadFolderAction(Request $request, CDocumentRepository $documentRepo)
548
    {
549
        $folderId = (int) $request->get('folderId');
550
        $courseNode = $this->getCourse()->getResourceNode();
551
552
        if (empty($folderId)) {
553
            $resourceNode = $courseNode;
554
        } else {
555
            $document = $documentRepo->find($folderId);
556
            $resourceNode = $document->getResourceNode();
557
        }
558
559
        $type = $documentRepo->getResourceType();
560
561
        if (null === $resourceNode || null === $courseNode) {
562
            throw new NotFoundHttpException();
563
        }
564
565
        $this->denyAccessUnlessGranted(
566
            ResourceNodeVoter::VIEW,
567
            $resourceNode,
568
            'Unauthorised access to resource'
569
        );
570
571
        $zipName = $resourceNode->getName().'.zip';
572
        $rootNodePath = $resourceNode->getPathForDisplay();
573
574
        /** @var Filesystem $fileSystem */
575
        $fileSystem = $this->get('oneup_flysystem.resources_filesystem');
576
577
        $resourceNodeRepo = $documentRepo->getResourceNodeRepository();
578
579
        $criteria = Criteria::create()
580
            ->where(Criteria::expr()->neq('resourceFile', null))
581
            ->andWhere(Criteria::expr()->eq('resourceType', $type))
582
        ;
583
584
        /** @var ArrayCollection|ResourceNode[] $children */
585
        /** @var QueryBuilder $children */
586
        $qb = $resourceNodeRepo->getChildrenQueryBuilder($resourceNode);
587
        $qb->addCriteria($criteria);
588
        $children = $qb->getQuery()->getResult();
589
590
        /** @var ResourceNode $node */
591
        foreach ($children as $node) {
592
            /*if ($node->hasResourceFile()) {
593
                $resourceFile = $node->getResourceFile();
594
                $systemName = $resourceFile->getFile()->getPathname();
595
                $stream = $fileSystem->readStream($systemName);
596
                //error_log($node->getPathForDisplay());
597
                $fileToDisplay = str_replace($rootNodePath, '', $node->getPathForDisplay());
598
                var_dump($fileToDisplay);
599
            }*/
600
            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...
601
            //var_dump($node['path']);
602
        }
603
604
        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...
605
606
607
        $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...
608
        {
609
            // Define suitable options for ZipStream Archive.
610
            $options = new Archive();
611
            $options->setContentType('application/octet-stream');
612
            //initialise zipstream with output zip filename and options.
613
            $zip = new ZipStream($zipName, $options);
614
615
            /** @var ResourceNode $node */
616
            foreach ($children as $node) {
617
                $resourceFile = $node->getResourceFile();
618
                $systemName = $resourceFile->getFile()->getPathname();
619
                $stream = $fileSystem->readStream($systemName);
620
                //error_log($node->getPathForDisplay());
621
                $fileToDisplay = str_replace($rootNodePath, '', $node->getPathForDisplay());
622
                $zip->addFileFromStream($fileToDisplay, $stream);
623
            }
624
            //$data = $repo->getDocumentContent($not_deleted_file['id']);
625
            //$zip->addFile($not_deleted_file['path'], $data);
626
            $zip->finish();
627
        });
628
629
        $disposition = $response->headers->makeDisposition(
630
            ResponseHeaderBag::DISPOSITION_ATTACHMENT,
631
            Transliterator::transliterate($zipName)
632
        );
633
        $response->headers->set('Content-Disposition', $disposition);
634
        $response->headers->set('Content-Type', 'application/octet-stream');
635
636
        return $response;
637
    }
638
639
    /**
640
     * Upload form.
641
     *
642
     * @Route("/{tool}/{type}/{id}/upload", name="chamilo_core_resource_upload", methods={"GET", "POST"},
643
     *                                      options={"expose"=true})
644
     */
645
    public function uploadAction(Request $request, $tool, $type, $id): Response
646
    {
647
        $this->setBreadCrumb( $request);
648
        //$helper = $this->container->get('oneup_uploader.templating.uploader_helper');
649
        //$endpoint = $helper->endpoint('courses');
650
        $session = $this->getSession();
651
        $sessionId = $session ? $session->getId() : 0;
0 ignored issues
show
introduced by
$session is of type Chamilo\CoreBundle\Entity\Session, thus it always evaluated to true.
Loading history...
652
653
        return $this->render(
654
            '@ChamiloTheme/Resource/upload.html.twig',
655
            [
656
                'id' => $id,
657
                'type' => $type,
658
                'tool' => $tool,
659
                'cidReq' => $this->getCourse()->getCode(),
660
                'id_session' => $sessionId,
661
            ]
662
        );
663
    }
664
665
    /**
666
     * @param Request      $request
667
     * @param ResourceNode $resourceNode
668
     * @param Glide        $glide
669
     * @param string       $mode show or download
670
     * @param string       $filter
671
     *
672
     * @return mixed|StreamedResponse
673
     */
674
    private function showFile(Request $request, ResourceNode $resourceNode, Glide $glide, $mode = 'show', $filter = '')
675
    {
676
        $this->denyAccessUnlessGranted(
677
            ResourceNodeVoter::VIEW,
678
            $resourceNode,
679
            'Unauthorised access to resource'
680
        );
681
        $resourceFile = $resourceNode->getResourceFile();
682
683
        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...
684
            throw new NotFoundHttpException();
685
        }
686
687
        $fileName = $resourceNode->getName();
688
        $filePath = $resourceFile->getFile()->getPathname();
689
        $mimeType = $resourceFile->getMimeType();
690
691
        switch ($mode) {
692
            case 'download':
693
                $forceDownload = true;
694
                break;
695
            case 'show':
696
            default:
697
                $forceDownload = false;
698
                // If it's an image then send it to Glide.
699
                if (strpos($mimeType, 'image') !== false) {
700
                    $server = $glide->getServer();
701
                    $params = $request->query->all();
702
703
                    // The filter overwrites the params from get
704
                    if (!empty($filter)) {
705
                        $params = $glide->getFilters()[$filter] ?? [];
706
                    }
707
708
                    // The image was cropped manually by the user, so we force to render this version,
709
                    // no matter other crop parameters.
710
                    $crop = $resourceFile->getCrop();
711
                    if (!empty($crop)) {
712
                        $params['crop'] = $crop;
713
                    }
714
715
                    return $server->getImageResponse($filePath, $params);
716
                }
717
                break;
718
        }
719
720
        $stream = $this->fs->readStream($filePath);
721
        $response = new StreamedResponse(function () use ($stream): void {
722
            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

722
            stream_copy_to_stream($stream, /** @scrutinizer ignore-type */ fopen('php://output', 'wb'));
Loading history...
723
        });
724
        $disposition = $response->headers->makeDisposition(
725
            $forceDownload ? ResponseHeaderBag::DISPOSITION_ATTACHMENT : ResponseHeaderBag::DISPOSITION_INLINE,
726
            Transliterator::transliterate($fileName)
727
        );
728
        $response->headers->set('Content-Disposition', $disposition);
729
        $response->headers->set('Content-Type', $mimeType ?: 'application/octet-stream');
730
731
        return $response;
732
    }
733
734
    /**
735
     * @param Request $request
736
     * @param string  $fileType
737
     *
738
     * @return RedirectResponse|Response
739
     */
740
    private function createResource(Request $request, $fileType = 'file')
741
    {
742
        $tool = $request->get('tool');
743
        $type = $request->get('type');
744
        $resourceNodeParentId = $request->get('id');
745
746
        $repository = $this->getRepositoryFromRequest($request);
747
748
        $form = $repository->getForm($this->container->get('form.factory'));
749
750
        if ($fileType === 'file') {
751
            $form->add(
752
                'content',
753
                CKEditorType::class,
754
                [
755
                    'mapped' => false,
756
                    'config' => [
757
                        'filebrowserImageBrowseRoute' => 'editor_filemanager',
758
                        'filebrowserImageBrowseRouteParameters' => array(
759
                            'tool' => $tool,
760
                            'type' => $type,
761
                            'cidReq' => $this->getCourse()->getCode(),
762
                            'id' => $resourceNodeParentId
763
                        )
764
                    ],
765
                ]
766
            );
767
        }
768
769
        $course = $this->getCourse();
770
        $session = $this->getSession();
771
        $parentNode = $course->getResourceNode();
772
        if (!empty($resourceNodeParentId)) {
773
            $parentNode = $repository->getResourceNodeRepository()->find($resourceNodeParentId);
774
        }
775
776
        $form->handleRequest($request);
777
        if ($form->isSubmitted() && $form->isValid()) {
778
            $em = $this->getDoctrine()->getManager();
779
780
            /** @var CDocument $newResource */
781
            $newResource = $form->getData();
782
783
            $newResource
784
                ->setCourse($course)
785
                ->setSession($session)
786
                ->setFiletype($fileType)
787
                //->setTitle($title) // already added in $form->getData()
788
                ->setReadonly(false)
789
            ;
790
791
            if ($fileType === 'file') {
792
                $content = $form->get('content')->getViewData();
793
                $fileName = $newResource->getTitle().'.html';
794
                $handle = tmpfile();
795
                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

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

796
                $meta = stream_get_meta_data(/** @scrutinizer ignore-type */ $handle);
Loading history...
797
798
                $file = new UploadedFile($meta['uri'], $fileName, null, null, true);
799
800
                $em->persist($newResource);
801
                $em->flush();
802
            }
803
804
            $resourceNode = $repository->addResourceNodeParent($newResource, $this->getUser(), $parentNode);
805
806
            if ($fileType === 'file') {
807
                $resourceNode->setName($fileName);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $fileName does not seem to be defined for all execution paths leading up to this point.
Loading history...
808
                $resourceFile = new ResourceFile();
809
                $resourceFile->setFile($file);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $file does not seem to be defined for all execution paths leading up to this point.
Loading history...
810
                $resourceFile->setName($fileName);
811
                $em->persist($resourceFile);
812
                $resourceNode->setResourceFile($resourceFile);
813
            }
814
815
            $em->persist($resourceNode);
816
817
            $repository->addResourceNodeToCourse(
818
                $resourceNode,
819
                ResourceLink::VISIBILITY_PUBLISHED,
820
                $course,
821
                $session,
822
                null
823
            );
824
825
            $em->flush();
826
827
            // Loops all sharing options
828
            /*foreach ($shareList as $share) {
829
                $idList = [];
830
                if (isset($share['search'])) {
831
                    $idList = explode(',', $share['search']);
832
                }
833
834
                $resourceRight = null;
835
                if (isset($share['mask'])) {
836
                    $resourceRight = new ResourceRight();
837
                    $resourceRight
838
                        ->setMask($share['mask'])
839
                        ->setRole($share['role'])
840
                    ;
841
                }
842
843
                // Build links
844
                switch ($share['sharing']) {
845
                    case 'everyone':
846
                        $repository->addResourceToEveryone(
847
                            $resourceNode,
848
                            $resourceRight
849
                        );
850
                        break;
851
                    case 'course':
852
                        $repository->addResourceToCourse(
853
                            $resourceNode,
854
                            $course,
855
                            $resourceRight
856
                        );
857
                        break;
858
                    case 'session':
859
                        $repository->addResourceToSession(
860
                            $resourceNode,
861
                            $course,
862
                            $session,
863
                            $resourceRight
864
                        );
865
                        break;
866
                    case 'user':
867
                        // Only for me
868
                        if (isset($share['only_me'])) {
869
                            $repository->addResourceOnlyToMe($resourceNode);
870
                        } else {
871
                            // To other users
872
                            $repository->addResourceToUserList($resourceNode, $idList);
873
                        }
874
                        break;
875
                    case 'group':
876
                        // @todo
877
                        break;
878
                }*/
879
            //}
880
            $em->flush();
881
            $this->addFlash('success', $this->trans('Saved'));
882
883
            return $this->redirectToRoute(
884
                'chamilo_core_resource_list',
885
                [
886
                    'id' => $resourceNodeParentId,
887
                    'tool' => $tool,
888
                    'type' => $type,
889
                    'cidReq' => $this->getCourse()->getCode(),
890
                ]
891
            );
892
        }
893
894
        switch ($fileType) {
895
            case 'folder':
896
                $template = '@ChamiloTheme/Resource/new_folder.html.twig';
897
                break;
898
            case 'file':
899
                $template = '@ChamiloTheme/Resource/new.html.twig';
900
                break;
901
        }
902
903
        return $this->render(
904
            $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...
905
            [
906
                'form' => $form->createView(),
907
                'parent' => $resourceNodeParentId,
908
                'file_type' => $fileType,
909
            ]
910
        );
911
    }
912
913
914
    /**
915
     * @param Request $request
916
     */
917
    public function setBreadCrumb(Request $request)
918
    {
919
        $tool = $request->get('tool');
920
        $type = $request->get('type');
921
        $resourceNodeId = $request->get('id');
922
        $courseCode = $request->get('cidReq');
923
924
        if (!empty($resourceNodeId)) {
925
            $breadcrumb = $this->breadcrumbBlockService;
926
927
            // Root tool link
928
            $breadcrumb->addChild(
929
                $this->translator->trans('Documents'),
930
                [
931
                    'uri' => $this->generateUrl(
932
                        'chamilo_core_resource_index',
933
                        ['tool' => $tool, 'type' => $type, 'cidReq' => $courseCode]
934
                    ),
935
                ]
936
            );
937
938
            $repo = $this->getRepositoryFromRequest($request);
939
940
            /** @var ResourceNode $parent */
941
            $originalResource = $repo->findOneBy([ 'resourceNode' => $resourceNodeId]);
942
            if ($originalResource === null) {
943
                return;
944
            }
945
            $parent = $originalParent = $originalResource->getResourceNode();
946
947
            $parentList = [];
948
            while ($parent !== null) {
949
                if ($type !== $parent->getResourceType()->getName()){
950
                    break;
951
                }
952
                $parent = $parent->getParent();
953
                if ($parent) {
954
                    $resource = $repo->findOneBy([ 'resourceNode' => $parent->getId()]);
955
                    if ($resource) {
956
                        $parentList[] = $resource;
957
                    }
958
                }
959
            }
960
961
            $parentList = array_reverse($parentList);
962
            /** @var AbstractResource $item */
963
            foreach ($parentList as $item) {
964
                $breadcrumb->addChild(
965
                    $item->getResourceName(),
966
                    [
967
                        'uri' => $this->generateUrl(
968
                            'chamilo_core_resource_list',
969
                            [
970
                                'tool' => $tool,
971
                                'type' => $type,
972
                                'id' => $item->getResourceNode()->getId(),
973
                                'cidReq' => $courseCode,
974
                            ]
975
                        ),
976
                    ]
977
                );
978
            }
979
980
            $breadcrumb->addChild(
981
                $originalResource->getResourceName(),
982
                [
983
                    'uri' => $this->generateUrl(
984
                        'chamilo_core_resource_list',
985
                        ['tool' => $tool, 'type' => $type, 'id' => $originalParent->getId(), 'cidReq' => $courseCode]
986
                    ),
987
                ]
988
            );
989
        }
990
    }
991
}
992