diff modules/book/book.install @ 1:c1f4ac30525a 6.0

Drupal 6.0
author Franck Deroche <webmaster@defr.org>
date Tue, 23 Dec 2008 14:28:28 +0100
parents
children 3edae6ecd6c6
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/modules/book/book.install	Tue Dec 23 14:28:28 2008 +0100
@@ -0,0 +1,290 @@
+<?php
+// $Id: book.install,v 1.20 2008/01/10 18:13:42 goba Exp $
+
+/**
+ * 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' => t('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' => t("The book page's {menu_links}.mlid."),
+      ),
+      'nid' => array(
+        'type' => 'int',
+        'unsigned' => TRUE,
+        'not null' => TRUE,
+        'default' => 0,
+        'description' => t("The book page's {node}.nid."),
+      ),
+      'bid' => array(
+        'type' => 'int',
+        'unsigned' => TRUE,
+        'not null' => TRUE,
+        'default' => 0,
+        'description' => t("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;
+}
+
+