Function scope & Drupal cache

Submitted by swim on Mon, 07/14/2014 - 04:43

When developing with caching in mind it's important to consider functionality scope. For example, writing code which is per visitor specific in PHP with caching support ahhh =O. While rewriting that same functionality in JavaScript offers us a quick and cache friendly solution. Consider the following examples.


/**
 * Implements hook_preprocess_TEMPLATE().
 */
function THEME_preprocess_page(&$variables) {
  $detect = mobile_switch_mobile_detect();

  if ($detect['ismobiledevice'] && !$detect['istablet']) {
    $variables['logo'] = url('sites/all/themes/THEME/images/logo_rev.png', array('absolute' => TRUE));
  }
}


/**
 * Custom header block content.
 */
function _header_search_content_block() {
  $detect = mobile_switch_mobile_detect();
  $form = drupal_get_form('search_form');

  // Format search form.
  $form['basic']['keys']['#attributes']['placeholder'] = t('Search');
  $form['basic']['keys']['#title_display'] = 'invisible';
  $form['basic']['keys']['#size'] = 20;

  if ($detect['ismobiledevice'] || $detect['istablet']) {
    $form['basic']['keys']['#size'] = 15; 
  }

  $items = array(
    render($form),
    l(t('another item'), 'link')
  );

  return theme('item_list', array('items' => $items));
}

Clearly this code can be easily rewritten in JavaScript. However with caching enabled we'll need a method to pass our device detection variables. The only function which is exempt from Drupal cache is boot(). Calling drupal_add_js() directly from hook_boot() fails; the following example is using Mobile Switch and illustrates a work around.


/**
 * This is an example of how to manipulate site elements with page
 * caching enabled. We pass our detection variables to js settings
 * which we can then act on.
 */
function MODULE_boot() {
  $detect = mobile_switch_mobile_detect();

  // Whatami.
  $_SESSION['detect'] = array(
    'ismobile' => $detect['ismobiledevice'],
    'istablet' => $detect['istablet']
  );
}

/**
 * Implements hook_init().
 */
function MODULE_init() {
  drupal_add_js(array('detect' => $_SESSION['detect']), 'setting');
}


/**
 * @file
 * MODULE.theme.js
 */

(function($) {

  Drupal.behaviors.MODULE = {
    attach: function(context, settings) {
      // Swap logo for mobile.
      if (settings.detect.ismobile && !settings.detect.istablet) {
        $('.site-branding__logo img').attr('src', Drupal.settings.basePath + 'sites/all/themes/THEME/images/logo_rev.png');
      }

      // Search box size.
      if (settings.detect.ismobile || settings.detect.istablet) {
        $('.l-region--header .search-form input.form-text').attr('size', 15);
      }
    }
  };

}(jQuery));

These flags can of course be used for more fruitful purposes =)... Note, this sort of consideration is most likely second nature to most Xd.