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.

Differences Between: [Versions 310 and 401] [Versions 311 and 401] [Versions 39 and 401] [Versions 400 and 401]

   1  <?php
   2  /**
   3   * Copyright 2009-2017 Horde LLC (http://www.horde.org/)
   4   *
   5   * See the enclosed file LICENSE for license information (LGPL). If you
   6   * did not receive this file, see http://www.horde.org/licenses/lgpl21.
   7   *
   8   * @category  Horde
   9   * @copyright 2009-2017 Horde LLC
  10   * @license   http://www.horde.org/licenses/lgpl21 LGPL 2.1
  11   * @package   Util
  12   */
  13  
  14  /**
  15   * An OO-way to access form variables.
  16   *
  17   * @todo $_expected and $_vars are used inconsistently. $_expected is used in
  18   * exists(), but not in getExists(). And both are expected to be of the same
  19   * format, while Horde_Form submits $_expected as a flat list and $_vars as a
  20   * multi-dimensional array, if the the form elements are or array type (like
  21   * object[] in Turba).
  22   * @todo The sanitized feature doesn't seem to be used anywhere at all.
  23   *
  24   * @author    Robert E. Coyle <robertecoyle@hotmail.com>
  25   * @author    Chuck Hagenbuch <chuck@horde.org>
  26   * @author    Michael Slusarz <slusarz@horde.org>
  27   * @category  Horde
  28   * @copyright 2009-2017 Horde LLC
  29   * @license   http://www.horde.org/licenses/lgpl21 LGPL 2.1
  30   * @package   Util
  31   */
  32  class Horde_Variables implements ArrayAccess, Countable, IteratorAggregate
  33  {
  34      /**
  35       * The list of expected variables.
  36       *
  37       * @var array
  38       */
  39      protected $_expected = array();
  40  
  41      /**
  42       * Has the input been sanitized?
  43       *
  44       * @var boolean
  45       */
  46      protected $_sanitized = false;
  47  
  48      /**
  49       * Array of form variables.
  50       *
  51       * @var array
  52       */
  53      protected $_vars;
  54  
  55      /**
  56       * Returns a Horde_Variables object populated with the form input.
  57       *
  58       * @param string $sanitize  Sanitize the input variables?
  59       *
  60       * @return Horde_Variables  Variables object.
  61       */
  62      public static function getDefaultVariables($sanitize = false)
  63      {
  64          return new self(null, $sanitize);
  65      }
  66  
  67      /**
  68       * Constructor.
  69       *
  70       * @param array $vars       The list of form variables (if null, defaults
  71       *                          to PHP's $_REQUEST value). If '_formvars'
  72       *                          exists, it must be a JSON encoded array that
  73       *                          contains the list of allowed form variables.
  74       * @param string $sanitize  Sanitize the input variables?
  75       */
  76      public function __construct($vars = array(), $sanitize = false)
  77      {
  78          if (is_null($vars)) {
  79              $request_copy = $_REQUEST;
  80              $vars = Horde_Util::dispelMagicQuotes($request_copy);
  81          }
  82  
  83          if (isset($vars['_formvars'])) {
  84              $this->_expected = @json_decode($vars['_formvars'], true);
  85              unset($vars['_formvars']);
  86          }
  87  
  88          $this->_vars = $vars;
  89  
  90          if ($sanitize) {
  91              $this->sanitize();
  92          }
  93      }
  94  
  95      /**
  96       * Sanitize the form input.
  97       */
  98      public function sanitize()
  99      {
 100          if (!$this->_sanitized) {
 101              foreach (array_keys($this->_vars) as $key) {
 102                  $this->$key = $this->filter($key);
 103              }
 104              $this->_sanitized = true;
 105          }
 106      }
 107  
 108      /**
 109       * Alias of isset().
 110       *
 111       * @see __isset()
 112       */
 113      public function exists($varname)
 114      {
 115          return $this->__isset($varname);
 116      }
 117  
 118      /**
 119       * isset() implementation.
 120       *
 121       * @param string $varname  The form variable name.
 122       *
 123       * @return boolean  Does $varname form variable exist?
 124       */
 125      public function __isset($varname)
 126      {
 127          return count($this->_expected)
 128              ? $this->_getExists($this->_expected, $varname, $value)
 129              : $this->_getExists($this->_vars, $varname, $value);
 130      }
 131  
 132      /**
 133       * Implements isset() for ArrayAccess interface.
 134       *
 135       * @see __isset()
 136       */
 137      public function offsetExists($field)
 138      {
 139          return $this->__isset($field);
 140      }
 141  
 142      /**
 143       * Returns the value of a given form variable.
 144       *
 145       * @param string $varname  The form variable name.
 146       * @param string $default  The default form variable value.
 147       *
 148       * @return mixed  The form variable, or $default if it doesn't exist.
 149       */
 150      public function get($varname, $default = null)
 151      {
 152          return $this->_getExists($this->_vars, $varname, $value)
 153              ? $value
 154              : $default;
 155      }
 156  
 157      /**
 158       * Returns the value of a given form variable.
 159       *
 160       * @param string $varname  The form variable name.
 161       *
 162       * @return mixed  The form variable, or null if it doesn't exist.
 163       */
 164      public function __get($varname)
 165      {
 166          $this->_getExists($this->_vars, $varname, $value);
 167          return $value;
 168      }
 169  
 170      /**
 171       * Implements getter for ArrayAccess interface.
 172       *
 173       * @see __get()
 174       */
 175      public function offsetGet($field)
 176      {
 177          return $this->__get($field);
 178      }
 179  
 180      /**
 181       * Given a variable name, returns the value and sets a variable indicating
 182       * whether the value exists in the form data.
 183       *
 184       * @param string $varname   The form variable name.
 185       * @param boolean &$exists  Reference to variable that will indicate
 186       *                          whether $varname existed in form data.
 187       *
 188       * @return mixed  The form variable, or null if it doesn't exist.
 189       */
 190      public function getExists($varname, &$exists)
 191      {
 192          $exists = $this->_getExists($this->_vars, $varname, $value);
 193          return $value;
 194      }
 195  
 196      /**
 197       * Sets the value of a given form variable.
 198       *
 199       * @see __set()
 200       */
 201      public function set($varname, $value)
 202      {
 203          $this->$varname = $value;
 204      }
 205  
 206      /**
 207       * Sets the value of a given form variable.
 208       *
 209       * @param string $varname  The form variable name.
 210       * @param mixed $value     The value to set.
 211       */
 212      public function __set($varname, $value)
 213      {
 214          $keys = array();
 215  
 216          if (Horde_Array::getArrayParts($varname, $base, $keys)) {
 217              array_unshift($keys, $base);
 218              $place = &$this->_vars;
 219              $i = count($keys);
 220  
 221              while ($i--) {
 222                  $key = array_shift($keys);
 223                  if (!isset($place[$key])) {
 224                      $place[$key] = array();
 225                  }
 226                  $place = &$place[$key];
 227              }
 228  
 229              $place = $value;
 230          } else {
 231              $this->_vars[$varname] = $value;
 232          }
 233      }
 234  
 235      /**
 236       * Implements setter for ArrayAccess interface.
 237       *
 238       * @see __set()
 239       */
 240      public function offsetSet($field, $value)
 241      {
 242          $this->__set($field, $value);
 243      }
 244  
 245      /**
 246       * Deletes a given form variable.
 247       *
 248       * @see __unset()
 249       */
 250      public function remove($varname)
 251      {
 252          unset($this->$varname);
 253      }
 254  
 255      /**
 256       * Deletes a given form variable.
 257       *
 258       * @param string $varname  The form variable name.
 259       */
 260      public function __unset($varname)
 261      {
 262          Horde_Array::getArrayParts($varname, $base, $keys);
 263  
 264          if (is_null($base)) {
 265              unset($this->_vars[$varname]);
 266          } else {
 267              $ptr = &$this->_vars[$base];
 268              $end = count($keys) - 1;
 269              foreach ($keys as $key => $val) {
 270                  if (!isset($ptr[$val])) {
 271                      break;
 272                  }
 273                  if ($end == $key) {
 274                      array_splice($ptr, array_search($val, array_keys($ptr)), 1);
 275                  } else {
 276                      $ptr = &$ptr[$val];
 277                  }
 278              }
 279          }
 280      }
 281  
 282      /**
 283       * Implements unset() for ArrayAccess interface.
 284       *
 285       * @see __unset()
 286       */
 287      public function offsetUnset($field)
 288      {
 289          $this->__unset($field);
 290      }
 291  
 292      /**
 293       * Merges a list of variables into the current form variable list.
 294       *
 295       * @param array $vars  Form variables.
 296       */
 297      public function merge($vars)
 298      {
 299          foreach ($vars as $varname => $value) {
 300              $this->$varname = $value;
 301          }
 302      }
 303  
 304      /**
 305       * Set $varname to $value ONLY if it's not already present.
 306       *
 307       * @param string $varname  The form variable name.
 308       * @param mixed $value     The value to set.
 309       *
 310       * @return boolean  True if the value was altered.
 311       */
 312      public function add($varname, $value)
 313      {
 314          if ($this->exists($varname)) {
 315              return false;
 316          }
 317  
 318          $this->_vars[$varname] = $value;
 319          return true;
 320      }
 321  
 322      /**
 323       * Filters a form value so that it can be used in HTML output.
 324       *
 325       * @param string $varname  The form variable name.
 326       *
 327       * @return mixed  The filtered variable, or null if it doesn't exist.
 328       */
 329      public function filter($varname)
 330      {
 331          $val = $this->$varname;
 332  
 333          if (is_null($val) || $this->_sanitized) {
 334              return $val;
 335          }
 336  
 337          return is_array($val)
 338              ? filter_var_array($val, FILTER_SANITIZE_FULL_SPECIAL_CHARS, FILTER_FLAG_NO_ENCODE_QUOTES)
 339              : filter_var($val, FILTER_SANITIZE_FULL_SPECIAL_CHARS, FILTER_FLAG_NO_ENCODE_QUOTES);
 340      }
 341  
 342      /* Protected methods. */
 343  
 344      /**
 345       * Fetch the requested variable ($varname) into $value, and return
 346       * whether or not the variable was set in $array.
 347       *
 348       * @param array $array     The array to search in (usually either
 349       *                         $this->_vars or $this->_expected).
 350       * @param string $varname  The name of the variable to look for.
 351       * @param mixed &$value    $varname's value gets assigned to this variable.
 352       *
 353       * @return boolean  Whether or not the variable was set (or, if we've
 354       *                  checked $this->_expected, should have been set).
 355       */
 356      protected function _getExists($array, $varname, &$value)
 357      {
 358          if (Horde_Array::getArrayParts($varname, $base, $keys)) {
 359              if (!isset($array[$base])) {
 360                  $value = null;
 361                  return false;
 362              }
 363  
 364              $searchspace = &$array[$base];
 365              $i = count($keys);
 366  
 367              while ($i--) {
 368                  $key = array_shift($keys);
 369                  if (!isset($searchspace[$key])) {
 370                      $value = null;
 371                      return false;
 372                  }
 373                  $searchspace = &$searchspace[$key];
 374              }
 375              $value = $searchspace;
 376  
 377              return true;
 378          }
 379  
 380          $value = isset($array[$varname])
 381              ? $array[$varname]
 382              : null;
 383  
 384          return !is_null($value);
 385      }
 386  
 387      /* Countable methods. */
 388  
 389      /**
 390       */
 391      public function count()
 392      {
 393          return count($this->_vars);
 394      }
 395  
 396      /* IteratorAggregate method. */
 397  
 398      public function getIterator()
 399      {
 400          return new ArrayIterator($this->_vars);
 401      }
 402  
 403  }