Completed
Push — master ( 55196a...15a37f )
by Julito
12:31
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
        $url = $this->generateUrl('editor_filemanager');
750
        $form->add(
751
            'content',
752
            CKEditorType::class,
753
            [
754
                'mapped' => false,
755
                'config' => [
756
                    'filebrowserImageBrowseRoute' => 'editor_filemanager',
757
                    'filebrowserImageBrowseRouteParameters' => array(
758
                        'tool' => $tool,
759
                        'type' => $type,
760
                        'cidReq' => $this->getCourse()->getCode(),
761
                        'id' => $resourceNodeParentId
762
                    )
763
                    ],
764
            ]
765
        );
766
767
        $course = $this->getCourse();
768
        $session = $this->getSession();
769
        $parentNode = $course->getResourceNode();
770
        if (!empty($resourceNodeParentId)) {
771
            $parentNode = $repository->getResourceNodeRepository()->find($resourceNodeParentId);
772
        }
773
774
        $form->handleRequest($request);
775
        if ($form->isSubmitted() && $form->isValid()) {
776
            /** @var CDocument $newResource */
777
            $newResource = $form->getData();
778
779
            $newResource
780
                ->setCourse($course)
781
                ->setSession($session)
782
                ->setFiletype($fileType)
783
                //->setTitle($title) // already added in $form->getData()
784
                ->setReadonly(false)
785
            ;
786
787
            $content = $form->get('content')->getViewData();
788
789
            $fileName = $newResource->getTitle().'.html';
790
            $handle = tmpfile();
791
            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

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

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