You are here

resp_img.module in Responsive images and styles 7

Same filename and directory in other branches
  1. 8 resp_img.module
  2. 7.2 resp_img.module

File

resp_img.module
View source
<?php

/**
 * @file resp_img.module
 */
if (!defined('RESP_IMG_COOKIE')) {
  define('RESP_IMG_COOKIE', 'respimg');
}
if (!defined('RESP_IMG_RATIO_COOKIE')) {
  define('RESP_IMG_RATIO_COOKIE', 'respimg_ratio');
}

/**
 * Implements hook_ctools_plugin_directory()
 */
function resp_img_ctools_plugin_directory($module, $plugin) {
  if ($module == 'ctools' && $plugin == 'export_ui') {
    return 'plugins/' . $plugin;
  }
}

/**
 * Implements hook_init().
 */
function resp_img_init() {
  resp_img_add_js();
  if (module_exists('context')) {
    $plugin = context_get_plugin('condition', 'resp_img_context_condition_suffix');
    if ($plugin) {
      $plugin
        ->execute(resp_img_get_best_suffix());
    }
  }
}

/**
 * Implements hook_enable().
 */
function resp_img_enable() {
  $cache_class_cache_page = variable_get('cache_class_cache_page');
  if (!empty($cache_class_cache_page)) {
    variable_set('resp_img_cache_class_cache_page_old', $cache_class_cache_page);
  }
  variable_set('cache_class_cache_page', 'RespImgPageCache');
}

/**
 * Implements hook_disable().
 */
function resp_img_disable() {
  $cache_class_cache_page_old = variable_get('resp_img_cache_class_cache_page_old');
  if (isset($cache_class_cache_page_old)) {
    variable_set('cache_class_cache_page', $cache_class_cache_page_old);
  }
  else {
    variable_del('cache_class_cache_page');
  }
  variable_del('resp_img_cache_class_cache_page_old');
}

/**
 * Implements hook_menu().
 */
function resp_img_menu() {
  $items = array();
  $items['admin/config/media/resp_img/settings'] = array(
    'title' => 'Settings',
    'description' => 'Responsive images and styles',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'resp_img_admin_settings',
    ),
    'access arguments' => array(
      'administer image styles',
    ),
    'file' => 'resp_img.admin.inc',
    'type' => MENU_LOCAL_TASK,
  );
  $items['admin/config/media/resp_img/create_style'] = array(
    'title' => 'Add responsive style',
    'description' => 'Add a responsive image style',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'resp_img_add_style_form',
    ),
    'access arguments' => array(
      'administer image styles',
    ),
    'file' => 'resp_img.admin.inc',
    'type' => MENU_LOCAL_TASK,
  );
  return $items;
}

/**
* Load a single suffix
*/
function resp_img_suffix_load($name) {
  ctools_include('export');
  $result = ctools_export_load_object('resp_img_suffix', 'names', array(
    $name,
  ));
  if (isset($result[$name])) {
    return $result[$name];
  }
}

/**
 * Load all suffixes
 */
function resp_img_suffix_load_all() {
  ctools_include('export');
  return ctools_export_load_object('resp_img_suffix');
}

/**
* Save a single suffix
*/
function resp_img_suffix_save(&$resp_img_suffix) {
  $update = isset($resp_img_suffix->id) && is_numeric($resp_img_suffix->id) ? array(
    'id',
  ) : array();
  return drupal_write_record('resp_img_suffix', $resp_img_suffix, $update);
}

/**
 * Load suffix and breakpoint for all suffixes
 */
function resp_img_suffix_load_all_breakpoints() {
  static $widths = array();
  if (empty($widths)) {
    $suffixes = resp_img_suffix_load_all();
    foreach ($suffixes as $suffix) {
      $widths[$suffix->suffix] = (int) $suffix->breakpoint;
    }
    $widths[variable_get('resp_img_default_suffix', '')] = 1;
    arsort($widths);
  }
  return $widths;
}

/**
 * Add cookie support, script and settings
 */
function resp_img_add_js() {
  static $added = FALSE;
  if (!$added) {
    $added = TRUE;
    $settings = array();
    $settings['default_suffix'] = variable_get('resp_img_default_suffix', '');
    $settings['current_suffix'] = resp_img_get_best_suffix();
    $settings['forceRedirect'] = variable_get('resp_img_forceredirect', FALSE);
    $settings['forceResize'] = variable_get('resp_img_forceresize', FALSE);
    $settings['reloadOnResize'] = variable_get('resp_img_reloadonresize', FALSE);
    $settings['useDevicePixelRatio'] = variable_get('resp_img_use_device_pixel_ratio', FALSE);
    $settings['suffixes'] = resp_img_suffix_load_all_breakpoints();
    drupal_add_library('system', 'jquery.cookie');
    drupal_add_js(array(
      'respImg' => $settings,
    ), array(
      'type' => 'setting',
      'weight' => -11,
      'group' => JS_DEFAULT,
    ));
    drupal_add_js(drupal_get_path('module', 'resp_img') . '/resp_img.js', array(
      'type' => 'file',
      'weight' => -10,
      'group' => JS_DEFAULT,
    ));
  }
}

/**
 * Replace suffix if needed / possible
 */
function resp_img_replace_suffix($path) {
  $bestfit_suffix = resp_img_get_best_suffix();
  $default_suffix = variable_get('resp_img_default_suffix', '');
  if (isset($bestfit_suffix) && !empty($bestfit_suffix) && $bestfit_suffix != $default_suffix) {
    $path = str_replace($default_suffix, $bestfit_suffix, $path);
  }
  return $path;
}

/**
 * Determine best match
 */
function resp_img_get_best_suffix() {
  static $bestfit = FALSE;
  if ($bestfit === FALSE && isset($_COOKIE[RESP_IMG_COOKIE]) && is_numeric($_COOKIE[RESP_IMG_COOKIE])) {
    $width = $_COOKIE[RESP_IMG_COOKIE];
    $ratio = _resp_img_get_device_pixel_ratio();
    $width = $width * $ratio;
    $bestfit = variable_get('resp_img_default_suffix', '');
    $widths = resp_img_suffix_load_all_breakpoints();
    foreach ($widths as $k => $v) {
      if ($width >= $v) {
        $bestfit = $k;
        break;
      }
    }
  }
  return $bestfit;
}
function _resp_img_get_device_pixel_ratio() {
  static $ratio = FALSE;
  if ($ratio === FALSE && variable_get('resp_img_use_device_pixel_ratio', FALSE) && isset($_COOKIE[RESP_IMG_RATIO_COOKIE]) && is_numeric($_COOKIE[RESP_IMG_RATIO_COOKIE])) {
    $ratio = $_COOKIE[RESP_IMG_RATIO_COOKIE];
  }
  else {
    $ratio = 1;
  }
  return $ratio;
}

/**
 * Implements hook_theme_registry_alter().
 */
function resp_img_theme_registry_alter(&$theme_registry) {
  foreach ($theme_registry as $key => $info) {
    if ($key == 'image') {
      if (isset($theme_registry[$key]['preprocess functions']) && is_array($theme_registry[$key]['preprocess functions'])) {
        array_unshift($theme_registry[$key]['preprocess functions'], 'resp_img_pp_image');
      }
      else {
        $theme_registry[$key]['preprocess functions'] = array(
          'resp_img_pp_image',
        );
      }
    }
    if ($key == 'field_slideshow') {
      if (isset($theme_registry[$key]['preprocess functions']) && is_array($theme_registry[$key]['preprocess functions'])) {
        array_unshift($theme_registry[$key]['preprocess functions'], 'resp_img_pp_field_slideshow');
      }
      else {
        $theme_registry[$key]['preprocess functions'] = array(
          'resp_img_pp_field_slideshow',
        );
      }
    }
  }
}

/**
 * Support for field_slideshow.
 */
function resp_img_pp_field_slideshow(&$variables) {
  resp_img_add_js();
  if (isset($variables['image_style'])) {
    $variables['image_style'] = resp_img_replace_suffix($variables['image_style']);
  }
  if (isset($variables['items']) && is_array($variables['items'])) {
    foreach ($variables['items'] as $key => $item) {
      if (isset($variables['items'][$key]['path']['path'])) {
        $variables['items'][$key]['path']['path'] = resp_img_replace_suffix($variables['items'][$key]['path']['path']);
      }
    }
  }
}

/**
 * Support for general images.
 */
function resp_img_pp_image(&$variables) {
  resp_img_add_js();
  if (isset($variables['style_name']) && $variables['style_name'] != resp_img_replace_suffix($variables['style_name'])) {
    $variables['style_name'] = resp_img_replace_suffix($variables['style_name']);
    $variables['path'] = resp_img_replace_suffix($variables['path']);
    foreach (array(
      'width',
      'height',
    ) as $key) {
      if (isset($variables[$key])) {
        unset($variables[$key]);
      }
    }
  }
}

/**
 * Alter all links for things like colorbox.
 */
function resp_img_url_outbound_alter(&$path, &$options, $original_path) {
  if (!preg_match('|^/?admin/|', $path)) {
    $path = resp_img_replace_suffix($path);
  }
}

/**
 * Alter all image sources.
 */
function resp_img_file_url_alter(&$uri) {
  $uri = resp_img_replace_suffix($uri);
}

/**
 * Support for purge/expire module.
 * Specific for nginx / barracuda
 * Clears the cache for anonymous users and for the current user
 * Required changes to nginx config files
 * nginx_speed_purge.conf
 *   change fastcgi_cache_purge speed $1$host$request_method$2$is_args$args;
 *   to     fastcgi_cache_purge speed $1$host$2;
 * nginx_advanced_include.conf
 *   change fastcgi_cache_key "$device$host$key_uri$cookie_OctopusCacheID";
 *   to     fastcgi_cache_key "$device$host$key_uri$cookie_OctopusCacheID$cookie_respimg";
 */
function resp_img_expire_cache_alter(&$expire, $node, &$paths) {
  if (variable_get('resp_img_purgeexpire', FALSE)) {
    if (!is_array($expire)) {
      return;
    }

    // make array unique
    $expire = array_unique($expire);

    // add a copy of each path for each defined suffix (using width)
    $extra_paths = array();
    $widths = resp_img_suffix_load_all_breakpoints();
    foreach ($widths as $k => $v) {
      foreach ($expire as $path) {
        $extra_paths[] = $path . $v;

        // if Cache cookie is set add a copy of each path for the current user
        if (isset($_COOKIE['OctopusCacheID'])) {
          $extra_paths[] = $path . $_COOKIE['OctopusCacheID'] . $v;
        }
      }
    }
    $expire = array_merge($expire, $extra_paths);
  }
}

/**
 * Implements hook_form_alter().
 */
function resp_img_form_alter(&$form, &$form_state, $form_id) {
  if ($form_id == 'field_ui_field_edit_form') {
    if ($form['#instance']['widget']['module'] == 'text') {
      $form['resp_img'] = array(
        '#title' => t('Responsive images and styles'),
        '#type' => 'fieldset',
        '#collapsible' => FALSE,
      );
      $form['resp_img']['use_for_resp_img'] = array(
        '#type' => 'checkbox',
        '#title' => t('Apply responsive images and styles to this field'),
        //variable_get('resp_img_*entitytype*_*bundle*_*fieldname*, 0)
        '#default_value' => variable_get('resp_img_' . $form['instance']['entity_type']['#value'] . '_' . $form['instance']['bundle']['#value'] . '_' . $form['instance']['field_name']['#value'], 0),
        '#description' => t('If selected, responsive images and styles will be applied to the content of this field.'),
      );
      $form['#submit'][] = 'resp_img_add_entity_type_field';
    }
  }
}
function resp_img_add_entity_type_field($form, &$form_state) {
  variable_set('resp_img_' . $form['instance']['entity_type']['#value'] . '_' . $form['instance']['bundle']['#value'] . '_' . $form['instance']['field_name']['#value'], $form_state['values']['use_for_resp_img']);
}

/**
 * Implements hook_entity_view_alter().
 */
function resp_img_entity_view_alter(&$build, $type) {
  foreach (element_children($build) as $child) {
    if (isset($build[$child]['#field_name'])) {
      if (variable_get('resp_img_' . $build['#entity_type'] . '_' . $build['#bundle'] . '_' . $build[$child]['#field_name'], 0)) {
        $build[$child]['#post_render'][] = 'resp_img_post_render';
      }
    }
  }
}
function resp_img_post_render($content, $element) {
  return _resp_img_replace($content);
}
function _resp_img_replace($content) {
  $result = array();
  preg_match_all('/<img[^>]+>/i', $content, $result);
  $orig_imgs = $imgs = $result[0];
  $sfx = resp_img_suffix_load_all();
  $suffixes = array();
  foreach ($sfx as $suffix) {
    $suffixes[] = $suffix->suffix;
  }

  // media caches its file urls, so we need to replace all suffixes to the default suffix,
  // before finding the best fitting suffix with resp_img_replace_suffix.
  $imgs = str_replace($suffixes, variable_get('resp_img_default_suffix', ''), $imgs);
  $new_imgs = preg_replace('/(height|width)=("[^"]*")/i', "", $imgs);
  foreach ($new_imgs as &$img) {
    $src = array();
    preg_match('/src=("[^"]*")/i', $img, $src);
    $src = $src[1];
    $new_src = resp_img_replace_suffix($src);
    $img = str_replace($src, $new_src, $img);
  }
  $content = str_replace($orig_imgs, $new_imgs, $content);
  return $content;
}

/**
 * Implements hook_ctools_plugin_api().
 */
function resp_img_ctools_plugin_api($owner, $api) {
  return array(
    'version' => 1,
  );
}

/**
 * Implements hook_context_plugins().
 */
function resp_img_context_plugins() {
  $plugins = array();
  $plugins['resp_img_context_condition_suffix'] = array(
    'handler' => array(
      'path' => drupal_get_path('module', 'resp_img') . '/plugins',
      'file' => 'resp_img_context_condition_suffix.inc',
      'class' => 'resp_img_context_condition_suffix',
      'parent' => 'context_condition',
    ),
  );
  return $plugins;
}

/**
 * Implements hook_context_registry().
 */
function resp_img_context_registry() {
  return array(
    'conditions' => array(
      'resp_img_context_condition_suffix' => array(
        'title' => t('Responsive Images'),
        'plugin' => 'resp_img_context_condition_suffix',
      ),
    ),
  );
}

/**
 * Implements hook_entity_info_alter().
 */
function resp_img_entity_info_alter(&$entity_info) {

  // Support the media module
  $entity_info['file']['view modes']['media_responsive'] = array(
    'label' => t('Responsive'),
    'custom settings' => TRUE,
  );
}

/**
 * Implements hook_block_view_alter().
 */
function resp_img_block_view_alter(&$data, $block) {
  if (variable_get('resp_img_block_enabled', 1) && isset($data['content'])) {
    if (is_string($data['content'])) {
      $data['content'] = _resp_img_replace($data['content']);
    }
    else {
      $data['content']['#post_render'][] = 'resp_img_post_render';
    }
  }
}
function _resp_img_get_suffix() {
  static $suffix = FALSE;
  if ($suffix === FALSE && isset($_COOKIE[RESP_IMG_COOKIE]) && is_numeric($_COOKIE[RESP_IMG_COOKIE])) {
    $width = $_COOKIE[RESP_IMG_COOKIE];
    $suffix = variable_get('resp_img_default_suffix', '');
    $widths = resp_img_suffix_load_all_breakpoints();
    foreach ($widths as $k => $v) {
      if ($width >= $v) {
        $suffix = $k;
        break;
      }
    }
  }
  return $suffix;
}

Functions

Namesort descending Description
resp_img_add_entity_type_field
resp_img_add_js Add cookie support, script and settings
resp_img_block_view_alter Implements hook_block_view_alter().
resp_img_context_plugins Implements hook_context_plugins().
resp_img_context_registry Implements hook_context_registry().
resp_img_ctools_plugin_api Implements hook_ctools_plugin_api().
resp_img_ctools_plugin_directory Implements hook_ctools_plugin_directory()
resp_img_disable Implements hook_disable().
resp_img_enable Implements hook_enable().
resp_img_entity_info_alter Implements hook_entity_info_alter().
resp_img_entity_view_alter Implements hook_entity_view_alter().
resp_img_expire_cache_alter Support for purge/expire module. Specific for nginx / barracuda Clears the cache for anonymous users and for the current user Required changes to nginx config files nginx_speed_purge.conf change fastcgi_cache_purge speed…
resp_img_file_url_alter Alter all image sources.
resp_img_form_alter Implements hook_form_alter().
resp_img_get_best_suffix Determine best match
resp_img_init Implements hook_init().
resp_img_menu Implements hook_menu().
resp_img_post_render
resp_img_pp_field_slideshow Support for field_slideshow.
resp_img_pp_image Support for general images.
resp_img_replace_suffix Replace suffix if needed / possible
resp_img_suffix_load Load a single suffix
resp_img_suffix_load_all Load all suffixes
resp_img_suffix_load_all_breakpoints Load suffix and breakpoint for all suffixes
resp_img_suffix_save Save a single suffix
resp_img_theme_registry_alter Implements hook_theme_registry_alter().
resp_img_url_outbound_alter Alter all links for things like colorbox.
_resp_img_get_device_pixel_ratio
_resp_img_get_suffix
_resp_img_replace