Index: install.php
===================================================================
RCS file: /cvs/drupal/drupal/install.php,v
retrieving revision 1.6
diff -u -p -r1.6 install.php
--- install.php 8 Aug 2006 21:18:02 -0000 1.6
+++ install.php 15 Aug 2006 06:12:20 -0000
@@ -114,6 +114,9 @@ function install_verify_settings() {
*/
function install_change_settings() {
global $profile, $db_url, $db_type, $db_prefix;
+ // see http://drupal.org/node/74992
+ // temporary fix.
+ $profile = 'default';
$url = parse_url($db_url);
$db_user = urldecode($url['user']);
Index: modules/book/book.install
===================================================================
RCS file: /cvs/drupal/drupal/modules/book/book.install,v
retrieving revision 1.4
diff -u -p -r1.4 book.install
--- modules/book/book.install 15 Aug 2006 05:25:19 -0000 1.4
+++ modules/book/book.install 15 Aug 2006 06:12:20 -0000
@@ -5,26 +5,85 @@ function book_install() {
switch ($GLOBALS['db_type']) {
case 'mysql':
case 'mysqli':
- db_query("CREATE TABLE {book} (
+ db_query("CREATE TABLE {book_pages} (
vid int(10) unsigned NOT NULL default '0',
nid int(10) unsigned NOT NULL default '0',
+ bid int(10) unsigned NOT NULL default '0',
parent int(10) NOT NULL default '0',
weight tinyint(3) NOT NULL default '0',
PRIMARY KEY (vid),
KEY nid (nid),
+ KEY bid (bid),
KEY parent (parent)
) /*!40100 DEFAULT CHARACTER SET UTF8 */ ");
+ db_query("CREATE TABLE {book} (
+ bid INT( 10 ) UNSIGNED NOT NULL default '0' PRIMARY KEY ,
+ nid INT( 10 ) UNSIGNED NOT NULL default '0' ,
+ book_author VARCHAR(255) NOT NULL default '' ,
+ book_license LONGTEXT NOT NULL default '' ,
+ weight TINYINT( 3 ) NOT NULL default '0',
+ KEY nid (nid)
+ ) /*!40100 DEFAULT CHARACTER SET UTF8 */ ");
break;
case 'pgsql':
- db_query("CREATE TABLE {book} (
+ db_query("CREATE TABLE {book_pages} (
vid int_unsigned NOT NULL default '0',
nid int_unsigned NOT NULL default '0',
- parent int NOT NULL default '0',
+ bid int_unsigned NOT NULL default '0',
+ parent int_unsigned NOT NULL default '0',
weight smallint NOT NULL default '0',
PRIMARY KEY (vid)
+ ");
+ db_query("CREATE TABLE {book} (
+ bid int_unsigned NOT NULL default '0',
+ nid int_unsigned NOT NULL default '0',
+ book_author varchar(255) NOT NULL default '',
+ book_license text NOT NULL default '',
+ weight smallint NOT NULL default '',
)");
+ db_query("CREATE INDEX {book_pages}_nid_idx ON {book_pages} (nid)");
+ db_query("CREATE INDEX {book_pages}_xid_idx ON {book_pages} (bid)");
+ db_query("CREATE INDEX {book_pages}_parent_idx ON {book_pages} (parent)");
db_query("CREATE INDEX {book}_nid_idx ON {book} (nid)");
- db_query("CREATE INDEX {book}_parent_idx ON {book} (parent)");
+ db_query("CREATE INDEX {book}_bid_idx ON {book} (bid)");
+ break;
+ }
+}
+
+/**
+ * Update book table definitions.
+ */
+function book_update_1000() {
+ $ret = array();
+ switch ($GLOBALS['db_type']) {
+ case 'mysql':
+ case 'mysqli':
+ $ret[] = update_sql("ALTER TABLE `{book}` RENAME `{book_pages}`;");
+ $ret[] = update_sql("CREATE TABLE `{book}` (
+ `bid` INT( 10 ) UNSIGNED NOT NULL default '0' PRIMARY KEY ,
+ `nid` INT( 10 ) UNSIGNED NOT NULL default '0' ,
+ `book_author` VARCHAR(255) NOT NULL default '' ,
+ `book_license` LONGTEXT NOT NULL default '' ,
+ `weight` TINYINT( 3 ) NOT NULL default '0',
+ KEY nid (nid)
+ ) TYPE = MYISAM");
+ $ret[] = update_sql("ALTER TABLE `{book_pages}` ADD `bid` INT( 10 ) UNSIGNED NOT NULL AFTER `nid` ;");
+ $ret[] = update_sql("ALTER TABLE `{book_pages}` ADD INDEX ( `bid` );");
+ break;
+ case 'pgsql':
+ $ret[] = update_sql("ALTER TABLE {book} RENAME {book_pages};");
+ $ret[] = update_sql("CREATE TABLE {book} (
+ bid int_unsigned NOT NULL default '0' ,
+ nid int_unsigned NOT NULL default '0' ,
+ book_author varchar(255) NOT NULL default '' ,
+ book_license text NOT NULL default '' ,
+ weight smallint NOT NULL default '0'
+ ");
+ $ret[] = update_sql("CREATE INDEX {book}_bid_idx ON {book}(bid);");
+ $ret[] = update_sql("CREATE INDEX {book}_uid_idx ON {book}(uid);");
+ db_add_column($ret, 'book_pages', 'bid', 'int', array('not null' => TRUE, 'default' => 0));
+ $ret[] = update_sql("CREATE INDEX {book_pages}_bid_idx ON {book_pages}(bid);");
break;
}
+ return $ret;
}
Index: modules/book/book.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/book/book.module,v
retrieving revision 1.382
diff -u -p -r1.382 book.module
--- modules/book/book.module 14 Aug 2006 07:14:49 -0000 1.382
+++ modules/book/book.module 15 Aug 2006 06:12:22 -0000
@@ -14,8 +14,14 @@ function book_node_info() {
'book' => array(
'name' => t('book page'),
'module' => 'book',
- 'description' => t("A book is a collaborative writing effort: users can collaborate writing the pages of the book, positioning the pages in the right order, and reviewing or modifying pages previously written. So when you have some information to share or when you read a page of the book and you didn't like it, or if you think a certain page could have been written better, you can do something about it."),
- )
+ 'description' => t("A book is a collaborative writing effort: users can collaborate writing the pages of the book, positioning the pages in the right order, and reviewing or modifying pages previously written. So when you have some information to share or when you read a page of the book and you didn't like it, or if you think a certain page could have been written better, you can do something about it.
+ Use this link to select a book to add a page to, otherwise your book page will be created independently of any existing book.", array('%url' => url('node/add/book/select_book'))),
+ ),
+ 'book_cover' => array(
+ 'name' => t('book cover'),
+ 'module' => 'book_cover',
+ 'description' => t('Add a new book.'),
+ ),
);
}
@@ -26,8 +32,38 @@ function book_perm() {
return array('outline posts in books', 'create book pages', 'create new books', 'edit book pages', 'edit own book pages', 'see printer-friendly version');
}
+
+/**
+ * Implementation of hook_access() for a book cover.
+ */
+function book_cover_access($op, $node) {
+ global $user;
+
+ if ($op == 'create') {
+ // Only registered users can create books. Given the nature
+ // of the book module this is considered to be a good/safe idea.
+ return user_access('create new books');
+ }
+
+ if ($op == 'update') {
+ // Only registered users can update book pages. Given the nature
+ // of the book module this is considered to be a good/safe idea.
+ // One can only update a book page if there are no suggested updates
+ // of that page waiting for approval. That is, only updates that
+ // don't overwrite the current or pending information are allowed.
+
+ if ($node->uid == $user->uid && user_access('edit own book pages')) {
+ return TRUE;
+ }
+ else {
+ // do nothing. node-access() will determine further access
+ }
+ }
+}
+
+
/**
- * Implementation of hook_access().
+ * Implementation of hook_access() for a book page.
*/
function book_access($op, $node) {
global $user;
@@ -61,6 +97,16 @@ function book_link($type, $node = NULL,
$links = array();
+ if ($type == 'node' && $node->type == 'book_cover') {
+ if (user_access('create new books', $node)) {
+ $links['book_add_child'] = array(
+ 'title' => t('add child page'),
+ 'href' => "node/add/book/bid/$node->bid"
+ );
+ }
+ return $links;
+ }
+
if ($type == 'node' && isset($node->parent)) {
if (!$teaser) {
if (book_access('create', $node)) {
@@ -107,10 +153,10 @@ function book_menu($may_cache) {
'weight' => 8);
$items[] = array(
'path' => 'book',
- 'title' => t('books'),
- 'callback' => 'book_render',
- 'access' => user_access('access content'),
- 'type' => MENU_SUGGESTED_ITEM);
+ 'title' => t('book shelf'),
+ 'callback' => 'book_shelf',
+ 'type' => MENU_NORMAL_ITEM,
+ 'access' => user_access('access content'));
$items[] = array(
'path' => 'book/export',
'callback' => 'book_export',
@@ -122,12 +168,30 @@ function book_menu($may_cache) {
// We put this in !$may_cache so it's only added once per request
drupal_add_css(drupal_get_path('module', 'book') .'/book.css');
+ $items[] = array(
+ 'path' => 'node/add/book/select_book',
+ 'title' => t('New page'),
+ 'callback' => '_add_page_select_book',
+ 'access' => user_access('create book pages'),
+ 'type' => MENU_LOCAL_TASK,
+ 'weight' => 2);
// To avoid SQL overhead, check whether we are on a node page and whether the
// user is allowed to outline posts in books.
if (arg(0) == 'node' && is_numeric(arg(1)) && user_access('outline posts in books')) {
// Only add the outline-tab for non-book pages:
- $result = db_query(db_rewrite_sql("SELECT n.nid FROM {node} n WHERE n.nid = %d AND n.type != 'book'"), arg(1));
- if (db_num_rows($result) > 0) {
+ $result = db_fetch_object(db_query(db_rewrite_sql('SELECT n.nid, n.type FROM {node} n WHERE n.nid = %d'), arg(1)));
+ if ($result->type == 'book') {
+ // If it's a book page, add the 'book' tab.
+ $items[] = array(
+ 'path' => 'node/'.arg(1).'/move_to_book',
+ 'title' => t('book'),
+ 'callback' => 'move_page_to_book',
+ 'access' => user_access('outline posts in books'),
+ 'type' => MENU_LOCAL_TASK,
+ 'weight' => 8);
+ }
+ elseif ($result->type != 'book_cover') {
+ // add outline tab
$items[] = array(
'path' => 'node/'. arg(1) .'/outline',
'title' => t('outline'),
@@ -144,6 +208,90 @@ function book_menu($may_cache) {
}
/**
+ * Menu call back: Select a book to move a page to.
+ * @param:
+ * outline: TRUE if it is a non-book page.
+ */
+function move_page_to_book($outline = FALSE) {
+ $result = db_query('SELECT b.bid, n.title FROM {book} b JOIN {node} n ON n.nid = b.nid ORDER BY b.weight, n.title');
+ $books = array();
+ $books[0] = t('Independent, top-level book page');
+ while ($book = db_fetch_object($result)) {
+ $books[$book->bid] = $book->title;
+ }
+ $nid = arg(1);
+ $bid = db_result(db_query('SELECT bid FROM {book_pages} WHERE nid = %d', $nid));
+ $form = array();
+ $form['bid'] = array(
+ '#type' => 'select',
+ '#title' => t('Select a book'),
+ '#default_value' => $bid,
+ '#options' => $books,
+ '#description' => t('Select the book you wish to move your page to.'),
+ );
+
+ $form['outline'] = array(
+ '#type' => 'value',
+ '#value' => FALSE,
+ );
+ $form['nid'] = array(
+ '#type' => 'value',
+ '#value' => $nid,
+ );
+ $form['children_note'] = array(
+ '#value' => t('
Note: All of this pages\'s children will be moved together to the new book. If you do not wish that, please update the outline of the children pages first.
'), + ); + $form['submit'] = array( + '#type' => 'submit', + '#value' => t('Submit'), + ); + + //override some of the above defaults if it is not a book_page node + if ($outline) { + $form['outline']['#value'] = TRUE; + $form['children_note'] = NULL; + } + + $output = drupal_get_form('move_page_to_book', $form); + return $output; +} + +/** + * Menu call back: Select a book to move a page to. + */ +function move_page_to_book_submit($form_id, $form) { + + if($form['outline']) { + $node = node_load($form['nid']); + db_query('INSERT INTO {book_pages} (nid, vid, bid, parent, weight) VALUES (%d, %d, %d, %d, %d)', $node->nid, $node->vid, $form['bid'], $form['parent'], $form['weight']); + db_query("UPDATE {node_revisions} SET log = '%s' WHERE vid = %d", $form['log'], $node->vid); + drupal_set_message(t('The post has been added to the book. Now update where in the book you want to add the post.')); + drupal_goto('node/'. $form['nid'].'/outline'); + } + + $result = db_query('UPDATE {book_pages} SET bid = %d, parent = 0 WHERE nid = %d', $form['bid'], $form['nid']); + book_update_children_bid($form['nid'], $form['bid']); + drupal_set_message(t('The page and its children have been relocated.If you wish to move this node to another book, you must first remove the node from the book outline, then add it back to the book you wish.
')); $form['update'] = array('#type' => 'submit', '#value' => t('Update book outline'), ); @@ -336,17 +621,17 @@ function book_outline_submit($form_id, $ switch ($op) { case t('Add to book outline'): - db_query('INSERT INTO {book} (nid, vid, parent, weight) VALUES (%d, %d, %d, %d)', $node->nid, $node->vid, $form_values['parent'], $form_values['weight']); + db_query('INSERT INTO {book_pages} (nid, vid, parent, weight) VALUES (%d, %d, %d, %d)', $node->nid, $node->vid, $form_values['parent'], $form_values['weight']); db_query("UPDATE {node_revisions} SET log = '%s' WHERE vid = %d", $form_values['log'], $node->vid); drupal_set_message(t('The post has been added to the book.')); break; case t('Update book outline'): - db_query('UPDATE {book} SET parent = %d, weight = %d WHERE vid = %d', $form_values['parent'], $form_values['weight'], $node->vid); + db_query('UPDATE {book_pages} SET parent = %d, weight = %d WHERE vid = %d', $form_values['parent'], $form_values['weight'], $node->vid); db_query("UPDATE {node_revisions} SET log = '%s' WHERE vid = %d", $form_values['log'], $node->vid); drupal_set_message(t('The book outline has been updated.')); break; case t('Remove from book outline'): - db_query('DELETE FROM {book} WHERE nid = %d', $node->nid); + db_query('DELETE FROM {book_pages} WHERE nid = %d', $node->nid); drupal_set_message(t('The post has been removed from the book.')); break; } @@ -366,7 +651,7 @@ function book_outline_submit($form_id, $ * */ function book_location($node, $nodes = array()) { - $parent = db_fetch_object(db_query(db_rewrite_sql('SELECT n.nid, n.title, b.parent, b.weight FROM {node} n INNER JOIN {book} b ON n.vid = b.vid WHERE n.nid = %d'), $node->parent)); + $parent = db_fetch_object(db_query(db_rewrite_sql('SELECT n.nid, n.title, b.parent, b.weight FROM {node} n INNER JOIN {book_pages} b ON n.vid = b.vid WHERE n.nid = %d'), $node->parent)); if (isset($parent->title)) { $nodes = book_location($parent, $nodes); $nodes[] = $parent; @@ -378,7 +663,7 @@ function book_location($node, $nodes = a * Accumulates the nodes up to the root of the book from the given node in the $nodes array. */ function book_location_down($node, $nodes = array()) { - $last_direct_child = db_fetch_object(db_query(db_rewrite_sql('SELECT n.nid, n.title, b.parent, b.weight FROM {node} n INNER JOIN {book} b ON n.vid = b.vid WHERE n.status = 1 AND b.parent = %d ORDER BY b.weight DESC, n.title DESC'), $node->nid)); + $last_direct_child = db_fetch_object(db_query(db_rewrite_sql('SELECT n.nid, n.title, b.parent, b.weight FROM {node} n INNER JOIN {book_pages} b ON n.vid = b.vid WHERE n.status = 1 AND b.parent = %d ORDER BY b.weight DESC, n.title DESC'), $node->nid)); if ($last_direct_child) { $nodes[] = $last_direct_child; $nodes = book_location_down($last_direct_child, $nodes); @@ -396,7 +681,7 @@ function book_prev($node) { } // Previous on the same level: - $direct_above = db_fetch_object(db_query(db_rewrite_sql("SELECT n.nid, n.title, b.weight FROM {node} n INNER JOIN {book} b ON n.vid = b.vid WHERE b.parent = %d AND n.status = 1 AND (b.weight < %d OR (b.weight = %d AND n.title < '%s')) ORDER BY b.weight DESC, n.title DESC"), $node->parent, $node->weight, $node->weight, $node->title)); + $direct_above = db_fetch_object(db_query(db_rewrite_sql("SELECT n.nid, n.title, b.weight FROM {node} n INNER JOIN {book_pages} b ON n.vid = b.vid WHERE b.parent = %d AND n.status = 1 AND n.moderate = 0 AND (b.weight < %d OR (b.weight = %d AND n.title < '%s')) ORDER BY b.weight DESC, n.title DESC"), $node->parent, $node->weight, $node->weight, $node->title)); if ($direct_above) { // Get last leaf of $above. $path = book_location_down($direct_above); @@ -405,7 +690,7 @@ function book_prev($node) { } else { // Direct parent: - $prev = db_fetch_object(db_query(db_rewrite_sql('SELECT n.nid, n.title FROM {node} n INNER JOIN {book} b ON n.vid = b.vid WHERE n.nid = %d AND n.status = 1'), $node->parent)); + $prev = db_fetch_object(db_query(db_rewrite_sql('SELECT n.nid, n.title FROM {node} n INNER JOIN {book_pages} b ON n.vid = b.vid WHERE n.nid = %d AND n.status = 1 AND n.moderate = 0'), $node->parent)); return $prev; } } @@ -415,7 +700,7 @@ function book_prev($node) { */ function book_next($node) { // get first direct child - $child = db_fetch_object(db_query(db_rewrite_sql('SELECT n.nid, n.title, b.weight FROM {node} n INNER JOIN {book} b ON n.vid = b.vid WHERE b.parent = %d AND n.status = 1 ORDER BY b.weight ASC, n.title ASC'), $node->nid)); + $child = db_fetch_object(db_query(db_rewrite_sql('SELECT n.nid, n.title, b.weight FROM {node} n INNER JOIN {book_pages} b ON n.vid = b.vid WHERE b.parent = %d AND n.status = 1 AND n.moderate = 0 ORDER BY b.weight ASC, n.title ASC'), $node->nid)); if ($child) { return $child; } @@ -425,7 +710,7 @@ function book_next($node) { $path[] = $node; while (($leaf = array_pop($path)) && count($path)) { - $next = db_fetch_object(db_query(db_rewrite_sql("SELECT n.nid, n.title, b.weight FROM {node} n INNER JOIN {book} b ON n.vid = b.vid WHERE b.parent = %d AND n.status = 1 AND (b.weight > %d OR (b.weight = %d AND n.title > '%s')) ORDER BY b.weight ASC, n.title ASC"), $leaf->parent, $leaf->weight, $leaf->weight, $leaf->title)); + $next = db_fetch_object(db_query(db_rewrite_sql("SELECT n.nid, n.title, b.weight FROM {node} n INNER JOIN {book_pages} b ON n.vid = b.vid WHERE b.parent = %d AND n.status = 1 AND n.moderate = 0 AND (b.weight > %d OR (b.weight = %d AND n.title > '%s')) ORDER BY b.weight ASC, n.title ASC"), $leaf->parent, $leaf->weight, $leaf->weight, $leaf->title)); if ($next) { return $next; } @@ -444,6 +729,90 @@ function book_content($node, $teaser = F } /** +* Theme the name of the Author(s) on the book cover +*/ +function theme_book_author($author) { + return ''. $license .'
'; + return $output; +} + +/** +* Implementation of hook_view() for a book cover. +*/ +function book_cover_view(&$node, $teaser = FALSE, $page = FALSE) { + $node = node_prepare($node, $teaser); + if (!empty($node->book_author)) { + $node->content['book_author'] = array( + '#value' => theme('book_author', $node->book_author), + '#weight' => -1, + ); + $node->teaser = ''. $node->teaser; + } + if (!empty($node->book_license)) { + $node->book_license = check_markup($node->book_license, $node->format, FALSE); + $node->content['book_license'] = array( + '#value' => theme('book_license', $node->book_license) , + '#weight' => 100, + ); + } + $node->content['book_toc'] = array( + '#value' => _book_cover_toc($node->bid), + '#weight' => 200, + ); + return $node; +} + +/** + * Creates the Table of contents printed on book cover $bid. + * Returns formatted html. + */ +function _book_cover_toc($bid) { + $result = db_query('SELECT n.nid, n.title, bp.parent, bp.weight FROM {node} n INNER JOIN {book_pages} bp ON n.vid = bp.vid WHERE n.status = 1 AND bp.bid = %d ORDER BY bp.weight, n.title', $bid); + + while ($node = db_fetch_object($result)) { + if (!$children[$node->parent]) { + $children[$node->parent] = array(); + } + $children[$node->parent][] = $node; + } + + return theme('book_toc', $children); +} + +/** + * Theme function returning nested list items. + */ +function theme_book_toc ($children) { + $toc = '' . t('Either click here to create a book page that does not belong to any particular book or select below the book you wish to add the page to.', array('%url' => url('node/add/book/bid/0'))) .'
'; + $output .= theme('item_list', $books); + } + else { + drupal_goto('node/add/book/bid/0'); + } + return $output; +} + +/** + * Implementation of hook_form_alter() + */ +function book_form_alter($form_id, &$form) { + switch($form_id) { + case 'node_delete_confirm': + $node_type = db_result(db_query('SELECT type FROM {node} WHERE nid = %d ', $form['nid']['#value'])); + if ($node_type == 'book_cover') { + $form['book_cover'] = array( + '#value' => t('Note that all book pages belonging to this book (if any) will no longer be associated to any book. You may want to move remaining book pages within this book to another book, first. '), + ); + } + } +}