Problem/Motivation

Views fields that use the numeric field plugin cannot render float values between zero and negative one.
Values of this range will be rendered as positive instead of negative. E.g. -0.12 will be displayed as 0.12

This is due to the way NumericField::render() rounds the number first, and then adds back on the remainder:

$remainder = abs($value) - intval(abs($value));
$value = $value > 0 ? floor($value) : ceil($value);

From here our value of -0.12 will be 0.

$value = number_format($value, 0, '', $this->options['separator']);
if ($remainder) {
  // The substr may not be locale safe.
  $value .= $this->options['decimal'] . substr($remainder, 2);
}

Proposed resolution

Re-factor NumericField::render() so the correct precision is passed through to number_format()

Remaining tasks

  • Re-factor NumericField::render()
  • Add tests that include negative ranges -0.xx
  • Review and commit patch

User interface changes

None

API changes

None

Data model changes

None

Beta phase evaluation

Reference: https://www.drupal.org/core/beta-changes
Issue category Bug because rendered output does not match expected output
Issue priority Normal because only a small number of input values would be affected.
CommentFileSizeAuthor
#47 1952926-47.patch7.12 KBMirnaxvb
#47 interdiff-1952926-45-47.txt1.86 KBMirnaxvb
#45 1952926-45.patch6.18 KBLendude
#45 interdiff-1952926-44-45.txt10.15 KBLendude
#44 1952926-44.patch9.52 KBalexpott
#44 42-44-interdiff.txt4.23 KBalexpott
#42 1952926-42.patch7.34 KBalexpott
#42 37-42-interdiff.txt4.96 KBalexpott
#37 1952926-37.patch5.77 KBLendude
#37 interdiff-1952926-35-37.txt3.28 KBLendude
#35 1952926-35.patch5.76 KBLendude
#35 interdiff-1952926-29-35.txt7.53 KBLendude
#29 interdiff-1952926-27-29.txt1.7 KBLendude
#29 1952926-29.patch5.83 KBLendude
#27 1952926-27-26-interdiff.txt667 bytesLeon Kessler
#27 1952926-27.patch4.74 KBLeon Kessler
#26 1952926-26.patch4.74 KBfinne
#21 interdiff-1952926-17-21.txt3.78 KBLendude
#21 1952926-21.patch4.75 KBLendude
#21 1952926-21-SHOULDFAIL.patch2.88 KBLendude
#20 Handle_negative_numbers_views-1952926-20.patch3.08 KBtadityar
#17 Handle_negative_numbers_views-1952926-17.patch3.59 KBgigabates
#12 Handle_nagative_numbers_views-1952926-12.patch880 bytesshyam kumar kunkala
#10 Handle_negative_numbers_views-1952926-9.patch1.2 KBshyam kumar kunkala
#8 Handle_negative_numbers_views-1952926-8.patch.patch1.2 KBshyam kumar kunkala
#7 Handle_negative_numbers_views-1952926-7.patch.patch1.2 KBshyam kumar kunkala
#1 support_negative-1952926-1.patch831 bytesportico
Support from Acquia helps fund testing for Drupal Acquia logo

Comments

portico’s picture

Here is the patch.

Status: Needs review » Needs work

The last submitted patch, support_negative-1952926-1.patch, failed testing.

dawehner’s picture

Project: Views (for Drupal 7) » Drupal core
Version: 7.x-3.6 » 8.x-dev
Component: Code » views.module

Let's fix this properly in Drupal Core first, with tests etc.

portico’s picture

Version: 8.x-dev » 7.x-dev
portico’s picture

Status: Needs work » Needs review

#1: support_negative-1952926-1.patch queued for re-testing.

Status: Needs review » Needs work

The last submitted patch, support_negative-1952926-1.patch, failed testing.

shyam kumar kunkala’s picture

Assigned: Unassigned » shyam kumar kunkala
Status: Needs work » Patch (to be ported)
FileSize
1.2 KB

Here is the patch

shyam kumar kunkala’s picture

Status: Patch (to be ported) » Needs review
FileSize
1.2 KB

Here is the patch

Status: Needs review » Needs work

The last submitted patch, Handle_negative_numbers_views-1952926-8.patch.patch, failed testing.

shyam kumar kunkala’s picture

Status: Needs work » Needs review
FileSize
1.2 KB

Here is patch in specified format

Status: Needs review » Needs work

The last submitted patch, Handle_negative_numbers_views-1952926-9.patch, failed testing.

shyam kumar kunkala’s picture

Issue summary: View changes
Status: Needs work » Needs review
FileSize
880 bytes

Status: Needs review » Needs work

The last submitted patch, 12: Handle_nagative_numbers_views-1952926-12.patch, failed testing.

fonant’s picture

fonant’s picture

dcam’s picture

Version: 7.x-dev » 8.0.x-dev
Assigned: shyam kumar kunkala » Unassigned

Issues must be fixed in Drupal 8 first, then backported.

gigabates’s picture

Status: Needs work » Needs review
FileSize
3.59 KB

Simpler method using string length after decimal point to determine default precision. This also fixes a floating point precision issue where '1000.1234' would render as '1,000.12339999999995'. Includes tests for both issues.

dawehner’s picture

Issue tags: +VDC

I really like how this is rewritten! This is absolutely cleaner, I wonder whether number_format maybe changed at some point in time?

+++ b/core/modules/views/src/Tests/Handler/FieldNumericTest.php
@@ -0,0 +1,46 @@
+ * Definition of Drupal\views\Tests\Handler\FieldNumericTest.

This should be "Contains \"... just for consistency

jhedstrom’s picture

tadityar’s picture

Status: Needs work » Needs review
FileSize
3.08 KB

changed to contains

Lendude’s picture

Added some more tests to the ones given in #17, there is more that needs testing with this handler.

Added tests for 'hide_empty' and 'precision'. The precision tests also failed for #17 because of

+++ b/core/modules/views/src/Plugin/views/field/Numeric.php
@@ -131,17 +131,15 @@ public function buildOptionsForm(&$form, FormStateInterface $form_state) {
+      $precision = $this->options['set_precision'];

Needs to be $this->options['precision'];

Also the empty check was done after the rewriting instead of before rewriting so a value of 0 would not be considered empty with a precision set because it would be changed before the !==0 check.

Will add failing tests and patch, interdiff is against #17

Had no internet in the train and missed that some more work had been done since yesterday, but #20 did not address the extra issues I saw, so will post my patch.

The last submitted patch, 21: 1952926-21-SHOULDFAIL.patch, failed testing.

Lendude queued 21: 1952926-21.patch for re-testing.

Status: Needs review » Needs work

The last submitted patch, 21: 1952926-21.patch, failed testing.

finne’s picture

Assigned: Unassigned » finne
finne’s picture

Status: Needs work » Needs review
FileSize
4.74 KB

Rerolled the patch to work with the latest 8.0.x. Especially the renamed file NumericField.php.

Leon Kessler’s picture

Title: views_handler_field_numeric does not support negative value rendering in range -0.xx. » NumericField.php does not support negative value rendering in range -0.xx.
Issue summary: View changes
FileSize
4.74 KB
667 bytes

Re-rolling patch with #2546416: Rename ViewUnitTestBase to ViewKernelTestBase

Also updated issue summary and title.

A quick note for anyone who wants to manually test this: since #2342045: Standard views base fields need to use same rendering as Field UI fields, for formatting, access checking, and translation consistency there are no entity fields that use the numeric plugin - so you cannot test with a number entity field, you will need to use a views field that actually uses the numeric plugin. Currently only the file count field and user id field does (and not the node id field).
As these fields will never contain negative values, this bug will only affect fields that are using the numeric field plugin outside of core.

Leon Kessler’s picture

Issue tags: +Barcelona2015
Lendude’s picture

Thanks for the reroll.

Added beta eval.

Expanded the test coverage a bit to also include the decimal and separator options, since these are not covered by tests at the moment and they should be.

Leon Kessler’s picture

Assigned: finne » Unassigned

New patch looks good.

This should be unassigned now, hopefully someone can pick this up and RTBC.

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.

dawehner’s picture

+++ b/core/modules/views/src/Tests/Handler/FieldNumericTest.php
@@ -0,0 +1,103 @@
+ * @file
+ * Contains \Drupal\views\Tests\Handler\FieldNumericTest.
+ */

Nitpick: :)

I assume this needs a reroll in the meantime.

Lendude’s picture

@dawehner, yup, it did, still applied but needed array conversion and the test needed to be moved to the right spot. Also fixed the nitpick :)

dawehner’s picture

+++ b/core/modules/views/tests/src/Kernel/Handler/FieldNumericTest.php
@@ -0,0 +1,98 @@
+    $this->assertEqual($view->field['age']->advancedRender($view->result[0]), '0');
+    $this->assertEqual($view->field['age']->advancedRender($view->result[1]), '0.1234');
+    $this->assertEqual($view->field['age']->advancedRender($view->result[2]), '-0.1234');
+    $this->assertEqual($view->field['age']->advancedRender($view->result[3]), '1,000.1234');
+    $this->assertEqual($view->field['age']->advancedRender($view->result[4]), '-1,000.1234');
...
+    $this->assertEqual($view->field['age']->advancedRender($view->result[0]), '');
+    $this->assertEqual($view->field['age']->advancedRender($view->result[1]), '0.12');
+    $this->assertEqual($view->field['age']->advancedRender($view->result[2]), '-0.12');
+    $this->assertEqual($view->field['age']->advancedRender($view->result[3]), '1,000.12');
+    $this->assertEqual($view->field['age']->advancedRender($view->result[4]), '-1,000.12');

Do you mind using assertEquals and swapping parameters around?

Lendude’s picture

dawehner’s picture

Status: Needs review » Reviewed & tested by the community

Thank you @Lendude!

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 37: 1952926-37.patch, failed testing.

Lendude’s picture

Status: Needs work » Reviewed & tested by the community

Unrelated fail

alexpott’s picture

Status: Reviewed & tested by the community » Needs work
+++ b/core/modules/views/src/Plugin/views/field/NumericField.php
@@ -149,24 +149,24 @@ public function submitOptionsForm(&$form, FormStateInterface $form_state) {
+    if (!empty($this->options['set_precision'])) {
+      $precision = $this->options['precision'];
+    }
+    elseif ($decimal_position = strpos($value, '.')) {
+      $precision = strlen($value) - $decimal_position - 1;
+    }
+    else {
+      $precision = 0;
+    }
+    $value = number_format($value, $precision, $this->options['decimal'], $this->options['separator']);

Moving this to after the hide empty check looks wrong. Because if you set the precision to 0 and the value is 0.1 before it would be hidden if you have the empty zero option.

alexpott’s picture

Status: Needs work » Needs review
FileSize
4.96 KB
7.34 KB

Here's a test and fix to show what I'm on about. Also https://twitter.com/alexpott/status/856989395991265284

Lendude’s picture

#42 seems related to #1232920: Empty rounded numeric fields not hidden properly, that focusses on decimal fields though.

alexpott’s picture

We don't need to use preg_match - https://3v4l.org/q4VKG ?!?!?

More tests added.

Lendude’s picture

@alexpott thanks for all the test coverage!

Had some minor formatting/comment nitpicks, but in order to see if we have all the possible scenario's covered, I decided to rewrite the testing using a dataprovider.

This just addressed some nits and is a 1-1 rewrite of the tests, nothing new added.

jibran’s picture

Patch looks solid just minor observation.

  1. +++ b/core/modules/views/tests/src/Kernel/Handler/FieldNumericTest.php
    @@ -0,0 +1,133 @@
    +      'precision_2-hide_empty-hide_zero' => [
    ...
    +        [0, 0.1234, -0.1234, 1000.1234, -1000.1234, 0.0001, -0.0001],
    

    We should add empty sting here because it is also testing hide empty. I know we added it blow but we can add it here too.

  2. No separator case is also missing.
Mirnaxvb’s picture

Doing core mentoring with @Lendude.

Fixed feedback from #46.

jibran’s picture

Status: Needs review » Reviewed & tested by the community

Thanks, @Lendude and @Mirnaxvb

  • catch committed 8525587 on 8.4.x
    Issue #1952926 by Lendude, shyam kumar kunkala, alexpott, Leon Kessler,...

  • catch committed 8c7aa16 on 8.3.x
    Issue #1952926 by Lendude, shyam kumar kunkala, alexpott, Leon Kessler,...
catch’s picture

Status: Reviewed & tested by the community » Fixed

Committed/pushed to 8.4.x and cherry-picked to 8.3.x. Thanks!

Great how this simplifies the code too.

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.