File indexing completed on 2024-12-22 05:36:20
0001 <?php 0002 0003 class HTMLPurifier_Printer_HTMLDefinition extends HTMLPurifier_Printer 0004 { 0005 0006 /** 0007 * @type HTMLPurifier_HTMLDefinition, for easy access 0008 */ 0009 protected $def; 0010 0011 /** 0012 * @param HTMLPurifier_Config $config 0013 * @return string 0014 */ 0015 public function render($config) 0016 { 0017 $ret = ''; 0018 $this->config =& $config; 0019 0020 $this->def = $config->getHTMLDefinition(); 0021 0022 $ret .= $this->start('div', array('class' => 'HTMLPurifier_Printer')); 0023 0024 $ret .= $this->renderDoctype(); 0025 $ret .= $this->renderEnvironment(); 0026 $ret .= $this->renderContentSets(); 0027 $ret .= $this->renderInfo(); 0028 0029 $ret .= $this->end('div'); 0030 0031 return $ret; 0032 } 0033 0034 /** 0035 * Renders the Doctype table 0036 * @return string 0037 */ 0038 protected function renderDoctype() 0039 { 0040 $doctype = $this->def->doctype; 0041 $ret = ''; 0042 $ret .= $this->start('table'); 0043 $ret .= $this->element('caption', 'Doctype'); 0044 $ret .= $this->row('Name', $doctype->name); 0045 $ret .= $this->row('XML', $doctype->xml ? 'Yes' : 'No'); 0046 $ret .= $this->row('Default Modules', implode($doctype->modules, ', ')); 0047 $ret .= $this->row('Default Tidy Modules', implode($doctype->tidyModules, ', ')); 0048 $ret .= $this->end('table'); 0049 return $ret; 0050 } 0051 0052 0053 /** 0054 * Renders environment table, which is miscellaneous info 0055 * @return string 0056 */ 0057 protected function renderEnvironment() 0058 { 0059 $def = $this->def; 0060 0061 $ret = ''; 0062 0063 $ret .= $this->start('table'); 0064 $ret .= $this->element('caption', 'Environment'); 0065 0066 $ret .= $this->row('Parent of fragment', $def->info_parent); 0067 $ret .= $this->renderChildren($def->info_parent_def->child); 0068 $ret .= $this->row('Block wrap name', $def->info_block_wrapper); 0069 0070 $ret .= $this->start('tr'); 0071 $ret .= $this->element('th', 'Global attributes'); 0072 $ret .= $this->element('td', $this->listifyAttr($def->info_global_attr), null, 0); 0073 $ret .= $this->end('tr'); 0074 0075 $ret .= $this->start('tr'); 0076 $ret .= $this->element('th', 'Tag transforms'); 0077 $list = array(); 0078 foreach ($def->info_tag_transform as $old => $new) { 0079 $new = $this->getClass($new, 'TagTransform_'); 0080 $list[] = "<$old> with $new"; 0081 } 0082 $ret .= $this->element('td', $this->listify($list)); 0083 $ret .= $this->end('tr'); 0084 0085 $ret .= $this->start('tr'); 0086 $ret .= $this->element('th', 'Pre-AttrTransform'); 0087 $ret .= $this->element('td', $this->listifyObjectList($def->info_attr_transform_pre)); 0088 $ret .= $this->end('tr'); 0089 0090 $ret .= $this->start('tr'); 0091 $ret .= $this->element('th', 'Post-AttrTransform'); 0092 $ret .= $this->element('td', $this->listifyObjectList($def->info_attr_transform_post)); 0093 $ret .= $this->end('tr'); 0094 0095 $ret .= $this->end('table'); 0096 return $ret; 0097 } 0098 0099 /** 0100 * Renders the Content Sets table 0101 * @return string 0102 */ 0103 protected function renderContentSets() 0104 { 0105 $ret = ''; 0106 $ret .= $this->start('table'); 0107 $ret .= $this->element('caption', 'Content Sets'); 0108 foreach ($this->def->info_content_sets as $name => $lookup) { 0109 $ret .= $this->heavyHeader($name); 0110 $ret .= $this->start('tr'); 0111 $ret .= $this->element('td', $this->listifyTagLookup($lookup)); 0112 $ret .= $this->end('tr'); 0113 } 0114 $ret .= $this->end('table'); 0115 return $ret; 0116 } 0117 0118 /** 0119 * Renders the Elements ($info) table 0120 * @return string 0121 */ 0122 protected function renderInfo() 0123 { 0124 $ret = ''; 0125 $ret .= $this->start('table'); 0126 $ret .= $this->element('caption', 'Elements ($info)'); 0127 ksort($this->def->info); 0128 $ret .= $this->heavyHeader('Allowed tags', 2); 0129 $ret .= $this->start('tr'); 0130 $ret .= $this->element('td', $this->listifyTagLookup($this->def->info), array('colspan' => 2)); 0131 $ret .= $this->end('tr'); 0132 foreach ($this->def->info as $name => $def) { 0133 $ret .= $this->start('tr'); 0134 $ret .= $this->element('th', "<$name>", array('class' => 'heavy', 'colspan' => 2)); 0135 $ret .= $this->end('tr'); 0136 $ret .= $this->start('tr'); 0137 $ret .= $this->element('th', 'Inline content'); 0138 $ret .= $this->element('td', $def->descendants_are_inline ? 'Yes' : 'No'); 0139 $ret .= $this->end('tr'); 0140 if (!empty($def->excludes)) { 0141 $ret .= $this->start('tr'); 0142 $ret .= $this->element('th', 'Excludes'); 0143 $ret .= $this->element('td', $this->listifyTagLookup($def->excludes)); 0144 $ret .= $this->end('tr'); 0145 } 0146 if (!empty($def->attr_transform_pre)) { 0147 $ret .= $this->start('tr'); 0148 $ret .= $this->element('th', 'Pre-AttrTransform'); 0149 $ret .= $this->element('td', $this->listifyObjectList($def->attr_transform_pre)); 0150 $ret .= $this->end('tr'); 0151 } 0152 if (!empty($def->attr_transform_post)) { 0153 $ret .= $this->start('tr'); 0154 $ret .= $this->element('th', 'Post-AttrTransform'); 0155 $ret .= $this->element('td', $this->listifyObjectList($def->attr_transform_post)); 0156 $ret .= $this->end('tr'); 0157 } 0158 if (!empty($def->auto_close)) { 0159 $ret .= $this->start('tr'); 0160 $ret .= $this->element('th', 'Auto closed by'); 0161 $ret .= $this->element('td', $this->listifyTagLookup($def->auto_close)); 0162 $ret .= $this->end('tr'); 0163 } 0164 $ret .= $this->start('tr'); 0165 $ret .= $this->element('th', 'Allowed attributes'); 0166 $ret .= $this->element('td', $this->listifyAttr($def->attr), array(), 0); 0167 $ret .= $this->end('tr'); 0168 0169 if (!empty($def->required_attr)) { 0170 $ret .= $this->row('Required attributes', $this->listify($def->required_attr)); 0171 } 0172 0173 $ret .= $this->renderChildren($def->child); 0174 } 0175 $ret .= $this->end('table'); 0176 return $ret; 0177 } 0178 0179 /** 0180 * Renders a row describing the allowed children of an element 0181 * @param HTMLPurifier_ChildDef $def HTMLPurifier_ChildDef of pertinent element 0182 * @return string 0183 */ 0184 protected function renderChildren($def) 0185 { 0186 $context = new HTMLPurifier_Context(); 0187 $ret = ''; 0188 $ret .= $this->start('tr'); 0189 $elements = array(); 0190 $attr = array(); 0191 if (isset($def->elements)) { 0192 if ($def->type == 'strictblockquote') { 0193 $def->validateChildren(array(), $this->config, $context); 0194 } 0195 $elements = $def->elements; 0196 } 0197 if ($def->type == 'chameleon') { 0198 $attr['rowspan'] = 2; 0199 } elseif ($def->type == 'empty') { 0200 $elements = array(); 0201 } elseif ($def->type == 'table') { 0202 $elements = array_flip( 0203 array( 0204 'col', 0205 'caption', 0206 'colgroup', 0207 'thead', 0208 'tfoot', 0209 'tbody', 0210 'tr' 0211 ) 0212 ); 0213 } 0214 $ret .= $this->element('th', 'Allowed children', $attr); 0215 0216 if ($def->type == 'chameleon') { 0217 0218 $ret .= $this->element( 0219 'td', 0220 '<em>Block</em>: ' . 0221 $this->escape($this->listifyTagLookup($def->block->elements)), 0222 null, 0223 0 0224 ); 0225 $ret .= $this->end('tr'); 0226 $ret .= $this->start('tr'); 0227 $ret .= $this->element( 0228 'td', 0229 '<em>Inline</em>: ' . 0230 $this->escape($this->listifyTagLookup($def->inline->elements)), 0231 null, 0232 0 0233 ); 0234 0235 } elseif ($def->type == 'custom') { 0236 0237 $ret .= $this->element( 0238 'td', 0239 '<em>' . ucfirst($def->type) . '</em>: ' . 0240 $def->dtd_regex 0241 ); 0242 0243 } else { 0244 $ret .= $this->element( 0245 'td', 0246 '<em>' . ucfirst($def->type) . '</em>: ' . 0247 $this->escape($this->listifyTagLookup($elements)), 0248 null, 0249 0 0250 ); 0251 } 0252 $ret .= $this->end('tr'); 0253 return $ret; 0254 } 0255 0256 /** 0257 * Listifies a tag lookup table. 0258 * @param array $array Tag lookup array in form of array('tagname' => true) 0259 * @return string 0260 */ 0261 protected function listifyTagLookup($array) 0262 { 0263 ksort($array); 0264 $list = array(); 0265 foreach ($array as $name => $discard) { 0266 if ($name !== '#PCDATA' && !isset($this->def->info[$name])) { 0267 continue; 0268 } 0269 $list[] = $name; 0270 } 0271 return $this->listify($list); 0272 } 0273 0274 /** 0275 * Listifies a list of objects by retrieving class names and internal state 0276 * @param array $array List of objects 0277 * @return string 0278 * @todo Also add information about internal state 0279 */ 0280 protected function listifyObjectList($array) 0281 { 0282 ksort($array); 0283 $list = array(); 0284 foreach ($array as $obj) { 0285 $list[] = $this->getClass($obj, 'AttrTransform_'); 0286 } 0287 return $this->listify($list); 0288 } 0289 0290 /** 0291 * Listifies a hash of attributes to AttrDef classes 0292 * @param array $array Array hash in form of array('attrname' => HTMLPurifier_AttrDef) 0293 * @return string 0294 */ 0295 protected function listifyAttr($array) 0296 { 0297 ksort($array); 0298 $list = array(); 0299 foreach ($array as $name => $obj) { 0300 if ($obj === false) { 0301 continue; 0302 } 0303 $list[] = "$name = <i>" . $this->getClass($obj, 'AttrDef_') . '</i>'; 0304 } 0305 return $this->listify($list); 0306 } 0307 0308 /** 0309 * Creates a heavy header row 0310 * @param string $text 0311 * @param int $num 0312 * @return string 0313 */ 0314 protected function heavyHeader($text, $num = 1) 0315 { 0316 $ret = ''; 0317 $ret .= $this->start('tr'); 0318 $ret .= $this->element('th', $text, array('colspan' => $num, 'class' => 'heavy')); 0319 $ret .= $this->end('tr'); 0320 return $ret; 0321 } 0322 } 0323 0324 // vim: et sw=4 sts=4