Skip to content
Snippets Groups Projects
Verified Commit 2ceafd06 authored by Lauri Timmanee's avatar Lauri Timmanee
Browse files

Issue #3052663 by joaopauloc.dev, smustgrave, quietone, Balu Ertl, xjm,...

Issue #3052663 by joaopauloc.dev, smustgrave, quietone, Balu Ertl, xjm, scottsperry: Validate the min, max and default values for Numeric fields
parent d582b8c5
No related branches found
No related tags found
40 merge requests!8528Issue #3456871 by Tim Bozeman: Support NULL services,!8323Fix source code editing and in place front page site studio editing.,!6278Issue #3187770 by godotislate, smustgrave, catch, quietone: Views Rendered...,!54479.5.x SF update,!3878Removed unused condition head title for views,!38582585169-10.1.x,!3818Issue #2140179: $entity->original gets stale between updates,!3742Issue #3328429: Create item list field formatter for displaying ordered and unordered lists,!3731Claro: role=button on status report items,!3668Resolve #3347842 "Deprecate the trusted",!3651Issue #3347736: Create new SDC component for Olivero (header-search),!3546refactored dialog.pcss file,!3531Issue #3336994: StringFormatter always displays links to entity even if the user in context does not have access,!3502Issue #3335308: Confusing behavior with FormState::setFormState and FormState::setMethod,!3452Issue #3332701: Refactor Claro's tablesort-indicator stylesheet,!3451Issue #2410579: Allows setting the current language programmatically.,!3355Issue #3209129: Scrolling problems when adding a block via layout builder,!3226Issue #2987537: Custom menu link entity type should not declare "bundle" entity key,!3154Fixes #2987987 - CSRF token validation broken on routes with optional parameters.,!3147Issue #3328457: Replace most substr($a, $i) where $i is negative with str_ends_with(),!3146Issue #3328456: Replace substr($a, 0, $i) with str_starts_with(),!3133core/modules/system/css/components/hidden.module.css,!31312878513-10.1.x,!2964Issue #2865710 : Dependencies from only one instance of a widget are used in display modes,!2812Issue #3312049: [Followup] Fix Drupal.Commenting.FunctionComment.MissingReturnType returns for NULL,!2614Issue #2981326: Replace non-test usages of \Drupal::logger() with IoC injection,!2378Issue #2875033: Optimize joins and table selection in SQL entity query implementation,!2334Issue #3228209: Add hasRole() method to AccountInterface,!2062Issue #3246454: Add weekly granularity to views date sort,!1255Issue #3238922: Refactor (if feasible) uses of the jQuery serialize function to use vanillaJS,!1105Issue #3025039: New non translatable field on translatable content throws error,!1073issue #3191727: Focus states on mobile second level navigation items fixed,!10223132456: Fix issue where views instances are emptied before an ajax request is complete,!877Issue #2708101: Default value for link text is not saved,!844Resolve #3036010 "Updaters",!673Issue #3214208: FinishResponseSubscriber could create duplicate headers,!617Issue #3043725: Provide a Entity Handler for user cancelation,!579Issue #2230909: Simple decimals fail to pass validation,!560Move callback classRemove outside of the loop,!555Issue #3202493
Pipeline #40956 passed
Pipeline: drupal

#40961

    Pipeline: drupal

    #40960

      Pipeline: drupal

      #40959

        +1
        ...@@ -33,6 +33,7 @@ public function fieldSettingsForm(array $form, FormStateInterface $form_state) { ...@@ -33,6 +33,7 @@ public function fieldSettingsForm(array $form, FormStateInterface $form_state) {
        '#type' => 'number', '#type' => 'number',
        '#title' => $this->t('Minimum'), '#title' => $this->t('Minimum'),
        '#default_value' => $settings['min'], '#default_value' => $settings['min'],
        '#element_validate' => [[static::class, 'validateMinAndMaxConfig']],
        '#description' => $this->t('The minimum value that should be allowed in this field. Leave blank for no minimum.'), '#description' => $this->t('The minimum value that should be allowed in this field. Leave blank for no minimum.'),
        ]; ];
        $element['max'] = [ $element['max'] = [
        ...@@ -124,4 +125,32 @@ protected static function truncateDecimal($decimal, $num) { ...@@ -124,4 +125,32 @@ protected static function truncateDecimal($decimal, $num) {
        return floor($decimal * pow(10, $num)) / pow(10, $num); return floor($decimal * pow(10, $num)) / pow(10, $num);
        } }
        /**
        * Validates that the minimum value is less than the maximum.
        *
        * @param array[] $element
        * The numeric element to be validated.
        * @param \Drupal\Core\Form\FormStateInterface $form_state
        * The current state of the form.
        * @param array[] $complete_form
        * The complete form structure.
        */
        public static function validateMinAndMaxConfig(array &$element, FormStateInterface &$form_state, array &$complete_form): void {
        $settingsValue = $form_state->getValue('settings');
        // Ensure that the minimum and maximum are numeric.
        $minValue = is_numeric($settingsValue['min']) ? (float) $settingsValue['min'] : NULL;
        $maxValue = is_numeric($settingsValue['max']) ? (float) $settingsValue['max'] : NULL;
        // Only proceed with validation if both values are numeric.
        if ($minValue === NULL || $maxValue === NULL) {
        return;
        }
        if ($minValue > $maxValue) {
        $form_state->setError($element, t('The minimum value must be less than or equal to %max.', ['%max' => $maxValue]));
        return;
        }
        }
        } }
        ...@@ -284,6 +284,17 @@ public function testNumberIntegerField() { ...@@ -284,6 +284,17 @@ public function testNumberIntegerField() {
        // Verify that the "content" attribute has been set to the value of the // Verify that the "content" attribute has been set to the value of the
        // field, and the prefix is being displayed. // field, and the prefix is being displayed.
        $this->assertSession()->elementTextContains('xpath', '//div[@content="' . $integer_value . '"]', 'ThePrefix' . $integer_value); $this->assertSession()->elementTextContains('xpath', '//div[@content="' . $integer_value . '"]', 'ThePrefix' . $integer_value);
        $field_configuration_url = 'entity_test/structure/entity_test/fields/entity_test.entity_test.' . $field_name;
        $this->drupalGet($field_configuration_url);
        // Tests Number validation messages.
        $edit = [
        'settings[min]' => 10,
        'settings[max]' => 8,
        ];
        $this->submitForm($edit, 'Save settings');
        $this->assertSession()->pageTextContains("The minimum value must be less than or equal to {$edit['settings[max]']}.");
        } }
        /** /**
        ......
        ...@@ -4,6 +4,8 @@ ...@@ -4,6 +4,8 @@
        use Drupal\Core\Field\FieldItemInterface; use Drupal\Core\Field\FieldItemInterface;
        use Drupal\Core\Field\FieldItemListInterface; use Drupal\Core\Field\FieldItemListInterface;
        use Drupal\Core\Field\Plugin\Field\FieldType\NumericItemBase;
        use Drupal\Core\Form\FormState;
        use Drupal\entity_test\Entity\EntityTest; use Drupal\entity_test\Entity\EntityTest;
        use Drupal\field\Entity\FieldConfig; use Drupal\field\Entity\FieldConfig;
        use Drupal\Tests\field\Kernel\FieldKernelTestBase; use Drupal\Tests\field\Kernel\FieldKernelTestBase;
        ...@@ -188,4 +190,68 @@ public function dataNumberFieldSettingsProvider() { ...@@ -188,4 +190,68 @@ public function dataNumberFieldSettingsProvider() {
        yield ['decimal', 1, 2, 1.5, FALSE]; yield ['decimal', 1, 2, 1.5, FALSE];
        } }
        /**
        * Tests the validation of minimum and maximum values.
        *
        * @param int|float|string $min
        * Min value to be tested.
        * @param int|float|string $max
        * Max value to be tested.
        * @param int|float|string $value
        * Value to be tested with min and max values.
        * @param bool $hasError
        * Expected validation result.
        * @param string $message
        * (optional) Error message result.
        *
        * @dataProvider dataTestMinMaxValue
        */
        public function testFormFieldMinMaxValue(int|float|string $min, int|float|string $max, int|float|string $value, bool $hasError, string $message = ''): void {
        $element = [
        '#type' => 'number',
        '#title' => 'min',
        '#default_value' => $min,
        '#element_validate' => [[NumericItemBase::class, 'validateMinAndMaxConfig']],
        '#description' => 'The minimum value that should be allowed in this field. Leave blank for no minimum.',
        '#parents' => [],
        '#name' => 'min',
        ];
        $form_state = new FormState();
        $form_state->setValue('min', $value);
        $form_state->setValue('settings', [
        'min' => $min,
        'max' => $max,
        'prefix' => '',
        'suffix' => '',
        'precision' => 10,
        'scale' => 2,
        ]);
        $completed_form = [];
        NumericItemBase::validateMinAndMaxConfig($element, $form_state, $completed_form);
        $errors = $form_state->getErrors();
        $this->assertEquals($hasError, count($errors) > 0);
        if ($errors) {
        $error = current($errors);
        $this->assertEquals($error, $message);
        }
        }
        /**
        * Data provider for testFormFieldMinMaxValue().
        *
        * @return \Generator
        * The test data.
        */
        public function dataTestMinMaxValue() {
        yield [1, 10, 5, FALSE, ''];
        yield [10, 5, 6, TRUE, 'The minimum value must be less than or equal to 5.'];
        yield [1, 0, 6, TRUE, 'The minimum value must be less than or equal to 0.'];
        yield [0, -2, 0.5, TRUE, 'The minimum value must be less than or equal to -2.'];
        yield [-10, -20, -5, TRUE, 'The minimum value must be less than or equal to -20.'];
        yield [1, '', -5, FALSE, ''];
        yield ['', '', '', FALSE, ''];
        yield ['2', '1', '', TRUE, 'The minimum value must be less than or equal to 1.'];
        }
        } }
        0% Loading or .
        You are about to add 0 people to the discussion. Proceed with caution.
        Finish editing this message first!
        Please register or to comment