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. [ARC062F]Painting Graphs with AtCoDeer

    题意:一个无向图,用$k$种不同的颜色给每条边染色,问能染出多少种不同的图,如果两张图能通过循环移位环边使得颜色相同,那么这两张图被认为是相同的 数学太差伤不起啊...补了一下Burnside定理的证 ...

  2. 【推导】【构造】XVII Open Cup named after E.V. Pankratiev Stage 14, Grand Prix of Tatarstan, Sunday, April 2, 2017 Problem E. Space Tourists

    给你n,K,问你要选出最少几个长度为2的K进制数,才能让所有的n位K进制数删除n-2个元素后,所剩余的长度为2的子序列至少有一个是你所选定的. 如果n>K,那么根据抽屉原理,对于所有n位K进制数 ...

  3. 【强连通分量缩点】【DFS】【动态规划】Urozero Autumn Training Camp 2016 Day 5: NWERC-2016 Problem B. British Menu

    有向图,不经过重复点的最长链,强连通分量大小不超过5. 每个强连通分量内部暴力预处理任意两对点之间的最长路,外面DAG上dp. 不是很好写,但是预处理完了之后,可以重构每个强连通分量内部的结构,然后整 ...

  4. 【找规律】【递推】【二项式定理】Codeforces Round #419 (Div. 1) B. Karen and Test

    打个表出来看看,其实很明显. 推荐打这俩组 11 1 10 100 1000 10000 100000 1000000 10000000 100000000 1000000000 1000000000 ...

  5. python基础之集合,字符编码

    六.集合类型 1.用途:关系运算 2.定义方式:s = {1,2,’a’} {}内用,分隔开多个元素,每个元素都必须是不可变(即可hash)类型 强调:2.1集合内的元素时无序的 2.2集合内的元素不 ...

  6. 搭建vsftpd

    安装完软件以后 1.建立用户 adduser ftp passwd 密码 2.修改vsftp.conf文件 anonymous_enable改为NO,阻止匿名上传 Anon_mkdir_write_e ...

  7. Educational Codeforces Round 8 B. New Skateboard 暴力

    B. New Skateboard 题目连接: http://www.codeforces.com/contest/628/problem/A Description Max wants to buy ...

  8. Smart config风险分析与对策

    Smart config风险分析与对策 1.简介:          Smart config是一种将未联网设备快速连接wifi的技术,大概原理如下图所示: 2.业务需求:          要求实现 ...

  9. ADO特有的流化和还原

    ADO特有的流化和还原 {*******************************************************}{ }{ ADO 数据流化 }{ }{ 版权所有 (C) 20 ...

  10. this和$(this)的关系

    环境关键字this引用的是DOM元素 $(this)是jQuery对象 下面点击按钮分别alert一下 alert(this); alert($(this)); 获取DOM对象的属性id,可以 $(t ...