1<?php
2
3// OUT OF DATE, NEEDS UPDATING!
4// USE XMLWRITER!
5
6class HTMLPurifier_Printer
7{
8
9    /**
10     * For HTML generation convenience funcs.
11     * @type HTMLPurifier_Generator
12     */
13    protected $generator;
14
15    /**
16     * For easy access.
17     * @type HTMLPurifier_Config
18     */
19    protected $config;
20
21    /**
22     * Initialize $generator.
23     */
24    public function __construct()
25    {
26    }
27
28    /**
29     * Give generator necessary configuration if possible
30     * @param HTMLPurifier_Config $config
31     */
32    public function prepareGenerator($config)
33    {
34        $all = $config->getAll();
35        $context = new HTMLPurifier_Context();
36        $this->generator = new HTMLPurifier_Generator($config, $context);
37    }
38
39    /**
40     * Main function that renders object or aspect of that object
41     * @note Parameters vary depending on printer
42     */
43    // function render() {}
44
45    /**
46     * Returns a start tag
47     * @param string $tag Tag name
48     * @param array $attr Attribute array
49     * @return string
50     */
51    protected function start($tag, $attr = array())
52    {
53        return $this->generator->generateFromToken(
54            new HTMLPurifier_Token_Start($tag, $attr ? $attr : array())
55        );
56    }
57
58    /**
59     * Returns an end tag
60     * @param string $tag Tag name
61     * @return string
62     */
63    protected function end($tag)
64    {
65        return $this->generator->generateFromToken(
66            new HTMLPurifier_Token_End($tag)
67        );
68    }
69
70    /**
71     * Prints a complete element with content inside
72     * @param string $tag Tag name
73     * @param string $contents Element contents
74     * @param array $attr Tag attributes
75     * @param bool $escape whether or not to escape contents
76     * @return string
77     */
78    protected function element($tag, $contents, $attr = array(), $escape = true)
79    {
80        return $this->start($tag, $attr) .
81            ($escape ? $this->escape($contents) : $contents) .
82            $this->end($tag);
83    }
84
85    /**
86     * @param string $tag
87     * @param array $attr
88     * @return string
89     */
90    protected function elementEmpty($tag, $attr = array())
91    {
92        return $this->generator->generateFromToken(
93            new HTMLPurifier_Token_Empty($tag, $attr)
94        );
95    }
96
97    /**
98     * @param string $text
99     * @return string
100     */
101    protected function text($text)
102    {
103        return $this->generator->generateFromToken(
104            new HTMLPurifier_Token_Text($text)
105        );
106    }
107
108    /**
109     * Prints a simple key/value row in a table.
110     * @param string $name Key
111     * @param mixed $value Value
112     * @return string
113     */
114    protected function row($name, $value)
115    {
116        if (is_bool($value)) {
117            $value = $value ? 'On' : 'Off';
118        }
119        return
120            $this->start('tr') . "\n" .
121            $this->element('th', $name) . "\n" .
122            $this->element('td', $value) . "\n" .
123            $this->end('tr');
124    }
125
126    /**
127     * Escapes a string for HTML output.
128     * @param string $string String to escape
129     * @return string
130     */
131    protected function escape($string)
132    {
133        $string = HTMLPurifier_Encoder::cleanUTF8($string);
134        $string = htmlspecialchars($string, ENT_COMPAT, 'UTF-8');
135        return $string;
136    }
137
138    /**
139     * Takes a list of strings and turns them into a single list
140     * @param string[] $array List of strings
141     * @param bool $polite Bool whether or not to add an end before the last
142     * @return string
143     */
144    protected function listify($array, $polite = false)
145    {
146        if (empty($array)) {
147            return 'None';
148        }
149        $ret = '';
150        $i = count($array);
151        foreach ($array as $value) {
152            $i--;
153            $ret .= $value;
154            if ($i > 0 && !($polite && $i == 1)) {
155                $ret .= ', ';
156            }
157            if ($polite && $i == 1) {
158                $ret .= 'and ';
159            }
160        }
161        return $ret;
162    }
163
164    /**
165     * Retrieves the class of an object without prefixes, as well as metadata
166     * @param object $obj Object to determine class of
167     * @param string $sec_prefix Further prefix to remove
168     * @return string
169     */
170    protected function getClass($obj, $sec_prefix = '')
171    {
172        static $five = null;
173        if ($five === null) {
174            $five = version_compare(PHP_VERSION, '5', '>=');
175        }
176        $prefix = 'HTMLPurifier_' . $sec_prefix;
177        if (!$five) {
178            $prefix = strtolower($prefix);
179        }
180        $class = str_replace($prefix, '', get_class($obj));
181        $lclass = strtolower($class);
182        $class .= '(';
183        switch ($lclass) {
184            case 'enum':
185                $values = array();
186                foreach ($obj->valid_values as $value => $bool) {
187                    $values[] = $value;
188                }
189                $class .= implode(', ', $values);
190                break;
191            case 'css_composite':
192                $values = array();
193                foreach ($obj->defs as $def) {
194                    $values[] = $this->getClass($def, $sec_prefix);
195                }
196                $class .= implode(', ', $values);
197                break;
198            case 'css_multiple':
199                $class .= $this->getClass($obj->single, $sec_prefix) . ', ';
200                $class .= $obj->max;
201                break;
202            case 'css_denyelementdecorator':
203                $class .= $this->getClass($obj->def, $sec_prefix) . ', ';
204                $class .= $obj->element;
205                break;
206            case 'css_importantdecorator':
207                $class .= $this->getClass($obj->def, $sec_prefix);
208                if ($obj->allow) {
209                    $class .= ', !important';
210                }
211                break;
212        }
213        $class .= ')';
214        return $class;
215    }
216}
217
218// vim: et sw=4 sts=4
219