Passed
Push — master ( 8276d9...eeb046 )
by Julito
11:16
created

ResourceController::newFolderAction()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 1
dl 0
loc 5
rs 10
c 0
b 0
f 0
1
<?php
2
3
/* For licensing terms, see /license.txt */
4
5
namespace Chamilo\CoreBundle\Controller;
6
7
use APY\DataGridBundle\Grid\Action\MassAction;
8
use APY\DataGridBundle\Grid\Action\RowAction;
9
use APY\DataGridBundle\Grid\Column\Column;
10
use APY\DataGridBundle\Grid\Export\CSVExport;
11
use APY\DataGridBundle\Grid\Export\ExcelExport;
12
use APY\DataGridBundle\Grid\Grid;
13
use APY\DataGridBundle\Grid\Row;
14
use APY\DataGridBundle\Grid\Source\Entity;
15
use Chamilo\CoreBundle\Entity\Resource\AbstractResource;
16
use Chamilo\CoreBundle\Entity\Resource\ResourceComment;
17
use Chamilo\CoreBundle\Entity\Resource\ResourceInterface;
18
use Chamilo\CoreBundle\Entity\Resource\ResourceLink;
19
use Chamilo\CoreBundle\Entity\Resource\ResourceNode;
20
use Chamilo\CoreBundle\Form\Type\ResourceCommentType;
21
use Chamilo\CoreBundle\Repository\IllustrationRepository;
22
use Chamilo\CoreBundle\Repository\ResourceRepository;
23
use Chamilo\CoreBundle\Repository\ResourceWithLinkInterface;
24
use Chamilo\CoreBundle\Security\Authorization\Voter\ResourceNodeVoter;
25
use Chamilo\CoreBundle\Traits\ControllerTrait;
26
use Chamilo\CoreBundle\Traits\CourseControllerTrait;
27
use Chamilo\CoreBundle\Traits\ResourceControllerTrait;
28
use Chamilo\CourseBundle\Controller\CourseControllerInterface;
29
use Doctrine\Common\Collections\ArrayCollection;
30
use Doctrine\Common\Collections\Criteria;
31
use Doctrine\ORM\QueryBuilder;
32
use FOS\CKEditorBundle\Form\Type\CKEditorType;
33
use Symfony\Component\Filesystem\Exception\FileNotFoundException;
34
use Symfony\Component\HttpFoundation\File\UploadedFile;
35
use Symfony\Component\HttpFoundation\JsonResponse;
36
use Symfony\Component\HttpFoundation\RedirectResponse;
37
use Symfony\Component\HttpFoundation\Request;
38
use Symfony\Component\HttpFoundation\Response;
39
use Symfony\Component\HttpFoundation\ResponseHeaderBag;
40
use Symfony\Component\HttpFoundation\StreamedResponse;
41
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
42
use Symfony\Component\Routing\Annotation\Route;
43
use Symfony\Component\Routing\Router;
44
use Symfony\Component\Routing\RouterInterface;
45
use ZipStream\Option\Archive;
46
use ZipStream\ZipStream;
47
48
/**
49
 * Class ResourceController.
50
 *
51
 * @Route("/resources")
52
 *
53
 * @author Julio Montoya <[email protected]>.
54
 */
55
class ResourceController extends AbstractResourceController implements CourseControllerInterface
56
{
57
    use CourseControllerTrait;
58
    use ResourceControllerTrait;
59
    use ControllerTrait;
60
61
    private $fileContentName = 'file_content';
62
63
    /**
64
     * @Route("/{tool}/{type}", name="chamilo_core_resource_index")
65
     *
66
     * Example: /document/files (See the 'tool' and the 'resource_type' DB tables.)
67
     * For the tool value check the Tool entity.
68
     * For the type value check the ResourceType entity.
69
     */
70
    public function indexAction(Request $request, Grid $grid): Response
71
    {
72
        $tool = $request->get('tool');
73
        $type = $request->get('type');
74
75
        $parentResourceNode = $this->getParentResourceNode($request);
76
        $repository = $this->getRepositoryFromRequest($request);
77
        $settings = $repository->getResourceSettings();
78
79
        $grid = $this->getGrid($request, $repository, $grid, $parentResourceNode->getId());
80
81
        $breadcrumb = $this->getBreadCrumb();
82
        $breadcrumb->addChild(
83
            $this->trans($tool),
84
            [
85
                'uri' => '#',
86
            ]
87
        );
88
89
        // The base resource node is the course.
90
        $id = $parentResourceNode->getId();
91
92
        return $grid->getGridResponse(
93
            $repository->getTemplates()->getFromAction(__FUNCTION__),
94
            [
95
                'tool' => $tool,
96
                'type' => $type,
97
                'id' => $id,
98
                'parent_resource_node' => $parentResourceNode,
99
                'resource_settings' => $settings,
100
            ]
101
        );
102
    }
103
104
    public function getGrid(Request $request, ResourceRepository $repository, Grid $grid, int $resourceNodeId): Grid
105
    {
106
        $class = $repository->getRepository()->getClassName();
107
108
        // The group 'resource' is set in the @GRID\Source annotation in the entity.
109
        $source = new Entity($class, 'resource');
110
        /** @var ResourceNode $parentNode */
111
        $parentNode = $repository->getResourceNodeRepository()->find($resourceNodeId);
112
113
        $this->denyAccessUnlessGranted(
114
            ResourceNodeVoter::VIEW,
115
            $parentNode,
116
            $this->trans('Unauthorised access to resource')
117
        );
118
119
        $settings = $repository->getResourceSettings();
120
121
        $course = $this->getCourse();
122
        $session = $this->getSession();
123
        /** @var QueryBuilder $qb */
124
        $qb = $repository->getResources($this->getUser(), $parentNode, $course, $session, null);
125
126
        // 3. Set QueryBuilder to the source.
127
        $source->initQueryBuilder($qb);
128
        $grid->setSource($source);
129
130
        $resourceParams = $this->getResourceParams($request);
131
132
        if (0 === $resourceParams['id']) {
133
            $resourceParams['id'] = $resourceNodeId;
134
        }
135
136
        $grid->setRouteUrl($this->generateUrl('chamilo_core_resource_list', $resourceParams));
137
138
        //$grid->hideFilters();
139
        //$grid->setLimits(20);
140
        //$grid->isReadyForRedirect();
141
        //$grid->setMaxResults(1);
142
        //$grid->setLimits(2);
143
        //$grid->setColumns($columns);
144
        $routeParams = $resourceParams;
145
        $routeParams['id'] = null;
146
147
        /** @var Column $titleColumn */
148
        $titleColumn = $repository->getTitleColumn($grid);
149
150
        $titleColumn->setSafe(false); // allows links in the title
151
152
        // Title link.
153
        $titleColumn->setTitle($this->trans('Name'));
154
        $titleColumn->manipulateRenderCell(
155
            function ($value, Row $row, $router) use ($routeParams, $settings) {
156
                /** @var Router $router */
157
                /** @var ResourceInterface $entity */
158
                $entity = $row->getEntity();
159
                $resourceNode = $entity->getResourceNode();
160
                $id = $resourceNode->getId();
161
162
                $myParams = $routeParams;
163
                $myParams['id'] = $id;
164
                unset($myParams[0]);
165
166
                $icon = $resourceNode->getIcon().' &nbsp;';
167
                if ($resourceNode->hasResourceFile()) {
168
                    // Process node that contains a file, process previews.
169
                    if ($resourceNode->isResourceFileAnImage()) {
170
                        $url = $router->generate('chamilo_core_resource_view_file', $myParams);
171
172
                        return $icon.'<a data-fancybox="gallery" href="'.$url.'">'.$value.'</a>';
173
                    }
174
175
                    if ($resourceNode->isResourceFileAVideo()) {
176
                        $url = $router->generate('chamilo_core_resource_view_file', $myParams);
177
178
                        return '
179
                        <video width="640" height="320" controls id="video'.$id.'" controls preload="metadata" style="display:none;">
180
                            <source src="'.$url.'" type="video/mp4">
181
                            Your browser doesn\'t support HTML5 video tag.
182
                        </video>
183
                        '.$icon.' <a data-fancybox="gallery"  data-width="640" data-height="360" href="#video'.$id.'">'.$value.'</a>';
184
                    }
185
186
                    $url = $router->generate('chamilo_core_resource_preview', $myParams);
187
188
                    return $icon.
189
                        '<a data-fancybox="gallery" data-type="iframe" data-src="'.$url.'" href="javascript:;" >'.
190
                        $value.'</a>';
191
                } else {
192
                    if ($settings->isAllowNodeCreation()) {
193
                        $url = $router->generate(
194
                            'chamilo_core_resource_list',
195
                            $myParams
196
                        );
197
                    } else {
198
                        $url = $router->generate('chamilo_core_resource_view_resource', $myParams);
199
                    }
200
201
                    return $icon.'<a href="'.$url.'">'.$value.'</a>';
202
                }
203
            }
204
        );
205
206
        /*if ($grid->hasColumn('filetype')) {
207
            $grid->getColumn('filetype')->manipulateRenderCell(
208
                function ($value, Row $row, $router) {
209
                    $entity = $row->getEntity();
210
                    $resourceNode = $entity->getResourceNode();
211
212
                    if ($resourceNode->hasResourceFile()) {
213
                        $file = $resourceNode->getResourceFile();
214
215
                        return $file->getMimeType();
216
                    }
217
218
                    return $this->trans('Folder');
219
                }
220
            );
221
        }*/
222
223
        if ($grid->hasColumn('iid')) {
224
            $grid->setHiddenColumns(['iid']);
225
        }
226
227
        // Delete mass action.
228
        if ($this->isGranted(ResourceNodeVoter::DELETE, $parentNode)) {
229
            $routeParams['icon'] = 'far fa-trash-alt';
230
            $deleteMassAction = new MassAction(
231
                'Delete',
232
                'ChamiloCoreBundle:Resource:deleteMass',
233
                true,
234
                $routeParams
235
            );
236
            $grid->addMassAction($deleteMassAction);
237
        }
238
239
        // Info action.
240
        $myRowAction = new RowAction(
241
            $this->trans('Info'),
242
            'chamilo_core_resource_info',
243
            false,
244
            '_self',
245
            [
246
                'class' => 'btn btn-secondary info_action resource_info',
247
                'icon' => 'fa-info-circle',
248
                'iframe' => false,
249
            ]
250
        );
251
252
        $setNodeParameters = function (RowAction $action, Row $row) use ($routeParams) {
253
            $id = $row->getEntity()->getResourceNode()->getId();
254
            $routeParams['id'] = $id;
255
            $action->setRouteParameters($routeParams);
256
            $attributes = $action->getAttributes();
257
            $attributes['data-action'] = $action->getRoute();
258
            $attributes['data-action-id'] = $action->getRoute().'_'.$id;
259
            $attributes['data-node-id'] = $id;
260
            $attributes['title'] = $this->trans('Info').' '.$row->getEntity()->getResourceName();
261
            $action->setAttributes($attributes);
262
263
            return $action;
264
        };
265
266
        $myRowAction->addManipulateRender($setNodeParameters);
267
        $grid->addRowAction($myRowAction);
268
269
        // Download action
270
        $myRowAction = new RowAction(
271
            $this->trans('Download'),
272
            'chamilo_core_resource_download',
273
            false,
274
            '_self',
275
            [
276
                'class' => 'btn btn-secondary download_action',
277
                'icon' => 'fa-download',
278
                'title' => $this->trans('Download'),
279
            ]
280
        );
281
282
        $setNodeDownloadParameters = function (RowAction $action, Row $row) use ($routeParams) {
283
            /** @var ResourceNode $resourceNode */
284
            $resourceNode = $row->getEntity()->getResourceNode();
285
            if (false === $resourceNode->hasResourceFile()) {
286
                return null;
287
            }
288
            $id = $row->getEntity()->getResourceNode()->getId();
289
            $routeParams['id'] = $id;
290
            $action->setRouteParameters($routeParams);
291
            $attributes = $action->getAttributes();
292
            $action->setAttributes($attributes);
293
294
            return $action;
295
        };
296
        $myRowAction->addManipulateRender($setNodeDownloadParameters);
297
        $grid->addRowAction($myRowAction);
298
299
        // Set EDIT/DELETE
300
        $setNodeParameters = function (RowAction $action, Row $row) use ($routeParams) {
301
            $id = $row->getEntity()->getResourceNode()->getId();
302
            $allowedEdit = $this->isGranted(ResourceNodeVoter::EDIT, $row->getEntity()->getResourceNode());
303
304
            if (false === $allowedEdit) {
305
                return null;
306
            }
307
308
            $routeParams['id'] = $id;
309
310
            $action->setRouteParameters($routeParams);
311
            $attributes = $action->getAttributes();
312
            //$attributes['data-action'] = $action->getRoute();
313
            //$attributes['data-action-id'] = $action->getRoute().'_'.$id;
314
            //$attributes['data-node-id'] = $id;
315
            $action->setAttributes($attributes);
316
317
            return $action;
318
        };
319
320
        if ($this->isGranted(ResourceNodeVoter::EDIT, $parentNode)) {
321
            // Enable/Disable
322
            $myRowAction = new RowAction(
323
                '',
324
                'chamilo_core_resource_change_visibility',
325
                false,
326
                '_self'
327
            );
328
329
            $setVisibleParameters = function (RowAction $action, Row $row) use ($routeParams) {
330
                /** @var AbstractResource $resource */
331
                $resource = $row->getEntity();
332
                $allowedEdit = $this->isGranted(ResourceNodeVoter::EDIT, $resource->getResourceNode());
333
334
                if (false === $allowedEdit) {
335
                    return null;
336
                }
337
338
                $id = $resource->getResourceNode()->getId();
339
340
                $icon = 'fa-eye-slash';
341
                if ($this->hasCourse()) {
342
                    $link = $resource->getCourseSessionResourceLink($this->getCourse(), $this->getSession());
343
                } else {
344
                    $link = $resource->getFirstResourceLink();
345
                }
346
347
                if (null === $link) {
348
                    return null;
349
                }
350
                if (ResourceLink::VISIBILITY_PUBLISHED === $link->getVisibility()) {
351
                    $icon = 'fa-eye';
352
                }
353
                $routeParams['id'] = $id;
354
                $action->setRouteParameters($routeParams);
355
                $attributes = [
356
                    'class' => 'btn btn-secondary change_visibility',
357
                    'data-id' => $id,
358
                    'icon' => $icon,
359
                ];
360
                $action->setAttributes($attributes);
361
362
                return $action;
363
            };
364
365
            $myRowAction->addManipulateRender($setVisibleParameters);
366
            $grid->addRowAction($myRowAction);
367
368
            if ($settings->isAllowResourceEdit()) {
369
                // Edit action.
370
                $myRowAction = new RowAction(
371
                    $this->trans('Edit'),
372
                    'chamilo_core_resource_edit',
373
                    false,
374
                    '_self',
375
                    ['class' => 'btn btn-secondary', 'icon' => 'fa fa-pen']
376
                );
377
                $myRowAction->addManipulateRender($setNodeParameters);
378
                $grid->addRowAction($myRowAction);
379
            }
380
381
            // More action.
382
            /*$myRowAction = new RowAction(
383
                $this->trans('More'),
384
                'chamilo_core_resource_preview',
385
                false,
386
                '_self',
387
                ['class' => 'btn btn-secondary edit_resource', 'icon' => 'fa fa-ellipsis-h']
388
            );
389
390
            $myRowAction->addManipulateRender($setNodeParameters);
391
            $grid->addRowAction($myRowAction);*/
392
393
            // Delete action.
394
            $myRowAction = new RowAction(
395
                $this->trans('Delete'),
396
                'chamilo_core_resource_delete',
397
                true,
398
                '_self',
399
                [
400
                    'class' => 'btn btn-danger',
401
                    //'data_hidden' => true,
402
                ]
403
            );
404
            $myRowAction->addManipulateRender($setNodeParameters);
405
            $grid->addRowAction($myRowAction);
406
        }
407
408
        /*$grid->addExport(new CSVExport($this->trans('CSV export'), 'export', ['course' => $courseIdentifier]));
409
        $grid->addExport(
410
            new ExcelExport(
411
                $this->trans('Excel export'),
412
                'export',
413
                ['course' => $courseIdentifier]
414
            )
415
        );*/
416
417
        return $grid;
418
    }
419
420
    /**
421
     * @Route("/{tool}/{type}/{id}/list", name="chamilo_core_resource_list")
422
     *
423
     * If node has children show it
424
     */
425
    public function listAction(Request $request, Grid $grid): Response
426
    {
427
        $tool = $request->get('tool');
428
        $type = $request->get('type');
429
        $resourceNodeId = $request->get('id');
430
431
        $repository = $this->getRepositoryFromRequest($request);
432
        $settings = $repository->getResourceSettings();
433
434
        $grid = $this->getGrid($request, $repository, $grid, $resourceNodeId);
435
436
        $this->setBreadCrumb($request);
437
        $parentResourceNode = $this->getParentResourceNode($request);
438
439
        return $grid->getGridResponse(
440
            $repository->getTemplates()->getFromAction(__FUNCTION__),
441
            [
442
                'parent_id' => $resourceNodeId,
443
                'tool' => $tool,
444
                'type' => $type,
445
                'id' => $resourceNodeId,
446
                'parent_resource_node' => $parentResourceNode,
447
                'resource_settings' => $settings,
448
            ]
449
        );
450
    }
451
452
    private function setBreadCrumb(Request $request)
453
    {
454
        $tool = $request->get('tool');
455
        $type = $request->get('type');
456
        $resourceNodeId = $request->get('id');
457
        $routeParams = $this->getResourceParams($request);
458
459
        if (!empty($resourceNodeId)) {
460
            $breadcrumb = $this->getBreadCrumb();
461
            $toolParams = $routeParams;
462
            $toolParams['id'] = null;
463
464
            // Root tool link
465
            $breadcrumb->addChild(
466
                $this->trans($tool),
467
                [
468
                    'uri' => $this->generateUrl('chamilo_core_resource_index', $toolParams),
469
                ]
470
            );
471
472
            $repo = $this->getRepositoryFromRequest($request);
473
            $settings = $repo->getResourceSettings();
474
475
            /** @var ResourceInterface $originalResource */
476
            $originalResource = $repo->findOneBy(['resourceNode' => $resourceNodeId]);
477
            if (null === $originalResource) {
478
                return;
479
            }
480
            $parent = $originalParent = $originalResource->getResourceNode();
481
482
            $parentList = [];
483
            while (null !== $parent) {
484
                if ($type !== $parent->getResourceType()->getName()) {
485
                    break;
486
                }
487
                $parent = $parent->getParent();
488
                if ($parent) {
489
                    $resource = $repo->findOneBy(['resourceNode' => $parent->getId()]);
490
                    if ($resource) {
491
                        $parentList[] = $resource;
492
                    }
493
                }
494
            }
495
496
            $parentList = array_reverse($parentList);
497
            /** @var ResourceInterface $item */
498
            foreach ($parentList as $item) {
499
                $params = $routeParams;
500
                $params['id'] = $item->getResourceNode()->getId();
501
                $breadcrumb->addChild(
502
                    $item->getResourceName(),
503
                    [
504
                        'uri' => $this->generateUrl('chamilo_core_resource_list', $params),
505
                    ]
506
                );
507
            }
508
509
            $params = $routeParams;
510
            $params['id'] = $originalParent->getId();
511
            if (false === $settings->isAllowNodeCreation() || $originalResource->getResourceNode()->hasResourceFile()) {
512
                $breadcrumb->addChild($originalResource->getResourceName());
513
            } else {
514
                $breadcrumb->addChild(
515
                    $originalResource->getResourceName(),
516
                    [
517
                        'uri' => $this->generateUrl('chamilo_core_resource_list', $params),
518
                    ]
519
                );
520
            }
521
        }
522
    }
523
524
    /**
525
     * @Route("/{tool}/{type}/{id}/new_folder", methods={"GET", "POST"}, name="chamilo_core_resource_new_folder")
526
     */
527
    public function newFolderAction(Request $request): Response
528
    {
529
        $this->setBreadCrumb($request);
530
531
        return $this->createResource($request, 'folder');
532
    }
533
534
    /**
535
     * @param string $fileType
536
     *
537
     * @return RedirectResponse|Response
538
     */
539
    private function createResource(Request $request, $fileType = 'file')
540
    {
541
        $resourceNodeParentId = $request->get('id');
542
        $repository = $this->getRepositoryFromRequest($request);
543
544
        // Default parent node is course.
545
        $parentNode = $this->getParentResourceNode($request);
546
547
        $this->denyAccessUnlessGranted(
548
            ResourceNodeVoter::CREATE,
549
            $parentNode,
550
            $this->trans('Unauthorised access to resource')
551
        );
552
553
        $form = $repository->getForm($this->container->get('form.factory'), null);
554
555
        $settings = $repository->getResourceSettings();
556
557
        if ('file' === $fileType && $settings->isAllowToSaveEditorToResourceFile()) {
558
            $resourceParams = $this->getResourceParams($request);
559
            $form->add(
560
                $this->fileContentName,
561
                CKEditorType::class,
562
                [
563
                    'mapped' => false,
564
                    'config' => [
565
                        'filebrowserImageBrowseRoute' => 'resources_filemanager',
566
                        'filebrowserImageBrowseRouteParameters' => $resourceParams,
567
                        'fullPage' => true,
568
                    ],
569
                ]
570
            );
571
        }
572
573
        $form->handleRequest($request);
574
        if ($form->isSubmitted() && $form->isValid()) {
575
            $em = $this->getDoctrine()->getManager();
576
577
            $course = $this->getCourse();
578
            $session = $this->getSession();
579
580
            /** @var ResourceInterface $newResource */
581
            $newResource = $repository->saveResource($form, $course, $session, $fileType);
582
583
            $file = null;
584
            if ('file' === $fileType && $settings->isAllowToSaveEditorToResourceFile()) {
585
                $content = $form->get($this->fileContentName)->getViewData();
586
                $newResource->setTitle($newResource->getTitle().'.html');
0 ignored issues
show
Bug introduced by
The method setTitle() does not exist on Chamilo\CoreBundle\Entit...ource\ResourceInterface. It seems like you code against a sub-type of Chamilo\CoreBundle\Entit...ource\ResourceInterface such as Chamilo\CoreBundle\Entity\Course or Chamilo\CourseBundle\Entity\CLink or Chamilo\CourseBundle\Entity\CAnnouncement or Chamilo\CourseBundle\Entity\CThematicPlan or Chamilo\CourseBundle\Entity\CQuiz or Chamilo\CourseBundle\Entity\CCourseDescription or Chamilo\CourseBundle\Entity\CDocument or Chamilo\CourseBundle\Entity\CThematic or Chamilo\CourseBundle\Entity\CQuizQuestionCategory or Chamilo\CourseBundle\Entity\CStudentPublication or Chamilo\CourseBundle\Entity\CCalendarEvent. ( Ignorable by Annotation )

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

586
                $newResource->/** @scrutinizer ignore-call */ 
587
                              setTitle($newResource->getTitle().'.html');
Loading history...
Bug introduced by
The method getTitle() does not exist on Chamilo\CoreBundle\Entit...ource\ResourceInterface. It seems like you code against a sub-type of Chamilo\CoreBundle\Entit...ource\ResourceInterface such as Chamilo\CoreBundle\Entity\Course or Chamilo\CourseBundle\Entity\CLink or Chamilo\CourseBundle\Entity\CAnnouncement or Chamilo\CourseBundle\Entity\CThematicPlan or Chamilo\CourseBundle\Entity\CQuiz or Chamilo\CourseBundle\Entity\CCourseDescription or Chamilo\CourseBundle\Entity\CDocument or Chamilo\CourseBundle\Entity\CThematic or Chamilo\CourseBundle\Entity\CQuizQuestionCategory or Chamilo\CourseBundle\Entity\CStudentPublication or Chamilo\CourseBundle\Entity\CCalendarEvent. ( Ignorable by Annotation )

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

586
                $newResource->setTitle($newResource->/** @scrutinizer ignore-call */ getTitle().'.html');
Loading history...
587
                $fileName = $newResource->getTitle();
588
589
                $handle = tmpfile();
590
                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

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

591
                $meta = stream_get_meta_data(/** @scrutinizer ignore-type */ $handle);
Loading history...
592
                $file = new UploadedFile($meta['uri'], $fileName, 'text/html', null, true);
593
                $em->persist($newResource);
594
            }
595
596
            $repository->addResourceToCourseWithParent(
597
                $newResource,
598
                $parentNode,
599
                ResourceLink::VISIBILITY_PUBLISHED,
600
                $this->getUser(),
601
                $course,
602
                $session,
603
                null,
604
                $file
605
            );
606
607
            $em->flush();
608
609
            // Loops all sharing options
610
            /*foreach ($shareList as $share) {
611
                $idList = [];
612
                if (isset($share['search'])) {
613
                    $idList = explode(',', $share['search']);
614
                }
615
616
                $resourceRight = null;
617
                if (isset($share['mask'])) {
618
                    $resourceRight = new ResourceRight();
619
                    $resourceRight
620
                        ->setMask($share['mask'])
621
                        ->setRole($share['role'])
622
                    ;
623
                }
624
625
                // Build links
626
                switch ($share['sharing']) {
627
                    case 'everyone':
628
                        $repository->addResourceToEveryone(
629
                            $resourceNode,
630
                            $resourceRight
631
                        );
632
                        break;
633
                    case 'course':
634
                        $repository->addResourceToCourse(
635
                            $resourceNode,
636
                            $course,
637
                            $resourceRight
638
                        );
639
                        break;
640
                    case 'session':
641
                        $repository->addResourceToSession(
642
                            $resourceNode,
643
                            $course,
644
                            $session,
645
                            $resourceRight
646
                        );
647
                        break;
648
                    case 'user':
649
                        // Only for me
650
                        if (isset($share['only_me'])) {
651
                            $repository->addResourceOnlyToMe($resourceNode);
652
                        } else {
653
                            // To other users
654
                            $repository->addResourceToUserList($resourceNode, $idList);
655
                        }
656
                        break;
657
                    case 'group':
658
                        // @todo
659
                        break;
660
                }*/
661
            //}
662
            $em->flush();
663
            $this->addFlash('success', $this->trans('Saved'));
664
665
            $params = $this->getResourceParams($request);
666
            $params['id'] = $resourceNodeParentId;
667
668
            return $this->redirectToRoute(
669
                'chamilo_core_resource_list',
670
                $params
671
            );
672
        }
673
674
        switch ($fileType) {
675
            case 'folder':
676
                $template = $repository->getTemplates()->getFromAction('newFolderAction');
677
678
                break;
679
            case 'file':
680
                $template = $repository->getTemplates()->getFromAction('newAction');
681
682
                break;
683
        }
684
685
        $routeParams = $this->getResourceParams($request);
686
        $routeParams['form'] = $form->createView();
687
        $routeParams['parent'] = $resourceNodeParentId;
688
        $routeParams['file_type'] = $fileType;
689
690
        return $this->render($template, $routeParams);
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...
691
    }
692
693
    /**
694
     * @Route("/{tool}/{type}/{id}/new", methods={"GET", "POST"}, name="chamilo_core_resource_new")
695
     */
696
    public function newAction(Request $request): Response
697
    {
698
        $this->setBreadCrumb($request);
699
700
        return $this->createResource($request, 'file');
701
    }
702
703
    /**
704
     * @Route("/{tool}/{type}/{id}/disk_space", methods={"GET", "POST"}, name="chamilo_core_resource_disk_space")
705
     */
706
    public function diskSpaceAction(Request $request): Response
707
    {
708
        $this->setBreadCrumb($request);
709
        $nodeId = $request->get('id');
710
        $repository = $this->getRepositoryFromRequest($request);
711
712
        /** @var ResourceNode $resourceNode */
713
        $resourceNode = $repository->getResourceNodeRepository()->find($nodeId);
714
715
        $this->denyAccessUnlessGranted(
716
            ResourceNodeVoter::VIEW,
717
            $resourceNode,
718
            $this->trans('Unauthorised access to resource')
719
        );
720
721
        $course = $this->getCourse();
722
        $totalSize = 0;
723
        if ($course) {
0 ignored issues
show
introduced by
$course is of type Chamilo\CoreBundle\Entity\Course, thus it always evaluated to true.
Loading history...
724
            $totalSize = $course->getDiskQuota();
725
        }
726
727
        $size = $repository->getResourceNodeRepository()->getSize(
728
            $resourceNode,
729
            $repository->getResourceType(),
730
            $course
731
        );
732
733
        $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...
734
        $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...
735
        $sessions = $course->getSessions();
736
737
        foreach ($sessions as $sessionRelCourse) {
738
            $session = $sessionRelCourse->getSession();
739
740
            $labels[] = $course->getTitle().' - '.$session->getName();
741
            $size = $repository->getResourceNodeRepository()->getSize(
742
                $resourceNode,
743
                $repository->getResourceType(),
744
                $course,
745
                $session
746
            );
747
            $data[] = $size;
748
        }
749
750
        $groups = $course->getGroups();
751
        foreach ($groups as $group) {
752
            $labels[] = $course->getTitle().' - '.$group->getName();
753
            $size = $repository->getResourceNodeRepository()->getSize(
754
                $resourceNode,
755
                $repository->getResourceType(),
756
                $course,
757
                null,
758
                $group
759
            );
760
            $data[] = $size;
761
        }
762
763
        $used = array_sum($data);
764
        $labels[] = $this->trans('Free');
765
        $data[] = $totalSize - $used;
766
767
        return $this->render(
768
            $repository->getTemplates()->getFromAction(__FUNCTION__),
769
            [
770
                'resourceNode' => $resourceNode,
771
                'labels' => $labels,
772
                'data' => $data,
773
            ]
774
        );
775
    }
776
777
    /**
778
     * @Route("/{tool}/{type}/{id}/edit", methods={"GET", "POST"})
779
     */
780
    public function editAction(Request $request, IllustrationRepository $illustrationRepository): Response
781
    {
782
        $resourceNodeId = $request->get('id');
783
784
        $this->setBreadCrumb($request);
785
        $repository = $this->getRepositoryFromRequest($request);
786
        $resource = $repository->getResourceFromResourceNode($resourceNodeId);
787
        $this->denyAccessUnlessValidResource($resource);
0 ignored issues
show
Bug introduced by
It seems like $resource can also be of type null; however, parameter $resource of Chamilo\CoreBundle\Contr...ssUnlessValidResource() does only seem to accept Chamilo\CoreBundle\Entit...source\AbstractResource, 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

787
        $this->denyAccessUnlessValidResource(/** @scrutinizer ignore-type */ $resource);
Loading history...
788
        $settings = $repository->getResourceSettings();
789
        $resourceNode = $resource->getResourceNode();
790
791
        $this->denyAccessUnlessGranted(
792
            ResourceNodeVoter::EDIT,
793
            $resourceNode,
794
            $this->trans('Unauthorised access to resource')
795
        );
796
797
        $resourceNodeParentId = $resourceNode->getId();
798
799
        $routeParams = $this->getResourceParams($request);
800
        $routeParams['id'] = $resourceNodeParentId;
801
802
        $form = $repository->getForm($this->container->get('form.factory'), $resource);
803
804
        if ($resourceNode->hasEditableContent() && $settings->isAllowToSaveEditorToResourceFile()) {
805
            $form->add(
806
                $this->fileContentName,
807
                CKEditorType::class,
808
                [
809
                    'mapped' => false,
810
                    'config' => [
811
                        'filebrowserImageBrowseRoute' => 'resources_filemanager',
812
                        'filebrowserImageBrowseRouteParameters' => $routeParams,
813
                    ],
814
                ]
815
            );
816
            $content = $repository->getResourceNodeFileContent($resourceNode);
817
            $form->get($this->fileContentName)->setData($content);
818
        }
819
820
        $form->handleRequest($request);
821
822
        if ($form->isSubmitted() && $form->isValid()) {
823
            /** @var AbstractResource $newResource */
824
            $newResource = $form->getData();
825
826
            if ($form->has($this->fileContentName)) {
827
                $data = $form->get($this->fileContentName)->getData();
828
                $repository->updateResourceFileContent($newResource, $data);
829
            }
830
831
            $repository->updateNodeForResource($newResource);
832
833
            if ($form->has('illustration')) {
834
                $illustration = $form->get('illustration')->getData();
835
                if ($illustration) {
836
                    $file = $illustrationRepository->addIllustration($newResource, $this->getUser(), $illustration);
837
                    $em = $illustrationRepository->getEntityManager();
838
                    $em->persist($file);
839
                    $em->flush();
840
                }
841
            }
842
843
            $this->addFlash('success', $this->trans('Updated'));
844
845
            $resourceNodeParentId = $newResource->getResourceNode()->getParent()->getId();
846
            $routeParams['id'] = $resourceNodeParentId;
847
848
            return $this->redirectToRoute('chamilo_core_resource_list', $routeParams);
849
        }
850
851
        return $this->render(
852
            $repository->getTemplates()->getFromAction(__FUNCTION__),
853
            [
854
                'form' => $form->createView(),
855
                'parent' => $resourceNodeParentId,
856
            ]
857
        );
858
    }
859
860
    /**
861
     * Shows a resource information.
862
     *
863
     * @Route("/{tool}/{type}/{id}/info", methods={"GET", "POST"}, name="chamilo_core_resource_info")
864
     */
865
    public function infoAction(Request $request, IllustrationRepository $illustrationRepository): Response
866
    {
867
        $this->setBreadCrumb($request);
868
        $nodeId = $request->get('id');
869
870
        $repository = $this->getRepositoryFromRequest($request);
871
872
        /** @var AbstractResource $resource */
873
        $resource = $repository->getResourceFromResourceNode($nodeId);
874
        $this->denyAccessUnlessValidResource($resource);
875
876
        $resourceNode = $resource->getResourceNode();
877
        $this->denyAccessUnlessGranted(
878
            ResourceNodeVoter::VIEW,
879
            $resourceNode,
880
            $this->trans('Unauthorised access to resource')
881
        );
882
883
        $tool = $request->get('tool');
884
        $type = $request->get('type');
885
886
        $illustration = $illustrationRepository->getIllustrationUrlFromNode($resource->getResourceNode());
887
888
        $form = $this->createForm(ResourceCommentType::class, null);
889
890
        $params = [
891
            'resource' => $resource,
892
            'illustration' => $illustration,
893
            'tool' => $tool,
894
            'type' => $type,
895
            'comment_form' => $form->createView(),
896
        ];
897
898
        return $this->render(
899
            $repository->getTemplates()->getFromAction(__FUNCTION__, $request->isXmlHttpRequest()),
900
            $params
901
        );
902
    }
903
904
    /**
905
     * Shows a resource information.
906
     *
907
     * @Route("/{tool}/{type}/{id}/comments/new", methods={"POST"}, name="chamilo_core_resource_comment_new")
908
     */
909
    public function addCommentAction(Request $request): Response
910
    {
911
        if (!$request->isXmlHttpRequest()) {
912
            return new JsonResponse(['message' => 'Only ajax'], Response::HTTP_BAD_REQUEST);
913
        }
914
915
        $nodeId = $request->get('id');
916
        $repository = $this->getRepositoryFromRequest($request);
917
918
        /** @var AbstractResource $resource */
919
        $resource = $repository->getResourceFromResourceNode($nodeId);
920
        $this->denyAccessUnlessValidResource($resource);
921
922
        $comment = new ResourceComment();
923
        $form = $this->createForm(ResourceCommentType::class, $comment, ['method' => 'POST']);
924
925
        $form->handleRequest($request);
926
        if ($form->isSubmitted() && $form->isValid()) {
927
            /** @var ResourceComment $comment */
928
            $comment = $form->getData();
929
            $comment->setAuthor($this->getUser());
930
            $resource->getResourceNode()->addComment($comment);
931
            $repository->getEntityManager()->persist($resource);
932
            $repository->getEntityManager()->flush();
933
934
            return new JsonResponse(['message' => 'added'], Response::HTTP_OK);
935
        }
936
937
        return new JsonResponse(['message' => 'error'], Response::HTTP_BAD_REQUEST);
938
    }
939
940
    /**
941
     * Shows a resource information.
942
     *
943
     * @Route("/{tool}/{type}/{id}/comments", methods={"GET"}, name="chamilo_core_resource_comments")
944
     */
945
    public function getCommentAction(Request $request): Response
946
    {
947
        $nodeId = $request->get('id');
948
        $repository = $this->getRepositoryFromRequest($request);
949
950
        /** @var AbstractResource $resource */
951
        $resource = $repository->getResourceFromResourceNode($nodeId);
952
        $this->denyAccessUnlessValidResource($resource);
953
        $comments = $resource->getResourceNode()->getComments();
954
955
        return new JsonResponse($comments, Response::HTTP_OK);
956
    }
957
958
    /**
959
     * Shows a resource information.
960
     *
961
     * @Route("/{tool}/{type}/{id}/comments/{commentId}", methods={"DELETE"}, name="chamilo_core_resource_comments")
962
     */
963
    public function deleteCommentAction(Request $request, $commentId): Response
964
    {
965
        $nodeId = $request->get('id');
966
        $repository = $this->getRepositoryFromRequest($request);
967
968
        /** @var AbstractResource $resource */
969
        $resource = $repository->getResourceFromResourceNode($nodeId);
970
        $this->denyAccessUnlessValidResource($resource);
971
972
        $em = $repository->getEntityManager();
973
        $comment = $em->getRepository('ChamiloCoreBundle:Resource\ResourceComment')->find($commentId);
974
        $resource->getResourceNode()->getComments()->removeElement($comment);
975
        $repository->getEntityManager()->persist($resource);
976
        $repository->getEntityManager()->flush();
977
978
        return new JsonResponse(['message' => 'ok'], Response::HTTP_OK);
979
    }
980
981
    /**
982
     * Preview a file. Mostly used when using a modal.
983
     *
984
     * @Route("/{tool}/{type}/{id}/preview", methods={"GET"}, name="chamilo_core_resource_preview")
985
     */
986
    public function previewAction(Request $request): Response
987
    {
988
        $this->setBreadCrumb($request);
989
        $nodeId = $request->get('id');
990
991
        $repository = $this->getRepositoryFromRequest($request);
992
993
        /** @var AbstractResource $resource */
994
        $resource = $repository->getResourceFromResourceNode($nodeId);
995
        $this->denyAccessUnlessValidResource($resource);
996
997
        $resourceNode = $resource->getResourceNode();
998
999
        $this->denyAccessUnlessGranted(
1000
            ResourceNodeVoter::VIEW,
1001
            $resourceNode,
1002
            $this->trans('Unauthorised access to resource')
1003
        );
1004
1005
        $tool = $request->get('tool');
1006
        $type = $request->get('type');
1007
1008
        $params = [
1009
            'resource' => $resource,
1010
            'tool' => $tool,
1011
            'type' => $type,
1012
        ];
1013
1014
        return $this->render($repository->getTemplates()->getFromAction(__FUNCTION__), $params);
1015
    }
1016
1017
    /**
1018
     * @Route("/{tool}/{type}/{id}/change_visibility", name="chamilo_core_resource_change_visibility")
1019
     */
1020
    public function changeVisibilityAction(Request $request): Response
1021
    {
1022
        $id = $request->get('id');
1023
1024
        $repository = $this->getRepositoryFromRequest($request);
1025
1026
        /** @var AbstractResource $resource */
1027
        $resource = $repository->getResourceFromResourceNode($id);
1028
1029
        $this->denyAccessUnlessValidResource($resource);
1030
1031
        $resourceNode = $resource->getResourceNode();
1032
1033
        $this->denyAccessUnlessGranted(
1034
            ResourceNodeVoter::EDIT,
1035
            $resourceNode,
1036
            $this->trans('Unauthorised access to resource')
1037
        );
1038
1039
        /** @var ResourceLink $link */
1040
        if ($this->hasCourse()) {
1041
            $link = $resource->getCourseSessionResourceLink($this->getCourse(), $this->getSession());
1042
        } else {
1043
            $link = $resource->getFirstResourceLink();
1044
        }
1045
1046
        $icon = 'fa-eye';
1047
        // Use repository to change settings easily.
1048
        if ($link && ResourceLink::VISIBILITY_PUBLISHED === $link->getVisibility()) {
1049
            $repository->setVisibilityDraft($resource);
1050
            $icon = 'fa-eye-slash';
1051
        } else {
1052
            $repository->setVisibilityPublished($resource);
1053
        }
1054
1055
        $result = ['icon' => $icon];
1056
1057
        return new JsonResponse($result);
1058
    }
1059
1060
    /**
1061
     * @Route("/{tool}/{type}/{id}", name="chamilo_core_resource_delete")
1062
     */
1063
    public function deleteAction(Request $request): Response
1064
    {
1065
        $em = $this->getDoctrine()->getManager();
1066
1067
        $id = $request->get('id');
1068
        $resourceNode = $this->getDoctrine()->getRepository('ChamiloCoreBundle:Resource\ResourceNode')->find($id);
1069
        $parentId = $resourceNode->getParent()->getId();
1070
1071
        $this->denyAccessUnlessGranted(
1072
            ResourceNodeVoter::DELETE,
1073
            $resourceNode,
1074
            $this->trans('Unauthorised access to resource')
1075
        );
1076
1077
        $children = $resourceNode->getChildren();
1078
1079
        if (!empty($children)) {
1080
            /** @var ResourceNode $child */
1081
            foreach ($children as $child) {
1082
                $em->remove($child);
1083
            }
1084
        }
1085
1086
        $em->remove($resourceNode);
1087
        $this->addFlash('success', $this->trans('Deleted'));
1088
        $em->flush();
1089
1090
        $routeParams = $this->getResourceParams($request);
1091
        $routeParams['id'] = $parentId;
1092
1093
        return $this->redirectToRoute('chamilo_core_resource_list', $routeParams);
1094
    }
1095
1096
    /**
1097
     * @Route("/{tool}/{type}/{id}", methods={"DELETE"}, name="chamilo_core_resource_delete_mass")
1098
     */
1099
    public function deleteMassAction($primaryKeys, $allPrimaryKeys, Request $request): Response
1100
    {
1101
        $em = $this->getDoctrine()->getManager();
1102
        $repo = $this->getRepositoryFromRequest($request);
1103
1104
        $parentId = 0;
1105
        foreach ($primaryKeys as $id) {
1106
            $resource = $repo->find($id);
1107
            $resourceNode = $resource->getResourceNode();
1108
1109
            if (null === $resourceNode) {
1110
                continue;
1111
            }
1112
1113
            $this->denyAccessUnlessGranted(
1114
                ResourceNodeVoter::DELETE,
1115
                $resourceNode,
1116
                $this->trans('Unauthorised access to resource')
1117
            );
1118
1119
            $parentId = $resourceNode->getParent()->getId();
1120
            $em->remove($resource);
1121
        }
1122
1123
        $this->addFlash('success', $this->trans('Deleted'));
1124
        $em->flush();
1125
1126
        $routeParams = $this->getResourceParams($request);
1127
        $routeParams['id'] = $parentId;
1128
1129
        return $this->redirectToRoute('chamilo_core_resource_list', $routeParams);
1130
    }
1131
1132
    /**
1133
     * Shows the associated resource file.
1134
     *
1135
     * @Route("/{tool}/{type}/{id}/view", methods={"GET"}, name="chamilo_core_resource_view_file")
1136
     */
1137
    public function viewAction(Request $request, RouterInterface $router): Response
1138
    {
1139
        $id = $request->get('id');
1140
        $filter = $request->get('filter');
1141
        $mode = $request->get('mode');
1142
        $em = $this->getDoctrine();
1143
        /** @var ResourceNode $resourceNode */
1144
        $resourceNode = $em->getRepository('ChamiloCoreBundle:Resource\ResourceNode')->find($id);
1145
1146
        if (null === $resourceNode) {
1147
            throw new FileNotFoundException('Resource not found');
1148
        }
1149
1150
        $repo = $this->getRepositoryFromRequest($request);
1151
1152
        if ($repo instanceof ResourceWithLinkInterface) {
1153
            $resource = $repo->getResourceFromResourceNode($resourceNode->getId());
1154
            $url = $repo->getLink($resource, $router, $this->getCourseUrlQueryToArray());
0 ignored issues
show
Bug introduced by
It seems like $resource can also be of type null; however, parameter $resource of Chamilo\CoreBundle\Repos...inkInterface::getLink() does only seem to accept Chamilo\CoreBundle\Entit...ource\ResourceInterface, 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

1154
            $url = $repo->getLink(/** @scrutinizer ignore-type */ $resource, $router, $this->getCourseUrlQueryToArray());
Loading history...
1155
1156
            return $this->redirect($url);
1157
        }
1158
1159
        return $this->showFile($request, $resourceNode, $mode, $filter);
1160
    }
1161
1162
    /**
1163
     * @param string $mode
1164
     * @param string $filter
1165
     *
1166
     * @return mixed|StreamedResponse
1167
     */
1168
    private function showFile(Request $request, ResourceNode $resourceNode, $mode = 'show', $filter = '')
1169
    {
1170
        $this->denyAccessUnlessGranted(
1171
            ResourceNodeVoter::VIEW,
1172
            $resourceNode,
1173
            $this->trans('Unauthorised access to resource')
1174
        );
1175
1176
        $repo = $this->getRepositoryFromRequest($request);
1177
        $resourceFile = $resourceNode->getResourceFile();
1178
1179
        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...
1180
            throw new NotFoundHttpException($this->trans('File not found for resource'));
1181
        }
1182
1183
        $fileName = $resourceNode->getSlug();
1184
        $mimeType = $resourceFile->getMimeType();
1185
1186
        switch ($mode) {
1187
            case 'download':
1188
                $forceDownload = true;
1189
1190
                break;
1191
            case 'show':
1192
            default:
1193
                $forceDownload = false;
1194
                // If it's an image then send it to Glide.
1195
                if (false !== strpos($mimeType, 'image')) {
1196
                    $glide = $this->getGlide();
1197
                    $server = $glide->getServer();
1198
                    $params = $request->query->all();
1199
1200
                    // The filter overwrites the params from get
1201
                    if (!empty($filter)) {
1202
                        $params = $glide->getFilters()[$filter] ?? [];
1203
                    }
1204
1205
                    // The image was cropped manually by the user, so we force to render this version,
1206
                    // no matter other crop parameters.
1207
                    $crop = $resourceFile->getCrop();
1208
                    if (!empty($crop)) {
1209
                        $params['crop'] = $crop;
1210
                    }
1211
1212
                    $fileName = $repo->getResourceNodeRepository()->getFilename($resourceFile);
1213
1214
                    return $server->getImageResponse($fileName, $params);
1215
                }
1216
1217
                break;
1218
        }
1219
1220
        $stream = $repo->getResourceNodeFileStream($resourceNode);
1221
1222
        $response = new StreamedResponse(
1223
            function () use ($stream): void {
1224
                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

1224
                stream_copy_to_stream($stream, /** @scrutinizer ignore-type */ fopen('php://output', 'wb'));
Loading history...
Bug introduced by
It seems like $stream can also be of type string; however, parameter $source 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

1224
                stream_copy_to_stream(/** @scrutinizer ignore-type */ $stream, fopen('php://output', 'wb'));
Loading history...
1225
            }
1226
        );
1227
        $disposition = $response->headers->makeDisposition(
1228
            $forceDownload ? ResponseHeaderBag::DISPOSITION_ATTACHMENT : ResponseHeaderBag::DISPOSITION_INLINE,
1229
            $fileName
1230
        //Transliterator::transliterate($fileName)
1231
        );
1232
        $response->headers->set('Content-Disposition', $disposition);
1233
        $response->headers->set('Content-Type', $mimeType ?: 'application/octet-stream');
1234
1235
        return $response;
1236
    }
1237
1238
    /**
1239
     * Shows the associated resource file.
1240
     *
1241
     * @Route("/{tool}/{type}/{id}/view_resource", methods={"GET"}, name="chamilo_core_resource_view_resource")
1242
     */
1243
    public function viewResourceAction(Request $request, RouterInterface $router): Response
1244
    {
1245
        $id = $request->get('id');
1246
        $em = $this->getDoctrine();
1247
1248
        /** @var ResourceNode $resourceNode */
1249
        $resourceNode = $em->getRepository('ChamiloCoreBundle:Resource\ResourceNode')->find($id);
1250
1251
        $this->denyAccessUnlessGranted(
1252
            ResourceNodeVoter::VIEW,
1253
            $resourceNode,
1254
            $this->trans('Unauthorised access to resource')
1255
        );
1256
1257
        $repository = $this->getRepositoryFromRequest($request);
1258
1259
        /** @var AbstractResource $resource */
1260
        $resource = $repository->getResourceFromResourceNode($id);
1261
1262
        $tool = $request->get('tool');
1263
        $type = $request->get('type');
1264
        $this->setBreadCrumb($request);
1265
1266
        $params = [
1267
            'resource' => $resource,
1268
            'tool' => $tool,
1269
            'type' => $type,
1270
        ];
1271
1272
        return $this->render($repository->getTemplates()->getFromAction(__FUNCTION__), $params);
1273
1274
        //return $this->showFile($request, $resourceNode, $mode, $filter);
1275
    }
1276
1277
    /**
1278
     * @Route("/{tool}/{type}/{id}/download", methods={"GET"}, name="chamilo_core_resource_download")
1279
     */
1280
    public function downloadAction(Request $request)
1281
    {
1282
        $resourceNodeId = (int) $request->get('id');
1283
        $courseNode = $this->getCourse()->getResourceNode();
1284
1285
        $repo = $this->getRepositoryFromRequest($request);
1286
1287
        if (empty($resourceNodeId)) {
1288
            $resourceNode = $courseNode;
1289
        } else {
1290
            $resourceNode = $repo->getResourceNodeRepository()->find($resourceNodeId);
1291
        }
1292
1293
        $this->denyAccessUnlessGranted(
1294
            ResourceNodeVoter::VIEW,
1295
            $resourceNode,
1296
            $this->trans('Unauthorised access to resource')
1297
        );
1298
1299
        // If resource node has a file just download it. Don't download the children.
1300
        if ($resourceNode->hasResourceFile()) {
1301
            // Redirect to download single file.
1302
            return $this->showFile($request, $resourceNode, 'download');
1303
        }
1304
1305
        $zipName = $resourceNode->getSlug().'.zip';
1306
        $rootNodePath = $resourceNode->getPathForDisplay();
1307
        $resourceNodeRepo = $repo->getResourceNodeRepository();
1308
1309
        $criteria = Criteria::create()
1310
            ->where(Criteria::expr()->neq('resourceFile', null)) // must have a file
1311
            // ->andWhere(Criteria::expr()->eq('resourceType', $type))
1312
        ;
1313
1314
        /** @var ArrayCollection|ResourceNode[] $children */
1315
        /** @var QueryBuilder $children */
1316
        $qb = $resourceNodeRepo->getChildrenQueryBuilder($resourceNode);
1317
        $qb->addCriteria($criteria);
1318
        $children = $qb->getQuery()->getResult();
1319
        $count = count($children);
1320
        if (0 === $count) {
1321
            $params = $this->getResourceParams($request);
1322
            $params['id'] = $resourceNodeId;
1323
1324
            $this->addFlash('warning', $this->trans('No files'));
1325
1326
            return $this->redirectToRoute('chamilo_core_resource_list', $params);
1327
        }
1328
1329
        $response = new StreamedResponse(
1330
            function () use ($rootNodePath, $zipName, $children, $repo) {
1331
                // Define suitable options for ZipStream Archive.
1332
                $options = new Archive();
1333
                $options->setContentType('application/octet-stream');
1334
                //initialise zipstream with output zip filename and options.
1335
                $zip = new ZipStream($zipName, $options);
1336
1337
                /** @var ResourceNode $node */
1338
                foreach ($children as $node) {
1339
                    //$resourceFile = $node->getResourceFile();
1340
                    //$systemName = $resourceFile->getFile()->getPathname();
1341
                    $stream = $repo->getResourceNodeFileStream($node);
1342
                    //error_log($node->getPathForDisplay());
1343
                    $fileToDisplay = str_replace($rootNodePath, '', $node->getPathForDisplay());
1344
                    $zip->addFileFromStream($fileToDisplay, $stream);
1345
                }
1346
                $zip->finish();
1347
            }
1348
        );
1349
1350
        $disposition = $response->headers->makeDisposition(
1351
            ResponseHeaderBag::DISPOSITION_ATTACHMENT,
1352
            $zipName //Transliterator::transliterate($zipName)
1353
        );
1354
        $response->headers->set('Content-Disposition', $disposition);
1355
        $response->headers->set('Content-Type', 'application/octet-stream');
1356
1357
        return $response;
1358
    }
1359
1360
    /**
1361
     * Upload form.
1362
     *
1363
     * @Route("/{tool}/{type}/{id}/upload", name="chamilo_core_resource_upload", methods={"GET", "POST"},
1364
     *                                      options={"expose"=true})
1365
     */
1366
    public function uploadAction(Request $request, $tool, $type, $id): Response
1367
    {
1368
        $repository = $this->getRepositoryFromRequest($request);
1369
        $resourceNode = $repository->getResourceNodeRepository()->find($id);
1370
1371
        $this->denyAccessUnlessGranted(
1372
            ResourceNodeVoter::EDIT,
1373
            $resourceNode,
1374
            $this->trans('Unauthorised access to resource')
1375
        );
1376
1377
        $this->setBreadCrumb($request);
1378
1379
        $routeParams = $this->getResourceParams($request);
1380
        $routeParams['tool'] = $tool;
1381
        $routeParams['type'] = $type;
1382
        $routeParams['id'] = $id;
1383
1384
        return $this->render($repository->getTemplates()->getFromAction(__FUNCTION__), $routeParams);
1385
    }
1386
}
1387