Completed
Pull Request — master (#1916)
by Gilles
16:37 queued 03:48
created

FileController::processImage()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 12
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 1 Features 0
Metric Value
c 1
b 1
f 0
dl 0
loc 12
rs 9.4285
cc 1
eloc 9
nc 1
nop 6
1
<?php
2
/*************************************************************************************/
3
/*      This file is part of the Thelia package.                                     */
4
/*                                                                                   */
5
/*      Copyright (c) OpenStudio                                                     */
6
/*      email : [email protected]                                                       */
7
/*      web : http://www.thelia.net                                                  */
8
/*                                                                                   */
9
/*      For the full copyright and license information, please view the LICENSE.txt  */
10
/*      file that was distributed with this source code.                             */
11
/*************************************************************************************/
12
13
namespace Thelia\Controller\Admin;
14
15
use Propel\Runtime\Exception\PropelException;
16
use Symfony\Component\HttpFoundation\File\UploadedFile;
17
use Thelia\Core\Event\File\FileCreateOrUpdateEvent;
18
use Thelia\Core\Event\File\FileDeleteEvent;
19
use Thelia\Core\Event\File\FileToggleVisibilityEvent;
20
use Thelia\Core\Event\TheliaEvents;
21
use Thelia\Core\Event\UpdateFilePositionEvent;
22
use Thelia\Core\HttpFoundation\Response;
23
use Thelia\Core\Security\AccessManager;
24
use Thelia\Core\Security\Resource\AdminResources;
25
use Thelia\Files\Exception\ProcessFileException;
26
use Thelia\Files\FileConfiguration;
27
use Thelia\Files\FileManager;
28
use Thelia\Files\FileModelInterface;
29
use Thelia\Form\Exception\FormValidationException;
30
use Thelia\Log\Tlog;
31
use Thelia\Model\Lang;
32
use Thelia\Tools\Rest\ResponseRest;
33
use Thelia\Tools\URL;
34
35
/**
36
 * Created by JetBrains PhpStorm.
37
 * Date: 8/19/13
38
 * Time: 3:24 PM
39
 *
40
 * Control View and Action (Model) via Events
41
 * Control Files and Images
42
 *
43
 * @package File
44
 * @author  Guillaume MOREL <[email protected]>
45
 *
46
 */
47
class FileController extends BaseAdminController
48
{
49
    /**
50
     * Get the FileManager
51
     *
52
     * @return FileManager
53
     */
54
    public function getFileManager()
55
    {
56
        return $this->container->get('thelia.file_manager');
57
    }
58
59
    /**
60
     * Manage how a file collection has to be saved
61
     *
62
     * @param  int      $parentId       Parent id owning files being saved
63
     * @param  string   $parentType     Parent Type owning files being saved (product, category, content, etc.)
64
     * @param  string   $objectType     Object type, e.g. image or document
65
     * @param  array    $validMimeTypes an array of valid mime types. If empty, any mime type is allowed.
66
     * @param  array    $extBlackList   an array of blacklisted extensions.
67
     * @return Response
68
     */
69
    public function saveFileAjaxAction(
70
        $parentId,
71
        $parentType,
72
        $objectType,
73
        $validMimeTypes = array(),
74
        $extBlackList = array()
75
    ) {
76
        if (null !== $response = $this->checkAuth(AdminResources::retrieve($parentType), array(), AccessManager::UPDATE)) {
77
            return $response;
78
        }
79
80
        $this->checkXmlHttpRequest();
81
82
83
        if ($this->getRequest()->isMethod('POST')) {
84
            /** @var UploadedFile $fileBeingUploaded */
85
            $fileBeingUploaded = $this->getRequest()->files->get('file');
86
            try {
87
                $this->processFile(
88
                    $fileBeingUploaded,
89
                    $parentId,
90
                    $parentType,
91
                    $objectType,
92
                    $validMimeTypes,
93
                    $extBlackList
94
                );
95
            } catch (ProcessFileException $e) {
96
                return new ResponseRest($e->getMessage(), 'text', $e->getCode());
0 ignored issues
show
Documentation introduced by
$e->getMessage() is of type string, but the function expects a array|null.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
97
            }
98
99
            return new ResponseRest(array('status' => true, 'message' => ''));
100
        }
101
102
        return new Response('', 404);
103
    }
104
105
    /**
106
     * Process file uploaded
107
     *
108
     * @param UploadedFile $fileBeingUploaded
109
     * @param int $parentId
110
     * @param string $parentType
111
     * @param string $objectType
112
     * @param array $validMimeTypes
113
     * @param array $extBlackList
114
     * @return ResponseRest
115
     *
116
     * @deprecated since version 2.3, to be removed in 2.6. Please use the process method File present in the same class.
117
     */
118
    public function processImage(
119
        $fileBeingUploaded,
120
        $parentId,
121
        $parentType,
122
        $objectType,
123
        $validMimeTypes = array(),
124
        $extBlackList = array()
125
    ) {
126
        @trigger_error('The '.__METHOD__.' method is deprecated since version 2.3 and will be removed in 2.6. Please use the process method File present in the same class.', E_USER_DEPRECATED);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
127
128
        return $this->processFile($fileBeingUploaded, $parentId, $parentType, $objectType, $validMimeTypes, $extBlackList);
129
    }
130
131
    /**
132
     * Process file uploaded
133
     *
134
     * @param UploadedFile $fileBeingUploaded
135
     * @param  int      $parentId       Parent id owning files being saved
136
     * @param  string   $parentType     Parent Type owning files being saved (product, category, content, etc.)
137
     * @param  string   $objectType     Object type, e.g. image or document
138
     * @param  array    $validMimeTypes an array of valid mime types. If empty, any mime type is allowed.
139
     * @param  array    $extBlackList   an array of blacklisted extensions.
140
     * @return ResponseRest
141
     *
142
     * @since 2.3
143
     */
144
    public function processFile(
145
        $fileBeingUploaded,
146
        $parentId,
147
        $parentType,
148
        $objectType,
149
        $validMimeTypes = array(),
150
        $extBlackList = array()
151
    ) {
152
        $fileManager = $this->getFileManager();
153
154
        // Validate if file is too big
155
        if ($fileBeingUploaded->getError() == 1) {
156
            $message = $this->getTranslator()
157
                ->trans(
158
                    'File is too large, please retry with a file having a size less than %size%.',
159
                    array('%size%' => ini_get('upload_max_filesize')),
160
                    'core'
161
                );
162
163
            throw new ProcessFileException($message, 403);
164
        }
165
166
        $message = null;
167
        $realFileName = $fileBeingUploaded->getClientOriginalName();
168
169
        if (! empty($validMimeTypes)) {
170
            $mimeType = $fileBeingUploaded->getMimeType();
171
172
            if (!isset($validMimeTypes[$mimeType])) {
173
                $message = $this->getTranslator()
174
                    ->trans(
175
                        'Only files having the following mime type are allowed: %types%',
176
                        [ '%types%' => implode(', ', array_keys($validMimeTypes))]
177
                    );
178
            } else {
179
                $regex = "#^(.+)\.(".implode("|", $validMimeTypes[$mimeType]).")$#i";
180
181
                if (!preg_match($regex, $realFileName)) {
182
                    $message = $this->getTranslator()
183
                        ->trans(
184
                            "There's a conflict between your file extension \"%ext\" and the mime type \"%mime\"",
185
                            [
186
                                '%mime' => $mimeType,
187
                                '%ext' => $fileBeingUploaded->getClientOriginalExtension()
188
                            ]
189
                        );
190
                }
191
            }
192
        }
193
194
        if (!empty($extBlackList)) {
195
            $regex = "#^(.+)\.(".implode("|", $extBlackList).")$#i";
196
197
            if (preg_match($regex, $realFileName)) {
198
                $message = $this->getTranslator()
199
                    ->trans(
200
                        'Files with the following extension are not allowed: %extension, please do an archive of the file if you want to upload it',
201
                        [
202
                            '%extension' => $fileBeingUploaded->getClientOriginalExtension(),
203
                        ]
204
                    );
205
            }
206
        }
207
208
        if ($message !== null) {
209
            throw new ProcessFileException($message, 415);
210
        }
211
212
        $fileModel = $fileManager->getModelInstance($objectType, $parentType);
213
214
        $parentModel = $fileModel->getParentFileModel();
215
216
        if ($parentModel === null || $fileModel === null || $fileBeingUploaded === null) {
217
            throw new ProcessFileException('', 404);
218
        }
219
220
        $defaultTitle = $parentModel->getTitle();
221
222
        if (empty($defaultTitle) && $objectType !== 'image') {
223
            $defaultTitle = $fileBeingUploaded->getClientOriginalName();
224
        }
225
226
        $fileModel
227
            ->setParentId($parentId)
228
            ->setLocale(Lang::getDefaultLanguage()->getLocale())
229
            ->setTitle($defaultTitle)
230
        ;
231
232
        $fileCreateOrUpdateEvent = new FileCreateOrUpdateEvent($parentId);
233
        $fileCreateOrUpdateEvent->setModel($fileModel);
234
        $fileCreateOrUpdateEvent->setUploadedFile($fileBeingUploaded);
235
        $fileCreateOrUpdateEvent->setParentName($parentModel->getTitle());
236
237
        // Dispatch Event to the Action
238
        $this->dispatch(
239
            TheliaEvents::IMAGE_SAVE,
240
            $fileCreateOrUpdateEvent
241
        );
242
243
        $this->adminLogAppend(
244
            AdminResources::retrieve($parentType),
245
            AccessManager::UPDATE,
246
            $this->getTranslator()->trans(
247
                'Saving %obj% for %parentName% parent id %parentId%',
248
                array(
249
                    '%parentName%' => $fileCreateOrUpdateEvent->getParentName(),
250
                    '%parentId%' => $fileCreateOrUpdateEvent->getParentId(),
251
                    '%obj%' => $objectType
252
                )
253
            )
254
        );
255
256
        //return new ResponseRest(array('status' => true, 'message' => ''));
0 ignored issues
show
Unused Code Comprehensibility introduced by
61% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
257
        return $fileCreateOrUpdateEvent;
258
    }
259
260
    /**
261
     * Manage how a image collection has to be saved
262
     *
263
     * @param int    $parentId   Parent id owning images being saved
264
     * @param string $parentType Parent Type owning images being saved
265
     *
266
     * @return Response
267
     */
268
    public function saveImageAjaxAction($parentId, $parentType)
269
    {
270
        $config = FileConfiguration::getImageConfig();
271
        return $this->saveFileAjaxAction(
272
            $parentId,
273
            $parentType,
274
            $config['objectType'],
275
            $config['validMimeTypes'],
276
            $config['extBlackList']
277
        );
278
    }
279
280
    /**
281
     * Manage how a document collection has to be saved
282
     *
283
     * @param int    $parentId   Parent id owning documents being saved
284
     * @param string $parentType Parent Type owning documents being saved
285
     *
286
     * @return Response
287
     */
288
    public function saveDocumentAjaxAction($parentId, $parentType)
289
    {
290
        $config = FileConfiguration::getDocumentConfig();
291
        return $this->saveFileAjaxAction(
292
            $parentId,
293
            $parentType,
294
            $config['objectType'],
295
            $config['validMimeTypes'],
296
            $config['extBlackList']
297
        );
298
    }
299
300
    /**
301
     * Manage how a image list will be displayed in AJAX
302
     *
303
     * @param int    $parentId   Parent id owning images being saved
304
     * @param string $parentType Parent Type owning images being saved
305
     *
306
     * @return Response
307
     */
308
    public function getImageListAjaxAction($parentId, $parentType)
309
    {
310
        $this->checkAuth(AdminResources::retrieve($parentType), array(), AccessManager::UPDATE);
311
        $this->checkXmlHttpRequest();
312
        $args = array('imageType' => $parentType, 'parentId' => $parentId);
313
314
        return $this->render('includes/image-upload-list-ajax', $args);
315
    }
316
317
    /**
318
     * Manage how a document list will be displayed in AJAX
319
     *
320
     * @param int    $parentId   Parent id owning documents being saved
321
     * @param string $parentType Parent Type owning documents being saved
322
     *
323
     * @return Response
324
     */
325
    public function getDocumentListAjaxAction($parentId, $parentType)
326
    {
327
        $this->checkAuth(AdminResources::retrieve($parentType), array(), AccessManager::UPDATE);
328
        $this->checkXmlHttpRequest();
329
        $args = array('documentType' => $parentType, 'parentId' => $parentId);
330
331
        return $this->render('includes/document-upload-list-ajax', $args);
332
    }
333
334
    /**
335
     * Manage how an image list will be uploaded in AJAX
336
     *
337
     * @param int    $parentId   Parent id owning images being saved
338
     * @param string $parentType Parent Type owning images being saved
339
     *
340
     * @return Response
341
     */
342
    public function getImageFormAjaxAction($parentId, $parentType)
343
    {
344
        $this->checkAuth(AdminResources::retrieve($parentType), array(), AccessManager::UPDATE);
345
        $this->checkXmlHttpRequest();
346
        $args = array('imageType' => $parentType, 'parentId' => $parentId);
347
348
        return $this->render('includes/image-upload-form', $args);
349
    }
350
351
    /**
352
     * Manage how an document list will be uploaded in AJAX
353
     *
354
     * @param int    $parentId   Parent id owning documents being saved
355
     * @param string $parentType Parent Type owning documents being saved
356
     *
357
     * @return Response
358
     */
359
    public function getDocumentFormAjaxAction($parentId, $parentType)
360
    {
361
        $this->checkAuth(AdminResources::retrieve($parentType), array(), AccessManager::UPDATE);
362
        $this->checkXmlHttpRequest();
363
        $args = array('documentType' => $parentType, 'parentId' => $parentId);
364
365
        return $this->render('includes/document-upload-form', $args);
366
    }
367
368
    /**
369
     * Manage how an image is viewed
370
     *
371
     * @param int    $imageId    Parent id owning images being saved
372
     * @param string $parentType Parent Type owning images being saved
373
     *
374
     * @return Response
375
     */
376
    public function viewImageAction($imageId, $parentType)
377
    {
378
        if (null !== $response = $this->checkAuth(AdminResources::retrieve($parentType), array(), AccessManager::UPDATE)) {
379
            return $response;
380
        }
381
        $fileManager = $this->getFileManager();
382
        $imageModel = $fileManager->getModelInstance('image', $parentType);
383
384
        $image = $imageModel->getQueryInstance()->findPk($imageId);
385
386
        $redirectUrl = $image->getRedirectionUrl();
387
388
        return $this->render('image-edit', array(
389
            'imageId' => $imageId,
390
            'imageType' => $parentType,
391
            'redirectUrl' => $redirectUrl,
392
            'formId' => $imageModel->getUpdateFormId(),
393
            'breadcrumb' => $image->getBreadcrumb(
394
                $this->getRouter($this->getCurrentRouter()),
395
                $this->container,
396
                'images',
397
                $this->getCurrentEditionLocale()
398
            )
399
        ));
400
    }
401
402
    /**
403
     * Manage how an document is viewed
404
     *
405
     * @param int    $documentId Parent id owning images being saved
406
     * @param string $parentType Parent Type owning images being saved
407
     *
408
     * @return Response
409
     */
410
    public function viewDocumentAction($documentId, $parentType)
411
    {
412
        if (null !== $response = $this->checkAuth(AdminResources::retrieve($parentType), array(), AccessManager::UPDATE)) {
413
            return $response;
414
        }
415
416
        $fileManager = $this->getFileManager();
417
        $documentModel = $fileManager->getModelInstance('document', $parentType);
418
419
        $document = $documentModel->getQueryInstance()->findPk($documentId);
420
421
        $redirectUrl = $document->getRedirectionUrl();
422
423
        return $this->render('document-edit', array(
424
            'documentId' => $documentId,
425
            'documentType' => $parentType,
426
            'redirectUrl' => $redirectUrl,
427
            'formId' => $documentModel->getUpdateFormId(),
428
            'breadcrumb' => $document->getBreadcrumb(
429
                $this->getRouter($this->getCurrentRouter()),
430
                $this->container,
431
                'documents',
432
                $this->getCurrentEditionLocale()
433
            )
434
        ));
435
    }
436
437
    /**
438
     * Manage how a file is updated
439
     *
440
     * @param int    $fileId     File identifier
441
     * @param string $parentType Parent Type owning file being saved
442
     * @param string $objectType the type of the file, image or document
443
     * @param string $eventName  the event type.
444
     *
445
     * @return FileModelInterface
446
     */
447
    protected function updateFileAction($fileId, $parentType, $objectType, $eventName)
448
    {
449
        $message = false;
0 ignored issues
show
Unused Code introduced by
$message is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
450
451
        $fileManager = $this->getFileManager();
452
453
        $fileModelInstance = $fileManager->getModelInstance($objectType, $parentType);
454
455
        $fileUpdateForm = $this->createForm($fileModelInstance->getUpdateFormId());
456
457
        /** @var FileModelInterface $file */
458
        $file = $fileModelInstance->getQueryInstance()->findPk($fileId);
459
460
        try {
461
            $oldFile = clone $file;
462
463
            if (null === $file) {
464
                throw new \InvalidArgumentException(sprintf('%d %s id does not exist', $fileId, $objectType));
465
            }
466
467
            $data = $this->validateForm($fileUpdateForm)->getData();
468
469
            $event = new FileCreateOrUpdateEvent(null);
470
471
            if (array_key_exists('visible', $data)) {
472
                $file->setVisible($data['visible'] ? 1 : 0);
0 ignored issues
show
Documentation introduced by
$data['visible'] ? 1 : 0 is of type integer, but the function expects a boolean.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
473
            }
474
475
            $file->setLocale($data['locale']);
476
477
            if (array_key_exists('title', $data)) {
478
                $file->setTitle($data['title']);
479
            }
480
            if (array_key_exists('chapo', $data)) {
481
                $file->setChapo($data['chapo']);
482
            }
483
            if (array_key_exists('description', $data)) {
484
                $file->setDescription($data['description']);
485
            }
486
            if (array_key_exists('postscriptum', $data)) {
487
                $file->setPostscriptum($data['postscriptum']);
488
            }
489
490
            if (isset($data['file'])) {
491
                $file->setFile($data['file']);
492
            }
493
494
            $event->setModel($file);
495
            $event->setOldModel($oldFile);
496
497
            $files = $this->getRequest()->files;
498
499
            $fileForm = $files->get($fileUpdateForm->getName());
500
501
            if (isset($fileForm['file'])) {
502
                $event->setUploadedFile($fileForm['file']);
503
            }
504
505
            $this->dispatch($eventName, $event);
506
507
            $fileUpdated = $event->getModel();
508
509
            $this->adminLogAppend(
510
                AdminResources::retrieve($parentType),
511
                AccessManager::UPDATE,
512
                sprintf(
513
                    '%s with Ref %s (ID %d) modified',
514
                    ucfirst($objectType),
515
                    $fileUpdated->getTitle(),
516
                    $fileUpdated->getId()
517
                ),
518
                $fileUpdated->getId()
519
            );
520
521
            if ($this->getRequest()->get('save_mode') == 'close') {
522
                if ($objectType == 'document') {
523
                    $tab = 'documents';
524
                } else {
525
                    $tab = 'images';
526
                }
527
528
                return $this->generateRedirect(
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $this->generateRe...urrent_tab' => $tab))); (Symfony\Component\HttpFoundation\RedirectResponse) is incompatible with the return type documented by Thelia\Controller\Admin\...oller::updateFileAction of type Thelia\Files\FileModelInterface|null.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
529
                    URL::getInstance()->absoluteUrl($file->getRedirectionUrl(), ['current_tab' => $tab])
530
                );
531
            } else {
532
                return $this->generateSuccessRedirect($fileUpdateForm);
0 ignored issues
show
Bug Compatibility introduced by
The expression $this->generateSuccessRedirect($fileUpdateForm); of type Symfony\Component\HttpFo...n\RedirectResponse|null adds the type Symfony\Component\HttpFoundation\RedirectResponse to the return on line 532 which is incompatible with the return type documented by Thelia\Controller\Admin\...oller::updateFileAction of type Thelia\Files\FileModelInterface|null.
Loading history...
533
            }
534
        } catch (FormValidationException $e) {
535
            $message = sprintf('Please check your input: %s', $e->getMessage());
536
        } catch (PropelException $e) {
537
            $message = $e->getMessage();
538
        } catch (\Exception $e) {
539
            $message = sprintf('Sorry, an error occurred: %s', $e->getMessage().' '.$e->getFile());
540
        }
541
542
        if ($message !== false) {
543
            Tlog::getInstance()->error(sprintf('Error during %s editing : %s.', $objectType, $message));
544
545
            $fileUpdateForm->setErrorMessage($message);
546
547
            $this->getParserContext()
548
                ->addForm($fileUpdateForm)
549
                ->setGeneralError($message);
550
        }
551
552
        return $file;
553
    }
554
555
    /**
556
     * Manage how an image is updated
557
     *
558
     * @param int    $imageId    Parent id owning images being saved
559
     * @param string $parentType Parent Type owning images being saved
560
     *
561
     * @return Response
562
     */
563
    public function updateImageAction($imageId, $parentType)
564
    {
565
        if (null !== $response = $this->checkAuth(AdminResources::retrieve($parentType), array(), AccessManager::UPDATE)) {
566
            return $response;
567
        }
568
569
        $imageInstance = $this->updateFileAction($imageId, $parentType, 'image', TheliaEvents::IMAGE_UPDATE);
570
571
        if ($imageInstance instanceof \Symfony\Component\HttpFoundation\Response) {
572
            return $imageInstance;
573
        } else {
574
            return $this->render('image-edit', array(
575
                'imageId' => $imageId,
576
                'imageType' => $parentType,
577
                'redirectUrl' => $imageInstance->getRedirectionUrl(),
578
                'formId' => $imageInstance->getUpdateFormId()
579
            ));
580
        }
581
    }
582
583
    /**
584
     * Manage how an document is updated
585
     *
586
     * @param int    $documentId Parent id owning documents being saved
587
     * @param string $parentType Parent Type owning documents being saved
588
     *
589
     * @return Response
590
     */
591
    public function updateDocumentAction($documentId, $parentType)
592
    {
593
        if (null !== $response = $this->checkAuth(AdminResources::retrieve($parentType), array(), AccessManager::UPDATE)) {
594
            return $response;
595
        }
596
597
        $documentInstance = $this->updateFileAction($documentId, $parentType, 'document', TheliaEvents::DOCUMENT_UPDATE);
598
599
        if ($documentInstance instanceof \Symfony\Component\HttpFoundation\Response) {
600
            return $documentInstance;
601
        } else {
602
            return $this->render('document-edit', array(
603
                'documentId' => $documentId,
604
                'documentType' => $parentType,
605
                'redirectUrl' => $documentInstance->getRedirectionUrl(),
606
                'formId' => $documentInstance->getUpdateFormId()
607
            ));
608
        }
609
    }
610
611
    /**
612
     * Manage how a file has to be deleted
613
     *
614
     * @param int    $fileId     Parent id owning file being deleted
615
     * @param string $parentType Parent Type owning file being deleted
616
     * @param string $objectType the type of the file, image or document
617
     * @param string $eventName  the event type.
618
     *
619
     * @return Response
620
     */
621
    public function deleteFileAction($fileId, $parentType, $objectType, $eventName)
622
    {
623
        $message = null;
624
625
        $this->checkAuth(AdminResources::retrieve($parentType), array(), AccessManager::UPDATE);
626
        $this->checkXmlHttpRequest();
627
628
        $fileManager = $this->getFileManager();
629
        $modelInstance = $fileManager->getModelInstance($objectType, $parentType);
630
631
        $model = $modelInstance->getQueryInstance()->findPk($fileId);
632
633
        if ($model == null) {
634
            return $this->pageNotFound();
635
        }
636
637
        // Feed event
638
        $fileDeleteEvent = new FileDeleteEvent($model);
639
640
        // Dispatch Event to the Action
641
        try {
642
            $this->dispatch($eventName, $fileDeleteEvent);
643
644
            $this->adminLogAppend(
645
                AdminResources::retrieve($parentType),
646
                AccessManager::UPDATE,
647
                $this->getTranslator()->trans(
648
                    'Deleting %obj% for %id% with parent id %parentId%',
649
                    array(
650
                        '%obj%' => $objectType,
651
                        '%id%' => $fileDeleteEvent->getFileToDelete()->getId(),
652
                        '%parentId%' => $fileDeleteEvent->getFileToDelete()->getParentId(),
653
                    )
654
                ),
655
                $fileDeleteEvent->getFileToDelete()->getId()
656
            );
657
        } catch (\Exception $e) {
658
            $message = $this->getTranslator()->trans(
659
                'Fail to delete  %obj% for %id% with parent id %parentId% (Exception : %e%)',
660
                array(
661
                    '%obj%' => $objectType,
662
                    '%id%' => $fileDeleteEvent->getFileToDelete()->getId(),
663
                    '%parentId%' => $fileDeleteEvent->getFileToDelete()->getParentId(),
664
                    '%e%' => $e->getMessage()
665
                )
666
            );
667
668
            $this->adminLogAppend(
669
                AdminResources::retrieve($parentType),
670
                AccessManager::UPDATE,
671
                $message,
672
                $fileDeleteEvent->getFileToDelete()->getId()
673
            );
674
        }
675
676
        if (null === $message) {
677
            $message = $this->getTranslator()->trans(
678
                '%obj%s deleted successfully',
679
                ['%obj%' => ucfirst($objectType)],
680
                'image'
681
            );
682
        }
683
684
        return new Response($message);
685
    }
686
687
    /**
688
     * Manage how an image has to be deleted (AJAX)
689
     *
690
     * @param int    $imageId    Parent id owning image being deleted
691
     * @param string $parentType Parent Type owning image being deleted
692
     *
693
     * @return Response
694
     */
695
    public function deleteImageAction($imageId, $parentType)
696
    {
697
        return $this->deleteFileAction($imageId, $parentType, 'image', TheliaEvents::IMAGE_DELETE);
698
    }
699
700
    /**
701
     * Manage how a document has to be deleted (AJAX)
702
     *
703
     * @param int    $documentId Parent id owning document being deleted
704
     * @param string $parentType Parent Type owning document being deleted
705
     *
706
     * @return Response
707
     */
708
    public function deleteDocumentAction($documentId, $parentType)
709
    {
710
        return $this->deleteFileAction($documentId, $parentType, 'document', TheliaEvents::DOCUMENT_DELETE);
711
    }
712
713
    public function updateFilePositionAction($parentType, $parentId, $objectType, $eventName)
714
    {
715
        $message = null;
716
717
        $position = $this->getRequest()->request->get('position');
718
719
        $this->checkAuth(AdminResources::retrieve($parentType), array(), AccessManager::UPDATE);
720
        $this->checkXmlHttpRequest();
721
722
        $fileManager = $this->getFileManager();
723
        $modelInstance = $fileManager->getModelInstance($objectType, $parentType);
724
        $model = $modelInstance->getQueryInstance()->findPk($parentId);
725
726
        if ($model === null || $position === null) {
727
            return $this->pageNotFound();
728
        }
729
730
        // Feed event
731
        $event = new UpdateFilePositionEvent(
732
            $modelInstance->getQueryInstance($parentType),
0 ignored issues
show
Unused Code introduced by
The call to FileModelInterface::getQueryInstance() has too many arguments starting with $parentType.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
733
            $parentId,
734
            UpdateFilePositionEvent::POSITION_ABSOLUTE,
735
            $position
736
        );
737
738
        // Dispatch Event to the Action
739
        try {
740
            $this->dispatch($eventName, $event);
741
        } catch (\Exception $e) {
742
            $message = $this->getTranslator()->trans(
743
                'Fail to update %type% position: %err%',
744
                [ '%type%' => $objectType, '%err%' => $e->getMessage() ]
745
            );
746
        }
747
748
        if (null === $message) {
749
            $message = $this->getTranslator()->trans(
750
                '%type% position updated',
751
                [ '%type%' => ucfirst($objectType) ]
752
            );
753
        }
754
755
        return new Response($message);
756
    }
757
758
    public function updateImagePositionAction($parentType, /** @noinspection PhpUnusedParameterInspection */  $parentId)
0 ignored issues
show
Unused Code introduced by
The parameter $parentId is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
759
    {
760
        $imageId = $this->getRequest()->request->get('image_id');
761
762
        return $this->updateFilePositionAction($parentType, $imageId, 'image', TheliaEvents::IMAGE_UPDATE_POSITION);
763
    }
764
765
    public function updateDocumentPositionAction($parentType, /** @noinspection PhpUnusedParameterInspection */  $parentId)
0 ignored issues
show
Unused Code introduced by
The parameter $parentId is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
766
    {
767
        $documentId = $this->getRequest()->request->get('document_id');
768
769
        return $this->updateFilePositionAction($parentType, $documentId, 'document', TheliaEvents::DOCUMENT_UPDATE_POSITION);
770
    }
771
772
    public function toggleVisibilityFileAction($documentId, $parentType, $objectType, $eventName)
773
    {
774
        $message = null;
775
776
        //$position = $this->getRequest()->request->get('position');
0 ignored issues
show
Unused Code Comprehensibility introduced by
65% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
777
778
        $this->checkAuth(AdminResources::retrieve($parentType), array(), AccessManager::UPDATE);
779
        $this->checkXmlHttpRequest();
780
781
        $fileManager = $this->getFileManager();
782
        $modelInstance = $fileManager->getModelInstance($objectType, $parentType);
783
784
        $model = $modelInstance->getQueryInstance()->findPk($documentId);
785
786
        if ($model === null) {
787
            return $this->pageNotFound();
788
        }
789
790
        // Feed event
791
        $event = new FileToggleVisibilityEvent(
792
            $modelInstance->getQueryInstance(),
793
            $documentId
794
        );
795
796
        // Dispatch Event to the Action
797
        try {
798
            $this->dispatch($eventName, $event);
799
        } catch (\Exception $e) {
800
            $message = $this->getTranslator()->trans(
801
                'Fail to update %type% visibility: %err%',
802
                [ '%type%' => $objectType, '%err%' => $e->getMessage() ]
803
            );
804
        }
805
806
        if (null === $message) {
807
            $message = $this->getTranslator()->trans(
808
                '%type% visibility updated',
809
                [ '%type%' => ucfirst($objectType) ]
810
            );
811
        }
812
813
        return new Response($message);
814
    }
815
816
    public function toggleVisibilityDocumentAction($parentType, $documentId)
817
    {
818
        return $this->toggleVisibilityFileAction($documentId, $parentType, 'document', TheliaEvents::DOCUMENT_TOGGLE_VISIBILITY);
819
    }
820
821
    public function toggleVisibilityImageAction($parentType, $documentId)
822
    {
823
        return $this->toggleVisibilityFileAction($documentId, $parentType, 'image', TheliaEvents::IMAGE_TOGGLE_VISIBILITY);
824
    }
825
}
826