123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128 |
- <?php
- /**
- * Defines common attribute collections that modules reference
- */
- class HTMLPurifier_AttrCollections
- {
- /**
- * Associative array of attribute collections, indexed by name
- */
- public $info = array();
- /**
- * Performs all expansions on internal data for use by other inclusions
- * It also collects all attribute collection extensions from
- * modules
- * @param $attr_types HTMLPurifier_AttrTypes instance
- * @param $modules Hash array of HTMLPurifier_HTMLModule members
- */
- public function __construct($attr_types, $modules) {
- // load extensions from the modules
- foreach ($modules as $module) {
- foreach ($module->attr_collections as $coll_i => $coll) {
- if (!isset($this->info[$coll_i])) {
- $this->info[$coll_i] = array();
- }
- foreach ($coll as $attr_i => $attr) {
- if ($attr_i === 0 && isset($this->info[$coll_i][$attr_i])) {
- // merge in includes
- $this->info[$coll_i][$attr_i] = array_merge(
- $this->info[$coll_i][$attr_i], $attr);
- continue;
- }
- $this->info[$coll_i][$attr_i] = $attr;
- }
- }
- }
- // perform internal expansions and inclusions
- foreach ($this->info as $name => $attr) {
- // merge attribute collections that include others
- $this->performInclusions($this->info[$name]);
- // replace string identifiers with actual attribute objects
- $this->expandIdentifiers($this->info[$name], $attr_types);
- }
- }
- /**
- * Takes a reference to an attribute associative array and performs
- * all inclusions specified by the zero index.
- * @param &$attr Reference to attribute array
- */
- public function performInclusions(&$attr) {
- if (!isset($attr[0])) return;
- $merge = $attr[0];
- $seen = array(); // recursion guard
- // loop through all the inclusions
- for ($i = 0; isset($merge[$i]); $i++) {
- if (isset($seen[$merge[$i]])) continue;
- $seen[$merge[$i]] = true;
- // foreach attribute of the inclusion, copy it over
- if (!isset($this->info[$merge[$i]])) continue;
- foreach ($this->info[$merge[$i]] as $key => $value) {
- if (isset($attr[$key])) continue; // also catches more inclusions
- $attr[$key] = $value;
- }
- if (isset($this->info[$merge[$i]][0])) {
- // recursion
- $merge = array_merge($merge, $this->info[$merge[$i]][0]);
- }
- }
- unset($attr[0]);
- }
- /**
- * Expands all string identifiers in an attribute array by replacing
- * them with the appropriate values inside HTMLPurifier_AttrTypes
- * @param &$attr Reference to attribute array
- * @param $attr_types HTMLPurifier_AttrTypes instance
- */
- public function expandIdentifiers(&$attr, $attr_types) {
- // because foreach will process new elements we add, make sure we
- // skip duplicates
- $processed = array();
- foreach ($attr as $def_i => $def) {
- // skip inclusions
- if ($def_i === 0) continue;
- if (isset($processed[$def_i])) continue;
- // determine whether or not attribute is required
- if ($required = (strpos($def_i, '*') !== false)) {
- // rename the definition
- unset($attr[$def_i]);
- $def_i = trim($def_i, '*');
- $attr[$def_i] = $def;
- }
- $processed[$def_i] = true;
- // if we've already got a literal object, move on
- if (is_object($def)) {
- // preserve previous required
- $attr[$def_i]->required = ($required || $attr[$def_i]->required);
- continue;
- }
- if ($def === false) {
- unset($attr[$def_i]);
- continue;
- }
- if ($t = $attr_types->get($def)) {
- $attr[$def_i] = $t;
- $attr[$def_i]->required = $required;
- } else {
- unset($attr[$def_i]);
- }
- }
- }
- }
- // vim: et sw=4 sts=4
|