]>
Commit | Line | Data |
---|---|---|
d4949327 NL |
1 | <?php\r |
2 | \r | |
3 | class HTMLPurifier_Printer_HTMLDefinition extends HTMLPurifier_Printer\r | |
4 | {\r | |
5 | \r | |
6 | /**\r | |
7 | * @type HTMLPurifier_HTMLDefinition, for easy access\r | |
8 | */\r | |
9 | protected $def;\r | |
10 | \r | |
11 | /**\r | |
12 | * @param HTMLPurifier_Config $config\r | |
13 | * @return string\r | |
14 | */\r | |
15 | public function render($config)\r | |
16 | {\r | |
17 | $ret = '';\r | |
18 | $this->config =& $config;\r | |
19 | \r | |
20 | $this->def = $config->getHTMLDefinition();\r | |
21 | \r | |
22 | $ret .= $this->start('div', array('class' => 'HTMLPurifier_Printer'));\r | |
23 | \r | |
24 | $ret .= $this->renderDoctype();\r | |
25 | $ret .= $this->renderEnvironment();\r | |
26 | $ret .= $this->renderContentSets();\r | |
27 | $ret .= $this->renderInfo();\r | |
28 | \r | |
29 | $ret .= $this->end('div');\r | |
30 | \r | |
31 | return $ret;\r | |
32 | }\r | |
33 | \r | |
34 | /**\r | |
35 | * Renders the Doctype table\r | |
36 | * @return string\r | |
37 | */\r | |
38 | protected function renderDoctype()\r | |
39 | {\r | |
40 | $doctype = $this->def->doctype;\r | |
41 | $ret = '';\r | |
42 | $ret .= $this->start('table');\r | |
43 | $ret .= $this->element('caption', 'Doctype');\r | |
44 | $ret .= $this->row('Name', $doctype->name);\r | |
45 | $ret .= $this->row('XML', $doctype->xml ? 'Yes' : 'No');\r | |
46 | $ret .= $this->row('Default Modules', implode($doctype->modules, ', '));\r | |
47 | $ret .= $this->row('Default Tidy Modules', implode($doctype->tidyModules, ', '));\r | |
48 | $ret .= $this->end('table');\r | |
49 | return $ret;\r | |
50 | }\r | |
51 | \r | |
52 | \r | |
53 | /**\r | |
54 | * Renders environment table, which is miscellaneous info\r | |
55 | * @return string\r | |
56 | */\r | |
57 | protected function renderEnvironment()\r | |
58 | {\r | |
59 | $def = $this->def;\r | |
60 | \r | |
61 | $ret = '';\r | |
62 | \r | |
63 | $ret .= $this->start('table');\r | |
64 | $ret .= $this->element('caption', 'Environment');\r | |
65 | \r | |
66 | $ret .= $this->row('Parent of fragment', $def->info_parent);\r | |
67 | $ret .= $this->renderChildren($def->info_parent_def->child);\r | |
68 | $ret .= $this->row('Block wrap name', $def->info_block_wrapper);\r | |
69 | \r | |
70 | $ret .= $this->start('tr');\r | |
71 | $ret .= $this->element('th', 'Global attributes');\r | |
72 | $ret .= $this->element('td', $this->listifyAttr($def->info_global_attr), null, 0);\r | |
73 | $ret .= $this->end('tr');\r | |
74 | \r | |
75 | $ret .= $this->start('tr');\r | |
76 | $ret .= $this->element('th', 'Tag transforms');\r | |
77 | $list = array();\r | |
78 | foreach ($def->info_tag_transform as $old => $new) {\r | |
79 | $new = $this->getClass($new, 'TagTransform_');\r | |
80 | $list[] = "<$old> with $new";\r | |
81 | }\r | |
82 | $ret .= $this->element('td', $this->listify($list));\r | |
83 | $ret .= $this->end('tr');\r | |
84 | \r | |
85 | $ret .= $this->start('tr');\r | |
86 | $ret .= $this->element('th', 'Pre-AttrTransform');\r | |
87 | $ret .= $this->element('td', $this->listifyObjectList($def->info_attr_transform_pre));\r | |
88 | $ret .= $this->end('tr');\r | |
89 | \r | |
90 | $ret .= $this->start('tr');\r | |
91 | $ret .= $this->element('th', 'Post-AttrTransform');\r | |
92 | $ret .= $this->element('td', $this->listifyObjectList($def->info_attr_transform_post));\r | |
93 | $ret .= $this->end('tr');\r | |
94 | \r | |
95 | $ret .= $this->end('table');\r | |
96 | return $ret;\r | |
97 | }\r | |
98 | \r | |
99 | /**\r | |
100 | * Renders the Content Sets table\r | |
101 | * @return string\r | |
102 | */\r | |
103 | protected function renderContentSets()\r | |
104 | {\r | |
105 | $ret = '';\r | |
106 | $ret .= $this->start('table');\r | |
107 | $ret .= $this->element('caption', 'Content Sets');\r | |
108 | foreach ($this->def->info_content_sets as $name => $lookup) {\r | |
109 | $ret .= $this->heavyHeader($name);\r | |
110 | $ret .= $this->start('tr');\r | |
111 | $ret .= $this->element('td', $this->listifyTagLookup($lookup));\r | |
112 | $ret .= $this->end('tr');\r | |
113 | }\r | |
114 | $ret .= $this->end('table');\r | |
115 | return $ret;\r | |
116 | }\r | |
117 | \r | |
118 | /**\r | |
119 | * Renders the Elements ($info) table\r | |
120 | * @return string\r | |
121 | */\r | |
122 | protected function renderInfo()\r | |
123 | {\r | |
124 | $ret = '';\r | |
125 | $ret .= $this->start('table');\r | |
126 | $ret .= $this->element('caption', 'Elements ($info)');\r | |
127 | ksort($this->def->info);\r | |
128 | $ret .= $this->heavyHeader('Allowed tags', 2);\r | |
129 | $ret .= $this->start('tr');\r | |
130 | $ret .= $this->element('td', $this->listifyTagLookup($this->def->info), array('colspan' => 2));\r | |
131 | $ret .= $this->end('tr');\r | |
132 | foreach ($this->def->info as $name => $def) {\r | |
133 | $ret .= $this->start('tr');\r | |
134 | $ret .= $this->element('th', "<$name>", array('class' => 'heavy', 'colspan' => 2));\r | |
135 | $ret .= $this->end('tr');\r | |
136 | $ret .= $this->start('tr');\r | |
137 | $ret .= $this->element('th', 'Inline content');\r | |
138 | $ret .= $this->element('td', $def->descendants_are_inline ? 'Yes' : 'No');\r | |
139 | $ret .= $this->end('tr');\r | |
140 | if (!empty($def->excludes)) {\r | |
141 | $ret .= $this->start('tr');\r | |
142 | $ret .= $this->element('th', 'Excludes');\r | |
143 | $ret .= $this->element('td', $this->listifyTagLookup($def->excludes));\r | |
144 | $ret .= $this->end('tr');\r | |
145 | }\r | |
146 | if (!empty($def->attr_transform_pre)) {\r | |
147 | $ret .= $this->start('tr');\r | |
148 | $ret .= $this->element('th', 'Pre-AttrTransform');\r | |
149 | $ret .= $this->element('td', $this->listifyObjectList($def->attr_transform_pre));\r | |
150 | $ret .= $this->end('tr');\r | |
151 | }\r | |
152 | if (!empty($def->attr_transform_post)) {\r | |
153 | $ret .= $this->start('tr');\r | |
154 | $ret .= $this->element('th', 'Post-AttrTransform');\r | |
155 | $ret .= $this->element('td', $this->listifyObjectList($def->attr_transform_post));\r | |
156 | $ret .= $this->end('tr');\r | |
157 | }\r | |
158 | if (!empty($def->auto_close)) {\r | |
159 | $ret .= $this->start('tr');\r | |
160 | $ret .= $this->element('th', 'Auto closed by');\r | |
161 | $ret .= $this->element('td', $this->listifyTagLookup($def->auto_close));\r | |
162 | $ret .= $this->end('tr');\r | |
163 | }\r | |
164 | $ret .= $this->start('tr');\r | |
165 | $ret .= $this->element('th', 'Allowed attributes');\r | |
166 | $ret .= $this->element('td', $this->listifyAttr($def->attr), array(), 0);\r | |
167 | $ret .= $this->end('tr');\r | |
168 | \r | |
169 | if (!empty($def->required_attr)) {\r | |
170 | $ret .= $this->row('Required attributes', $this->listify($def->required_attr));\r | |
171 | }\r | |
172 | \r | |
173 | $ret .= $this->renderChildren($def->child);\r | |
174 | }\r | |
175 | $ret .= $this->end('table');\r | |
176 | return $ret;\r | |
177 | }\r | |
178 | \r | |
179 | /**\r | |
180 | * Renders a row describing the allowed children of an element\r | |
181 | * @param HTMLPurifier_ChildDef $def HTMLPurifier_ChildDef of pertinent element\r | |
182 | * @return string\r | |
183 | */\r | |
184 | protected function renderChildren($def)\r | |
185 | {\r | |
186 | $context = new HTMLPurifier_Context();\r | |
187 | $ret = '';\r | |
188 | $ret .= $this->start('tr');\r | |
189 | $elements = array();\r | |
190 | $attr = array();\r | |
191 | if (isset($def->elements)) {\r | |
192 | if ($def->type == 'strictblockquote') {\r | |
193 | $def->validateChildren(array(), $this->config, $context);\r | |
194 | }\r | |
195 | $elements = $def->elements;\r | |
196 | }\r | |
197 | if ($def->type == 'chameleon') {\r | |
198 | $attr['rowspan'] = 2;\r | |
199 | } elseif ($def->type == 'empty') {\r | |
200 | $elements = array();\r | |
201 | } elseif ($def->type == 'table') {\r | |
202 | $elements = array_flip(\r | |
203 | array(\r | |
204 | 'col',\r | |
205 | 'caption',\r | |
206 | 'colgroup',\r | |
207 | 'thead',\r | |
208 | 'tfoot',\r | |
209 | 'tbody',\r | |
210 | 'tr'\r | |
211 | )\r | |
212 | );\r | |
213 | }\r | |
214 | $ret .= $this->element('th', 'Allowed children', $attr);\r | |
215 | \r | |
216 | if ($def->type == 'chameleon') {\r | |
217 | \r | |
218 | $ret .= $this->element(\r | |
219 | 'td',\r | |
220 | '<em>Block</em>: ' .\r | |
221 | $this->escape($this->listifyTagLookup($def->block->elements)),\r | |
222 | null,\r | |
223 | 0\r | |
224 | );\r | |
225 | $ret .= $this->end('tr');\r | |
226 | $ret .= $this->start('tr');\r | |
227 | $ret .= $this->element(\r | |
228 | 'td',\r | |
229 | '<em>Inline</em>: ' .\r | |
230 | $this->escape($this->listifyTagLookup($def->inline->elements)),\r | |
231 | null,\r | |
232 | 0\r | |
233 | );\r | |
234 | \r | |
235 | } elseif ($def->type == 'custom') {\r | |
236 | \r | |
237 | $ret .= $this->element(\r | |
238 | 'td',\r | |
239 | '<em>' . ucfirst($def->type) . '</em>: ' .\r | |
240 | $def->dtd_regex\r | |
241 | );\r | |
242 | \r | |
243 | } else {\r | |
244 | $ret .= $this->element(\r | |
245 | 'td',\r | |
246 | '<em>' . ucfirst($def->type) . '</em>: ' .\r | |
247 | $this->escape($this->listifyTagLookup($elements)),\r | |
248 | null,\r | |
249 | 0\r | |
250 | );\r | |
251 | }\r | |
252 | $ret .= $this->end('tr');\r | |
253 | return $ret;\r | |
254 | }\r | |
255 | \r | |
256 | /**\r | |
257 | * Listifies a tag lookup table.\r | |
258 | * @param array $array Tag lookup array in form of array('tagname' => true)\r | |
259 | * @return string\r | |
260 | */\r | |
261 | protected function listifyTagLookup($array)\r | |
262 | {\r | |
263 | ksort($array);\r | |
264 | $list = array();\r | |
265 | foreach ($array as $name => $discard) {\r | |
266 | if ($name !== '#PCDATA' && !isset($this->def->info[$name])) {\r | |
267 | continue;\r | |
268 | }\r | |
269 | $list[] = $name;\r | |
270 | }\r | |
271 | return $this->listify($list);\r | |
272 | }\r | |
273 | \r | |
274 | /**\r | |
275 | * Listifies a list of objects by retrieving class names and internal state\r | |
276 | * @param array $array List of objects\r | |
277 | * @return string\r | |
278 | * @todo Also add information about internal state\r | |
279 | */\r | |
280 | protected function listifyObjectList($array)\r | |
281 | {\r | |
282 | ksort($array);\r | |
283 | $list = array();\r | |
284 | foreach ($array as $obj) {\r | |
285 | $list[] = $this->getClass($obj, 'AttrTransform_');\r | |
286 | }\r | |
287 | return $this->listify($list);\r | |
288 | }\r | |
289 | \r | |
290 | /**\r | |
291 | * Listifies a hash of attributes to AttrDef classes\r | |
292 | * @param array $array Array hash in form of array('attrname' => HTMLPurifier_AttrDef)\r | |
293 | * @return string\r | |
294 | */\r | |
295 | protected function listifyAttr($array)\r | |
296 | {\r | |
297 | ksort($array);\r | |
298 | $list = array();\r | |
299 | foreach ($array as $name => $obj) {\r | |
300 | if ($obj === false) {\r | |
301 | continue;\r | |
302 | }\r | |
303 | $list[] = "$name = <i>" . $this->getClass($obj, 'AttrDef_') . '</i>';\r | |
304 | }\r | |
305 | return $this->listify($list);\r | |
306 | }\r | |
307 | \r | |
308 | /**\r | |
309 | * Creates a heavy header row\r | |
310 | * @param string $text\r | |
311 | * @param int $num\r | |
312 | * @return string\r | |
313 | */\r | |
314 | protected function heavyHeader($text, $num = 1)\r | |
315 | {\r | |
316 | $ret = '';\r | |
317 | $ret .= $this->start('tr');\r | |
318 | $ret .= $this->element('th', $text, array('colspan' => $num, 'class' => 'heavy'));\r | |
319 | $ret .= $this->end('tr');\r | |
320 | return $ret;\r | |
321 | }\r | |
322 | }\r | |
323 | \r | |
324 | // vim: et sw=4 sts=4\r |