File indexing completed on 2024-12-22 05:36:21
0001 <?php 0002 0003 /** 0004 * Defines common attribute collections that modules reference 0005 */ 0006 0007 class HTMLPurifier_AttrCollections 0008 { 0009 0010 /** 0011 * Associative array of attribute collections, indexed by name. 0012 * @type array 0013 */ 0014 public $info = array(); 0015 0016 /** 0017 * Performs all expansions on internal data for use by other inclusions 0018 * It also collects all attribute collection extensions from 0019 * modules 0020 * @param HTMLPurifier_AttrTypes $attr_types HTMLPurifier_AttrTypes instance 0021 * @param HTMLPurifier_HTMLModule[] $modules Hash array of HTMLPurifier_HTMLModule members 0022 */ 0023 public function __construct($attr_types, $modules) 0024 { 0025 $this->doConstruct($attr_types, $modules); 0026 } 0027 0028 public function doConstruct($attr_types, $modules) 0029 { 0030 // load extensions from the modules 0031 foreach ($modules as $module) { 0032 foreach ($module->attr_collections as $coll_i => $coll) { 0033 if (!isset($this->info[$coll_i])) { 0034 $this->info[$coll_i] = array(); 0035 } 0036 foreach ($coll as $attr_i => $attr) { 0037 if ($attr_i === 0 && isset($this->info[$coll_i][$attr_i])) { 0038 // merge in includes 0039 $this->info[$coll_i][$attr_i] = array_merge( 0040 $this->info[$coll_i][$attr_i], 0041 $attr 0042 ); 0043 continue; 0044 } 0045 $this->info[$coll_i][$attr_i] = $attr; 0046 } 0047 } 0048 } 0049 // perform internal expansions and inclusions 0050 foreach ($this->info as $name => $attr) { 0051 // merge attribute collections that include others 0052 $this->performInclusions($this->info[$name]); 0053 // replace string identifiers with actual attribute objects 0054 $this->expandIdentifiers($this->info[$name], $attr_types); 0055 } 0056 } 0057 0058 /** 0059 * Takes a reference to an attribute associative array and performs 0060 * all inclusions specified by the zero index. 0061 * @param array &$attr Reference to attribute array 0062 */ 0063 public function performInclusions(&$attr) 0064 { 0065 if (!isset($attr[0])) { 0066 return; 0067 } 0068 $merge = $attr[0]; 0069 $seen = array(); // recursion guard 0070 // loop through all the inclusions 0071 for ($i = 0; isset($merge[$i]); $i++) { 0072 if (isset($seen[$merge[$i]])) { 0073 continue; 0074 } 0075 $seen[$merge[$i]] = true; 0076 // foreach attribute of the inclusion, copy it over 0077 if (!isset($this->info[$merge[$i]])) { 0078 continue; 0079 } 0080 foreach ($this->info[$merge[$i]] as $key => $value) { 0081 if (isset($attr[$key])) { 0082 continue; 0083 } // also catches more inclusions 0084 $attr[$key] = $value; 0085 } 0086 if (isset($this->info[$merge[$i]][0])) { 0087 // recursion 0088 $merge = array_merge($merge, $this->info[$merge[$i]][0]); 0089 } 0090 } 0091 unset($attr[0]); 0092 } 0093 0094 /** 0095 * Expands all string identifiers in an attribute array by replacing 0096 * them with the appropriate values inside HTMLPurifier_AttrTypes 0097 * @param array &$attr Reference to attribute array 0098 * @param HTMLPurifier_AttrTypes $attr_types HTMLPurifier_AttrTypes instance 0099 */ 0100 public function expandIdentifiers(&$attr, $attr_types) 0101 { 0102 // because foreach will process new elements we add, make sure we 0103 // skip duplicates 0104 $processed = array(); 0105 0106 foreach ($attr as $def_i => $def) { 0107 // skip inclusions 0108 if ($def_i === 0) { 0109 continue; 0110 } 0111 0112 if (isset($processed[$def_i])) { 0113 continue; 0114 } 0115 0116 // determine whether or not attribute is required 0117 if ($required = (strpos($def_i, '*') !== false)) { 0118 // rename the definition 0119 unset($attr[$def_i]); 0120 $def_i = trim($def_i, '*'); 0121 $attr[$def_i] = $def; 0122 } 0123 0124 $processed[$def_i] = true; 0125 0126 // if we've already got a literal object, move on 0127 if (is_object($def)) { 0128 // preserve previous required 0129 $attr[$def_i]->required = ($required || $attr[$def_i]->required); 0130 continue; 0131 } 0132 0133 if ($def === false) { 0134 unset($attr[$def_i]); 0135 continue; 0136 } 0137 0138 if ($t = $attr_types->get($def)) { 0139 $attr[$def_i] = $t; 0140 $attr[$def_i]->required = $required; 0141 } else { 0142 unset($attr[$def_i]); 0143 } 0144 } 0145 } 0146 } 0147 0148 // vim: et sw=4 sts=4