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'] .= '\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 \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; }