| 1 |
<?php
|
| 2 |
// $Id: codefilter.module,v 1.29 2008/01/14 10:00:46 johnalbin Exp $
|
| 3 |
|
| 4 |
/**
|
| 5 |
* Implement hook_init().
|
| 6 |
*
|
| 7 |
* Adds the codefilter stylesheet to the page
|
| 8 |
*/
|
| 9 |
function codefilter_init() {
|
| 10 |
drupal_add_css(drupal_get_path('module', 'codefilter') .'/codefilter.css', array('preprocess' => FALSE));
|
| 11 |
}
|
| 12 |
|
| 13 |
/**
|
| 14 |
* Processes chunks of escaped PHP code into HTML.
|
| 15 |
*/
|
| 16 |
function codefilter_process_php($text) {
|
| 17 |
// Note, pay attention to odd preg_replace-with-/e behaviour on slashes
|
| 18 |
// Undo possible linebreak filter conversion
|
| 19 |
$text = preg_replace('@</?(br|p)\s*/?>@', '', str_replace('\"', '"', $text));
|
| 20 |
// Undo the escaping in the prepare step
|
| 21 |
$text = decode_entities($text);
|
| 22 |
// Trim leading and trailing linebreaks
|
| 23 |
$text = trim($text, "\r\n");
|
| 24 |
// Highlight as PHP
|
| 25 |
$text = '<div class="codeblock">'. highlight_string("<?php\n$text\n?>", 1) .'</div>';
|
| 26 |
// Remove newlines to avoid clashing with the linebreak filter
|
| 27 |
$text = str_replace("\n", '', $text);
|
| 28 |
return codefilter_fix_spaces($text);
|
| 29 |
}
|
| 30 |
|
| 31 |
/**
|
| 32 |
* Helper function for codefilter_process_code().
|
| 33 |
*/
|
| 34 |
function codefilter_process_php_inline($matches) {
|
| 35 |
// Undo nl2br
|
| 36 |
$text = str_replace('<br />', '', $matches[0]);
|
| 37 |
// Decode entities (the highlighter re-entifies) and highlight text
|
| 38 |
$text = highlight_string(decode_entities($text), 1);
|
| 39 |
// Remove PHP's own added code tags
|
| 40 |
$text = str_replace(array('<code>', '</code>', "\n"), array('', '', ''), $text);
|
| 41 |
return $text;
|
| 42 |
}
|
| 43 |
|
| 44 |
/**
|
| 45 |
* Processes chunks of escaped code into HTML.
|
| 46 |
*/
|
| 47 |
function codefilter_process_code($text) {
|
| 48 |
// Undo linebreak escaping
|
| 49 |
$text = str_replace(' ', "\n", $text);
|
| 50 |
// Inline or block level piece?
|
| 51 |
$multiline = strpos($text, "\n") !== FALSE;
|
| 52 |
// Note, pay attention to odd preg_replace-with-/e behaviour on slashes
|
| 53 |
$text = preg_replace("/^\n/", '', preg_replace('@</?(br|p)\s*/?>@', '', str_replace('\"', '"', $text)));
|
| 54 |
// Trim leading and trailing linebreaks
|
| 55 |
$text = trim($text, "\n");
|
| 56 |
// Escape newlines
|
| 57 |
$text = nl2br($text);
|
| 58 |
|
| 59 |
// PHP code in regular code
|
| 60 |
$text = preg_replace_callback('/<\?php.+?\?>/s', 'codefilter_process_php_inline', $text);
|
| 61 |
|
| 62 |
$text = '<code>'. codefilter_fix_spaces(str_replace(' ', ' ', $text)) .'</code>';
|
| 63 |
if ($multiline) $text = '<div class="codeblock">'. $text .'</div>';
|
| 64 |
// Remove newlines to avoid clashing with the linebreak filter
|
| 65 |
return str_replace("\n", '', $text);
|
| 66 |
}
|
| 67 |
|
| 68 |
function codefilter_fix_spaces($text) {
|
| 69 |
return preg_replace('@ (?! )@', ' ', $text);
|
| 70 |
}
|
| 71 |
|
| 72 |
/**
|
| 73 |
* Escape code blocks during input filter 'prepare'.
|
| 74 |
*
|
| 75 |
* @param $text
|
| 76 |
* The string to escape.
|
| 77 |
* @param $type
|
| 78 |
* The type of code block, either 'code' or 'php'.
|
| 79 |
* @return
|
| 80 |
* The escaped string.
|
| 81 |
*/
|
| 82 |
function codefilter_escape($text, $type = 'code') {
|
| 83 |
// Note, pay attention to odd preg_replace-with-/e behaviour on slashes
|
| 84 |
$text = check_plain(str_replace('\"', '"', $text));
|
| 85 |
|
| 86 |
// Protect newlines from line break converter
|
| 87 |
$text = str_replace(array("\r", "\n"), array('', ' '), $text);
|
| 88 |
|
| 89 |
// Add codefilter escape tags
|
| 90 |
$text = "[codefilter_$type]{$text}[/codefilter_$type]";
|
| 91 |
|
| 92 |
return $text;
|
| 93 |
}
|
| 94 |
|
| 95 |
/**
|
| 96 |
* Implement hook_filter_info().
|
| 97 |
*/
|
| 98 |
function codefilter_filter_info() {
|
| 99 |
$filters['codefilter'] = array(
|
| 100 |
'title' => t('Code filter'),
|
| 101 |
'description' => t('Allows users to post code verbatim using <code> and <?php ?> tags.'),
|
| 102 |
'prepare callback' => '_codefilter_prepare',
|
| 103 |
'process callback' => '_codefilter_process',
|
| 104 |
'tips callback' => '_codefilter_tips',
|
| 105 |
);
|
| 106 |
return $filters;
|
| 107 |
}
|
| 108 |
|
| 109 |
function _codefilter_prepare($text, $format) {
|
| 110 |
/* Note: we replace <code> </code>, <?php ?>, [?php ?], <% %>, and [% %]
|
| 111 |
to prevent other filters from acting on them. */
|
| 112 |
$text = preg_replace('@<code>(.+?)</code>@se', "codefilter_escape('$1', 'code')", $text);
|
| 113 |
$text = preg_replace('@[\[<](\?php|%)(.+?)(\?|%)[\]>]@se', "codefilter_escape('$2', 'php')", $text);
|
| 114 |
return $text;
|
| 115 |
}
|
| 116 |
|
| 117 |
function _codefilter_process($text, $format) {
|
| 118 |
$text = preg_replace('@\[codefilter_code\](.+?)\[/codefilter_code\]@se', "codefilter_process_code('$1')", $text);
|
| 119 |
$text = preg_replace('@\[codefilter_php\](.+?)\[/codefilter_php\]@se', "codefilter_process_php('$1')", $text);
|
| 120 |
return $text;
|
| 121 |
}
|
| 122 |
|
| 123 |
function _codefilter_tips($format, $long = FALSE) {
|
| 124 |
if ($long) {
|
| 125 |
return t('To post pieces of code, surround them with <code>...</code> tags. For PHP code, you can use <?php ... ?>, which will also colour it based on syntax.');
|
| 126 |
}
|
| 127 |
else {
|
| 128 |
return t('You may post code using <code>...</code> (generic) or <?php ... ?> (highlighted PHP) tags.');
|
| 129 |
}
|
| 130 |
}
|