View source
<?php
require_once drupal_get_path('module', 'geshifilter') . '/geshifilter.inc';
function _geshifilter_parse_attributes($attributes, $format) {
$lang = NULL;
$line_numbering = NULL;
$linenumbers_start = NULL;
$title = NULL;
list($generic_code_tags, $language_tags, $tag_to_lang) = _geshifilter_get_tags($format);
$language_attributes = _geshifilter_whitespace_explode(GESHIFILTER_ATTRIBUTES_LANGUAGE);
$attributes_preg_string = implode('|', array_merge($language_attributes, array(
GESHIFILTER_ATTRIBUTE_LINE_NUMBERING,
GESHIFILTER_ATTRIBUTE_LINE_NUMBERING_START,
GESHIFILTER_ATTRIBUTE_FANCY_N,
GESHIFILTER_ATTRIBUTE_TITLE,
)));
$enabled_languages = _geshifilter_get_enabled_languages();
preg_match_all('#(' . $attributes_preg_string . ')="?([^"]*)"?#', $attributes, $attribute_matches);
foreach ($attribute_matches[1] as $a_key => $att_name) {
$att_value = $attribute_matches[2][$a_key];
$class_to_lang = str_replace('language-', '', $att_value);
if (in_array($att_name, $language_attributes)) {
if (in_array($att_value, $language_tags)) {
$att_value = $tag_to_lang[$att_value];
}
if (array_key_exists($att_value, $enabled_languages)) {
$lang = $att_value;
}
elseif ($att_name == 'class' && array_key_exists($class_to_lang, $enabled_languages)) {
$lang = $class_to_lang;
}
}
elseif ($att_name == GESHIFILTER_ATTRIBUTE_LINE_NUMBERING) {
switch (strtolower($att_value)) {
case "off":
$line_numbering = 0;
break;
case "normal":
$line_numbering = 1;
break;
case "fancy":
$line_numbering = 5;
break;
}
}
elseif ($att_name == GESHIFILTER_ATTRIBUTE_FANCY_N) {
$att_value = (int) $att_value;
if ($att_value >= 2) {
$line_numbering = $att_value;
}
}
elseif ($att_name == GESHIFILTER_ATTRIBUTE_LINE_NUMBERING_START) {
if ($line_numbering < 1) {
$line_numbering = 1;
}
$linenumbers_start = (int) $att_value;
}
elseif ($att_name == GESHIFILTER_ATTRIBUTE_TITLE) {
$title = $att_value;
}
}
return array(
'language' => $lang,
'line_numbering' => $line_numbering,
'linenumbers_start' => $linenumbers_start,
'title' => $title,
);
}
function _geshifilter_prepare($format, $text) {
list($generic_code_tags, $language_tags, $tag_to_lang) = _geshifilter_get_tags($format);
$tags = array_merge($generic_code_tags, $language_tags);
$tags = preg_replace('#(\\+|\\#)#', '\\\\$1', $tags);
$tags_string = implode('|', $tags);
$tag_styles = array_filter(_geshifilter_tag_styles($format));
if (in_array(GESHIFILTER_BRACKETS_ANGLE, $tag_styles)) {
$pattern = '#(<)(' . $tags_string . ')((\\s+[^>]*)*)(>)(.*?)(</\\2\\s*>|$)#s';
$text = preg_replace_callback($pattern, function ($match) use ($format) {
return _geshifilter_prepare_callback($match, $format);
}, $text);
}
if (in_array(GESHIFILTER_BRACKETS_SQUARE, $tag_styles)) {
$pattern = '#((?<!\\[)\\[)(' . $tags_string . ')((\\s+[^\\]]*)*)(\\])(.*?)((?<!\\[)\\[/\\2\\s*\\]|$)#s';
$text = preg_replace_callback($pattern, function ($match) use ($format) {
return _geshifilter_prepare_callback($match, $format);
}, $text);
}
if (in_array(GESHIFILTER_BRACKETS_DOUBLESQUARE, $tag_styles)) {
$pattern = '#(\\[\\[)(' . $tags_string . ')((\\s+[^\\]]*)*)(\\]\\])(.*?)(\\[\\[/\\2\\s*\\]\\]|$)#s';
$text = preg_replace_callback($pattern, function ($match) use ($format) {
return _geshifilter_prepare_callback($match, $format);
}, $text);
}
if (in_array(GESHIFILTER_BRACKETS_PHPBLOCK, $tag_styles)) {
$pattern = '#[\\[<](\\?php|\\?PHP|%)(.+?)((\\?|%)[\\]>]|$)#s';
$text = preg_replace_callback($pattern, function ($match) use ($format) {
return _geshifilter_prepare_php_callback($match, $format);
}, $text);
}
return $text;
}
function _geshifilter_prepare_callback($match, $format) {
$tag_name = $match[2];
$tag_attributes = $match[3];
$content = $match[6];
if (geshifilter_decode_entities($format)) {
$content = html_entity_decode($content, ENT_QUOTES);
}
$lang = variable_get('geshifilter_default_highlighting', GESHIFILTER_DEFAULT_PLAINTEXT);
if ($lang == GESHIFILTER_DEFAULT_DONOTHING) {
$enabled_languages = _geshifilter_get_enabled_languages();
list($generic_code_tags, $language_tags, $tag_to_lang) = _geshifilter_get_tags($format);
if (isset($tag_to_lang[$tag_name]) && isset($enabled_languages[$tag_to_lang[$tag_name]])) {
$lang = $tag_to_lang[$tag_name];
}
else {
$settings = _geshifilter_parse_attributes($tag_attributes, $format);
if ($settings['language'] && isset($enabled_languages[$settings['language']])) {
$lang = $settings['language'];
}
}
if ($lang == GESHIFILTER_DEFAULT_DONOTHING) {
return $match[0];
}
}
return '[geshifilter-' . $tag_name . $tag_attributes . ']' . str_replace(array(
"\r",
"\n",
), array(
'',
' ',
), check_plain($content)) . '[/geshifilter-' . $tag_name . ']';
}
function _geshifilter_prepare_php_callback($match, $format) {
if (geshifilter_decode_entities($format)) {
$match[2] = html_entity_decode($match[2], ENT_QUOTES);
}
return '[geshifilter-questionmarkphp]' . str_replace(array(
"\r",
"\n",
), array(
'',
' ',
), check_plain($match[2])) . '[/geshifilter-questionmarkphp]';
}
function _geshifilter_process($format, $text) {
$geshi_library = libraries_load('geshi');
if (!$geshi_library['loaded']) {
drupal_set_message($geshi_library['error message'], 'error');
return $text;
}
list($generic_code_tags, $language_tags, $tag_to_lang) = _geshifilter_get_tags($format);
if (in_array(GESHIFILTER_BRACKETS_PHPBLOCK, array_filter(_geshifilter_tag_styles($format)))) {
$language_tags[] = 'questionmarkphp';
$tag_to_lang['questionmarkphp'] = 'php';
}
$tags = array_merge($generic_code_tags, $language_tags);
$tags = preg_replace('#(\\+|\\#)#', '\\\\$1', $tags);
$tags_string = implode('|', $tags);
$pattern = '#\\[geshifilter-(' . $tags_string . ')([^\\]]*)\\](.*?)(\\[/geshifilter-\\1\\])#s';
$text = preg_replace_callback($pattern, function ($match) use ($format) {
return _geshifilter_replace_callback($match, $format);
}, $text);
return $text;
}
function _geshifilter_replace_callback($match, $format) {
$complete_match = $match[0];
$tag_name = $match[1];
$tag_attributes = $match[2];
$source_code = $match[3];
$source_code = decode_entities($source_code);
$lang = variable_get('geshifilter_default_highlighting', GESHIFILTER_DEFAULT_PLAINTEXT);
$line_numbering = variable_get('geshifilter_default_line_numbering', GESHIFILTER_LINE_NUMBERS_DEFAULT_NONE);
$linenumbers_start = 1;
$title = NULL;
list($generic_code_tags, $language_tags, $tag_to_lang) = _geshifilter_get_tags($format);
if (in_array(GESHIFILTER_BRACKETS_PHPBLOCK, array_filter(_geshifilter_tag_styles($format)))) {
$language_tags[] = 'questionmarkphp';
$tag_to_lang['questionmarkphp'] = 'php';
}
if (isset($tag_to_lang[$tag_name])) {
$lang = $tag_to_lang[$tag_name];
}
$settings = _geshifilter_parse_attributes($tag_attributes, $format);
if (isset($settings['language'])) {
$lang = $settings['language'];
}
if (isset($settings['line_numbering'])) {
$line_numbering = $settings['line_numbering'];
}
if (isset($settings['linenumbers_start'])) {
$linenumbers_start = $settings['linenumbers_start'];
}
if (isset($settings['title'])) {
$title = $settings['title'];
}
if ($lang == GESHIFILTER_DEFAULT_DONOTHING) {
return $complete_match;
}
if ($lang == GESHIFILTER_DEFAULT_PLAINTEXT) {
$lang = 'text';
}
$inline_mode = strpos($source_code, "\n") === FALSE;
return geshifilter_process_sourcecode($source_code, $lang, $line_numbering, $linenumbers_start, $inline_mode, $title);
}
function _geshifilter_override_geshi_defaults(&$geshi, $langcode) {
$geshi
->set_line_style('font-family: monospace; font-weight: normal;', 'font-family: monospace; font-weight: bold; font-style: italic;');
$geshi
->set_code_style('font-family: monospace; font-weight: normal; font-style: normal');
$geshi
->set_overall_class('geshifilter-' . $langcode);
$geshi
->enable_keyword_links(variable_get('geshifilter_enable_keyword_urls', TRUE));
}
function geshifilter_process_sourcecode($source_code, $lang, $line_numbering = 0, $linenumbers_start = 1, $inline_mode = FALSE, $title = NULL) {
if ($lang == 'php' && variable_get('geshifilter_use_highlight_string_for_php', FALSE)) {
return geshifilter_highlight_string_process($source_code, $inline_mode);
}
else {
return geshifilter_geshi_process($source_code, $lang, $line_numbering, $linenumbers_start, $inline_mode, $title);
}
}
function geshifilter_geshi_process($source_code, $lang, $line_numbering = 0, $linenumbers_start = 1, $inline_mode = FALSE, $title = NULL) {
$geshi_library = libraries_load('geshi');
if (!$geshi_library['loaded']) {
drupal_set_message($geshi_library['error message'], 'error');
return $source_code;
}
$cache_id = "geshifilter:{$lang}:{$line_numbering}:{$linenumbers_start}:{$inline_mode}" . md5($title . $source_code);
if ($cached = cache_get($cache_id, 'cache_filter')) {
return $cached->data;
}
$source_code = trim($source_code, "\n\r");
$geshi = _geshifilter_geshi_factory($source_code, $lang);
$ccs_mode = variable_get('geshifilter_css_mode', GESHIFILTER_CSS_INLINE);
if ($ccs_mode == GESHIFILTER_CSS_CLASSES_AUTOMATIC || $ccs_mode == GESHIFILTER_CSS_CLASSES_ONLY) {
$geshi
->enable_classes(TRUE);
}
_geshifilter_override_geshi_defaults($geshi, $lang);
if ($inline_mode) {
$geshi
->set_header_type(GESHI_HEADER_NONE);
$overall_class = 'geshifilter-' . $lang;
$code_class = "{$lang} {$overall_class}";
$source_code = '<span class="geshifilter"' . (isset($title) ? ' title="' . check_plain($title) . '"' : '') . '><code class="' . $code_class . '">' . $geshi
->parse_code() . '</code></span>';
}
else {
$geshi
->set_header_type((int) variable_get('geshifilter_code_container', GESHI_HEADER_PRE));
if ($line_numbering == 1) {
$geshi
->enable_line_numbers(GESHI_NORMAL_LINE_NUMBERS);
$geshi
->start_line_numbers_at($linenumbers_start);
}
elseif ($line_numbering >= 2) {
$geshi
->enable_line_numbers(GESHI_FANCY_LINE_NUMBERS, $line_numbering);
$geshi
->start_line_numbers_at($linenumbers_start);
}
if (isset($title)) {
$source_code = '<div class="geshifilter-title">' . check_plain($title) . '</div>';
}
else {
$source_code = '';
}
$source_code .= '<div class="geshifilter">' . $geshi
->parse_code() . '</div>';
}
cache_set($cache_id, $source_code, 'cache_filter', time() + 60 * 60 * 24);
return $source_code;
}
function geshifilter_highlight_string_process($source_code, $inline_mode) {
$text = trim($source_code);
if (substr($text, 0, 5) != '<?php') {
$source_code = '<?php' . $source_code;
}
if (substr($text, -2) != '?>') {
$source_code = $source_code . '?>';
}
$container = $inline_mode ? 'span' : 'div';
$text = '<' . $container . ' class="codeblock geshifilter">' . highlight_string($source_code, TRUE) . '</' . $container . '>';
$text = str_replace("\n", '', $text);
return $text;
}