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&nbsp;=&nbsp;<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