玩转Drupal主题

玩转Drupal主题(2):在mission statement中添加PHP脚本

Cartson 做了几个 Drupal China 的 brochure,非常的漂亮,所以想循环的在 Drupal China 的首页逐一显示,通常这个可以通过 javascript 来实现,但是为了网站的整体考虑,打算用 PHP 来实现,所以就写了一段最简单的显示代码:

$img = array();
$img[] = '';
$img[] = '';
$max = count($img);
$count = rand(0,$max);
print $img[$count];
?>

但是却遇到了一个问题,Drupal 的 Mission Statement 中自动滤掉了PHP代码,导致无法正常显示,但是好在 Drupal 异常的灵活,可以很方便的解决这个问题。下面是一个简单的解决方案。嗯,其实就一句话:把mission statement的内容放在一个新创建的 mission.tpl.php 文件中,然后将 page.tpl.php 中的 print $mission 修改为 include 'mission.tpl.php' 即可。这样做其实也有一个好处,可以更方便的编辑 Mission Statement,因为它现在有一个单独的模板文件控制,而无需再在 管理->设置 中的文本框中书写 Mission Statement 。效果见Drupal China的首页。

不过发现了一个小问题:用 rand() 函数生成的 random display 效果其实并不是很好,可能是因为只有两个brochure的缘故,每个的显示几率都是 50% ,连续两次显示同一个brochure的几率是 25% 还是挺大的,如果brochure多一些,那么每次刷新页面得到的图片重复的几率就小了。

Blog分类: 

玩转Drupal主题(1):解放 $links

在Drupal的主题中,控制一系列meta data显示的变量是$links,所谓的meta data也就是每篇post上面或是下面的“» read more | kzeng's blog | add new comment | 3 reads”这一行数据,有的时候,我们会希望把这个$links中的数据分开显示,譬如把“read more”放在一个比较显眼的地方,但是由于PHPTemplate并没有帮我们分别命名这些变量,所以无法直接来任意摆放这些它们。下面就介绍一个解放这些变量的方法,让使用者可以灵活的在主题中放置这些变量。

第一种方法是一种不彻底的解放,利用preg_match把$links中的每个一个数据都加上class,然后通过class来控制显示与位置(譬如用display:none;来隐去不必要的部分,用position来控制显示位置等等,但是这并不是彻底的解决方案。

第二种是修改Drupal的核心文件或是PHPTemplate Engine,一般最好避开这种方式,不然等到升级Drupal的时候就会比较麻烦,特别是如果隔的时间久了,你忘记了曾经做过哪些改动,升级时会出现意外,譬如我在升级到4.7的时候因为忘记了自己曾经patch过数据库中几个数据表的primary index的设置,导致升级时出现失败,还要在手动更改过来,所以一般来说修改显示最好的办法是修改主题文件,这样可以为将来省去不少麻烦,并且PHPTemplate的灵活性也使我们可以方便的修改Drupal的显示。

下面要介绍的这种方式是受到Drupal Handbook中关于提取“read more”的方法的启发,并主要来源于Nick的相关讨论。其最核心的部分是利用PHP中的preg_match来分离各个显示变量。在你的主题文件夹下新建一个Template.php文件,如果已经有这个文件则只需将下面的函数加在原文件的结尾。

Template.php 中新定义个显示变量的函数如下:
function _phptemplate_variables($hook, $vars) {
switch ($hook) {
case "node":
foreach ($vars['node']->links as $link) {
/*准备分离$links*/
preg_match("/]*).*?>(.*?)<\/a>/i",$link, $matches);
/*用preg_match替换,注意更改上一行的那个全角的?,因为我的codefilter错误分行才把它改成全角的,应该是半角的*/
$textparts = explode(" ", $matches[2]);
$urlparts = explode("/", $matches[1]);
$linkurl = $matches[1];
$default_title = $matches[2];
/*分离定义新的变量*/
switch (true) {
case in_array("blog", $urlparts):
$linktitle = $vars['node']->name."'s Blog";
$bloglink =
''.$linktitle.'';
$feedlink =
'
.'" class="feedlink">RSS
';
$vars['bloglink'] = $bloglink ." | ".$feedlink;
break;
case in_array("forward", $urlparts):
$stylecodename = "emaillink";
$linktitle = "email page";
$vars['emaillink'] =
'
.$linkurl.'" class="'
.$stylecodename.'">'
.$linktitle.'
';
break;
case in_array("comment", $textparts):
case in_array("comments", $textparts):
$stylecodename = "commentlink";
$vars['commentlink'] =
'
.$linkurl.'" class="'
.$stylecodename.'">'
.$default_title.'
';
break;
case in_array("read", $textparts):
$stylecodename = "readmorelink";
$vars['readmorelink'] = ''.$default_title.'';
break;
case in_array("printer", $textparts):
$vars['printlink'] =
'Print Page';
break;
default:
$vars['otherlinks'] .= ''.$default_title.'';
}
}
}
break;
}
return $vars;
}
?>

这样你就有 $readmorelink, $commentlink, $printlink 等多个变量可以使用了,在node.tpl.php中只需

即可。

注意:我在没有汉化的Drupal中使用这种方式成功,在汉化过的Drupal中,preg_match可能找到是汉语的string(我猜测),或者应该加上t()吧,呵呵,有空再研究一下:)

Blog分类: