]> git.immae.eu Git - github/wallabag/wallabag.git/blob - inc/3rdparty/htmlpurifier/HTMLPurifier/ErrorCollector.php
[add] HTML Purifier added to clean code
[github/wallabag/wallabag.git] / inc / 3rdparty / htmlpurifier / HTMLPurifier / ErrorCollector.php
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