/**
* 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. CentOS7安装配置FTP服务器

    假设我们有以下要求 路径 权限 备注 /ftp/open 公司所有人员包括来宾均可以访问 只读 /ftp/private 仅允许Alice.Jack.Tom三个人访问 Alice.Jack只允许下载, ...

  2. Objective-C:自定义Block函数

    Block函数是一种类似于函数指针的函数,程序员只需要把需要操作的代码封装到定义的block中即可,以后需要使用时,直接调用,非常方便.... 举例如下: 第一种形式:自定义一个无返回值而且无参数的b ...

  3. struts2与struts1整合,Unable to load configuration. - interceptor-ref ... struts.xml

    struts.xml中为了与struts1的MVC模式整合,需要类似如下的拦截器的引用 <interceptor-stack name="integration"> & ...

  4. Myeclipse 自定义代码自动格式化(ctrl+alt+F)

    打开如图界面:preference->java->code style->formatter下的edit... 如设设置java代码多长换行:

  5. android-HttpClient上传信息(包括图片)到服务端

    需要下载apache公司下的HttpComponents项目下的HTTPCLIENT ----------地址为http://hc.apache.org/downloads.cgi 主要是用到了htt ...

  6. [原]HDU-1598-find the most comfortable road(暴力枚举+Kruskal最小生成树)

    题意: 给出一个图,然后Q个询问,每次询问从一个节点到另一个节点,联通图中的“最大边和最小边之差”的最小值,但如果节点之间不连通,则输出-1. 思路:由于询问Q < 11,m < 1000 ...

  7. leetcode:Intersection of Two Linked Lists(两个链表的交叉点)

    Write a program to find the node at which the intersection of two singly linked lists begins. For ex ...

  8. visual studio 中删除多余的空白行

    替换  Ctrl+H  正则  勾选  替换 ^\s*\n 为空

  9. 3D volume texture和cube map

    cube map texture可以理解为6个面的纸盒, sample的时候使用vector射线型的sample. volume texture可以理解是一摞2D texture,sample的时候用 ...

  10. BZOJ 3083 - 遥远的国度

    原题地址:http://www.lydsy.com/JudgeOnline/problem.php?id=3083 说话间又一个多月过去了..该来除除草了,每天都是训练.没效率,训练.没效率..省选考 ...