上回说到实现了各种文件的上传,正要给attachment.php实现高亮显示源代码……(天外音——pia飞)。

先上Demo:

icon-icpc-smallsource code (ZOJ2705.cpp)

attachment-demo

在wordpress的template hierarchy里,对附件显示(attachment display)的处理,wp会按照

  1. MIME_type.php – 可以是任意的MIME,对于type/subtype,比如text/plain会按照:

    1. type.php (e.g. text.php)
    2. subtype.php (e.g. plain.php)
    3. type_subtype (e.g. text_plain.php)
  2. attachment.php
  3. single.php
  4. index.php

的顺序,调用第一个主题(theme)中可用的php文件。wp模认主题里没有attachment.php,我所用的主题mandigo里提供有attachment.php,对于图片,会显示缩略图(thumbnail),而对于其他文件,只显示一个图标(icon)和文件标题(title)。而我希望对于上传的源代码,可以直接显示代码内容,最好还是语法高亮的。因为很多时候我们只是想简单的看一下代码,这样也要下载太麻烦了,而且硬盘空间可能不够(……几k的空间都没有么……),提供预览也能排雷,下了个假档影响多不好啊。

为了达到这一目的,图方便,我直接对attachment.php文件进行了hack,首先加入了下面这一段代码:

<?php
$wud = wp_upload_dir();
$upload_path = $wud['basedir'];
$upload_url = $wud['baseurl'];
$path = wp_get_attachment_url($post->ID);
if (preg_match('#^' . $upload_url . '#', $path)) {
	$path = preg_replace('#^' . $upload_url . '#', $upload_path, $path);
	if (is_file($path)) {
		$map = array(
			'c'		=> 'cpp',
			'cpp'	=> 'cpp',
			'hs'	=> 'haskell',
			'pl'	=> 'perl',
			'php'	=> 'php',
			'txt'	=> 'plain',
			'xml'	=> 'xml',
			'html'	=> 'xml',
		);
		$ext = pathinfo($path, PATHINFO_EXTENSION);
		if (array_key_exists($ext, $map)) {
			$type = $map[$ext];
			$content = file_get_contents($path);
			// TODO
		}
	}
}
?>

$path是替换得到的附件路径,$ext是附件的扩展名,如果$ext不在硬编码的$map里,那么什么也不做。否则读取文件的内容并保存到$content中,通过扩展名得到代码的语言类型$type。接下来就是要把$content输出到页面里。

如果只是要显示代码的话,将TODO替换为

echo '<pre>' . $content . '</pre>';

就可以了,但这样的代码没有高亮,很难看。要实现语法高亮可以使用SyntaxHighlighter,它提供了code, c, cpp, php等许多shortcode。于是我尝试用do_shortcode得到语法高亮的代码:

echo do_shortcode('['.$type.']'.$content.'[/'.$type.']');

结果得到的就是原封不动的”[type]content[/type]“,shortcode完全没工作,百思不得其解。最后仔细看了syntaxhighlighter.php才发现

// A filter function that runs do_shortcode() but only with this plugin's shortcodes
function shortcode_hack( $content, $callback ) {
	// Backup current registered shortcodes and clear them all out
	// Register all of this plugin's shortcodes
	// Do the shortcodes (only this plugins's are registered)
	// Put the original shortcodes back
}

SyntaxHighlighter有大量的shortcode,容易和别的插件打架,所以把它们藏在了自己的“域”里,这可让我郁闷了。最后还是找到了变通之道,SyntaxHighlighter是通过

add_filter('the_content', array(&$this, 'parse_shortcodes'), 7);

工作的,于是我将do_shortcode版换成apply_filters版替换成

echo apply_filters('the_content', '['.$type.']'.$content.'[/'.$type.']');

赞,终于正常工作了。

6 Responses to “Hack attachment.php to Display and Hightlight code(text/*)”
  1. dd says:

    这样hack我觉得不是很和谐,想升级WP的时候就有点麻烦了,特别是自己搞了很多hacks的时候。妥贴的办法还是写成插件不要改动WP源代码的好。另一种办法是用git之类自己搞个branch,每次upstream升级了就merge一次。

  2. quark says:

    发现一个错字,”*再*wordpress的template hierarchy里”

  3. hsys says:

    5555, http://watashi.ws/blog/?attachment_id=550 是个假档….点进去以后里面写 Sorry, no posts matched your criteria …..

  4.  
Leave a Reply