Squiz Matrix  4.12.2
 All Data Structures Namespaces Functions Variables Pages
content_type_code.inc
1 <?php
18 require_once SQ_CORE_PACKAGE_PATH.'/content_type/content_type.inc';
19 
32 {
33 
34 
41  function __construct($assetid=0)
42  {
43  $this->_ser_attrs = TRUE;
44  parent::__construct($assetid);
45 
46  }//end constructor
47 
48 
58  function highlightOther($str)
59  {
60  $highlighted = $str;
61 
62  $classes = $GLOBALS['SQ_SYSTEM']->getUserPrefs($this->type(), 'SQ_CODE_EDITOR_HTML_CLASSES');
63 
64  // Match Comments
65  $highlighted = str_replace('<!--', '&lt!--', $highlighted);
66  $highlighted = str_replace('-->', '--&gt;', $highlighted);
67 
68  // $highlighted = preg_replace('/COMMENT_START(.*|\n)COMMENT_END/i', 'SPANSTART class="'.$classes['html_comment'].'>&lt;--\\1--&gt;ENDSPAN',$highlighted);
69 
70 
71  // Below Matches Single html tags(those without attributes specifified, as well as singleton tags);
72  $matches = Array();
73  preg_match_all('/<([A-Za-z]+[A-Za-z0-9_]*)(\s*\/)>/i', $highlighted, $matches);
74 
75  $count = count($matches[0]);
76  for ($i = 0; $i < $count; $i++) {
77  $needle = $matches[0][$i];
78  $replace = 'SPANSTART class="'.$classes['tag_brackets'].'">&lt;ENDSPAN';
79  $replace .= 'SPANSTART class="'.$classes['tag_name'].'">'.$matches[1][$i].'ENDSPAN';
80  $replace .= 'SPANSTART class="'.$classes['tag_brackets'].'">'.$matches[2][$i].'&gt;ENDSPAN';
81  $highlighted = str_replace($needle, $replace, $highlighted);
82  }
83 
84  // End tags ( </aaa> )
85  $matches = Array();
86  preg_match_all('/<\/\s*([A-Za-z][A-Za-z0-9_]*)>/i', $highlighted, $matches);
87 
88  $count = count($matches[0]);
89  for ($i = 0; $i < $count; $i++) {
90  $needle = $matches[0][$i];
91  $replace = 'SPANSTART class="'.$classes['tag_brackets'].'">&lt;/ENDSPAN';
92  $replace .= 'SPANSTART class="'.$classes['tag_name'].'">'.$matches[1][$i].'ENDSPAN';
93  $replace .= 'SPANSTART class="'.$classes['tag_brackets'].'">&gt;ENDSPAN';
94  $highlighted = str_replace($needle, $replace, $highlighted);
95  }
96 
97  $simple_matches = Array();
98 
99  // Tags like <h1> etc;
100  $matches = Array();
101  preg_match_all('/<\s*([A-Za-z]+[A-Za-z0-9_]*)>/i', $highlighted, $matches);
102 
103  $count = count($matches[0]);
104  for ($i = 0; $i < $count; $i++) {
105  $needle = $matches[0][$i];
106  $replace = 'SPANSTART class="'.$classes['tag_brackets'].'">&lt;ENDSPAN';
107  $replace .= 'SPANSTART class="'.$classes['tag_name'].'">'.$matches[1][$i].'ENDSPAN';
108  $replace .= 'SPANSTART class="'.$classes['tag_brackets'].'">&gt;ENDSPAN';
109  $highlighted = str_replace($needle, $replace, $highlighted);
110  }
111 
112  foreach ($simple_matches as $needle) {
113  $replace = 'SPANSTART style="color: blue;">'.htmlspecialchars($needle).'ENDSPAN';
114  $highlighted = str_replace($needle, $replace, $highlighted);
115  }
116 
117  // Match Param Names
118  $matches = Array();
119  preg_match_all('/<\\s*([A-Za-z][A-Za-z0-9]*)\\s+([^>]*)\\s*>/i', $highlighted, $matches);
120 
121  $count = count($matches[0]);
122  for ($i = 0; $i < $count; $i++) {
123  $original = $matches[0][$i];
124  $replace_text = $original;
125  $replace_text = str_replace('<', '&lt;', $replace_text);
126  $replace_text = str_replace('/>', 'ORIG_END_TAG', $replace_text);
127  $replace_text = str_replace('>', 'TAG_END_BRACE', $replace_text);
128  $replace_text = preg_replace('/([a-z]+-?_?[a-z]*)\\s*=\\s*\"([^\"]*)\"/i', 'SPANSTART class="'.$classes['attribute_names'].'">$1ENDSPAN=SPANSTART class="'.$classes['attribute_value'].'">&quot;$2&quot;ENDSPAN', $replace_text);
129  $replace_text = preg_replace('/&lt;('.trim($matches[1][$i]).')/i', 'SPANSTART class="'.$classes['tag_brackets'].'">&lt;ENDSPANSPANSTART class="'.$classes['tag_name'].'">'.$matches[1][$i].'ENDSPAN', $replace_text);
130 
131  $highlighted = str_replace($original, $replace_text, $highlighted);
132  }
133 
134  $highlighted = str_replace('<', '&lt;', $highlighted);
135 
136  $highlighted = str_replace('SPANSTART', '<span', $highlighted);
137  $highlighted = str_replace('ENDSPAN', '</span>', $highlighted);
138  $highlighted = str_replace('ORIG_END_TAG', '<span class="'.$classes['tag_brackets'].'">/&gt;</span>', $highlighted);
139  $highlighted = str_replace('TAG_END_BRACE', '<span class="'.$classes['tag_brackets'].'">&gt;</span>', $highlighted);
140 
141  return $highlighted;
142 
143  }//end highlightOther()
144 
145 
155  function highlightPHP($str)
156  {
157  $highlighted = $str;
158  if (trim($str) == '') return '';
159  // Grab the preferences
160  $classes = $GLOBALS['SQ_SYSTEM']->getUserPrefs($this->type(), 'SQ_CODE_EDITOR_PHP_CLASSES');
161 
162  $system_colours = Array();
163  $system_colours[strtolower(strval(ini_get('highlight.bg')))] = $classes['background'];
164  $system_colours[strtolower(strval(ini_get('highlight.default')))] = $classes['default'];
165  $system_colours[strtolower(strval(ini_get('highlight.html')))] = $classes['html'];
166  $system_colours[strtolower(strval(ini_get('highlight.keyword')))] = $classes['keyword'];
167  $system_colours[strtolower(strval(ini_get('highlight.comment')))] = $classes['comment'];
168  $system_colours[strtolower(strval(ini_get('highlight.string')))] = $classes['string'];
169 
170  $one_liner = FALSE;
171  // Check if its only one line
172  if (substr_count($highlighted, ';') <= 1) {
173  $one_liner = TRUE;
174  }
175 
176  $highlighted = highlight_string($highlighted, TRUE);
177 
178  $highlighted = str_replace('<code>', '', $highlighted);
179  $highlighted = str_replace('</code>', '', $highlighted);
180  $highlighted = str_replace('&nbsp;', ' ', $highlighted);
181 
182  $highlighted = str_replace(Array('<font ', '</font>'), Array('<span ', '</span>'), $highlighted);
183  foreach ($classes as $colour => $class) {
184  $highlighted = str_replace('color="'.strtoupper($colour).'"', 'class="'.$class.'"', $highlighted);
185  }
186 
187  $matches = Array();
188  preg_match_all('#color="(.*?)"#', $highlighted, $matches);
189  $count = count($matches[0]);
190  for ($i = 0; $i < $count; $i++) {
191  $needle = $matches[0][$i];
192  $replace_class = $system_colours[strtolower($matches[1][$i])];
193  $replace = 'class="'.$replace_class.'"';
194  $highlighted = str_replace($needle, $replace, $highlighted);
195  }
196 
197  // If there is only one expression, we want it to appear in the current context, so we have to strip out any new lines
198  if ($one_liner == TRUE) {
199  $highlighted = str_replace("\n", '', $highlighted);
200  }
201  // PHP Seems to pop this span over multiple lines when it has similar elements in a row
202  // eg. if there is a brace ({) and a var on the next line, the highlighter sees them as the same
203  // grouping and the span puts both inside. This will split those up into 2 spans
204  // preg_match_all('/<span class\=".*">\{<br \/>.*<\/span>/i', $highlighted, $matches=Array());
205 
206  $highlighted = str_replace('<br />', "\n", $highlighted);
207 
208  return $highlighted;
209 
210  }//end highlightPHP()
211 
212 
222  function highlightScript($str)
223  {
224  $reserved = Array(
225  'abstract', 'as', 'boolean', 'break', 'byte', 'case', 'catch', 'char', 'class', 'continue', 'const',
226  'debugger', 'default', 'delete', 'do', 'double', 'else', 'enum', 'export', 'extends', 'FALSE', 'final',
227  'finally', 'float', 'for', 'function', 'goto', 'if', 'implements', 'import', 'in', 'instanceof', 'int', 'interface',
228  'is', 'long', 'namespace', 'native', 'new', 'null', 'package', 'private', 'protected', 'public', 'return', 'short', 'static',
229  'super', 'switch', 'synchronized', 'this', 'throw', 'throws', 'transient', 'TRUE', 'try', 'typeof', 'use', 'var', 'void', 'volatile',
230  'while', 'with',
231  );
232  $highlighted = str_replace(Array('jsender', 'jsstarter'), '' , $str);
233 
234  // Get our user preferences
235  $classes = $GLOBALS['SQ_SYSTEM']->getUserPrefs($this->type(), 'SQ_CODE_EDITOR_JS_CLASSES');
236 
237  $highlighted = preg_replace('/(\".*\")/i', '<span class="'.$classes['string'].'">\\1</span>', $highlighted);
238  $highlighted = preg_replace('/(\'.*\')/i', '<span class="'.$classes['string'].'">\\1</span>', $highlighted);
239 
240  // Highlight any reserved words
241 
242  foreach ($reserved as $word) {
243  $highlighted = str_replace(' '.$word.' ', '<span class="'.$classes['reserved'].'"> '.$word.' </span>', $highlighted);
244  $highlighted = str_replace(' '.$word.'.', '<span class="'.$classes['reserved'].'"> '.$word.'.</span>', $highlighted);
245  }
246 
247  $highlighted = preg_replace('/([a-zA-Z_]*)\((.*)\)/i', '<span class="'.$classes['function'].'">\\1</span><span class="'.$classes['brackets'].'">(</span><span class="'.$classes['default'].'">\\2</span><span class="'.$classes['brackets'].'">)</span>', $highlighted);
248  $highlighted = preg_replace('/\/\/(.*)\n/', '<span class="'.$classes['comment'].'">//\\1</span>', $highlighted);
249 
250 
251  return $highlighted;
252 
253  }//end highlightScript()
254 
255 
265  function syntaxHighlight($str)
266  {
267  $highlighted = '';
268 
269  $php_start_token = 'PHPSTARTTAG';
270  $php_end_token = 'PHPENDTAG';
271 
272  // Remove windows carriage returns
273  $str = str_replace("\r", '', $str);
274 
275  // Handle the XML Tags, so they don't get messed up with the PHP start tags
276  $matches = Array();
277  preg_match_all('/<\?\s*xml.*\?>/i', $str, $matches);
278  foreach ($matches as $text) {
279  $replace = str_replace(Array('<?', '?>'), Array('<XMLSTART', 'XMLEND>'), $text);
280  $str = str_replace($text, $replace, $str);
281  }
282 
283  $str = str_replace('<?php', $php_start_token, $str);
284  $str = str_replace('<?PHP', $php_start_token, $str);
285  $str = str_replace('<?', $php_start_token.' ', $str);
286  $str = str_replace(' ?>', ' '.$php_end_token, $str);
287  $str = str_replace('<?', $php_start_token.' ', $str);
288  $str = str_replace('?>', $php_end_token, $str);
289 
290  // Replace any php code that appears between quotes (ie in an html attribute)
291  // Replaced with an alphabetical string, so that attributes see this as a valid attribute value
292  $str = preg_replace('/\"(.*)'.$php_start_token.'(.*)'.$php_end_token.'(.*)\"/i', '"\\1inlinephpstart\\2inlinephpend\\3"',$str);
293 
294  // Get some javascript gear in here now. The rest of the text will be parsed as usual(like inline PHP, quotes etc.
295  // But this may highlight some reserved words etc.
296  $str = preg_replace('/(script .*javascript.*>)/i', '\\1jsstarter', $str);
297  $str = preg_replace('/(<\/script>)/i', 'jsender\\1', $str);
298 
299  // Keep shortening the original string, by cutting it at the php tags
300  while (FALSE !== ($start_pos = strpos($str, $php_start_token))) {
301  $other_string = substr($str, 0, $start_pos);
302 
303  $highlighted .= $this->highlightOther($other_string);
304  $str = substr($str, $start_pos);
305  $length = strlen($str);
306  if (strpos($str, $php_end_token) === FALSE) {
307  $str .= $php_end_token;
308  }
309 
310  $end_pos = strpos($str, $php_end_token);
311  $end_pos += strlen($php_end_token);
312  $php_string = substr($str, 0, $end_pos);
313 
314  $php_string = str_replace($php_start_token, '<?php', $php_string);
315  $php_string = str_replace($php_end_token, '?>', $php_string);
316 
317  $php_highlighted = $this->highlightPHP($php_string);
318 
319  // Remove the leading first line, that causes problems
320  $php_highlighted = preg_replace('/(<span class="php_html">)\n/i', '\\1', $php_highlighted, 1);
321  $highlighted .= $php_highlighted;
322 
323  $str = substr($str, strpos($str, $php_end_token) + strlen($php_end_token));
324 
325  }// End While PHP Tags exist
326 
327  // Get the bit after the last PHP tag
328  $highlighted .= $this->highlightOther($str);
329 
330  $start_pos = strpos($highlighted, 'jsstarter');
331  $end_pos = strpos($highlighted, 'jsender');
332  $script = substr($highlighted, $start_pos, $end_pos - $start_pos + 7);
333 
334  if ($end_pos !== FALSE && $start_pos !== FALSE) {
335  $result = $this->highlightScript($script);
336  $highlighted = str_replace($script, $result, $highlighted);
337  } else {
338  $highlighted = str_replace(Array ('jsender', 'jsstarter'), '', $highlighted);
339  }
340 
341  $highlighted = str_replace(Array('inlinephpstart', 'inlinephpend'), Array('&lt;?php', '?&gt;'), $highlighted);
342  $highlighted = str_replace('>jsender<', '><', $highlighted);
343  $highlighted = str_replace(Array('XMLSTART', 'XMLEND'), Array('?', '?'), $highlighted);
344 
345  $line_num_prefs = $GLOBALS['SQ_SYSTEM']->getUserPrefs($this->type(), 'SQ_CODE_EDITOR_LINE_NUMBERS');
346  $current_line_settings = $this->attr('line_numbers');
347  foreach ($current_line_settings as $name => $value) {
348  $line_num_prefs[$name] = $value;
349  }
350 
351  // Some post processing. Remove trailing empty lines. Fix up end tags that seem to get indented etc
352  // Use this to process anything that seems to abnormal in highlighting
353  $lines = explode("\n", $highlighted);
354  // Iterate backwards, so we deal with only those lines at the end
355  for ($i = count($lines) -1; $i > 0; $i--) {
356  // Remove empty lines, and those that contain only span closing tags
357  if ((trim($lines[$i]) == '') || (trim($lines[$i]) == '</span>')) {
358  $lines[$i - 1] .= $lines[$i];
359  unset($lines[$i]);
360  continue;
361  }
362  break;
363  }
364  $highlighted = implode("\n", $lines);
365  if ($line_num_prefs['use_line_numbers'] == TRUE) {
366  $highlighted = $this->addLineNumbers($highlighted, $line_num_prefs['line_number_left'], $line_num_prefs['line_number_style'], $line_num_prefs['line_number_class']);
367  }
368  return '<pre>'.$highlighted.'</pre>';
369 
370  }//end syntaxHighlight()
371 
372 
385  function addLineNumbers($str, $left=TRUE, $style='span', $class='line_numbers')
386  {
387  $lines = explode("\n", $str);
388 
389  if ($left == FALSE) $style='span';
390  switch (strtolower($style)) {
391  case 'span':
392  if ($left) {
393  // Setup the replace value.
394  // We leave -margin_value- and -line_number- in there, as they will be determined later
395  $replace = '<span class="'.$class.'" style="-margin_value-">-line_number-</span>';
396  $replace = "\n$replace";
397 
398  // Replace all the new lines with our gear
399  if ($left) {
400  $str = preg_replace('/\n/i', $replace, $str);
401  // Add one for the first line
402  $str = $replace.$str;
403  }
404 
405  // Now we need a count of how many lines there are.
406  $matches = Array();
407  preg_match_all('/-line_number-/i', $str, $matches);
408  $line_number = count($matches[0]);
409 
410  // Now we can go through the line numbers, and pad them on the left with spaces
411  // So they appear right-aligned and in 1 column
412  $current_line = 1;
413  while (FALSE !== strpos($str, '-line_number-')) {
414  $filler = str_repeat('&nbsp;', strlen(strval($line_number)) - strlen(strval($current_line)));
415  $str = preg_replace('/-line_number-/i', $filler.$current_line.':', $str, 1);
416  $current_line++;
417  }
418 
419  // Work out the margin based on the number of digits in our line numbers
420  $margin = strlen(strval($line_number)) * 6 + 5;
421 
422  for ($i = 1; $i <= $line_number; $i++) {
423  $replace = 'margin-right: 10px;';
424  $str = preg_replace('/-margin_value-/i', $replace, $str, 1);
425  }
426  } else {
427  // Line Numbers on the right
428  $new_str = '<table style="width: 100%;" ><tr><td><pre>'.$str.'</pre></td><td style="width: 100px;" >';
429  $line_numbers = range(1, count($lines));
430  $new_str .= '<pre>'.implode("\n", $line_numbers).'</pre>';
431  $new_str .= '</td></tr></table>';
432  $str = $new_str;
433  }
434  break;
435  case 'list':
436  $str = implode('</pre></li><li class="'.$class.'"><pre>', $lines);
437  $str = '<ol><li class="'.$class.'">'.$str.'</li></ol>';
438  break;
439  }//end switch line style
440  return $str;
441 
442  }//end addLineNumbers()
443 
444 
445 }//end class
446 
447 ?>