1 <?php 2 // This file is part of Moodle - http://moodle.org/ 3 // 4 // Moodle is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // Moodle is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU General Public License for more details. 13 // 14 // You should have received a copy of the GNU General Public License 15 // along with Moodle. If not, see <http://www.gnu.org/licenses/>. 16 17 18 /** 19 * Float type form element 20 * 21 * Contains HTML class for a float type element 22 * 23 * @package core_form 24 * @category form 25 * @copyright 2019 Shamim Rezaie <shamim@moodle.com> 26 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 27 */ 28 29 defined('MOODLE_INTERNAL') || die(); 30 31 global $CFG; 32 require_once($CFG->libdir . '/form/text.php'); 33 34 /** 35 * Float type form element. 36 * 37 * This is preferred over the text element when working with float numbers, and takes care of the fact that different languages 38 * may use different symbols as the decimal separator. 39 * Using this element, submitted float numbers will be automatically translated from the localised format into the computer format, 40 * and vice versa when they are being displayed. 41 * 42 * @copyright 2019 Shamim Rezaie <shamim@moodle.com> 43 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 44 */ 45 class MoodleQuickForm_float extends MoodleQuickForm_text { 46 47 /** 48 * MoodleQuickForm_float constructor. 49 * 50 * @param string $elementName (optional) name of the float field 51 * @param string $elementLabel (optional) float field label 52 * @param string $attributes (optional) Either a typical HTML attribute string or an associative array 53 */ 54 public function __construct($elementName = null, $elementLabel = null, $attributes = null) { 55 parent::__construct($elementName, $elementLabel, $attributes); 56 $this->_type = 'float'; 57 } 58 59 /** 60 * Called by HTML_QuickForm whenever form event is made on this element. 61 * 62 * @param string $event Name of event 63 * @param mixed $arg event arguments 64 * @param object $caller calling object 65 * @return bool 66 */ 67 public function onQuickFormEvent($event, $arg, &$caller) { 68 switch ($event) { 69 case 'updateValue': 70 if ($value = $this->_findValue($caller->_constantValues)) { 71 $value = $this->format_float($value); 72 } 73 if (null === $value) { 74 $value = $this->_findValue($caller->_submitValues); 75 if (null === $value) { 76 if ($value = $this->_findValue($caller->_defaultValues)) { 77 $value = $this->format_float($value); 78 } 79 } 80 } 81 if (null !== $value) { 82 parent::setValue($value); 83 } 84 return true; 85 case 'createElement': 86 $caller->setType($arg[0], PARAM_RAW_TRIMMED); 87 default: 88 return parent::onQuickFormEvent($event, $arg, $caller); 89 } 90 } 91 92 /** 93 * Checks that the submitted value is a valid float number. 94 * 95 * @param string $value The localised float number that is submitted. 96 * @return string|null Validation error message or null. 97 */ 98 public function validateSubmitValue($value) { 99 if (false === unformat_float($value, true)) { 100 return get_string('err_numeric', 'core_form'); 101 } 102 } 103 104 /** 105 * Sets the value of the form element. 106 * 107 * @param string $value Default value of the form element 108 */ 109 public function setValue($value) { 110 $value = $this->format_float($value); 111 parent::setValue($value); 112 } 113 114 /** 115 * Returns the value of the form element. 116 * 117 * @return false|float 118 */ 119 public function getValue() { 120 $value = parent::getValue(); 121 if ($value) { 122 $value = unformat_float($value, true); 123 } 124 return $value; 125 } 126 127 /** 128 * Returns a 'safe' element's value. 129 * 130 * @param array $submitValues array of submitted values to search 131 * @param bool $assoc whether to return the value as associative array 132 * @return mixed 133 */ 134 public function exportValue(&$submitValues, $assoc = false) { 135 $value = $this->_findValue($submitValues); 136 if (null === $value) { 137 $value = $this->getValue(); 138 } else if ($value) { 139 $value = unformat_float($value, true); 140 } 141 return $this->_prepareValue($value, $assoc); 142 } 143 144 /** 145 * Used by getFrozenHtml() to pass the element's value if _persistantFreeze is on. 146 * 147 * @return string 148 */ 149 public function _getPersistantData() { 150 if (!$this->_persistantFreeze) { 151 return ''; 152 } else { 153 $id = $this->getAttribute('id'); 154 if (isset($id)) { 155 // Id of persistant input is different then the actual input. 156 $id = array('id' => $id . '_persistant'); 157 } else { 158 $id = array(); 159 } 160 161 return '<input' . $this->_getAttrString(array( 162 'type' => 'hidden', 163 'name' => $this->getAttribute('name'), 164 'value' => $this->getAttribute('value') 165 ) + $id) . ' />'; 166 } 167 } 168 169 /** 170 * Given a float, prints it nicely. 171 * This function reserves the number of decimal places. 172 * 173 * @param float|null $value The float number to format 174 * @return string Localised float 175 */ 176 private function format_float($value) { 177 if (is_numeric($value)) { 178 // We want to keep trailing zeros after the decimal point if there is any. 179 // Therefore we cannot just call format_float() and pass -1 as the number of decimal points. 180 $pieces = preg_split('/E/i', $value); // In case it is in the scientific format. 181 $decimalpos = strpos($pieces[0], '.'); 182 if ($decimalpos !== false) { 183 $decimalpart = substr($pieces[0], $decimalpos + 1); 184 $decimals = strlen($decimalpart); 185 } else { 186 $decimals = 0; 187 } 188 $pieces[0] = format_float($pieces[0], $decimals); 189 $value = implode('E', $pieces); 190 } 191 return $value; 192 } 193 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body