HTMLPurifier 4.4.0
|
00001 <?php 00002 00007 class HTMLPurifier_ErrorCollector 00008 { 00009 00014 const LINENO = 0; 00015 const SEVERITY = 1; 00016 const MESSAGE = 2; 00017 const CHILDREN = 3; 00018 00019 protected $errors; 00020 protected $_current; 00021 protected $_stacks = array(array()); 00022 protected $locale; 00023 protected $generator; 00024 protected $context; 00025 00026 protected $lines = array(); 00027 00028 public function __construct($context) { 00029 $this->locale =& $context->get('Locale'); 00030 $this->context = $context; 00031 $this->_current =& $this->_stacks[0]; 00032 $this->errors =& $this->_stacks[0]; 00033 } 00034 00042 public function send($severity, $msg) { 00043 00044 $args = array(); 00045 if (func_num_args() > 2) { 00046 $args = func_get_args(); 00047 array_shift($args); 00048 unset($args[0]); 00049 } 00050 00051 $token = $this->context->get('CurrentToken', true); 00052 $line = $token ? $token->line : $this->context->get('CurrentLine', true); 00053 $col = $token ? $token->col : $this->context->get('CurrentCol', true); 00054 $attr = $this->context->get('CurrentAttr', true); 00055 00056 // perform special substitutions, also add custom parameters 00057 $subst = array(); 00058 if (!is_null($token)) { 00059 $args['CurrentToken'] = $token; 00060 } 00061 if (!is_null($attr)) { 00062 $subst['$CurrentAttr.Name'] = $attr; 00063 if (isset($token->attr[$attr])) $subst['$CurrentAttr.Value'] = $token->attr[$attr]; 00064 } 00065 00066 if (empty($args)) { 00067 $msg = $this->locale->getMessage($msg); 00068 } else { 00069 $msg = $this->locale->formatMessage($msg, $args); 00070 } 00071 00072 if (!empty($subst)) $msg = strtr($msg, $subst); 00073 00074 // (numerically indexed) 00075 $error = array( 00076 self::LINENO => $line, 00077 self::SEVERITY => $severity, 00078 self::MESSAGE => $msg, 00079 self::CHILDREN => array() 00080 ); 00081 $this->_current[] = $error; 00082 00083 00084 // NEW CODE BELOW ... 00085 00086 $struct = null; 00087 // Top-level errors are either: 00088 // TOKEN type, if $value is set appropriately, or 00089 // "syntax" type, if $value is null 00090 $new_struct = new HTMLPurifier_ErrorStruct(); 00091 $new_struct->type = HTMLPurifier_ErrorStruct::TOKEN; 00092 if ($token) $new_struct->value = clone $token; 00093 if (is_int($line) && is_int($col)) { 00094 if (isset($this->lines[$line][$col])) { 00095 $struct = $this->lines[$line][$col]; 00096 } else { 00097 $struct = $this->lines[$line][$col] = $new_struct; 00098 } 00099 // These ksorts may present a performance problem 00100 ksort($this->lines[$line], SORT_NUMERIC); 00101 } else { 00102 if (isset($this->lines[-1])) { 00103 $struct = $this->lines[-1]; 00104 } else { 00105 $struct = $this->lines[-1] = $new_struct; 00106 } 00107 } 00108 ksort($this->lines, SORT_NUMERIC); 00109 00110 // Now, check if we need to operate on a lower structure 00111 if (!empty($attr)) { 00112 $struct = $struct->getChild(HTMLPurifier_ErrorStruct::ATTR, $attr); 00113 if (!$struct->value) { 00114 $struct->value = array($attr, 'PUT VALUE HERE'); 00115 } 00116 } 00117 if (!empty($cssprop)) { 00118 $struct = $struct->getChild(HTMLPurifier_ErrorStruct::CSSPROP, $cssprop); 00119 if (!$struct->value) { 00120 // if we tokenize CSS this might be a little more difficult to do 00121 $struct->value = array($cssprop, 'PUT VALUE HERE'); 00122 } 00123 } 00124 00125 // Ok, structs are all setup, now time to register the error 00126 $struct->addError($severity, $msg); 00127 } 00128 00135 public function getRaw() { 00136 return $this->errors; 00137 } 00138 00144 public function getHTMLFormatted($config, $errors = null) { 00145 $ret = array(); 00146 00147 $this->generator = new HTMLPurifier_Generator($config, $this->context); 00148 if ($errors === null) $errors = $this->errors; 00149 00150 // 'At line' message needs to be removed 00151 00152 // generation code for new structure goes here. It needs to be recursive. 00153 foreach ($this->lines as $line => $col_array) { 00154 if ($line == -1) continue; 00155 foreach ($col_array as $col => $struct) { 00156 $this->_renderStruct($ret, $struct, $line, $col); 00157 } 00158 } 00159 if (isset($this->lines[-1])) { 00160 $this->_renderStruct($ret, $this->lines[-1]); 00161 } 00162 00163 if (empty($errors)) { 00164 return '<p>' . $this->locale->getMessage('ErrorCollector: No errors') . '</p>'; 00165 } else { 00166 return '<ul><li>' . implode('</li><li>', $ret) . '</li></ul>'; 00167 } 00168 00169 } 00170 00171 private function _renderStruct(&$ret, $struct, $line = null, $col = null) { 00172 $stack = array($struct); 00173 $context_stack = array(array()); 00174 while ($current = array_pop($stack)) { 00175 $context = array_pop($context_stack); 00176 foreach ($current->errors as $error) { 00177 list($severity, $msg) = $error; 00178 $string = ''; 00179 $string .= '<div>'; 00180 // W3C uses an icon to indicate the severity of the error. 00181 $error = $this->locale->getErrorName($severity); 00182 $string .= "<span class=\"error e$severity\"><strong>$error</strong></span> "; 00183 if (!is_null($line) && !is_null($col)) { 00184 $string .= "<em class=\"location\">Line $line, Column $col: </em> "; 00185 } else { 00186 $string .= '<em class="location">End of Document: </em> '; 00187 } 00188 $string .= '<strong class="description">' . $this->generator->escape($msg) . '</strong> '; 00189 $string .= '</div>'; 00190 // Here, have a marker for the character on the column appropriate. 00191 // Be sure to clip extremely long lines. 00192 //$string .= '<pre>'; 00193 //$string .= ''; 00194 //$string .= '</pre>'; 00195 $ret[] = $string; 00196 } 00197 foreach ($current->children as $type => $array) { 00198 $context[] = $current; 00199 $stack = array_merge($stack, array_reverse($array, true)); 00200 for ($i = count($array); $i > 0; $i--) { 00201 $context_stack[] = $context; 00202 } 00203 } 00204 } 00205 } 00206 00207 } 00208 00209 // vim: et sw=4 sts=4