Showing posts with label module. Show all posts
Showing posts with label module. Show all posts

Thursday, December 18, 2014

Drupal plugin

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.

Thursday, September 18, 2014

Plugin

Plugins are features added out of box. It is not needed to know all the internals of an application to write a new plugin. And the application does not need to know about the feature internals. The new plugin feature is called the extension to the existing software. To make the total thing work, the extensions are registered to an extension point.

There are two things that incorporate plugin.

  • Loadable separate code.
  • Features/extensions that are registered at some extension point.

Example of a plugin

Suppose there is a need for feature to share a webpage content as emails. The feature is to send email with less interaction from the user. The user does not need to open a web application interface in the browser to send email. The feature can be implemented by a email plugin of the browser. The email plugin may insert a ‘send page’ button through registering in menu-item-extension point. And when the user clicks the ‘send page’ button from the browser-menu it opens up few text-boxes. Eventually the user types the address and subject and presses the send button to send the email.

Here is a component diagram to demonstrate the idea,

This is an email sending feature that is implemented by email plugin. And the plugin registers in menu-item-extension point. The plugin know very little about the core features or other plugins. And the core application does not know the internals of the plugin at all.

Actually this type of plugin exists for firefox browser. For firefox the plugins are called addons. And there is an addon named send page. The code is available here.

<menupopup id="menu_FilePopup">
  <menuitem id="menu_sendpagebyemail" label="Send page by email..." key="spbe_sendPageKey" 
    oncommand="spbe_showDialog();" insertbefore="menu_sendLink" accesskey="e"/>
</menupopup>

The xul code above registers a menu-entry labeled ‘Send page by email…’ in popup menu.

Finally the addon is provided in distributable package which firefox can load easily on demand.

The plugin system makes it possible to implement the beautiful correlation above.

Modules and plugins

Plugins and modules come hand in hand. Both modules and plugins are pieces of code. Both of them emphasize on separation of concern. In a module certain things are grouped together for development-ease or other purposes. But in a plugin they incorporate a feature and the basic idea is separation from the core features.

Sometimes module loaders facilitate a way to load plugins. In this case modules are also special type of plugins. They are loaded in the invisible extension point of the application binary.

Advantages

Developing parts as plugins is a useful approach. It comes with some benefits.

Make little things work quickly and easily

Plugins are written to give some specific features. And their concerns are limited. So is the development time. This time-tuning is important because of human bias of instant gratification.

Additionally the separated code can be tested and debugged in absence of other features(of which it is not dependent). Thus separation helps development,debugging and testing units. For example, if it is needed to think of a feature to write a browser plugin to send email, then it is not needed to worry about other browser plugins like video player or something. In this way it is possible to be more focused and productive.

Plugins improve motivation

Plugins makes it possible to write a small separate segment of a big task. So it gives the satisfaction of achievement. Though it is a portion of big task, still it motivates to finish the unit. It helps the unit-bias of human psychology to finish an unit task.

Plugins and extension point mechanism makes things simple

Extending a big application is big cognitive load. To know all the internals is mandatory. Otherwise it can lead to bugs. And there is need to know the big APIs too. But in plugin the scope is small. It is not necessary to worry about the whole application but only the plugin-api. For example, to write an email sending feature for existing browser which has plugin support, it needs very little for the integration,

  • To know the plugin API. (To know the skeleton plugin that does nothing.)
  • To know how to add an extension.

Additionally, there are other things like showing an edit box and sending an email, but they have nothing to do with the core application.

OK, this is all about plugins now. In future, there will be discussions on how people facilitate plugins in their applications.