You are here

site_map.module in Site map 8

Provides a site map functionality.

Original author: Nic Ivy Now maintained by Fredrik Jonsson fredrik at combonet dot se

File

site_map.module
View source
<?php

/**
 * @file
 * Provides a site map functionality.
 *
 * Original author: Nic Ivy
 * Now maintained by Fredrik Jonsson fredrik at combonet dot se
 */
use Drupal\system\Entity\Menu;
use Drupal\Core\Menu\MenuTreeParameters;
use Drupal\Core\Url;

/**
 * Implements hook_theme().
 */
function site_map_theme() {
  return array(
    'site_map' => array(
      'variables' => array(
        'message' => NULL,
        'rss_legend' => NULL,
        'site_map_items' => array(),
        'additional' => NULL,
      ),
      'file' => 'site_map.theme.inc',
    ),
    'site_map_box' => array(
      'variables' => array(
        'title' => NULL,
        'content' => NULL,
        'attributes' => array(),
        'options' => NULL,
      ),
    ),
    'site_map_feed_icon' => array(
      'variables' => array(
        'url' => NULL,
        'name' => NULL,
        'type' => 'node',
      ),
    ),
    'site_map_menu_link' => array(
      'render element' => 'element',
      'function' => 'theme_site_map_menu_link',
      'file' => 'site_map.theme.inc',
    ),
    'site_map_menu_tree' => array(
      'render element' => 'tree',
      'function' => 'theme_site_map_menu_tree',
      'file' => 'site_map.theme.inc',
    ),
    'site_map_rss_legend' => array(
      'variables' => array(),
      'function' => 'theme_site_map_rss_legend',
      'file' => 'site_map.theme.inc',
    ),
    'site_map_order' => array(
      'render element' => 'element',
      'function' => 'theme_site_map_order',
      'file' => 'site_map.theme.inc',
    ),
  );
}

/**
 * Menu callback for the site map front page.
 *
 * @return string
 *   Returns HTML string for front page site map.
 */
function _site_map_front_page() {
  $config = \Drupal::config('site_map.settings');
  $class = array();
  $options = array();
  $title = t('Front page');
  $output = \Drupal::l(t('Front page of %sn', array(
    '%sn' => \Drupal::config('system.site')
      ->get('name'),
  )), Url::fromRoute('<front>', [], array(
    'html' => TRUE,
  )));
  if ($config
    ->get('show_rss_links') != 0) {
    $feed_icon = array(
      '#theme' => 'site_map_feed_icon',
      '#url' => $config
        ->get('rss_front'),
      '#name' => 'front page',
    );
    $rss_link = drupal_render($feed_icon);
    if (\Drupal::service('module_handler')
      ->moduleExists('commentrss') && \Drupal::config('commentrss.settings')
      ->get('commentrss_site')) {
      $feed_icon = array(
        '#theme' => 'site_map_feed_icon',
        '#url' => 'crss',
        '#type' => 'comment',
        '#name' => 'front page comments',
      );
      $rss_link .= ' ' . drupal_render($feed_icon);
    }
    if ($config
      ->get('show_rss_links') == 1) {
      $output .= ' ' . $rss_link;
    }
    else {
      $class[] = 'site-map-rss-left';
      $output = $rss_link . ' ' . $output;
    }
  }
  \Drupal::service('site_map.helper')
    ->setOption($options, 'show_titles', 1, 'show_titles', TRUE);
  $class[] = 'site-map-box-front';
  $attributes = array(
    'class' => $class,
  );
  $site_map_box = array(
    '#theme' => 'site_map_box',
    '#title' => $title,
    '#content' => array(
      '#markup' => $output,
    ),
    '#attributes' => $attributes,
    '#options' => $options,
  );
  return $site_map_box;
}

/**
 * Render the latest blogs.
 *
 * @return string
 *   Returns HTML string of site map for blogs.
 */
function _site_map_blogs() {
  $config = \Drupal::config('site_map.settings');
  $output = '';
  $class = array();
  $options = array();
  if (\Drupal::service('module_handler')
    ->moduleExists('blog')) {
    $title = t('Blogs');
    $output = '<div class="description">' . t('Community blog and recent blog authors at %sn.', array(
      '%sn' => \Drupal::config('system.site')
        ->get('name'),
    )) . '</div>';
    $blog_link = \Drupal::l(t('All blogs'), Url::fromUri('base://' . 'blog'));
    if ($config
      ->get('show_rss_links') != 0) {
      $feed_icon = array(
        '#theme' => 'site_map_feed_icon',
        '#url' => 'blog/feed',
        '#name' => 'all blogs',
      );
      $rss_link = drupal_render($feed_icon);
      if ($config
        ->get('show_rss_links') == 1) {
        $blog_link .= ' ' . $rss_link;
      }
      else {
        $class[] = 'site-map-rss-left';
        $blog_link = $rss_link . ' ' . $blog_link;
      }
    }
    \Drupal::service('site_map.helper')
      ->setOption($options, 'show_titles', 1, 'show_titles', TRUE);
    $blogs = array();
    $blogs[] = $blog_link;
    $query = db_select('node', 'n');
    $query
      ->join('users', 'u', 'u.uid = n.uid');
    $query
      ->fields('u', array(
      'uid',
      'name',
    ));
    $query
      ->addExpression('COUNT(u.uid)', 'numitems');
    $query
      ->condition('n.type', 'blog')
      ->condition('n.status', 1)
      ->groupBy('u.uid')
      ->groupBy('u.name')
      ->orderBy('numitems', 'DESC')
      ->orderBy('u.name', 'ASC')
      ->range(0, 10);
    $query
      ->addTag('node_access');
    $query
      ->distinct();
    $result = $query
      ->execute();
    foreach ($result as $blog) {
      $blog_item = t('<a href="@url">@name\'s blog</a> (@num_items)', array(
        '@url' => "blog/{$blog->uid}",
        '@name' => $blog->name,
        '@num_items' => $blog->numitems,
      ));
      if ($config
        ->get('show_rss_links') != 0) {
        $feed_icon = array(
          '#theme' => 'site_map_feed_icon',
          '#url' => "blog/{$blog->uid}/feed",
        );
        $rss_link = drupal_render($feed_icon);
        if ($config
          ->get('show_rss_links') == 1) {
          $blog_item .= ' ' . $rss_link;
        }
        else {
          $blog_item = $rss_link . ' ' . $blog_item;
        }
      }
      $blogs[] = $blog_item;
    }
    $class[] = 'site-map-box-blog';
    $attributes = array(
      'class' => $class,
    );
    $blog_list = array(
      '#theme' => 'item_list',
      '#items' => $blogs,
    );
    $output .= drupal_render($blog_list);
    $site_map_box = array(
      '#theme' => 'site_map_box',
      '#title' => $title,
      '#content' => $output,
      '#attributes' => $attributes,
      '#options' => $options,
    );
    $output = drupal_render($site_map_box);
  }
  return $output;
}

/**
 * Render the latest maps for audio.
 *
 * @return string
 *   Returns HTML string of site map for audio.
 */
function _site_map_audio() {
  $config = \Drupal::config('site_map.settings');
  $output = '';
  $class = array();
  $options = array();
  if (\Drupal::service('module_handler')
    ->moduleExists('audio')) {
    $title = t('Audio');
    $output = \Drupal::l(t('Audio content'), Url::fromUri('base://' . 'audio'));
    if ($config
      ->get('show_rss_links') != 0) {
      $feed_icon = array(
        '#theme' => 'site_map_feed_icon',
        '#url' => 'audio/feed',
        '#name' => 'audio content',
      );
      $rss_link = drupal_render($feed_icon);
      if ($config
        ->get('show_rss_links') == 1) {
        $output .= ' ' . $rss_link;
      }
      else {
        $class[] = 'site-map-rss-left';
        $output = $rss_link . ' ' . $output;
      }
    }
    \Drupal::service('site_map.helper')
      ->setOption($options, 'show_titles', 1, 'show_titles', TRUE);
    $class[] = 'site-map-box-audio';
    $attributes = array(
      'class' => $class,
    );
    $site_map_box = array(
      '#theme' => 'site_map_box',
      '#title' => $title,
      '#content' => $output,
      '#attributes' => $attributes,
      '#options' => $options,
    );
    $output = drupal_render($site_map_box);
  }
  return $output;
}

/**
 * Render the latest maps for video.
 *
 * @return string
 *   Returns HTML string of site map for video.
 */
function _site_map_video() {
  $config = \Drupal::config('site_map.settings');
  $output = '';
  $class = array();
  $options = array();
  if (\Drupal::service('module_handler')
    ->moduleExists('video')) {
    $title = t('Video');
    $output = \Drupal::l(t('Video content'), Url::fromUri('base://' . 'video'));
    if ($config
      ->get('show_rss_links') != 0) {
      $feed_icon = array(
        '#theme' => 'site_map_feed_icon',
        '#url' => 'video/feed',
        '#name' => 'video content',
      );
      $rss_link = drupal_render($feed_icon);
      if ($config
        ->get('show_rss_links') == 1) {
        $output .= ' ' . $rss_link;
      }
      else {
        $class[] = 'site-map-rss-left';
        $output = $rss_link . '  ' . $output;
      }
    }
    \Drupal::service('site_map.helper')
      ->setOption($options, 'show_titles', 1, 'show_titles', TRUE);
    $class[] = 'site-map-box-video';
    $attributes = array(
      'class' => $class,
    );
    $site_map_box = array(
      '#theme' => 'site_map_box',
      '#title' => $title,
      '#content' => $output,
      '#attributes' => $attributes,
      '#options' => $options,
    );
    $output = drupal_render($site_map_box);
  }
  return $output;
}

/**
 * Render the latest maps for books.
 *
 * @return string
 *   Returns HTML string of site map for books.
 */
function _site_map_books() {
  $config = \Drupal::config('site_map.settings');
  $output = '';
  $options = array();
  $book_titles = array();
  $bids = array_filter($config
    ->get('show_books'));
  if (\Drupal::service('module_handler')
    ->moduleExists('book') && !empty($bids)) {
    $books_expanded = $config
      ->get('books_expanded');
    $title = t('Books');
    $description = '<div class="description">' . t('Books at %sn.', array(
      '%sn' => \Drupal::config('system.site')
        ->get('name'),
    )) . '</div>';
    foreach (\Drupal::service('book.manager')
      ->getAllBooks() as $book) {
      if (in_array($book['bid'], $bids)) {
        if ($books_expanded) {

          // Retrieve the expanded tree.
          $tree = \Drupal::service('book.manager')
            ->bookTreeAllData($book['bid']);
          if (\Drupal::service('module_handler')
            ->moduleExists('i18n_menu')) {
            $tree = i18n_menu_localize_tree($tree, $GLOBALS['language']->language);
          }
          $tree_output = \Drupal::service('book.manager')
            ->bookTreeOutput($tree);
          $output .= drupal_render($tree_output);
        }
        else {
          $book_titles[] = \Drupal::l($book['title'], Url::fromRoute('entity.node.canonical', array(
            'node' => $book['bid'],
          )));
        }
      }
    }
    \Drupal::service('site_map.helper')
      ->setOption($options, 'show_titles', 1, 'show_titles', TRUE);
    if (!$books_expanded && !empty($book_titles)) {
      $book_titles = array(
        '#theme' => 'item_list',
        '#items' => $book_titles,
      );
      $output .= drupal_render($book_titles);
    }
    if (!empty($output)) {
      $attributes = array(
        'class' => array(
          'site-map-box-book',
        ),
      );
      $site_map_box = array(
        '#theme' => 'site_map_box',
        '#title' => $title,
        '#content' => array(
          '#markup' => $description . $output,
        ),
        '#attributes' => $attributes,
        '#options' => $options,
      );
      $output = $site_map_box;
    }
  }
  return $output;
}

/**
 * Render the latest maps for all the menus.
 *
 * @return string
 *   Returns HTML string of site map for menus.
 */
function _site_map_menus($mid) {
  $output = '';
  $class = array();
  $options = array();
  if (!empty($mid)) {
    $menu = Menu::load($mid);

    // Retrieve the expanded tree.
    $tree = \Drupal::service('menu.link_tree')
      ->load($mid, new MenuTreeParameters());
    $manipulators = array(
      array(
        'callable' => 'menu.default_tree_manipulators:checkAccess',
      ),
      array(
        'callable' => 'menu.default_tree_manipulators:generateIndexAndSort',
      ),
    );
    $tree = \Drupal::service('menu.link_tree')
      ->transform($tree, $manipulators);
    if (\Drupal::service('module_handler')
      ->moduleExists('i18n_menu')) {
      $tree = i18n_menu_localize_tree($tree, $GLOBALS['language']->language);
    }

    // Add an alter hook so that other modules can manipulate the
    // menu tree prior to rendering.
    $alter_mid = preg_replace('/[^a-z0-9_]+/', '_', $mid);
    \Drupal::moduleHandler()
      ->alter(array(
      'site_map_menu_tree',
      'site_map_menu_tree_' . $alter_mid,
    ), $tree, $menu);
    $menu_display = \Drupal::service('menu.link_tree')
      ->buildForSiteMap($tree);
    $menu_html = drupal_render($menu_display);
    if (!empty($menu_html)) {
      $title = $menu
        ->label();
      if (\Drupal::service('module_handler')
        ->moduleExists('i18n_string')) {
        $m_array = array(
          'menu',
          'menu',
          $menu['menu_name'],
          'title',
        );
        $title = i18n_string_plain($m_array, $title);
      }
      \Drupal::service('site_map.helper')
        ->setOption($options, 'show_titles', 1, 'show_titles', TRUE);
      $class[] = 'site-map-box-menu';
      $class[] = 'site-map-box-menu-' . $mid;
      $attributes = array(
        'class' => $class,
      );
      $site_map_box = array(
        '#theme' => 'site_map_box',
        '#title' => $title,
        '#content' => $menu_html,
        '#attributes' => $attributes,
        '#options' => $options,
      );
      $output .= drupal_render($site_map_box);
    }
  }
  return $output;
}

/**
 * Render the latest maps for faq.
 *
 * @return string
 *   Returns HTML string of site map for faq.
 */
function _site_map_faq() {
  $output = '';
  $options = array();
  if (\Drupal::service('module_handler')
    ->moduleExists('faq')) {
    $title = \Drupal::config('faq.settings')
      ->get('faq_title');
    $attributes = array(
      'class' => array(
        'site-map-box-faq',
      ),
    );
    $output = faq_get_faq_list();
    \Drupal::service('site_map.helper')
      ->setOption($options, 'show_titles', 1, 'show_titles', TRUE);
    $site_map_box = array(
      '#theme' => 'site_map_box',
      '#title' => $title,
      '#content' => $output,
      '#attributes' => $attributes,
      '#options' => $options,
    );
    $output = drupal_render($site_map_box);
  }
  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 string $tid
 *   The term's ID.
 *
 * @return string
 *   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];
}

Functions

Namesort descending Description
site_map_taxonomy_term_count_nodes Count the number of published nodes classified by a term.
site_map_theme Implements hook_theme().
_site_map_audio Render the latest maps for audio.
_site_map_blogs Render the latest blogs.
_site_map_books Render the latest maps for books.
_site_map_faq Render the latest maps for faq.
_site_map_front_page Menu callback for the site map front page.
_site_map_menus Render the latest maps for all the menus.
_site_map_video Render the latest maps for video.