ILIAS  release_4-3 Revision
 All Data Structures Namespaces Files Functions Variables Groups Pages
ErrorCollector.php
Go to the documentation of this file.
1 <?php
2 
8 {
9 
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 
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 
135  public function getRaw() {
136  return $this->errors;
137  }
138 
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