You are here

function _toc_filter_process_callback in TOC filter 6

Same name and namespace in other branches
  1. 7 toc_filter.module \_toc_filter_process_callback()

TOC filter processor callback: Convert's <h2> to a linked table of contents.

1 call to _toc_filter_process_callback()
toc_filter_filter in ./toc_filter.module
Implementation of hook_filter().

File

./toc_filter.module, line 80
Converts header tags into a linked table of contents.

Code

function _toc_filter_process_callback($text) {
  if (stripos($text, '[toc') === FALSE || !preg_match('/(?:<p>)?\\s*\\[TOC(?::([a-z-]+))?([^\\]]+)?\\]\\s*(?:<\\/p>)?/i', $text, $matches)) {
    return $text;
  }
  $match = $matches[0];
  $type = !empty($matches[1]) ? drupal_strtolower($matches[1]) : 'ul';
  $title = !empty($matches[2]) ? trim($matches[2]) : '';

  // Set format based on type.
  switch ($type) {
    case 'jump-menu':
    case 'menu':
      $format = 'jump_menu';
      break;
    case 'faq':
      $format = 'faq';
      break;
    case 'number':
    case 'ol':
      $format = 'number';
      break;
    case 'ul':
    case 'bullet':
    default:
      $format = 'bullet';
      break;
  }
  $title = empty($title) ? variable_get('toc_filter_' . $format . '_default_title', '') : $title;
  $is_numbered = $format == 'number' || $format == 'faq' ? TRUE : FALSE;
  $header_tag = variable_get('toc_filter_header_tag', 'h3');
  preg_match_all('/(<' . $header_tag . '[^>]*>)(.*?)(<\\/' . $header_tag . '>)/s', $text, $header_matches);
  $targets = array();
  $links = array();
  for ($i = 0, $len = count($header_matches[0]); $i < $len; $i++) {
    $header_match = $header_matches[0][$i];
    $open_tag = $header_matches[1][$i];
    $header_title = $header_matches[2][$i];
    $close_tag = $header_matches[3][$i];
    $header_id = preg_replace('/[^-a-z0-9]+/', '-', drupal_strtolower(trim($header_title)));

    // Add header class to open tag
    $open_tag_attributes = toc_filter_parse_tag_attributes($open_tag) + array(
      'class' => '',
    );
    $open_tag_attributes['class'] .= (empty($open_tag_attributes['class']) ? '' : ' ') . 'toc-header toc-header-' . $format;
    $header_replace = '<' . $header_tag . drupal_attributes($open_tag_attributes) . '>' . '<a name="' . $header_id . '" id="' . $header_id . '" class="toc-bookmark" rel="bookmark" title="' . strip_tags($header_title) . '"></a>' . ($is_numbered ? '<span class="toc-number">' . ($i + 1) . '.  </span> ' : '') . $header_title . $close_tag;

    // Must manually build each link item since l() function can't generate just an anchor link (aka #anchor).
    $targets['#' . $header_id] = strip_tags($header_title);
    $links[] = '<a href="#' . $header_id . '">' . strip_tags($header_title, '<i><em><b><strong><br>') . '</a>';

    // Add anchor before header
    $back_to_top = theme('toc_filter_back_to_top', $i == 0 ? 'first' : '');
    $text = str_replace($header_match, $back_to_top . $header_replace, $text);
  }

  // If no TOC links found then just remove the [toc] tag and return the text.
  if (empty($links)) {
    return str_replace($match, '', $text);
  }

  // Theme list
  $links_list_type = $is_numbered ? 'ol' : 'ul';
  $toc_content = theme('item_list', $links, check_plain($title), $links_list_type, array(
    'class' => 'toc-filter-links',
  ));
  $output = theme('toc_filter', $format, $toc_content);

  // Add jump menu with noscript list.
  if ($format == 'jump_menu' && module_exists('ctools')) {
    $options = array();
    if ($title) {
      $options['choose'] = check_plain($title);
    }
    ctools_include('jump-menu');
    $output = '<div class="toc-filter-jump-menu">' . drupal_get_form('ctools_jump_menu', $targets, $options) . '</div>' . '<noscript>' . $output . '</noscript>';
  }

  // Prepend #top
  $output = '<a name="top"></a>' . $output;

  // Replace matched text with output.
  $text = str_replace($match, $output, $text);

  // Add closing back to top.
  $text .= theme('toc_filter_back_to_top', 'last');
  return $text;
}