Search moodle.org's
Developer Documentation

See Release Notes
Long Term Support Release

  • Bug fixes for general core bugs in 4.1.x will end 13 November 2023 (12 months).
  • Bug fixes for security issues in 4.1.x will end 10 November 2025 (36 months).
  • PHP version: minimum PHP 7.4.0 Note: minimum PHP version has increased since Moodle 4.0. PHP 8.0.x is supported too.
/lib/form/ -> float.php (source)
   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  }