1: <?php
2:
3: 4: 5: 6:
7: class HTMLPurifier_ErrorCollector
8: {
9:
10: 11: 12: 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: 37: 38: 39: 40: 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:
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:
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:
85:
86: $struct = null;
87:
88:
89:
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:
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:
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:
121: $struct->value = array($cssprop, 'PUT VALUE HERE');
122: }
123: }
124:
125:
126: $struct->addError($severity, $msg);
127: }
128:
129: 130: 131: 132: 133: 134:
135: public function getRaw() {
136: return $this->errors;
137: }
138:
139: 140: 141: 142: 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:
151:
152:
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:
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:
191:
192:
193:
194:
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:
210: