升级WP旧模板,让它支持Widgets

正如大家所见,我使用的WordPress模板已经是很旧很旧的了,是以前在WordPress 1.5还是1.0系列的默认模板之上,简单修改而来的。没有选用三栏布局,因为我喜欢用稍微大一点的字体,三栏布局对我来说侧边栏东西太多,加上文章长了以后侧边栏的下面空白很大。不过旧模板自然也就没有Widgets:

No Sidebars Defined

You are seeing this message because the theme you are currently using isn’t widget-aware, meaning that it has no sidebars that you are able to change. For information on making your theme widget-aware, please follow these instructions.

刚开始我还能忍受,Sidebar上没有的东西俺自己手工加上,不过用上Simple Tags插件之后,感叹到了插件和Tags的强大,Relate Post很方便,可Relate Tags就是出不来,探查一番,原因应该就是我的模板不支持Widgets。所以忍不住了,模板可以不变样,但不能不升级,我就动手把它改成支持Widgets的吧。

刚才的提示中已经给出了修改指引的链接,首先把模板中的Sidebar改成ul形式的,Theme Editor -> Sidebar (sidebar.php),第一行的ul换成div即可:

<ul id="sidebar">
......中间的很多内容
</ul>

看了一下,对外观没有太大影响,css应该是用id来引用的,不过还是需要调整一点css:

/* 启用Widgets后Sidebar样式有些变化,在这里修正 */
#sidebar {list-style: none;}
#sidebar li ul li:before {
    content: "\00BB \0020";
}
#sidebar li ul li {
    margin-bottom: 5px;
}

然后还是修改Sidebar模板文件,加入是否有动态Sidebar的检查、如果有就调入的PHP代码:

<ul id="sidebar">
<?php if ( !function_exists('dynamic_sidebar')
    || !dynamic_sidebar() ) : ?>
......中间的很多内容
<?php endif; ?>
</ul>

代码一共就3行,前面加2行,后面加一行,就是个简单的判断而已。别着急,现在还没有完成,还有最后一步。

在模板目录下,比如我的就是wp-content/themes/fwolfs-blog这个目录,创建一个新文件functions.php,内容就4行:

<?php
if ( function_exists('register_sidebar') )
    register_sidebar();
?>

好了,现在再刷新Design -> Widgets页面,就有内容了,我的旧模板现在也支持Widgets了。

同样的,Design -> Theme Editor页面中也会多一项可编辑内容:

Theme Functions (functions.php)

PS1: 如果要添加多个Sidebar,需要模板的支持,也就是模板中制定需要几个Sidebar,在Design中就能管理几个(register_sidebars(n),n就是Sidebar数量)。

PS2: 如果想在Widgets的Text里面内嵌php代码,比如设定只有首页才显示BlogRoll,那么需要安装PHP Code Widget插件,并使用PHP Code代码块。直接在原来的Text中写php代码的话,会原封不动的被当成php代码输出,昏死。

PS3: 一切都折腾好了,Relate Tags功能还是得手工添加php代码块到Widgets中:

<?php
if (is_tag()) {
    st_related_tags();
    st_remove_related_tags();
}
?>

Gregarius编辑feed时中文乱码的解决

Gregarius编辑feeds的时候,中文总是乱码(版本r1787),其实解决方法很简单的:

找到admin/channels.php这个文件,找到第900行,修改为:

//$title = htmlentities($title,ENT_QUOTES);
$title = htmlspecialchars($title, ENT_QUOTES);

这个是feed标题乱码的修正,再向下翻到Description部分,大概在988行左右,修改为:

// Description
//$descr = trim(htmlentities(strip_tags($descr), ENT_QUOTES));
$descr = trim(htmlspecialchars(strip_tags($descr), ENT_QUOTES));

这样就ok了。

原因很简单,htmlentities这个函数在转义到html标记的时候,会吧中文字符中一些字节也进行了转义,形成了乱码,而htmlspecialchars这个函数只转义特定的5个字符,不会存在这种情况。

hack之后,单引号和双引号都能输入了,但是反斜杠\仍然是不能输入的,应该是在输入处理的时候过滤掉了,或者进行了其他的转换,不过一般也用不到,就不改了。西文环境用户的处理习惯就是和我们不大一样啊。

参考

adodb5连接sybase的一个错误

这个错误比较蹊跷,所以拿出来说一说。环境:php 5.2.3, adodb 5.04, ubuntu 7.10 Gutsy.

前两天为了使用adodb和sqlite3,就把adodb升级成了只支持php5的adodb5(5.0.4),过两天发现另外一个使用sybase的程序不正常了,运行时不工作直接退出,没有任何错误信息,通过添加die('hi');的方式定位到错误发生在$db = &ADONewConnection('sybase');这一行。

adodb对sybase的支持一直不强,不过还没有到不工作的地步,但这个错误没有任何提示,实在是不好找,无奈之下用ZendStudio来跟踪一下,弄了一个最简单的小程序,当然,它是不工作没错误直接结束:

#! /usr/bin/php
<?php
require_once('adodb/adodb.inc.php');
$db = &ADONewConnection('sybase');
print_r($db);
$db->Connect('server3', 'sa', '', 'dbname');
$rs = $db->Execute('select 1');
print_r($rs);
?>

ZendStudio下Debug就报错了:

Compile Error: /home/fwolf/dev/include/adodb5/drivers/adodb-sybase.inc.php line 271 - Cannot make static method ADOConnection::UnixDate() non static in class ADODB_sybase

拿着错误信息上网一查,原来是在adodb-sybase.inc.php文件中,180行开始的地方定义了两个函数UnixDate()和UnixTimeStamp()(提示错误在271行,271行是类ADODB_sybase的定义结束位置,所以这个错误是在代码编译是产生的,而不是运行时),而这两个函数在adodb.inc.php中是作为static函数定义的(2481、2505行),php5不允许覆盖static函数(这个在oop中好像是叫重载,太长时间没摸书本,记不清了),所以产生编译错误,程序中止。在adodb.inc.php的4089行,包含adodb-sybase.inc.php的时候又加上了@符号:

@include_once($file);

所以错误信息被屏蔽,不显示了。ZendStudio由于Debug的原因,可能所有的错误都捕捉到了,忽略@。去掉@之后,直接运行就也可以报错了。

问题弄清楚了,如何改呢,我想大概有两种方式:

  1. 修改adodb.inc.php,不将UnixDate()函数定义为static。
  2. 修改adodb-sybase.inc.php,取消两个函数的重复定义。

相比之下,觉得第一种方法更好一些,第二种方法可能会引发其它的错误。所以改下来一共是去掉四个static:

Line 2481: ADOConnection::UnixDate()
Line 2505: ADOConnection::UnixTimeStamp()
Line 3204: ADORecordSet::UnixDate()
Line 3215: ADORecordSet::UnixTimeStamp()

简单测试了一下,基本工作正常。

参考

PS: ZendStudio使用单独的一套php.ini,放在/path/to/ZendStudio-5.5.0/bin/php5目录下,我总是忘记,每次include path不对劲的时候都要找半天。

WordPress升级到2.3.1

以前用的是2.2版本,现在最新版是2.3.1,我看重的主要改进是添加了tag的支持,就升过来了。

升级过程非常简单,下载包,解压,覆盖,然后执行一下wp-admin/upgrade.php就可以了。

忘记了WordPress从哪个版本开始支持Widgets功能的,可我用的这个模板是从1.5版本的默认主题,一路改过来的,虽然没有动大手术,琐碎的修改还是有一些的。对于我这个懒人来说,重新套模板然后更改显然是不划算的,虽然后来学聪明了,有些修改作成了插件,剩下的好像也不少,所以尽可能的在旧模板的基础上更改。

Widgets好像就是个可高度自定义的sidebar,在我现在的模板中,打开Widgets页面总是提示“No Sidebars Defined”,不支持,好在我的要求也不高,咱自己动手,丰衣足食。

WordPress的wp-includes/widgets.php这个文件,是Widgets的主要实现代码,所以修改主要是参照了这个文件的内容。好了,开始编辑现在这个旧模板的sidebar文件。

首先,要把存档archive改成下拉列表框,月份多了实在看着不舒服,widgets.php中有这么一段:

function wp_widget_archives($args) {
    extract($args);
    $options = get_option('widget_archives');
    $c = $options['count'] ? '1' : '0';
    $d = $options['dropdown'] ? '1' : '0';
    $title = empty($options['title']) ? __('Archives') : $options['title'];

    echo $before_widget;
    echo $before_title . $title . $after_title;

    if($d) {
?>
        <select name="archive-dropdown" onchange='document.location.href=this.options[this.selectedIndex].value;'> <option value=""><?php echo attribute_escape(__('Select Month')); ?></option> <?php wp_get_archives("type=monthly&format=option&show_post_count=$c"); ?> </select>

可以看出,内置的wp_get_archives函数的参数,原来只有type=monthly,现在多了format=optionshow_post_count=$c,前者应该代表是否下拉列表框形式显示,值的定义为$options['dropdown'];后者是是否显示本月文章计数,值的定义为$options['count'],并且都是用1代表真,0代表假,所以修改就简单了,把原来的:

<?php wp_get_archives('type=monthly'); ?>

更改为:

        <select name="archive-dropdown" onchange='document.location.href=this.options[this.selectedIndex].value;'> <option value=""><?php echo attribute_escape(__('Select Month')); ?></option> <?php wp_get_archives("type=monthly&format=option&show_post_count=1"); ?> </select>

就行了。

然后,把archive月份存档和category分类列表的位置互换,分类列表放在上面,直接调整代码顺序即可,同时给分类列表也加上分类计数的显示:

            <li><h2>Categories</h2>
                <ul>
                <?php wp_list_cats('sort_column=name&show_count=1'); ?>
                </ul>
            </li>

最后,添加Tag Cloud,没有这个升级就白作了,参照widgets.php中的:

function wp_widget_tag_cloud($args) {
    extract($args);
    $options = get_option('widget_tag_cloud');
    $title = empty($options['title']) ? __('Tags') : $options['title'];

    echo $before_widget;
    echo $before_title . $title . $after_title;
    wp_tag_cloud();
    echo $after_widget;
}

没什么太复杂的,直接调用wp_tag_cloud()函数,连参数都没有,最终代码为:

            <li><h2>Tags Cloud</h2>
                <ul>
                <?php wp_tag_cloud(); ?>
                </ul>
            </li>

这样就大功告成了,虽然模板不支持Widgets,侧边栏倒也符合我的基本使用需要了。

参考