Version 1
[yaffs-website] / vendor / ezyang / htmlpurifier / library / HTMLPurifier / Printer / ConfigForm.php
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                         if (is_array($v)) {
331                             // HACK
332                             $v = implode(";", $v);
333                         }
334                         $nvalue .= "$i:$v" . PHP_EOL;
335                     }
336                     $value = $nvalue;
337                     break;
338                 default:
339                     $value = '';
340             }
341         }
342         if ($type === HTMLPurifier_VarParser::MIXED) {
343             return 'Not supported';
344             $value = serialize($value);
345         }
346         $attr = array(
347             'name' => "$name" . "[$ns.$directive]",
348             'id' => "$name:$ns.$directive"
349         );
350         if ($value === null) {
351             $attr['disabled'] = 'disabled';
352         }
353         if (isset($def->allowed)) {
354             $ret .= $this->start('select', $attr);
355             foreach ($def->allowed as $val => $b) {
356                 $attr = array();
357                 if ($value == $val) {
358                     $attr['selected'] = 'selected';
359                 }
360                 $ret .= $this->element('option', $val, $attr);
361             }
362             $ret .= $this->end('select');
363         } elseif ($type === HTMLPurifier_VarParser::TEXT ||
364                 $type === HTMLPurifier_VarParser::ITEXT ||
365                 $type === HTMLPurifier_VarParser::ALIST ||
366                 $type === HTMLPurifier_VarParser::HASH ||
367                 $type === HTMLPurifier_VarParser::LOOKUP) {
368             $attr['cols'] = $this->cols;
369             $attr['rows'] = $this->rows;
370             $ret .= $this->start('textarea', $attr);
371             $ret .= $this->text($value);
372             $ret .= $this->end('textarea');
373         } else {
374             $attr['value'] = $value;
375             $attr['type'] = 'text';
376             $ret .= $this->elementEmpty('input', $attr);
377         }
378         return $ret;
379     }
380 }
381
382 /**
383  * Bool form field printer
384  */
385 class HTMLPurifier_Printer_ConfigForm_bool extends HTMLPurifier_Printer
386 {
387     /**
388      * @param string $ns
389      * @param string $directive
390      * @param string $value
391      * @param string $name
392      * @param HTMLPurifier_Config|array $config
393      * @return string
394      */
395     public function render($ns, $directive, $value, $name, $config)
396     {
397         if (is_array($config) && isset($config[0])) {
398             $gen_config = $config[0];
399             $config = $config[1];
400         } else {
401             $gen_config = $config;
402         }
403         $this->prepareGenerator($gen_config);
404         $ret = '';
405         $ret .= $this->start('div', array('id' => "$name:$ns.$directive"));
406
407         $ret .= $this->start('label', array('for' => "$name:Yes_$ns.$directive"));
408         $ret .= $this->element('span', "$ns.$directive:", array('class' => 'verbose'));
409         $ret .= $this->text(' Yes');
410         $ret .= $this->end('label');
411
412         $attr = array(
413             'type' => 'radio',
414             'name' => "$name" . "[$ns.$directive]",
415             'id' => "$name:Yes_$ns.$directive",
416             'value' => '1'
417         );
418         if ($value === true) {
419             $attr['checked'] = 'checked';
420         }
421         if ($value === null) {
422             $attr['disabled'] = 'disabled';
423         }
424         $ret .= $this->elementEmpty('input', $attr);
425
426         $ret .= $this->start('label', array('for' => "$name:No_$ns.$directive"));
427         $ret .= $this->element('span', "$ns.$directive:", array('class' => 'verbose'));
428         $ret .= $this->text(' No');
429         $ret .= $this->end('label');
430
431         $attr = array(
432             'type' => 'radio',
433             'name' => "$name" . "[$ns.$directive]",
434             'id' => "$name:No_$ns.$directive",
435             'value' => '0'
436         );
437         if ($value === false) {
438             $attr['checked'] = 'checked';
439         }
440         if ($value === null) {
441             $attr['disabled'] = 'disabled';
442         }
443         $ret .= $this->elementEmpty('input', $attr);
444
445         $ret .= $this->end('div');
446
447         return $ret;
448     }
449 }
450
451 // vim: et sw=4 sts=4