View source
<?php
function footermap_help($path, $arg) {
switch ($path) {
case 'admin/structure/footermap':
return '<p>' . t('You must enable the footermap block within Drupal\'s block management system: !link', array(
'!link' => l('admin/structure/block', 'admin/structure/block'),
)) . '</p>';
break;
case 'admin/help#footermap':
return '<p>' . t('Displays a dynamic, flexible sitemap at the bottom of a page via the Drupal block system. This is routinely used as a way of providing quick links at the bottom of the page. It is not advised to generate a full site map at the footer without caching.') . '</p>';
break;
}
}
function footermap_menu() {
$items = array();
$items['admin/structure/footermap'] = array(
'title' => 'Footermap',
'description' => 'Configure settings that footermap will use to dynamically generate the sitemap.',
'page callback' => 'drupal_get_form',
'page arguments' => array(
'footermap_settings',
),
'access arguments' => array(
'administer site configuration',
),
'type' => MENU_NORMAL_ITEM,
);
return $items;
}
function footermap_theme($existing, $type, $theme, $path) {
return array(
'footermap' => array(
'variables' => array(
'footermap' => NULL,
'title' => NULL,
'cached' => NULL,
),
'file' => 'footermap.theme.inc',
'template' => 'footermap',
),
'footermap_item' => array(
'variables' => array(
'href' => NULL,
'title' => NULL,
'options' => NULL,
'level' => NULL,
'children' => NULL,
'attributes' => NULL,
),
'file' => 'footermap.theme.inc',
),
'footermap_header' => array(
'variables' => array(
'title' => NULL,
'items' => NULL,
'attributes' => NULL,
),
'file' => 'footermap.theme.inc',
),
);
}
function footermap_settings() {
$form = array();
$form['recurse_limit'] = array(
'#type' => 'textfield',
'#title' => t('Recurse Limit'),
'#description' => t('Limit the footermap recursion function to <em>N</em> recursions. The default is 0, unlimited. This is useful if you have a deep hierarchy of child menu items that you do not want to display in the footermap.'),
'#size' => 3,
'#max_length' => 3,
'#default_value' => variable_get('recurse_limit', 0),
);
$form['footermap_heading'] = array(
'#type' => 'radios',
'#title' => t('Enable Menu Heading'),
'#description' => t('This will enable the menu-name property (e.g. navigation, user-menu) to be displayed as the heading above each menu column. This is nice if you have your menus setup in distinct blocks or controlled via the recurse-limit property above.'),
'#options' => array(
t('No'),
t('Yes'),
),
'#default_value' => variable_get('footermap_heading', 0),
);
$form['top_menu'] = array(
'#type' => 'textfield',
'#title' => t('Drupal Root Menu'),
'#description' => t('Set the menu id to use as the top level. Default is to start at 0 i .e. primary menus - primary, secondary, and navigation menus'),
'#default_value' => variable_get('top_menu', 0),
'#max_length' => 3,
'#size' => 3,
);
$avail_menus = footermap_get_primary_menus(variable_get('top_menu', 0));
$form['avail_menus'] = array(
'#type' => 'checkboxes',
'#title' => t('Available menus'),
'#description' => t('Limit the available menus under the "top menu" setting above to the following menu items and their children.'),
'#options' => $avail_menus,
'#default_value' => variable_get('avail_menus', array()),
);
$form['sys_menus'] = array(
'#type' => 'radios',
'#title' => t('Enable System Menu Items'),
'#description' => t('Enable system menus to be displayed. This is disabled by default, bu t is known to not work with Views menus because of a bug in <a href="http://api.drupal.org/api/function/hook_menu_link_alter/7">hook_menu_link_alter</a>'),
'#options' => array(
t('No'),
t('Yes'),
),
'#default_value' => variable_get('sys_menus', 0),
);
return system_settings_form($form, FALSE);
}
function footermap_block_info() {
$blocks = array();
$blocks['footermap'] = array(
'info' => t('Footermap block'),
'weight' => 5,
'status' => 1,
'region' => 'footer',
'cache' => DRUPAL_CACHE_CUSTOM,
);
return $blocks;
}
function footermap_block_view($delta = '') {
if ($delta == 'footermap') {
$block = array(
'subject' => '',
'content' => footermap_render(),
);
}
return $block;
}
function footermap_render() {
global $user;
global $language;
$recurse = variable_get('recurse_limit', 0);
$base = variable_get('top_menu', 0);
$menus = menu_get_menus(TRUE);
$mapref = array();
$avail_menus = variable_get('avail_menus', array());
$o = '';
$i = 1;
foreach ($menus as $key => $menu) {
if (isset($avail_menus[$key]) && $avail_menus[$key] === $key) {
$mapref[$key] = array(
'#theme' => 'footermap_header',
'#title' => $menu,
'#attributes' => array(
'class' => array(
'footermap-col',
'footermap-header',
),
'id' => 'footermap-col-' . $i,
),
'#attached' => array(
'css' => array(
drupal_get_path('module', 'footermap') . '/footermap.css',
),
),
);
$i++;
}
}
$content = array(
'#theme' => 'footermap',
'#footermap' => '',
'#title' => '',
'#cached' => FALSE,
);
$lang = !empty($user->language) ? $user->language : (!empty($language->language) ? $language->language : LANGUAGE_NONE);
$cached = cache_get('footermap-' . $lang, 'cache');
if (isset($cached->data)) {
$mapref = $cached->data;
$content['#cached'] = TRUE;
}
else {
footermap_get_menu($base, $mapref, $recurse, 0);
}
$content['#footermap'] = $mapref;
return $content;
}
function footermap_get_menu($mlid, &$mapref, $recurse, $level) {
global $user;
if ($recurse != 0 && $level >= $recurse) {
return;
}
$avail_menus = variable_get('avail_menus', array());
$query = db_select('menu_links', 'ml');
$query
->fields('ml')
->condition('ml.plid', $mlid, '=')
->condition('ml.hidden', 0, '=')
->orderBy('ml.plid')
->orderBy('ml.weight')
->orderBy('ml.link_title');
$query
->leftJoin('menu_router', 'mr', 'ml.router_path = mr.path');
$query
->fields('mr')
->orderBy('mr.title');
if (variable_get('sys_menus', 0) == 0) {
$query
->condition('ml.module', 'system', '<>');
}
$res = $query
->execute();
foreach ($res as $item) {
if (!_footermap_check_menu_item($avail_menus, $item)) {
continue;
}
if (isset($item->path)) {
if (empty($item->access_callback)) {
continue;
}
$map = array();
$args = array();
$map = explode('/', $item->link_path);
if (!empty($item->to_arg_functions)) {
_menu_link_map_translate($map, $item->to_arg_functions);
}
$args = menu_unserialize($item->access_arguments, $map);
if ($item->access_callback == 'user_access') {
if (!empty($args[0])) {
if (!user_access($args[0], $user)) {
continue;
}
}
}
else {
if ($item->access_callback == 'node_access') {
if (is_numeric($args[1])) {
$node = node_load($args[1]);
if (!node_access('view', $node)) {
continue;
}
}
else {
continue;
}
}
}
}
if (isset($mapref[$item->menu_name])) {
$child =& $mapref[$item->menu_name]['#items'];
}
else {
$child =& $mapref;
}
$options = $item->options ? unserialize($item->options) : array();
$item->link_path = preg_replace("/\\/%\$/", '', $item->link_path);
$child['menu-' . $item->mlid] = array(
'#theme' => 'footermap_item',
'#href' => $item->link_path,
'#title' => $item->link_title,
'#options' => $options,
'#attributes' => array(
'class' => array(
'footermap-item',
'footermap-item-' . $level,
),
'id' => 'footermap-item-' . $item->mlid,
),
'#level' => $level,
'#language' => isset($item->language) ? $item->language : LANGUAGE_NONE,
);
if ($item->has_children == 1) {
footermap_get_menu($item->mlid, $child['menu-' . $item->mlid]['#children'], $recurse, $level + 1);
}
}
}
function footermap_get_primary_menus($top_menu) {
$ret = array();
if (!is_numeric($top_menu)) {
return $ret;
}
$query = db_select('menu_links', 'ml');
$query
->fields('ml')
->condition('ml.plid', $top_menu, '=')
->condition('ml.hidden', 0, '=');
$query
->join('menu_custom', 'mc', 'ml.menu_name = mc.menu_name');
$query
->fields('mc');
$res = $query
->execute();
foreach ($res as $menu) {
$ret[$menu->menu_name] = t($menu->title);
}
return $ret;
}
function _footermap_check_menu_item($avail_menus, $item) {
foreach ($avail_menus as $key => $mn) {
if ($mn === $item->menu_name) {
return TRUE;
}
}
return FALSE;
}