diff --git a/core/lib/Drupal/Component/Utility/BytesValidator.php b/core/lib/Drupal/Component/Utility/BytesValidator.php new file mode 100644 index 0000000000..831c42213e --- /dev/null +++ b/core/lib/Drupal/Component/Utility/BytesValidator.php @@ -0,0 +1,150 @@ + $settings['max_filesize'], '#description' => t('Enter a value like "512" (bytes), "80 KB" (kilobytes) or "50 MB" (megabytes) in order to restrict the allowed file size. If left empty the file sizes will be limited only by PHP\'s maximum post and file upload sizes (current limit %limit).', ['%limit' => format_size(Environment::getUploadMaxSize())]), '#size' => 10, - '#element_validate' => [[get_class($this), 'validateMaxFilesize']], + '#element_validate' => [[get_class($this), 'validateExtensions']], '#weight' => 5, ]; @@ -197,11 +200,11 @@ class FileItem extends EntityReferenceItem { } /** - * Form API callback + * Form API callback. * * Removes slashes from the beginning and end of the destination value and - * ensures that the file directory path is not included at the beginning of the - * value. + * ensures that the file directory path is not included at the beginning of + * the value. * * This function is assigned as an #element_validate callback in * fieldSettingsForm(). @@ -220,7 +223,8 @@ class FileItem extends EntityReferenceItem { * * This doubles as a convenience clean-up function and a validation routine. * Commas are allowed by the end-user, but ultimately the value will be stored - * as a space-separated list for compatibility with file_validate_extensions(). + * as a space-separated list for compatibility with + * file_validate_extensions(). */ public static function validateExtensions($element, FormStateInterface $form_state) { if (!empty($element['#value'])) { @@ -239,15 +243,21 @@ class FileItem extends EntityReferenceItem { /** * Form API callback. * - * Ensures that a size has been entered and that it can be parsed by + * Ensures that a valid size has been entered and that it can be parsed by * \Drupal\Component\Utility\Bytes::toInt(). * * This function is assigned as an #element_validate callback in * fieldSettingsForm(). */ public static function validateMaxFilesize($element, FormStateInterface $form_state) { - if (!empty($element['#value']) && !is_numeric(Bytes::toInt($element['#value']))) { - $form_state->setError($element, t('The "@name" option must contain a valid value. You may either leave the text field empty or enter a string like "512" (bytes), "80 KB" (kilobytes) or "50 MB" (megabytes).', ['@name' => $element['title']])); +<<<<<<< HEAD + if (BytesValidator::validateByteSizeString()) { +======= + $bytes_validator = new BytesValidator(); + if ($bytes_validator->validateByteSizeString($element['#value'])) { +>>>>>>> 03191ff2c2... 870576-58.patch + $translatable_markup = new TranslatableMarkup('The "@name" option must contain a valid value. You may either leave the text field empty or enter a string like "512" (bytes), "80 KB" (kilobytes) or "50 MB" (megabytes).', ['@name' => $element['#title']]); + $form_state->setError($element, $translatable_markup); } } @@ -260,10 +270,9 @@ class FileItem extends EntityReferenceItem { * @return string * An unsanitized file directory URI with tokens replaced. The result of * the token replacement is then converted to plain text and returned. - * * @see \Drupal\Core\Utility\Token::replace() */ - public function getUploadLocation($data = []) { + public function getUploadLocation(array $data = []) { return static::doGetUploadLocation($this->getSettings(), $data); } @@ -281,7 +290,7 @@ class FileItem extends EntityReferenceItem { * * @see \Drupal\Core\Utility\Token::replace() */ - protected static function doGetUploadLocation(array $settings, $data = []) { + protected static function doGetUploadLocation(array $settings, array $data = []) { $destination = trim($settings['file_directory'], '/'); // Replace tokens. As the tokens might contain HTML we convert it to plain diff --git a/core/modules/file/tests/src/Unit/BytesValidatorTest.php b/core/modules/file/tests/src/Unit/BytesValidatorTest.php new file mode 100644 index 0000000000..f03b0c15a0 --- /dev/null +++ b/core/modules/file/tests/src/Unit/BytesValidatorTest.php @@ -0,0 +1,85 @@ +assertEquals($expected, $result); + } + + /** + * Data provider for testValidateMaxfilesize(). + * + * @return array[] + * Array of inputs and error expectations. + */ + public function maxFileSizeInputsProvider() { + $data = [ + ['0 bytes', TRUE], + [' ', TRUE], + ['', TRUE], + ['0 K', TRUE], + ['100bytes', TRUE], + ['10000', TRUE], + ['100 bytes', TRUE], + ['999989 bytes', TRUE], + ['999989bytes', TRUE], + ['2', TRUE], + ['3K', TRUE], + ['5MB', TRUE], + ['10G', TRUE], + ['6GiB', TRUE], + ['8bytes', TRUE], + ['9mbytes', TRUE], + // Should we allow these spaces? + ['1 0 0 0 0 m b y tes', TRUE], + [' 123456 ', TRUE], + + ['123456.03 ', FALSE], + ['nonumbers', FALSE], + ['bread', FALSE], + ['bananas', FALSE], + ['1234b1', FALSE], + ['543xd1', FALSE], + ['-1', FALSE], + ['-975', FALSE], + [' word ', FALSE], + [' word', FALSE], + ['word ', FALSE], + [' words with spaces ', FALSE], + ['words with spaces ', FALSE], + [' words with spaces', FALSE], + [' 123456.03 ', FALSE], + ['123456.03 ', FALSE], + [' 123456.03', FALSE], + [' some words & stuff', FALSE], + ]; + + // Improve test output by using the input value as a label for the dataset. + foreach ($data as $index => $item) { + // If the index looks like an in eg "1000" "2" etc, php still detects + // it as a numeric index. Adding text to all the labels to force them + // to render. + $data["Sample input: '{$item[0]}'"] = $item; + unset($data[$index]); + } + + return $data; + } + +} diff --git a/tests/Drupal/Tests/Component/Utility/BytesTest.php b/tests/Drupal/Tests/Component/Utility/BytesTest.php deleted file mode 100644 index 72485ea802..0000000000 --- a/tests/Drupal/Tests/Component/Utility/BytesTest.php +++ /dev/null @@ -1,62 +0,0 @@ -assertEquals($expected_int, Bytes::toInt($size)); - } - - /** - * Provides data for testToInt. - * - * @return array - * An array of arrays, each containing the argument for - * \Drupal\Component\Utility\Bytes::toInt(): size, and the expected return - * value. - */ - public function providerTestToInt() { - return [ - ['1', 1], - ['1 byte', 1], - ['1 KB' , Bytes::KILOBYTE], - ['1 MB' , pow(Bytes::KILOBYTE, 2)], - ['1 GB' , pow(Bytes::KILOBYTE, 3)], - ['1 TB' , pow(Bytes::KILOBYTE, 4)], - ['1 PB' , pow(Bytes::KILOBYTE, 5)], - ['1 EB' , pow(Bytes::KILOBYTE, 6)], - ['1 ZB' , pow(Bytes::KILOBYTE, 7)], - ['1 YB' , pow(Bytes::KILOBYTE, 8)], - ['23476892 bytes', 23476892], - // 76 MB. - ['76MRandomStringThatShouldBeIgnoredByParseSize.', 79691776], - // 76.24 GB (with typo). - ['76.24 Giggabyte', 81862076662], - ]; - } - -}