1<?php
2
3declare(strict_types=1);
4
5/*
6 * This file is part of the TYPO3 CMS project.
7 *
8 * It is free software; you can redistribute it and/or modify it under
9 * the terms of the GNU General Public License, either version 2
10 * of the License, or any later version.
11 *
12 * For the full copyright and license information, please read the
13 * LICENSE.txt file that was distributed with this source code.
14 *
15 * The TYPO3 project - inspiring people to share!
16 */
17
18namespace TYPO3\CMS\Form\Mvc\Validation;
19
20use TYPO3\CMS\Core\Resource\File;
21use TYPO3\CMS\Core\Utility\GeneralUtility;
22use TYPO3\CMS\Extbase\Domain\Model\FileReference;
23use TYPO3\CMS\Extbase\Validation\Validator\AbstractValidator;
24use TYPO3\CMS\Form\Mvc\Property\TypeConverter\PseudoFile;
25use TYPO3\CMS\Form\Mvc\Validation\Exception\InvalidValidationOptionsException;
26
27/**
28 * Validator for countable types
29 *
30 * Scope: frontend
31 * @internal
32 */
33class FileSizeValidator extends AbstractValidator
34{
35    /**
36     * @var array
37     */
38    protected $supportedOptions = [
39        'minimum' => ['0B', 'The minimum file size to accept', 'string'],
40        'maximum' => [PHP_INT_MAX . 'B', 'The maximum file size to accept', 'string']
41    ];
42
43    /**
44     * The given value is valid
45     *
46     * @param FileReference|File|PseudoFile $resource
47     */
48    public function isValid($resource)
49    {
50        $this->validateOptions();
51        if ($resource instanceof FileReference) {
52            $fileSize = $resource->getOriginalResource()->getSize();
53        } elseif ($resource instanceof File) {
54            $fileSize = $resource->getSize();
55        } elseif ($resource instanceof PseudoFile) {
56            $fileSize = $resource->getSize();
57        } else {
58            $this->addError(
59                $this->translateErrorMessage(
60                    'validation.error.1505303626',
61                    'form'
62                ) ?? '',
63                1505303626
64            );
65            return;
66        }
67
68        $minFileSize = GeneralUtility::getBytesFromSizeMeasurement($this->options['minimum']);
69        $maxFileSize = GeneralUtility::getBytesFromSizeMeasurement($this->options['maximum']);
70
71        $labels = ' Bytes| Kilobyte| Megabyte| Gigabyte';
72        if ($fileSize < $minFileSize) {
73            $this->addError(
74                $this->translateErrorMessage(
75                    'validation.error.1505305752',
76                    'form',
77                    [GeneralUtility::formatSize($minFileSize, $labels)]
78                ) ?? '',
79                1505305752,
80                [GeneralUtility::formatSize($minFileSize, $labels)]
81            );
82        }
83        if ($fileSize > $maxFileSize) {
84            $this->addError(
85                $this->translateErrorMessage(
86                    'validation.error.1505305753',
87                    'form',
88                    [GeneralUtility::formatSize($maxFileSize, $labels)]
89                ) ?? '',
90                1505305753,
91                [GeneralUtility::formatSize($maxFileSize, $labels)]
92            );
93        }
94    }
95
96    /**
97     * Checks if this validator is correctly configured
98     *
99     * @throws InvalidValidationOptionsException if the configured validation options are incorrect
100     */
101    protected function validateOptions()
102    {
103        if (!preg_match('/^(\d*\.?\d+)(B|K|M|G)$/i', $this->options['minimum'])) {
104            throw new InvalidValidationOptionsException('The option "minimum" has an invalid format. Valid formats are something like this: "10B|K|M|G".', 1505304205);
105        }
106        if (!preg_match('/^(\d*\.?\d+)(B|K|M|G)$/i', $this->options['maximum'])) {
107            throw new InvalidValidationOptionsException('The option "maximum" has an invalid format. Valid formats are something like this: "10B|K|M|G".', 1505304206);
108        }
109    }
110}
111