You are here

power_menu.module in Power Menu 7.2

Same filename and directory in other branches
  1. 6 power_menu.module
  2. 7 power_menu.module

File

power_menu.module
View source
<?php

/**
 * @file
 * Allows to set active menu items based on several plugins. Also can provide additional fields on every menu entry.
 */
include_once 'includes/views.inc';

/**
 * Implements hook_permission().
 */
function power_menu_permission() {
  return array(
    'administer power menu' => array(
      'title' => t('Administer power menu configuration'),
    ),
  );
}

/**
 * Implements hook_menu().
 */
function power_menu_menu() {
  $items['admin/config/search/power_menu'] = array(
    'title' => 'Power Menu configuration',
    'description' => 'Configure power menu plugins.',
    'access arguments' => array(
      'administer power menu',
    ),
    'page arguments' => array(
      'power_menu_configuration_form',
    ),
    'page callback' => 'drupal_get_form',
    'file' => 'power_menu.admin.inc',
  );
  $items['admin/config/search/power_menu/handler'] = array(
    'title' => 'Menu handlers',
    'type' => MENU_DEFAULT_LOCAL_TASK,
    'weight' => -1,
  );
  $items['admin/config/search/power_menu/handler/edit/%'] = array(
    'title' => 'Power Menu configuration',
    'description' => 'Configure power menu plugin.',
    'access arguments' => array(
      'administer power menu',
    ),
    'page arguments' => array(
      'power_menu_configuration_handler_form',
      6,
    ),
    'page callback' => 'drupal_get_form',
    'type' => MENU_NORMAL_ITEM,
    'file' => 'power_menu.admin.inc',
  );
  $items['admin/config/search/power_menu/fields'] = array(
    'title' => 'Menu fields',
    'description' => 'Configure power menu fields.',
    'access arguments' => array(
      'administer power menu',
    ),
    'page arguments' => array(
      'power_menu_fields_configuration_form',
    ),
    'page callback' => 'drupal_get_form',
    'type' => MENU_LOCAL_TASK,
    'file' => 'power_menu.admin.inc',
    'weight' => 0,
  );
  return $items;
}

/**
 * Implements hook_menu_alter().
 */
function power_menu_menu_alter(&$items) {
  $menus = variable_get('power_menu_fields_menus', array());
  foreach ($menus as $key => $value) {
    $value = power_menu_create_machine_name($value);

    // Hide the field diplay
    $items['admin/config/search/power_menu/fields/' . $value . '/fields']['type'] = MENU_CALLBACK;
    $items['admin/config/search/power_menu/fields/' . $value . '/display']['type'] = MENU_CALLBACK;
  }
}

/**
 * Implements hook_help().
 */
function power_menu_help($path, $arg) {
  switch ($path) {
    case 'admin/config/search/power_menu':
      $output = '<p>' . t('The power menu allows you to set active menu items based on several plugins. This is mainly necessary when nodes not "connected" with a menu item. The power menu also provides fields for every menu entry.') . '</p>';
      $output .= '<p>' . t('On this settings page, you can define in which order the menu handler should process.') . '</p>';
      return $output;
    case 'admin/config/search/power_menu/fields':
      $output = '<p>' . t('The power menu allows you to set active menu items based on several plugins. This is mainly necessary when nodes not "connected" with a menu item. The power menu also provides fields for every menu entry.') . '</p>';
      $output .= '<p>' . t('On this settings page, you can define which menu should have fields.') . '</p>';
      return $output;
  }
}

/**
 * Implements hook_theme().
 */
function power_menu_theme() {
  return array(
    'power_menu_plugins_order' => array(
      'render element' => 'element',
      'file' => 'power_menu.admin.inc',
    ),
  );
}

/**
 * Implements hook_ctools_plugin_type() to inform the plugin system that the
 * Power Menu owns menu_handlers plugin type.
 *
 * All of these are empty because the defaults all work.
 */
function power_menu_ctools_plugin_type() {
  return array(
    'menu_handlers' => array(
      'classes' => array(
        'handler',
      ),
    ),
  );
}

/**
 * Compare the weigth of the plugins
 */
function power_menu_handlers_weight_compare($a, $b) {
  if ($a['weight'] == $b['weight']) {
    return 0;
  }
  return $a['weight'] < $b['weight'] ? -1 : 1;
}

/**
 * Shortcut function to get menu_handlers plugins. The handlers are sorted by the module settings.
 *
 * @param $only_enabled
 *   Is this parameter set to TRUE, only enabled menu_handlers returned.
 * @return
 *   An array of available menu_handlers
 */
function power_menu_get_menu_handlers($only_enabled = FALSE) {
  ctools_include('plugins');
  $handlers = ctools_get_plugins('power_menu', 'menu_handlers');
  $ordered_handlers = array();
  $settings = variable_get('power_menu_handlers_settings', array());

  // Sort handlers by settings weight
  uasort($settings, 'power_menu_handlers_weight_compare');

  // Sort available handlers based on settings array and merge with new handler plugins
  foreach ($settings as $key => $value) {
    if ((!$only_enabled || $value['enabled']) && !empty($handlers[$key])) {
      $ordered_handlers[$key] = $handlers[$key];
    }
    unset($handlers[$key]);
  }
  if ($only_enabled) {
    return $ordered_handlers;
  }
  else {
    return array_merge($ordered_handlers, $handlers);
  }
}

/**
 * Implements hook_ctools_plugin_directory() to let the system know
 * where our plugins are.
 */
function power_menu_ctools_plugin_directory($owner, $plugin_type) {
  if ($owner == 'power_menu') {
    return 'plugins/' . $plugin_type;
  }
}

/**
 * Implements hook_ctools_render_alter().
 *
 * When we use CTools Pagemanager, hook_nodeapi (view) is not being called, because ctools alters the
 * hook_menu and redirects the page callback to it's own function in node_view.inc Well, power_menu
 * never knows that a node is actually being displayed -> so we alter the ctools_render function and
 * start the normal power_menu_nodeapi procedure
 */

/*
function power_menu_ctools_render_alter($info, $page, $args, $contexts, $task, $subtask) {
  if (!empty($task['admin path']) && $task['admin path'] == 'node/%node' && $page) {
    power_menu_nodeapi($contexts['argument_nid_1']->data, 'view', NULL, $page);
  }
}
*/

/**
 * Implements hook_entity_view().
 */
function power_menu_entity_view($entity, $type, $view_mode, $langcode) {

  // TODO: Add aditional test, that the function is only called on the main entity. At the moment the function is called as many entities shown in full mode (e.g. comments on a full node view)
  // Power menu sets active menu only on full or defined view modes and enabled handlers
  $defined_view_modes = variable_get('power_menu_view_mode', 'full');

  // Is it an array with multiple view modes
  if (is_array($defined_view_modes)) {
    $set_path = in_array($view_mode, $defined_view_modes) ? TRUE : FALSE;
  }
  else {
    $set_path = $view_mode == $defined_view_modes ? TRUE : FALSE;
  }
  if ($set_path && variable_get('power_menu_handlers_enabled', FALSE)) {
    power_menu_set_path($entity, $type, $langcode);
  }
}

/**
 * Sets the system path to use for the active menu trail.
 *
 * @param $entity
 *   The entity
 * @param $type
 *   The entity type
 * @param $langcode
 *   The language code
 *
 * @return
 *   The system path
 */
function power_menu_set_path($entity, $type, $langcode) {

  // TODO: Implement cache_clear when forms submitted!
  $path = power_menu_get_path($entity, $type);

  // Is the path set to <front>, do only activate the item
  if ($path == '<front>') {
    $path = variable_get('site_frontpage', 'node');
    menu_set_active_item($path);
  }
  elseif (preg_match('/^<[A-Za-z0-9]*>$/', $path)) {

    // Do not set a path on special menu items like <nolink> ...
    // This items mostly used on multiple menu-items and in this case
    // Power Menu could/would activate the wrong.
  }
  else {

    // Set the path for evey selected menu in the power_menu settings
    foreach (variable_get('power_menu_handlers_menus', array()) as $menu_name) {

      // The official way to set the active path
      menu_tree_set_path($menu_name, $path);
    }

    // TODO: Cache the breadcrumbs
    // Set the breadcrumb when is activated in settings and a path is set
    if (variable_get('power_menu_handlers_breadcrumb', TRUE) && isset($path)) {
      $breadcrumbs = power_menu_get_breadcrumbs($path);

      // Add title only a title filed exists
      if (variable_get('power_menu_handlers_breadcrumb_title', FALSE) && !empty($entity->title)) {
        $breadcrumbs[] = $entity->title;
      }
      drupal_set_breadcrumb($breadcrumbs);
    }
  }
  return $path;
}

/**
 * Gets the system path for the current page.
 *
 * @param $entity
 *   The entity
 * @param $type
 *   The entity type
 * @param $defined_path
 *   Define a specific path to get the current page path
 * @param $use_cache
 *   Get the cached path.
 *
 * @return
 *   The system path
 */
function power_menu_get_path($entity, $type, $defined_path = NULL, $use_cache = TRUE) {

  // The cache key is the entity uri
  $uri = entity_uri($type, $entity);
  global $language;
  $cache_key = "handler:{$language->language}:{$uri['path']}";
  $cached_path = cache_get($cache_key, 'cache_power_menu');
  $path = $use_cache && $cached_path ? $cached_path->data : FALSE;
  if (!$path) {

    // Get the active menu item
    $router_item = menu_get_item($defined_path);
    if (!$router_item) {
      return $path;
    }

    // Get the alias for given item to use
    $alias = drupal_get_path_alias($router_item['href']);

    // Call all enabled plugins except a plugin changed the router information
    foreach (power_menu_get_menu_handlers(TRUE) as $handler) {
      $instance = power_menu_plugin_get_handler_instance($handler);
      if ($instance) {
        $path = $instance
          ->getMenuPathToActivate($entity, $type, $router_item, $alias);
        if (!empty($path)) {

          // Is a path set, do not loop over the next plugins
          break;
        }
      }
    }
    cache_set($cache_key, $path, 'cache_power_menu');
    return $path;
  }
  return $path;
}

/**
 * Creates an instance for given handler configuration.
 *
 * @param array $handler
 *   The handler definition.
 *
 * @return
 *   The class instance which implements the PowerMenuHandlerInterface or FALSE if no instance created.
 *
 */
function power_menu_plugin_get_handler_instance($handler) {
  $class_name = ctools_plugin_get_class($handler, 'handler');

  // Plugin class found?
  if ($class_name) {
    $instance = new $class_name();

    // Has the class implemented the PowerMenuHandlerInterface interface
    if ($instance instanceof PowerMenuHandlerInterface) {
      return $instance;
    }
  }
  return FALSE;
}

/**
 * Creates an instance for given handler name.
 *
 * @param array $handler_name
 *   The name of the handler.
 *
 * @return
 *   The class instance which implements the PowerMenuHandlerInterface or FALSE if no instance created.
 *
 */
function power_menu_plugin_get_handler_instance_by_name($handler_name) {
  $handlers = power_menu_get_menu_handlers();
  if (!empty($handlers[$handler_name])) {
    $handler = $handlers[$handler_name];
    return power_menu_plugin_get_handler_instance($handler);
  }
  return FALSE;
}

/**
 * Constructs the breadcrumb for given path. This works only, when the path is used in e menu link.
 *
 * @param $path
 *   The system path to get the breadcrumb for.
 * @return
 *   The populated breadcrumb array.
 */
function power_menu_get_breadcrumbs($path) {
  $crumbs = array(
    l(t('Home'), '<front>'),
  );
  $menu = db_select('menu_links', 'ml')
    ->fields('ml', array(
    'menu_name',
  ))
    ->condition('ml.link_path', $path, '=')
    ->execute()
    ->fetchField();
  if ($menu) {
    $tree = menu_tree_page_data($menu);

    // Use translated menu items
    if (function_exists('i18n_menu_localize_tree')) {
      $tree = i18n_menu_localize_tree($tree);
    }
    _power_menu_recurse_crumbs($tree, $path, $crumbs);
  }
  return $crumbs;
}

/**
 *  Recursively loop ober the menu tree to get the breadcrumbs.
 */
function _power_menu_recurse_crumbs($tree, $path, &$crumbs, $above = array()) {
  foreach ($tree as $menu_item) {
    if (!$menu_item['link']['in_active_trail']) {
      continue;
    }
    if ($menu_item['link']['link_path'] == $path) {
      foreach ($above as $trail_item) {
        $crumbs[] = l($trail_item['link']['title'], $trail_item['link']['link_path']);
      }
      $crumbs[] = l($menu_item['link']['title'], $menu_item['link']['link_path']);
      break;
    }
    if (is_array($menu_item['below'])) {
      _power_menu_recurse_crumbs($menu_item['below'], $path, $crumbs, array_merge($above, array(
        $menu_item,
      )));
    }
  }
}

/**
 * Implements hook_form_ID_alter().
 *
 * We are going to alter the form for editing a menu item and are going to add
 * some additional fields.
 */
function power_menu_form_menu_edit_item_alter(&$form, &$form_state) {
  $mlid = $form['mlid']['#value'];

  // Is it a new menu link, get the menu name from the arguments
  if ($mlid) {
    $menu_link = menu_link_load($mlid);
    $menu_name = $menu_link['menu_name'];
  }
  else {

    // A new menu link is created
    $menu_name = $form['original_item']['#value']['menu_name'];

    // Set mlid to NULL in case 0 is used for the menu overview entity
    $mlid = NULL;
  }

  // Add handler fields only when the  menu is defined as a power menu
  $menus = variable_get('power_menu_handlers_menus', array());
  if (in_array($menu_name, $menus)) {
    $handlers = power_menu_get_menu_handlers(TRUE);
    if ($handlers) {
      foreach ($handlers as $handler) {
        $instance = power_menu_plugin_get_handler_instance($handler);
        if ($instance) {
          $handler_form = $instance
            ->menuFormAlter($form, $form_state);

          // Add additional form elements from handler
          if (is_array($handler_form)) {
            $form['power_menu']['handlers'][$handler['name']] = array(
              '#type' => 'fieldset',
              '#title' => t($handler['title']),
              '#collapsible' => TRUE,
              '#collapsed' => FALSE,
            );
            $form['power_menu']['handlers'][$handler['name']]['sa'] = $handler_form;
          }
        }
      }

      // Show fieldset only when some handler has added form elements
      if (!empty($form['power_menu']['handlers'])) {
        $form['#submit'][] = 'power_menu_form_menu_edit_item_handlers_submit';
        $form['#validate'][] = 'power_menu_form_menu_edit_item_handlers_validate';
        $form['power_menu']['handlers']['#type'] = 'fieldset';
        $form['power_menu']['handlers']['#title'] = t('Power Menu Handlers');
        $form['power_menu']['handlers']['#collapsible'] = TRUE;
        $form['power_menu']['handlers']['#collapsed'] = FALSE;
      }
    }
  }

  // Add menu field entity fields
  power_menu_add_fields_entity_fields($menu_name, $mlid, $form, $form_state);
}

/**
 * Implements hook_form_ID_alter().
 *
 * We are going to alter the form so that a user can set default properties.
 * Default properties are used incase no properties are found on menu items.
 *
 */
function power_menu_form_menu_overview_form_alter(&$form, &$form_state) {

  // Atach menu field entity fields.
  power_menu_add_fields_entity_fields($form['#menu']['menu_name'], 0, $form, $form_state);
}

/**
 * Implements hook_menu_link_delete().
 */
function power_menu_menu_link_delete($link) {
  $args = array(
    $link,
  );
  _power_menu_call_handler_function('menuLinkDelete', $args);

  // Cleanup power_menu fields for deleted menu_links
  $id = power_menu_get_fields_entity_id_by_mlid($link['mlid']);
  if ($id) {
    entity_delete('power_menu_fields', $id);
  }
}

/**
 * Implements hook_menu_delete():
 */
function power_menu_menu_delete($menu) {

  // Cleanup power_menu fields for deleted menus
  $id = power_menu_get_fields_entity_id_by_menu($menu['menu_name']);
  if ($id) {
    entity_delete('power_menu_fields', $id);
  }
}

/**
 * Add the power menu field entity to the given form.
 */
function power_menu_add_fields_entity_fields($menu_name, $mlid, &$form, &$form_state) {

  // Create bundle name for the given menu name
  $bundle_name = power_menu_create_machine_name($menu_name);

  // Check is this field selected for menu fields
  $selected_menus = variable_get('power_menu_fields_menus', array());

  // Check is this menu selected for fieldable
  if (in_array($menu_name, $selected_menus)) {
    $form['#submit'][] = 'power_menu_form_menu_edit_fields_submit';
    $form['#validate'][] = 'power_menu_form_menu_edit_fields_validate';

    // Add Power Menu fields
    $form['power_menu']['fields'] = array(
      '#type' => 'fieldset',
      '#title' => t('Power Menu fields'),
      '#collapsible' => TRUE,
      '#collapsed' => FALSE,
      '#tree' => TRUE,
      '#parents' => array(
        'power_menu',
        'fields',
      ),
    );

    // Load entity id for this menu link
    $query = new EntityFieldQuery();
    $query
      ->entityCondition('entity_type', 'power_menu_fields')
      ->propertyCondition('mlid', $mlid)
      ->propertyCondition('menu_name', $bundle_name);
    $result = $query
      ->execute();

    // Is no entity found, create a new
    if (empty($result)) {
      $entity = entity_create('power_menu_fields', array(
        'menu_name' => $bundle_name,
        'mlid' => $mlid,
      ));
    }
    else {
      $entity_nid = array_keys($result['power_menu_fields']);
      $entity = entity_load('power_menu_fields', $entity_nid);
      $entity = reset($entity);
    }

    // Set the correct parents for the attached field values, because they added to a fieldset
    $form['#parents'] = array(
      'power_menu',
      'fields',
    );

    // Add entity fields
    field_attach_form('power_menu_fields', $entity, $form['power_menu']['fields'], $form_state);

    // Add entity to form
    $form['power_menu']['fields']['entity'] = array(
      '#type' => 'value',
      '#value' => $entity,
    );
  }
}

/**
 * Attached menu form validate callback.
 *
 * Callback function when menu_edit_item form is being validated.
 */
function power_menu_form_menu_edit_item_handlers_validate(&$form, &$form_state, $form_id = NULL) {
  $args = array(
    &$form,
    &$form_state,
  );
  _power_menu_call_handler_function('menuFormValidate', $args, TRUE);
}

/**
 * Attached menu form submit callback.
 *
 * Callback function when menu_edit_item form is being submitted.
 */
function power_menu_form_menu_edit_item_handlers_submit($form, &$form_state) {
  $args = array(
    $form,
    &$form_state,
  );
  _power_menu_call_handler_function('menuFormSubmit', $args, TRUE);
}

/**
 * Attached menu entity fields validation callback.
 *
 * Callback function when menu or menu link forms validated.
 */
function power_menu_form_menu_edit_fields_validate(&$form, &$form_state, $form_id = NULL) {
}

/**
 * Attached menu entity fields submit callback.
 *
 * Callback function when menu or menu link forms submitted.
 */
function power_menu_form_menu_edit_fields_submit($form, &$form_state) {

  // Fields relevant processing.
  // Is no entity added, no field processing necessary
  if (isset($form_state['values']['power_menu']['fields']['entity'])) {

    // Get and save the entity
    $entity = $form_state['values']['power_menu']['fields']['entity'];

    // Unset the 'menu_name' because this is a value from the core menu field and overwrites in entity_form_submit_build_entity()
    // the power_menu_fields bundle name also called 'menu_name'!
    unset($form_state['values']['menu_name']);
    entity_form_submit_build_entity('power_menu_fields', $entity, $form, $form_state);
    $entity
      ->save();

    // Clear cache for given path or the default entry
    if (isset($form_state['values']['link_path'])) {
      cache_clear_all('fields:' . $form_state['values']['link_path'], 'cache_power_menu');
    }
    elseif ($entity->mlid == 0) {
      cache_clear_all('fields:/', 'cache_power_menu');
    }

    // Clear cache for the defined menu link
    if (isset($form_state['values']['mlid'])) {
      cache_clear_all('fields:mlid:' . $form_state['values']['mlid'], 'cache_power_menu');
    }

    // Clear block cache
    cache_clear_all('power_menu:power_menu_field_display', 'cache_block', TRUE);
  }
}

/**
 * Helper function to call a function in all registred handler objects.
 *
 * @param $function
 *   Function to call in handler object
 * @param $args
 *   The parameters to be passed to the callback, as an indexed array.
 * @param $only_enabled
 *   When TRUE, call only enabled handlers
 */
function _power_menu_call_handler_function($function, &$args, $only_enabled = FALSE) {
  $handlers = power_menu_get_menu_handlers($only_enabled);
  foreach ($handlers as $handler) {
    $instance = power_menu_plugin_get_handler_instance($handler);
    if ($instance) {
      call_user_func_array(array(
        &$instance,
        $function,
      ), $args);
    }
  }
}

/**
 * Get all entity bundles with an uri callback
 *
 * @return array
 *   An array with 'entity_key|bundle_key' as key and 'entity_label : bundle_lable' as value.
 */
function power_menu_get_entities_and_bundles() {
  $entity_infos = entity_get_info();
  $bundles = array();
  foreach ($entity_infos as $entity_key => $entity) {

    // Ignore entities with no uri callback
    if (empty($entity['uri callback'])) {
      continue;
    }
    foreach ($entity['bundles'] as $bundle_key => $bundle) {
      $bundles[$entity_key . '|' . $bundle_key] = $entity['label'] . ' : ' . $bundle['label'];
    }
  }
  return $bundles;
}

/**
 * Implementation of hook_flush_caches()
 */
function power_menu_flush_caches() {
  return array(
    'cache_power_menu',
  );
}

/**
 * Implements hook_entity_info().
 */
function power_menu_entity_info() {

  // Add a bundle for every activated menu in the fields settings
  $menus = variable_get('power_menu_fields_menus', array());
  $bundles = array();
  foreach ($menus as $key => $value) {

    // Allways use underscores for menu key hyphens, because hyphens are not allowed for bundle names.
    $value = power_menu_create_machine_name($value);
    $bundles[$value] = array(
      'admin' => array(
        'path' => 'admin/config/search/power_menu/fields/' . $value,
        'access arguments' => array(
          'administer power menu',
        ),
      ),
      'label' => $value,
    );
  }
  $info['power_menu_fields'] = array(
    'label' => t('Power Menu fields'),
    'controller class' => 'EntityAPIController',
    'base table' => 'power_menu_fields',
    'uri callback' => 'entity_class_uri',
    'fieldable' => TRUE,
    'entity keys' => array(
      'id' => 'id',
      'bundle' => 'menu_name',
    ),
    'bundle keys' => array(
      'bundle' => 'menu_name',
    ),
    'bundles' => $bundles,
    // Additional entity API keys
    'entity class' => 'Entity',
    'module' => 'power_menu',
  );
  return $info;
}

/**
 * Gets the Power Menu Fileds entity for given path
 *
 * @param $path
 *  The system path to search for the fields entity. Is no path set, the system path is used. To get the default element use '/' as value for $path.
 * @param $fallback
 *  Is set to TRUE, the default entity is returned when no entity is retrived from defined path.
 * @param string $menu_name
 *   The menu name to retrive the default menu field entity from
 * @return
 *   The entity or NULL is no entity found for the given path
 */
function power_menu_get_fields_entity($path = NULL, $fallback = TRUE, $menu_name = 'main-menu') {
  $menu_name_orig = $menu_name;
  $menu_name = power_menu_create_machine_name($menu_name);

  // Is no path set, use the current sytsem path
  if (!isset($path)) {
    $path = implode('/', arg());
  }

  // The cache is used to store the resolved menu item path from power menu for given system path.
  // With this mechanism it is not necessary to store the field entity for every system path
  $cache_path_key = 'path:' . $path;
  $cached_path = cache_get($cache_path_key, 'cache_power_menu');
  $lookup_path = $cached_path ? $cached_path->data : $path;

  // Loaded menu field entities also stored in cache. Get it.
  $cache_key = 'fields:' . $lookup_path;
  $entity = cache_get($cache_key, 'cache_power_menu');
  $entity = $entity ? $entity->data : NULL;

  // Is the entity not cached, load it
  if (!$entity) {

    // Lookup for the default menu field entity?
    if ($lookup_path == '/' && $fallback) {
      $id = power_menu_get_fields_entity_id_by_menu($menu_name);
    }
    else {

      // Is the defined path the front page, get <front> as search condition
      if (variable_get('site_frontpage', 'node') == $lookup_path) {
        $lookup_path = '<front>';
      }

      // Get the menu link from given path
      $query = db_select('power_menu_fields', 'pmf');
      $query
        ->leftJoin('menu_links', 'ml', 'pmf.mlid = ml.mlid');
      $id = $query
        ->fields('pmf', array(
        'id',
      ))
        ->condition('ml.link_path', $lookup_path)
        ->condition('ml.menu_name', $menu_name_orig)
        ->execute()
        ->fetchField();
    }

    // No element found, lookup for the default entry
    if (!$id && $fallback && $lookup_path != '/') {
      $entity = power_menu_get_fields_entity('/', TRUE, $menu_name);
      $lookup_path = '/';
    }
    elseif ($id) {
      $entity = entity_load('power_menu_fields', array(
        $id,
      ));

      // Return only the entity and not an array
      $entity = $entity ? array_pop($entity) : NULL;
    }
    cache_set($cache_path_key, $lookup_path, 'cache_power_menu');
    cache_set('fields:' . $lookup_path, $entity, 'cache_power_menu');
  }
  return $entity;
}

/**
 * Implements hook_block_info().
 */
function power_menu_block_info() {
  $blocks = array();
  $blocks['power_menu_field_display'] = array(
    'info' => t('Power Menu field display'),
    'cache' => DRUPAL_CACHE_PER_PAGE,
  );
  return $blocks;
}

/**
 * Implements hook_block_configure().
 */
function power_menu_block_configure($delta) {
  $form = array();
  switch ($delta) {
    case 'power_menu_field_display':
      $menus = menu_get_menus();
      $entity_info = entity_get_info('power_menu_fields');
      $view_modes = array(
        'default' => t('Default'),
      );
      foreach ($entity_info['view modes'] as $key => $view_mode) {
        $view_modes[$key] = $view_mode['label'];
      }
      $form['power_menu_fields_menu'] = array(
        '#type' => 'select',
        '#title' => t('Display Menu'),
        '#default_value' => variable_get('power_menu_field_display_block_menu', 'main-menu'),
        '#options' => $menus,
        '#description' => t('Select the menu from which the <a href="/admin/config/search/power_menu/fields">display</a> should be used.'),
      );
      $form['power_menu_fields_view_mode'] = array(
        '#type' => 'select',
        '#title' => t('Display View mode'),
        '#default_value' => variable_get('power_menu_field_display_block_view_mode', 'default'),
        '#options' => $view_modes,
        '#description' => t('Select the view mode which should be used to render the Power Menu field entity.'),
      );
  }
  return $form;
}

/**
 * Implements hook_block_save().
 */
function power_menu_block_save($delta, $edit) {
  switch ($delta) {
    case 'power_menu_field_display':
      variable_set('power_menu_field_display_block_menu', $edit['power_menu_fields_menu']);
      variable_set('power_menu_field_display_block_view_mode', $edit['power_menu_fields_view_mode']);
  }
}

/**
 * Implements hook_block_view().
 */
function power_menu_block_view($delta = '') {
  $block = array();
  switch ($delta) {
    case 'power_menu_field_display':
      $content = '';
      $field_entity = power_menu_get_fields_entity(NULL, TRUE, variable_get('power_menu_field_display_block_menu', 'main-menu'));
      if ($field_entity) {
        $content = entity_view('power_menu_fields', array(
          $field_entity,
        ), variable_get('power_menu_field_display_block_view_mode', 'default'), NULL, TRUE);
      }
      $block['content'] = $content;
      break;
  }
  return $block;
}

/**
 * Gets the Power Menu Fields entity for given Menu Link ID
 *
 * @param $mlid
 *  The Menu Link ID to search for the fields entity.
 * @return
 *   The entity or NULL is no entity found for the given Menu Link ID
 */
function power_menu_get_fields_entity_by_mlid($mlid) {
  $cache_key = 'fields:mlid:' . $mlid;
  $entity = cache_get($cache_key, 'cache_power_menu');
  $entity = $entity ? $entity->data : NULL;

  // Is the entity not cached, load it
  if (!$entity) {

    // Get the menu link from given mlid
    $id = power_menu_get_fields_entity_id_by_mlid($mlid);
    if ($id) {
      $entity = entity_load('power_menu_fields', array(
        $id,
      ));

      // Return only the entity and not an array
      $entity = $entity ? array_pop($entity) : NULL;
    }
    cache_set($cache_key, $entity, 'cache_power_menu');
  }
  return $entity;
}

/**
 * Returns the power_menu fields entity id for given menu link id (mlid).
 *
 * @param $mlid
 *  The menu link id
 * @return
 *  The power_menu field entity id or FALSE is no entity found for this mlid
 */
function power_menu_get_fields_entity_id_by_mlid($mlid) {
  $query = db_select('power_menu_fields', 'pmf');
  $id = $query
    ->fields('pmf', array(
    'id',
  ))
    ->condition('pmf.mlid', $mlid)
    ->execute()
    ->fetchField();
  return $id;
}

/**
 * Returns the power_menu fields entity id for given menu (menu name).
 *
 * @param $menu_name
 *  The menu machine name
 * @return
 *  The power_menu field entity id or FALSE is no entity found for this menu name
 */
function power_menu_get_fields_entity_id_by_menu($menu_name) {
  $bundle_name = power_menu_create_machine_name($menu_name);
  $id = db_select('power_menu_fields', 'pmf')
    ->fields('pmf', array(
    'id',
  ))
    ->condition('pmf.mlid', 0)
    ->condition('pmf.menu_name', $bundle_name)
    ->execute()
    ->fetchField();
  return $id;
}

/**
 * Implements hook_features_pipe_COMPONENT_alter().
 */
function power_menu_features_pipe_field_alter(&$pipe, $data, $export) {

  // Add a dependency to power_menu when Power Menu fields exported to Features
  foreach ($data as $identifier) {
    if (strpos($identifier, 'power_menu_fields') === 0) {
      $pipe['dependencies'][] = 'power_menu';
      break;
    }
  }
}

/**
 * Creates a machine name from given string.
 *
 * At the moment, it replaces all hyphens with underscores.
 *
 * @param $value
 *   The string to use as machine names
 * @return
 *   The machine name
 */
function power_menu_create_machine_name($value) {
  return $value = str_replace('-', '_', $value);
}

/**
 * Implements hook_form_FORMID_alter().
 *
 * Append the menu-link info for the editors.
 *
 * We can't add additional columns to the taxonomy_overview_terms theme function and we
 * don't want to "copy" the code to add an additional column. That's the reason why we
 * add the information as additional markup to the term-name.
 */
function power_menu_form_taxonomy_overview_terms_alter(&$form, &$form_state) {
  $show_info = variable_get('power_menu_taxonomy_show_menu_link_info', FALSE);
  $vocabulary = variable_get('power_menu_taxonomy_vocabulary', array(
    'vid' => NULL,
    'machine_name' => NULL,
  ));

  // Is it the defined navigation taxonomy
  if ($show_info && isset($form['#vocabulary']->vid) && $form['#vocabulary']->vid == $vocabulary['vid']) {
    $terms = variable_get('power_menu_taxonomy_terms', array());
    foreach ($form as &$value) {
      if (is_array($value) && isset($value['#term']['name'])) {
        $tid = $value['#term']['tid'];
        if (array_key_exists($tid, $terms)) {

          // Change the render array, that we can append additional information
          $value['view']['link'] = $value['view'];
          unset($value['view']['#type']);
          $menu_link = menu_link_load($terms[$tid]);
          $title = l($menu_link['link_title'], $menu_link['link_path']);
          $title = strlen($title) != 0 ? $title : $menu_link['title'];
          $options = array(
            '!title' => $title,
            '!edit' => l(t('edit'), 'admin/structure/menu/item/' . $menu_link['mlid'] . '/edit'),
          );
          $value['view']['menu_information']['#type'] = 'markup';
          $value['view']['menu_information']['#markup'] = ' - ' . t('Associated menu link: !title (!edit)', $options);
        }
      }
    }
  }
}

Functions

Namesort descending Description
power_menu_add_fields_entity_fields Add the power menu field entity to the given form.
power_menu_block_configure Implements hook_block_configure().
power_menu_block_info Implements hook_block_info().
power_menu_block_save Implements hook_block_save().
power_menu_block_view Implements hook_block_view().
power_menu_create_machine_name Creates a machine name from given string.
power_menu_ctools_plugin_directory Implements hook_ctools_plugin_directory() to let the system know where our plugins are.
power_menu_ctools_plugin_type Implements hook_ctools_plugin_type() to inform the plugin system that the Power Menu owns menu_handlers plugin type.
power_menu_entity_info Implements hook_entity_info().
power_menu_entity_view Implements hook_entity_view().
power_menu_features_pipe_field_alter Implements hook_features_pipe_COMPONENT_alter().
power_menu_flush_caches Implementation of hook_flush_caches()
power_menu_form_menu_edit_fields_submit Attached menu entity fields submit callback.
power_menu_form_menu_edit_fields_validate Attached menu entity fields validation callback.
power_menu_form_menu_edit_item_alter Implements hook_form_ID_alter().
power_menu_form_menu_edit_item_handlers_submit Attached menu form submit callback.
power_menu_form_menu_edit_item_handlers_validate Attached menu form validate callback.
power_menu_form_menu_overview_form_alter Implements hook_form_ID_alter().
power_menu_form_taxonomy_overview_terms_alter Implements hook_form_FORMID_alter().
power_menu_get_breadcrumbs Constructs the breadcrumb for given path. This works only, when the path is used in e menu link.
power_menu_get_entities_and_bundles Get all entity bundles with an uri callback
power_menu_get_fields_entity Gets the Power Menu Fileds entity for given path
power_menu_get_fields_entity_by_mlid Gets the Power Menu Fields entity for given Menu Link ID
power_menu_get_fields_entity_id_by_menu Returns the power_menu fields entity id for given menu (menu name).
power_menu_get_fields_entity_id_by_mlid Returns the power_menu fields entity id for given menu link id (mlid).
power_menu_get_menu_handlers Shortcut function to get menu_handlers plugins. The handlers are sorted by the module settings.
power_menu_get_path Gets the system path for the current page.
power_menu_handlers_weight_compare Compare the weigth of the plugins
power_menu_help Implements hook_help().
power_menu_menu Implements hook_menu().
power_menu_menu_alter Implements hook_menu_alter().
power_menu_menu_delete Implements hook_menu_delete():
power_menu_menu_link_delete Implements hook_menu_link_delete().
power_menu_permission Implements hook_permission().
power_menu_plugin_get_handler_instance Creates an instance for given handler configuration.
power_menu_plugin_get_handler_instance_by_name Creates an instance for given handler name.
power_menu_set_path Sets the system path to use for the active menu trail.
power_menu_theme Implements hook_theme().
_power_menu_call_handler_function Helper function to call a function in all registred handler objects.
_power_menu_recurse_crumbs Recursively loop ober the menu tree to get the breadcrumbs.