Drupal is a PHP content-management framework for web development. The popularity of drupal is evident in the vast community and contributed modules. The popularity comes from the ease of customization and simplicity of design. In this article the plugins of drupal aka the `modules` are analyzed. This is a continuous effort to investigate plugins in different projects.
Drupal modules are grouped into a folder/directory named after that module. The directory contains the following files,
.info
file. The content of the.info
file enable us to know about the module without loading it or installing it. These informations are kept in key-value pairs. They contain the name, description, version, package and testing information etc..module
file. This is a PHP script containing primarily the hooks that needs to be loaded when the page is hit. To write a drupal module one must write the.module
file and write at least one hook function..install
file. This file is used only for installation and uninstallation. They may create database or do other tasks that are done at the time of installations. It contain the_install
and_uninstall
hooks..inc
files. These files are loaded on demand. They are PHP sources containing instructions which is not needed in every page hit.
There are other files for testing and for command line operations. But those are not covered here. The cardinal part of the module is in the .module
file. It contains function definitions. The function names are identified by the hooks using the PHP reflection feature. For example, a module can add menu by writing the following functions.
function mymodule_menu() {
$items['abc/def'] = array(
'page callback' => 'mymodule_abc_view',
);
return $items;
}
function mymodule_abc_view() {
return "Here is the abc content";
}
The above code is for module named mymodule
. So the menu hook is the function named mymodule_menu
. It is derived by prefixing the module name before _menu
. And the return value of the hook is the array containing the menu items and the functions to be called on the menu hit. The ‘abc/def’ is the menu path identifying a page. It appears on the address bar of the browser.
All the _menu
hooks can be called and executed by module_invoke_all
function. It is possible to call user defined hooks to be populated by other modules.
function module_invoke_all($hook) {
$args = func_get_args();
// Remove $hook from the arguments.
unset($args[0]);
$return = array();
foreach (module_implements($hook) as $module) {
$function = $module . '_' . $hook;
if (function_exists($function)) {
$result = call_user_func_array($function, $args);
if (isset($result) && is_array($result)) {
$return = array_merge_recursive($return, $result);
}
elseif (isset($result)) {
$return[] = $result;
}
}
}
return $return;
}
In the code above the function name is created by code $function = $module . '_' . $hook;
. So it is conjunction of the module name and the hook name. The function above is responsible to call all the hooks of the loaded modules.
Now let us investigate the blog
module.
The purpose of this module
The blog.info file contains the description of the module. It enables blogging for drupal users.
Loading and unloading
The blog.install contains blog_install
and blog_uninstall
functions which are the _install
and _uninstall
hooks.
The blog_install() alters the blog
node and adds body
field for it. The node
is the parent object and it has it’s own defined way to save, load and render data. The blog is kind of subclass
of the node
. Anyway the abstraction of node is not covered here.
The blog_uninstall() just deletes unnecessary variable.
Note that the blog_install() function is called while installing and blog_uninstall() is called while uninstalling. But they are not called in each page hit. While in each page hit the blog.module
file is parsed but none of them are executed.
Extension points
The blog_menu
function defined in blog.module
file is the _menu
hook. Here _menu
is the extension point. This hook is called when the module is enabled for use. Once called the total menu tree is built and kept in the database. It is not executed in per page hit.
/**
* Implements hook_menu().
*/
function blog_menu() {
$items['blog'] = array(
'title' => 'Blogs',
'page callback' => 'blog_page_last',
'access arguments' => array('access content'),
'type' => MENU_SUGGESTED_ITEM,
'file' => 'blog.pages.inc',
);
$items['blog/%user_uid_optional'] = array(
'title' => 'My blog',
'page callback' => 'blog_page_user',
'page arguments' => array(1),
'access callback' => 'blog_page_user_access',
'access arguments' => array(1),
'file' => 'blog.pages.inc',
);
$items['blog/%user/feed'] = array(
'title' => 'Blogs',
'page callback' => 'blog_feed_user',
'page arguments' => array(1),
'access callback' => 'blog_page_user_access',
'access arguments' => array(1),
'type' => MENU_CALLBACK,
'file' => 'blog.pages.inc',
);
$items['blog/feed'] = array(
'title' => 'Blogs',
'page callback' => 'blog_feed_last',
'access arguments' => array('access content'),
'type' => MENU_CALLBACK,
'file' => 'blog.pages.inc',
);
return $items;
}
Note that the menu has it’s own plugin-system and the extension-points. The blog
, blog/%user_uid_optional
, blog/%user/feed
and blog/feed
are the extension-points aka paths of menu-plugin-system. And blog_page_last
, blog_page_user
, blog_feed_user
and blog_feed_last
are the hooks registered in those extension-points respectively. This is an added twist in drupal architecture. It decouples the menu-extension-points
from the core extension-points
. This makes it flexible and separable.
And with added benefits these menu related hooks and callbacks are defined in separate file named blog.pages.inc
to make the blog.module
slimmer. The blog.pages.inc
file is loaded when the related pages are loaded. Thus it reduces the processing time too.
Summary
Drupal project is based on functional programming in PHP. It still affords complex architecture and development needs. The reflection property of PHP function makes the hooking effortless. The analytic minds are tuned to find dumb instruments in the code. Drupal is very compulsive in that sense.