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