This issue is a spin-off from issue #1068016-22: number field validation fails to block some invalid input causing later SQL fatal error which is dealing with negative sign(s) entered in other than the first position of a text string intended to represent a number. In reviewing the solution proposed there, it was confirmed that the following currently are also rejected as invalid text representations of numbers:

1,000.00 (USA)
1.000,00 (France)

As a result, I asked "Shouldn't the validation logic pass what is produced by the [number] formatter(s)?"

To Do
Enhanced the number validation function and write tests.

Comments

yched’s picture

Subscribe for now. Thanks for creating the issue.

lars toomre’s picture

I have a custom form that has a column of numeric fields on which the user enters positive dollar values that may include ',' as a thousands separator. If it helps others generate a more complete solution, the admittedly incomplete function that I have been using to validate these fields is enclosed:

/**
 * Decodes a numeric text field on a form into its numeric value.
 *
 * This function is designed convert a basic number text field to its numeric
 * equivalent.  It sets an error message if a number could not be decoded.
 *
 * @param $element
 *   Form API element on which to set error message.
 * @param $text
 *   User-entered text representing the numeric value.
 *
 * @return $value
 *   Numeric value decoded from the text string.
 */
function MYMODULE_number_value_validate($element, $text) {
  static $number;

  // Quickly return any already decoded value
  if (isset($number[$text])) {
    return $number[$text];
  }

  // Generate the regular expression to validate the entered amounts.
  $decimal_separator = '.';
  $digit_group_separator = ',';
  $regexp = "/^-?(((\d{1,3}". $digit_group_separator .")?(\d{3}". $digit_group_separator .")*(\d{3}){1})|\d+)(". $decimal_separator ."\d{1,2})?$/";

  // Make sure the amount is entered using the correct format.
  if (!empty($text)) {
    if (preg_match($regexp, $text)) {
      $converted_number = str_replace(array($decimal_separator, $digit_group_separator), array('.', ''),  $text);
      $number[$text] = (float) $converted_number;
    }
    else {
      form_set_error($element, t('The numeric text (!amount) was not recognized as a valid number.', array('!amount' => $text)));
      return;
    }
  }
  return $number[$value];
}

I used a local static variable since this subroutine (in my case) was called from both the form validation and submit functions with table cell values that periodically repeat. I also have experimented with caching the numeric text/number pairs in the form generation function and reading from cache (if necessary) in this validation function. I had trouble though coming up with an unique cache key that addressed the possibility of an $options array as outlined below.

Regular expressions confound me so this function does not handle a leading +/- and hence negative values. I also have not retrieved the decimal_separator or digit_group_separator values that I think are part of the locale settings.

Ideally, whatever solution we come up should include full decoding of whatever was set via the associated formmatter. Hence, numeric text strings like '(1.000,00) $' should validate as text representation for -$1,000.00 (like users are accustomed to using in spreadsheets such as Excel).

I have wondered whether a generic solution also should include an $options array which might allow one to set degree of precision to consider in determining the numeric value (zero to eight perhaps?). Another option might be a flag to treat the text as numeric money and hence return the above value as the integer 100000 which avoids digital computer rounding errors.

One final thought: Perhaps a more complete solution already exists in some contrib module like Commerce or Ubercart?

bfroehle’s picture

Since contrib might want to reuse these in non-form api modules, can we consider making a form api element of #type 'decimal', 'integer', etc?

xano’s picture

Title: Enhance the validation function for number field decoding » Number form element validation is broken for floats
Category: task » bug

This is a pretty nasty bug that does not only apply to locales where commas are used as decimal signs, but also occurs when people use grouping separators. To solve this, I wrote a small helper class for Currency. It allows for different types of decimal separators and a rather complex combination of negative signs. We could at least use some of these features in core. Grouping signs are not supported yet, as I have not been able to figure out how to parse numbers like "10,000,000.00" (Anglo), "10.000.000,00" (continental European), and "1,00,00,000.00" (Hindi) all to 10000000.00 due to the different combinations of separators and grouping sizes that can be used.

swentel’s picture

Component: field system » number.module
Niklas Fiekas’s picture

I realize that this does not solve the issue (until browsers have better support for the new input types), but the original thought was: Let the number element implement exactly the HTML5 specification: http://www.w3.org/TR/html-markup/datatypes.html#common.data.float

Browsers that support the new input type may then accept anything (grouping, commas) and will always sent it to the server in the standard format.

<form>
<input type="number" step="any" name="number">
<input type="submit">
</form>

For example, Chrome, today:
5.4 gets sent as 5.4
7,3 gets sent as 7.3
1000,000.5 does not pass client side validation (anyway).
6- does not pass client side validation (anyway).

Version: 8.0.x-dev » 8.1.x-dev

Drupal 8.0.6 was released on April 6 and is the final bugfix release for the Drupal 8.0.x series. Drupal 8.0.x will not receive any further development aside from security fixes. Drupal 8.1.0-rc1 is now available and sites should prepare to update to 8.1.0.

Bug reports should be targeted against the 8.1.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.2.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.1.x-dev » 8.2.x-dev

Drupal 8.1.9 was released on September 7 and is the final bugfix release for the Drupal 8.1.x series. Drupal 8.1.x will not receive any further development aside from security fixes. Drupal 8.2.0-rc1 is now available and sites should prepare to upgrade to 8.2.0.

Bug reports should be targeted against the 8.2.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.3.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.2.x-dev » 8.3.x-dev

Drupal 8.2.6 was released on February 1, 2017 and is the final full bugfix release for the Drupal 8.2.x series. Drupal 8.2.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.3.0 on April 5, 2017. (Drupal 8.3.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.3.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.4.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.3.x-dev » 8.4.x-dev

Drupal 8.3.6 was released on August 2, 2017 and is the final full bugfix release for the Drupal 8.3.x series. Drupal 8.3.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.4.0 on October 4, 2017. (Drupal 8.4.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.4.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.5.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.4.x-dev » 8.5.x-dev

Drupal 8.4.4 was released on January 3, 2018 and is the final full bugfix release for the Drupal 8.4.x series. Drupal 8.4.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.5.0 on March 7, 2018. (Drupal 8.5.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.5.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.6.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.5.x-dev » 8.6.x-dev

Drupal 8.5.6 was released on August 1, 2018 and is the final bugfix release for the Drupal 8.5.x series. Drupal 8.5.x will not receive any further development aside from security fixes. Sites should prepare to update to 8.6.0 on September 5, 2018. (Drupal 8.6.0-rc1 is available for testing.)

Bug reports should be targeted against the 8.6.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.7.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.6.x-dev » 8.8.x-dev

Drupal 8.6.x will not receive any further development aside from security fixes. Bug reports should be targeted against the 8.8.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.9.x-dev branch. For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

Version: 8.8.x-dev » 8.9.x-dev

Drupal 8.8.7 was released on June 3, 2020 and is the final full bugfix release for the Drupal 8.8.x series. Drupal 8.8.x will not receive any further development aside from security fixes. Sites should prepare to update to Drupal 8.9.0 or Drupal 9.0.0 for ongoing support.

Bug reports should be targeted against the 8.9.x-dev branch from now on, and new development or disruptive changes should be targeted against the 9.1.x-dev branch. For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

pameeela’s picture

Issue summary: View changes
Status: Active » Closed (cannot reproduce)
Issue tags: +Bug Smash Initiative

The original issue of not passing validation is fixed, and both 1,000.00 and 1.000,00 can be entered into a float field.

Pasting 1,000.00 results in 1000.00 (comma is stripped) and it is saved as 1000.00.

Pasting 1.000,00 results in 1.00000 (comma is stripped) and it is saved as 1.00.

I found #1964192: form_validate_number() excludes countries that use commas which addresses the comma vs point issue, so I'm marking this closed.