Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 1
<?php
2
 
3
/**
4
 * Error collection class that enables HTML Purifier to report HTML
5
 * problems back to the user
6
 */
7
class HTMLPurifier_ErrorCollector
8
{
9
 
10
    /**
11
     * Identifiers for the returned error array. These are purposely numeric
12
     * so list() can be used.
13
     */
14
    const LINENO   = 0;
15
    const SEVERITY = 1;
16
    const MESSAGE  = 2;
17
    const CHILDREN = 3;
18
 
19
    /**
20
     * @type array
21
     */
22
    protected $errors;
23
 
24
    /**
25
     * @type array
26
     */
27
    protected $_current;
28
 
29
    /**
30
     * @type array
31
     */
32
    protected $_stacks = array(array());
33
 
34
    /**
35
     * @type HTMLPurifier_Language
36
     */
37
    protected $locale;
38
 
39
    /**
40
     * @type HTMLPurifier_Generator
41
     */
42
    protected $generator;
43
 
44
    /**
45
     * @type HTMLPurifier_Context
46
     */
47
    protected $context;
48
 
49
    /**
50
     * @type array
51
     */
52
    protected $lines = array();
53
 
54
    /**
55
     * @param HTMLPurifier_Context $context
56
     */
57
    public function __construct($context)
58
    {
59
        $this->locale    =& $context->get('Locale');
60
        $this->context   = $context;
61
        $this->_current  =& $this->_stacks[0];
62
        $this->errors    =& $this->_stacks[0];
63
    }
64
 
65
    /**
66
     * Sends an error message to the collector for later use
67
     * @param int $severity Error severity, PHP error style (don't use E_USER_)
68
     * @param string $msg Error message text
69
     */
70
    public function send($severity, $msg)
71
    {
72
        $args = array();
73
        if (func_num_args() > 2) {
74
            $args = func_get_args();
75
            array_shift($args);
76
            unset($args[0]);
77
        }
78
 
79
        $token = $this->context->get('CurrentToken', true);
80
        $line  = $token ? $token->line : $this->context->get('CurrentLine', true);
81
        $col   = $token ? $token->col  : $this->context->get('CurrentCol', true);
82
        $attr  = $this->context->get('CurrentAttr', true);
83
 
84
        // perform special substitutions, also add custom parameters
85
        $subst = array();
86
        if (!is_null($token)) {
87
            $args['CurrentToken'] = $token;
88
        }
89
        if (!is_null($attr)) {
90
            $subst['$CurrentAttr.Name'] = $attr;
91
            if (isset($token->attr[$attr])) {
92
                $subst['$CurrentAttr.Value'] = $token->attr[$attr];
93
            }
94
        }
95
 
96
        if (empty($args)) {
97
            $msg = $this->locale->getMessage($msg);
98
        } else {
99
            $msg = $this->locale->formatMessage($msg, $args);
100
        }
101
 
102
        if (!empty($subst)) {
103
            $msg = strtr($msg, $subst);
104
        }
105
 
106
        // (numerically indexed)
107
        $error = array(
108
            self::LINENO   => $line,
109
            self::SEVERITY => $severity,
110
            self::MESSAGE  => $msg,
111
            self::CHILDREN => array()
112
        );
113
        $this->_current[] = $error;
114
 
115
        // NEW CODE BELOW ...
116
        // Top-level errors are either:
117
        //  TOKEN type, if $value is set appropriately, or
118
        //  "syntax" type, if $value is null
119
        $new_struct = new HTMLPurifier_ErrorStruct();
120
        $new_struct->type = HTMLPurifier_ErrorStruct::TOKEN;
121
        if ($token) {
122
            $new_struct->value = clone $token;
123
        }
124
        if (is_int($line) && is_int($col)) {
125
            if (isset($this->lines[$line][$col])) {
126
                $struct = $this->lines[$line][$col];
127
            } else {
128
                $struct = $this->lines[$line][$col] = $new_struct;
129
            }
130
            // These ksorts may present a performance problem
131
            ksort($this->lines[$line], SORT_NUMERIC);
132
        } else {
133
            if (isset($this->lines[-1])) {
134
                $struct = $this->lines[-1];
135
            } else {
136
                $struct = $this->lines[-1] = $new_struct;
137
            }
138
        }
139
        ksort($this->lines, SORT_NUMERIC);
140
 
141
        // Now, check if we need to operate on a lower structure
142
        if (!empty($attr)) {
143
            $struct = $struct->getChild(HTMLPurifier_ErrorStruct::ATTR, $attr);
144
            if (!$struct->value) {
145
                $struct->value = array($attr, 'PUT VALUE HERE');
146
            }
147
        }
148
        if (!empty($cssprop)) {
149
            $struct = $struct->getChild(HTMLPurifier_ErrorStruct::CSSPROP, $cssprop);
150
            if (!$struct->value) {
151
                // if we tokenize CSS this might be a little more difficult to do
152
                $struct->value = array($cssprop, 'PUT VALUE HERE');
153
            }
154
        }
155
 
156
        // Ok, structs are all setup, now time to register the error
157
        $struct->addError($severity, $msg);
158
    }
159
 
160
    /**
161
     * Retrieves raw error data for custom formatter to use
162
     */
163
    public function getRaw()
164
    {
165
        return $this->errors;
166
    }
167
 
168
    /**
169
     * Default HTML formatting implementation for error messages
170
     * @param HTMLPurifier_Config $config Configuration, vital for HTML output nature
171
     * @param array $errors Errors array to display; used for recursion.
172
     * @return string
173
     */
174
    public function getHTMLFormatted($config, $errors = null)
175
    {
176
        $ret = array();
177
 
178
        $this->generator = new HTMLPurifier_Generator($config, $this->context);
179
        if ($errors === null) {
180
            $errors = $this->errors;
181
        }
182
 
183
        // 'At line' message needs to be removed
184
 
185
        // generation code for new structure goes here. It needs to be recursive.
186
        foreach ($this->lines as $line => $col_array) {
187
            if ($line == -1) {
188
                continue;
189
            }
190
            foreach ($col_array as $col => $struct) {
191
                $this->_renderStruct($ret, $struct, $line, $col);
192
            }
193
        }
194
        if (isset($this->lines[-1])) {
195
            $this->_renderStruct($ret, $this->lines[-1]);
196
        }
197
 
198
        if (empty($errors)) {
199
            return '<p>' . $this->locale->getMessage('ErrorCollector: No errors') . '</p>';
200
        } else {
201
            return '<ul><li>' . implode('</li><li>', $ret) . '</li></ul>';
202
        }
203
 
204
    }
205
 
206
    private function _renderStruct(&$ret, $struct, $line = null, $col = null)
207
    {
208
        $stack = array($struct);
209
        $context_stack = array(array());
210
        while ($current = array_pop($stack)) {
211
            $context = array_pop($context_stack);
212
            foreach ($current->errors as $error) {
213
                list($severity, $msg) = $error;
214
                $string = '';
215
                $string .= '<div>';
216
                // W3C uses an icon to indicate the severity of the error.
217
                $error = $this->locale->getErrorName($severity);
218
                $string .= "<span class=\"error e$severity\"><strong>$error</strong></span> ";
219
                if (!is_null($line) && !is_null($col)) {
220
                    $string .= "<em class=\"location\">Line $line, Column $col: </em> ";
221
                } else {
222
                    $string .= '<em class="location">End of Document: </em> ';
223
                }
224
                $string .= '<strong class="description">' . $this->generator->escape($msg) . '</strong> ';
225
                $string .= '</div>';
226
                // Here, have a marker for the character on the column appropriate.
227
                // Be sure to clip extremely long lines.
228
                //$string .= '<pre>';
229
                //$string .= '';
230
                //$string .= '</pre>';
231
                $ret[] = $string;
232
            }
233
            foreach ($current->children as $array) {
234
                $context[] = $current;
235
                $stack = array_merge($stack, array_reverse($array, true));
236
                for ($i = count($array); $i > 0; $i--) {
237
                    $context_stack[] = $context;
238
                }
239
            }
240
        }
241
    }
242
}
243
 
244
// vim: et sw=4 sts=4