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   * Defines common attribute collections that modules reference
   5   */
   6  
   7  class HTMLPurifier_AttrCollections
   8  {
   9  
  10      /**
  11       * Associative array of attribute collections, indexed by name.
  12       * @type array
  13       */
  14      public $info = array();
  15  
  16      /**
  17       * Performs all expansions on internal data for use by other inclusions
  18       * It also collects all attribute collection extensions from
  19       * modules
  20       * @param HTMLPurifier_AttrTypes $attr_types HTMLPurifier_AttrTypes instance
  21       * @param HTMLPurifier_HTMLModule[] $modules Hash array of HTMLPurifier_HTMLModule members
  22       */
  23      public function __construct($attr_types, $modules)
  24      {
  25          $this->doConstruct($attr_types, $modules);
  26      }
  27  
  28      public function doConstruct($attr_types, $modules)
  29      {
  30          // load extensions from the modules
  31          foreach ($modules as $module) {
  32              foreach ($module->attr_collections as $coll_i => $coll) {
  33                  if (!isset($this->info[$coll_i])) {
  34                      $this->info[$coll_i] = array();
  35                  }
  36                  foreach ($coll as $attr_i => $attr) {
  37                      if ($attr_i === 0 && isset($this->info[$coll_i][$attr_i])) {
  38                          // merge in includes
  39                          $this->info[$coll_i][$attr_i] = array_merge(
  40                              $this->info[$coll_i][$attr_i],
  41                              $attr
  42                          );
  43                          continue;
  44                      }
  45                      $this->info[$coll_i][$attr_i] = $attr;
  46                  }
  47              }
  48          }
  49          // perform internal expansions and inclusions
  50          foreach ($this->info as $name => $attr) {
  51              // merge attribute collections that include others
  52              $this->performInclusions($this->info[$name]);
  53              // replace string identifiers with actual attribute objects
  54              $this->expandIdentifiers($this->info[$name], $attr_types);
  55          }
  56      }
  57  
  58      /**
  59       * Takes a reference to an attribute associative array and performs
  60       * all inclusions specified by the zero index.
  61       * @param array &$attr Reference to attribute array
  62       */
  63      public function performInclusions(&$attr)
  64      {
  65          if (!isset($attr[0])) {
  66              return;
  67          }
  68          $merge = $attr[0];
  69          $seen  = array(); // recursion guard
  70          // loop through all the inclusions
  71          for ($i = 0; isset($merge[$i]); $i++) {
  72              if (isset($seen[$merge[$i]])) {
  73                  continue;
  74              }
  75              $seen[$merge[$i]] = true;
  76              // foreach attribute of the inclusion, copy it over
  77              if (!isset($this->info[$merge[$i]])) {
  78                  continue;
  79              }
  80              foreach ($this->info[$merge[$i]] as $key => $value) {
  81                  if (isset($attr[$key])) {
  82                      continue;
  83                  } // also catches more inclusions
  84                  $attr[$key] = $value;
  85              }
  86              if (isset($this->info[$merge[$i]][0])) {
  87                  // recursion
  88                  $merge = array_merge($merge, $this->info[$merge[$i]][0]);
  89              }
  90          }
  91          unset($attr[0]);
  92      }
  93  
  94      /**
  95       * Expands all string identifiers in an attribute array by replacing
  96       * them with the appropriate values inside HTMLPurifier_AttrTypes
  97       * @param array &$attr Reference to attribute array
  98       * @param HTMLPurifier_AttrTypes $attr_types HTMLPurifier_AttrTypes instance
  99       */
 100      public function expandIdentifiers(&$attr, $attr_types)
 101      {
 102          // because foreach will process new elements we add, make sure we
 103          // skip duplicates
 104          $processed = array();
 105  
 106          foreach ($attr as $def_i => $def) {
 107              // skip inclusions
 108              if ($def_i === 0) {
 109                  continue;
 110              }
 111  
 112              if (isset($processed[$def_i])) {
 113                  continue;
 114              }
 115  
 116              // determine whether or not attribute is required
 117              if ($required = (strpos($def_i, '*') !== false)) {
 118                  // rename the definition
 119                  unset($attr[$def_i]);
 120                  $def_i = trim($def_i, '*');
 121                  $attr[$def_i] = $def;
 122              }
 123  
 124              $processed[$def_i] = true;
 125  
 126              // if we've already got a literal object, move on
 127              if (is_object($def)) {
 128                  // preserve previous required
 129                  $attr[$def_i]->required = ($required || $attr[$def_i]->required);
 130                  continue;
 131              }
 132  
 133              if ($def === false) {
 134                  unset($attr[$def_i]);
 135                  continue;
 136              }
 137  
 138              if ($t = $attr_types->get($def)) {
 139                  $attr[$def_i] = $t;
 140                  $attr[$def_i]->required = $required;
 141              } else {
 142                  unset($attr[$def_i]);
 143              }
 144          }
 145      }
 146  }
 147  
 148  // vim: et sw=4 sts=4