Differences Between: [Versions 310 and 403] [Versions 311 and 403] [Versions 39 and 403] [Versions 400 and 403] [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 * @var HTMLPurifier_Config 37 */ 38 protected $genConfig; 39 40 /** 41 * @param string $name Form element name for directives to be stuffed into 42 * @param string $doc_url String documentation URL, will have fragment tagged on 43 * @param bool $compress Integer max length before compressing a directive name, set to false to turn off 44 */ 45 public function __construct( 46 $name, 47 $doc_url = null, 48 $compress = false 49 ) { 50 parent::__construct(); 51 $this->docURL = $doc_url; 52 $this->name = $name; 53 $this->compress = $compress; 54 // initialize sub-printers 55 $this->fields[0] = new HTMLPurifier_Printer_ConfigForm_default(); 56 $this->fields[HTMLPurifier_VarParser::C_BOOL] = new HTMLPurifier_Printer_ConfigForm_bool(); 57 } 58 59 /** 60 * Sets default column and row size for textareas in sub-printers 61 * @param $cols Integer columns of textarea, null to use default 62 * @param $rows Integer rows of textarea, null to use default 63 */ 64 public function setTextareaDimensions($cols = null, $rows = null) 65 { 66 if ($cols) { 67 $this->fields['default']->cols = $cols; 68 } 69 if ($rows) { 70 $this->fields['default']->rows = $rows; 71 } 72 } 73 74 /** 75 * Retrieves styling, in case it is not accessible by webserver 76 */ 77 public static function getCSS() 78 { 79 return file_get_contents(HTMLPURIFIER_PREFIX . '/HTMLPurifier/Printer/ConfigForm.css'); 80 } 81 82 /** 83 * Retrieves JavaScript, in case it is not accessible by webserver 84 */ 85 public static function getJavaScript() 86 { 87 return file_get_contents(HTMLPURIFIER_PREFIX . '/HTMLPurifier/Printer/ConfigForm.js'); 88 } 89 90 /** 91 * Returns HTML output for a configuration form 92 * @param HTMLPurifier_Config|array $config Configuration object of current form state, or an array 93 * where [0] has an HTML namespace and [1] is being rendered. 94 * @param array|bool $allowed Optional namespace(s) and directives to restrict form to. 95 * @param bool $render_controls 96 * @return string 97 */ 98 public function render($config, $allowed = true, $render_controls = true) 99 { 100 if (is_array($config) && isset($config[0])) { 101 $gen_config = $config[0]; 102 $config = $config[1]; 103 } else { 104 $gen_config = $config; 105 } 106 107 $this->config = $config; 108 $this->genConfig = $gen_config; 109 $this->prepareGenerator($gen_config); 110 111 $allowed = HTMLPurifier_Config::getAllowedDirectivesForForm($allowed, $config->def); 112 $all = array(); 113 foreach ($allowed as $key) { 114 list($ns, $directive) = $key; 115 $all[$ns][$directive] = $config->get($ns . '.' . $directive); 116 } 117 118 $ret = ''; 119 $ret .= $this->start('table', array('class' => 'hp-config')); 120 $ret .= $this->start('thead'); 121 $ret .= $this->start('tr'); 122 $ret .= $this->element('th', 'Directive', array('class' => 'hp-directive')); 123 $ret .= $this->element('th', 'Value', array('class' => 'hp-value')); 124 $ret .= $this->end('tr'); 125 $ret .= $this->end('thead'); 126 foreach ($all as $ns => $directives) { 127 $ret .= $this->renderNamespace($ns, $directives); 128 } 129 if ($render_controls) { 130 $ret .= $this->start('tbody'); 131 $ret .= $this->start('tr'); 132 $ret .= $this->start('td', array('colspan' => 2, 'class' => 'controls')); 133 $ret .= $this->elementEmpty('input', array('type' => 'submit', 'value' => 'Submit')); 134 $ret .= '[<a href="?">Reset</a>]'; 135 $ret .= $this->end('td'); 136 $ret .= $this->end('tr'); 137 $ret .= $this->end('tbody'); 138 } 139 $ret .= $this->end('table'); 140 return $ret; 141 } 142 143 /** 144 * Renders a single namespace 145 * @param $ns String namespace name 146 * @param array $directives array of directives to values 147 * @return string 148 */ 149 protected function renderNamespace($ns, $directives) 150 { 151 $ret = ''; 152 $ret .= $this->start('tbody', array('class' => 'namespace')); 153 $ret .= $this->start('tr'); 154 $ret .= $this->element('th', $ns, array('colspan' => 2)); 155 $ret .= $this->end('tr'); 156 $ret .= $this->end('tbody'); 157 $ret .= $this->start('tbody'); 158 foreach ($directives as $directive => $value) { 159 $ret .= $this->start('tr'); 160 $ret .= $this->start('th'); 161 if ($this->docURL) { 162 $url = str_replace('%s', urlencode("$ns.$directive"), $this->docURL); 163 $ret .= $this->start('a', array('href' => $url)); 164 } 165 $attr = array('for' => "{$this->name}:$ns.$directive"); 166 167 // crop directive name if it's too long 168 if (!$this->compress || (strlen($directive) < $this->compress)) { 169 $directive_disp = $directive; 170 } else { 171 $directive_disp = substr($directive, 0, $this->compress - 2) . '...'; 172 $attr['title'] = $directive; 173 } 174 175 $ret .= $this->element( 176 'label', 177 $directive_disp, 178 // component printers must create an element with this id 179 $attr 180 ); 181 if ($this->docURL) { 182 $ret .= $this->end('a'); 183 } 184 $ret .= $this->end('th'); 185 186 $ret .= $this->start('td'); 187 $def = $this->config->def->info["$ns.$directive"]; 188 if (is_int($def)) { 189 $allow_null = $def < 0; 190 $type = abs($def); 191 } else { 192 $type = $def->type; 193 $allow_null = isset($def->allow_null); 194 } 195 if (!isset($this->fields[$type])) { 196 $type = 0; 197 } // default 198 $type_obj = $this->fields[$type]; 199 if ($allow_null) { 200 $type_obj = new HTMLPurifier_Printer_ConfigForm_NullDecorator($type_obj); 201 } 202 $ret .= $type_obj->render($ns, $directive, $value, $this->name, array($this->genConfig, $this->config)); 203 $ret .= $this->end('td'); 204 $ret .= $this->end('tr'); 205 } 206 $ret .= $this->end('tbody'); 207 return $ret; 208 } 209 210 } 211 212 /** 213 * Printer decorator for directives that accept null 214 */ 215 class HTMLPurifier_Printer_ConfigForm_NullDecorator extends HTMLPurifier_Printer 216 { 217 /** 218 * Printer being decorated 219 * @type HTMLPurifier_Printer 220 */ 221 protected $obj; 222 223 /** 224 * @param HTMLPurifier_Printer $obj Printer to decorate 225 */ 226 public function __construct($obj) 227 { 228 parent::__construct(); 229 $this->obj = $obj; 230 } 231 232 /** 233 * @param string $ns 234 * @param string $directive 235 * @param string $value 236 * @param string $name 237 * @param HTMLPurifier_Config|array $config 238 * @return string 239 */ 240 public function render($ns, $directive, $value, $name, $config) 241 { 242 if (is_array($config) && isset($config[0])) { 243 $gen_config = $config[0]; 244 $config = $config[1]; 245 } else { 246 $gen_config = $config; 247 } 248 $this->prepareGenerator($gen_config); 249 250 $ret = ''; 251 $ret .= $this->start('label', array('for' => "$name:Null_$ns.$directive")); 252 $ret .= $this->element('span', "$ns.$directive:", array('class' => 'verbose')); 253 $ret .= $this->text(' Null/Disabled'); 254 $ret .= $this->end('label'); 255 $attr = array( 256 'type' => 'checkbox', 257 'value' => '1', 258 'class' => 'null-toggle', 259 'name' => "$name" . "[Null_$ns.$directive]", 260 'id' => "$name:Null_$ns.$directive", 261 'onclick' => "toggleWriteability('$name:$ns.$directive',checked)" // INLINE JAVASCRIPT!!!! 262 ); 263 if ($this->obj instanceof HTMLPurifier_Printer_ConfigForm_bool) { 264 // modify inline javascript slightly 265 $attr['onclick'] = 266 "toggleWriteability('$name:Yes_$ns.$directive',checked);" . 267 "toggleWriteability('$name:No_$ns.$directive',checked)"; 268 } 269 if ($value === null) { 270 $attr['checked'] = 'checked'; 271 } 272 $ret .= $this->elementEmpty('input', $attr); 273 $ret .= $this->text(' or '); 274 $ret .= $this->elementEmpty('br'); 275 $ret .= $this->obj->render($ns, $directive, $value, $name, array($gen_config, $config)); 276 return $ret; 277 } 278 } 279 280 /** 281 * Swiss-army knife configuration form field printer 282 */ 283 class HTMLPurifier_Printer_ConfigForm_default extends HTMLPurifier_Printer 284 { 285 /** 286 * @type int 287 */ 288 public $cols = 18; 289 290 /** 291 * @type int 292 */ 293 public $rows = 5; 294 295 /** 296 * @param string $ns 297 * @param string $directive 298 * @param string $value 299 * @param string $name 300 * @param HTMLPurifier_Config|array $config 301 * @return string 302 */ 303 public function render($ns, $directive, $value, $name, $config) 304 { 305 if (is_array($config) && isset($config[0])) { 306 $gen_config = $config[0]; 307 $config = $config[1]; 308 } else { 309 $gen_config = $config; 310 } 311 $this->prepareGenerator($gen_config); 312 // this should probably be split up a little 313 $ret = ''; 314 $def = $config->def->info["$ns.$directive"]; 315 if (is_int($def)) { 316 $type = abs($def); 317 } else { 318 $type = $def->type; 319 } 320 if (is_array($value)) { 321 switch ($type) { 322 case HTMLPurifier_VarParser::LOOKUP: 323 $array = $value; 324 $value = array(); 325 foreach ($array as $val => $b) { 326 $value[] = $val; 327 } 328 //TODO does this need a break? 329 case HTMLPurifier_VarParser::ALIST: 330 $value = implode(PHP_EOL, $value); 331 break; 332 case HTMLPurifier_VarParser::HASH: 333 $nvalue = ''; 334 foreach ($value as $i => $v) { 335 if (is_array($v)) { 336 // HACK 337 $v = implode(";", $v); 338 } 339 $nvalue .= "$i:$v" . PHP_EOL; 340 } 341 $value = $nvalue; 342 break; 343 default: 344 $value = ''; 345 } 346 } 347 if ($type === HTMLPurifier_VarParser::C_MIXED) { 348 return 'Not supported'; 349 $value = serialize($value); 350 } 351 $attr = array( 352 'name' => "$name" . "[$ns.$directive]", 353 'id' => "$name:$ns.$directive" 354 ); 355 if ($value === null) { 356 $attr['disabled'] = 'disabled'; 357 } 358 if (isset($def->allowed)) { 359 $ret .= $this->start('select', $attr); 360 foreach ($def->allowed as $val => $b) { 361 $attr = array(); 362 if ($value == $val) { 363 $attr['selected'] = 'selected'; 364 } 365 $ret .= $this->element('option', $val, $attr); 366 } 367 $ret .= $this->end('select'); 368 } elseif ($type === HTMLPurifier_VarParser::TEXT || 369 $type === HTMLPurifier_VarParser::ITEXT || 370 $type === HTMLPurifier_VarParser::ALIST || 371 $type === HTMLPurifier_VarParser::HASH || 372 $type === HTMLPurifier_VarParser::LOOKUP) { 373 $attr['cols'] = $this->cols; 374 $attr['rows'] = $this->rows; 375 $ret .= $this->start('textarea', $attr); 376 $ret .= $this->text($value); 377 $ret .= $this->end('textarea'); 378 } else { 379 $attr['value'] = $value; 380 $attr['type'] = 'text'; 381 $ret .= $this->elementEmpty('input', $attr); 382 } 383 return $ret; 384 } 385 } 386 387 /** 388 * Bool form field printer 389 */ 390 class HTMLPurifier_Printer_ConfigForm_bool extends HTMLPurifier_Printer 391 { 392 /** 393 * @param string $ns 394 * @param string $directive 395 * @param string $value 396 * @param string $name 397 * @param HTMLPurifier_Config|array $config 398 * @return string 399 */ 400 public function render($ns, $directive, $value, $name, $config) 401 { 402 if (is_array($config) && isset($config[0])) { 403 $gen_config = $config[0]; 404 $config = $config[1]; 405 } else { 406 $gen_config = $config; 407 } 408 $this->prepareGenerator($gen_config); 409 $ret = ''; 410 $ret .= $this->start('div', array('id' => "$name:$ns.$directive")); 411 412 $ret .= $this->start('label', array('for' => "$name:Yes_$ns.$directive")); 413 $ret .= $this->element('span', "$ns.$directive:", array('class' => 'verbose')); 414 $ret .= $this->text(' Yes'); 415 $ret .= $this->end('label'); 416 417 $attr = array( 418 'type' => 'radio', 419 'name' => "$name" . "[$ns.$directive]", 420 'id' => "$name:Yes_$ns.$directive", 421 'value' => '1' 422 ); 423 if ($value === true) { 424 $attr['checked'] = 'checked'; 425 } 426 if ($value === null) { 427 $attr['disabled'] = 'disabled'; 428 } 429 $ret .= $this->elementEmpty('input', $attr); 430 431 $ret .= $this->start('label', array('for' => "$name:No_$ns.$directive")); 432 $ret .= $this->element('span', "$ns.$directive:", array('class' => 'verbose')); 433 $ret .= $this->text(' No'); 434 $ret .= $this->end('label'); 435 436 $attr = array( 437 'type' => 'radio', 438 'name' => "$name" . "[$ns.$directive]", 439 'id' => "$name:No_$ns.$directive", 440 'value' => '0' 441 ); 442 if ($value === false) { 443 $attr['checked'] = 'checked'; 444 } 445 if ($value === null) { 446 $attr['disabled'] = 'disabled'; 447 } 448 $ret .= $this->elementEmpty('input', $attr); 449 450 $ret .= $this->end('div'); 451 452 return $ret; 453 } 454 } 455 456 // vim: et sw=4 sts=4
title
Description
Body
title
Description
Body
title
Description
Body
title
Body