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