HTMLPurifier 4.4.0
|
00001 <?php 00002 00007 class HTMLPurifier_AttrCollections 00008 { 00009 00013 public $info = array(); 00014 00022 public function __construct($attr_types, $modules) { 00023 // load extensions from the modules 00024 foreach ($modules as $module) { 00025 foreach ($module->attr_collections as $coll_i => $coll) { 00026 if (!isset($this->info[$coll_i])) { 00027 $this->info[$coll_i] = array(); 00028 } 00029 foreach ($coll as $attr_i => $attr) { 00030 if ($attr_i === 0 && isset($this->info[$coll_i][$attr_i])) { 00031 // merge in includes 00032 $this->info[$coll_i][$attr_i] = array_merge( 00033 $this->info[$coll_i][$attr_i], $attr); 00034 continue; 00035 } 00036 $this->info[$coll_i][$attr_i] = $attr; 00037 } 00038 } 00039 } 00040 // perform internal expansions and inclusions 00041 foreach ($this->info as $name => $attr) { 00042 // merge attribute collections that include others 00043 $this->performInclusions($this->info[$name]); 00044 // replace string identifiers with actual attribute objects 00045 $this->expandIdentifiers($this->info[$name], $attr_types); 00046 } 00047 } 00048 00054 public function performInclusions(&$attr) { 00055 if (!isset($attr[0])) return; 00056 $merge = $attr[0]; 00057 $seen = array(); // recursion guard 00058 // loop through all the inclusions 00059 for ($i = 0; isset($merge[$i]); $i++) { 00060 if (isset($seen[$merge[$i]])) continue; 00061 $seen[$merge[$i]] = true; 00062 // foreach attribute of the inclusion, copy it over 00063 if (!isset($this->info[$merge[$i]])) continue; 00064 foreach ($this->info[$merge[$i]] as $key => $value) { 00065 if (isset($attr[$key])) continue; // also catches more inclusions 00066 $attr[$key] = $value; 00067 } 00068 if (isset($this->info[$merge[$i]][0])) { 00069 // recursion 00070 $merge = array_merge($merge, $this->info[$merge[$i]][0]); 00071 } 00072 } 00073 unset($attr[0]); 00074 } 00075 00082 public function expandIdentifiers(&$attr, $attr_types) { 00083 00084 // because foreach will process new elements we add, make sure we 00085 // skip duplicates 00086 $processed = array(); 00087 00088 foreach ($attr as $def_i => $def) { 00089 // skip inclusions 00090 if ($def_i === 0) continue; 00091 00092 if (isset($processed[$def_i])) continue; 00093 00094 // determine whether or not attribute is required 00095 if ($required = (strpos($def_i, '*') !== false)) { 00096 // rename the definition 00097 unset($attr[$def_i]); 00098 $def_i = trim($def_i, '*'); 00099 $attr[$def_i] = $def; 00100 } 00101 00102 $processed[$def_i] = true; 00103 00104 // if we've already got a literal object, move on 00105 if (is_object($def)) { 00106 // preserve previous required 00107 $attr[$def_i]->required = ($required || $attr[$def_i]->required); 00108 continue; 00109 } 00110 00111 if ($def === false) { 00112 unset($attr[$def_i]); 00113 continue; 00114 } 00115 00116 if ($t = $attr_types->get($def)) { 00117 $attr[$def_i] = $t; 00118 $attr[$def_i]->required = $required; 00119 } else { 00120 unset($attr[$def_i]); 00121 } 00122 } 00123 00124 } 00125 00126 } 00127 00128 // vim: et sw=4 sts=4