171 lines
		
	
	
		
			5.5 KiB
		
	
	
	
		
			PHP
		
	
	
		
		
			
		
	
	
			171 lines
		
	
	
		
			5.5 KiB
		
	
	
	
		
			PHP
		
	
	
|  | <?php | ||
|  | 
 | ||
|  | /** | ||
|  |  * @todo Unit test | ||
|  |  */ | ||
|  | class HTMLPurifier_ContentSets | ||
|  | { | ||
|  | 
 | ||
|  |     /** | ||
|  |      * List of content set strings (pipe separators) indexed by name. | ||
|  |      * @type array | ||
|  |      */ | ||
|  |     public $info = array(); | ||
|  | 
 | ||
|  |     /** | ||
|  |      * List of content set lookups (element => true) indexed by name. | ||
|  |      * @type array | ||
|  |      * @note This is in HTMLPurifier_HTMLDefinition->info_content_sets | ||
|  |      */ | ||
|  |     public $lookup = array(); | ||
|  | 
 | ||
|  |     /** | ||
|  |      * Synchronized list of defined content sets (keys of info). | ||
|  |      * @type array | ||
|  |      */ | ||
|  |     protected $keys = array(); | ||
|  |     /** | ||
|  |      * Synchronized list of defined content values (values of info). | ||
|  |      * @type array | ||
|  |      */ | ||
|  |     protected $values = array(); | ||
|  | 
 | ||
|  |     /** | ||
|  |      * Merges in module's content sets, expands identifiers in the content | ||
|  |      * sets and populates the keys, values and lookup member variables. | ||
|  |      * @param HTMLPurifier_HTMLModule[] $modules List of HTMLPurifier_HTMLModule | ||
|  |      */ | ||
|  |     public function __construct($modules) | ||
|  |     { | ||
|  |         if (!is_array($modules)) { | ||
|  |             $modules = array($modules); | ||
|  |         } | ||
|  |         // populate content_sets based on module hints
 | ||
|  |         // sorry, no way of overloading
 | ||
|  |         foreach ($modules as $module) { | ||
|  |             foreach ($module->content_sets as $key => $value) { | ||
|  |                 $temp = $this->convertToLookup($value); | ||
|  |                 if (isset($this->lookup[$key])) { | ||
|  |                     // add it into the existing content set
 | ||
|  |                     $this->lookup[$key] = array_merge($this->lookup[$key], $temp); | ||
|  |                 } else { | ||
|  |                     $this->lookup[$key] = $temp; | ||
|  |                 } | ||
|  |             } | ||
|  |         } | ||
|  |         $old_lookup = false; | ||
|  |         while ($old_lookup !== $this->lookup) { | ||
|  |             $old_lookup = $this->lookup; | ||
|  |             foreach ($this->lookup as $i => $set) { | ||
|  |                 $add = array(); | ||
|  |                 foreach ($set as $element => $x) { | ||
|  |                     if (isset($this->lookup[$element])) { | ||
|  |                         $add += $this->lookup[$element]; | ||
|  |                         unset($this->lookup[$i][$element]); | ||
|  |                     } | ||
|  |                 } | ||
|  |                 $this->lookup[$i] += $add; | ||
|  |             } | ||
|  |         } | ||
|  | 
 | ||
|  |         foreach ($this->lookup as $key => $lookup) { | ||
|  |             $this->info[$key] = implode(' | ', array_keys($lookup)); | ||
|  |         } | ||
|  |         $this->keys   = array_keys($this->info); | ||
|  |         $this->values = array_values($this->info); | ||
|  |     } | ||
|  | 
 | ||
|  |     /** | ||
|  |      * Accepts a definition; generates and assigns a ChildDef for it | ||
|  |      * @param HTMLPurifier_ElementDef $def HTMLPurifier_ElementDef reference | ||
|  |      * @param HTMLPurifier_HTMLModule $module Module that defined the ElementDef | ||
|  |      */ | ||
|  |     public function generateChildDef(&$def, $module) | ||
|  |     { | ||
|  |         if (!empty($def->child)) { // already done!
 | ||
|  |             return; | ||
|  |         } | ||
|  |         $content_model = $def->content_model; | ||
|  |         if (is_string($content_model)) { | ||
|  |             // Assume that $this->keys is alphanumeric
 | ||
|  |             $def->content_model = preg_replace_callback( | ||
|  |                 '/\b(' . implode('|', $this->keys) . ')\b/', | ||
|  |                 array($this, 'generateChildDefCallback'), | ||
|  |                 $content_model | ||
|  |             ); | ||
|  |             //$def->content_model = str_replace(
 | ||
|  |             //    $this->keys, $this->values, $content_model);
 | ||
|  |         } | ||
|  |         $def->child = $this->getChildDef($def, $module); | ||
|  |     } | ||
|  | 
 | ||
|  |     public function generateChildDefCallback($matches) | ||
|  |     { | ||
|  |         return $this->info[$matches[0]]; | ||
|  |     } | ||
|  | 
 | ||
|  |     /** | ||
|  |      * Instantiates a ChildDef based on content_model and content_model_type | ||
|  |      * member variables in HTMLPurifier_ElementDef | ||
|  |      * @note This will also defer to modules for custom HTMLPurifier_ChildDef | ||
|  |      *       subclasses that need content set expansion | ||
|  |      * @param HTMLPurifier_ElementDef $def HTMLPurifier_ElementDef to have ChildDef extracted | ||
|  |      * @param HTMLPurifier_HTMLModule $module Module that defined the ElementDef | ||
|  |      * @return HTMLPurifier_ChildDef corresponding to ElementDef | ||
|  |      */ | ||
|  |     public function getChildDef($def, $module) | ||
|  |     { | ||
|  |         $value = $def->content_model; | ||
|  |         if (is_object($value)) { | ||
|  |             trigger_error( | ||
|  |                 'Literal object child definitions should be stored in '. | ||
|  |                 'ElementDef->child not ElementDef->content_model', | ||
|  |                 E_USER_NOTICE | ||
|  |             ); | ||
|  |             return $value; | ||
|  |         } | ||
|  |         switch ($def->content_model_type) { | ||
|  |             case 'required': | ||
|  |                 return new HTMLPurifier_ChildDef_Required($value); | ||
|  |             case 'optional': | ||
|  |                 return new HTMLPurifier_ChildDef_Optional($value); | ||
|  |             case 'empty': | ||
|  |                 return new HTMLPurifier_ChildDef_Empty(); | ||
|  |             case 'custom': | ||
|  |                 return new HTMLPurifier_ChildDef_Custom($value); | ||
|  |         } | ||
|  |         // defer to its module
 | ||
|  |         $return = false; | ||
|  |         if ($module->defines_child_def) { // save a func call
 | ||
|  |             $return = $module->getChildDef($def); | ||
|  |         } | ||
|  |         if ($return !== false) { | ||
|  |             return $return; | ||
|  |         } | ||
|  |         // error-out
 | ||
|  |         trigger_error( | ||
|  |             'Could not determine which ChildDef class to instantiate', | ||
|  |             E_USER_ERROR | ||
|  |         ); | ||
|  |         return false; | ||
|  |     } | ||
|  | 
 | ||
|  |     /** | ||
|  |      * Converts a string list of elements separated by pipes into | ||
|  |      * a lookup array. | ||
|  |      * @param string $string List of elements | ||
|  |      * @return array Lookup array of elements | ||
|  |      */ | ||
|  |     protected function convertToLookup($string) | ||
|  |     { | ||
|  |         $array = explode('|', str_replace(' ', '', $string)); | ||
|  |         $ret = array(); | ||
|  |         foreach ($array as $k) { | ||
|  |             $ret[$k] = true; | ||
|  |         } | ||
|  |         return $ret; | ||
|  |     } | ||
|  | } | ||
|  | 
 | ||
|  | // vim: et sw=4 sts=4
 |