149 lines
		
	
	
		
			4.7 KiB
		
	
	
	
		
			PHP
		
	
	
		
		
			
		
	
	
			149 lines
		
	
	
		
			4.7 KiB
		
	
	
	
		
			PHP
		
	
	
|  | <?php | ||
|  | 
 | ||
|  | /** | ||
|  |  * Defines common attribute collections that modules reference | ||
|  |  */ | ||
|  | 
 | ||
|  | class HTMLPurifier_AttrCollections | ||
|  | { | ||
|  | 
 | ||
|  |     /** | ||
|  |      * Associative array of attribute collections, indexed by name. | ||
|  |      * @type array | ||
|  |      */ | ||
|  |     public $info = array(); | ||
|  | 
 | ||
|  |     /** | ||
|  |      * Performs all expansions on internal data for use by other inclusions | ||
|  |      * It also collects all attribute collection extensions from | ||
|  |      * modules | ||
|  |      * @param HTMLPurifier_AttrTypes $attr_types HTMLPurifier_AttrTypes instance | ||
|  |      * @param HTMLPurifier_HTMLModule[] $modules Hash array of HTMLPurifier_HTMLModule members | ||
|  |      */ | ||
|  |     public function __construct($attr_types, $modules) | ||
|  |     { | ||
|  |         $this->doConstruct($attr_types, $modules); | ||
|  |     } | ||
|  | 
 | ||
|  |     public function doConstruct($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 array &$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 array &$attr Reference to attribute array | ||
|  |      * @param HTMLPurifier_AttrTypes $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
 |