From 5dfc673f05ba44683327e095633a594521942e9e Mon Sep 17 00:00:00 2001
From: Joao Ventura <joao.ventura@wunderkraut.com>
Date: Wed, 10 Feb 2016 19:20:58 +0100
Subject: Issue #2230909 by jcnventura, exlin: Simple decimals fail to pass
 validation

---
 .../Plugin/Field/FieldWidget/NumberWidget.php      |  1 +
 core/lib/Drupal/Core/Render/Element/Number.php     |  8 ++++++-
 .../field/src/Tests/Number/NumberFieldTest.php     | 27 ++++++++++++++--------
 3 files changed, 26 insertions(+), 10 deletions(-)

diff --git a/core/lib/Drupal/Core/Field/Plugin/Field/FieldWidget/NumberWidget.php b/core/lib/Drupal/Core/Field/Plugin/Field/FieldWidget/NumberWidget.php
index 57abc60..5c0f003 100644
--- a/core/lib/Drupal/Core/Field/Plugin/Field/FieldWidget/NumberWidget.php
+++ b/core/lib/Drupal/Core/Field/Plugin/Field/FieldWidget/NumberWidget.php
@@ -78,6 +78,7 @@ public function formElement(FieldItemListInterface $items, $delta, array $elemen
       '#type' => 'number',
       '#default_value' => $value,
       '#placeholder' => $this->getSetting('placeholder'),
+      '#number_type' => $this->fieldDefinition->getType(),
     );
 
     // Set the step for floating point and decimal numbers.
diff --git a/core/lib/Drupal/Core/Render/Element/Number.php b/core/lib/Drupal/Core/Render/Element/Number.php
index fbb0805..d9cd8a4 100644
--- a/core/lib/Drupal/Core/Render/Element/Number.php
+++ b/core/lib/Drupal/Core/Render/Element/Number.php
@@ -92,8 +92,14 @@ public static function validateNumber(&$element, FormStateInterface $form_state,
       // Check that the input is an allowed multiple of #step (offset by #min if
       // #min is set).
       $offset = isset($element['#min']) ? $element['#min'] : 0.0;
+      $step = $element['#step'];
+      if (isset($element['#number_type']) && ($element['#number_type'] == 'decimal')) {
+        // PHP mangles the precision of floating-point arguments, so convert
+        // the step to string for non-floating-point numbers.
+        $step = (string) $element['#step'];
+      }
 
-      if (!NumberUtility::validStep($value, $element['#step'], $offset)) {
+      if (!NumberUtility::validStep($value, $step, $offset)) {
         $form_state->setError($element, t('%name is not a valid number.', array('%name' => $name)));
       }
     }
diff --git a/core/modules/field/src/Tests/Number/NumberFieldTest.php b/core/modules/field/src/Tests/Number/NumberFieldTest.php
index 9537170..b6f67f8 100644
--- a/core/modules/field/src/Tests/Number/NumberFieldTest.php
+++ b/core/modules/field/src/Tests/Number/NumberFieldTest.php
@@ -48,7 +48,7 @@ function testNumberDecimalField() {
       'entity_type' => 'entity_test',
       'type' => 'decimal',
       'settings' => array(
-        'precision' => 8, 'scale' => 4,
+        'precision' => 10, 'scale' => 4,
       )
     ))->save();
     entity_create('field_config', array(
@@ -77,15 +77,24 @@ function testNumberDecimalField() {
     $this->assertRaw('placeholder="0.00"');
 
     // Submit a signed decimal value within the allowed precision and scale.
-    $value = '-1234.5678';
-    $edit = array(
-      "{$field_name}[0][value]" => $value,
+    $valid_entries = array(
+      '-1234.5678',
+      '19999.0000',
+      '99999.0000',
     );
-    $this->drupalPostForm(NULL, $edit, t('Save'));
-    preg_match('|entity_test/manage/(\d+)|', $this->url, $match);
-    $id = $match[1];
-    $this->assertText(t('entity_test @id has been created.', array('@id' => $id)), 'Entity was created');
-    $this->assertRaw($value, 'Value is displayed.');
+
+    foreach ($valid_entries as $valid_entry) {
+      $this->drupalGet('entity_test/add');
+      $edit = array(
+        "{$field_name}[0][value]" => $valid_entry,
+      );
+      $this->drupalPostForm(NULL, $edit, t('Save'));
+      preg_match('|entity_test/manage/(\d+)|', $this->url, $match);
+      $id = $match[1];
+      $this->assertText(t('entity_test @id has been created.', array('@id' => $id)), 'Entity was created');
+      $this->assertRaw($valid_entry, 'Value is displayed.');
+      $this->assertNoRaw(t('%name is not a valid number.', array('%name' => $field_name)), 'Values are accepted');
+    }
 
     // Try to create entries with more than one decimal separator; assert fail.
     $wrong_entries = array(
-- 
2.6.3

