Drupal中,主题是可以继承的,或者说是扩展。例如,要创建一个新的名为custom的主题,该主题与名为default的主题只有某些细小的差别。这个时候,不需要复制一份default到custom,可以在custom声明该主题继承自default就可以了。

主题的继承关系在info文件中说明。首先,default主题的info文件不需要修改:

name = Default Theme

custom主题的info文件需要特别地声明base theme属性:

name = Custom Theme
base theme = default

Drupal内部是如何解析这种继承关系的呢?解析的过程发生在system_list()函数中:

$result = db_query("SELECT * FROM {system} WHERE type = 'theme' OR (type = 'module' AND status = 1) ORDER BY weight ASC, name ASC");
foreach ($result as $record) {
$record->info = unserialize($record->info); // Build a list of themes.
if ($record->type == 'theme') {
$lists['theme'][$record->name] = $record;
}
} foreach ($lists['theme'] as $key => $theme) {
if (!empty($theme->info['base theme'])) {
// Make a list of the theme's base themes.
require_once DRUPAL_ROOT . '/includes/theme.inc';
$lists['theme'][$key]->base_themes = drupal_find_base_themes($lists['theme'], $key);
// Don't proceed if there was a problem with the root base theme.
if (!current($lists['theme'][$key]->base_themes)) {
continue;
} // Determine the root base theme.
$base_key = key($lists['theme'][$key]->base_themes);
// Add to the list of sub-themes for each of the theme's base themes.
foreach (array_keys($lists['theme'][$key]->base_themes) as $base_theme) {
$lists['theme'][$base_theme]->sub_themes[$key] = $lists['theme'][$key]->info['name'];
} // Add the base theme's theme engine info.
$lists['theme'][$key]->info['engine'] = isset($lists['theme'][$base_key]->info['engine']) ? $lists['theme'][$base_key]->info['engine'] : 'theme';
}
else {
// A plain theme is its own engine.
$base_key = $key;
if (!isset($lists['theme'][$key]->info['engine'])) {
$lists['theme'][$key]->info['engine'] = 'theme';
}
}
// Set the theme engine prefix.
$lists['theme'][$key]->prefix = ($lists['theme'][$key]->info['engine'] == 'theme') ? $base_key : $lists['theme'][$key]->info['engine'];
}

首先,从系统表system中读取出主题信息,记录到$lists['theme']数组:

$result = db_query("SELECT * FROM {system} WHERE type = 'theme' OR (type = 'module' AND status = 1) ORDER BY weight ASC, name ASC");
foreach ($result as $record) {
$record->info = unserialize($record->info); // Build a list of themes.
if ($record->type == 'theme') {
$lists['theme'][$record->name] = $record;
}
}

然后,遍历$lists['theme']数组。如果声明了base theme属性,则通过drupal_find_base_themes()函数获取父主题:

require_once DRUPAL_ROOT . '/includes/theme.inc';
$lists['theme'][$key]->base_themes = drupal_find_base_themes($lists['theme'], $key);
// Don't proceed if there was a problem with the root base theme.
if (!current($lists['theme'][$key]->base_themes)) {
continue;
}

drupal_find_base_theme()返回的是一个数组。在当前例子中,返回的数组是array('default' => 'Default Theme')。主题也是可以多重继承的,假设default主题再继承自top主题,drupal_find_base_theme()返回的数组则是array('top' => 'Top Theme', 'default' => 'Default Theme')。base_themes数组是有序的,最顶层的主题在最前面,然后依次下来。

function drupal_find_base_themes($themes, $key, $used_keys = array()) {
$base_key = $themes[$key]->info['base theme'];
// Does the base theme exist?
if (!isset($themes[$base_key])) {
return array($base_key => NULL);
} $current_base_theme = array($base_key => $themes[$base_key]->info['name']); // Is the base theme itself a child of another theme?
if (isset($themes[$base_key]->info['base theme'])) {
// Do we already know the base themes of this theme?
if (isset($themes[$base_key]->base_themes)) {
return $themes[$base_key]->base_themes + $current_base_theme;
}
// Prevent loops.
if (!empty($used_keys[$base_key])) {
return array($base_key => NULL);
}
$used_keys[$base_key] = TRUE;
return drupal_find_base_themes($themes, $base_key, $used_keys) + $current_base_theme;
}
// If we get here, then this is our parent theme.
return $current_base_theme;
}

接下来得到root base theme,base_themes数组中的第一个key,上例中是top。

// Determine the root base theme.
$base_key = key($lists['theme'][$key]->base_themes);

再后,更新每个base theme的sub_themes属性。sub_themes是无序的,取决于于主题加载顺序。

// Add to the list of sub-themes for each of the theme's base themes.
foreach (array_keys($lists['theme'][$key]->base_themes) as $base_theme) {
$lists['theme'][$base_theme]->sub_themes[$key] = $lists['theme'][$key]->info['name'];
}

最后,设置引擎前缀engine prefix,就是主题解析函数都是以什么开头的。注意变量$base_key,当有继承存在,$base_key代表root base theme,否则就是current theme。当前主题有声明engine属性时,prefix就是engine属性,否则就是$base_key。

if (!empty($theme->info['base theme'])) {
// Determine the root base theme.
$base_key = key($lists['theme'][$key]->base_themes); // Add the base theme's theme engine info.
$lists['theme'][$key]->info['engine'] = isset($lists['theme'][$base_key]->info['engine']) ? $lists['theme'][$base_key]->info['engine'] : 'theme';
}
else {
// A plain theme is its own engine.
$base_key = $key;
if (!isset($lists['theme'][$key]->info['engine'])) {
$lists['theme'][$key]->info['engine'] = 'theme';
}
} // Set the theme engine prefix.
$lists['theme'][$key]->prefix = ($lists['theme'][$key]->info['engine'] == 'theme') ? $base_key : $lists['theme'][$key]->info['engine'];

Drupal如何解析主题继承关系?的更多相关文章

  1. Jaxb 解析 带有继承关系的bean与xml

    具体方法: 1. 在jaxb的setClasstobebounds中,只需要子类的class,无需父类. 2. 父类的前面加如下声明: @XmlAccessorType(XmlAccessType.F ...

  2. Java类继承关系中的初始化顺序

    Java类初始化的顺序经常让人犯迷糊,现在本文尝试着从JVM的角度,对Java非继承和继承关系中类的初始化顺序进行试验,尝试给出JVM角度的解释. 非继承关系中的初始化顺序 对于非继承关系,主类Ini ...

  3. HandlerMethodReturnValueHandler SpringMVC 参数解析 继承关系以及各解析器解析类型

    I HandlerMethodReturnValueHandler (org.springframework.web.method.support) AbstractMessageConverterM ...

  4. HandlerMethodArgumentResolver SpringMVC 参数解析 继承关系以及各解析器解析类型

    HandlerMethodArgumentResolver SpringMVC 参数解析 继承关系以及各解析器解析类型 I HandlerMethodArgumentResolver (org.spr ...

  5. 深入Spring Boot:ClassLoader的继承关系和影响

    前言 对spring boot本身启动原理的分析, Spring boot里的ClassLoader继承关系 可以运行下面提供的demo,分别在不同的场景下运行,可以知道不同场景下的Spring bo ...

  6. Style在Android中的继承关系

    Style在Android中的继承关系 Android的Styles(样式)和Themes(主题)非常类似Web开发里的CSS,方便开发者将页面内容和布局呈现分开.Style和Theme在Androi ...

  7. drf:restful概念,类继承关系,drf请求封装,drf请求流程,版本控制组件,认证组件(token),权限组件

    1.restful规范 resfful规范的概念最重要: 是一套规范,规则,用于程序之间进行数据交换的约定. 他规定了一些协议,对我们感受最直接的就是,以前写增删改查的时候需要些四个视图寒素,rest ...

  8. C++类继承关系视图的自动生成

    原创文章,转载请注明出处. 工欲善其事,必先利其器.阅读大型C++工程项目,如果有一些自动化的分析工具支持,学习的效率将大大提升.在前文中介绍了Source Insight在Linux下的安装方法,本 ...

  9. Hibernate注解方式配置-继承关系

    在JPA中,实体继承关系的映射策略共有三种:单表继承策略(table per class).Joined策略(table per subclass)和Table_PER_Class策略. 1.单表继承 ...

随机推荐

  1. noip 1999 回文数

    题目描述 若一个数(首位不为零)从左向右读与从右向左读都一样,我们就将其称之为回文数. 例如:给定一个10进制数56,将56加65(即把56从右向左读),得到121是一个回文数. 又如:对于10进制数 ...

  2. Problem H: 零起点学算法109——单数变复数

    #include <stdio.h> #include<string.h> int main(void) { int n; ]; scanf("%d",&a ...

  3. 修改ORACLE实例名

    修改数据库的SID  举例说明,我的数据库的SID叫testdb,现在要改成oral.更改ORACLE数据库的sid,涉及到的用东西比较多,但是大概来说就以下六步. 1.停止所有的Oracle服务.  ...

  4. 怎么提高DB的效率

    主要从4方面,提高db的效率: 1,建立索引:(巴东) 2,多线程: 3,锁的范围(表级,行级...) 4,内存数据库

  5. svn安装和配置

    安装svn 参考http://blog.csdn.net/dl425134845/article/details/41978541 系统版本 uname -a # 查看内核/操作系统/CPU信息 he ...

  6. 掌握Linux编程的10个步骤

    Linux 编程经典书籍推荐 Denis 2008年10月17日 浏览:84168 成为一名精通 Linux 程序设计的高级程序员一直是不少朋友孜孜以求的目标.根据中华英才网统计数据,北京地区 Lin ...

  7. linux UART串口驱动开发文档

    转:http://www.360doc.com/content/10/0417/18/829197_23519037.shtml linux UART串口驱动开发文档时间:2010-01-09 14: ...

  8. 利用谷歌API生成二维码

    http://chart.apis.google.com/chart?cht=qr&chs=104x104&chld=L|0&chl=http://www.cnblogs.co ...

  9. 推送代码分支时出现:fatal: 'origin' does not appear to be a git repository

    关于ubuntu进行提交本地分支到远程库出现问题: 解决方案: 执行如下命令: git remote add origin git@github.com:yourusername/test.git y ...

  10. 基于 Scrapy-redis 的分布式爬虫详细设计

    基于 Scrapy-redis 的分布式爬虫设计   目录 前言 安装 环境 Debian / Ubuntu / Deepin 下安装 Windows 下安装 基本使用 初始化项目 创建爬虫 运行爬虫 ...