Blame | Last modification | View Log | Download
<?php namespace ProcessWire;/*** Inputfield for floating point numbers** ProcessWire 3.x, Copyright 2020 by Ryan Cramer* https://processwire.com** @property int $precision* @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)**/class InputfieldFloat extends InputfieldInteger {public static function getModuleInfo() {return array('title' => __('Float', __FILE__), // Module Title'summary' => __('Floating point number with precision', __FILE__), // Module Summary'version' => 104,'permanent' => true,);}/*** Construct**/public function __construct() {$this->set('precision', 2);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;return $precision === null || $precision === '' ? '' : (int) $precision;}/*** Sanitize value** @param float|string $value* @return float|string**/protected function sanitizeValue($value) {if(!strlen("$value")) return '';if(!is_float($value) && !is_int($value)) {$value = $this->wire()->sanitizer->float($value, array('blankValue' => ''));if(!strlen("$value")) return '';}$precision = $this->precision;if($precision === null || $precision === '') {$precision = FieldtypeFloat::getPrecision($value);}return round((float) $value, $precision);}/*** Typecast value to float, override from InputfieldInteger** @param string|int|float $value* @return int**/protected function typeValue($value) {return (float) $value;}/*** Override method from Inputfield to convert local 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;if(is_float($value) && strlen("$value") && !ctype_digit(str_replace('.', '', $value))) {// float value is using a non "." as decimal point, needs conversion because// the HTML5 number input type requires "." as the decimal$attributes['value'] = $this->localeConvertValue($value);}}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;if(ctype_digit(str_replace('.', '', $value))) return $value;$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) {/** @var InputfieldInteger $f */$f = $this->wire()->modules->get('InputfieldInteger');$f->attr('name', 'precision');$f->label = $this->_('Number of decimal digits to round to');$f->attr('value', $this->precision);$f->attr('size', 8);$inputfields->add($f);} else {// precision is configured with FieldtypeFloat}return $inputfields;}}