/**
* Passes alterable variables to specific hook_TYPE_alter() implementations.
*
* This dispatch function hands off the passed-in variables to type-specific
* hook_TYPE_alter() implementations in modules. It ensures a consistent
* interface for all altering operations.
*
* A maximum of 2 alterable arguments is supported (a third is supported for
* legacy reasons, but should not be used in new code). In case more arguments
* need to be passed and alterable, modules provide additional variables
* assigned by reference in the last $context argument:
* @code
* $context = array(
* 'alterable' => &$alterable,
* 'unalterable' => $unalterable,
* 'foo' => 'bar',
* );
* drupal_alter('mymodule_data', $alterable1, $alterable2, $context);
* @endcode
*
* Note that objects are always passed by reference in PHP5. If it is absolutely
* required that no implementation alters a passed object in $context, then an
* object needs to be cloned:
* @code
* $context = array(
* 'unalterable_object' => clone $object,
* );
* drupal_alter('mymodule_data', $data, $context);
* @endcode
*
* @param $type
* A string describing the type of the alterable $data. 'form', 'links',
* 'node_content', and so on are several examples. Alternatively can be an
* array, in which case hook_TYPE_alter() is invoked for each value in the
* array, ordered first by module, and then for each module, in the order of
* values in $type. For example, when Form API is using drupal_alter() to
* execute both hook_form_alter() and hook_form_FORM_ID_alter()
* implementations, it passes array('form', 'form_' . $form_id) for $type.
* @param $data
* The variable that will be passed to hook_TYPE_alter() implementations to be
* altered. The type of this variable depends on the value of the $type
* argument. For example, when altering a 'form', $data will be a structured
* array. When altering a 'profile', $data will be an object.
* @param $context1
* (optional) An additional variable that is passed by reference.
* @param $context2
* (optional) An additional variable that is passed by reference. If more
* context needs to be provided to implementations, then this should be an
* associative array as described above.
* @param $context3
* (optional) An additional variable that is passed by reference. This
* parameter is deprecated and will not exist in Drupal 8; consequently, it
* should not be used for new Drupal 7 code either. It is here only for
* backwards compatibility with older code that passed additional arguments
* to drupal_alter().
*/
function drupal_alter($type, &$data, &$context1 = NULL, &$context2 = NULL, &$context3 = NULL) {
// Use the advanced drupal_static() pattern, since this is called very often.
static $drupal_static_fast;
if (!isset($drupal_static_fast)) {
$drupal_static_fast['functions'] = &drupal_static(__FUNCTION__);
}
$functions = &$drupal_static_fast['functions']; // Most of the time, $type is passed as a string, so for performance,
// normalize it to that. When passed as an array, usually the first item in
// the array is a generic type, and additional items in the array are more
// specific variants of it, as in the case of array('form', 'form_FORM_ID').
if (is_array($type)) {
$cid = implode(',', $type);
$extra_types = $type;
$type = array_shift($extra_types);
// Allow if statements in this function to use the faster isset() rather
// than !empty() both when $type is passed as a string, or as an array with
// one item.
if (empty($extra_types)) {
unset($extra_types);
}
}
else {
$cid = $type;
} // Some alter hooks are invoked many times per page request, so statically
// cache the list of functions to call, and on subsequent calls, iterate
// through them quickly.
if (!isset($functions[$cid])) {
$functions[$cid] = array();
$hook = $type . '_alter';
$modules = module_implements($hook);
if (!isset($extra_types)) {
// For the more common case of a single hook, we do not need to call
// function_exists(), since module_implements() returns only modules with
// implementations.
foreach ($modules as $module) {
$functions[$cid][] = $module . '_' . $hook;
}
}
else {
// For multiple hooks, we need $modules to contain every module that
// implements at least one of them.
$extra_modules = array();
foreach ($extra_types as $extra_type) {
$extra_modules = array_merge($extra_modules, module_implements($extra_type . '_alter'));
}
// If any modules implement one of the extra hooks that do not implement
// the primary hook, we need to add them to the $modules array in their
// appropriate order. module_implements() can only return ordered
// implementations of a single hook. To get the ordered implementations
// of multiple hooks, we mimic the module_implements() logic of first
// ordering by module_list(), and then calling
// drupal_alter('module_implements').
if (array_diff($extra_modules, $modules)) {
// Merge the arrays and order by module_list().
$modules = array_intersect(module_list(), array_merge($modules, $extra_modules));
// Since module_implements() already took care of loading the necessary
// include files, we can safely pass FALSE for the array values.
$implementations = array_fill_keys($modules, FALSE);
// Let modules adjust the order solely based on the primary hook. This
// ensures the same module order regardless of whether this if block
// runs. Calling drupal_alter() recursively in this way does not result
// in an infinite loop, because this call is for a single $type, so we
// won't end up in this code block again.
drupal_alter('module_implements', $implementations, $hook);
$modules = array_keys($implementations);
}
foreach ($modules as $module) {
// Since $modules is a merged array, for any given module, we do not
// know whether it has any particular implementation, so we need a
// function_exists().
$function = $module . '_' . $hook;
if (function_exists($function)) {
$functions[$cid][] = $function;
}
foreach ($extra_types as $extra_type) {
$function = $module . '_' . $extra_type . '_alter';
if (function_exists($function)) {
$functions[$cid][] = $function;
}
}
}
}
// Allow the theme to alter variables after the theme system has been
// initialized.
global $theme, $base_theme_info;
if (isset($theme)) {
$theme_keys = array();
foreach ($base_theme_info as $base) {
$theme_keys[] = $base->name;
}
$theme_keys[] = $theme;
foreach ($theme_keys as $theme_key) {
$function = $theme_key . '_' . $hook;
if (function_exists($function)) {
$functions[$cid][] = $function;
}
if (isset($extra_types)) {
foreach ($extra_types as $extra_type) {
$function = $theme_key . '_' . $extra_type . '_alter';
if (function_exists($function)) {
$functions[$cid][] = $function;
}
}
}
}
}
} foreach ($functions[$cid] as $function) {
$function($data, $context1, $context2, $context3);
}
}

drupal_alter()函数提供一个对钩子系统的调用,实现对系统变量的自定义修改。例如:当系统处于维护状态时,网站应该只允许管理员访问,一般访问者只能看到“系统处于维护状态”这样的提示信息。一般访问者访问网站时,若是在变更维护状态之前已经登录网站,这时user模块提供一个钩子,实现访问者的自动注销。

// menu.inc的501-508行
$site_status = variable_get('maintenance_mode') ? MENU_SITE_OFFLINE : MENU_SITE_ONLINE;
drupal_alter('menu_site_status', $site_status , $_GET['q']);

drupal_alter()会调用形如hook_TYPE_alter这样的钩子,此例子中是user模块的user_menu_site_status_alter()函数:

// user.module的1834-1874行
function user_menu_site_status_alter(&$menu_site_status, $path) {
if ($menu_site_status == MENU_SITE_OFFLINE) {
// If the site is offline, log out unprivileged users.
if (user_is_logged_in() && !user_access('access site in maintenance mode')) {
module_load_include('pages.inc', 'user', 'user');
user_logout();
} ... ...
} ...
}

第57行:注意参数$data,是引用定义的,也可以理解为传址。再看一下user_menu_site_status_alter()钩子的参数,这里的$menu_site_status也是引用定义,和$data刚好对应。也就是说,在user_menu_site_status_alter()中修改$menu_site_status的值,也就是在修改$data的值。
以此类推,drupal_alter()定义了三个context参数,也都是引用定义的。所以,在钩子函数中如果有需要,也可以修改这三个context参数的值:

function hook_menu_site_status_alter(&$menu_site_status, &$context1, &$context2, &$context3) {
$context1 = 'new value';
... ...
}

第143-144行:drupal_alter()被调用时,theme系统有可能准备就绪,也有可能尚未就绪。通过全局变量$theme可以判断theme系统是否就绪:

global $theme;
if (isset($theme)) {
// theme系统准备就绪
} else {
// theme系统尚未就绪
}

除了module可以提供钩子(格式如:module_TYPE_alter)修改变量值以外,theme也可以提供钩子(格式:theme_TYPE_alter)修改变量值。所以,drupal必须要求模块和主题命名的唯一。

Drupal 7.23:函数drupal_alter()注释的更多相关文章

  1. Drupal 7.23:函数module_invoke_all()注释

    /** * Invokes a hook in all enabled modules that implement it. * * All arguments are passed by value ...

  2. python函数知识二 动态参数、函数的注释、名称空间、函数的嵌套、global,nonlocal

    6.函数的动态参数 *args,**kwargs:能接受动态的位置参数和动态的关键字参数 *args -- tuple *kwargs -- dict 动态参数优先级:位置参数 > 动态位置参数 ...

  3. Python函数02/函数的动态参数/函数的注释/名称空间/函数的嵌套/global以及nolocal的用法

    Python函数02/函数的动态参数/函数的注释/名称空间/函数的嵌套/global以及nolocal的用法 目录 Python函数02/函数的动态参数/函数的注释/名称空间/函数的嵌套/global ...

  4. VA中用文件头注释和函数头注释Suggestions

    写C++代码,不能不用VA,这里贴两个我最常用的注释Suggestions. [1.File Header 文件头注释] /*** @file     $FILE_BASE$.$FILE_EXT$* ...

  5. 使用VAssistX给文件和函数添加注释-2015.12.31

    在Visual Studio使用VAssistX助手可以非常方便的给文件和函数添加注释,增加更多的记录信息,从而方便在时间久后,对代码阅读理解的提示,以及别人后续对代码的维护和BUG修改. 添加头文件 ...

  6. Visual Studio+VAssistX自动添加注释,函数头注释,文件头注释

    转载:http://blog.csdn.net/xzytl60937234/article/details/70455777 在VAssistX中为C++提供了比较规范注释模板,用这个注释模板为编写的 ...

  7. python27期day10:函数的动态参数、函数的注释、函数的名称空间、函数的嵌套、global(修改全局的)、nonlocal(修改局部的)、函数名的第一类对象及使用、作业题。

    1.动态参数的作用: 能够接收不固定长度参数 位置参数过多时可以使用动态参数 * args是程序员之间约定俗称(可以更换但是不建议更换) * args获取的是一个元组 ** kwargs获取的是一个字 ...

  8. Drupal 7.23版本升级笔记

    转载请注明出处:http://blog.csdn.net/panjunbiao/article/details/9860849 今天将尝试将Drupal网站从7.22升级到7.23,下面是升级笔记. ...

  9. [C++]VAssistX函数添加注释功能设置

    问题情况:每次手写注释太慢,而且不系一.问题原因:C++可以利用宏写注释,也可以使用VAssistX提供的方法.问题处理:1.安装VAssistX在VS2010上 2.VS2010菜单->VAs ...

随机推荐

  1. C 语言文件操作

    C 语言文件操作 1. 数据流:     程序与数据的交互以流的形式进行.fopen 即打开数据流,fclose 即刷新数据流.     所谓数据流,是一种抽象,表示这段数据像流一样,需要逐步接收,不 ...

  2. left join查询结果大于原始数据

    left join onon后面一定是一个主键或者是一个值为唯一的字段吗  on后面关联的条件如果是1对1的数量就不变,如果是1对多的数量就会增加 追问: 问题就在这,我1对多了 追答: 通常的做法是 ...

  3. 【推荐】HTML5 UI框架 推荐

    笔者的男装网店:http://shop101289731.taobao.com .冬装,在寒冷的冬季温暖你.新品上市,环境选购 最近自己瞎搞一下web网页的东西.想开发先找资源. 整理了一下HTML5 ...

  4. Spring 事务配置的几种方式

    参考:http://www.blogjava.net/robbie/archive/2009/04/05/264003.html http://www.cnblogs.com/appleat/arch ...

  5. jdk、apache-ant结合yuicompressor配置的CSS与JS合并压缩工具

    前序:网上很多css与js合并打包工具,其中最流行的就是ant结合yui-compressor,鉴于学习与工作需要今天就学习了一下这种方式,供大家学习交流. 步骤:1.安装jdk,并配置其变量环境:有 ...

  6. allegro下快捷键设置[转贴]

    zz : http://yuandi6.blog.163.com/blog/static/207265185201210245435397/ 修改变量文件,设置自定义快捷键. Allegro可以通过修 ...

  7. bash/shell 数学计算

    $ echo $((20.0/7)) $ zcalc $ bc <<< 20+5/2 $ bc <<< 'scale=4;20+5/2' $ expr 20 + 5 ...

  8. 《OD大数据实战》Hadoop伪分布式环境搭建

    一.安装并配置Linux 8. 使用当前root用户创建文件夹,并给/opt/下的所有文件夹及文件赋予775权限,修改用户组为当前用户 mkdir -p /opt/modules mkdir -p / ...

  9. Machine Learning for hackers读书笔记(四)排序:智能收件箱

    #数据集来源http://spamassassin.apache.org/publiccorpus/ #加载数据 library(tm)library(ggplot2)data.path<-'F ...

  10. core--作业

    线程被封装在进程中,进程能不能被封装? 当有多个进程协调一起来完成一项任务的时候,就使用"作业"来完成 作业将进程组合在一起,并创建一个"盒子"来限制进程能够做 ...