diff options
author | Nicolas LÅ“uillet <nicolas@loeuillet.org> | 2014-02-21 15:57:10 +0100 |
---|---|---|
committer | Nicolas LÅ“uillet <nicolas@loeuillet.org> | 2014-02-21 15:57:10 +0100 |
commit | 99679d06884120c57f43b44e55e03595f1f87bed (patch) | |
tree | a3f2a1aa1afdaeca1386d0c6e8a75344fd2241fb /inc/3rdparty/htmlpurifier/HTMLPurifier/Printer | |
parent | 655214ab30ee84884dc408488b85586f36263fcb (diff) | |
parent | d3b47e94705e17b3ba3529cbb1dc6efe69c5d2b7 (diff) | |
download | wallabag-99679d06884120c57f43b44e55e03595f1f87bed.tar.gz wallabag-99679d06884120c57f43b44e55e03595f1f87bed.tar.zst wallabag-99679d06884120c57f43b44e55e03595f1f87bed.zip |
Merge pull request #481 from wallabag/dev1.5.2
1.5.2
Diffstat (limited to 'inc/3rdparty/htmlpurifier/HTMLPurifier/Printer')
5 files changed, 830 insertions, 0 deletions
diff --git a/inc/3rdparty/htmlpurifier/HTMLPurifier/Printer/CSSDefinition.php b/inc/3rdparty/htmlpurifier/HTMLPurifier/Printer/CSSDefinition.php new file mode 100644 index 00000000..afc8c18a --- /dev/null +++ b/inc/3rdparty/htmlpurifier/HTMLPurifier/Printer/CSSDefinition.php | |||
@@ -0,0 +1,44 @@ | |||
1 | <?php | ||
2 | |||
3 | class HTMLPurifier_Printer_CSSDefinition extends HTMLPurifier_Printer | ||
4 | { | ||
5 | /** | ||
6 | * @type HTMLPurifier_CSSDefinition | ||
7 | */ | ||
8 | protected $def; | ||
9 | |||
10 | /** | ||
11 | * @param HTMLPurifier_Config $config | ||
12 | * @return string | ||
13 | */ | ||
14 | public function render($config) | ||
15 | { | ||
16 | $this->def = $config->getCSSDefinition(); | ||
17 | $ret = ''; | ||
18 | |||
19 | $ret .= $this->start('div', array('class' => 'HTMLPurifier_Printer')); | ||
20 | $ret .= $this->start('table'); | ||
21 | |||
22 | $ret .= $this->element('caption', 'Properties ($info)'); | ||
23 | |||
24 | $ret .= $this->start('thead'); | ||
25 | $ret .= $this->start('tr'); | ||
26 | $ret .= $this->element('th', 'Property', array('class' => 'heavy')); | ||
27 | $ret .= $this->element('th', 'Definition', array('class' => 'heavy', 'style' => 'width:auto;')); | ||
28 | $ret .= $this->end('tr'); | ||
29 | $ret .= $this->end('thead'); | ||
30 | |||
31 | ksort($this->def->info); | ||
32 | foreach ($this->def->info as $property => $obj) { | ||
33 | $name = $this->getClass($obj, 'AttrDef_'); | ||
34 | $ret .= $this->row($property, $name); | ||
35 | } | ||
36 | |||
37 | $ret .= $this->end('table'); | ||
38 | $ret .= $this->end('div'); | ||
39 | |||
40 | return $ret; | ||
41 | } | ||
42 | } | ||
43 | |||
44 | // vim: et sw=4 sts=4 | ||
diff --git a/inc/3rdparty/htmlpurifier/HTMLPurifier/Printer/ConfigForm.css b/inc/3rdparty/htmlpurifier/HTMLPurifier/Printer/ConfigForm.css new file mode 100644 index 00000000..7af30fc3 --- /dev/null +++ b/inc/3rdparty/htmlpurifier/HTMLPurifier/Printer/ConfigForm.css | |||
@@ -0,0 +1,10 @@ | |||
1 | |||
2 | .hp-config {} | ||
3 | |||
4 | .hp-config tbody th {text-align:right; padding-right:0.5em;} | ||
5 | .hp-config thead, .hp-config .namespace {background:#3C578C; color:#FFF;} | ||
6 | .hp-config .namespace th {text-align:center;} | ||
7 | .hp-config .verbose {display:none;} | ||
8 | .hp-config .controls {text-align:center;} | ||
9 | |||
10 | /* vim: et sw=4 sts=4 */ | ||
diff --git a/inc/3rdparty/htmlpurifier/HTMLPurifier/Printer/ConfigForm.js b/inc/3rdparty/htmlpurifier/HTMLPurifier/Printer/ConfigForm.js new file mode 100644 index 00000000..83e06553 --- /dev/null +++ b/inc/3rdparty/htmlpurifier/HTMLPurifier/Printer/ConfigForm.js | |||
@@ -0,0 +1,5 @@ | |||
1 | function toggleWriteability(id_of_patient, checked) { | ||
2 | document.getElementById(id_of_patient).disabled = checked; | ||
3 | } | ||
4 | |||
5 | // vim: et sw=4 sts=4 | ||
diff --git a/inc/3rdparty/htmlpurifier/HTMLPurifier/Printer/ConfigForm.php b/inc/3rdparty/htmlpurifier/HTMLPurifier/Printer/ConfigForm.php new file mode 100644 index 00000000..660960f3 --- /dev/null +++ b/inc/3rdparty/htmlpurifier/HTMLPurifier/Printer/ConfigForm.php | |||
@@ -0,0 +1,447 @@ | |||
1 | <?php | ||
2 | |||
3 | /** | ||
4 | * @todo Rewrite to use Interchange objects | ||
5 | */ | ||
6 | class HTMLPurifier_Printer_ConfigForm extends HTMLPurifier_Printer | ||
7 | { | ||
8 | |||
9 | /** | ||
10 | * Printers for specific fields. | ||
11 | * @type HTMLPurifier_Printer[] | ||
12 | */ | ||
13 | protected $fields = array(); | ||
14 | |||
15 | /** | ||
16 | * Documentation URL, can have fragment tagged on end. | ||
17 | * @type string | ||
18 | */ | ||
19 | protected $docURL; | ||
20 | |||
21 | /** | ||
22 | * Name of form element to stuff config in. | ||
23 | * @type string | ||
24 | */ | ||
25 | protected $name; | ||
26 | |||
27 | /** | ||
28 | * Whether or not to compress directive names, clipping them off | ||
29 | * after a certain amount of letters. False to disable or integer letters | ||
30 | * before clipping. | ||
31 | * @type bool | ||
32 | */ | ||
33 | protected $compress = false; | ||
34 | |||
35 | /** | ||
36 | * @param string $name Form element name for directives to be stuffed into | ||
37 | * @param string $doc_url String documentation URL, will have fragment tagged on | ||
38 | * @param bool $compress Integer max length before compressing a directive name, set to false to turn off | ||
39 | */ | ||
40 | public function __construct( | ||
41 | $name, | ||
42 | $doc_url = null, | ||
43 | $compress = false | ||
44 | ) { | ||
45 | parent::__construct(); | ||
46 | $this->docURL = $doc_url; | ||
47 | $this->name = $name; | ||
48 | $this->compress = $compress; | ||
49 | // initialize sub-printers | ||
50 | $this->fields[0] = new HTMLPurifier_Printer_ConfigForm_default(); | ||
51 | $this->fields[HTMLPurifier_VarParser::BOOL] = new HTMLPurifier_Printer_ConfigForm_bool(); | ||
52 | } | ||
53 | |||
54 | /** | ||
55 | * Sets default column and row size for textareas in sub-printers | ||
56 | * @param $cols Integer columns of textarea, null to use default | ||
57 | * @param $rows Integer rows of textarea, null to use default | ||
58 | */ | ||
59 | public function setTextareaDimensions($cols = null, $rows = null) | ||
60 | { | ||
61 | if ($cols) { | ||
62 | $this->fields['default']->cols = $cols; | ||
63 | } | ||
64 | if ($rows) { | ||
65 | $this->fields['default']->rows = $rows; | ||
66 | } | ||
67 | } | ||
68 | |||
69 | /** | ||
70 | * Retrieves styling, in case it is not accessible by webserver | ||
71 | */ | ||
72 | public static function getCSS() | ||
73 | { | ||
74 | return file_get_contents(HTMLPURIFIER_PREFIX . '/HTMLPurifier/Printer/ConfigForm.css'); | ||
75 | } | ||
76 | |||
77 | /** | ||
78 | * Retrieves JavaScript, in case it is not accessible by webserver | ||
79 | */ | ||
80 | public static function getJavaScript() | ||
81 | { | ||
82 | return file_get_contents(HTMLPURIFIER_PREFIX . '/HTMLPurifier/Printer/ConfigForm.js'); | ||
83 | } | ||
84 | |||
85 | /** | ||
86 | * Returns HTML output for a configuration form | ||
87 | * @param HTMLPurifier_Config|array $config Configuration object of current form state, or an array | ||
88 | * where [0] has an HTML namespace and [1] is being rendered. | ||
89 | * @param array|bool $allowed Optional namespace(s) and directives to restrict form to. | ||
90 | * @param bool $render_controls | ||
91 | * @return string | ||
92 | */ | ||
93 | public function render($config, $allowed = true, $render_controls = true) | ||
94 | { | ||
95 | if (is_array($config) && isset($config[0])) { | ||
96 | $gen_config = $config[0]; | ||
97 | $config = $config[1]; | ||
98 | } else { | ||
99 | $gen_config = $config; | ||
100 | } | ||
101 | |||
102 | $this->config = $config; | ||
103 | $this->genConfig = $gen_config; | ||
104 | $this->prepareGenerator($gen_config); | ||
105 | |||
106 | $allowed = HTMLPurifier_Config::getAllowedDirectivesForForm($allowed, $config->def); | ||
107 | $all = array(); | ||
108 | foreach ($allowed as $key) { | ||
109 | list($ns, $directive) = $key; | ||
110 | $all[$ns][$directive] = $config->get($ns . '.' . $directive); | ||
111 | } | ||
112 | |||
113 | $ret = ''; | ||
114 | $ret .= $this->start('table', array('class' => 'hp-config')); | ||
115 | $ret .= $this->start('thead'); | ||
116 | $ret .= $this->start('tr'); | ||
117 | $ret .= $this->element('th', 'Directive', array('class' => 'hp-directive')); | ||
118 | $ret .= $this->element('th', 'Value', array('class' => 'hp-value')); | ||
119 | $ret .= $this->end('tr'); | ||
120 | $ret .= $this->end('thead'); | ||
121 | foreach ($all as $ns => $directives) { | ||
122 | $ret .= $this->renderNamespace($ns, $directives); | ||
123 | } | ||
124 | if ($render_controls) { | ||
125 | $ret .= $this->start('tbody'); | ||
126 | $ret .= $this->start('tr'); | ||
127 | $ret .= $this->start('td', array('colspan' => 2, 'class' => 'controls')); | ||
128 | $ret .= $this->elementEmpty('input', array('type' => 'submit', 'value' => 'Submit')); | ||
129 | $ret .= '[<a href="?">Reset</a>]'; | ||
130 | $ret .= $this->end('td'); | ||
131 | $ret .= $this->end('tr'); | ||
132 | $ret .= $this->end('tbody'); | ||
133 | } | ||
134 | $ret .= $this->end('table'); | ||
135 | return $ret; | ||
136 | } | ||
137 | |||
138 | /** | ||
139 | * Renders a single namespace | ||
140 | * @param $ns String namespace name | ||
141 | * @param array $directives array of directives to values | ||
142 | * @return string | ||
143 | */ | ||
144 | protected function renderNamespace($ns, $directives) | ||
145 | { | ||
146 | $ret = ''; | ||
147 | $ret .= $this->start('tbody', array('class' => 'namespace')); | ||
148 | $ret .= $this->start('tr'); | ||
149 | $ret .= $this->element('th', $ns, array('colspan' => 2)); | ||
150 | $ret .= $this->end('tr'); | ||
151 | $ret .= $this->end('tbody'); | ||
152 | $ret .= $this->start('tbody'); | ||
153 | foreach ($directives as $directive => $value) { | ||
154 | $ret .= $this->start('tr'); | ||
155 | $ret .= $this->start('th'); | ||
156 | if ($this->docURL) { | ||
157 | $url = str_replace('%s', urlencode("$ns.$directive"), $this->docURL); | ||
158 | $ret .= $this->start('a', array('href' => $url)); | ||
159 | } | ||
160 | $attr = array('for' => "{$this->name}:$ns.$directive"); | ||
161 | |||
162 | // crop directive name if it's too long | ||
163 | if (!$this->compress || (strlen($directive) < $this->compress)) { | ||
164 | $directive_disp = $directive; | ||
165 | } else { | ||
166 | $directive_disp = substr($directive, 0, $this->compress - 2) . '...'; | ||
167 | $attr['title'] = $directive; | ||
168 | } | ||
169 | |||
170 | $ret .= $this->element( | ||
171 | 'label', | ||
172 | $directive_disp, | ||
173 | // component printers must create an element with this id | ||
174 | $attr | ||
175 | ); | ||
176 | if ($this->docURL) { | ||
177 | $ret .= $this->end('a'); | ||
178 | } | ||
179 | $ret .= $this->end('th'); | ||
180 | |||
181 | $ret .= $this->start('td'); | ||
182 | $def = $this->config->def->info["$ns.$directive"]; | ||
183 | if (is_int($def)) { | ||
184 | $allow_null = $def < 0; | ||
185 | $type = abs($def); | ||
186 | } else { | ||
187 | $type = $def->type; | ||
188 | $allow_null = isset($def->allow_null); | ||
189 | } | ||
190 | if (!isset($this->fields[$type])) { | ||
191 | $type = 0; | ||
192 | } // default | ||
193 | $type_obj = $this->fields[$type]; | ||
194 | if ($allow_null) { | ||
195 | $type_obj = new HTMLPurifier_Printer_ConfigForm_NullDecorator($type_obj); | ||
196 | } | ||
197 | $ret .= $type_obj->render($ns, $directive, $value, $this->name, array($this->genConfig, $this->config)); | ||
198 | $ret .= $this->end('td'); | ||
199 | $ret .= $this->end('tr'); | ||
200 | } | ||
201 | $ret .= $this->end('tbody'); | ||
202 | return $ret; | ||
203 | } | ||
204 | |||
205 | } | ||
206 | |||
207 | /** | ||
208 | * Printer decorator for directives that accept null | ||
209 | */ | ||
210 | class HTMLPurifier_Printer_ConfigForm_NullDecorator extends HTMLPurifier_Printer | ||
211 | { | ||
212 | /** | ||
213 | * Printer being decorated | ||
214 | * @type HTMLPurifier_Printer | ||
215 | */ | ||
216 | protected $obj; | ||
217 | |||
218 | /** | ||
219 | * @param HTMLPurifier_Printer $obj Printer to decorate | ||
220 | */ | ||
221 | public function __construct($obj) | ||
222 | { | ||
223 | parent::__construct(); | ||
224 | $this->obj = $obj; | ||
225 | } | ||
226 | |||
227 | /** | ||
228 | * @param string $ns | ||
229 | * @param string $directive | ||
230 | * @param string $value | ||
231 | * @param string $name | ||
232 | * @param HTMLPurifier_Config|array $config | ||
233 | * @return string | ||
234 | */ | ||
235 | public function render($ns, $directive, $value, $name, $config) | ||
236 | { | ||
237 | if (is_array($config) && isset($config[0])) { | ||
238 | $gen_config = $config[0]; | ||
239 | $config = $config[1]; | ||
240 | } else { | ||
241 | $gen_config = $config; | ||
242 | } | ||
243 | $this->prepareGenerator($gen_config); | ||
244 | |||
245 | $ret = ''; | ||
246 | $ret .= $this->start('label', array('for' => "$name:Null_$ns.$directive")); | ||
247 | $ret .= $this->element('span', "$ns.$directive:", array('class' => 'verbose')); | ||
248 | $ret .= $this->text(' Null/Disabled'); | ||
249 | $ret .= $this->end('label'); | ||
250 | $attr = array( | ||
251 | 'type' => 'checkbox', | ||
252 | 'value' => '1', | ||
253 | 'class' => 'null-toggle', | ||
254 | 'name' => "$name" . "[Null_$ns.$directive]", | ||
255 | 'id' => "$name:Null_$ns.$directive", | ||
256 | 'onclick' => "toggleWriteability('$name:$ns.$directive',checked)" // INLINE JAVASCRIPT!!!! | ||
257 | ); | ||
258 | if ($this->obj instanceof HTMLPurifier_Printer_ConfigForm_bool) { | ||
259 | // modify inline javascript slightly | ||
260 | $attr['onclick'] = | ||
261 | "toggleWriteability('$name:Yes_$ns.$directive',checked);" . | ||
262 | "toggleWriteability('$name:No_$ns.$directive',checked)"; | ||
263 | } | ||
264 | if ($value === null) { | ||
265 | $attr['checked'] = 'checked'; | ||
266 | } | ||
267 | $ret .= $this->elementEmpty('input', $attr); | ||
268 | $ret .= $this->text(' or '); | ||
269 | $ret .= $this->elementEmpty('br'); | ||
270 | $ret .= $this->obj->render($ns, $directive, $value, $name, array($gen_config, $config)); | ||
271 | return $ret; | ||
272 | } | ||
273 | } | ||
274 | |||
275 | /** | ||
276 | * Swiss-army knife configuration form field printer | ||
277 | */ | ||
278 | class HTMLPurifier_Printer_ConfigForm_default extends HTMLPurifier_Printer | ||
279 | { | ||
280 | /** | ||
281 | * @type int | ||
282 | */ | ||
283 | public $cols = 18; | ||
284 | |||
285 | /** | ||
286 | * @type int | ||
287 | */ | ||
288 | public $rows = 5; | ||
289 | |||
290 | /** | ||
291 | * @param string $ns | ||
292 | * @param string $directive | ||
293 | * @param string $value | ||
294 | * @param string $name | ||
295 | * @param HTMLPurifier_Config|array $config | ||
296 | * @return string | ||
297 | */ | ||
298 | public function render($ns, $directive, $value, $name, $config) | ||
299 | { | ||
300 | if (is_array($config) && isset($config[0])) { | ||
301 | $gen_config = $config[0]; | ||
302 | $config = $config[1]; | ||
303 | } else { | ||
304 | $gen_config = $config; | ||
305 | } | ||
306 | $this->prepareGenerator($gen_config); | ||
307 | // this should probably be split up a little | ||
308 | $ret = ''; | ||
309 | $def = $config->def->info["$ns.$directive"]; | ||
310 | if (is_int($def)) { | ||
311 | $type = abs($def); | ||
312 | } else { | ||
313 | $type = $def->type; | ||
314 | } | ||
315 | if (is_array($value)) { | ||
316 | switch ($type) { | ||
317 | case HTMLPurifier_VarParser::LOOKUP: | ||
318 | $array = $value; | ||
319 | $value = array(); | ||
320 | foreach ($array as $val => $b) { | ||
321 | $value[] = $val; | ||
322 | } | ||
323 | //TODO does this need a break? | ||
324 | case HTMLPurifier_VarParser::ALIST: | ||
325 | $value = implode(PHP_EOL, $value); | ||
326 | break; | ||
327 | case HTMLPurifier_VarParser::HASH: | ||
328 | $nvalue = ''; | ||
329 | foreach ($value as $i => $v) { | ||
330 | $nvalue .= "$i:$v" . PHP_EOL; | ||
331 | } | ||
332 | $value = $nvalue; | ||
333 | break; | ||
334 | default: | ||
335 | $value = ''; | ||
336 | } | ||
337 | } | ||
338 | if ($type === HTMLPurifier_VarParser::MIXED) { | ||
339 | return 'Not supported'; | ||
340 | $value = serialize($value); | ||
341 | } | ||
342 | $attr = array( | ||
343 | 'name' => "$name" . "[$ns.$directive]", | ||
344 | 'id' => "$name:$ns.$directive" | ||
345 | ); | ||
346 | if ($value === null) { | ||
347 | $attr['disabled'] = 'disabled'; | ||
348 | } | ||
349 | if (isset($def->allowed)) { | ||
350 | $ret .= $this->start('select', $attr); | ||
351 | foreach ($def->allowed as $val => $b) { | ||
352 | $attr = array(); | ||
353 | if ($value == $val) { | ||
354 | $attr['selected'] = 'selected'; | ||
355 | } | ||
356 | $ret .= $this->element('option', $val, $attr); | ||
357 | } | ||
358 | $ret .= $this->end('select'); | ||
359 | } elseif ($type === HTMLPurifier_VarParser::TEXT || | ||
360 | $type === HTMLPurifier_VarParser::ITEXT || | ||
361 | $type === HTMLPurifier_VarParser::ALIST || | ||
362 | $type === HTMLPurifier_VarParser::HASH || | ||
363 | $type === HTMLPurifier_VarParser::LOOKUP) { | ||
364 | $attr['cols'] = $this->cols; | ||
365 | $attr['rows'] = $this->rows; | ||
366 | $ret .= $this->start('textarea', $attr); | ||
367 | $ret .= $this->text($value); | ||
368 | $ret .= $this->end('textarea'); | ||
369 | } else { | ||
370 | $attr['value'] = $value; | ||
371 | $attr['type'] = 'text'; | ||
372 | $ret .= $this->elementEmpty('input', $attr); | ||
373 | } | ||
374 | return $ret; | ||
375 | } | ||
376 | } | ||
377 | |||
378 | /** | ||
379 | * Bool form field printer | ||
380 | */ | ||
381 | class HTMLPurifier_Printer_ConfigForm_bool extends HTMLPurifier_Printer | ||
382 | { | ||
383 | /** | ||
384 | * @param string $ns | ||
385 | * @param string $directive | ||
386 | * @param string $value | ||
387 | * @param string $name | ||
388 | * @param HTMLPurifier_Config|array $config | ||
389 | * @return string | ||
390 | */ | ||
391 | public function render($ns, $directive, $value, $name, $config) | ||
392 | { | ||
393 | if (is_array($config) && isset($config[0])) { | ||
394 | $gen_config = $config[0]; | ||
395 | $config = $config[1]; | ||
396 | } else { | ||
397 | $gen_config = $config; | ||
398 | } | ||
399 | $this->prepareGenerator($gen_config); | ||
400 | $ret = ''; | ||
401 | $ret .= $this->start('div', array('id' => "$name:$ns.$directive")); | ||
402 | |||
403 | $ret .= $this->start('label', array('for' => "$name:Yes_$ns.$directive")); | ||
404 | $ret .= $this->element('span', "$ns.$directive:", array('class' => 'verbose')); | ||
405 | $ret .= $this->text(' Yes'); | ||
406 | $ret .= $this->end('label'); | ||
407 | |||
408 | $attr = array( | ||
409 | 'type' => 'radio', | ||
410 | 'name' => "$name" . "[$ns.$directive]", | ||
411 | 'id' => "$name:Yes_$ns.$directive", | ||
412 | 'value' => '1' | ||
413 | ); | ||
414 | if ($value === true) { | ||
415 | $attr['checked'] = 'checked'; | ||
416 | } | ||
417 | if ($value === null) { | ||
418 | $attr['disabled'] = 'disabled'; | ||
419 | } | ||
420 | $ret .= $this->elementEmpty('input', $attr); | ||
421 | |||
422 | $ret .= $this->start('label', array('for' => "$name:No_$ns.$directive")); | ||
423 | $ret .= $this->element('span', "$ns.$directive:", array('class' => 'verbose')); | ||
424 | $ret .= $this->text(' No'); | ||
425 | $ret .= $this->end('label'); | ||
426 | |||
427 | $attr = array( | ||
428 | 'type' => 'radio', | ||
429 | 'name' => "$name" . "[$ns.$directive]", | ||
430 | 'id' => "$name:No_$ns.$directive", | ||
431 | 'value' => '0' | ||
432 | ); | ||
433 | if ($value === false) { | ||
434 | $attr['checked'] = 'checked'; | ||
435 | } | ||
436 | if ($value === null) { | ||
437 | $attr['disabled'] = 'disabled'; | ||
438 | } | ||
439 | $ret .= $this->elementEmpty('input', $attr); | ||
440 | |||
441 | $ret .= $this->end('div'); | ||
442 | |||
443 | return $ret; | ||
444 | } | ||
445 | } | ||
446 | |||
447 | // vim: et sw=4 sts=4 | ||
diff --git a/inc/3rdparty/htmlpurifier/HTMLPurifier/Printer/HTMLDefinition.php b/inc/3rdparty/htmlpurifier/HTMLPurifier/Printer/HTMLDefinition.php new file mode 100644 index 00000000..679d19ba --- /dev/null +++ b/inc/3rdparty/htmlpurifier/HTMLPurifier/Printer/HTMLDefinition.php | |||
@@ -0,0 +1,324 @@ | |||
1 | <?php | ||
2 | |||
3 | class HTMLPurifier_Printer_HTMLDefinition extends HTMLPurifier_Printer | ||
4 | { | ||
5 | |||
6 | /** | ||
7 | * @type HTMLPurifier_HTMLDefinition, for easy access | ||
8 | */ | ||
9 | protected $def; | ||
10 | |||
11 | /** | ||
12 | * @param HTMLPurifier_Config $config | ||
13 | * @return string | ||
14 | */ | ||
15 | public function render($config) | ||
16 | { | ||
17 | $ret = ''; | ||
18 | $this->config =& $config; | ||
19 | |||
20 | $this->def = $config->getHTMLDefinition(); | ||
21 | |||
22 | $ret .= $this->start('div', array('class' => 'HTMLPurifier_Printer')); | ||
23 | |||
24 | $ret .= $this->renderDoctype(); | ||
25 | $ret .= $this->renderEnvironment(); | ||
26 | $ret .= $this->renderContentSets(); | ||
27 | $ret .= $this->renderInfo(); | ||
28 | |||
29 | $ret .= $this->end('div'); | ||
30 | |||
31 | return $ret; | ||
32 | } | ||
33 | |||
34 | /** | ||
35 | * Renders the Doctype table | ||
36 | * @return string | ||
37 | */ | ||
38 | protected function renderDoctype() | ||
39 | { | ||
40 | $doctype = $this->def->doctype; | ||
41 | $ret = ''; | ||
42 | $ret .= $this->start('table'); | ||
43 | $ret .= $this->element('caption', 'Doctype'); | ||
44 | $ret .= $this->row('Name', $doctype->name); | ||
45 | $ret .= $this->row('XML', $doctype->xml ? 'Yes' : 'No'); | ||
46 | $ret .= $this->row('Default Modules', implode($doctype->modules, ', ')); | ||
47 | $ret .= $this->row('Default Tidy Modules', implode($doctype->tidyModules, ', ')); | ||
48 | $ret .= $this->end('table'); | ||
49 | return $ret; | ||
50 | } | ||
51 | |||
52 | |||
53 | /** | ||
54 | * Renders environment table, which is miscellaneous info | ||
55 | * @return string | ||
56 | */ | ||
57 | protected function renderEnvironment() | ||
58 | { | ||
59 | $def = $this->def; | ||
60 | |||
61 | $ret = ''; | ||
62 | |||
63 | $ret .= $this->start('table'); | ||
64 | $ret .= $this->element('caption', 'Environment'); | ||
65 | |||
66 | $ret .= $this->row('Parent of fragment', $def->info_parent); | ||
67 | $ret .= $this->renderChildren($def->info_parent_def->child); | ||
68 | $ret .= $this->row('Block wrap name', $def->info_block_wrapper); | ||
69 | |||
70 | $ret .= $this->start('tr'); | ||
71 | $ret .= $this->element('th', 'Global attributes'); | ||
72 | $ret .= $this->element('td', $this->listifyAttr($def->info_global_attr), null, 0); | ||
73 | $ret .= $this->end('tr'); | ||
74 | |||
75 | $ret .= $this->start('tr'); | ||
76 | $ret .= $this->element('th', 'Tag transforms'); | ||
77 | $list = array(); | ||
78 | foreach ($def->info_tag_transform as $old => $new) { | ||
79 | $new = $this->getClass($new, 'TagTransform_'); | ||
80 | $list[] = "<$old> with $new"; | ||
81 | } | ||
82 | $ret .= $this->element('td', $this->listify($list)); | ||
83 | $ret .= $this->end('tr'); | ||
84 | |||
85 | $ret .= $this->start('tr'); | ||
86 | $ret .= $this->element('th', 'Pre-AttrTransform'); | ||
87 | $ret .= $this->element('td', $this->listifyObjectList($def->info_attr_transform_pre)); | ||
88 | $ret .= $this->end('tr'); | ||
89 | |||
90 | $ret .= $this->start('tr'); | ||
91 | $ret .= $this->element('th', 'Post-AttrTransform'); | ||
92 | $ret .= $this->element('td', $this->listifyObjectList($def->info_attr_transform_post)); | ||
93 | $ret .= $this->end('tr'); | ||
94 | |||
95 | $ret .= $this->end('table'); | ||
96 | return $ret; | ||
97 | } | ||
98 | |||
99 | /** | ||
100 | * Renders the Content Sets table | ||
101 | * @return string | ||
102 | */ | ||
103 | protected function renderContentSets() | ||
104 | { | ||
105 | $ret = ''; | ||
106 | $ret .= $this->start('table'); | ||
107 | $ret .= $this->element('caption', 'Content Sets'); | ||
108 | foreach ($this->def->info_content_sets as $name => $lookup) { | ||
109 | $ret .= $this->heavyHeader($name); | ||
110 | $ret .= $this->start('tr'); | ||
111 | $ret .= $this->element('td', $this->listifyTagLookup($lookup)); | ||
112 | $ret .= $this->end('tr'); | ||
113 | } | ||
114 | $ret .= $this->end('table'); | ||
115 | return $ret; | ||
116 | } | ||
117 | |||
118 | /** | ||
119 | * Renders the Elements ($info) table | ||
120 | * @return string | ||
121 | */ | ||
122 | protected function renderInfo() | ||
123 | { | ||
124 | $ret = ''; | ||
125 | $ret .= $this->start('table'); | ||
126 | $ret .= $this->element('caption', 'Elements ($info)'); | ||
127 | ksort($this->def->info); | ||
128 | $ret .= $this->heavyHeader('Allowed tags', 2); | ||
129 | $ret .= $this->start('tr'); | ||
130 | $ret .= $this->element('td', $this->listifyTagLookup($this->def->info), array('colspan' => 2)); | ||
131 | $ret .= $this->end('tr'); | ||
132 | foreach ($this->def->info as $name => $def) { | ||
133 | $ret .= $this->start('tr'); | ||
134 | $ret .= $this->element('th', "<$name>", array('class' => 'heavy', 'colspan' => 2)); | ||
135 | $ret .= $this->end('tr'); | ||
136 | $ret .= $this->start('tr'); | ||
137 | $ret .= $this->element('th', 'Inline content'); | ||
138 | $ret .= $this->element('td', $def->descendants_are_inline ? 'Yes' : 'No'); | ||
139 | $ret .= $this->end('tr'); | ||
140 | if (!empty($def->excludes)) { | ||
141 | $ret .= $this->start('tr'); | ||
142 | $ret .= $this->element('th', 'Excludes'); | ||
143 | $ret .= $this->element('td', $this->listifyTagLookup($def->excludes)); | ||
144 | $ret .= $this->end('tr'); | ||
145 | } | ||
146 | if (!empty($def->attr_transform_pre)) { | ||
147 | $ret .= $this->start('tr'); | ||
148 | $ret .= $this->element('th', 'Pre-AttrTransform'); | ||
149 | $ret .= $this->element('td', $this->listifyObjectList($def->attr_transform_pre)); | ||
150 | $ret .= $this->end('tr'); | ||
151 | } | ||
152 | if (!empty($def->attr_transform_post)) { | ||
153 | $ret .= $this->start('tr'); | ||
154 | $ret .= $this->element('th', 'Post-AttrTransform'); | ||
155 | $ret .= $this->element('td', $this->listifyObjectList($def->attr_transform_post)); | ||
156 | $ret .= $this->end('tr'); | ||
157 | } | ||
158 | if (!empty($def->auto_close)) { | ||
159 | $ret .= $this->start('tr'); | ||
160 | $ret .= $this->element('th', 'Auto closed by'); | ||
161 | $ret .= $this->element('td', $this->listifyTagLookup($def->auto_close)); | ||
162 | $ret .= $this->end('tr'); | ||
163 | } | ||
164 | $ret .= $this->start('tr'); | ||
165 | $ret .= $this->element('th', 'Allowed attributes'); | ||
166 | $ret .= $this->element('td', $this->listifyAttr($def->attr), array(), 0); | ||
167 | $ret .= $this->end('tr'); | ||
168 | |||
169 | if (!empty($def->required_attr)) { | ||
170 | $ret .= $this->row('Required attributes', $this->listify($def->required_attr)); | ||
171 | } | ||
172 | |||
173 | $ret .= $this->renderChildren($def->child); | ||
174 | } | ||
175 | $ret .= $this->end('table'); | ||
176 | return $ret; | ||
177 | } | ||
178 | |||
179 | /** | ||
180 | * Renders a row describing the allowed children of an element | ||
181 | * @param HTMLPurifier_ChildDef $def HTMLPurifier_ChildDef of pertinent element | ||
182 | * @return string | ||
183 | */ | ||
184 | protected function renderChildren($def) | ||
185 | { | ||
186 | $context = new HTMLPurifier_Context(); | ||
187 | $ret = ''; | ||
188 | $ret .= $this->start('tr'); | ||
189 | $elements = array(); | ||
190 | $attr = array(); | ||
191 | if (isset($def->elements)) { | ||
192 | if ($def->type == 'strictblockquote') { | ||
193 | $def->validateChildren(array(), $this->config, $context); | ||
194 | } | ||
195 | $elements = $def->elements; | ||
196 | } | ||
197 | if ($def->type == 'chameleon') { | ||
198 | $attr['rowspan'] = 2; | ||
199 | } elseif ($def->type == 'empty') { | ||
200 | $elements = array(); | ||
201 | } elseif ($def->type == 'table') { | ||
202 | $elements = array_flip( | ||
203 | array( | ||
204 | 'col', | ||
205 | 'caption', | ||
206 | 'colgroup', | ||
207 | 'thead', | ||
208 | 'tfoot', | ||
209 | 'tbody', | ||
210 | 'tr' | ||
211 | ) | ||
212 | ); | ||
213 | } | ||
214 | $ret .= $this->element('th', 'Allowed children', $attr); | ||
215 | |||
216 | if ($def->type == 'chameleon') { | ||
217 | |||
218 | $ret .= $this->element( | ||
219 | 'td', | ||
220 | '<em>Block</em>: ' . | ||
221 | $this->escape($this->listifyTagLookup($def->block->elements)), | ||
222 | null, | ||
223 | 0 | ||
224 | ); | ||
225 | $ret .= $this->end('tr'); | ||
226 | $ret .= $this->start('tr'); | ||
227 | $ret .= $this->element( | ||
228 | 'td', | ||
229 | '<em>Inline</em>: ' . | ||
230 | $this->escape($this->listifyTagLookup($def->inline->elements)), | ||
231 | null, | ||
232 | 0 | ||
233 | ); | ||
234 | |||
235 | } elseif ($def->type == 'custom') { | ||
236 | |||
237 | $ret .= $this->element( | ||
238 | 'td', | ||
239 | '<em>' . ucfirst($def->type) . '</em>: ' . | ||
240 | $def->dtd_regex | ||
241 | ); | ||
242 | |||
243 | } else { | ||
244 | $ret .= $this->element( | ||
245 | 'td', | ||
246 | '<em>' . ucfirst($def->type) . '</em>: ' . | ||
247 | $this->escape($this->listifyTagLookup($elements)), | ||
248 | null, | ||
249 | 0 | ||
250 | ); | ||
251 | } | ||
252 | $ret .= $this->end('tr'); | ||
253 | return $ret; | ||
254 | } | ||
255 | |||
256 | /** | ||
257 | * Listifies a tag lookup table. | ||
258 | * @param array $array Tag lookup array in form of array('tagname' => true) | ||
259 | * @return string | ||
260 | */ | ||
261 | protected function listifyTagLookup($array) | ||
262 | { | ||
263 | ksort($array); | ||
264 | $list = array(); | ||
265 | foreach ($array as $name => $discard) { | ||
266 | if ($name !== '#PCDATA' && !isset($this->def->info[$name])) { | ||
267 | continue; | ||
268 | } | ||
269 | $list[] = $name; | ||
270 | } | ||
271 | return $this->listify($list); | ||
272 | } | ||
273 | |||
274 | /** | ||
275 | * Listifies a list of objects by retrieving class names and internal state | ||
276 | * @param array $array List of objects | ||
277 | * @return string | ||
278 | * @todo Also add information about internal state | ||
279 | */ | ||
280 | protected function listifyObjectList($array) | ||
281 | { | ||
282 | ksort($array); | ||
283 | $list = array(); | ||
284 | foreach ($array as $obj) { | ||
285 | $list[] = $this->getClass($obj, 'AttrTransform_'); | ||
286 | } | ||
287 | return $this->listify($list); | ||
288 | } | ||
289 | |||
290 | /** | ||
291 | * Listifies a hash of attributes to AttrDef classes | ||
292 | * @param array $array Array hash in form of array('attrname' => HTMLPurifier_AttrDef) | ||
293 | * @return string | ||
294 | */ | ||
295 | protected function listifyAttr($array) | ||
296 | { | ||
297 | ksort($array); | ||
298 | $list = array(); | ||
299 | foreach ($array as $name => $obj) { | ||
300 | if ($obj === false) { | ||
301 | continue; | ||
302 | } | ||
303 | $list[] = "$name = <i>" . $this->getClass($obj, 'AttrDef_') . '</i>'; | ||
304 | } | ||
305 | return $this->listify($list); | ||
306 | } | ||
307 | |||
308 | /** | ||
309 | * Creates a heavy header row | ||
310 | * @param string $text | ||
311 | * @param int $num | ||
312 | * @return string | ||
313 | */ | ||
314 | protected function heavyHeader($text, $num = 1) | ||
315 | { | ||
316 | $ret = ''; | ||
317 | $ret .= $this->start('tr'); | ||
318 | $ret .= $this->element('th', $text, array('colspan' => $num, 'class' => 'heavy')); | ||
319 | $ret .= $this->end('tr'); | ||
320 | return $ret; | ||
321 | } | ||
322 | } | ||
323 | |||
324 | // vim: et sw=4 sts=4 | ||