diff --git a/core/modules/file/src/Plugin/Field/FieldType/FileItemMaxFileSizeValidator.php b/lib/Drupal/Component/Utility/BytesValidator.php similarity index 73% rename from core/modules/file/src/Plugin/Field/FieldType/FileItemMaxFileSizeValidator.php rename to lib/Drupal/Component/Utility/BytesValidator.php index 713cf743af..1b8a1826e4 100644 --- a/core/modules/file/src/Plugin/Field/FieldType/FileItemMaxFileSizeValidator.php +++ b/lib/Drupal/Component/Utility/BytesValidator.php @@ -1,15 +1,11 @@ $element['#title']]); - $form_state->setError($element, $translatable_markup); + if (!self::sizeIsValidByteString() || !self::toIntCanParseString()) { + return FALSE; } + + return TRUE; } /** @@ -63,7 +58,7 @@ class FileItemMaxFileSizeValidator { * TRUE if size is a valid byte size string, FALSE if not. */ private static function sizeIsValidByteString() { - return ( + return !( self::sizeIsNotAlphaNumeric() || self::sizeNotStartWithNumber() || self::sizeHasNumbersFollowingAlphaChar() diff --git a/core/modules/file/src/Plugin/Field/FieldType/FileItem.php b/core/modules/file/src/Plugin/Field/FieldType/FileItem.php index c2400fe564..8f6849594a 100644 --- a/core/modules/file/src/Plugin/Field/FieldType/FileItem.php +++ b/core/modules/file/src/Plugin/Field/FieldType/FileItem.php @@ -2,6 +2,7 @@ namespace Drupal\file\Plugin\Field\FieldType; +use Drupal\Component\FileSystem\BytesValidator; use Drupal\Component\Utility\Bytes; use Drupal\Component\Render\PlainTextOutput; use Drupal\Component\Utility\Environment; @@ -12,6 +13,7 @@ use Drupal\Core\Field\Plugin\Field\FieldType\EntityReferenceItem; use Drupal\Core\File\FileSystemInterface; use Drupal\Core\Form\FormStateInterface; use Drupal\Core\StreamWrapper\StreamWrapperInterface; +use Drupal\Core\StringTranslation\TranslatableMarkup; use Drupal\Core\TypedData\DataDefinition; /** @@ -181,7 +183,7 @@ class FileItem extends EntityReferenceItem { '#default_value' => $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' => [[FileItemMaxFileSizeValidator::class, 'validateMaxFilesize']], + '#element_validate' => [[get_class($this), 'validateExtensions']], '#weight' => 5, ]; @@ -237,6 +239,22 @@ class FileItem extends EntityReferenceItem { } } + /** + * Form API callback. + * + * 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 (BytesValidator::validateByteSizeString()) { + $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); + } + } + /** * Determines the URI for a file field. * 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/core/modules/file/tests/src/Unit/FileItemFieldSettingsFormTest.php b/core/modules/file/tests/src/Unit/FileItemFieldSettingsFormTest.php deleted file mode 100644 index 65de0d88dd..0000000000 --- a/core/modules/file/tests/src/Unit/FileItemFieldSettingsFormTest.php +++ /dev/null @@ -1,102 +0,0 @@ - 'Maximum upload size', - '#value' => $input, - ]; - - $form_state = $this->prophesize(FormState::class); - if ($should_error) { - $form_state->setError($element, Argument::type(TranslatableMarkup::class)) - ->shouldBeCalled(); - } - else { - $form_state->setError($element, Argument::type(TranslatableMarkup::class)) - ->shouldNotBeCalled(); - } - FileItemMaxFileSizeValidator::validateMaxFilesize($element, $form_state->reveal()); - - } - - /** - * Data provider for testValidateMaxfilesize(). - * - * @return array[] - * Array of inputs and error expectations. - */ - public function maxFileSizeInputsProvider() { - $data = [ - ['0 bytes', FALSE], - ['123456.03 ', TRUE], - [' ', FALSE], - ['', FALSE], - ['0 K', FALSE], - ['100bytes', FALSE], - ['10000', FALSE], - ['100 bytes', FALSE], - ['999989 bytes', FALSE], - ['999989bytes', FALSE], - ['2', FALSE], - ['3K', FALSE], - ['5MB', FALSE], - ['10G', FALSE], - ['6GiB', FALSE], - ['8bytes', FALSE], - ['9mbytes', FALSE], - // Should we allow these spaces? - ['1 0 0 0 0 m b y tes', FALSE], - ['nonumbers', TRUE], - ['bread', TRUE], - ['bananas', TRUE], - ['1234b1', TRUE], - ['543xd1', TRUE], - ['-1', TRUE], - ['-975', TRUE], - [' word ', TRUE], - [' word', TRUE], - ['word ', TRUE], - [' words with spaces ', TRUE], - ['words with spaces ', TRUE], - [' words with spaces', TRUE], - [' 123456 ', FALSE], - [' 123456.03 ', TRUE], - ['123456.03 ', TRUE], - [' 123456.03', TRUE], - [' some words & stuff', TRUE], - ]; - - // 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; - } - -}