Module Development in Drupal

In this post, we cover different aspects for developing modules in Drupal including creating modules, setting variables and other

Creating Module

Modules location

  • The /modules folder that is reserved for core is not good location for your custom modules
  • The good location is /sites/all/modules folder to keep the contributed and custom modules(/sites/all/modules/contr or /sites/all/modules/custom)

Modules Naming

  • keep lower case
  • its not good practice to include numbers

->the modules description along the name and core version is stored in .info files as following:

name = Sample Module
description = sample module description
core = 7.x
version = 7.x-0.1-dev ;to show up in the admin ui
package = Block Wrapper
files[] = nameOfModule.module
dependencies[] = module1
configure = admin/config/moduleName ;this adds configuration button next to module name in modules list

In order to show up in core admin UI, need .module file. It can be empty but required. Documentation can be included

/**
*@file
*Custom functionally for your custom module
*/

Try, clear cache and check to install the module from admin/modules interface

Create Module Admin Interface

Once installed, next we create an admin UI interface to be able edit configurations and settings of the custom module. To do so, we are going to use hook_config_menu:

function moduleName_config_menu(){
    $items = array();

    //Admin config group
    $items['admin/config/kapasoft'] = array(
        'title' => 'Kapasoft',
        'description' => 'Configure Interface with Driver',
        'access arguments' => array('administer kapasoft configurations'),
    );

    //admin configuraiton - settings
    $items['admin/config/kapasoft/manage'] = array(
        'title' => 'Kapasoft configuration',
        'description' => 'Manage Kapasoft Interface config settings',
        'access arguments' => array('administer kapasoft configurations'),
        'page callback' => 'drupal_get_form',
        'page arguments' => array('kapasoft_config_form'),
    );

    return $items;
}

Here we create the module’s admin page – ‘manage’ in admin UI section ‘admin/config/kapasoft’. Next, clear the cache and see if it appears in the admin menu

You should see an error, because in the ‘page callback’ we specify function that builds a form but its not yet declared. Lets do it now

Admin Menu Form

Here, we create a form displayed in admin UI for our module to manipulate settings. In last step, we specified the function(i.e kapasoft_config_form) that builds the form. Now, we implement it as follows:

function kapasoft_config_form($nodes, &$form_state){
    $form = array();

    $form['overview'] = array(
        '#markup' => t('This interface allows to manage KapaSoft modules Settings'),
        '#prefix' => '<p>',
        '#suffix' => '</p>',
    );

    $form['interface_config'] = array(
        '#title' => t('Interface Config'),
        '#description' => t('Configurations of Driver'),
        '#type' => 'fieldset',
        '#collapsible' => TRUE,
        '#collapsed' => FALSE,
    );

    $form['interface_config']['driver_url'] = array(
        '#title' => t('Driver Url'),
        '#description' => t('url of the driver'),
        '#type' => 'textfield',
        '#default_value' => 'localhost',
        '#required' => TRUE,
    );

    $form['interface_config']['driver_port'] = array(
        '#title' => t('Driver Port'),
        '#description' => t('port of the driver'),
        '#type' => 'textfield',
        '#default_value' => '3000',
        '#required' => TRUE,
    );

    $form['submit'] = array(
        '#type' => 'submit',
        '#value' => t('Save'),
    );
    return $form;
}

Here we add two fields and set default values. Afterwards, clear the cache and go to the admin UI (admin/config/kapasoft/manage) to see the form with default settings.

Make Data Persistent

One of the ways Drupal provides ability to persist almost any type of data are through the variable_get, variable_set and variable_del API. Good for settings but shouldn’t be used for content

Lets, adjust our default values:

function kapasoft_config_settings_form($nodes, &$form_state){
...
 $form['interface_config']['driver_url'] = array(
        '#title' => t('Driver Url'),
        '#description' => t('url of the driver'),
        '#type' => 'textfield',
        '#default_value' => variable_get('kapasoft_driver_url', 'localhost'),
        '#required' => TRUE,
    );

    $form['interface_config']['driver_port'] = array(
        '#title' => t('Driver Port'),
        '#description' => t('port of the driver'),
        '#type' => 'textfield',
        '#default_value' => variable_get('kapasoft_driver_port', 3000),
        '#required' => TRUE,
    );
}

In the highlighted lines, the default value is retrieved from variable. If the variables hasn’t been set,yet, then it sets to the default values as specified(i.e. ‘locahlost’, 3000))

At submission, lets save the new variables as well:

function kapasoft_config_form_submit($form, &$form_state){
    //rebuild the form
    $form_state['rebuild'] = TRUE;

    //Save kapasoft setting variables
    variable_set('kapasoft_driver_url', $form_state['values']['driver_url']);
    variable_set('kapasoft_driver_port', $form_state['values']['driver_port']);
 
    //notify user
    drupal_set_message(t('kapasoft driver settings are saved'));
}

At form submission, the values from the form is taken and saved using the variable_set API

Variable_get With Defaults

So far as implemented, it only works with the form. If the form is not submitted, variables are not saved.

In addition, defaults are set in dozen places that don’t scale. In another words, we would have to edit code for each instance of variable_get/variable_set if the default value changes

So, we going to use hook_install to set the default variables once at the time module is installed. This hook is placed in moduleName.install file as following:

function kapasoft_config_install(){
    //set default variables
    variable_set('kapasoft_driver_url', 'localhost');
    variable_set('kapasoft_driver_port', '3000');

    //get localization function for installation as t() may not be available
    $t = get_t();

    //give user feedback
    drupal_set_message($t('Kapasoft driver configurations created'));
}

function kapasoft_config_uninstall(){
    //Delete variables
    variable_del('kapasoft_driver_url');
    variable_del('kapasoft_driver_url');
    
    //get localization function for installation as t() may not be available
    $t = get_t();
    
    //give user feedback
    drupal_set_message($t('Kapasoft driver configurations removed'));    
}

Next, remove all default values from moduleName.module file, so there is single point of initialization for defaults in the moduleName.install file(i.e. make variable_get(‘kapasoft_driver_url’, 3000) to variable_get(‘kapasoft_driver_url’))

Adding Configuration Button

To add a configuration button next to module name in the modules list, add the following line in the modulesName.info file:

...
configure = admin/config/kapasoft/manage

Here the path ‘admin/config/kapasoft/manage’ is the path specified in the moduleName_config_menu() function above

Shorten Code

We can shorten code by completely removing submit function(i.e kapasoft_config_settings_form_submit()) and let the Drupal built in mechanism handle our form submission by updating the form build function as follows:

function kapasoft_config_form($nodes, &$form_state){
...
//    $form['submit'] = array(
//        '#type' => 'submit',
//        '#value' => t('Save'),
//    );

    return system_settings_form($form);
}

As you see, we uncomment the submit button and return Drupal function ‘system_settings_form() with an argument that contains our admin form. This will handle the submission, save the variables and display the message to user. Note, make sure the variable names are the same as specified in form.

Load Other Modules

To utilize other modules within your module, all you need is to load it as following:

module_load_include('inc', 'location', 'earth');
module_load_include('inc', 'gmap3_tools');

This loads the ‘location’ and gmap3_tools modules. Afterwards, you are able to use any of their modules API

How To add Content Type

Here is a great article Creating Custom Content Type…

How to add Block

see post Blocks in Drupal

Troubleshooting

1. Form structure and values
When implementing form validation, it may be useful to print out the form structure

function bazar_node_form_validate($form, &$form_state){
    //to see what validated - the structure
    dpm($form_state);
    //purposely set error
    form_set_error('','testing');

The ‘bazar_node_form_validation’ is custom form validation function added to the list of function names that are used to validate the form in hook_form_alter:

/**
 * implements hook_form_alter()
 */
function bazar_form_alter(&$form, &$form_state, $form_id){
    //like to add validation but i don't know the form id
    dpm($form_id);
    //i would like to see the structure of the form
    dpm($form);
    //return to browser, clear craches and go to form

    //Afterwards, we can turn on debuging only for our form of interest. From the form id we can figure out the validation callback function to be bazar_node_form_validate
    switch($form_id){
        case 'bazar_node_form':{
            //dpm($form);
            //look for #validate that takes list of function names that are used to validate the form. I can ad custom funciton to this array
            $form['#validate'][] = 'bazar_node_form_validate';
            break;
        }
    }
}

Here, we are adding custom validation function ‘bazar_node_form_validate’ to the form with id ‘bazar_node_form’

2. Verify variables loaded
Here is an example to find out what variables are loaded for your theme function(the theme hook specifies theme funciotn)

function theme_ThemeName_gmap($variables){
    dpm($variables);
}

This will print out all the variables passed to this theme. The theme funciton ‘theme_ThemeName_gmap’ was specified in the theme_hook

Useful Links

  • https://api.drupal.org/api/drupal/

Leave a Reply

Your email address will not be published. Required fields are marked *