Completed
Push — master ( 4874d1...5ea477 )
by Julito
10:24
created

ResourceController::indexAction()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 21
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 11
nc 1
nop 2
dl 0
loc 21
rs 9.9
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
        $this->setBreadCrumb($request);
312
313
        $repository = $this->getRepositoryFromRequest($request);
314
        /** @var AbstractResource $resource */
315
        $resource = $repository->getRepository()->findOneBy(['resourceNode' => $nodeId]);
316
        $node = $resource->getResourceNode();
317
        $resourceNodeParentId = $node->getId();
318
319
        $form = $repository->getForm($this->container->get('form.factory'), $resource);
320
321
        if ($node->isEditable()) {
322
            $form->add(
323
                'content',
324
                CKEditorType::class,
325
                [
326
                    'mapped' => false,
327
                    'config' => [
328
                        'filebrowserImageBrowseRoute' => 'editor_filemanager',
329
                        'filebrowserImageBrowseRouteParameters' => array(
330
                            'tool' => $tool,
331
                            'type' => $type,
332
                            'cidReq' => $this->getCourse()->getCode(),
333
                            'id' => $resourceNodeParentId
334
                        )
335
                    ],
336
                ]
337
            );
338
            $content = $repository->getResourceFileContent($resource);
339
            $form->get('content')->setData($content);
340
        }
341
342
        $form->handleRequest($request);
343
344
        if ($form->isSubmitted() && $form->isValid()) {
345
            /** @var CDocument $newResource */
346
            $newResource = $form->getData();
347
            $em = $this->getDoctrine()->getManager();
348
            $data = $form->get('content')->getData();
349
            $repository->updateResourceFileContent($newResource, $data);
350
351
            $em->persist($newResource);
352
            $em->flush();
353
            $this->addFlash('success', $this->trans('Updated'));
354
355
            if ($newResource->getResourceNode()->hasResourceFile()) {
356
                $resourceNodeParentId = $newResource->getResourceNode()->getParent()->getId();
357
            }
358
359
            return $this->redirectToRoute(
360
                'chamilo_core_resource_list',
361
                [
362
                    'id' => $resourceNodeParentId,
363
                    'tool' => $tool,
364
                    'type' => $type,
365
                    'cidReq' => $this->getCourse()->getCode(),
366
                ]
367
            );
368
        }
369
370
        return $this->render(
371
            '@ChamiloTheme/Resource/edit.html.twig',
372
            [
373
                'form' => $form->createView(),
374
                'parent' => $resourceNodeParentId,
375
            ]
376
        );
377
    }
378
379
    /**
380
     * Shows a resource.
381
     *
382
     * @Route("/{tool}/{type}/{id}/show", methods={"GET"}, name="chamilo_core_resource_show")
383
     *
384
     * @param Request $request
385
     *
386
     * @return Response
387
     */
388
    public function showAction(Request $request): Response
389
    {
390
        $this->setBreadCrumb($request);
391
392
        $em = $this->getDoctrine();
393
394
        $id = $request->get('id');
395
        $resourceNode = $em->getRepository('ChamiloCoreBundle:Resource\ResourceNode')->find($id);
396
397
        if (null === $resourceNode) {
398
            throw new NotFoundHttpException();
399
        }
400
401
        $this->denyAccessUnlessGranted(
402
            ResourceNodeVoter::VIEW,
403
            $resourceNode,
404
            'Unauthorised access to resource'
405
        );
406
407
        $tool = $request->get('tool');
408
        $type = $request->get('type');
409
410
        $params = [
411
            'resource_node' => $resourceNode,
412
            'tool' => $tool,
413
            'type' => $type,
414
        ];
415
416
        return $this->render('@ChamiloTheme/Resource/show.html.twig', $params);
417
    }
418
419
    /**
420
     * @Route("/{tool}/{type}/{id}", methods={"DELETE"}, name="chamilo_core_resource_delete")
421
     *
422
     * @param Request $request
423
     *
424
     * @return Response
425
     */
426
    public function deleteAction(Request $request): Response
427
    {
428
        $tool = $request->get('tool');
429
        $type = $request->get('type');
430
431
        $em = $this->getDoctrine()->getManager();
432
433
        $id = $request->get('id');
434
        $resourceNode = $this->getDoctrine()->getRepository('ChamiloCoreBundle:Resource\ResourceNode')->find($id);
435
        $parentId = $resourceNode->getParent()->getId();
436
437
        if (null === $resourceNode) {
438
            throw new NotFoundHttpException();
439
        }
440
441
        $this->denyAccessUnlessGranted(
442
            ResourceNodeVoter::DELETE,
443
            $resourceNode,
444
            'Unauthorised access to resource'
445
        );
446
447
        $em->remove($resourceNode);
448
        $this->addFlash('success', $this->trans('Deleted'));
449
        $em->flush();
450
451
        return $this->redirectToRoute(
452
            'chamilo_core_resource_list',
453
            [
454
                'id' => $parentId,
455
                'tool' => $tool,
456
                'type' => $type,
457
                'cidReq' => $this->getCourse()->getCode(),
458
            ]
459
        );
460
    }
461
462
    /**
463
     * @Route("/{tool}/{type}/{id}", methods={"DELETE"}, name="chamilo_core_resource_delete_mass")
464
     *
465
     * @param Request $request
466
     *
467
     * @return Response
468
     */
469
    public function deleteMassAction($primaryKeys, $allPrimaryKeys, Request $request): Response
470
    {
471
        $tool = $request->get('tool');
472
        $type = $request->get('type');
473
        $em = $this->getDoctrine()->getManager();
474
        $repo = $this->getRepositoryFromRequest($request);
475
476
        $parentId = 0;
477
        foreach ($primaryKeys as $id) {
478
            $resource = $repo->find($id);
479
            $resourceNode = $resource->getResourceNode();
480
481
            if (null === $resourceNode) {
482
                continue;
483
            }
484
485
            $this->denyAccessUnlessGranted(
486
                ResourceNodeVoter::DELETE,
487
                $resourceNode,
488
                'Unauthorised access to resource'
489
            );
490
491
            $parentId = $resourceNode->getParent()->getId();
492
            $em->remove($resource);
493
        }
494
495
        $this->addFlash('success', $this->trans('Deleted'));
496
        $em->flush();
497
498
        return $this->redirectToRoute(
499
            'chamilo_core_resource_list',
500
            [
501
                'id' => $parentId,
502
                'tool' => $tool,
503
                'type' => $type,
504
                'cidReq' => $this->getCourse()->getCode(),
505
            ]
506
        );
507
    }
508
509
    /**
510
     * @Route("/{tool}/{type}/{id}/file", methods={"GET"}, name="chamilo_core_resource_file")
511
     *
512
     * @param Request $request
513
     * @param Glide   $glide
514
     *
515
     * @return Response
516
     */
517
    public function getResourceFileAction(Request $request, Glide $glide): Response
518
    {
519
        $id = $request->get('id');
520
        $filter = $request->get('filter');
521
        $mode = $request->get('mode');
522
        $em = $this->getDoctrine();
523
        $resourceNode = $em->getRepository('ChamiloCoreBundle:Resource\ResourceNode')->find($id);
524
525
        if ($resourceNode === null) {
526
            throw new FileNotFoundException('Not found');
527
        }
528
529
        return $this->showFile($request, $resourceNode, $glide, $mode, $filter);
530
    }
531
532
    /**
533
     * Gets a document when calling route resources_document_get_file.
534
     *
535
     * @param Request             $request
536
     * @param CDocumentRepository $documentRepo
537
     * @param Glide               $glide
538
     *
539
     * @return Response
540
     * @throws \League\Flysystem\FileNotFoundException
541
     */
542
    public function getDocumentAction(Request $request, CDocumentRepository $documentRepo, Glide $glide): Response
543
    {
544
        $file = $request->get('file');
545
        $mode = $request->get('mode');
546
        // see list of filters in config/services.yaml
547
        $filter = $request->get('filter');
548
        $mode = !empty($mode) ? $mode : 'show';
549
        $criteria = [
550
            'path' => "/$file",
551
            'course' => $this->getCourse(),
552
        ];
553
554
        $document = $documentRepo->findOneBy($criteria);
555
556
        if (null === $document) {
557
            throw new NotFoundHttpException();
558
        }
559
        /** @var ResourceNode $resourceNode */
560
        $resourceNode = $document->getResourceNode();
561
562
        return $this->showFile($request, $resourceNode, $glide, $mode, $filter);
563
    }
564
565
    /**
566
     * Downloads a folder.
567
     *
568
     * @param Request             $request
569
     * @param CDocumentRepository $documentRepo
570
     *
571
     * @return Response
572
     */
573
    public function downloadFolderAction(Request $request, CDocumentRepository $documentRepo)
574
    {
575
        $folderId = (int) $request->get('folderId');
576
        $courseNode = $this->getCourse()->getResourceNode();
577
578
        if (empty($folderId)) {
579
            $resourceNode = $courseNode;
580
        } else {
581
            $document = $documentRepo->find($folderId);
582
            $resourceNode = $document->getResourceNode();
583
        }
584
585
        $type = $documentRepo->getResourceType();
586
587
        if (null === $resourceNode || null === $courseNode) {
588
            throw new NotFoundHttpException();
589
        }
590
591
        $this->denyAccessUnlessGranted(
592
            ResourceNodeVoter::VIEW,
593
            $resourceNode,
594
            'Unauthorised access to resource'
595
        );
596
597
        $zipName = $resourceNode->getName().'.zip';
598
        $rootNodePath = $resourceNode->getPathForDisplay();
599
600
        /** @var Filesystem $fileSystem */
601
        $fileSystem = $this->get('oneup_flysystem.resources_filesystem');
602
603
        $resourceNodeRepo = $documentRepo->getResourceNodeRepository();
604
605
        $criteria = Criteria::create()
606
            ->where(Criteria::expr()->neq('resourceFile', null))
607
            ->andWhere(Criteria::expr()->eq('resourceType', $type))
608
        ;
609
610
        /** @var ArrayCollection|ResourceNode[] $children */
611
        /** @var QueryBuilder $children */
612
        $qb = $resourceNodeRepo->getChildrenQueryBuilder($resourceNode);
613
        $qb->addCriteria($criteria);
614
        $children = $qb->getQuery()->getResult();
615
616
        /** @var ResourceNode $node */
617
        foreach ($children as $node) {
618
            /*if ($node->hasResourceFile()) {
619
                $resourceFile = $node->getResourceFile();
620
                $systemName = $resourceFile->getFile()->getPathname();
621
                $stream = $fileSystem->readStream($systemName);
622
                //error_log($node->getPathForDisplay());
623
                $fileToDisplay = str_replace($rootNodePath, '', $node->getPathForDisplay());
624
                var_dump($fileToDisplay);
625
            }*/
626
            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...
627
            //var_dump($node['path']);
628
        }
629
630
        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...
631
632
633
        $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...
634
        {
635
            // Define suitable options for ZipStream Archive.
636
            $options = new Archive();
637
            $options->setContentType('application/octet-stream');
638
            //initialise zipstream with output zip filename and options.
639
            $zip = new ZipStream($zipName, $options);
640
641
            /** @var ResourceNode $node */
642
            foreach ($children as $node) {
643
                $resourceFile = $node->getResourceFile();
644
                $systemName = $resourceFile->getFile()->getPathname();
645
                $stream = $fileSystem->readStream($systemName);
646
                //error_log($node->getPathForDisplay());
647
                $fileToDisplay = str_replace($rootNodePath, '', $node->getPathForDisplay());
648
                $zip->addFileFromStream($fileToDisplay, $stream);
649
            }
650
            //$data = $repo->getDocumentContent($not_deleted_file['id']);
651
            //$zip->addFile($not_deleted_file['path'], $data);
652
            $zip->finish();
653
        });
654
655
        $disposition = $response->headers->makeDisposition(
656
            ResponseHeaderBag::DISPOSITION_ATTACHMENT,
657
            Transliterator::transliterate($zipName)
658
        );
659
        $response->headers->set('Content-Disposition', $disposition);
660
        $response->headers->set('Content-Type', 'application/octet-stream');
661
662
        return $response;
663
    }
664
665
    /**
666
     * Upload form.
667
     *
668
     * @Route("/{tool}/{type}/{id}/upload", name="chamilo_core_resource_upload", methods={"GET", "POST"},
669
     *                                      options={"expose"=true})
670
     */
671
    public function uploadAction(Request $request, $tool, $type, $id): Response
672
    {
673
        $this->setBreadCrumb( $request);
674
        //$helper = $this->container->get('oneup_uploader.templating.uploader_helper');
675
        //$endpoint = $helper->endpoint('courses');
676
        $session = $this->getSession();
677
        $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...
678
679
        return $this->render(
680
            '@ChamiloTheme/Resource/upload.html.twig',
681
            [
682
                'id' => $id,
683
                'type' => $type,
684
                'tool' => $tool,
685
                'cidReq' => $this->getCourse()->getCode(),
686
                'id_session' => $sessionId,
687
            ]
688
        );
689
    }
690
691
    /**
692
     * @param Request      $request
693
     * @param ResourceNode $resourceNode
694
     * @param Glide        $glide
695
     * @param string       $mode show or download
696
     * @param string       $filter
697
     *
698
     * @return mixed|StreamedResponse
699
     */
700
    private function showFile(Request $request, ResourceNode $resourceNode, Glide $glide, $mode = 'show', $filter = '')
701
    {
702
        $this->denyAccessUnlessGranted(
703
            ResourceNodeVoter::VIEW,
704
            $resourceNode,
705
            'Unauthorised access to resource'
706
        );
707
        $resourceFile = $resourceNode->getResourceFile();
708
709
        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...
710
            throw new NotFoundHttpException();
711
        }
712
713
        $fileName = $resourceNode->getName();
714
        $filePath = $resourceFile->getFile()->getPathname();
715
        $mimeType = $resourceFile->getMimeType();
716
717
        switch ($mode) {
718
            case 'download':
719
                $forceDownload = true;
720
                break;
721
            case 'show':
722
            default:
723
                $forceDownload = false;
724
                // If it's an image then send it to Glide.
725
                if (strpos($mimeType, 'image') !== false) {
726
                    $server = $glide->getServer();
727
                    $params = $request->query->all();
728
729
                    // The filter overwrites the params from get
730
                    if (!empty($filter)) {
731
                        $params = $glide->getFilters()[$filter] ?? [];
732
                    }
733
734
                    // The image was cropped manually by the user, so we force to render this version,
735
                    // no matter other crop parameters.
736
                    $crop = $resourceFile->getCrop();
737
                    if (!empty($crop)) {
738
                        $params['crop'] = $crop;
739
                    }
740
741
                    return $server->getImageResponse($filePath, $params);
742
                }
743
                break;
744
        }
745
746
        $stream = $this->fs->readStream($filePath);
747
        $response = new StreamedResponse(function () use ($stream): void {
748
            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

748
            stream_copy_to_stream($stream, /** @scrutinizer ignore-type */ fopen('php://output', 'wb'));
Loading history...
749
        });
750
        $disposition = $response->headers->makeDisposition(
751
            $forceDownload ? ResponseHeaderBag::DISPOSITION_ATTACHMENT : ResponseHeaderBag::DISPOSITION_INLINE,
752
            Transliterator::transliterate($fileName)
753
        );
754
        $response->headers->set('Content-Disposition', $disposition);
755
        $response->headers->set('Content-Type', $mimeType ?: 'application/octet-stream');
756
757
        return $response;
758
    }
759
760
    /**
761
     * @param Request $request
762
     * @param string  $fileType
763
     *
764
     * @return RedirectResponse|Response
765
     */
766
    private function createResource(Request $request, $fileType = 'file')
767
    {
768
        $tool = $request->get('tool');
769
        $type = $request->get('type');
770
        $resourceNodeParentId = $request->get('id');
771
772
        $repository = $this->getRepositoryFromRequest($request);
773
774
        $form = $repository->getForm($this->container->get('form.factory'));
775
776
        if ($fileType === 'file') {
777
            $form->add(
778
                'content',
779
                CKEditorType::class,
780
                [
781
                    'mapped' => false,
782
                    'config' => [
783
                        'filebrowserImageBrowseRoute' => 'editor_filemanager',
784
                        'filebrowserImageBrowseRouteParameters' => array(
785
                            'tool' => $tool,
786
                            'type' => $type,
787
                            'cidReq' => $this->getCourse()->getCode(),
788
                            'id' => $resourceNodeParentId
789
                        )
790
                    ],
791
                ]
792
            );
793
        }
794
795
        $course = $this->getCourse();
796
        $session = $this->getSession();
797
        $parentNode = $course->getResourceNode();
798
        if (!empty($resourceNodeParentId)) {
799
            $parentNode = $repository->getResourceNodeRepository()->find($resourceNodeParentId);
800
        }
801
802
        $form->handleRequest($request);
803
        if ($form->isSubmitted() && $form->isValid()) {
804
            $em = $this->getDoctrine()->getManager();
805
806
            /** @var CDocument $newResource */
807
            $newResource = $form->getData();
808
809
            $newResource
810
                ->setCourse($course)
811
                ->setSession($session)
812
                ->setFiletype($fileType)
813
                //->setTitle($title) // already added in $form->getData()
814
                ->setReadonly(false)
815
            ;
816
817
            if ($fileType === 'file') {
818
                $content = $form->get('content')->getViewData();
819
                $fileName = $newResource->getTitle().'.html';
820
                $handle = tmpfile();
821
                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

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

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