Yaffs site version 1.1
[yaffs-website] / vendor / ezyang / htmlpurifier / library / HTMLPurifier / ContentSets.php
1 <?php
2
3 /**
4  * @todo Unit test
5  */
6 class HTMLPurifier_ContentSets
7 {
8
9     /**
10      * List of content set strings (pipe separators) indexed by name.
11      * @type array
12      */
13     public $info = array();
14
15     /**
16      * List of content set lookups (element => true) indexed by name.
17      * @type array
18      * @note This is in HTMLPurifier_HTMLDefinition->info_content_sets
19      */
20     public $lookup = array();
21
22     /**
23      * Synchronized list of defined content sets (keys of info).
24      * @type array
25      */
26     protected $keys = array();
27     /**
28      * Synchronized list of defined content values (values of info).
29      * @type array
30      */
31     protected $values = array();
32
33     /**
34      * Merges in module's content sets, expands identifiers in the content
35      * sets and populates the keys, values and lookup member variables.
36      * @param HTMLPurifier_HTMLModule[] $modules List of HTMLPurifier_HTMLModule
37      */
38     public function __construct($modules)
39     {
40         if (!is_array($modules)) {
41             $modules = array($modules);
42         }
43         // populate content_sets based on module hints
44         // sorry, no way of overloading
45         foreach ($modules as $module) {
46             foreach ($module->content_sets as $key => $value) {
47                 $temp = $this->convertToLookup($value);
48                 if (isset($this->lookup[$key])) {
49                     // add it into the existing content set
50                     $this->lookup[$key] = array_merge($this->lookup[$key], $temp);
51                 } else {
52                     $this->lookup[$key] = $temp;
53                 }
54             }
55         }
56         $old_lookup = false;
57         while ($old_lookup !== $this->lookup) {
58             $old_lookup = $this->lookup;
59             foreach ($this->lookup as $i => $set) {
60                 $add = array();
61                 foreach ($set as $element => $x) {
62                     if (isset($this->lookup[$element])) {
63                         $add += $this->lookup[$element];
64                         unset($this->lookup[$i][$element]);
65                     }
66                 }
67                 $this->lookup[$i] += $add;
68             }
69         }
70
71         foreach ($this->lookup as $key => $lookup) {
72             $this->info[$key] = implode(' | ', array_keys($lookup));
73         }
74         $this->keys   = array_keys($this->info);
75         $this->values = array_values($this->info);
76     }
77
78     /**
79      * Accepts a definition; generates and assigns a ChildDef for it
80      * @param HTMLPurifier_ElementDef $def HTMLPurifier_ElementDef reference
81      * @param HTMLPurifier_HTMLModule $module Module that defined the ElementDef
82      */
83     public function generateChildDef(&$def, $module)
84     {
85         if (!empty($def->child)) { // already done!
86             return;
87         }
88         $content_model = $def->content_model;
89         if (is_string($content_model)) {
90             // Assume that $this->keys is alphanumeric
91             $def->content_model = preg_replace_callback(
92                 '/\b(' . implode('|', $this->keys) . ')\b/',
93                 array($this, 'generateChildDefCallback'),
94                 $content_model
95             );
96             //$def->content_model = str_replace(
97             //    $this->keys, $this->values, $content_model);
98         }
99         $def->child = $this->getChildDef($def, $module);
100     }
101
102     public function generateChildDefCallback($matches)
103     {
104         return $this->info[$matches[0]];
105     }
106
107     /**
108      * Instantiates a ChildDef based on content_model and content_model_type
109      * member variables in HTMLPurifier_ElementDef
110      * @note This will also defer to modules for custom HTMLPurifier_ChildDef
111      *       subclasses that need content set expansion
112      * @param HTMLPurifier_ElementDef $def HTMLPurifier_ElementDef to have ChildDef extracted
113      * @param HTMLPurifier_HTMLModule $module Module that defined the ElementDef
114      * @return HTMLPurifier_ChildDef corresponding to ElementDef
115      */
116     public function getChildDef($def, $module)
117     {
118         $value = $def->content_model;
119         if (is_object($value)) {
120             trigger_error(
121                 'Literal object child definitions should be stored in '.
122                 'ElementDef->child not ElementDef->content_model',
123                 E_USER_NOTICE
124             );
125             return $value;
126         }
127         switch ($def->content_model_type) {
128             case 'required':
129                 return new HTMLPurifier_ChildDef_Required($value);
130             case 'optional':
131                 return new HTMLPurifier_ChildDef_Optional($value);
132             case 'empty':
133                 return new HTMLPurifier_ChildDef_Empty();
134             case 'custom':
135                 return new HTMLPurifier_ChildDef_Custom($value);
136         }
137         // defer to its module
138         $return = false;
139         if ($module->defines_child_def) { // save a func call
140             $return = $module->getChildDef($def);
141         }
142         if ($return !== false) {
143             return $return;
144         }
145         // error-out
146         trigger_error(
147             'Could not determine which ChildDef class to instantiate',
148             E_USER_ERROR
149         );
150         return false;
151     }
152
153     /**
154      * Converts a string list of elements separated by pipes into
155      * a lookup array.
156      * @param string $string List of elements
157      * @return array Lookup array of elements
158      */
159     protected function convertToLookup($string)
160     {
161         $array = explode('|', str_replace(' ', '', $string));
162         $ret = array();
163         foreach ($array as $k) {
164             $ret[$k] = true;
165         }
166         return $ret;
167     }
168 }
169
170 // vim: et sw=4 sts=4