Search moodle.org's
Developer Documentation

See Release Notes
Long Term Support Release

  • Bug fixes for general core bugs in 3.9.x will end* 10 May 2021 (12 months).
  • Bug fixes for security issues in 3.9.x will end* 8 May 2023 (36 months).
  • PHP version: minimum PHP 7.2.0 Note: minimum PHP version has increased since Moodle 3.8. PHP 7.3.x and 7.4.x are supported too.
   1  <?php
   2  
   3  /**

   4   * Parses string representations into their corresponding native PHP

   5   * variable type. The base implementation does a simple type-check.

   6   */
   7  class HTMLPurifier_VarParser
   8  {
   9  
  10      const C_STRING = 1;
  11      const ISTRING = 2;
  12      const TEXT = 3;
  13      const ITEXT = 4;
  14      const C_INT = 5;
  15      const C_FLOAT = 6;
  16      const C_BOOL = 7;
  17      const LOOKUP = 8;
  18      const ALIST = 9;
  19      const HASH = 10;
  20      const C_MIXED = 11;
  21  
  22      /**

  23       * Lookup table of allowed types. Mainly for backwards compatibility, but

  24       * also convenient for transforming string type names to the integer constants.

  25       */
  26      public static $types = array(
  27          'string' => self::C_STRING,
  28          'istring' => self::ISTRING,
  29          'text' => self::TEXT,
  30          'itext' => self::ITEXT,
  31          'int' => self::C_INT,
  32          'float' => self::C_FLOAT,
  33          'bool' => self::C_BOOL,
  34          'lookup' => self::LOOKUP,
  35          'list' => self::ALIST,
  36          'hash' => self::HASH,
  37          'mixed' => self::C_MIXED
  38      );
  39  
  40      /**

  41       * Lookup table of types that are string, and can have aliases or

  42       * allowed value lists.

  43       */
  44      public static $stringTypes = array(
  45          self::C_STRING => true,
  46          self::ISTRING => true,
  47          self::TEXT => true,
  48          self::ITEXT => true,
  49      );
  50  
  51      /**

  52       * Validate a variable according to type.

  53       * It may return NULL as a valid type if $allow_null is true.

  54       *

  55       * @param mixed $var Variable to validate

  56       * @param int $type Type of variable, see HTMLPurifier_VarParser->types

  57       * @param bool $allow_null Whether or not to permit null as a value

  58       * @return string Validated and type-coerced variable

  59       * @throws HTMLPurifier_VarParserException

  60       */
  61      final public function parse($var, $type, $allow_null = false)
  62      {
  63          if (is_string($type)) {
  64              if (!isset(HTMLPurifier_VarParser::$types[$type])) {
  65                  throw new HTMLPurifier_VarParserException("Invalid type '$type'");
  66              } else {
  67                  $type = HTMLPurifier_VarParser::$types[$type];
  68              }
  69          }
  70          $var = $this->parseImplementation($var, $type, $allow_null);
  71          if ($allow_null && $var === null) {
  72              return null;
  73          }
  74          // These are basic checks, to make sure nothing horribly wrong

  75          // happened in our implementations.

  76          switch ($type) {
  77              case (self::C_STRING):
  78              case (self::ISTRING):
  79              case (self::TEXT):
  80              case (self::ITEXT):
  81                  if (!is_string($var)) {
  82                      break;
  83                  }
  84                  if ($type == self::ISTRING || $type == self::ITEXT) {
  85                      $var = strtolower($var);
  86                  }
  87                  return $var;
  88              case (self::C_INT):
  89                  if (!is_int($var)) {
  90                      break;
  91                  }
  92                  return $var;
  93              case (self::C_FLOAT):
  94                  if (!is_float($var)) {
  95                      break;
  96                  }
  97                  return $var;
  98              case (self::C_BOOL):
  99                  if (!is_bool($var)) {
 100                      break;
 101                  }
 102                  return $var;
 103              case (self::LOOKUP):
 104              case (self::ALIST):
 105              case (self::HASH):
 106                  if (!is_array($var)) {
 107                      break;
 108                  }
 109                  if ($type === self::LOOKUP) {
 110                      foreach ($var as $k) {
 111                          if ($k !== true) {
 112                              $this->error('Lookup table contains value other than true');
 113                          }
 114                      }
 115                  } elseif ($type === self::ALIST) {
 116                      $keys = array_keys($var);
 117                      if (array_keys($keys) !== $keys) {
 118                          $this->error('Indices for list are not uniform');
 119                      }
 120                  }
 121                  return $var;
 122              case (self::C_MIXED):
 123                  return $var;
 124              default:
 125                  $this->errorInconsistent(get_class($this), $type);
 126          }
 127          $this->errorGeneric($var, $type);
 128      }
 129  
 130      /**

 131       * Actually implements the parsing. Base implementation does not

 132       * do anything to $var. Subclasses should overload this!

 133       * @param mixed $var

 134       * @param int $type

 135       * @param bool $allow_null

 136       * @return string

 137       */
 138      protected function parseImplementation($var, $type, $allow_null)
 139      {
 140          return $var;
 141      }
 142  
 143      /**

 144       * Throws an exception.

 145       * @throws HTMLPurifier_VarParserException

 146       */
 147      protected function error($msg)
 148      {
 149          throw new HTMLPurifier_VarParserException($msg);
 150      }
 151  
 152      /**

 153       * Throws an inconsistency exception.

 154       * @note This should not ever be called. It would be called if we

 155       *       extend the allowed values of HTMLPurifier_VarParser without

 156       *       updating subclasses.

 157       * @param string $class

 158       * @param int $type

 159       * @throws HTMLPurifier_Exception

 160       */
 161      protected function errorInconsistent($class, $type)
 162      {
 163          throw new HTMLPurifier_Exception(
 164              "Inconsistency in $class: " . HTMLPurifier_VarParser::getTypeName($type) .
 165              " not implemented"
 166          );
 167      }
 168  
 169      /**

 170       * Generic error for if a type didn't work.

 171       * @param mixed $var

 172       * @param int $type

 173       */
 174      protected function errorGeneric($var, $type)
 175      {
 176          $vtype = gettype($var);
 177          $this->error("Expected type " . HTMLPurifier_VarParser::getTypeName($type) . ", got $vtype");
 178      }
 179  
 180      /**

 181       * @param int $type

 182       * @return string

 183       */
 184      public static function getTypeName($type)
 185      {
 186          static $lookup;
 187          if (!$lookup) {
 188              // Lazy load the alternative lookup table

 189              $lookup = array_flip(HTMLPurifier_VarParser::$types);
 190          }
 191          if (!isset($lookup[$type])) {
 192              return 'unknown';
 193          }
 194          return $lookup[$type];
 195      }
 196  }
 197  
 198  // vim: et sw=4 sts=4