taxonomy_menu_trails.module in Taxonomy Menu Trails 7.2
Same filename and directory in other branches
Changes menu trail of current entity to its term's menu item.
@author Dmitriy.trt <http://drupal.org/user/329125>
File
taxonomy_menu_trails.moduleView source
<?php
/**
* @file
* Changes menu trail of current entity to its term's menu item.
*
* @author Dmitriy.trt <http://drupal.org/user/329125>
*/
/**
* Gets settings for specified entity type and bundle name.
*
* @param string $entity_type
* @param string $bundle
* @param boolean $load_default
* Should function populate settings with default values if there were no
* settings saved yet. If settings were saved, they will be filled with
* default values independent from this parameter (to prevent warnings
* about missing array keys).
* @return array
* Numeric-indexed array with:
* - settings for entity type and bundle
* - variable name for settings
* - does variable already exists.
*/
function _taxonomy_menu_trails_get_settings($entity_type, $bundle, $load_default = TRUE) {
$var_name = 'taxonomy_menu_trails_' . $entity_type . '_' . $bundle;
$settings = variable_get($var_name);
$var_exists = !empty($settings);
if (!empty($settings)) {
$settings += _taxonomy_menu_trails_defaults();
}
elseif ($load_default) {
$settings = _taxonomy_menu_trails_defaults();
}
return array(
$settings,
$var_name,
$var_exists,
);
}
/**
* Returns default Taxonomy Menu Trails settings for bundle
*
* @return array
*/
function _taxonomy_menu_trails_defaults() {
$defaults = array(
'selection_method' => 'first',
'only_without_menu' => FALSE,
'set_breadcrumb' => 'if_empty',
'term_path' => 'default',
'term_path_patterns' => array(),
'instances' => array(),
'paths_ui' => '',
'trail_per_menu' => FALSE,
);
if (module_exists('i18n_taxonomy')) {
$defaults += array(
'terms_with_current_language' => FALSE,
);
}
return $defaults;
}
/**
* Extracts entity keys from entity type info.
*
* @param string $entity_type
* @param array $keys
* List of keys to extract.
* @return array
* Numerical-indexed array with entity keys in the same order like in $keys argument.
*/
function _taxonomy_menu_trails_get_entity_type_keys($entity_type, $keys = array(
'id',
'label',
)) {
$type_info = entity_get_info($entity_type);
$result = array();
foreach ($keys as $key) {
$result[] = $type_info['entity keys'][$key];
}
return $result;
}
/**
* Implements hook_init().
*/
function taxonomy_menu_trails_init() {
switch (arg(0)) {
case 'node':
if (is_numeric(arg(1))) {
$entity_type = 'node';
$entities = entity_load($entity_type, array(
arg(1),
));
$entity = reset($entities);
}
break;
}
// If entity was found, extract bundle name and get entity path from entity
// API, so it will be real entity path and not its child tab path.
// We don't need this for entity found with regexp.
if (!empty($entity)) {
list(, , $bundle) = entity_extract_ids($entity_type, $entity);
list($settings) = _taxonomy_menu_trails_get_settings($entity_type, $bundle, FALSE);
if ($settings['only_without_menu']) {
$entity_uri = entity_uri($entity_type, $entity);
$entity_path = $entity_uri['path'];
}
}
else {
$all_regexps = variable_get('taxonomy_menu_trails__path_regexps', array());
foreach ($all_regexps as $entity_type => $bundles) {
foreach ($bundles as $bundle => $placeholders) {
foreach ($placeholders as $placeholder => $regexps) {
foreach ($regexps as $regexp) {
// Run regular expression test. $matches[1] will contain placeholder
// matched value.
if (preg_match($regexp, $_GET['q'], $matches)) {
$placeholder_value = $matches[1];
list($id_key, $title_key, $bundle_key) = _taxonomy_menu_trails_get_entity_type_keys($entity_type, array(
'id',
'label',
'bundle',
));
$ids = FALSE;
$conditions = array(
$bundle_key => $bundle,
);
switch ($placeholder) {
case $id_key:
$ids = array(
$placeholder_value,
);
break;
case $title_key:
$conditions[$title_key] = $placeholder_value;
break;
}
$entities = entity_load($entity_type, $ids, $conditions);
$entity = reset($entities);
if (!empty($entity)) {
// Entity found, set current page as entity path and break all loops.
list($settings) = _taxonomy_menu_trails_get_settings($entity_type, $bundle, FALSE);
if ($settings['only_without_menu']) {
$entity_path = $_GET['q'];
}
break 4;
}
}
}
}
}
}
}
if (!empty($entity)) {
// TODO check for active trail cache existence and process only if there is
// no cache data for current path and make sure this behavior will work
// for Menu Block
if (!empty($settings['instances'])) {
$pass_own_menu_check = TRUE;
if ($settings['only_without_menu']) {
$has_own_menu = db_query('SELECT mlid FROM {menu_links} WHERE link_path = :path AND hidden = 0 LIMIT 1', array(
':path' => $entity_path,
))
->fetchField();
$pass_own_menu_check = !$has_own_menu;
}
if ($pass_own_menu_check) {
$has_terms = FALSE;
//TODO figure out: maybe we have to choose language in term reference fields
foreach ($settings['instances'] as $field) {
if (!empty($entity->{$field})) {
$has_terms = TRUE;
break;
}
}
if ($has_terms) {
$settings['entity_type'] = $entity_type;
module_load_include('inc', 'taxonomy_menu_trails');
_taxonomy_menu_trails_process($entity, $settings);
}
}
}
}
}
/**
* Implements hook_form_FORM_ID_alter() for field_ui_field_edit_form.
*/
function taxonomy_menu_trails_form_field_ui_field_edit_form_alter(&$form, &$state) {
if ($form['#instance']['entity_type'] == 'node' && $form['#field']['type'] == 'taxonomy_term_reference') {
form_load_include($state, 'admin.inc', 'taxonomy_menu_trails');
_taxonomy_menu_trails_alter_field_form($form);
}
}
/**
* Implements hook_form_FORM_ID_alter() for node_type_form.
*/
function taxonomy_menu_trails_form_node_type_form_alter(&$form, &$state) {
form_load_include($state, 'admin.inc', 'taxonomy_menu_trails');
_taxonomy_menu_trails_alter_bundle_form($form, 'node', $form['#node_type']);
$form['taxonomy_menu_trails']['#group'] = 'additional_settings';
$form['taxonomy_menu_trails']['#attached'] = array(
'js' => array(
drupal_get_path('module', 'taxonomy_menu_trails') . '/js/node-type-form.js',
),
);
}
/**
* Implements hook_field_delete_instance().
*/
function taxonomy_menu_trails_field_delete_instance($instance) {
$field_name = $instance['field_name'];
$info = field_info_field($field_name);
if ($info['type'] == 'taxonomy_term_reference') {
switch ($instance['entity_type']) {
case 'node':
module_load_include('admin.inc', 'taxonomy_menu_trails');
_taxonomy_menu_trails_delete_instance($instance);
break;
}
}
}
/**
* Implements hook_form_FORM_ID_alter() for field_ui_field_overview_form.
*/
function taxonomy_menu_trails_form_field_ui_field_overview_form_alter(&$form, &$state) {
switch ($form['#entity_type']) {
case 'node':
form_load_include($state, 'admin.inc', 'taxonomy_menu_trails');
_taxonomy_menu_trails_alter_overview_form($form);
break;
}
}
/**
* Stores selected menu item for taxonomy_menu_trails_menu_breadcrumb_alter().
*
* @param array|null $new_item
*
* @return array|null
*/
function taxonomy_menu_trails_selected_item_for_breadcrumb($new_item = NULL) {
$item =& drupal_static(__FUNCTION__);
if (isset($new_item)) {
$item = $new_item;
}
return $item;
}
/**
* Implements hook_menu_breadcrumb_alter().
*
* Injects selected menu item and its parents into the breadcrumb.
*/
function taxonomy_menu_trails_menu_breadcrumb_alter(&$active_trail, $item) {
if (drupal_is_front_page()) {
return;
}
if ($selected_item = taxonomy_menu_trails_selected_item_for_breadcrumb()) {
module_load_include('inc', 'taxonomy_menu_trails');
_taxonomy_menu_trails_menu_breadcrumb_alter($active_trail, $selected_item);
}
}
/**
* Implements hook_module_implements_alter().
*
* Moves taxonomy_menu_trails_init() to the beginning of the list before
* menu_breadcrumb_init(), so the breadcrumb retrieved by Menu Breadcrumb will
* be altered by taxonomy_menu_trails_menu_breadcrumb_alter() using the menu
* item selected by taxonomy_menu_trails_init() earlier.
*
* It is moved even if the Menu Breadcrumb is not enabled, so behavior is not
* changed when Menu Breadcrumb is enabled/disabled.
*/
function taxonomy_menu_trails_module_implements_alter(&$implementations, $hook) {
if ($hook == 'init' && isset($implementations['taxonomy_menu_trails'])) {
$group = $implementations['taxonomy_menu_trails'];
unset($implementations['taxonomy_menu_trails']);
$implementations = array(
'taxonomy_menu_trails' => $group,
) + $implementations;
}
}
/**
* Implements hook_preprocess_menu_item().
*
* Adds class "menu-item-preferred" to the preferred menu item for each menu
* (last item in active trail).
*/
function taxonomy_menu_trails_preprocess_menu_link(&$vars) {
// Fast static cache.
static $drupal_static_fast;
if (!isset($drupal_static_fast)) {
$drupal_static_fast['paths'] =& drupal_static(__FUNCTION__, array());
}
$preferred_paths =& $drupal_static_fast['paths'];
// Initialize preferred path for this menu if not yet done.
$element =& $vars['element'];
$menu_name = $element['#original_link']['menu_name'];
if (!isset($preferred_paths[$menu_name])) {
$active_path = menu_tree_get_path($menu_name);
$preferred_item = menu_link_get_preferred($active_path, $menu_name);
if (!$preferred_item) {
// No preferred items. Mark menu with FALSE to avoid loading it over and
// over again.
$preferred_paths[$menu_name] = FALSE;
return;
}
else {
$preferred_paths[$menu_name] = $preferred_item['href'];
}
}
// Compare preferred path with the current item path and add classes on match.
$preferred_path = $preferred_paths[$menu_name];
if ($preferred_path !== FALSE && $element['#href'] === $preferred_path) {
$vars['element']['#attributes']['class'][] = 'menu-item-preferred';
$vars['element']['#localized_options']['attributes']['class'][] = 'menu-item-preferred';
}
}