You are here

book_helper.module in Book helper 6

Same filename and directory in other branches
  1. 7 book_helper.module

Improves Drupal's core book module's functionality.

File

book_helper.module
View source
<?php

/**
 * @file
 * Improves Drupal's core book module's functionality.
 */

/**
 * Implementation of hook_help().
 */
function book_helper_help($path, $arg) {
  switch ($path) {
    case 'node/%/delete':
      book_helper_display_delete_book_page_warning($arg[1]);
      break;
  }
}

/**
 * Implementation of hook_perm().
 */
function book_helper_perm() {
  return array(
    'administer own book outlines',
  );
}

/**
 * Implementation of hook_menu().
 */
function book_helper_menu() {

  // Adds an order tab to book's main node.
  $items['node/%node/order'] = array(
    'title' => 'Order',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'book_helper_admin_edit',
      1,
    ),
    'access callback' => '_book_helper_access',
    'access arguments' => array(
      1,
    ),
    'type' => MENU_LOCAL_TASK,
    'weight' => 2,
    'file' => 'book_helper.admin.inc',
  );
  return $items;
}

/**
 * Implementation of hook_menu_alter(). Overrides the books outline page.
 *
 * @see book.module
 */
function book_helper_menu_alter(&$items) {

  // Hijack the book.module's 'edit order and titles' page. (admin/content/book/%node)
  // This allows us to add the hide/show checkbox to order book form.
  $items['admin/content/book/%node']['page arguments'] = array(
    'book_helper_admin_edit',
    3,
  );
  $items['admin/content/book/%node']['file'] = 'book_helper.admin.inc';
  $items['admin/content/book/%node']['file path'] = drupal_get_path('module', 'book_helper');

  // Remove outline tab.
  if (variable_get('book_helper_remove_outline', '0') == '1') {
    unset($items['node/%node/outline']);
  }
}

/**
 * Implementation of hook_menu_link_alter().
 */
function book_helper_menu_link_alter(&$item, $menu) {

  // Book module does not support hidden pages so we need to manually
  // preserve it when a book page is updated outside of the book helper
  // module's node/%/order page.
  if (isset($item['module']) && $item['module'] == 'book' && isset($item['mlid']) && !isset($item['hidden'])) {
    $item['hidden'] = db_result(db_query('SELECT hidden FROM {menu_links} WHERE mlid=%d', $item['mlid']));
  }
}

/**
 * Menu callback access; Determine if the order book tab is accessible.
 */
function _book_helper_access($node) {
  global $user;
  $is_node_book = isset($node->book['bid']) && $node->book['bid'] == $node->nid;
  if (!$is_node_book) {
    return FALSE;
  }

  // Allow users to administer their own books using 'administer own book outlines'
  if (user_access('administer own book outlines') && $node->uid === $user->uid) {
    return TRUE;
  }
  return _book_outline_access($node);
}

/**
 * Implementation of hook_nodeapi().
 */
function book_helper_nodeapi(&$node, $op, $teaser = NULL, $page = NULL) {
  switch ($op) {
    case 'view':

      // Remove book navigation.
      if (variable_get('book_helper_remove_book_navigation', 0) == 1) {
        unset($node->content['book_navigation']);
      }
      break;
    case 'load':

      // Track customized link title and whether it is sync (equal) to the node's title.
      $link_title = db_result(db_query('SELECT link_title FROM {book} b INNER JOIN {menu_links} ml ON b.mlid = ml.mlid WHERE b.nid = %d', $node->nid));
      if ($link_title) {
        $node_title = function_exists('node_parent_title_remove') ? node_parent_title_remove($node->title) : $node->title;
        $info['book_helper']['link_title_custom'] = $link_title;
        $info['book_helper']['link_title_sync'] = $link_title == $node_title ? TRUE : FALSE;
        return $info;
      }
      break;
    case 'insert':
    case 'update':

      // Get link title sync and custom from the book.module's array().
      if (isset($node->book['book_helper_link_title_sync'])) {
        $node->book_helper['link_title_sync'] = $node->book['book_helper_link_title_sync'];
      }
      if (isset($node->book['book_helper_link_title_custom'])) {
        $node->book_helper['link_title_custom'] = $node->book['book_helper_link_title_custom'];
      }

      // Update the book page's menu link title if it has been customized.
      if (!empty($node->book['bid']) && empty($node->book_helper['link_title_sync']) && $node->book_helper['link_title_custom'] != $node->book['link_title']) {
        db_query("UPDATE {menu_links} SET link_title='%s' WHERE mlid = %d", $node->book_helper['link_title_custom'], $node->book['mlid']);
      }
      break;
    default:
      break;
  }
}

/**
 * Implementation of hook_block().
 */
function book_helper_block($op = 'list', $delta = 0, $edit = array()) {
  switch ($op) {
    case 'list':
      $blocks['book-helper-inline-navigation'] = array(
        'info' => t('Book (inline) navigation'),
      );
      return $blocks;
    case 'view':
      $node = menu_get_object();
      if (!$node || !isset($node->book['bid'])) {
        return NULL;
      }
      else {
        return array(
          'content' => theme('book_navigation', $node->book),
        );
      }
    default:
      return;
  }
}

/**
 * Implementation of hook_form_FORM_ID_alter().
 */
function book_helper_form_book_admin_settings_alter(&$form, &$form_state) {
  module_load_include('inc', 'book_helper', 'book_helper.admin');
  _book_helper_form_book_admin_settings_alter($form, $form_state);
}

/**
 * Implementation of hook_form_alter().
 */
function book_helper_form_alter(&$form, &$form_state, $form_id) {
  if ($form['#id'] == 'node-form') {
    $node =& $form['#node'];
    $type = $form['type']['#value'];
    if (isset($form['book']) && !book_type_is_allowed($type) && empty($node->book['bid'])) {

      // Hide book fieldset.
      $form['book']['#access'] = FALSE;
    }
    elseif (!isset($node->nid) && !isset($_GET['parent']) && in_array($type, variable_get('book_helper_create_new', array()))) {

      // Create new book for selected nodes that are not being added as child pages.
      $node->book['bid'] == 'new';
      $form['book']['bid']['#default_value'] = 'new';
    }
    if (isset($form['book'])) {

      // Define default book helper properties.
      if (!isset($node->book_helper)) {
        $node->book_helper = array(
          'link_title_custom' => $node->title,
          'link_title_sync' => TRUE,
        );
      }

      // Add inputs to allow user to customize the book link title separately from the node's title.
      drupal_add_js(drupal_get_path('module', 'book_helper') . '/book_helper.js');
      $form['book']['book_helper_link_title_custom'] = array(
        '#type' => 'textfield',
        '#title' => t('Book link title'),
        '#default_value' => $node->book_helper['link_title_custom'],
        '#maxlength' => 255,
      );
      $form['book']['book_helper_link_title_sync'] = array(
        '#type' => 'checkbox',
        '#title' => t("Syncronize this node's title with its book link title."),
        '#default_value' => $node->book_helper['link_title_sync'],
      );
    }
  }
}

/**
 * Implementation of hook_link_alter().
 */
function book_helper_link_alter(&$links, $node, $comment = NULL) {
  $book_link_names = array(
    'book_add_child',
    'book_printer',
  );
  $book_helper_links = variable_get('book_helper_links', $book_link_names);
  foreach ($book_link_names as $book_link_name) {
    if (isset($links[$book_link_name]) && (empty($book_helper_links) || !in_array($book_link_name, $book_helper_links))) {
      unset($links[$book_link_name]);
    }
  }
}

////////////////////////////////////////////////////////////////////////////////

// Utility functions

////////////////////////////////////////////////////////////////////////////////

/**
 * Display a warning warning when deleting a book page that has child pages.
 */
function book_helper_display_delete_book_page_warning($nid) {
  $node = node_load($nid);
  if (isset($node->book) && $node->book['bid'] != $node->nid) {
    $book_node = node_load($node->book['bid']);
    $result = db_query('SELECT mlid, link_title AS title, link_path AS href FROM {menu_links} WHERE plid=%d ORDER BY weight', $node->book['mlid']);
    $links = array();
    while ($record = db_fetch_array($result)) {
      $links[$record['mlid']] = $record;
    }
    if (empty($links)) {
      return;
    }
    $t_args = array(
      '!book' => l($book_node->title, 'node' . $book_node->nid),
    );
    $output = t('The below book pages are not going to be deleted, they will be moved to the root of the !book book.', $t_args) . '<br />' . t('It is recommended that you delete or move these pages before proceeding.') . theme('links', $links, array());
    drupal_set_message($output, 'warning');
  }
}

////////////////////////////////////////////////////////////////////////////////

// Theme functions

////////////////////////////////////////////////////////////////////////////////

/**
 * Implementation of hook_theme_registry_alter(). Remove template_preprocess_book_navigation();
 *
 * Prevent book_navigation variables from being preprocessed multiple times.
 */
function book_helper_theme_registry_alter(&$theme_registry) {
  if (isset($theme_registry['book_navigation']['preprocess functions']) && is_array($theme_registry['book_navigation']['preprocess functions'])) {
    $theme_registry['book_navigation']['preprocess functions'] = array_diff($theme_registry['book_navigation']['preprocess functions'], array(
      'template_preprocess_book_navigation',
    ));
  }
}

/**
 * Override; Process variables for book-navigation.tpl.php.
 */
function book_helper_preprocess_book_navigation(&$variables) {
  $navigation_options = variable_get('book_helper_navigation_options', array(
    'tree',
    'prev',
    'next',
    'up',
  ));

  // Below code is copied from template_preprocess_book_navigation();
  $book_link = $variables['book_link'];

  // Provide extra variables for themers. Not needed by default.
  $variables['book_id'] = $book_link['bid'];
  $variables['book_title'] = check_plain($book_link['link_title']);
  $variables['book_url'] = 'node/' . $book_link['bid'];
  $variables['current_depth'] = $book_link['depth'];
  $variables['tree'] = '';
  if ($book_link['mlid']) {
    if (in_array('tree', $navigation_options)) {
      $variables['tree'] = book_children($book_link);
    }
    if (in_array('prev', $navigation_options) && ($prev = book_prev($book_link))) {
      $prev_href = url($prev['href']);
      drupal_add_link(array(
        'rel' => 'prev',
        'href' => $prev_href,
      ));
      $variables['prev_url'] = $prev_href;
      $variables['prev_title'] = check_plain($prev['title']);
    }
    if (in_array('up', $navigation_options) && $book_link['plid'] && ($parent = book_link_load($book_link['plid']))) {
      $parent_href = url($parent['href']);
      drupal_add_link(array(
        'rel' => 'up',
        'href' => $parent_href,
      ));
      $variables['parent_url'] = $parent_href;
      $variables['parent_title'] = check_plain($parent['title']);
    }
    if (in_array('next', $navigation_options) && ($next = book_next($book_link))) {
      $next_href = url($next['href']);
      drupal_add_link(array(
        'rel' => 'next',
        'href' => $next_href,
      ));
      $variables['next_url'] = $next_href;
      $variables['next_title'] = check_plain($next['title']);
    }
  }
  $variables['has_links'] = FALSE;

  // Link variables to filter for values and set state of the flag variable.
  $links = array(
    'prev_url',
    'prev_title',
    'parent_url',
    'parent_title',
    'next_url',
    'next_title',
  );
  foreach ($links as $link) {
    if (isset($variables[$link])) {

      // Flag when there is a value.
      $variables['has_links'] = TRUE;
    }
    else {

      // Set empty to prevent notices.
      $variables[$link] = '';
    }
  }
}

/**
 * Implementation of hook_theme().
 */
function book_helper_theme() {
  return array(
    'book_helper_admin_table' => array(
      'arguments' => array(
        'form' => NULL,
      ),
      'file' => 'book_helper.admin.inc',
    ),
  );
}

Functions

Namesort descending Description
book_helper_block Implementation of hook_block().
book_helper_display_delete_book_page_warning Display a warning warning when deleting a book page that has child pages.
book_helper_form_alter Implementation of hook_form_alter().
book_helper_form_book_admin_settings_alter Implementation of hook_form_FORM_ID_alter().
book_helper_help Implementation of hook_help().
book_helper_link_alter Implementation of hook_link_alter().
book_helper_menu Implementation of hook_menu().
book_helper_menu_alter Implementation of hook_menu_alter(). Overrides the books outline page.
book_helper_menu_link_alter Implementation of hook_menu_link_alter().
book_helper_nodeapi Implementation of hook_nodeapi().
book_helper_perm Implementation of hook_perm().
book_helper_preprocess_book_navigation Override; Process variables for book-navigation.tpl.php.
book_helper_theme Implementation of hook_theme().
book_helper_theme_registry_alter Implementation of hook_theme_registry_alter(). Remove template_preprocess_book_navigation();
_book_helper_access Menu callback access; Determine if the order book tab is accessible.