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