drupal module development quick guide

This tutorial is a one page short version of the beginner tutorial series from drupal.org. It requires that you have already installed a fresh drupal on your machine. There are only 2 files needed in order to create a module in drupal, a config file and a module file. Let’s get started.

In this tutorial, we will create a module called current_posts. A module needs it’s own folder, let’s create a folder called current_posts so the path to the module folder reads drupalRootDir/sites/all/modules/current_posts/

Note: All the custom codes in drupal lives in drupalRootDir/sites/ including third party libraries, custom modules, themes and configurations. Everything else are drupal core files that come with the drupal installation.

Now that we have the folder created for the module that we are going to create, let’s create the config file drupalRootDir/sites/all/modules/current_posts/current_posts.info and dump the following code in it. It tells drupal to include this module.

name = Current Posts
description = A block module that lists links to recent posts.
core = 7.x
configure = admin/config/content/current_posts
files[] = current_posts.test

The next file will be the actual heavy lifting php code for the module. Go ahead and create the module file drupalRootDir/sites/all/modules/current_posts/current_posts.module and dump the following code in it.

<?php
/**
 * @file
 * A block module that displays recent blog and forum posts.
 */

/**
 * Implements hook_help().
 *
 * Displays help and module information.
 *
 * @param path 
 *   Which path of the site we're using to display help
 * @param arg 
 *   Array that holds the current path as returned from arg() function
 */
function current_posts_help($path, $arg) {
  switch ($path) {
    case "admin/help#current_posts":
      return '<p>' . t("Displays links to nodes created on this date") . '</p>';
			break;
  }
} 

/**
 * Implements hook_block_info().
 */
function current_posts_block_info() {
  $blocks['current_posts'] = array(
    // The name that will appear in the block list.
    'info' => t('Current posts'),
    // Default setting.
    'cache' => DRUPAL_CACHE_PER_ROLE,
  );
  return $blocks;
}


function current_posts_contents($display){   //$display argument is new.
  //Get today's date.
  $today = getdate();
  //Calculate midnight a week ago.
  $start_time = mktime(0, 0, 0,$today['mon'],($today['mday'] - 7), $today['year']);
  //Get all posts from one week ago to the present.
  $end_time = time();
  
  $max_num = variable_get('current_posts_max', 3);
  
  //Use Database API to retrieve current posts.
  $query = db_select('node', 'n')
    ->fields('n', array('nid', 'title', 'created'))
    ->condition('status', 1) //Published.
    ->condition('created', array($start_time, $end_time), 'BETWEEN')
    ->orderBy('created', 'DESC'); //Most recent first. Query paused here.
 
   if ($display == 'block'){ 
  // Restrict the range if called with 'block' argument.
    $query->range(0, $max_num);
  } //Now proceeds to execute().
  //If called by page, query proceeds directly to execute().
  
  return $query->execute();
}

/**
 * Implements hook_block_view().
 * 
 * Prepares the contents of the block.
 */
function current_posts_block_view($delta = '') {
  switch ($delta) {
    case 'current_posts':
      $block['subject'] = t('Current posts');
      if (user_access('access content')) {
        // Use our custom function to retrieve data.
        $result = current_posts_contents('block');
        // Array to contain items for the block to render.
        $items = array();
        // Iterate over the resultset and format as links.
        foreach ($result as $node) {
          $items[] = array(
            'data' => l($node->title, 'node/' . $node->nid),
          ); 
        }
       // No content in the last week.
        if (empty($items)) {
          $block['content'] = t('No posts available.');  
        } 
        else {
          //Pass data through theme function.
          $block['content']['posts'] = array(
            '#theme' => 'item_list__current_posts__block',
            '#items' => $items,
          );
          //Add a link to the page for more entries.
          $block['content']['more'] = array(
            '#theme' => 'more_link__current_posts',
            '#url' => 'current_posts',
            '#title' => t('See the full list of current posts.'),
          );
        }
      }
    return $block;
  }
  
}

/**
* Implements hook_menu().
*/
function current_posts_menu() {
    $items = array();    
    $items['current_posts'] = array(
        'title' => 'Current posts',
        'page callback' => '_current_posts_page',
        'access arguments' => array('access current_posts content'),
        'type' => MENU_NORMAL_ITEM, //Will appear in Navigation menu.
      );
    return $items;
}

/**
 * Page callback: Current posts settings
 *
 * @see current_posts_menu()
 */
function current_posts_form($form, &$form_state) {
  $form['current_posts_max'] = array(
    '#type' => 'textfield',
    '#title' => t('Maximum number of posts'),
    '#default_value' => variable_get('current_posts_max', 3),
    '#size' => 2,
    '#maxlength' => 2,
    '#description' => t('The maximum number of links to display in the block.'),
    '#required' => TRUE,
  );

  return system_settings_form($form);
}



/**
 * Implements validation from the Form API.
 * 
 * @param $form
 *   A structured array containing the elements and properties of the form.
 * @param $form_state
 *   An array that stores information about the form's current state 
 *   during processing.
 */
function current_posts_form_validate($form, &$form_state){
  $max_num = $form_state['values']['current_posts_max'];
  if (!is_numeric($max_num)){
    form_set_error('current_posts_max', t('You must enter a number for the maximum number of posts to display.'));
  }
  elseif ($max_num <= 0){
    form_set_error('current_posts_max', t('Maximum number of posts to display must be positive.'));
  }
}


/**
 * Implements hook_permission().
 */
function current_posts_permission() {
  return array(
    'access current_posts content' => array(
      'title' => t('Access content for the Current posts module'),
    )
  );
}

/**
 * Custom page callback function, declared in current_posts_menu().
 */
function _current_posts_page() {
  drupal_set_title('Current posts');
  $result = current_posts_contents('page');
  //Array to contain items for the page to render.
  $items = array();
  //Iterate over the resultset and format as links.
  foreach ($result as $node) {
    $items[] = array(
    'data' => l($node->title, 'node/' . $node->nid),
    ); 
  }
  if (empty($items)) { //No content in the last week.
    $page_array['current_posts_arguments'] = array(
      //Title serves as page subtitle
      '#title' => t('All posts from the last week'),
      '#markup' => t('No posts available.'),
    );
    return $page_array;  
  } else {
    $page_array['current_posts_arguments'] = array(
      '#title' => t('All posts from the last week'),
      '#items' => $items,
      //Theme hook with suggestion.  
      '#theme' => 'item_list__current_posts',
    );
    return $page_array;
  }
}

With the above two files in place, we have the current_posts module installed in drupal. To enable the module, go to the admin dashboard, select modules from the top menu bar, find the current posts module, check the enabled checkbox and click Save configuration button at the bottom.

In the place where you enabled the module, you should see there are links Help and Permission on the right. They are there because of those functions in the current_posts.module, current_posts_help() and current_posts_permission(). There is also a link for Configure, and that’s there because of the line configure = admin/config/content/current_posts in the current_posts.info

If you go to the front end home page while you are logged in as an admin, you should see a link in Navigation for Current posts. If you logged out, they will be gone.

If you go to the admin dashbord, click Structure, and select Blocks, you should find Current posts.

Search within Codexpedia

Custom Search

Search the entire web

Custom Search