Drupal 7 – Simple Ajax implementation @ 3

In the past 2 days we have developed a custom module which demonstrates the basic Ajax implementation in Drupal 7.

 

Today i will continue the example written by Kevin Hankens and make the module more secure. We want to add a token in the Ajax request such that the server could check if it comes from a valid user. This token could be obtained from drupal_get_token() which will return a fixed token value for each user session. Here are the list of changes in the new eureka_ajax.module.

  • Set the token value in Drupal.settings in hook_init()
  • Add the token as query string in the theme_ajax_link()
  • Check if the token is valid in ajax_request_callback()


eureka_ajax.module

<?php
/**
 * Implementation of hook_init().
 */
function eureka_ajax_init() {
  // Include the js file
  drupal_add_js(drupal_get_path('module', 'eureka_ajax') . '/eureka_ajax.js');
  // Set the user token in Drupal.settings
  drupal_add_js(array('eurekaToken' => drupal_get_token()), 'setting');
}

/**
* Implementation of hook_permission().
*/
function eureka_ajax_permission() {
  // Restrict access to either of your new URLs.
  return array(
    'access eureka page' => array(
      'title' => t('Access eureka page'),
      'description' => t('Allow users to access eureka/page.'),
    ),
    'access eureka ajax' => array(
      'title' => t('Access eureka ajax'),
      'description' => t('Allow users to access the eureka ajax callback at eureka/ajax.'),
    ),
  );
}

/**
 * Implementation of hook_menu().
 */
function eureka_ajax_menu() {
  $items = array();

  // Create a Drupal page to display our AJAX link.
  $items['eureka/page'] = array(
    'title' => 'Test Page',
    'page callback' => 'test_page_callback',
    'access arguments' => array('access eureka page'),
    'type' => MENU_NORMAL_ITEM,
  );

  // Create a path to send our AJAX request to.
  $items['eureka/ajax'] = array(
    'title' => 'Ajax Request',
    'page callback' => 'ajax_request_callback',
    'access arguments' => array('access eureka ajax'),
    'type' => MENU_CALLBACK,
  );

  return $items;
}

/**
 * Callback function for /eureka/page.
 */
function test_page_callback() {
  return theme('ajax_link');
}

/**
 * Implementation of hook_theme().
 */
function eureka_ajax_theme() {
  return array(
    'ajax_link' => array(),
  );
}

/**
 * Implementation of theme_ajax_link().
 */
function theme_ajax_link() {
  return l(t('What is the date and time?'), 'eureka/ajax', array(
    'query' => array(
      'eureka_token' => drupal_get_token()
    ),
    'attributes' => array(
      'id' => 'eureka-ajax')
    )
  );
}

/**
 * Callback function for /eureka/ajax.
 */
function ajax_request_callback() {
  if (isset($_POST['from_js']) && $_POST['from_js']) {
    // It is a valid POST request
    if (isset($_POST['eureka_token']) && $_POST['eureka_token'] == drupal_get_token()) {
      // The token is correct
      $response = array(
        'message' => t('It is approximately !date', array('!date' => date('M j Y h:i:s'))),
      );
      drupal_json_output($response);
      exit;
    } else {
      // Return an empty json array for incorrect request
      drupal_json_output(array());
      exit;
    }
  } else {
    // It maybe a GET request
    if (isset($_GET['eureka_token']) && $_GET['eureka_token'] == drupal_get_token()) {
      // Return the time in if it does not comes from javascript
      return t('It is approximately !date', array('!date' => date('M j Y h:i:s')));
    } else {
      // Invalid token
      return t('Invalid token');
    }
  }
}

 

In the eureka_ajax.js, we need to retrieve the token value from Drupal.settings and set it in the POST request.
eureka_ajax.js

(function ($) {
  Drupal.behaviors.eurekaAjax = {
    attach: function (context, settings) {
      // Bind an AJAX callback to our link
      var eurekaAjaxLink = $('#eureka-ajax');
      
      eurekaAjaxLink.click(function(event) {
        // Prevent the default link action
        event.preventDefault();
        
        // Get the request URL without the query string
        var ajaxUrl = eurekaAjaxLink.attr('href').split('?');
        
        $.ajax({
          type: "POST",
          url: ajaxUrl[0],
          data: {
            // For server checking
            'from_js': true,
            'eureka_token': Drupal.settings.eurekaToken // add the token in POST request
          },
          dataType: "json",
          success: function (data) {
            // Display the time from successful response
            if (data.message) {
              $(".messages").remove();
              $("#content").prepend('<div class="messages status">' + data.message + '</div>');
            }
          },
          error: function (xmlhttp) {
            // Error alert for failure
            alert('An error occured: ' + xmlhttp.status);
          }
        });
      });
    }
  };
})(jQuery);

 

Clear the cache after the changes. Access the eureka/page and you will find the link is appended with the token as query string.

 

Copy that link and access it directly from browser, you will still get the time.

 

You can modify the token or even remove the token query string but this time you will get the Invalid token.

 

That’s all for the Ajax example. The example may not fulfill what you want but it should be a good example for you to get the rough idea on how to implement Ajax in Drupal 7. Thanks Kevin Hankens for his example in Drupal 6.

Done =)

Reference:

About these ads

One thought on “Drupal 7 – Simple Ajax implementation @ 3”

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s