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.
   1  <?php
   2  
   3  /**
   4   * @todo Unit test
   5   */
   6  class HTMLPurifier_ContentSets
   7  {
   8  
   9      /**
  10       * List of content set strings (pipe separators) indexed by name.
  11       * @type array
  12       */
  13      public $info = array();
  14  
  15      /**
  16       * List of content set lookups (element => true) indexed by name.
  17       * @type array
  18       * @note This is in HTMLPurifier_HTMLDefinition->info_content_sets
  19       */
  20      public $lookup = array();
  21  
  22      /**
  23       * Synchronized list of defined content sets (keys of info).
  24       * @type array
  25       */
  26      protected $keys = array();
  27      /**
  28       * Synchronized list of defined content values (values of info).
  29       * @type array
  30       */
  31      protected $values = array();
  32  
  33      /**
  34       * Merges in module's content sets, expands identifiers in the content
  35       * sets and populates the keys, values and lookup member variables.
  36       * @param HTMLPurifier_HTMLModule[] $modules List of HTMLPurifier_HTMLModule
  37       */
  38      public function __construct($modules)
  39      {
  40          if (!is_array($modules)) {
  41              $modules = array($modules);
  42          }
  43          // populate content_sets based on module hints
  44          // sorry, no way of overloading
  45          foreach ($modules as $module) {
  46              foreach ($module->content_sets as $key => $value) {
  47                  $temp = $this->convertToLookup($value);
  48                  if (isset($this->lookup[$key])) {
  49                      // add it into the existing content set
  50                      $this->lookup[$key] = array_merge($this->lookup[$key], $temp);
  51                  } else {
  52                      $this->lookup[$key] = $temp;
  53                  }
  54              }
  55          }
  56          $old_lookup = false;
  57          while ($old_lookup !== $this->lookup) {
  58              $old_lookup = $this->lookup;
  59              foreach ($this->lookup as $i => $set) {
  60                  $add = array();
  61                  foreach ($set as $element => $x) {
  62                      if (isset($this->lookup[$element])) {
  63                          $add += $this->lookup[$element];
  64                          unset($this->lookup[$i][$element]);
  65                      }
  66                  }
  67                  $this->lookup[$i] += $add;
  68              }
  69          }
  70  
  71          foreach ($this->lookup as $key => $lookup) {
  72              $this->info[$key] = implode(' | ', array_keys($lookup));
  73          }
  74          $this->keys   = array_keys($this->info);
  75          $this->values = array_values($this->info);
  76      }
  77  
  78      /**
  79       * Accepts a definition; generates and assigns a ChildDef for it
  80       * @param HTMLPurifier_ElementDef $def HTMLPurifier_ElementDef reference
  81       * @param HTMLPurifier_HTMLModule $module Module that defined the ElementDef
  82       */
  83      public function generateChildDef(&$def, $module)
  84      {
  85          if (!empty($def->child)) { // already done!
  86              return;
  87          }
  88          $content_model = $def->content_model;
  89          if (is_string($content_model)) {
  90              // Assume that $this->keys is alphanumeric
  91              $def->content_model = preg_replace_callback(
  92                  '/\b(' . implode('|', $this->keys) . ')\b/',
  93                  array($this, 'generateChildDefCallback'),
  94                  $content_model
  95              );
  96              //$def->content_model = str_replace(
  97              //    $this->keys, $this->values, $content_model);
  98          }
  99          $def->child = $this->getChildDef($def, $module);
 100      }
 101  
 102      public function generateChildDefCallback($matches)
 103      {
 104          return $this->info[$matches[0]];
 105      }
 106  
 107      /**
 108       * Instantiates a ChildDef based on content_model and content_model_type
 109       * member variables in HTMLPurifier_ElementDef
 110       * @note This will also defer to modules for custom HTMLPurifier_ChildDef
 111       *       subclasses that need content set expansion
 112       * @param HTMLPurifier_ElementDef $def HTMLPurifier_ElementDef to have ChildDef extracted
 113       * @param HTMLPurifier_HTMLModule $module Module that defined the ElementDef
 114       * @return HTMLPurifier_ChildDef corresponding to ElementDef
 115       */
 116      public function getChildDef($def, $module)
 117      {
 118          $value = $def->content_model;
 119          if (is_object($value)) {
 120              trigger_error(
 121                  'Literal object child definitions should be stored in '.
 122                  'ElementDef->child not ElementDef->content_model',
 123                  E_USER_NOTICE
 124              );
 125              return $value;
 126          }
 127          switch ($def->content_model_type) {
 128              case 'required':
 129                  return new HTMLPurifier_ChildDef_Required($value);
 130              case 'optional':
 131                  return new HTMLPurifier_ChildDef_Optional($value);
 132              case 'empty':
 133                  return new HTMLPurifier_ChildDef_Empty();
 134              case 'custom':
 135                  return new HTMLPurifier_ChildDef_Custom($value);
 136          }
 137          // defer to its module
 138          $return = false;
 139          if ($module->defines_child_def) { // save a func call
 140              $return = $module->getChildDef($def);
 141          }
 142          if ($return !== false) {
 143              return $return;
 144          }
 145          // error-out
 146          trigger_error(
 147              'Could not determine which ChildDef class to instantiate',
 148              E_USER_ERROR
 149          );
 150          return false;
 151      }
 152  
 153      /**
 154       * Converts a string list of elements separated by pipes into
 155       * a lookup array.
 156       * @param string $string List of elements
 157       * @return array Lookup array of elements
 158       */
 159      protected function convertToLookup($string)
 160      {
 161          $array = explode('|', str_replace(' ', '', $string));
 162          $ret = array();
 163          foreach ($array as $k) {
 164              $ret[$k] = true;
 165          }
 166          return $ret;
 167      }
 168  }
 169  
 170  // vim: et sw=4 sts=4