book.install

  1. 7.x drupal-7.x/modules/book/book.install
  2. 6.x drupal-6.x/modules/book/book.install

File

drupal-6.x/modules/book/book.install
View source
  1. <?php
  2. /**
  3. * Implementation of hook_install().
  4. */
  5. function book_install() {
  6. // Create tables.
  7. drupal_install_schema('book');
  8. // Add the node type.
  9. _book_install_type_create();
  10. }
  11. /**
  12. * Implementation of hook_uninstall().
  13. */
  14. function book_uninstall() {
  15. // Delete menu links.
  16. db_query("DELETE FROM {menu_links} WHERE module = 'book'");
  17. menu_cache_clear_all();
  18. // Remove tables.
  19. drupal_uninstall_schema('book');
  20. }
  21. function _book_install_type_create() {
  22. // Create an additional node type
  23. $book_node_type = array(
  24. 'type' => 'book',
  25. 'name' => t('Book page'),
  26. 'module' => 'node',
  27. '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.'),
  28. 'custom' => TRUE,
  29. 'modified' => TRUE,
  30. 'locked' => FALSE,
  31. );
  32. $book_node_type = (object)_node_type_set_defaults($book_node_type);
  33. node_type_save($book_node_type);
  34. // Default to not promoted.
  35. variable_set('node_options_book', array('status'));
  36. // Use this default type for adding content to books.
  37. variable_set('book_allowed_types', array('book'));
  38. variable_set('book_child_type', 'book');
  39. }
  40. /**
  41. * Drupal 5.x to 6.x update.
  42. *
  43. * This function moves any existing book hierarchy into the new structure used
  44. * in the 6.x module. Rather than storing the hierarchy in the {book} table,
  45. * the menu API is used to store the hierarchy in the {menu_links} table and the
  46. * {book} table serves to uniquely connect a node to a menu link.
  47. *
  48. * In order to accomplish this, the current hierarchy is processed using a stack.
  49. * The stack insures that each parent is processed before any of its children
  50. * in the book hierarchy, and is compatible with batched update processing.
  51. *
  52. */
  53. function book_update_6000() {
  54. $ret = array();
  55. // Set up for a multi-part update.
  56. if (!isset($_SESSION['book_update_6000'])) {
  57. $schema['book'] = array(
  58. 'fields' => array(
  59. 'mlid' => array('type' => 'int', 'unsigned' => TRUE, 'not null' => TRUE, 'default' => 0),
  60. 'nid' => array('type' => 'int', 'unsigned' => TRUE, 'not null' => TRUE, 'default' => 0),
  61. 'bid' => array('type' => 'int', 'unsigned' => TRUE, 'not null' => TRUE, 'default' => 0),
  62. ),
  63. 'primary key' => array('mlid'),
  64. 'unique keys' => array(
  65. 'nid' => array('nid'),
  66. ),
  67. 'indexes' => array(
  68. 'bid' => array('bid'),
  69. ),
  70. );
  71. // Add the node type.
  72. _book_install_type_create();
  73. // Fix role permissions to account for the changed names
  74. // Setup the array holding strings to match and the corresponding
  75. // strings to replace them with.
  76. $replace = array(
  77. 'outline posts in books' => 'administer book outlines',
  78. 'create book pages' => 'create book content',
  79. 'edit book pages' => 'edit any book content',
  80. 'edit own book pages' => 'edit own book content',
  81. 'see printer-friendly version' => 'access printer-friendly version',
  82. );
  83. // Loop over all the roles, and do the necessary transformations.
  84. $query = db_query("SELECT rid, perm FROM {permission} ORDER BY rid");
  85. while ($role = db_fetch_object($query)) {
  86. // Replace all the old permissions with the corresponding new permissions.
  87. $fixed_perm = strtr($role->perm, $replace);
  88. // If the user could previously create book pages, they should get the new
  89. // 'add content to books' permission.
  90. if (strpos($role->perm, 'create book pages') !== FALSE) {
  91. $fixed_perm .= ', add content to books';
  92. }
  93. // Only save if the permissions have changed.
  94. if ($fixed_perm != $role->perm) {
  95. $ret[] = update_sql("UPDATE {permission} SET perm = '$fixed_perm' WHERE rid = $role->rid");
  96. }
  97. }
  98. // Determine whether there are any existing nodes in the book hierarchy.
  99. if (db_result(db_query("SELECT COUNT(*) FROM {book}"))) {
  100. // Temporary table for the old book hierarchy; we'll discard revision info.
  101. $schema['book_temp'] = array(
  102. 'fields' => array(
  103. 'nid' => array('type' => 'int', 'unsigned' => TRUE, 'not null' => TRUE, 'default' => 0),
  104. 'parent' => array('type' => 'int', 'not null' => TRUE, 'default' => 0),
  105. 'weight' => array('type' => 'int', 'not null' => TRUE, 'default' => 0, 'size' => 'tiny')
  106. ),
  107. 'indexes' => array(
  108. 'parent' => array('parent')
  109. ),
  110. 'primary key' => array('nid'),
  111. );
  112. db_create_table($ret, 'book_temp', $schema['book_temp']);
  113. // Insert each node in the old table into the temporary table.
  114. $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");
  115. $ret[] = update_sql("DROP TABLE {book}");
  116. db_create_table($ret, 'book', $schema['book']);
  117. $_SESSION['book_update_6000_orphans']['from'] = 0;
  118. $_SESSION['book_update_6000'] = array();
  119. $result = db_query("SELECT * from {book_temp} WHERE parent = 0");
  120. // Collect all books - top-level nodes.
  121. while ($a = db_fetch_array($result)) {
  122. $_SESSION['book_update_6000'][] = $a;
  123. }
  124. $ret['#finished'] = FALSE;
  125. return $ret;
  126. }
  127. else {
  128. // No exising nodes in the hierarchy, so drop the table and re-create it.
  129. $ret[] = update_sql("DROP TABLE {book}");
  130. db_create_table($ret, 'book', $schema['book']);
  131. return $ret;
  132. }
  133. }
  134. elseif ($_SESSION['book_update_6000_orphans']) {
  135. // Do the first batched part of the update - collect orphans.
  136. $update_count = 400; // Update this many at a time
  137. $result = db_query_range("SELECT * FROM {book_temp}", $_SESSION['book_update_6000_orphans']['from'], $update_count);
  138. $has_rows = FALSE;
  139. // Go through the next $update_count book pages and locate the orphans.
  140. while ($book = db_fetch_array($result)) {
  141. $has_rows = TRUE;
  142. // Orphans are defined as nodes whose parent does not exist in the table.
  143. if ($book['parent'] && !db_result(db_query("SELECT COUNT(*) FROM {book_temp} WHERE nid = %d", $book['parent']))) {
  144. if (empty($_SESSION['book_update_6000_orphans']['book'])) {
  145. // The first orphan becomes the parent for all other orphans.
  146. $book['parent'] = 0;
  147. $_SESSION['book_update_6000_orphans']['book'] = $book;
  148. $ret[] = array('success' => TRUE, 'query' => 'Relocated orphan book pages.');
  149. }
  150. else {
  151. // Re-assign the parent value of the book, and add it to the stack.
  152. $book['parent'] = $_SESSION['book_update_6000_orphans']['book']['nid'];
  153. $_SESSION['book_update_6000'][] = $book;
  154. }
  155. }
  156. }
  157. if ($has_rows) {
  158. $_SESSION['book_update_6000_orphans']['from'] += $update_count;
  159. }
  160. else {
  161. // Done with this part
  162. if (!empty($_SESSION['book_update_6000_orphans']['book'])) {
  163. // The orphans' parent is added last, so it will be processed first.
  164. $_SESSION['book_update_6000'][] = $_SESSION['book_update_6000_orphans']['book'];
  165. }
  166. $_SESSION['book_update_6000_orphans'] = FALSE;
  167. }
  168. $ret['#finished'] = FALSE;
  169. return $ret;
  170. }
  171. else {
  172. // Do the next batched part of the update
  173. $update_count = 100; // Update this many at a time
  174. while ($update_count && $_SESSION['book_update_6000']) {
  175. // Get the last node off the stack.
  176. $book = array_pop($_SESSION['book_update_6000']);
  177. // Add all of this node's children to the stack
  178. $result = db_query("SELECT * FROM {book_temp} WHERE parent = %d", $book['nid']);
  179. while ($a = db_fetch_array($result)) {
  180. $_SESSION['book_update_6000'][] = $a;
  181. }
  182. if ($book['parent']) {
  183. // If its not a top level page, get its parent's mlid.
  184. $parent = db_fetch_array(db_query("SELECT b.mlid AS plid, b.bid FROM {book} b WHERE b.nid = %d", $book['parent']));
  185. $book = array_merge($book, $parent);
  186. }
  187. else {
  188. // There is not a parent - this is a new book.
  189. $book['plid'] = 0;
  190. $book['bid'] = $book['nid'];
  191. }
  192. $book += array(
  193. 'module' => 'book',
  194. 'link_path' => 'node/'. $book['nid'],
  195. 'router_path' => 'node/%',
  196. 'menu_name' => 'book-toc-'. $book['bid'],
  197. );
  198. $book = array_merge($book, db_fetch_array(db_query("SELECT title AS link_title FROM {node} WHERE nid = %d", $book['nid'])));
  199. // Items with depth > MENU_MAX_DEPTH cannot be saved.
  200. if (menu_link_save($book)) {
  201. db_query("INSERT INTO {book} (mlid, nid, bid) VALUES (%d, %d, %d)", $book['mlid'], $book['nid'], $book['bid']);
  202. }
  203. else {
  204. // The depth was greater then MENU_MAX_DEPTH, so attach it to the
  205. // closest valid parent.
  206. $book['plid'] = db_result(db_query("SELECT plid FROM {menu_links} WHERE mlid = %d", $book['plid']));
  207. if (menu_link_save($book)) {
  208. db_query("INSERT INTO {book} (mlid, nid, bid) VALUES (%d, %d, %d)", $book['mlid'], $book['nid'], $book['bid']);
  209. }
  210. }
  211. $update_count--;
  212. }
  213. $ret['#finished'] = FALSE;
  214. }
  215. if (empty($_SESSION['book_update_6000'])) {
  216. $ret['#finished'] = TRUE;
  217. $ret[] = array('success' => TRUE, 'query' => 'Relocated existing book pages.');
  218. $ret[] = update_sql("DROP TABLE {book_temp}");
  219. unset($_SESSION['book_update_6000']);
  220. unset($_SESSION['book_update_6000_orphans']);
  221. }
  222. return $ret;
  223. }
  224. /**
  225. * Implementation of hook_schema().
  226. */
  227. function book_schema() {
  228. $schema['book'] = array(
  229. 'description' => 'Stores book outline information. Uniquely connects each node in the outline to a link in {menu_links}',
  230. 'fields' => array(
  231. 'mlid' => array(
  232. 'type' => 'int',
  233. 'unsigned' => TRUE,
  234. 'not null' => TRUE,
  235. 'default' => 0,
  236. 'description' => "The book page's {menu_links}.mlid.",
  237. ),
  238. 'nid' => array(
  239. 'type' => 'int',
  240. 'unsigned' => TRUE,
  241. 'not null' => TRUE,
  242. 'default' => 0,
  243. 'description' => "The book page's {node}.nid.",
  244. ),
  245. 'bid' => array(
  246. 'type' => 'int',
  247. 'unsigned' => TRUE,
  248. 'not null' => TRUE,
  249. 'default' => 0,
  250. 'description' => "The book ID is the {book}.nid of the top-level page.",
  251. ),
  252. ),
  253. 'primary key' => array('mlid'),
  254. 'unique keys' => array(
  255. 'nid' => array('nid'),
  256. ),
  257. 'indexes' => array(
  258. 'bid' => array('bid'),
  259. ),
  260. );
  261. return $schema;
  262. }