praiadeseselle/wire/modules/Inputfield/InputfieldFloat.module

188 lines
5.7 KiB
Text
Raw Normal View History

2022-03-08 15:55:41 +01:00
<?php namespace ProcessWire;
/**
* Inputfield for floating point numbers
*
2022-11-05 18:32:48 +01:00
* ProcessWire 3.x, Copyright 2022 by Ryan Cramer
2022-03-08 15:55:41 +01:00
* https://processwire.com
*
2022-11-05 18:32:48 +01:00
* @property int $precision Decimals precision (or -1 to disable rounding in 3.0.193+)
2022-03-08 15:55:41 +01:00
* @property int $digits Total digits, for when used in decimal mode (default=0)
* @property string $inputType Input type to use, one of "text" or "number"
* @property int|float $min
* @property int|float $max
* @property int|float|string $step
* @property int $size
* @property string $placeholder
* @property int|float $initValue Initial/default value (when used as independent Inputfield)
* @property int|float|string $defaultValue Initial/default value (when used with FieldtypeInteger)
2022-11-05 18:32:48 +01:00
* @property bool|int $noE Convert “123E-3” and “123E3” type numbers to real numbers in the <input>? 3.0.193+
2022-03-08 15:55:41 +01:00
*
*/
class InputfieldFloat extends InputfieldInteger {
public static function getModuleInfo() {
return array(
'title' => __('Float', __FILE__), // Module Title
'summary' => __('Floating point number with precision', __FILE__), // Module Summary
2022-11-05 18:32:48 +01:00
'version' => 105,
2022-03-08 15:55:41 +01:00
'permanent' => true,
);
}
/**
* Construct
*
*/
public function __construct() {
$this->set('precision', 2);
$this->set('digits', 0);
2022-11-05 18:32:48 +01:00
$this->set('noE', 0);
2022-03-08 15:55:41 +01:00
parent::__construct();
}
/**
* Module init
*
*/
public function init() {
parent::init();
$this->attr('step', 'any'); // HTML5 attr required to support decimals with 'number' types
}
/**
* Get configured precision setting, or if given a value, precision of the value
*
* @param float|string|null $value
* @return int|string Returns integer of precision or blank string if none defined
*
*/
protected function getPrecision($value = null) {
if($value !== null) return FieldtypeFloat::getPrecision($value);
$precision = $this->precision;
2022-11-05 18:32:48 +01:00
return $precision === null || $precision === '' || $precision < 0 ? '' : (int) $precision;
2022-03-08 15:55:41 +01:00
}
/**
* Sanitize value
*
* @param float|string $value
* @return float|string
*
*/
protected function sanitizeValue($value) {
if(!strlen("$value")) return '';
if($this->digits > 0) {
return is_numeric("$value") ? (string) $value : '';
} else if(!is_float($value) && !is_int($value)) {
$value = $this->wire()->sanitizer->float($value, array('blankValue' => ''));
if(!strlen("$value")) return '';
}
$precision = $this->precision;
2022-11-05 18:32:48 +01:00
if($precision === null || $precision === '') $precision = $this->getPrecision($value);
return is_int($precision) && $precision > 0 ? round((float) $value, $precision) : $value;
2022-03-08 15:55:41 +01:00
}
/**
* Typecast value to float, override from InputfieldInteger
*
* @param string|int|float $value
* @return int
*
*/
protected function typeValue($value) {
return (float) $value;
}
2022-11-05 18:32:48 +01:00
/**
* Does the value have an E in it like ”123E-3” or "123E3” ?
*
* @param string $value
* @return bool
* @since 3.0.193
*
*/
public function hasE($value) {
$value = strtoupper((string) $value);
if(strpos($value, 'E') === false) return false;
$value = str_replace(array('-', '.', ',', ' '), '', $value);
list($a, $b) = explode('E', $value, 2);
$b = trim($b, '+-');
return ctype_digit("$a$b");
}
2022-03-08 15:55:41 +01:00
/**
* Override method from Inputfield to convert locale specific decimals for input[type=number]
*
* @param array $attributes
* @return string
*
*/
public function getAttributesString(array $attributes = null) {
if($attributes && $attributes['type'] === 'number') {
$value = isset($attributes['value']) ? $attributes['value'] : null;
2022-11-05 18:32:48 +01:00
if(is_float($value) || (is_string($value) && strlen($value))) {
// the HTML5 number input type requires "." as the decimal
$value = $this->localeConvertValue($value);
$attributes['value'] = $value;
2022-03-08 15:55:41 +01:00
}
2022-11-05 18:32:48 +01:00
if(empty($attributes['step']) || $attributes['step'] === 'any') {
$precision = (int) $this->precision;
if($precision < 1 && $value !== null) $precision = $this->getPrecision($value);
if($precision > 0) {
$attributes['step'] = '.' . ($precision > 1 ? str_repeat('0', $precision - 1) : '') . '1';
}
2022-03-08 15:55:41 +01:00
}
}
2022-11-05 18:32:48 +01:00
if($attributes && !empty($attributes['value']) && $this->noE && $this->hasE($attributes['value'])) {
$attributes['value'] = $this->wire()->sanitizer->float($attributes['value'], array('getString' => true));
}
2022-03-08 15:55:41 +01:00
return parent::getAttributesString($attributes);
}
/**
* Convert floats with non "." decimal points to use "." decimal point according to locale
*
* @param float|string $value
* @return string|float Returns string representation of float when value was converted
*
*/
protected function localeConvertValue($value) {
if(!strlen("$value")) return $value;
2022-11-05 18:32:48 +01:00
if(ctype_digit(str_replace(array('.', 'E', 'e', '-', '+'), '', "$value"))) return $value;
2022-03-08 15:55:41 +01:00
$locale = localeconv();
$decimal = $locale['decimal_point'];
if($decimal === '.' || strpos($value, $decimal) === false) return $value;
$parts = explode($decimal, $value, 2);
$value = implode('.', $parts);
return $value;
}
/**
* Inputfield config
*
* @return InputfieldWrapper
*
*/
public function getConfigInputfields() {
$inputfields = parent::getConfigInputfields();
if($this->hasFieldtype === false) {
2022-11-05 18:32:48 +01:00
// when used without FieldtypeFloat
2022-03-08 15:55:41 +01:00
/** @var InputfieldInteger $f */
$f = $this->wire()->modules->get('InputfieldInteger');
$f->attr('name', 'precision');
$f->label = $this->_('Number of decimal digits to round to');
2022-11-05 18:32:48 +01:00
$f->description = $this->_('Or use a negative number like `-1` to disable rounding.');
2022-03-08 15:55:41 +01:00
$f->attr('value', $this->precision);
$f->attr('size', 8);
$inputfields->add($f);
} else {
// precision is configured with FieldtypeFloat
}
2022-11-05 18:32:48 +01:00
// @todo anyone other than me want a config setting for $noE ?
2022-03-08 15:55:41 +01:00
return $inputfields;
}
}