Short description of the issue
Commit 7e80f3a5 added ___wakeupValue() to FieldtypeDecimal that routes through sanitizeValue(). Because sanitizer->float() (with the default precision=null) collapses "42.00" to 42 before the precision-padding loop runs (the loop only fires when a . is present in the sanitized value), values whose decimal part was all zeros now come back without zero padding. This contradicts the API.md (commit 84f93fde) which documents that decimal values are returned as fixed-precision strings.
Expected behavior
A FieldtypeDecimal field with precision 2:
- Stored
42.00 loads as "42.00".
- Stored
0.00 loads as "0.00".
- Stored
42.50 loads as "42.50".
Actual behavior
- Stored
42.00 now loads as "42".
- Stored
0.00 now loads as "0" (or 0 numerically).
- Stored
42.50 still loads as "42.50" (correct).
The discrepancy breaks downstream code that does:
printf('%s', $page->price) expecting a fixed-precision string.
if($page->price === '0.00') comparisons.
- JSON output that previously contained
"price":"42.00" and now contains "price":"42".
Optional: Suggestion for a possible fix
After sanitizeValue(), explicitly pad to the configured precision if the field has a fixed precision and the sanitized value is integral:
public function ___wakeupValue(Page $page, Field $field, $value) {
$value = $this->sanitizeValue($page, $field, $value);
$precision = (int) $field->precision;
if($precision > 0 && is_string($value) && strpos($value, '.') === false) {
$value = number_format((float) $value, $precision, '.', '');
}
return $value;
}
Steps to reproduce the issue
- Create a
Decimal field with precision 2, attach to a template.
- Save a page with the field set to
42.
- Reload the page and inspect —
var_dump($page->fieldname) returns string(2) "42" (was string(5) "42.00").
Setup/Environment
- ProcessWire version:
dev @ 15c749ed
- File:
wire/modules/Fieldtype/FieldtypeDecimal/FieldtypeDecimal.module
- Regression introduced in commit 7e80f3a5
Short description of the issue
Commit 7e80f3a5 added
___wakeupValue()toFieldtypeDecimalthat routes throughsanitizeValue(). Becausesanitizer->float()(with the defaultprecision=null) collapses"42.00"to42before the precision-padding loop runs (the loop only fires when a.is present in the sanitized value), values whose decimal part was all zeros now come back without zero padding. This contradicts the API.md (commit 84f93fde) which documents that decimal values are returned as fixed-precision strings.Expected behavior
A
FieldtypeDecimalfield with precision 2:42.00loads as"42.00".0.00loads as"0.00".42.50loads as"42.50".Actual behavior
42.00now loads as"42".0.00now loads as"0"(or0numerically).42.50still loads as"42.50"(correct).The discrepancy breaks downstream code that does:
printf('%s', $page->price)expecting a fixed-precision string.if($page->price === '0.00')comparisons."price":"42.00"and now contains"price":"42".Optional: Suggestion for a possible fix
After
sanitizeValue(), explicitly pad to the configured precision if the field has a fixed precision and the sanitized value is integral:Steps to reproduce the issue
Decimalfield with precision 2, attach to a template.42.var_dump($page->fieldname)returnsstring(2) "42"(wasstring(5) "42.00").Setup/Environment
dev@15c749edwire/modules/Fieldtype/FieldtypeDecimal/FieldtypeDecimal.module