array(
'title' => t('View published site map'),
),
);
}
/**
* Implements hook_theme().
*/
function site_map_theme() {
return array(
'site_map' => array(
'variables' => array(
'message' => NULL,
'rss_legend' => NULL,
'front_page' => NULL,
'blogs' => NULL,
'books' => NULL,
'menus' => NULL,
'faq' => NULL,
'taxonomys' => NULL,
'additional' => NULL,
),
'template' => 'site-map',
'file' => 'site_map.theme.inc',
),
'site_map_box' => array(
'variables' => array('title' => NULL, 'content' => NULL, 'class' => NULL),
'file' => 'site_map.theme.inc',
),
'site_map_feed_icon' => array(
'variables' => array('url' => NULL, 'type' => 'node'),
'file' => 'site_map.theme.inc',
),
'site_map_menu_link' => array(
'render element' => 'element',
'file' => 'site_map.theme.inc',
),
'site_map_menu_tree' => array(
'render element' => 'tree',
'file' => 'site_map.theme.inc',
),
'site_map_rss_legend' => array(
'variables' => array(),
'file' => 'site_map.theme.inc',
),
);
}
/**
* Implements hook_menu().
*/
function site_map_menu() {
$items['admin/config/content/sitemap'] = array(
'title' => 'Site map',
'description' => 'Control what should be displayed on the site map.',
'page callback' => 'drupal_get_form',
'page arguments' => array('site_map_admin_settings_form'),
'access arguments' => array('administer site configuration'),
'file' => 'site_map.admin.inc',
'type' => MENU_NORMAL_ITEM,
);
$items['sitemap'] = array(
'title' => 'Site map',
'description' => 'Display a site map with RSS feeds.',
'page callback' => 'site_map_page',
'access arguments' => array('access site map'),
'type' => MENU_SUGGESTED_ITEM,
);
return $items;
}
/**
* Implements hook_block().
*/
function site_map_block_info() {
$block['syndicate']['info'] = t('Syndicate (site map)');
return $block;
}
function site_map_block_view($delta = '') {
if (user_access('access content')) {
switch ($delta) {
case 'syndicate':
$block['subject'] = t('Syndicate');
if (arg(0) == 'blog') {
$uid = arg(1);
$feedurl = is_numeric($uid) ? "blog/$uid/feed" : 'blog/feed';
}
else {
$feedurl = variable_get('site_map_rss_front', 'rss.xml');
}
$block['content'] = theme('feed_icon', array('url' => url($feedurl), 'title' => t('Syndicate')));
$block['content'] .= '
' . l(t('more'), 'sitemap', array('title' => t('View the site map to see more RSS feeds.'))) . "
\n";
break;
}
return $block;
}
}
/**
* Menu callback for the site map.
*/
function site_map_page() {
drupal_set_title(variable_get('site_map_page_title', t('Site map')));
if (variable_get('site_map_css', 0) != 1) {
drupal_add_css(drupal_get_path('module', 'site_map') . '/site_map.css');
}
return theme('site_map');
}
function _site_map_front_page() {
$output = '';
$class = '';
$title = t('Front page');
$output = l(t('Front page of %sn', array('%sn' => variable_get('site_name', 'Drupal'))), '', array('html' => TRUE));
if (variable_get('site_map_show_rss_links', 1) != 0) {
$rss_link = theme('site_map_feed_icon', array('url' => variable_get('site_map_rss_front', 'rss.xml')));
if (module_exists('commentrss') && variable_get('commentrss_site', COMMENTRSS_SITE_FRONT_PAGE)) {
$rss_link .= ' ' . theme('site_map_feed_icon', array('url' => 'crss', 'type' => 'comment'));
}
if (variable_get('site_map_show_rss_links', 1) == 1) {
$output .= ' ' . $rss_link;
}
else {
$class = ' site-map-rss-left';
$output = $rss_link . ' ' . $output;
}
}
return theme('site_map_box', array('title' => $title, 'content' => $output, 'class' => 'site-map-front-box' . $class));
}
/**
* Render the latest blog authors
*/
function _site_map_blogs() {
$output = '';
$class = '';
if (module_exists('blog')) {
$title = t('Blogs');
$output = '' . t('Community blog and recent blog authors at %sn.', array('%sn' => variable_get('site_name', 'Drupal'))) . '
';
$blog_link = l(t('All blogs'), 'blog');
if (variable_get('site_map_show_rss_links', 1) != 0) {
$rss_link = theme('site_map_feed_icon', array('url' => 'blog/feed'));
if (variable_get('site_map_show_rss_links', 1) == 1) {
$blog_link .= ' ' . $rss_link;
}
else {
$class = ' site-map-rss-left';
$blog_link = $rss_link . ' ' . $blog_link;
}
}
$blogs = array();
$blogs[] = $blog_link;
$sql = "SELECT DISTINCT u.uid, u.name, count(u.uid) AS numitems
FROM {node} n
INNER JOIN {users} u ON u.uid = n.uid
WHERE n.type = 'blog' AND n.status = 1
GROUP BY u.uid, u.name
ORDER BY numitems DESC, u.name";
$result = db_query_range($sql, 0, 10);
foreach ($result as $blog) {
$blog_item = t('@name\'s blog (@num_items)', array('@url' => "blog/$blog->uid", '@name' => $blog->name, '@num_items' => $blog->numitems));
if (variable_get('site_map_show_rss_links', 1) != 0) {
$rss_link = theme('site_map_feed_icon', array('url' => "blog/$blog->uid/feed"));
if (variable_get('site_map_show_rss_links', 1) == 1) {
$blog_item .= ' ' . $rss_link;
}
else {
$blog_item = $rss_link . ' ' . $blog_item;
}
}
$blogs[] = $blog_item;
}
$output .= theme('item_list', array('items' => $blogs));
$output = theme('site_map_box', array('title' => $title, 'content' => $output, 'class' => 'site-map-blog-box' . $class));
}
return $output;
}
function _site_map_audio() {
$output = '';
$class = '';
if (module_exists('audio')) {
$title = t('Audio');
$output = l(t('Audio content'), 'audio');
if (variable_get('site_map_show_rss_links', 1) != 0) {
$rss_link = theme('site_map_feed_icon', array('url' => 'audio/feed'));
if (variable_get('site_map_show_rss_links', 1) == 1) {
$output .= ' ' . $rss_link;
}
else {
$class = ' site-map-rss-left';
$output = $rss_link . ' ' . $output;
}
}
$output = theme('site_map_box', array('title' => $title, 'content' => $output, 'class' => 'site-map-audio-box' . $class));
}
return $output;
}
function _site_map_video() {
$output = '';
$class = '';
if (module_exists('video')) {
$title = t('Video');
$output = l(t('Video content'), 'video');
if (variable_get('site_map_show_rss_links', 1) != 0) {
$rss_link = theme('site_map_feed_icon', array('url' => 'video/feed'));
if (variable_get('site_map_show_rss_links', 1) == 1) {
$output .= ' ' . $rss_link;
}
else {
$class = ' site-map-rss-left';
$output = $rss_link . ' ' . $output;
}
}
$output = theme('site_map_box', array('title' => $title, 'content' => $output, 'class' => 'site-map-video-box' . $class));
}
return $output;
}
/**
* Render books
*/
function _site_map_books() {
$output = '';
if (module_exists('book') && ($nids = variable_get('site_map_show_books', array()))) {
$title = t('Books');
$description = '' . t('Books at %sn.', array('%sn' => variable_get('site_name', 'Drupal'))) . '
';
$book_menus = array();
foreach ($nids as $nid) {
$node = node_load($nid);
$tree = menu_tree_all_data($node->book['menu_name']);
$data = array_shift($tree);
$output .= theme('book_title_link', array('link' => $data['link']));
$output .= ($data['below']) ? _site_map_menu_tree_output($data['below']) : '';
}
if ($output) {
$output = theme('site_map_box', array('title' => $title, 'content' => $description . $output, 'class' => 'site-map-book-box'));
}
}
return $output;
}
/**
* Render menus
*/
function _site_map_menus() {
$mids = variable_get('site_map_show_menus', array());
$output = '';
if ($mids) {
foreach ($mids as $mid) {
$menu = menu_load($mid);
// Use menu_tree_all_data to retrieve the expanded tree.
$tree = menu_tree_all_data($mid);
if (module_exists('i18nmenu')) {
i18nmenu_localize_tree($tree);
}
$menu_display = _site_map_menu_tree_output($tree);
$menu_html = drupal_render($menu_display);
if (!empty($menu_html)) {
$title = $menu['title'];
$output .= theme('site_map_box', array('title' => $title, 'content' => $menu_html, 'class' => 'site-map-menu-box'));
}
}
}
return $output;
}
function _site_map_faq() {
$output = '';
if (module_exists('faq')) {
$title = variable_get('faq_title', t('Frequently Asked Questions'));
$output = faq_get_faq_list();
$output = theme('site_map_box', array('title' => $title, 'content' => $output, 'class' => 'site-map-faq-box'));
}
return $output;
}
/**
* This function can be called from blocks or pages as desired.
*/
function _site_map_taxonomys() {
$output = '';
if (module_exists('taxonomy') && $vids = variable_get('site_map_show_vocabularies', array())) {
$result = db_query('SELECT vid, name, description FROM {taxonomy_vocabulary} WHERE vid IN (:vids) ORDER BY weight ASC, name', array(':vids' => $vids));
foreach ($result as $t) {
if (module_exists('i18ntaxonomy')) {
$t->name = tt("taxonomy:vocabulary:$t->vid:name", $t->name);
}
$output .= _site_map_taxonomy_tree($t->vid, $t->name, $t->description);
}
}
return $output;
}
/**
* Render the taxonomy tree.
*
* @param $tree
* The results of taxonomy_get_tree() with optional 'count' fields.
* @param $name
* An optional name for the tree. (Default: NULL)
* @param
* $description An optional description of the tree. (Default: NULL)
* @return
* A string representing a rendered tree.
*/
function _site_map_taxonomy_tree($vid, $name = NULL, $description = NULL) {
$output = '';
$class = '';
if ($vid == variable_get('forum_nav_vocabulary', '')) {
$title = l($name, 'forum');
$threshold = variable_get('site_map_forum_threshold', -1);
$forum_link = TRUE;
}
else {
$title = $name ? check_plain(t($name)) : '';
$threshold = variable_get('site_map_term_threshold', 0);
$forum_link = FALSE;
}
$title .= (module_exists('commentrss') && variable_get('commentrss_term', FALSE) ? ' ' . theme('site_map_feed_icon', array('url' => "crss/vocab/$vid", 'type' => 'comment')) : '');
$last_depth = -1;
$rss_depth = variable_get('site_map_rss_depth', 'all');
if (!is_numeric($rss_depth) || $rss_depth < 0) {
$rss_depth = 'all';
}
$cat_depth = variable_get('site_map_categories_depth', 'all');
if (!is_numeric($cat_depth)) {
$cat_depth = 'all';
}
$output .= !empty($description) ? '' . filter_xss_admin($description) . "
\n" : '';
// taxonomy_get_tree() honors access controls
$tree = taxonomy_get_tree($vid);
foreach ($tree as $term) {
$term->count = site_map_taxonomy_term_count_nodes($term->tid);
if ($term->count <= $threshold) {
continue;
}
if (module_exists('i18ntaxonomy')) {
$term->name = tt("taxonomy:term:$term->tid:name", $term->name);
}
// Adjust the depth of the based on the change
// in $term->depth since the $last_depth.
if ($term->depth > $last_depth) {
for ($i = 0; $i < ($term->depth - $last_depth); $i++) {
$output .= "\n";
}
}
elseif ($term->depth == $last_depth) {
$output .= '';
}
elseif ($term->depth < $last_depth) {
for ($i = 0; $i < ($last_depth - $term->depth); $i++) {
$output .= "\n
\n";
}
}
// Display the $term.
$output .= "\n- ";
$term_item = '';
if ($forum_link) {
$term_item .= l($term->name, 'forum/' . $term->tid, array('attributes' => array('title' => $term->description)));
}
elseif ($term->count) {
$term_item .= l($term->name, ($cat_depth < 0) ? taxonomy_term_path($term) : "taxonomy/term/$term->tid/$cat_depth", array('attributes' => array('title' => $term->description)));
}
else {
$term_item .= check_plain($term->name);
}
if (variable_get('site_map_show_count', 1)) {
$term_item .= " ($term->count)";
}
if (variable_get('site_map_show_rss_links', 1) != 0) {
$rss_link = theme('site_map_feed_icon', array('url' => "taxonomy/term/$term->tid/$rss_depth/feed"));
if (module_exists('commentrss') && variable_get('commentrss_term', FALSE)) {
$rss_link .= ' ' . theme('site_map_feed_icon', array('url' => "crss/term/$term->tid", 'type' => 'comment'));
}
if (variable_get('site_map_show_rss_links', 1) == 1) {
$term_item .= ' ' . $rss_link;
}
else {
$class = ' site-map-rss-left';
$term_item = $rss_link . ' ' . $term_item;
}
}
$output .= $term_item;
// Reset $last_depth in preparation for the next $term.
$last_depth = $term->depth;
}
// Bring the depth back to where it began, -1.
if ($last_depth > -1) {
for ($i = 0; $i < ($last_depth + 1); $i++) {
$output .= "
\n
\n";
}
}
$output = theme('site_map_box', array('title' => $title, 'content' => $output, 'class' => 'site-map-terms-box site-map-terms-box-' . $vid . $class));
return $output;
}
/**
* Count the number of published nodes classified by a term.
*
* This is a re-implementation of taxonomy_term_count_nodes() that has been
* removed from D7 core.
*
* Implementation note: the normal way to count field instances is through
* field_attach_query(), but taxonomy.module has a special denormalized
* table taxonomy_index which we can use for more speed. THX to taxonews.
*
* @param $tid
* The term's ID.
* @return
* An integer representing a number of nodes. Results are statically cached.
*/
function site_map_taxonomy_term_count_nodes($tid) {
$query = db_select('taxonomy_index', 'ti');
$query->addExpression('COUNT(ti.nid)');
$count = $query
->condition('ti.tid', $tid)
->execute()->fetchCol();
return $count[0];
}
/**
* This is a clone of the core menu_tree_output() function with the exception
* of theme('site_map_menu_tree') for theming override reasons.
*
* Returns a rendered menu tree.
*
* @param $tree
* A data structure representing the tree as returned from menu_tree_data.
* @return
* The rendered HTML of that data structure.
*/
function _site_map_menu_tree_output($tree) {
$build = array();
$items = array();
// Pull out just the menu links we are going to render so that we
// get an accurate count for the first/last classes.
foreach ($tree as $data) {
if (!$data['link']['hidden']) {
$items[] = $data;
}
}
$num_items = count($items);
foreach ($items as $i => $data) {
$class = array();
if ($i == 0) {
$class[] = 'first';
}
if ($i == $num_items - 1) {
$class[] = 'last';
}
// Set a class if the link has children.
if ($data['below']) {
$class[] = 'expanded';
}
elseif ($data['link']['has_children']) {
$class[] = 'collapsed';
}
else {
$class[] = 'leaf';
}
// Set a class if the link is in the active trail.
if ($data['link']['in_active_trail']) {
$class[] = 'active-trail';
$data['localized_options']['attributes']['class'][] = 'active-trail';
}
// Allow menu-specific theme overrides.
$element['#theme'] = 'site_map_menu_link__' . $data['link']['menu_name'];
$element['#attributes']['class'] = $class;
$element['#title'] = $data['link']['title'];
$element['#href'] = $data['link']['href'];
$element['#localized_options'] = !empty($data['link']['localized_options']) ? $data['link']['localized_options'] : array();
$element['#below'] = $data['below'] ? _site_map_menu_tree_output($data['below']) : $data['below'];
$element['#original_link'] = $data['link'];
// Index using the link's unique mlid.
$build[$data['link']['mlid']] = $element;
}
if ($build) {
// Make sure drupal_render() does not re-order the links.
$build['#sorted'] = TRUE;
// Add the theme wrapper for outer markup.
// Allow menu-specific theme overrides.
$build['#theme_wrappers'][] = 'site_map_menu_tree__' . $data['link']['menu_name'];
}
return $build;
}