]>
Commit | Line | Data |
---|---|---|
d4949327 NL |
1 | <?php\r |
2 | \r | |
3 | /**\r | |
4 | * Represents an XHTML 1.1 module, with information on elements, tags\r | |
5 | * and attributes.\r | |
6 | * @note Even though this is technically XHTML 1.1, it is also used for\r | |
7 | * regular HTML parsing. We are using modulization as a convenient\r | |
8 | * way to represent the internals of HTMLDefinition, and our\r | |
9 | * implementation is by no means conforming and does not directly\r | |
10 | * use the normative DTDs or XML schemas.\r | |
11 | * @note The public variables in a module should almost directly\r | |
12 | * correspond to the variables in HTMLPurifier_HTMLDefinition.\r | |
13 | * However, the prefix info carries no special meaning in these\r | |
14 | * objects (include it anyway if that's the correspondence though).\r | |
15 | * @todo Consider making some member functions protected\r | |
16 | */\r | |
17 | \r | |
18 | class HTMLPurifier_HTMLModule\r | |
19 | {\r | |
20 | \r | |
21 | // -- Overloadable ----------------------------------------------------\r | |
22 | \r | |
23 | /**\r | |
24 | * Short unique string identifier of the module.\r | |
25 | * @type string\r | |
26 | */\r | |
27 | public $name;\r | |
28 | \r | |
29 | /**\r | |
30 | * Informally, a list of elements this module changes.\r | |
31 | * Not used in any significant way.\r | |
32 | * @type array\r | |
33 | */\r | |
34 | public $elements = array();\r | |
35 | \r | |
36 | /**\r | |
37 | * Associative array of element names to element definitions.\r | |
38 | * Some definitions may be incomplete, to be merged in later\r | |
39 | * with the full definition.\r | |
40 | * @type array\r | |
41 | */\r | |
42 | public $info = array();\r | |
43 | \r | |
44 | /**\r | |
45 | * Associative array of content set names to content set additions.\r | |
46 | * This is commonly used to, say, add an A element to the Inline\r | |
47 | * content set. This corresponds to an internal variable $content_sets\r | |
48 | * and NOT info_content_sets member variable of HTMLDefinition.\r | |
49 | * @type array\r | |
50 | */\r | |
51 | public $content_sets = array();\r | |
52 | \r | |
53 | /**\r | |
54 | * Associative array of attribute collection names to attribute\r | |
55 | * collection additions. More rarely used for adding attributes to\r | |
56 | * the global collections. Example is the StyleAttribute module adding\r | |
57 | * the style attribute to the Core. Corresponds to HTMLDefinition's\r | |
58 | * attr_collections->info, since the object's data is only info,\r | |
59 | * with extra behavior associated with it.\r | |
60 | * @type array\r | |
61 | */\r | |
62 | public $attr_collections = array();\r | |
63 | \r | |
64 | /**\r | |
65 | * Associative array of deprecated tag name to HTMLPurifier_TagTransform.\r | |
66 | * @type array\r | |
67 | */\r | |
68 | public $info_tag_transform = array();\r | |
69 | \r | |
70 | /**\r | |
71 | * List of HTMLPurifier_AttrTransform to be performed before validation.\r | |
72 | * @type array\r | |
73 | */\r | |
74 | public $info_attr_transform_pre = array();\r | |
75 | \r | |
76 | /**\r | |
77 | * List of HTMLPurifier_AttrTransform to be performed after validation.\r | |
78 | * @type array\r | |
79 | */\r | |
80 | public $info_attr_transform_post = array();\r | |
81 | \r | |
82 | /**\r | |
83 | * List of HTMLPurifier_Injector to be performed during well-formedness fixing.\r | |
84 | * An injector will only be invoked if all of it's pre-requisites are met;\r | |
85 | * if an injector fails setup, there will be no error; it will simply be\r | |
86 | * silently disabled.\r | |
87 | * @type array\r | |
88 | */\r | |
89 | public $info_injector = array();\r | |
90 | \r | |
91 | /**\r | |
92 | * Boolean flag that indicates whether or not getChildDef is implemented.\r | |
93 | * For optimization reasons: may save a call to a function. Be sure\r | |
94 | * to set it if you do implement getChildDef(), otherwise it will have\r | |
95 | * no effect!\r | |
96 | * @type bool\r | |
97 | */\r | |
98 | public $defines_child_def = false;\r | |
99 | \r | |
100 | /**\r | |
101 | * Boolean flag whether or not this module is safe. If it is not safe, all\r | |
102 | * of its members are unsafe. Modules are safe by default (this might be\r | |
103 | * slightly dangerous, but it doesn't make much sense to force HTML Purifier,\r | |
104 | * which is based off of safe HTML, to explicitly say, "This is safe," even\r | |
105 | * though there are modules which are "unsafe")\r | |
106 | *\r | |
107 | * @type bool\r | |
108 | * @note Previously, safety could be applied at an element level granularity.\r | |
109 | * We've removed this ability, so in order to add "unsafe" elements\r | |
110 | * or attributes, a dedicated module with this property set to false\r | |
111 | * must be used.\r | |
112 | */\r | |
113 | public $safe = true;\r | |
114 | \r | |
115 | /**\r | |
116 | * Retrieves a proper HTMLPurifier_ChildDef subclass based on\r | |
117 | * content_model and content_model_type member variables of\r | |
118 | * the HTMLPurifier_ElementDef class. There is a similar function\r | |
119 | * in HTMLPurifier_HTMLDefinition.\r | |
120 | * @param HTMLPurifier_ElementDef $def\r | |
121 | * @return HTMLPurifier_ChildDef subclass\r | |
122 | */\r | |
123 | public function getChildDef($def)\r | |
124 | {\r | |
125 | return false;\r | |
126 | }\r | |
127 | \r | |
128 | // -- Convenience -----------------------------------------------------\r | |
129 | \r | |
130 | /**\r | |
131 | * Convenience function that sets up a new element\r | |
132 | * @param string $element Name of element to add\r | |
133 | * @param string|bool $type What content set should element be registered to?\r | |
134 | * Set as false to skip this step.\r | |
135 | * @param string $contents Allowed children in form of:\r | |
136 | * "$content_model_type: $content_model"\r | |
137 | * @param array $attr_includes What attribute collections to register to\r | |
138 | * element?\r | |
139 | * @param array $attr What unique attributes does the element define?\r | |
140 | * @see HTMLPurifier_ElementDef:: for in-depth descriptions of these parameters.\r | |
141 | * @return HTMLPurifier_ElementDef Created element definition object, so you\r | |
142 | * can set advanced parameters\r | |
143 | */\r | |
144 | public function addElement($element, $type, $contents, $attr_includes = array(), $attr = array())\r | |
145 | {\r | |
146 | $this->elements[] = $element;\r | |
147 | // parse content_model\r | |
148 | list($content_model_type, $content_model) = $this->parseContents($contents);\r | |
149 | // merge in attribute inclusions\r | |
150 | $this->mergeInAttrIncludes($attr, $attr_includes);\r | |
151 | // add element to content sets\r | |
152 | if ($type) {\r | |
153 | $this->addElementToContentSet($element, $type);\r | |
154 | }\r | |
155 | // create element\r | |
156 | $this->info[$element] = HTMLPurifier_ElementDef::create(\r | |
157 | $content_model,\r | |
158 | $content_model_type,\r | |
159 | $attr\r | |
160 | );\r | |
161 | // literal object $contents means direct child manipulation\r | |
162 | if (!is_string($contents)) {\r | |
163 | $this->info[$element]->child = $contents;\r | |
164 | }\r | |
165 | return $this->info[$element];\r | |
166 | }\r | |
167 | \r | |
168 | /**\r | |
169 | * Convenience function that creates a totally blank, non-standalone\r | |
170 | * element.\r | |
171 | * @param string $element Name of element to create\r | |
172 | * @return HTMLPurifier_ElementDef Created element\r | |
173 | */\r | |
174 | public function addBlankElement($element)\r | |
175 | {\r | |
176 | if (!isset($this->info[$element])) {\r | |
177 | $this->elements[] = $element;\r | |
178 | $this->info[$element] = new HTMLPurifier_ElementDef();\r | |
179 | $this->info[$element]->standalone = false;\r | |
180 | } else {\r | |
181 | trigger_error("Definition for $element already exists in module, cannot redefine");\r | |
182 | }\r | |
183 | return $this->info[$element];\r | |
184 | }\r | |
185 | \r | |
186 | /**\r | |
187 | * Convenience function that registers an element to a content set\r | |
188 | * @param string $element Element to register\r | |
189 | * @param string $type Name content set (warning: case sensitive, usually upper-case\r | |
190 | * first letter)\r | |
191 | */\r | |
192 | public function addElementToContentSet($element, $type)\r | |
193 | {\r | |
194 | if (!isset($this->content_sets[$type])) {\r | |
195 | $this->content_sets[$type] = '';\r | |
196 | } else {\r | |
197 | $this->content_sets[$type] .= ' | ';\r | |
198 | }\r | |
199 | $this->content_sets[$type] .= $element;\r | |
200 | }\r | |
201 | \r | |
202 | /**\r | |
203 | * Convenience function that transforms single-string contents\r | |
204 | * into separate content model and content model type\r | |
205 | * @param string $contents Allowed children in form of:\r | |
206 | * "$content_model_type: $content_model"\r | |
207 | * @return array\r | |
208 | * @note If contents is an object, an array of two nulls will be\r | |
209 | * returned, and the callee needs to take the original $contents\r | |
210 | * and use it directly.\r | |
211 | */\r | |
212 | public function parseContents($contents)\r | |
213 | {\r | |
214 | if (!is_string($contents)) {\r | |
215 | return array(null, null);\r | |
216 | } // defer\r | |
217 | switch ($contents) {\r | |
218 | // check for shorthand content model forms\r | |
219 | case 'Empty':\r | |
220 | return array('empty', '');\r | |
221 | case 'Inline':\r | |
222 | return array('optional', 'Inline | #PCDATA');\r | |
223 | case 'Flow':\r | |
224 | return array('optional', 'Flow | #PCDATA');\r | |
225 | }\r | |
226 | list($content_model_type, $content_model) = explode(':', $contents);\r | |
227 | $content_model_type = strtolower(trim($content_model_type));\r | |
228 | $content_model = trim($content_model);\r | |
229 | return array($content_model_type, $content_model);\r | |
230 | }\r | |
231 | \r | |
232 | /**\r | |
233 | * Convenience function that merges a list of attribute includes into\r | |
234 | * an attribute array.\r | |
235 | * @param array $attr Reference to attr array to modify\r | |
236 | * @param array $attr_includes Array of includes / string include to merge in\r | |
237 | */\r | |
238 | public function mergeInAttrIncludes(&$attr, $attr_includes)\r | |
239 | {\r | |
240 | if (!is_array($attr_includes)) {\r | |
241 | if (empty($attr_includes)) {\r | |
242 | $attr_includes = array();\r | |
243 | } else {\r | |
244 | $attr_includes = array($attr_includes);\r | |
245 | }\r | |
246 | }\r | |
247 | $attr[0] = $attr_includes;\r | |
248 | }\r | |
249 | \r | |
250 | /**\r | |
251 | * Convenience function that generates a lookup table with boolean\r | |
252 | * true as value.\r | |
253 | * @param string $list List of values to turn into a lookup\r | |
254 | * @note You can also pass an arbitrary number of arguments in\r | |
255 | * place of the regular argument\r | |
256 | * @return array array equivalent of list\r | |
257 | */\r | |
258 | public function makeLookup($list)\r | |
259 | {\r | |
260 | if (is_string($list)) {\r | |
261 | $list = func_get_args();\r | |
262 | }\r | |
263 | $ret = array();\r | |
264 | foreach ($list as $value) {\r | |
265 | if (is_null($value)) {\r | |
266 | continue;\r | |
267 | }\r | |
268 | $ret[$value] = true;\r | |
269 | }\r | |
270 | return $ret;\r | |
271 | }\r | |
272 | \r | |
273 | /**\r | |
274 | * Lazy load construction of the module after determining whether\r | |
275 | * or not it's needed, and also when a finalized configuration object\r | |
276 | * is available.\r | |
277 | * @param HTMLPurifier_Config $config\r | |
278 | */\r | |
279 | public function setup($config)\r | |
280 | {\r | |
281 | }\r | |
282 | }\r | |
283 | \r | |
284 | // vim: et sw=4 sts=4\r |