See Release Notes
Long Term Support Release
Differences Between: [Versions 401 and 402] [Versions 401 and 403]
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::C_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::C_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
title
Description
Body
title
Description
Body
title
Description
Body
title
Body