Initial code using Drupal 6.38
This commit is contained in:
commit
4824608a33
467 changed files with 90887 additions and 0 deletions
21
modules/book/book-all-books-block.tpl.php
Normal file
21
modules/book/book-all-books-block.tpl.php
Normal file
|
@ -0,0 +1,21 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file book-all-books-block.tpl.php
|
||||
* Default theme implementation for rendering book outlines within a block.
|
||||
* This template is used only when the block is configured to "show block on
|
||||
* all pages" which presents Multiple independent books on all pages.
|
||||
*
|
||||
* Available variables:
|
||||
* - $book_menus: Array of book outlines rendered as an unordered list. It is
|
||||
* keyed to the parent book ID which is also the ID of the parent node
|
||||
* containing an entire outline.
|
||||
*
|
||||
* @see template_preprocess_book_all_books_block()
|
||||
*/
|
||||
?>
|
||||
<?php foreach ($book_menus as $book_id => $menu) : ?>
|
||||
<div id="book-block-menu-<?php print $book_id; ?>" class="book-block-menu">
|
||||
<?php print $menu; ?>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
52
modules/book/book-export-html.tpl.php
Normal file
52
modules/book/book-export-html.tpl.php
Normal file
|
@ -0,0 +1,52 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file book-export-html.tpl.php
|
||||
* Default theme implementation for printed version of book outline.
|
||||
*
|
||||
* Available variables:
|
||||
* - $title: Top level node title.
|
||||
* - $head: Header tags.
|
||||
* - $language: Language code. e.g. "en" for english.
|
||||
* - $language_rtl: TRUE or FALSE depending on right to left language scripts.
|
||||
* - $base_url: URL to home page.
|
||||
* - $content: Nodes within the current outline rendered through
|
||||
* book-node-export-html.tpl.php.
|
||||
*
|
||||
* @see template_preprocess_book_export_html()
|
||||
*/
|
||||
?>
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" lang="<?php print $language->language; ?>" xml:lang="<?php print $language->language; ?>">
|
||||
<head>
|
||||
<?php print $head; ?>
|
||||
<title><?php print $title; ?></title>
|
||||
<base href="<?php print $base_url; ?>" />
|
||||
<link type="text/css" rel="stylesheet" href="misc/print.css" />
|
||||
<?php if ($language_rtl): ?>
|
||||
<link type="text/css" rel="stylesheet" href="misc/print-rtl.css" />
|
||||
<?php endif; ?>
|
||||
</head>
|
||||
<body>
|
||||
<?php
|
||||
/**
|
||||
* The given node is /embedded to its absolute depth in a top level
|
||||
* section/. For example, a child node with depth 2 in the hierarchy is
|
||||
* contained in (otherwise empty) <div> elements corresponding to
|
||||
* depth 0 and depth 1. This is intended to support WYSIWYG output - e.g.,
|
||||
* level 3 sections always look like level 3 sections, no matter their
|
||||
* depth relative to the node selected to be exported as printer-friendly
|
||||
* HTML.
|
||||
*/
|
||||
$div_close = '';
|
||||
?>
|
||||
<?php for ($i = 1; $i < $depth; $i++) : ?>
|
||||
<div class="section-<?php print $i; ?>">
|
||||
<?php $div_close .= '</div>'; ?>
|
||||
<?php endfor; ?>
|
||||
|
||||
<?php print $contents; ?>
|
||||
<?php print $div_close; ?>
|
||||
|
||||
</body>
|
||||
</html>
|
51
modules/book/book-navigation.tpl.php
Normal file
51
modules/book/book-navigation.tpl.php
Normal file
|
@ -0,0 +1,51 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file book-navigation.tpl.php
|
||||
* Default theme implementation to navigate books. Presented under nodes that
|
||||
* are a part of book outlines.
|
||||
*
|
||||
* Available variables:
|
||||
* - $tree: The immediate children of the current node rendered as an
|
||||
* unordered list.
|
||||
* - $current_depth: Depth of the current node within the book outline.
|
||||
* Provided for context.
|
||||
* - $prev_url: URL to the previous node.
|
||||
* - $prev_title: Title of the previous node.
|
||||
* - $parent_url: URL to the parent node.
|
||||
* - $parent_title: Title of the parent node. Not printed by default. Provided
|
||||
* as an option.
|
||||
* - $next_url: URL to the next node.
|
||||
* - $next_title: Title of the next node.
|
||||
* - $has_links: Flags TRUE whenever the previous, parent or next data has a
|
||||
* value.
|
||||
* - $book_id: The book ID of the current outline being viewed. Same as the
|
||||
* node ID containing the entire outline. Provided for context.
|
||||
* - $book_url: The book/node URL of the current outline being viewed.
|
||||
* Provided as an option. Not used by default.
|
||||
* - $book_title: The book/node title of the current outline being viewed.
|
||||
* Provided as an option. Not used by default.
|
||||
*
|
||||
* @see template_preprocess_book_navigation()
|
||||
*/
|
||||
?>
|
||||
<?php if ($tree || $has_links): ?>
|
||||
<div id="book-navigation-<?php print $book_id; ?>" class="book-navigation">
|
||||
<?php print $tree; ?>
|
||||
|
||||
<?php if ($has_links): ?>
|
||||
<div class="page-links clear-block">
|
||||
<?php if ($prev_url) : ?>
|
||||
<a href="<?php print $prev_url; ?>" class="page-previous" title="<?php print t('Go to previous page'); ?>"><?php print t('‹ ') . $prev_title; ?></a>
|
||||
<?php endif; ?>
|
||||
<?php if ($parent_url) : ?>
|
||||
<a href="<?php print $parent_url; ?>" class="page-up" title="<?php print t('Go to parent page'); ?>"><?php print t('up'); ?></a>
|
||||
<?php endif; ?>
|
||||
<?php if ($next_url) : ?>
|
||||
<a href="<?php print $next_url; ?>" class="page-next" title="<?php print t('Go to next page'); ?>"><?php print $next_title . t(' ›'); ?></a>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
</div>
|
||||
<?php endif; ?>
|
24
modules/book/book-node-export-html.tpl.php
Normal file
24
modules/book/book-node-export-html.tpl.php
Normal file
|
@ -0,0 +1,24 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file book-node-export-html.tpl.php
|
||||
* Default theme implementation for rendering a single node in a printer
|
||||
* friendly outline.
|
||||
*
|
||||
* @see book-node-export-html.tpl.php
|
||||
* Where it is collected and printed out.
|
||||
*
|
||||
* Available variables:
|
||||
* - $depth: Depth of the current node inside the outline.
|
||||
* - $title: Node title.
|
||||
* - $content: Node content.
|
||||
* - $children: All the child nodes recursively rendered through this file.
|
||||
*
|
||||
* @see template_preprocess_book_node_export_html()
|
||||
*/
|
||||
?>
|
||||
<div id="node-<?php print $node->nid; ?>" class="section-<?php print $depth; ?>">
|
||||
<h1 class="book-heading"><?php print $title; ?></h1>
|
||||
<?php print $content; ?>
|
||||
<?php print $children; ?>
|
||||
</div>
|
7
modules/book/book-rtl.css
Normal file
7
modules/book/book-rtl.css
Normal file
|
@ -0,0 +1,7 @@
|
|||
|
||||
.book-navigation .page-previous {
|
||||
float: right;
|
||||
}
|
||||
.book-navigation .page-up {
|
||||
float: right;
|
||||
}
|
249
modules/book/book.admin.inc
Normal file
249
modules/book/book.admin.inc
Normal file
|
@ -0,0 +1,249 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Admin page callbacks for the book module.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Returns an administrative overview of all books.
|
||||
*/
|
||||
function book_admin_overview() {
|
||||
$rows = array();
|
||||
foreach (book_get_books() as $book) {
|
||||
$rows[] = array(l($book['title'], $book['href'], $book['options']), l(t('edit order and titles'), "admin/content/book/". $book['nid']));
|
||||
}
|
||||
$headers = array(t('Book'), t('Operations'));
|
||||
|
||||
return theme('table', $headers, $rows);
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds and returns the book settings form.
|
||||
*
|
||||
* @see book_admin_settings_validate()
|
||||
*
|
||||
* @ingroup forms
|
||||
*/
|
||||
function book_admin_settings() {
|
||||
$types = node_get_types('names');
|
||||
$form['book_allowed_types'] = array(
|
||||
'#type' => 'checkboxes',
|
||||
'#title' => t('Allowed book outline types'),
|
||||
'#default_value' => variable_get('book_allowed_types', array('book')),
|
||||
'#options' => $types,
|
||||
'#description' => t('Select content types which users with the %add-perm permission will be allowed to add to the book hierarchy. Users with the %outline-perm permission can add all content types.', array('%add-perm' => t('add content to books'), '%outline-perm' => t('administer book outlines'))),
|
||||
'#required' => TRUE,
|
||||
);
|
||||
$form['book_child_type'] = array(
|
||||
'#type' => 'radios',
|
||||
'#title' => t('Default child page type'),
|
||||
'#default_value' => variable_get('book_child_type', 'book'),
|
||||
'#options' => $types,
|
||||
'#description' => t('The content type for the %add-child link must be one of those selected as an allowed book outline type.', array('%add-child' => t('Add child page'))),
|
||||
'#required' => TRUE,
|
||||
);
|
||||
$form['array_filter'] = array('#type' => 'value', '#value' => TRUE);
|
||||
$form['#validate'][] = 'book_admin_settings_validate';
|
||||
return system_settings_form($form);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate the book settings form.
|
||||
*
|
||||
* @see book_admin_settings()
|
||||
*/
|
||||
function book_admin_settings_validate($form, &$form_state) {
|
||||
$child_type = $form_state['values']['book_child_type'];
|
||||
if (empty($form_state['values']['book_allowed_types'][$child_type])) {
|
||||
form_set_error('book_child_type', t('The content type for the %add-child link must be one of those selected as an allowed book outline type.', array('%add-child' => t('Add child page'))));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the form to administrate the hierarchy of a single book.
|
||||
*
|
||||
* @see book_admin_edit_submit()
|
||||
*
|
||||
* @ingroup forms.
|
||||
*/
|
||||
function book_admin_edit($form_state, $node) {
|
||||
drupal_set_title(check_plain($node->title));
|
||||
$form = array();
|
||||
$form['#node'] = $node;
|
||||
_book_admin_table($node, $form);
|
||||
$form['save'] = array(
|
||||
'#type' => 'submit',
|
||||
'#value' => t('Save book pages'),
|
||||
);
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check that the book has not been changed while using the form.
|
||||
*
|
||||
* @see book_admin_edit()
|
||||
*/
|
||||
function book_admin_edit_validate($form, &$form_state) {
|
||||
if ($form_state['values']['tree_hash'] != $form_state['values']['tree_current_hash']) {
|
||||
form_set_error('', t('This book has been modified by another user, the changes could not be saved.'));
|
||||
$form_state['rebuild'] = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle submission of the book administrative page form.
|
||||
*
|
||||
* This function takes care to save parent menu items before their children.
|
||||
* Saving menu items in the incorrect order can break the menu tree.
|
||||
*
|
||||
* @see book_admin_edit()
|
||||
* @see menu_overview_form_submit()
|
||||
*/
|
||||
function book_admin_edit_submit($form, &$form_state) {
|
||||
// Save elements in the same order as defined in post rather than the form.
|
||||
// This ensures parents are updated before their children, preventing orphans.
|
||||
$order = array_flip(array_keys($form['#post']['table']));
|
||||
$form['table'] = array_merge($order, $form['table']);
|
||||
|
||||
foreach (element_children($form['table']) as $key) {
|
||||
if ($form['table'][$key]['#item']) {
|
||||
$row = $form['table'][$key];
|
||||
$values = $form_state['values']['table'][$key];
|
||||
|
||||
// Update menu item if moved.
|
||||
if ($row['plid']['#default_value'] != $values['plid'] || $row['weight']['#default_value'] != $values['weight']) {
|
||||
$row['#item']['plid'] = $values['plid'];
|
||||
$row['#item']['weight'] = $values['weight'];
|
||||
menu_link_save($row['#item']);
|
||||
}
|
||||
|
||||
// Update the title if changed.
|
||||
if ($row['title']['#default_value'] != $values['title']) {
|
||||
$node = node_load($values['nid'], FALSE);
|
||||
$node->title = $values['title'];
|
||||
$node->book['link_title'] = $values['title'];
|
||||
$node->revision = 1;
|
||||
$node->log = t('Title changed from %original to %current.', array('%original' => $node->title, '%current' => $values['title']));
|
||||
node_save($node);
|
||||
watchdog('content', 'book: updated %title.', array('%title' => $node->title), WATCHDOG_NOTICE, l(t('view'), 'node/'. $node->nid));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
drupal_set_message(t('Updated book %title.', array('%title' => $form['#node']->title)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the table portion of the form for the book administration page.
|
||||
*
|
||||
* @see book_admin_edit()
|
||||
*/
|
||||
function _book_admin_table($node, &$form) {
|
||||
$form['table'] = array(
|
||||
'#theme' => 'book_admin_table',
|
||||
'#tree' => TRUE,
|
||||
);
|
||||
|
||||
$tree = book_menu_subtree_data($node->book);
|
||||
$tree = array_shift($tree); // Do not include the book item itself.
|
||||
if ($tree['below']) {
|
||||
$hash = sha1(serialize($tree['below']));
|
||||
// Store the hash value as a hidden form element so that we can detect
|
||||
// if another user changed the book hierarchy.
|
||||
$form['tree_hash'] = array(
|
||||
'#type' => 'hidden',
|
||||
'#default_value' => $hash,
|
||||
);
|
||||
$form['tree_current_hash'] = array(
|
||||
'#type' => 'value',
|
||||
'#value' => $hash,
|
||||
);
|
||||
_book_admin_table_tree($tree['below'], $form['table']);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursive helper to build the main table in the book administration page form.
|
||||
*
|
||||
* @see book_admin_edit()
|
||||
*/
|
||||
function _book_admin_table_tree($tree, &$form) {
|
||||
foreach ($tree as $data) {
|
||||
$form['book-admin-'. $data['link']['nid']] = array(
|
||||
'#item' => $data['link'],
|
||||
'nid' => array('#type' => 'value', '#value' => $data['link']['nid']),
|
||||
'depth' => array('#type' => 'value', '#value' => $data['link']['depth']),
|
||||
'href' => array('#type' => 'value', '#value' => $data['link']['href']),
|
||||
'title' => array(
|
||||
'#type' => 'textfield',
|
||||
'#default_value' => $data['link']['link_title'],
|
||||
'#maxlength' => 255,
|
||||
'#size' => 40,
|
||||
),
|
||||
'weight' => array(
|
||||
'#type' => 'weight',
|
||||
'#default_value' => $data['link']['weight'],
|
||||
'#delta' => 15,
|
||||
),
|
||||
'plid' => array(
|
||||
'#type' => 'textfield',
|
||||
'#default_value' => $data['link']['plid'],
|
||||
'#size' => 6,
|
||||
),
|
||||
'mlid' => array(
|
||||
'#type' => 'hidden',
|
||||
'#default_value' => $data['link']['mlid'],
|
||||
),
|
||||
);
|
||||
if ($data['below']) {
|
||||
_book_admin_table_tree($data['below'], $form);
|
||||
}
|
||||
}
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* Theme function for the book administration page form.
|
||||
*
|
||||
* @ingroup themeable
|
||||
* @see book_admin_table()
|
||||
*/
|
||||
function theme_book_admin_table($form) {
|
||||
drupal_add_tabledrag('book-outline', 'match', 'parent', 'book-plid', 'book-plid', 'book-mlid', TRUE, MENU_MAX_DEPTH - 2);
|
||||
drupal_add_tabledrag('book-outline', 'order', 'sibling', 'book-weight');
|
||||
|
||||
$header = array(t('Title'), t('Weight'), t('Parent'), array('data' => t('Operations'), 'colspan' => '3'));
|
||||
|
||||
$rows = array();
|
||||
$destination = drupal_get_destination();
|
||||
$access = user_access('administer nodes');
|
||||
foreach (element_children($form) as $key) {
|
||||
$nid = $form[$key]['nid']['#value'];
|
||||
$href = $form[$key]['href']['#value'];
|
||||
|
||||
// Add special classes to be used with tabledrag.js.
|
||||
$form[$key]['plid']['#attributes']['class'] = 'book-plid';
|
||||
$form[$key]['mlid']['#attributes']['class'] = 'book-mlid';
|
||||
$form[$key]['weight']['#attributes']['class'] = 'book-weight';
|
||||
|
||||
$data = array(
|
||||
theme('indentation', $form[$key]['depth']['#value'] - 2) . drupal_render($form[$key]['title']),
|
||||
drupal_render($form[$key]['weight']),
|
||||
drupal_render($form[$key]['plid']) . drupal_render($form[$key]['mlid']),
|
||||
l(t('view'), $href),
|
||||
$access ? l(t('edit'), 'node/'. $nid .'/edit', array('query' => $destination)) : ' ',
|
||||
$access ? l(t('delete'), 'node/'. $nid .'/delete', array('query' => $destination) ) : ' ',
|
||||
);
|
||||
$row = array('data' => $data);
|
||||
if (isset($form[$key]['#attributes'])) {
|
||||
$row = array_merge($row, $form[$key]['#attributes']);
|
||||
}
|
||||
$row['class'] = empty($row['class']) ? 'draggable' : $row['class'] .' draggable';
|
||||
$rows[] = $row;
|
||||
}
|
||||
|
||||
return theme('table', $header, $rows, array('id' => 'book-outline'));
|
||||
}
|
||||
|
51
modules/book/book.css
Normal file
51
modules/book/book.css
Normal file
|
@ -0,0 +1,51 @@
|
|||
|
||||
.book-navigation .menu {
|
||||
border-top: 1px solid #888;
|
||||
padding: 1em 0 0 3em;
|
||||
}
|
||||
.book-navigation .page-links {
|
||||
border-top: 1px solid #888;
|
||||
border-bottom: 1px solid #888;
|
||||
text-align: center;
|
||||
padding: 0.5em;
|
||||
}
|
||||
.book-navigation .page-previous {
|
||||
text-align: left;
|
||||
width: 42%;
|
||||
display: block;
|
||||
float: left; /* LTR */
|
||||
}
|
||||
.book-navigation .page-up {
|
||||
margin: 0 5%;
|
||||
width: 4%;
|
||||
display: block;
|
||||
float: left; /* LTR */
|
||||
}
|
||||
.book-navigation .page-next {
|
||||
text-align: right;
|
||||
width: 42%;
|
||||
display: block;
|
||||
float: right;
|
||||
}
|
||||
#book-outline {
|
||||
min-width: 56em;
|
||||
}
|
||||
.book-outline-form .form-item {
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
#edit-book-bid-wrapper .description {
|
||||
clear: both;
|
||||
}
|
||||
#book-admin-edit select {
|
||||
margin-right: 24px;
|
||||
}
|
||||
#book-admin-edit select.progress-disabled {
|
||||
margin-right: 0;
|
||||
}
|
||||
#book-admin-edit tr.ahah-new-content {
|
||||
background-color: #ffd;
|
||||
}
|
||||
#book-admin-edit .form-item {
|
||||
float: left;
|
||||
}
|
11
modules/book/book.info
Normal file
11
modules/book/book.info
Normal file
|
@ -0,0 +1,11 @@
|
|||
name = Book
|
||||
description = Allows users to structure site pages in a hierarchy or outline.
|
||||
package = Core - optional
|
||||
version = VERSION
|
||||
core = 6.x
|
||||
|
||||
; Information added by Drupal.org packaging script on 2016-02-24
|
||||
version = "6.38"
|
||||
project = "drupal"
|
||||
datestamp = "1456343372"
|
||||
|
289
modules/book/book.install
Normal file
289
modules/book/book.install
Normal file
|
@ -0,0 +1,289 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Implementation of hook_install().
|
||||
*/
|
||||
function book_install() {
|
||||
// Create tables.
|
||||
drupal_install_schema('book');
|
||||
// Add the node type.
|
||||
_book_install_type_create();
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of hook_uninstall().
|
||||
*/
|
||||
function book_uninstall() {
|
||||
// Delete menu links.
|
||||
db_query("DELETE FROM {menu_links} WHERE module = 'book'");
|
||||
menu_cache_clear_all();
|
||||
// Remove tables.
|
||||
drupal_uninstall_schema('book');
|
||||
}
|
||||
|
||||
function _book_install_type_create() {
|
||||
// Create an additional node type
|
||||
$book_node_type = array(
|
||||
'type' => 'book',
|
||||
'name' => t('Book page'),
|
||||
'module' => 'node',
|
||||
'description' => t('A <em>book page</em> is a page of content, organized into a collection of related entries collectively known as a <em>book</em>. A <em>book page</em> automatically displays links to adjacent pages, providing a simple navigation system for organizing and reviewing structured content.'),
|
||||
'custom' => TRUE,
|
||||
'modified' => TRUE,
|
||||
'locked' => FALSE,
|
||||
);
|
||||
|
||||
$book_node_type = (object)_node_type_set_defaults($book_node_type);
|
||||
node_type_save($book_node_type);
|
||||
// Default to not promoted.
|
||||
variable_set('node_options_book', array('status'));
|
||||
// Use this default type for adding content to books.
|
||||
variable_set('book_allowed_types', array('book'));
|
||||
variable_set('book_child_type', 'book');
|
||||
}
|
||||
|
||||
/**
|
||||
* Drupal 5.x to 6.x update.
|
||||
*
|
||||
* This function moves any existing book hierarchy into the new structure used
|
||||
* in the 6.x module. Rather than storing the hierarchy in the {book} table,
|
||||
* the menu API is used to store the hierarchy in the {menu_links} table and the
|
||||
* {book} table serves to uniquely connect a node to a menu link.
|
||||
*
|
||||
* In order to accomplish this, the current hierarchy is processed using a stack.
|
||||
* The stack insures that each parent is processed before any of its children
|
||||
* in the book hierarchy, and is compatible with batched update processing.
|
||||
*
|
||||
*/
|
||||
function book_update_6000() {
|
||||
$ret = array();
|
||||
|
||||
// Set up for a multi-part update.
|
||||
if (!isset($_SESSION['book_update_6000'])) {
|
||||
|
||||
$schema['book'] = array(
|
||||
'fields' => array(
|
||||
'mlid' => array('type' => 'int', 'unsigned' => TRUE, 'not null' => TRUE, 'default' => 0),
|
||||
'nid' => array('type' => 'int', 'unsigned' => TRUE, 'not null' => TRUE, 'default' => 0),
|
||||
'bid' => array('type' => 'int', 'unsigned' => TRUE, 'not null' => TRUE, 'default' => 0),
|
||||
),
|
||||
'primary key' => array('mlid'),
|
||||
'unique keys' => array(
|
||||
'nid' => array('nid'),
|
||||
),
|
||||
'indexes' => array(
|
||||
'bid' => array('bid'),
|
||||
),
|
||||
);
|
||||
// Add the node type.
|
||||
_book_install_type_create();
|
||||
|
||||
// Fix role permissions to account for the changed names
|
||||
// Setup the array holding strings to match and the corresponding
|
||||
// strings to replace them with.
|
||||
$replace = array(
|
||||
'outline posts in books' => 'administer book outlines',
|
||||
'create book pages' => 'create book content',
|
||||
'edit book pages' => 'edit any book content',
|
||||
'edit own book pages' => 'edit own book content',
|
||||
'see printer-friendly version' => 'access printer-friendly version',
|
||||
);
|
||||
|
||||
// Loop over all the roles, and do the necessary transformations.
|
||||
$query = db_query("SELECT rid, perm FROM {permission} ORDER BY rid");
|
||||
while ($role = db_fetch_object($query)) {
|
||||
// Replace all the old permissions with the corresponding new permissions.
|
||||
$fixed_perm = strtr($role->perm, $replace);
|
||||
// If the user could previously create book pages, they should get the new
|
||||
// 'add content to books' permission.
|
||||
if (strpos($role->perm, 'create book pages') !== FALSE) {
|
||||
$fixed_perm .= ', add content to books';
|
||||
}
|
||||
// Only save if the permissions have changed.
|
||||
if ($fixed_perm != $role->perm) {
|
||||
$ret[] = update_sql("UPDATE {permission} SET perm = '$fixed_perm' WHERE rid = $role->rid");
|
||||
}
|
||||
}
|
||||
|
||||
// Determine whether there are any existing nodes in the book hierarchy.
|
||||
if (db_result(db_query("SELECT COUNT(*) FROM {book}"))) {
|
||||
// Temporary table for the old book hierarchy; we'll discard revision info.
|
||||
$schema['book_temp'] = array(
|
||||
'fields' => array(
|
||||
'nid' => array('type' => 'int', 'unsigned' => TRUE, 'not null' => TRUE, 'default' => 0),
|
||||
'parent' => array('type' => 'int', 'not null' => TRUE, 'default' => 0),
|
||||
'weight' => array('type' => 'int', 'not null' => TRUE, 'default' => 0, 'size' => 'tiny')
|
||||
),
|
||||
'indexes' => array(
|
||||
'parent' => array('parent')
|
||||
),
|
||||
'primary key' => array('nid'),
|
||||
);
|
||||
|
||||
db_create_table($ret, 'book_temp', $schema['book_temp']);
|
||||
|
||||
// Insert each node in the old table into the temporary table.
|
||||
$ret[] = update_sql("INSERT INTO {book_temp} (nid, parent, weight) SELECT b.nid, b.parent, b.weight FROM {book} b INNER JOIN {node} n on b.vid = n.vid");
|
||||
$ret[] = update_sql("DROP TABLE {book}");
|
||||
|
||||
db_create_table($ret, 'book', $schema['book']);
|
||||
|
||||
$_SESSION['book_update_6000_orphans']['from'] = 0;
|
||||
$_SESSION['book_update_6000'] = array();
|
||||
$result = db_query("SELECT * from {book_temp} WHERE parent = 0");
|
||||
|
||||
// Collect all books - top-level nodes.
|
||||
while ($a = db_fetch_array($result)) {
|
||||
$_SESSION['book_update_6000'][] = $a;
|
||||
}
|
||||
$ret['#finished'] = FALSE;
|
||||
return $ret;
|
||||
}
|
||||
else {
|
||||
// No exising nodes in the hierarchy, so drop the table and re-create it.
|
||||
$ret[] = update_sql("DROP TABLE {book}");
|
||||
db_create_table($ret, 'book', $schema['book']);
|
||||
return $ret;
|
||||
}
|
||||
}
|
||||
elseif ($_SESSION['book_update_6000_orphans']) {
|
||||
// Do the first batched part of the update - collect orphans.
|
||||
$update_count = 400; // Update this many at a time
|
||||
|
||||
$result = db_query_range("SELECT * FROM {book_temp}", $_SESSION['book_update_6000_orphans']['from'], $update_count);
|
||||
$has_rows = FALSE;
|
||||
// Go through the next $update_count book pages and locate the orphans.
|
||||
while ($book = db_fetch_array($result)) {
|
||||
$has_rows = TRUE;
|
||||
// Orphans are defined as nodes whose parent does not exist in the table.
|
||||
if ($book['parent'] && !db_result(db_query("SELECT COUNT(*) FROM {book_temp} WHERE nid = %d", $book['parent']))) {
|
||||
if (empty($_SESSION['book_update_6000_orphans']['book'])) {
|
||||
// The first orphan becomes the parent for all other orphans.
|
||||
$book['parent'] = 0;
|
||||
$_SESSION['book_update_6000_orphans']['book'] = $book;
|
||||
$ret[] = array('success' => TRUE, 'query' => 'Relocated orphan book pages.');
|
||||
}
|
||||
else {
|
||||
// Re-assign the parent value of the book, and add it to the stack.
|
||||
$book['parent'] = $_SESSION['book_update_6000_orphans']['book']['nid'];
|
||||
$_SESSION['book_update_6000'][] = $book;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($has_rows) {
|
||||
$_SESSION['book_update_6000_orphans']['from'] += $update_count;
|
||||
}
|
||||
else {
|
||||
// Done with this part
|
||||
if (!empty($_SESSION['book_update_6000_orphans']['book'])) {
|
||||
// The orphans' parent is added last, so it will be processed first.
|
||||
$_SESSION['book_update_6000'][] = $_SESSION['book_update_6000_orphans']['book'];
|
||||
}
|
||||
$_SESSION['book_update_6000_orphans'] = FALSE;
|
||||
}
|
||||
$ret['#finished'] = FALSE;
|
||||
return $ret;
|
||||
}
|
||||
else {
|
||||
// Do the next batched part of the update
|
||||
$update_count = 100; // Update this many at a time
|
||||
|
||||
while ($update_count && $_SESSION['book_update_6000']) {
|
||||
// Get the last node off the stack.
|
||||
$book = array_pop($_SESSION['book_update_6000']);
|
||||
|
||||
// Add all of this node's children to the stack
|
||||
$result = db_query("SELECT * FROM {book_temp} WHERE parent = %d", $book['nid']);
|
||||
while ($a = db_fetch_array($result)) {
|
||||
$_SESSION['book_update_6000'][] = $a;
|
||||
}
|
||||
|
||||
if ($book['parent']) {
|
||||
// If its not a top level page, get its parent's mlid.
|
||||
$parent = db_fetch_array(db_query("SELECT b.mlid AS plid, b.bid FROM {book} b WHERE b.nid = %d", $book['parent']));
|
||||
$book = array_merge($book, $parent);
|
||||
}
|
||||
else {
|
||||
// There is not a parent - this is a new book.
|
||||
$book['plid'] = 0;
|
||||
$book['bid'] = $book['nid'];
|
||||
}
|
||||
|
||||
$book += array(
|
||||
'module' => 'book',
|
||||
'link_path' => 'node/'. $book['nid'],
|
||||
'router_path' => 'node/%',
|
||||
'menu_name' => 'book-toc-'. $book['bid'],
|
||||
);
|
||||
$book = array_merge($book, db_fetch_array(db_query("SELECT title AS link_title FROM {node} WHERE nid = %d", $book['nid'])));
|
||||
|
||||
// Items with depth > MENU_MAX_DEPTH cannot be saved.
|
||||
if (menu_link_save($book)) {
|
||||
db_query("INSERT INTO {book} (mlid, nid, bid) VALUES (%d, %d, %d)", $book['mlid'], $book['nid'], $book['bid']);
|
||||
}
|
||||
else {
|
||||
// The depth was greater then MENU_MAX_DEPTH, so attach it to the
|
||||
// closest valid parent.
|
||||
$book['plid'] = db_result(db_query("SELECT plid FROM {menu_links} WHERE mlid = %d", $book['plid']));
|
||||
if (menu_link_save($book)) {
|
||||
db_query("INSERT INTO {book} (mlid, nid, bid) VALUES (%d, %d, %d)", $book['mlid'], $book['nid'], $book['bid']);
|
||||
}
|
||||
}
|
||||
$update_count--;
|
||||
}
|
||||
$ret['#finished'] = FALSE;
|
||||
}
|
||||
|
||||
if (empty($_SESSION['book_update_6000'])) {
|
||||
$ret['#finished'] = TRUE;
|
||||
$ret[] = array('success' => TRUE, 'query' => 'Relocated existing book pages.');
|
||||
$ret[] = update_sql("DROP TABLE {book_temp}");
|
||||
unset($_SESSION['book_update_6000']);
|
||||
unset($_SESSION['book_update_6000_orphans']);
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of hook_schema().
|
||||
*/
|
||||
function book_schema() {
|
||||
$schema['book'] = array(
|
||||
'description' => 'Stores book outline information. Uniquely connects each node in the outline to a link in {menu_links}',
|
||||
'fields' => array(
|
||||
'mlid' => array(
|
||||
'type' => 'int',
|
||||
'unsigned' => TRUE,
|
||||
'not null' => TRUE,
|
||||
'default' => 0,
|
||||
'description' => "The book page's {menu_links}.mlid.",
|
||||
),
|
||||
'nid' => array(
|
||||
'type' => 'int',
|
||||
'unsigned' => TRUE,
|
||||
'not null' => TRUE,
|
||||
'default' => 0,
|
||||
'description' => "The book page's {node}.nid.",
|
||||
),
|
||||
'bid' => array(
|
||||
'type' => 'int',
|
||||
'unsigned' => TRUE,
|
||||
'not null' => TRUE,
|
||||
'default' => 0,
|
||||
'description' => "The book ID is the {book}.nid of the top-level page.",
|
||||
),
|
||||
),
|
||||
'primary key' => array('mlid'),
|
||||
'unique keys' => array(
|
||||
'nid' => array('nid'),
|
||||
),
|
||||
'indexes' => array(
|
||||
'bid' => array('bid'),
|
||||
),
|
||||
);
|
||||
|
||||
return $schema;
|
||||
}
|
||||
|
||||
|
1095
modules/book/book.module
Normal file
1095
modules/book/book.module
Normal file
File diff suppressed because it is too large
Load diff
266
modules/book/book.pages.inc
Normal file
266
modules/book/book.pages.inc
Normal file
|
@ -0,0 +1,266 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* User page callbacks for the book module.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Menu callback; prints a listing of all books.
|
||||
*/
|
||||
function book_render() {
|
||||
$book_list = array();
|
||||
foreach (book_get_books() as $book) {
|
||||
$book_list[] = l($book['title'], $book['href'], $book['options']);
|
||||
}
|
||||
|
||||
return theme('item_list', $book_list);
|
||||
}
|
||||
|
||||
/**
|
||||
* Menu callback; Generates various representation of a book page and its children.
|
||||
*
|
||||
* The function delegates the generation of output to helper functions.
|
||||
* The function name is derived by prepending 'book_export_' to the
|
||||
* given output type. So, e.g., a type of 'html' results in a call to
|
||||
* the function book_export_html().
|
||||
*
|
||||
* @param $type
|
||||
* A string encoding the type of output requested. The following
|
||||
* types are currently supported in book module:
|
||||
*
|
||||
* - html: HTML (printer friendly output)
|
||||
*
|
||||
* Other types may be supported in contributed modules.
|
||||
* @param $nid
|
||||
* An integer representing the node id (nid) of the node to export
|
||||
* @return
|
||||
* A string representing the node and its children in the book hierarchy
|
||||
* in a format determined by the $type parameter.
|
||||
*/
|
||||
function book_export($type, $nid) {
|
||||
// Check that the node exists and that the current user has access to it.
|
||||
$node = node_load($nid);
|
||||
if (!$node) {
|
||||
return MENU_NOT_FOUND;
|
||||
}
|
||||
if (!node_access('view', $node)) {
|
||||
return MENU_ACCESS_DENIED;
|
||||
}
|
||||
|
||||
$type = drupal_strtolower($type);
|
||||
|
||||
$export_function = 'book_export_'. $type;
|
||||
|
||||
if (function_exists($export_function)) {
|
||||
print call_user_func($export_function, $nid);
|
||||
}
|
||||
else {
|
||||
drupal_set_message(t('Unknown export format.'));
|
||||
drupal_not_found();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This function is called by book_export() to generate HTML for export.
|
||||
*
|
||||
* The given node is /embedded to its absolute depth in a top level
|
||||
* section/. For example, a child node with depth 2 in the hierarchy
|
||||
* is contained in (otherwise empty) <div> elements
|
||||
* corresponding to depth 0 and depth 1. This is intended to support
|
||||
* WYSIWYG output - e.g., level 3 sections always look like level 3
|
||||
* sections, no matter their depth relative to the node selected to be
|
||||
* exported as printer-friendly HTML.
|
||||
*
|
||||
* @param $nid
|
||||
* An integer representing the node id (nid) of the node to export.
|
||||
* @return
|
||||
* A string containing HTML representing the node and its children in
|
||||
* the book hierarchy.
|
||||
*/
|
||||
function book_export_html($nid) {
|
||||
if (user_access('access printer-friendly version')) {
|
||||
$export_data = array();
|
||||
$node = node_load($nid);
|
||||
if (isset($node->book)) {
|
||||
$tree = book_menu_subtree_data($node->book);
|
||||
$contents = book_export_traverse($tree, 'book_node_export');
|
||||
return theme('book_export_html', $node->title, $contents, $node->book['depth']);
|
||||
}
|
||||
else {
|
||||
drupal_not_found();
|
||||
}
|
||||
}
|
||||
else {
|
||||
drupal_access_denied();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Menu callback; show the outline form for a single node.
|
||||
*/
|
||||
function book_outline($node) {
|
||||
drupal_set_title(check_plain($node->title));
|
||||
return drupal_get_form('book_outline_form', $node);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the form to handle all book outline operations via the outline tab.
|
||||
*
|
||||
* @see book_outline_form_submit()
|
||||
* @see book_remove_button_submit()
|
||||
*
|
||||
* @ingroup forms
|
||||
*/
|
||||
function book_outline_form(&$form_state, $node) {
|
||||
|
||||
if (!isset($node->book)) {
|
||||
// The node is not part of any book yet - set default options.
|
||||
$node->book = _book_link_defaults($node->nid);
|
||||
}
|
||||
else {
|
||||
$node->book['original_bid'] = $node->book['bid'];
|
||||
}
|
||||
// Find the depth limit for the parent select.
|
||||
if (!isset($node->book['parent_depth_limit'])) {
|
||||
$node->book['parent_depth_limit'] = _book_parent_depth_limit($node->book);
|
||||
}
|
||||
$form['#node'] = $node;
|
||||
$form['#id'] = 'book-outline';
|
||||
_book_add_form_elements($form, $node);
|
||||
|
||||
$form['book']['#collapsible'] = FALSE;
|
||||
|
||||
$form['update'] = array(
|
||||
'#type' => 'submit',
|
||||
'#value' => $node->book['original_bid'] ? t('Update book outline') : t('Add to book outline'),
|
||||
'#weight' => 15,
|
||||
);
|
||||
|
||||
$form['remove'] = array(
|
||||
'#type' => 'submit',
|
||||
'#value' => t('Remove from book outline'),
|
||||
'#access' => $node->nid != $node->book['bid'] && $node->book['bid'],
|
||||
'#weight' => 20,
|
||||
'#submit' => array('book_remove_button_submit'),
|
||||
);
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* Button submit function to redirect to removal confirm form.
|
||||
*
|
||||
* @see book_outline_form()
|
||||
*/
|
||||
function book_remove_button_submit($form, &$form_state) {
|
||||
$form_state['redirect'] = 'node/'. $form['#node']->nid .'/outline/remove';
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles book outline form submissions from the outline tab.
|
||||
*
|
||||
* @see book_outline_form()
|
||||
*/
|
||||
function book_outline_form_submit($form, &$form_state) {
|
||||
$node = $form['#node'];
|
||||
$form_state['redirect'] = "node/". $node->nid;
|
||||
$book_link = $form_state['values']['book'];
|
||||
if (!$book_link['bid']) {
|
||||
drupal_set_message(t('No changes were made'));
|
||||
return;
|
||||
}
|
||||
|
||||
$book_link['menu_name'] = book_menu_name($book_link['bid']);
|
||||
$node->book = $book_link;
|
||||
if (_book_update_outline($node)) {
|
||||
if ($node->book['parent_mismatch']) {
|
||||
// This will usually only happen when JS is disabled.
|
||||
drupal_set_message(t('The post has been added to the selected book. You may now position it relative to other pages.'));
|
||||
$form_state['redirect'] = "node/". $node->nid ."/outline";
|
||||
}
|
||||
else {
|
||||
drupal_set_message(t('The book outline has been updated.'));
|
||||
}
|
||||
}
|
||||
else {
|
||||
drupal_set_message(t('There was an error adding the post to the book.'), 'error');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Menu callback; builds a form to confirm removal of a node from the book.
|
||||
*
|
||||
* @see book_remove_form_submit()
|
||||
*
|
||||
* @ingroup forms
|
||||
*/
|
||||
function book_remove_form(&$form_state, $node) {
|
||||
$form['#node'] = $node;
|
||||
$title = array('%title' => $node->title);
|
||||
|
||||
if ($node->book['has_children']) {
|
||||
$description = t('%title has associated child pages, which will be relocated automatically to maintain their connection to the book. To recreate the hierarchy (as it was before removing this page), %title may be added again using the Outline tab, and each of its former child pages will need to be relocated manually.', $title);
|
||||
}
|
||||
else {
|
||||
$description = t('%title may be added to hierarchy again using the Outline tab.', $title);
|
||||
}
|
||||
|
||||
return confirm_form($form, t('Are you sure you want to remove %title from the book hierarchy?', $title), 'node/'. $node->nid, $description, t('Remove'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Confirm form submit function to remove a node from the book.
|
||||
*
|
||||
* @see book_remove_form()
|
||||
*/
|
||||
function book_remove_form_submit($form, &$form_state) {
|
||||
$node = $form['#node'];
|
||||
if ($node->nid != $node->book['bid']) {
|
||||
// Only allowed when this is not a book (top-level page).
|
||||
menu_link_delete($node->book['mlid']);
|
||||
db_query('DELETE FROM {book} WHERE nid = %d', $node->nid);
|
||||
drupal_set_message(t('The post has been removed from the book.'));
|
||||
}
|
||||
$form_state['redirect'] = 'node/'. $node->nid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders a new parent page select element when the book selection changes.
|
||||
*
|
||||
* This function is called via AJAX when the selected book is changed on a node
|
||||
* or book outline form. It creates a new parent page select element, adds it
|
||||
* to the cached form, and then returns the rendered element so it can be
|
||||
* displayed on the form.
|
||||
*
|
||||
* @return
|
||||
* The rendered parent page select element.
|
||||
*/
|
||||
function book_form_update() {
|
||||
$bid = $_POST['book']['bid'];
|
||||
if ($form = form_get_cache($_POST['form_build_id'], $form_state)) {
|
||||
|
||||
// Validate the bid.
|
||||
if (isset($form['book']['bid']['#options'][$bid])) {
|
||||
$book_link = $form['#node']->book;
|
||||
$book_link['bid'] = $bid;
|
||||
// Get the new options and update the cache.
|
||||
$form['book']['plid'] = _book_parent_select($book_link);
|
||||
form_set_cache($_POST['form_build_id'], $form, $form_state);
|
||||
|
||||
// Build and render the new select element, then return it in JSON format.
|
||||
$form_state = array();
|
||||
$form['#post'] = array();
|
||||
$form = form_builder($form['form_id']['#value'] , $form, $form_state);
|
||||
$output = drupal_render($form['book']['plid']);
|
||||
drupal_json(array('status' => TRUE, 'data' => $output));
|
||||
}
|
||||
else {
|
||||
drupal_json(array('status' => FALSE, 'data' => ''));
|
||||
}
|
||||
}
|
||||
else {
|
||||
drupal_json(array('status' => FALSE, 'data' => ''));
|
||||
}
|
||||
exit();
|
||||
}
|
Reference in a new issue