Passed
Push — master ( d2acd0...7e642c )
by Julito
09:19
created

ResourceController   C

Complexity

Total Complexity 57

Size/Duplication

Total Lines 871
Duplicated Lines 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
eloc 373
c 2
b 0
f 0
dl 0
loc 871
rs 5.04
wmc 57

18 Methods

Rating   Name   Duplication   Size   Complexity  
A newAction() 0 3 1
A indexAction() 0 21 1
A newFolderAction() 0 3 1
A previewAction() 0 28 1
B editAction() 0 73 8
A infoAction() 0 35 1
A deleteAction() 0 31 3
A viewResourceAction() 0 33 2
A uploadAction() 0 19 1
A deleteMassAction() 0 31 3
A viewAction() 0 12 2
B downloadAction() 0 78 5
A linkAction() 0 19 3
A diskSpaceAction() 0 68 3
B processFile() 0 68 9
B createResource() 0 153 8
A changeVisibilityAction() 0 36 4
A listAction() 0 2 1

How to fix   Complexity   

Complex Class

Complex classes like ResourceController often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use ResourceController, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
/* For licensing terms, see /license.txt */
4
5
namespace Chamilo\CoreBundle\Controller;
6
7
use Chamilo\CoreBundle\Entity\AbstractResource;
8
use Chamilo\CoreBundle\Entity\Course;
9
use Chamilo\CoreBundle\Entity\ResourceLink;
10
use Chamilo\CoreBundle\Entity\ResourceNode;
11
use Chamilo\CoreBundle\Form\Type\ResourceCommentType;
12
use Chamilo\CoreBundle\Repository\Node\IllustrationRepository;
13
use Chamilo\CoreBundle\Repository\ResourceWithLinkInterface;
14
use Chamilo\CoreBundle\Security\Authorization\Voter\ResourceNodeVoter;
15
use Chamilo\CoreBundle\Traits\ControllerTrait;
16
use Chamilo\CoreBundle\Traits\CourseControllerTrait;
17
use Chamilo\CoreBundle\Traits\ResourceControllerTrait;
18
use Chamilo\CourseBundle\Controller\CourseControllerInterface;
19
use Doctrine\Common\Collections\ArrayCollection;
20
use Doctrine\Common\Collections\Criteria;
21
use FOS\CKEditorBundle\Form\Type\CKEditorType;
22
use Symfony\Component\Filesystem\Exception\FileNotFoundException;
23
use Symfony\Component\HttpFoundation\File\UploadedFile;
24
use Symfony\Component\HttpFoundation\JsonResponse;
25
use Symfony\Component\HttpFoundation\RedirectResponse;
26
use Symfony\Component\HttpFoundation\Request;
27
use Symfony\Component\HttpFoundation\Response;
28
use Symfony\Component\HttpFoundation\ResponseHeaderBag;
29
use Symfony\Component\HttpFoundation\StreamedResponse;
30
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
31
use Symfony\Component\Routing\Annotation\Route;
32
use Symfony\Component\Routing\RouterInterface;
33
use ZipStream\Option\Archive;
34
use ZipStream\ZipStream;
35
36
/**
37
 * Class ResourceController.
38
 *
39
 * @Route("/r")
40
 *
41
 * @author Julio Montoya <[email protected]>.
42
 */
43
class ResourceController extends AbstractResourceController implements CourseControllerInterface
44
{
45
    use CourseControllerTrait;
46
    use ResourceControllerTrait;
47
    use ControllerTrait;
48
49
    private string $fileContentName = 'file_content';
50
51
    /**
52
     * @deprecated in favor of vue CRUD methods
53
     *
54
     * @Route("/{tool}/{type}", name="chamilo_core_resource_index")
55
     *
56
     * Example: /document/files (See the 'tool' and the 'resource_type' DB tables.)
57
     * For the tool value check the Tool entity.
58
     * For the type value check the ResourceType entity.
59
     */
60
    public function indexAction(Request $request): Response
61
    {
62
        $tool = $request->get('tool');
63
        $type = $request->get('type');
64
65
        $parentResourceNode = $this->getParentResourceNode($request);
66
        $repository = $this->getRepositoryFromRequest($request);
67
        $settings = $repository->getResourceSettings();
68
69
        // The base resource node is the course.
70
        $id = $parentResourceNode->getId();
71
72
        //return $grid->getGridResponse(
73
        return $this->render(
74
            $repository->getTemplates()->getFromAction(__FUNCTION__),
75
            [
76
                'tool' => $tool,
77
                'type' => $type,
78
                'id' => $id,
79
                'parent_resource_node' => $parentResourceNode,
80
                'resource_settings' => $settings,
81
            ]
82
        );
83
    }
84
85
    /**
86
     * @deprecated in favor of vue CRUD methods
87
     * @Route("/{tool}/{type}/{id}/list", name="chamilo_core_resource_list")
88
     *
89
     * If node has children show it
90
     */
91
    public function listAction(Request $request)
92
    {
93
        /*$tool = $request->get('tool');
94
        $type = $request->get('type');
95
        $resourceNodeId = $request->get('id');
96
97
        $repository = $this->getRepositoryFromRequest($request);
98
        $settings = $repository->getResourceSettings();*/
99
100
        /*$grid = $this->getGrid($request, $repository, $grid, $resourceNodeId, 'chamilo_core_resource_list');
101
        $parentResourceNode = $this->getParentResourceNode($request);
102
        $this->setBreadCrumb($request, $parentResourceNode);*/
103
104
        //return $grid->getGridResponse(
105
        /*return $this->render(
106
            $repository->getTemplates()->getFromAction(__FUNCTION__),
107
            [
108
                'parent_id' => $resourceNodeId,
109
                'tool' => $tool,
110
                'type' => $type,
111
                'id' => $resourceNodeId,
112
                'parent_resource_node' => $parentResourceNode,
113
                'resource_settings' => $settings,
114
            ]
115
        );*/
116
    }
117
118
    /**
119
     * @deprecated in favor of vue CRUD methods
120
     *
121
     * @Route("/{tool}/{type}/{id}/new_folder", methods={"GET", "POST"}, name="chamilo_core_resource_new_folder")
122
     */
123
    public function newFolderAction(Request $request): Response
124
    {
125
        return $this->createResource($request, 'folder');
126
    }
127
128
    /**
129
     * @deprecated in favor of vue CRUD methods
130
     *
131
     * @Route("/{tool}/{type}/{id}/new", methods={"GET", "POST"}, name="chamilo_core_resource_new")
132
     */
133
    public function newAction(Request $request): Response
134
    {
135
        return $this->createResource($request, 'file');
136
    }
137
138
    /**
139
     * @Route("/{tool}/{type}/{id}/disk_space", methods={"GET", "POST"}, name="chamilo_core_resource_disk_space")
140
     */
141
    public function diskSpaceAction(Request $request): Response
142
    {
143
        $nodeId = $request->get('id');
144
        $repository = $this->getRepositoryFromRequest($request);
145
146
        /** @var ResourceNode $resourceNode */
147
        $resourceNode = $repository->getResourceNodeRepository()->find($nodeId);
148
149
        $this->denyAccessUnlessGranted(
150
            ResourceNodeVoter::VIEW,
151
            $resourceNode,
152
            $this->trans('Unauthorised access to resource')
153
        );
154
155
        $this->setBreadCrumb($request, $resourceNode);
156
157
        $course = $this->getCourse();
158
        $totalSize = 0;
159
        if ($course) {
0 ignored issues
show
introduced by
$course is of type Chamilo\CoreBundle\Entity\Course, thus it always evaluated to true.
Loading history...
160
            $totalSize = $course->getDiskQuota();
161
        }
162
163
        $size = $repository->getResourceNodeRepository()->getSize(
164
            $resourceNode,
165
            $repository->getResourceType(),
166
            $course
167
        );
168
169
        $labels[] = $course->getTitle();
0 ignored issues
show
Comprehensibility Best Practice introduced by
$labels was never initialized. Although not strictly required by PHP, it is generally a good practice to add $labels = array(); before regardless.
Loading history...
170
        $data[] = $size;
0 ignored issues
show
Comprehensibility Best Practice introduced by
$data was never initialized. Although not strictly required by PHP, it is generally a good practice to add $data = array(); before regardless.
Loading history...
171
        $sessions = $course->getSessions();
172
173
        foreach ($sessions as $sessionRelCourse) {
174
            $session = $sessionRelCourse->getSession();
175
176
            $labels[] = $course->getTitle().' - '.$session->getName();
177
            $size = $repository->getResourceNodeRepository()->getSize(
178
                $resourceNode,
179
                $repository->getResourceType(),
180
                $course,
181
                $session
182
            );
183
            $data[] = $size;
184
        }
185
186
        /*$groups = $course->getGroups();
187
        foreach ($groups as $group) {
188
            $labels[] = $course->getTitle().' - '.$group->getName();
189
            $size = $repository->getResourceNodeRepository()->getSize(
190
                $resourceNode,
191
                $repository->getResourceType(),
192
                $course,
193
                null,
194
                $group
195
            );
196
            $data[] = $size;
197
        }*/
198
199
        $used = array_sum($data);
200
        $labels[] = $this->trans('Free');
201
        $data[] = $totalSize - $used;
202
203
        return $this->render(
204
            $repository->getTemplates()->getFromAction(__FUNCTION__),
205
            [
206
                'resourceNode' => $resourceNode,
207
                'labels' => $labels,
208
                'data' => $data,
209
            ]
210
        );
211
    }
212
213
    /**
214
     * @deprecated in favor of vue CRUD methods
215
     *
216
     * @Route("/{tool}/{type}/{id}/edit", methods={"GET", "POST"})
217
     */
218
    public function editAction(Request $request, IllustrationRepository $illustrationRepo): Response
219
    {
220
        $resourceNodeId = $request->get('id');
221
222
        $repository = $this->getRepositoryFromRequest($request);
223
        $resource = $repository->getResourceFromResourceNode($resourceNodeId);
224
        $this->denyAccessUnlessValidResource($resource);
225
        $settings = $repository->getResourceSettings();
226
        $resourceNode = $resource->getResourceNode();
227
228
        $this->denyAccessUnlessGranted(
229
            ResourceNodeVoter::EDIT,
230
            $resourceNode,
231
            $this->trans('Unauthorised access to resource')
232
        );
233
234
        $this->setBreadCrumb($request, $resourceNode);
235
        $resourceNodeParentId = $resourceNode->getId();
236
237
        $routeParams = $this->getResourceParams($request);
238
        $routeParams['id'] = $resourceNodeParentId;
239
240
        $form = $repository->getForm($this->container->get('form.factory'), $resource);
241
242
        if ($resourceNode->hasEditableTextContent() && $settings->isAllowToSaveEditorToResourceFile()) {
243
            $form->add(
244
                $this->fileContentName,
245
                CKEditorType::class,
246
                [
247
                    'mapped' => false,
248
                    'config' => [
249
                        'filebrowserImageBrowseRoute' => 'resources_filemanager',
250
                        'filebrowserImageBrowseRouteParameters' => $routeParams,
251
                    ],
252
                ]
253
            );
254
            $content = $repository->getResourceNodeFileContent($resourceNode);
255
            $form->get($this->fileContentName)->setData($content);
256
        }
257
258
        $form->handleRequest($request);
259
260
        if ($form->isSubmitted() && $form->isValid()) {
261
            /** @var AbstractResource $newResource */
262
            $newResource = $form->getData();
263
264
            if ($form->has($this->fileContentName)) {
265
                $data = $form->get($this->fileContentName)->getData();
266
                $repository->updateResourceFileContent($newResource, $data);
267
            }
268
269
            $repository->updateNodeForResource($newResource);
270
271
            if ($form->has('illustration')) {
272
                $illustration = $form->get('illustration')->getData();
273
                if ($illustration) {
274
                    $file = $illustrationRepo->addIllustration($newResource, $this->getUser(), $illustration);
275
                    $illustrationRepo->update($file);
276
                }
277
            }
278
279
            $this->addFlash('success', $this->trans('Updated'));
280
            $resourceNodeParentId = $newResource->getResourceNode()->getParent()->getId();
281
            $routeParams['id'] = $resourceNodeParentId;
282
283
            return $this->redirectToRoute('chamilo_core_resource_list', $routeParams);
284
        }
285
286
        return $this->render(
287
            $repository->getTemplates()->getFromAction(__FUNCTION__),
288
            [
289
                'form' => $form->createView(),
290
                'parent' => $resourceNodeParentId,
291
            ]
292
        );
293
    }
294
295
    /**
296
     * Shows a resource information.
297
     *
298
     * @Route("/{tool}/{type}/{id}/info", methods={"GET", "POST"}, name="chamilo_core_resource_info")
299
     */
300
    public function infoAction(Request $request): Response
301
    {
302
        $nodeId = $request->get('id');
303
        $repository = $this->getRepositoryFromRequest($request);
304
305
        /** @var AbstractResource $resource */
306
        $resource = $repository->getResourceFromResourceNode($nodeId);
307
        $this->denyAccessUnlessValidResource($resource);
308
        $resourceNode = $resource->getResourceNode();
309
310
        $this->denyAccessUnlessGranted(
311
            ResourceNodeVoter::VIEW,
312
            $resourceNode,
313
            $this->trans(sprintf('Unauthorised access to resource #%s', $nodeId))
314
        );
315
316
        $this->setBreadCrumb($request, $resourceNode);
317
318
        $tool = $request->get('tool');
319
        $type = $request->get('type');
320
321
        $form = $this->createForm(ResourceCommentType::class, null);
322
323
        $params = [
324
            'resource' => $resource,
325
            'course' => $this->getCourse(),
326
         //   'illustration' => $illustration,
327
            'tool' => $tool,
328
            'type' => $type,
329
            'comment_form' => $form->createView(),
330
        ];
331
332
        return $this->render(
333
            $repository->getTemplates()->getFromAction(__FUNCTION__, $request->isXmlHttpRequest()),
334
            $params
335
        );
336
    }
337
338
    /**
339
     * Preview a file. Mostly used when using a modal.
340
     *
341
     * @Route("/{tool}/{type}/{id}/preview", methods={"GET"}, name="chamilo_core_resource_preview")
342
     */
343
    public function previewAction(Request $request): Response
344
    {
345
        $nodeId = $request->get('id');
346
        $repository = $this->getRepositoryFromRequest($request);
347
348
        /** @var AbstractResource $resource */
349
        $resource = $repository->getResourceFromResourceNode($nodeId);
350
        $this->denyAccessUnlessValidResource($resource);
351
352
        $resourceNode = $resource->getResourceNode();
353
        $this->denyAccessUnlessGranted(
354
            ResourceNodeVoter::VIEW,
355
            $resourceNode,
356
            $this->trans('Unauthorised access to resource')
357
        );
358
359
        $this->setBreadCrumb($request, $resourceNode);
360
361
        $tool = $request->get('tool');
362
        $type = $request->get('type');
363
364
        $params = [
365
            'resource' => $resource,
366
            'tool' => $tool,
367
            'type' => $type,
368
        ];
369
370
        return $this->render($repository->getTemplates()->getFromAction(__FUNCTION__), $params);
371
    }
372
373
    /**
374
     * @Route("/{tool}/{type}/{id}/change_visibility", name="chamilo_core_resource_change_visibility")
375
     */
376
    public function changeVisibilityAction(Request $request): Response
377
    {
378
        $id = $request->get('id');
379
380
        $repository = $this->getRepositoryFromRequest($request);
381
382
        /** @var AbstractResource $resource */
383
        $resource = $repository->getResourceFromResourceNode($id);
384
        $this->denyAccessUnlessValidResource($resource);
385
386
        $resourceNode = $resource->getResourceNode();
387
388
        $this->denyAccessUnlessGranted(
389
            ResourceNodeVoter::EDIT,
390
            $resourceNode,
391
            $this->trans('Unauthorised access to resource')
392
        );
393
394
        if ($this->hasCourse()) {
395
            $link = $resource->getFirstResourceLinkFromCourseSession($this->getCourse(), $this->getSession());
396
        } else {
397
            $link = $resource->getFirstResourceLink();
398
        }
399
400
        $icon = 'fa-eye';
401
        // Use repository to change settings easily.
402
        if ($link && ResourceLink::VISIBILITY_PUBLISHED === $link->getVisibility()) {
403
            $repository->setVisibilityDraft($resource);
404
            $icon = 'fa-eye-slash';
405
        } else {
406
            $repository->setVisibilityPublished($resource);
407
        }
408
409
        $result = ['icon' => $icon];
410
411
        return new JsonResponse($result);
412
    }
413
414
    /**
415
     * @Route("/{tool}/{type}/{id}/delete", name="chamilo_core_resource_delete")
416
     */
417
    public function deleteAction(Request $request): Response
418
    {
419
        $em = $this->getDoctrine()->getManager();
420
421
        $id = $request->get('id');
422
        $resourceNode = $this->getDoctrine()->getRepository(ResourceNode::class)->find($id);
423
        $parentId = $resourceNode->getParent()->getId();
424
425
        $this->denyAccessUnlessGranted(
426
            ResourceNodeVoter::DELETE,
427
            $resourceNode,
428
            $this->trans('Unauthorised access to resource')
429
        );
430
431
        $children = $resourceNode->getChildren();
432
433
        if (!empty($children)) {
434
            /** @var ResourceNode $child */
435
            foreach ($children as $child) {
436
                $em->remove($child);
437
            }
438
        }
439
440
        $em->remove($resourceNode);
441
        $this->addFlash('success', $this->trans('Deleted').': '.$resourceNode->getSlug());
442
        $em->flush();
443
444
        $routeParams = $this->getResourceParams($request);
445
        $routeParams['id'] = $parentId;
446
447
        return $this->redirectToRoute('chamilo_core_resource_list', $routeParams);
448
    }
449
450
    /**
451
     * @Route("/{tool}/{type}/{id}/delete_mass", methods={"DELETE"}, name="chamilo_core_resource_delete_mass")
452
     */
453
    public function deleteMassAction($primaryKeys, $allPrimaryKeys, Request $request): Response
454
    {
455
        $em = $this->getDoctrine()->getManager();
456
        $repo = $this->getRepositoryFromRequest($request);
457
458
        $parentId = 0;
459
        foreach ($primaryKeys as $id) {
460
            $resource = $repo->find($id);
461
            $resourceNode = $resource->getResourceNode();
462
463
            if (null === $resourceNode) {
464
                continue;
465
            }
466
467
            $this->denyAccessUnlessGranted(
468
                ResourceNodeVoter::DELETE,
469
                $resourceNode,
470
                $this->trans('Unauthorised access to resource')
471
            );
472
473
            $parentId = $resourceNode->getParent()->getId();
474
            $em->remove($resource);
475
        }
476
477
        $this->addFlash('success', $this->trans('Deleted'));
478
        $em->flush();
479
480
        $routeParams = $this->getResourceParams($request);
481
        $routeParams['id'] = $parentId;
482
483
        return $this->redirectToRoute('chamilo_core_resource_list', $routeParams);
484
    }
485
486
    /**
487
     * Shows the associated resource file.
488
     *
489
     * @Route("/{tool}/{type}/{id}/view_resource", methods={"GET"}, name="chamilo_core_resource_view_resource")
490
     */
491
    public function viewResourceAction(Request $request, RouterInterface $router): Response
492
    {
493
        $id = $request->get('id');
494
495
        /** @var ResourceNode $resourceNode */
496
        $resourceNode = $this->getResourceNodeRepository()->find($id);
497
498
        if (null === $resourceNode) {
499
            throw new FileNotFoundException('Resource not found');
500
        }
501
502
        $this->denyAccessUnlessGranted(
503
            ResourceNodeVoter::VIEW,
504
            $resourceNode,
505
            $this->trans('Unauthorised access to resource')
506
        );
507
508
        $repository = $this->getRepositoryFromRequest($request);
509
510
        /** @var AbstractResource $resource */
511
        $resource = $repository->getResourceFromResourceNode($id);
512
513
        $tool = $request->get('tool');
514
        $type = $request->get('type');
515
        $this->setBreadCrumb($request, $resourceNode);
516
517
        $params = [
518
            'resource' => $resource,
519
            'tool' => $tool,
520
            'type' => $type,
521
        ];
522
523
        return $this->render($repository->getTemplates()->getFromAction(__FUNCTION__), $params);
524
    }
525
526
    /**
527
     * View file of a resource node.
528
     *
529
     * @Route("/{tool}/{type}/{id}/view", methods={"GET"}, name="chamilo_core_resource_view")
530
     */
531
    public function viewAction(Request $request): Response
532
    {
533
        $id = $request->get('id');
534
        $filter = $request->get('filter'); // See filters definitions in /config/services.yml.
535
        /** @var ResourceNode $resourceNode */
536
        $resourceNode = $this->getResourceNodeRepository()->find($id);
537
538
        if (null === $resourceNode) {
539
            throw new FileNotFoundException('Resource not found');
540
        }
541
542
        return $this->processFile($request, $resourceNode, 'show', $filter);
543
    }
544
545
    /**
546
     * Redirect resource to link.
547
     *
548
     * @Route("/{tool}/{type}/{id}/link", methods={"GET"}, name="chamilo_core_resource_link")
549
     */
550
    public function linkAction(Request $request, RouterInterface $router): Response
551
    {
552
        $id = $request->get('id');
553
        /** @var ResourceNode $resourceNode */
554
        $resourceNode = $this->getResourceNodeRepository()->find($id);
555
556
        if (null === $resourceNode) {
557
            throw new FileNotFoundException('Resource not found');
558
        }
559
560
        $repo = $this->getRepositoryFromRequest($request);
561
        if ($repo instanceof ResourceWithLinkInterface) {
562
            $resource = $repo->getResourceFromResourceNode($resourceNode->getId());
563
            $url = $repo->getLink($resource, $router, $this->getCourseUrlQueryToArray());
564
565
            return $this->redirect($url);
566
        }
567
568
        return $this->abort('No redirect');
569
    }
570
571
    /**
572
     * Download file of a resource node.
573
     *
574
     * @Route("/{tool}/{type}/{id}/download", methods={"GET"}, name="chamilo_core_resource_download")
575
     */
576
    public function downloadAction(Request $request)
577
    {
578
        $id = (int) $request->get('id');
579
580
        /** @var ResourceNode $resourceNode */
581
        $resourceNode = $this->getResourceNodeRepository()->find($id);
582
583
        if (null === $resourceNode) {
584
            throw new FileNotFoundException('Resource not found');
585
        }
586
587
        $repo = $this->getRepositoryFromRequest($request);
588
589
        $this->denyAccessUnlessGranted(
590
            ResourceNodeVoter::VIEW,
591
            $resourceNode,
592
            $this->trans('Unauthorised access to resource')
593
        );
594
595
        // If resource node has a file just download it. Don't download the children.
596
        if ($resourceNode->hasResourceFile()) {
597
            // Redirect to download single file.
598
            return $this->processFile($request, $resourceNode, 'download');
599
        }
600
601
        $zipName = $resourceNode->getSlug().'.zip';
602
        //$rootNodePath = $resourceNode->getPathForDisplay();
603
        $resourceNodeRepo = $repo->getResourceNodeRepository();
604
        $type = $repo->getResourceType();
605
606
        $criteria = Criteria::create()
607
            ->where(Criteria::expr()->neq('resourceFile', null)) // must have a file
608
             ->andWhere(Criteria::expr()->eq('resourceType', $type)) // only download same type
609
        ;
610
611
        $qb = $resourceNodeRepo->getChildrenQueryBuilder($resourceNode);
612
        $qb->addCriteria($criteria);
613
        /** @var ArrayCollection|ResourceNode[] $children */
614
        $children = $qb->getQuery()->getResult();
615
        $count = count($children);
616
        if (0 === $count) {
617
            $params = $this->getResourceParams($request);
618
            $params['id'] = $id;
619
620
            $this->addFlash('warning', $this->trans('No files'));
621
622
            return $this->redirectToRoute('chamilo_core_resource_list', $params);
623
        }
624
625
        $response = new StreamedResponse(
626
            function () use ($zipName, $children, $repo) {
627
                // Define suitable options for ZipStream Archive.
628
                $options = new Archive();
629
                $options->setContentType('application/octet-stream');
630
                //initialise zipstream with output zip filename and options.
631
                $zip = new ZipStream($zipName, $options);
632
633
                /** @var ResourceNode $node */
634
                foreach ($children as $node) {
635
                    $stream = $repo->getResourceNodeFileStream($node);
636
                    $fileName = $node->getResourceFile()->getOriginalName();
637
                    //$fileToDisplay = basename($node->getPathForDisplay());
638
                    //$fileToDisplay = str_replace($rootNodePath, '', $node->getPathForDisplay());
639
                    //error_log($fileToDisplay);
640
                    $zip->addFileFromStream($fileName, $stream);
641
                }
642
                $zip->finish();
643
            }
644
        );
645
646
        $disposition = $response->headers->makeDisposition(
647
            ResponseHeaderBag::DISPOSITION_ATTACHMENT,
648
            $zipName //Transliterator::transliterate($zipName)
649
        );
650
        $response->headers->set('Content-Disposition', $disposition);
651
        $response->headers->set('Content-Type', 'application/octet-stream');
652
653
        return $response;
654
    }
655
656
    /**
657
     * Upload form.
658
     *
659
     * @Route("/{tool}/{type}/{id}/upload", name="chamilo_core_resource_upload", methods={"GET", "POST"},
660
     *                                      options={"expose"=true})
661
     */
662
    public function uploadAction(Request $request, $tool, $type, $id): Response
663
    {
664
        $repository = $this->getRepositoryFromRequest($request);
665
        $resourceNode = $repository->getResourceNodeRepository()->find($id);
666
667
        $this->denyAccessUnlessGranted(
668
            ResourceNodeVoter::EDIT,
669
            $resourceNode,
670
            $this->trans('Unauthorised access to resource')
671
        );
672
673
        $this->setBreadCrumb($request, $resourceNode);
674
675
        $routeParams = $this->getResourceParams($request);
676
        $routeParams['tool'] = $tool;
677
        $routeParams['type'] = $type;
678
        $routeParams['id'] = $id;
679
680
        return $this->render($repository->getTemplates()->getFromAction(__FUNCTION__), $routeParams);
681
    }
682
683
    /**
684
     * @return mixed|StreamedResponse
685
     */
686
    private function processFile(Request $request, ResourceNode $resourceNode, $mode = 'show', $filter = '')
687
    {
688
        $this->denyAccessUnlessGranted(
689
            ResourceNodeVoter::VIEW,
690
            $resourceNode,
691
            $this->trans('Unauthorised view access to resource')
692
        );
693
694
        $resourceFile = $resourceNode->getResourceFile();
695
696
        if (!$resourceFile) {
697
            throw new NotFoundHttpException($this->trans('File not found for resource'));
698
        }
699
700
        $fileName = $resourceNode->getResourceFile()->getOriginalName();
701
        $mimeType = $resourceFile->getMimeType();
702
        $resourceNodeRepo = $this->getResourceNodeRepository();
703
704
        switch ($mode) {
705
            case 'download':
706
                $forceDownload = true;
707
708
                break;
709
            case 'show':
710
            default:
711
                $forceDownload = false;
712
                // If it's an image then send it to Glide.
713
                if (false !== strpos($mimeType, 'image')) {
714
                    $glide = $this->getGlide();
715
                    $server = $glide->getServer();
716
                    $params = $request->query->all();
717
718
                    // The filter overwrites the params from GET.
719
                    if (!empty($filter)) {
720
                        $params = $glide->getFilters()[$filter] ?? [];
721
                    }
722
723
                    // The image was cropped manually by the user, so we force to render this version,
724
                    // no matter other crop parameters.
725
                    $crop = $resourceFile->getCrop();
726
                    if (!empty($crop)) {
727
                        $params['crop'] = $crop;
728
                    }
729
730
                    $fileName = $resourceNodeRepo->getFilename($resourceFile);
731
732
                    return $server->getImageResponse($fileName, $params);
733
                }
734
735
                break;
736
        }
737
738
        $stream = $resourceNodeRepo->getResourceNodeFileStream($resourceNode);
739
740
        $response = new StreamedResponse(
741
            function () use ($stream): void {
742
                stream_copy_to_stream($stream, fopen('php://output', 'wb'));
743
            }
744
        );
745
        $disposition = $response->headers->makeDisposition(
746
            $forceDownload ? ResponseHeaderBag::DISPOSITION_ATTACHMENT : ResponseHeaderBag::DISPOSITION_INLINE,
747
            $fileName
748
        //Transliterator::transliterate($fileName)
749
        );
750
        $response->headers->set('Content-Disposition', $disposition);
751
        $response->headers->set('Content-Type', $mimeType ?: 'application/octet-stream');
752
753
        return $response;
754
    }
755
756
    /**
757
     * @param string $fileType
758
     *
759
     * @return RedirectResponse|Response
760
     */
761
    private function createResource(Request $request, $fileType = 'file')
762
    {
763
        $resourceNodeParentId = $request->get('id');
764
        $repository = $this->getRepositoryFromRequest($request);
765
766
        // Default parent node is course.
767
        $parentNode = $this->getParentResourceNode($request);
768
769
        $this->setBreadCrumb($request, $parentNode);
770
771
        $this->denyAccessUnlessGranted(
772
            ResourceNodeVoter::CREATE,
773
            $parentNode,
774
            $this->trans('Unauthorised access to resource')
775
        );
776
777
        $form = $repository->getForm($this->container->get('form.factory'), null);
778
        $settings = $repository->getResourceSettings();
779
780
        if ('file' === $fileType && $settings->isAllowToSaveEditorToResourceFile()) {
781
            $resourceParams = $this->getResourceParams($request);
782
            $form->add(
783
                $this->fileContentName,
784
                CKEditorType::class,
785
                [
786
                    'mapped' => false,
787
                    'config' => [
788
                        'filebrowserImageBrowseRoute' => 'resources_filemanager',
789
                        'filebrowserImageBrowseRouteParameters' => $resourceParams,
790
                        'fullPage' => true,
791
                    ],
792
                ]
793
            );
794
        }
795
796
        $form->handleRequest($request);
797
        if ($form->isSubmitted() && $form->isValid()) {
798
            $em = $this->getDoctrine()->getManager();
799
            $course = $this->getCourse()->getId();
800
            $course = $this->getDoctrine()->getRepository(Course::class)->find($course);
801
            $session = $this->getSession();
802
803
            // @var AbstractResource $newResource
804
            /*$newResource = $repository->setResourceProperties($form, $course, $session, $fileType);
805
806
            $file = null;
807
            if ('file' === $fileType && $settings->isAllowToSaveEditorToResourceFile()) {
808
                $content = $form->get($this->fileContentName)->getViewData();
809
                $newResource->setTitle($newResource->getTitle().'.html');
810
                $fileName = $newResource->getTitle();
811
812
                $handle = tmpfile();
813
                fwrite($handle, $content);
814
                $meta = stream_get_meta_data($handle);
815
                $file = new UploadedFile($meta['uri'], $fileName, 'text/html', null, true);
816
            }
817
            $newResource->addCourseLink(
818
                $course,
819
                $session
820
            );
821
            $em->persist($newResource);
822
            $em->flush();
823
824
            $repository->addFile($newResource, $file);
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
            $params = $this->getResourceParams($request);
884
            $params['id'] = $resourceNodeParentId;
885
886
            return $this->redirectToRoute(
887
                'chamilo_core_resource_list',
888
                $params
889
            );
890
        }
891
892
        $template = null;
893
        switch ($fileType) {
894
            case 'folder':
895
                $template = $repository->getTemplates()->getFromAction('newFolderAction');
896
897
                break;
898
            case 'file':
899
                $template = $repository->getTemplates()->getFromAction('newAction');
900
901
                break;
902
        }
903
904
        if ($template) {
905
            $routeParams = $this->getResourceParams($request);
906
            $routeParams['form'] = $form->createView();
907
            $routeParams['parent'] = $resourceNodeParentId;
908
            $routeParams['file_type'] = $fileType;
909
910
            return $this->render($template, $routeParams);
911
        }
912
913
        throw $this->createAccessDeniedException();
914
    }
915
}
916