You are here

simplemeta.module in Simple Meta 7.2

SimpleMeta module.

File

simplemeta.module
View source
<?php

/**
 * @file
 * SimpleMeta module.
 */

/**
 * Implements hook_permission().
 */
function simplemeta_permission() {
  return array(
    'administer simplemeta' => array(
      'title' => t('Administer SimpleMeta'),
    ),
  );
}

/**
 * Implements hook_entity_info().
 */
function simplemeta_entity_info() {
  $info = array();
  $info['simplemeta'] = array(
    'label' => t('SimpleMeta'),
    'plural label' => t('SimpleMeta'),
    'entity class' => 'SimplemetaEntity',
    'controller class' => 'EntityAPIController',
    'metadata controller class' => 'SimplemetaEntityMetadataController',
    'module' => 'simplemeta',
    'base table' => 'simplemeta',
    'fieldable' => FALSE,
    'entity keys' => array(
      'id' => 'sid',
    ),
    // We have only one bundle.
    // 'bundles' property can actually be omitted in this case.
    'bundles' => array(
      'simplemeta' => array(
        'label' => t('SimpleMeta'),
      ),
    ),
    'view modes' => array(
      'meta' => array(
        'label' => t('On-page metadata'),
        'custom settings' => FALSE,
      ),
    ),
    'label callback' => 'entity_class_label',
    'uri callback' => 'entity_class_uri',
    'access callback' => 'simplemeta_access',
    'creation callback' => 'simplemeta_create',
    'form callback' => 'simplemeta_form',
    'admin ui' => array(
      'path' => 'admin/content/simplemeta',
      'file' => 'simplemeta.admin.inc',
      'controller class' => 'EntityDefaultUIController',
      'menu wildcard' => '%simplemeta',
    ),
  );
  return $info;
}

/**
 * SimpleMeta entity access callback.
 *
 * @see entity_access()
 */
function simplemeta_access($op, $entity = NULL, $account = NULL) {
  return user_access('administer simplemeta', $account);
}

/**
 * Simplemeta entity creation callback.
 *
 * @see entity_create()
 */
function simplemeta_create($values = array()) {
  return entity_get_controller('simplemeta')
    ->create($values);
}

/**
 * Load multiple SimpleMeta entities.
 *
 * @see entity_load()
 */
function simplemeta_load_multiple($sids = array(), $conditions = array(), $reset = FALSE) {
  return entity_load('simplemeta', $sids, $conditions, $reset);
}

/**
 * Load single SimpleMeta entity.
 *
 * @see entity_load_single()
 */
function simplemeta_load($sid, $reset = FALSE) {
  $entities = simplemeta_load_multiple(array(
    $sid,
  ), array(), $reset);
  return reset($entities);
}

/**
 * Implements hook_flush_caches().
 */
function simplemeta_flush_caches() {
  return array(
    'cache_simplemeta',
  );
}

/**
 * Implements hook_admin_menu_cache_info().
 */
function simplemeta_admin_menu_cache_info() {
  $caches = array(
    'simplemeta' => array(
      'title' => t('SimpleMeta'),
      'callback' => '_simplemeta_flush_cache',
    ),
  );
  return $caches;
}

/**
 * Admin Menu cache flush callback.
 *
 * @see simplemeta_admin_menu_cache_info()
 */
function _simplemeta_flush_cache($name = NULL) {
  cache_clear_all('*', 'cache_simplemeta', TRUE);
  cache_clear_all('simplemeta:info', 'cache');
}

/**
 * Implements hook_menu().
 */
function simplemeta_menu() {
  $items = array();
  $items['admin/content/simplemeta/settings'] = array(
    'title' => 'Settings',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'simplemeta_settings_form',
    ),
    'access arguments' => array(
      'administer simplemeta',
    ),
    'file' => 'simplemeta.admin.inc',
  );
  return $items;
}

/**
 * Implements $module_preprocess_$hook().
 */
function simplemeta_preprocess_html(&$vars) {
  global $language;
  if ($meta = simplemeta_get_page_meta(current_path(), $language->language)) {
    $content = $meta->content;

    // Set page title.
    if (isset($content['title']) && ($rendered = drupal_render($content['title']))) {
      $vars['head_title'] = $rendered;
    }
  }
}

/**
 * Implements hook_page_alter().
 */
function simplemeta_page_alter(&$page) {
  global $language;
  if ($meta = simplemeta_get_page_meta(current_path(), $language->language)) {
    $content = $meta->content;
    unset($content['title']);
    $page['page_bottom']['simplemeta'] = $content;
  }
}

/**
 * Load SimpleMeta entity by path.
 *
 * @param string|array $path
 *   Single path or list of paths.
 * @param string $language
 *   Language code.
 *
 * @return SimplemetaEntity|FALSE
 *   SimplemetaEntity metadata object or FALSE on failure.
 */
function simplemeta_meta_load_by_path($path, $language = '') {
  $query = new EntityFieldQuery();
  $condition = is_array($path) ? 'IN' : '=';
  $query
    ->entityCondition('entity_type', 'simplemeta')
    ->propertyCondition('path', $path, $condition)
    ->propertyCondition('language', $language);
  if ($condition == 'IN') {
    $query
      ->propertyOrderBy('fit', 'DESC');
    $query
      ->range(0, 1);
  }
  $result = $query
    ->execute();
  if (!empty($result['simplemeta'])) {
    $row = reset($result['simplemeta']);
    return entity_load_single('simplemeta', $row->sid);
  }
  return FALSE;
}

/**
 * Get SimpleMeta entity for a page, by path.
 *
 * @param string $path
 *   Path of the page to get metadata for.
 * @param string $language
 *   Language code to get metadata for.
 * @param bool $reset
 *   TRUE to reset static cache.
 *
 * @return SimplemetaEntity|FALSE
 *   SimpleMeta entity if appropriate found, FALSE otherwise.
 */
function simplemeta_get_page_meta($path = NULL, $language = '', $reset = FALSE) {
  static $meta = array();
  if (!isset($path)) {
    $path = current_path();
  }
  if (!isset($meta[$path]) || $reset) {
    $meta[$path] = FALSE;
    $cid = $path . ':' . $language;
    if ($cache = cache_get($cid, 'cache_simplemeta')) {
      $meta[$path] = $cache->data;
    }
    else {
      $original_map = arg(NULL, $path);
      $parts = array_slice($original_map, 0, MENU_MAX_PARTS);
      $ancestors = simplemeta_path_get_ancestors($parts);
      $entity = simplemeta_meta_load_by_path($ancestors, $language);

      // If there is no language-specific meta, try to load language-neutral.
      if (!$entity && $language) {
        $entity = simplemeta_meta_load_by_path($ancestors);
      }
      if ($entity) {

        // @todo Content should probably be added to the entity outside of there.
        $content = $entity
          ->view('meta');
        $entity->content = $content['simplemeta'][$entity->sid];
        cache_set($cid, $entity, 'cache_simplemeta');
        $meta[$path] = $entity;
      }
    }
  }
  return $meta[$path];
}

/**
 * Get path ancestors.
 *
 * Get path ancestors (represented as parts) to find appropriate SimpleMeta
 * entity for the page.
 *
 * @param string[] $parts
 *   An array of path parts; for example,
 *   array('node', '12345', 'edit').
 *
 * @return string[]
 *   List of path ancestors.
 *
 * @see menu_get_ancestors()
 */
function simplemeta_path_get_ancestors($parts) {
  $number_parts = count($parts);
  $ancestors = array();
  $length = $number_parts - 1;
  $end = (1 << $number_parts) - 1;

  // Menu_masks actually takes defined menu paths (via hook_menu()
  // implementation) into account.
  // @todo function probably should return list of all possible ancestors (but it's a bigger list actually)
  $masks = variable_get('menu_masks');

  // If the optimized menu_masks array is not available use brute force to get
  // the correct $ancestors and $placeholders returned. Do not use this as the
  // default value of the menu_masks variable to avoid building such a big
  // array.
  if (!$masks) {
    $masks = range(511, 1);
  }

  // Only examine patterns that actually exist as router items (the masks).
  foreach ($masks as $i) {
    if ($i > $end) {

      // Only look at masks that are not longer than the path of interest.
      continue;
    }
    elseif ($i < 1 << $length) {

      // We have exhausted the masks of a given length, so decrease the length.
      --$length;
    }

    // Path patterns which have less parts than original path must end with %
    // this also includes shorter paths without %.
    if ($length < $number_parts - 1 && $i & 1) {
      continue;
    }
    $current = '';
    for ($j = $length; $j >= 0; $j--) {

      // Check the bit on the $j offset.
      if ($i & 1 << $j) {

        // Bit one means the original value.
        $current .= $parts[$length - $j];
      }
      else {

        // Bit zero means means wildcard.
        $current .= '%';
      }

      // Unless we are at offset 0, add a slash.
      if ($j) {
        $current .= '/';
      }
    }
    $ancestors[] = $current;
  }
  return $ancestors;
}

/**
 * Helper function. Calculate how much specific the path is.
 *
 * @param string $path
 *   Page path to calculate a fit for.
 *
 * @return int
 *   A numeric representation of how specific the path is.
 */
function _simplemeta_meta_calculate_fit($path) {
  $fit = 0;
  $parts = explode('/', $path, MENU_MAX_PARTS);
  $number_parts = count($parts);
  $slashes = $number_parts - 1;
  foreach ($parts as $k => $part) {
    if ($part != '%') {
      $fit |= 1 << $slashes - $k;
    }
  }
  return $fit;
}

/**
 * Helper function. Get available languages options.
 *
 * @return array
 *   Array of languages labels keyed by language codes. Empty string key
 *   means language-neutral.
 *
 * @see language_list()
 */
function _simplemeta_language_list() {
  $languages = language_list();
  $options = array();
  foreach ($languages as $language) {
    $options[$language->language] = $language->name;
  }
  $options = array(
    '' => t('- Language neutral -'),
  ) + $options;
  return $options;
}

Functions

Namesort descending Description
simplemeta_access SimpleMeta entity access callback.
simplemeta_admin_menu_cache_info Implements hook_admin_menu_cache_info().
simplemeta_create Simplemeta entity creation callback.
simplemeta_entity_info Implements hook_entity_info().
simplemeta_flush_caches Implements hook_flush_caches().
simplemeta_get_page_meta Get SimpleMeta entity for a page, by path.
simplemeta_load Load single SimpleMeta entity.
simplemeta_load_multiple Load multiple SimpleMeta entities.
simplemeta_menu Implements hook_menu().
simplemeta_meta_load_by_path Load SimpleMeta entity by path.
simplemeta_page_alter Implements hook_page_alter().
simplemeta_path_get_ancestors Get path ancestors.
simplemeta_permission Implements hook_permission().
simplemeta_preprocess_html Implements $module_preprocess_$hook().
_simplemeta_flush_cache Admin Menu cache flush callback.
_simplemeta_language_list Helper function. Get available languages options.
_simplemeta_meta_calculate_fit Helper function. Calculate how much specific the path is.