2001-11-15 22:53:06 +00:00
< ? php
2003-09-25 07:27:22 +00:00
// $Id$
2004-08-21 06:42:38 +00:00
2008-09-20 20:22:25 +00:00
/**
* Root directory of Drupal installation .
*/
2009-02-08 20:27:51 +00:00
define ( 'DRUPAL_ROOT' , getcwd ());
2008-09-20 20:22:25 +00:00
2004-08-21 06:42:38 +00:00
/**
* @ file
* Administrative page for handling updates from one Drupal version to another .
*
2006-03-11 13:45:41 +00:00
* Point your browser to " http://www.example.com/update.php " and follow the
2004-08-21 06:42:38 +00:00
* instructions .
*
* If you are not logged in as administrator , you will need to modify the access
2007-08-28 11:42:56 +00:00
* check statement inside your settings . php file . After finishing the upgrade ,
* be sure to open settings . php again , and change it back to its original state !
2004-08-21 06:42:38 +00:00
*/
2001-12-16 14:42:51 +00:00
2008-01-07 19:43:29 +00:00
/**
* Global flag to identify update . php run , and so avoid various unwanted
* operations , such as hook_init () and hook_exit () invokes , css / js preprocessing
* and translation , and solve some theming issues . This flag is checked on several
* places in Drupal code ( not just update . php ) .
*/
2007-11-30 12:19:10 +00:00
define ( 'MAINTENANCE_MODE' , 'update' );
2005-12-06 09:25:22 +00:00
/**
2006-03-11 13:45:41 +00:00
* Add a column to a database using syntax appropriate for PostgreSQL .
* Save result of SQL commands in $ret array .
2005-12-06 09:25:22 +00:00
*
* Note : when you add a column with NOT NULL and you are not sure if there are
2006-06-19 06:12:08 +00:00
* already rows in the table , you MUST also add DEFAULT . Otherwise PostgreSQL
* won ' t work when the table is not empty , and db_add_column () will fail .
* To have an empty string as the default , you must use : 'default' => " '' "
* in the $attributes array . If NOT NULL and DEFAULT are set the PostgreSQL
* version will set values of the added column in old rows to the
2005-12-06 09:25:22 +00:00
* DEFAULT value .
*
* @ param $ret
2006-03-11 13:45:41 +00:00
* Array to which results will be added .
2005-12-06 09:25:22 +00:00
* @ param $table
2006-03-11 13:45:41 +00:00
* Name of the table , without {}
2005-12-06 09:25:22 +00:00
* @ param $column
2006-03-11 13:45:41 +00:00
* Name of the column
2005-12-06 09:25:22 +00:00
* @ param $type
2006-03-11 13:45:41 +00:00
* Type of column
2005-12-06 09:25:22 +00:00
* @ param $attributes
2006-03-11 13:45:41 +00:00
* Additional optional attributes . Recognized attributes :
* not null => TRUE | FALSE
2006-06-19 06:12:08 +00:00
* default => NULL | FALSE | value ( the value must be enclosed in '' marks )
2005-12-06 09:25:22 +00:00
* @ return
2006-03-11 13:45:41 +00:00
* nothing , but modifies $ret parameter .
2005-12-06 09:25:22 +00:00
*/
function db_add_column ( & $ret , $table , $column , $type , $attributes = array ()) {
if ( array_key_exists ( 'not null' , $attributes ) and $attributes [ 'not null' ]) {
$not_null = 'NOT NULL' ;
}
if ( array_key_exists ( 'default' , $attributes )) {
if ( is_null ( $attributes [ 'default' ])) {
$default_val = 'NULL' ;
$default = 'default NULL' ;
}
elseif ( $attributes [ 'default' ] === FALSE ) {
$default = '' ;
}
else {
$default_val = " $attributes[default] " ;
$default = " default $attributes[default] " ;
2004-02-25 22:20:09 +00:00
}
2001-11-15 22:53:06 +00:00
}
2005-12-06 09:25:22 +00:00
2008-04-14 17:48:46 +00:00
$ret [] = update_sql ( " ALTER TABLE { " . $table . " } ADD $column $type " );
2007-08-26 08:27:09 +00:00
if ( ! empty ( $default )) {
2008-04-14 17:48:46 +00:00
$ret [] = update_sql ( " ALTER TABLE { " . $table . " } ALTER $column SET $default " );
2007-08-26 08:27:09 +00:00
}
if ( ! empty ( $not_null )) {
2007-08-30 19:54:22 +00:00
if ( ! empty ( $default )) {
2008-04-14 17:48:46 +00:00
$ret [] = update_sql ( " UPDATE { " . $table . " } SET $column = $default_val " );
2007-08-26 08:27:09 +00:00
}
2008-04-14 17:48:46 +00:00
$ret [] = update_sql ( " ALTER TABLE { " . $table . " } ALTER $column SET NOT NULL " );
2005-12-06 09:25:22 +00:00
}
2003-05-20 04:52:06 +00:00
}
2005-12-06 09:25:22 +00:00
/**
2006-03-11 13:45:41 +00:00
* Change a column definition using syntax appropriate for PostgreSQL .
* Save result of SQL commands in $ret array .
2005-12-06 09:25:22 +00:00
*
2006-03-11 13:45:41 +00:00
* Remember that changing a column definition involves adding a new column
* and dropping an old one . This means that any indices , primary keys and
* sequences from serial - type columns are dropped and might need to be
2006-01-22 07:30:47 +00:00
* recreated .
*
2005-12-06 09:25:22 +00:00
* @ param $ret
2006-03-11 13:45:41 +00:00
* Array to which results will be added .
2005-12-06 09:25:22 +00:00
* @ param $table
2006-03-11 13:45:41 +00:00
* Name of the table , without {}
2005-12-06 09:25:22 +00:00
* @ param $column
2006-03-11 13:45:41 +00:00
* Name of the column to change
2005-12-06 09:25:22 +00:00
* @ param $column_new
2006-03-11 13:45:41 +00:00
* New name for the column ( set to the same as $column if you don ' t want to change the name )
2005-12-06 09:25:22 +00:00
* @ param $type
2006-03-11 13:45:41 +00:00
* Type of column
2005-12-06 09:25:22 +00:00
* @ param $attributes
2006-03-11 13:45:41 +00:00
* Additional optional attributes . Recognized attributes :
* not null => TRUE | FALSE
* default => NULL | FALSE | value ( with or without '' , it won ' t be added )
2005-12-06 09:25:22 +00:00
* @ return
2006-03-11 13:45:41 +00:00
* nothing , but modifies $ret parameter .
2005-12-06 09:25:22 +00:00
*/
function db_change_column ( & $ret , $table , $column , $column_new , $type , $attributes = array ()) {
if ( array_key_exists ( 'not null' , $attributes ) and $attributes [ 'not null' ]) {
$not_null = 'NOT NULL' ;
}
if ( array_key_exists ( 'default' , $attributes )) {
if ( is_null ( $attributes [ 'default' ])) {
$default_val = 'NULL' ;
$default = 'default NULL' ;
}
elseif ( $attributes [ 'default' ] === FALSE ) {
$default = '' ;
}
else {
$default_val = " $attributes[default] " ;
$default = " default $attributes[default] " ;
}
}
2008-04-14 17:48:46 +00:00
$ret [] = update_sql ( " ALTER TABLE { " . $table . " } RENAME $column TO " . $column . " _old " );
$ret [] = update_sql ( " ALTER TABLE { " . $table . " } ADD $column_new $type " );
$ret [] = update_sql ( " UPDATE { " . $table . " } SET $column_new = " . $column . " _old " );
2008-03-19 07:36:28 +00:00
if ( $default ) {
2008-04-14 17:48:46 +00:00
$ret [] = update_sql ( " ALTER TABLE { " . $table . " } ALTER $column_new SET $default " );
2008-03-19 07:36:28 +00:00
}
if ( $not_null ) {
2008-04-14 17:48:46 +00:00
$ret [] = update_sql ( " ALTER TABLE { " . $table . " } ALTER $column_new SET NOT NULL " );
2008-03-19 07:36:28 +00:00
}
2008-04-14 17:48:46 +00:00
$ret [] = update_sql ( " ALTER TABLE { " . $table . " } DROP " . $column . " _old " );
2005-12-06 09:25:22 +00:00
}
2005-12-09 15:33:39 +00:00
/**
* Perform one update and store the results which will later be displayed on
* the finished page .
*
2008-01-17 20:05:23 +00:00
* An update function can force the current and all later updates for this
* module to abort by returning a $ret array with an element like :
* $ret [ '#abort' ] = array ( 'success' => FALSE , 'query' => 'What went wrong' );
* The schema version will not be updated in this case , and all the
* aborted updates will continue to appear on update . php as updates that
* have not yet been run .
*
2005-12-09 15:33:39 +00:00
* @ param $module
* The module whose update will be run .
* @ param $number
* The update number to run .
2007-05-04 09:41:37 +00:00
* @ param $context
2007-07-02 14:41:37 +00:00
* The batch context array
2005-12-09 15:33:39 +00:00
*/
2007-05-04 09:41:37 +00:00
function update_do_one ( $module , $number , & $context ) {
2008-01-17 20:05:23 +00:00
// If updates for this module have been aborted
// in a previous step, go no further.
if ( ! empty ( $context [ 'results' ][ $module ][ '#abort' ])) {
return ;
}
2008-04-14 17:48:46 +00:00
$function = $module . '_update_' . $number ;
2007-05-04 09:41:37 +00:00
if ( function_exists ( $function )) {
2007-05-07 10:06:00 +00:00
$ret = $function ( $context [ 'sandbox' ]);
2007-05-04 09:41:37 +00:00
}
2005-12-09 15:33:39 +00:00
if ( isset ( $ret [ '#finished' ])) {
2007-05-04 09:41:37 +00:00
$context [ 'finished' ] = $ret [ '#finished' ];
2005-12-09 15:33:39 +00:00
unset ( $ret [ '#finished' ]);
}
2005-12-06 09:25:22 +00:00
2007-05-04 09:41:37 +00:00
if ( ! isset ( $context [ 'results' ][ $module ])) {
$context [ 'results' ][ $module ] = array ();
2005-12-06 09:25:22 +00:00
}
2007-05-04 09:41:37 +00:00
if ( ! isset ( $context [ 'results' ][ $module ][ $number ])) {
$context [ 'results' ][ $module ][ $number ] = array ();
2005-12-09 15:33:39 +00:00
}
2008-01-17 20:05:23 +00:00
$context [ 'results' ][ $module ][ $number ] = array_merge ( $context [ 'results' ][ $module ][ $number ], $ret );
2005-12-09 15:33:39 +00:00
2008-01-17 20:05:23 +00:00
if ( ! empty ( $ret [ '#abort' ])) {
$context [ 'results' ][ $module ][ '#abort' ] = TRUE ;
}
2008-01-21 15:06:41 +00:00
// Record the schema update if it was completed successfully.
if ( $context [ 'finished' ] == 1 && empty ( $context [ 'results' ][ $module ][ '#abort' ])) {
2005-12-09 15:33:39 +00:00
drupal_set_installed_schema_version ( $module , $number );
}
2005-12-06 09:25:22 +00:00
2008-04-14 17:48:46 +00:00
$context [ 'message' ] = 'Updating ' . check_plain ( $module ) . ' module' ;
2005-12-06 09:25:22 +00:00
}
function update_selection_page () {
2006-08-18 18:58:47 +00:00
drupal_set_title ( 'Drupal database update' );
2008-08-31 12:45:41 +00:00
$output = drupal_get_form ( 'update_script_selection_form' );
2006-08-18 18:58:47 +00:00
2007-03-02 09:40:27 +00:00
update_task_list ( 'select' );
2006-08-18 18:58:47 +00:00
return $output ;
}
function update_script_selection_form () {
2008-10-24 18:47:02 +00:00
$form = array ();
$count = 0 ;
2005-10-07 06:11:12 +00:00
$form [ 'start' ] = array (
2005-12-06 09:25:22 +00:00
'#tree' => TRUE ,
'#type' => 'fieldset' ,
'#collapsed' => TRUE ,
2008-08-31 12:45:41 +00:00
'#collapsible' => TRUE ,
2005-12-06 09:25:22 +00:00
);
2006-07-31 16:23:52 +00:00
// Ensure system.module's updates appear first
$form [ 'start' ][ 'system' ] = array ();
2007-12-17 12:23:01 +00:00
$modules = drupal_get_installed_schema_version ( NULL , FALSE , TRUE );
foreach ( $modules as $module => $schema_version ) {
2008-08-31 12:45:41 +00:00
$pending = array ();
2005-12-09 16:14:26 +00:00
$updates = drupal_get_schema_versions ( $module );
2007-12-17 12:23:01 +00:00
// Skip incompatible module updates completely, otherwise test schema versions.
if ( ! update_check_incompatibility ( $module ) && $updates !== FALSE && $schema_version >= 0 ) {
// module_invoke returns NULL for nonexisting hooks, so if no updates
// are removed, it will == 0.
$last_removed = module_invoke ( $module , 'update_last_removed' );
if ( $schema_version < $last_removed ) {
$form [ 'start' ][ $module ] = array (
2008-08-31 12:45:41 +00:00
'#title' => $module ,
'#item' => '<em>' . $module . '</em> module can not be updated. Its schema version is ' . $schema_version . '. Updates up to and including ' . $last_removed . ' have been removed in this release. In order to update <em>' . $module . '</em> module, you will first <a href="http://drupal.org/upgrade">need to upgrade</a> to the last version in which these updates were available.' ,
2007-12-17 12:23:01 +00:00
'#prefix' => '<div class="warning">' ,
'#suffix' => '</div>' ,
);
continue ;
}
2005-12-09 16:14:26 +00:00
$updates = drupal_map_assoc ( $updates );
2006-08-14 05:47:36 +00:00
foreach ( array_keys ( $updates ) as $update ) {
2007-12-17 12:23:01 +00:00
if ( $update > $schema_version ) {
2008-08-31 12:45:41 +00:00
// The description for an update comes from its Doxygen.
$func = new ReflectionFunction ( $module . '_update_' . $update );
$description = str_replace ( array ( " \n " , '*' , '/' ), '' , $func -> getDocComment ());
$pending [] = " $update - $description " ;
if ( ! isset ( $default )) {
$default = $update ;
}
}
}
if ( ! empty ( $pending )) {
if ( ! isset ( $default )) {
$default = $schema_version ;
2006-08-14 05:47:36 +00:00
}
2008-08-31 12:45:41 +00:00
$form [ 'start' ][ $module ] = array (
'#type' => 'hidden' ,
'#value' => $default ,
);
$form [ 'start' ][ $module . '_updates' ] = array (
'#markup' => theme ( 'item_list' , $pending , $module . ' module' ),
);
2006-08-14 05:47:36 +00:00
}
2005-12-06 09:25:22 +00:00
}
2008-08-31 12:45:41 +00:00
unset ( $default );
2008-10-24 18:47:02 +00:00
$count = $count + count ( $pending );
2005-12-06 09:25:22 +00:00
}
2008-10-24 18:47:02 +00:00
if ( empty ( $count )) {
2008-08-31 12:45:41 +00:00
drupal_set_message ( t ( 'No pending updates.' ));
unset ( $form );
$form [ 'links' ] = array (
'#markup' => theme ( 'item_list' , update_helpful_links ()),
);
}
else {
$form [ 'help' ] = array (
'#markup' => '<p>The version of Drupal you are updating from has been automatically detected.</p>' ,
'#weight' => - 5 ,
);
2008-10-24 18:47:02 +00:00
$form [ 'start' ][ '#title' ] = strtr ( '!num pending updates' , array ( '!num' => $count ));
2008-08-31 12:45:41 +00:00
$form [ 'has_js' ] = array (
'#type' => 'hidden' ,
'#default_value' => FALSE ,
'#attributes' => array ( 'id' => 'edit-has_js' ),
);
$form [ 'submit' ] = array (
'#type' => 'submit' ,
2009-03-01 08:07:36 +00:00
'#value' => 'Apply pending updates' ,
2008-08-31 12:45:41 +00:00
);
}
2006-08-18 18:58:47 +00:00
return $form ;
2005-12-06 09:25:22 +00:00
}
2007-05-04 09:41:37 +00:00
function update_batch () {
global $base_url ;
2008-10-08 11:11:09 +00:00
// During the update, toggle site maintenance so that schema changes do not
// affect visiting users.
2009-01-19 10:46:52 +00:00
drupal_set_session ( 'site_offline' , variable_get ( 'site_offline' , FALSE ));
2008-10-08 11:11:09 +00:00
if ( $_SESSION [ 'site_offline' ] == FALSE ) {
2008-09-19 07:17:58 +00:00
variable_set ( 'site_offline' , TRUE );
}
2007-05-04 09:41:37 +00:00
$operations = array ();
2005-12-06 09:25:22 +00:00
// Set the installed version so updates start at the correct place.
2006-08-29 09:12:03 +00:00
foreach ( $_POST [ 'start' ] as $module => $version ) {
2005-12-08 08:40:10 +00:00
drupal_set_installed_schema_version ( $module , $version - 1 );
2006-08-14 05:47:36 +00:00
$updates = drupal_get_schema_versions ( $module );
$max_version = max ( $updates );
2005-12-06 09:25:22 +00:00
if ( $version <= $max_version ) {
2006-08-14 05:47:36 +00:00
foreach ( $updates as $update ) {
if ( $update >= $version ) {
2007-05-04 09:41:37 +00:00
$operations [] = array ( 'update_do_one' , array ( $module , $update ));
2006-08-14 05:47:36 +00:00
}
2005-12-06 09:25:22 +00:00
}
}
}
2007-05-04 09:41:37 +00:00
$batch = array (
'operations' => $operations ,
'title' => 'Updating' ,
'init_message' => 'Starting updates' ,
2007-07-02 14:41:37 +00:00
'error_message' => 'An unrecoverable error has occurred. You can find the error message below. It is advised to copy it to the clipboard for reference.' ,
2007-05-04 09:41:37 +00:00
'finished' => 'update_finished' ,
);
batch_set ( $batch );
2008-04-14 17:48:46 +00:00
batch_process ( $base_url . '/update.php?op=results' , $base_url . '/update.php' );
2005-12-06 09:25:22 +00:00
}
2007-05-04 09:41:37 +00:00
function update_finished ( $success , $results , $operations ) {
// clear the caches in case the data has been updated.
2008-01-07 19:43:29 +00:00
drupal_flush_all_caches ();
2005-12-06 09:25:22 +00:00
2009-01-19 10:46:52 +00:00
drupal_set_session ( 'update_results' , $results );
drupal_set_session ( 'update_success' , $success );
drupal_set_session ( 'updates_remaining' , $operations );
2008-11-03 05:55:57 +00:00
2008-10-08 11:11:09 +00:00
// Now that the update is done, we can disable site maintenance if it was
// previously turned off.
if ( isset ( $_SESSION [ 'site_offline' ]) && $_SESSION [ 'site_offline' ] == FALSE ) {
variable_set ( 'site_offline' , FALSE );
unset ( $_SESSION [ 'site_offline' ]);
}
2005-12-06 09:25:22 +00:00
}
2008-08-31 12:45:41 +00:00
function update_helpful_links () {
2005-08-17 01:44:14 +00:00
// NOTE: we can't use l() here because the URL would point to 'update.php?q=admin'.
2009-01-17 18:55:29 +00:00
$links [] = '<a href="' . base_path () . '">Front page</a>' ;
2008-04-14 17:48:46 +00:00
$links [] = '<a href="' . base_path () . '?q=admin">Administration pages</a>' ;
2008-08-31 12:45:41 +00:00
return $links ;
}
function update_results_page () {
drupal_set_title ( 'Drupal database update' );
$links = update_helpful_links ();
2006-03-01 22:19:24 +00:00
2007-03-02 09:40:27 +00:00
update_task_list ();
2006-03-28 09:29:23 +00:00
// Report end result
2007-10-02 08:41:13 +00:00
if ( module_exists ( 'dblog' )) {
2008-04-14 17:48:46 +00:00
$log_message = ' All errors have been <a href="' . base_path () . '?q=admin/reports/dblog">logged</a>.' ;
2007-10-02 08:41:13 +00:00
}
else {
$log_message = ' All errors have been logged.' ;
}
2007-05-04 09:41:37 +00:00
if ( $_SESSION [ 'update_success' ]) {
2008-04-14 17:48:46 +00:00
$output = '<p>Updates were attempted. If you see no failures below, you may proceed happily to the <a href="' . base_path () . '?q=admin">administration pages</a>. Otherwise, you may need to update your database manually.' . $log_message . '</p>' ;
2006-03-01 22:19:24 +00:00
}
else {
2007-05-04 09:41:37 +00:00
list ( $module , $version ) = array_pop ( reset ( $_SESSION [ 'updates_remaining' ]));
2008-04-14 17:48:46 +00:00
$output = '<p class="error">The update process was aborted prematurely while running <strong>update #' . $version . ' in ' . $module . '.module</strong>.' . $log_message ;
2007-10-02 08:41:13 +00:00
if ( module_exists ( 'dblog' )) {
$output .= ' You may need to check the <code>watchdog</code> database table manually.' ;
}
$output .= '</p>' ;
2006-03-01 22:19:24 +00:00
}
2007-08-28 11:42:56 +00:00
if ( ! empty ( $GLOBALS [ 'update_free_access' ])) {
$output .= " <p><strong>Reminder: don't forget to set the <code> \$ update_free_access</code> value in your <code>settings.php</code> file back to <code>FALSE</code>.</strong></p> " ;
2001-11-15 22:53:06 +00:00
}
2007-05-06 05:47:52 +00:00
2005-12-06 09:25:22 +00:00
$output .= theme ( 'item_list' , $links );
// Output a list of queries executed
2007-03-28 07:02:47 +00:00
if ( ! empty ( $_SESSION [ 'update_results' ])) {
2005-12-06 09:25:22 +00:00
$output .= '<div id="update-results">' ;
$output .= '<h2>The following queries were executed</h2>' ;
foreach ( $_SESSION [ 'update_results' ] as $module => $updates ) {
2008-04-14 17:48:46 +00:00
$output .= '<h3>' . $module . ' module</h3>' ;
2005-12-06 09:25:22 +00:00
foreach ( $updates as $number => $queries ) {
2008-01-17 20:05:23 +00:00
if ( $number != '#abort' ) {
2008-04-14 17:48:46 +00:00
$output .= '<h4>Update #' . $number . '</h4>' ;
2008-01-17 20:05:23 +00:00
$output .= '<ul>' ;
foreach ( $queries as $query ) {
if ( $query [ 'success' ]) {
2008-04-14 17:48:46 +00:00
$output .= '<li class="success">' . $query [ 'query' ] . '</li>' ;
2008-01-17 20:05:23 +00:00
}
else {
2008-04-14 17:48:46 +00:00
$output .= '<li class="failure"><strong>Failed:</strong> ' . $query [ 'query' ] . '</li>' ;
2008-01-17 20:05:23 +00:00
}
2005-12-06 09:25:22 +00:00
}
2008-01-17 20:05:23 +00:00
if ( ! count ( $queries )) {
$output .= '<li class="none">No queries</li>' ;
2005-12-06 09:25:22 +00:00
}
}
$output .= '</ul>' ;
}
}
$output .= '</div>' ;
}
2007-05-04 09:41:37 +00:00
unset ( $_SESSION [ 'update_results' ]);
unset ( $_SESSION [ 'update_success' ]);
2005-12-06 09:25:22 +00:00
2005-08-17 01:44:14 +00:00
return $output ;
2001-11-15 22:53:06 +00:00
}
2005-08-17 01:44:14 +00:00
function update_info_page () {
2008-01-07 19:43:29 +00:00
// Change query-strings on css/js files to enforce reload for all users.
_drupal_flush_css_js ();
2008-01-30 22:13:25 +00:00
// Flush the cache of all data for the update status module.
if ( db_table_exists ( 'cache_update' )) {
2008-02-03 18:41:16 +00:00
cache_clear_all ( '*' , 'cache_update' , TRUE );
2008-01-30 22:13:25 +00:00
}
2008-01-07 19:43:29 +00:00
2007-03-02 09:40:27 +00:00
update_task_list ( 'info' );
2005-07-29 20:31:05 +00:00
drupal_set_title ( 'Drupal database update' );
2009-01-21 14:47:12 +00:00
$token = drupal_get_token ( 'update' );
2007-07-15 05:57:40 +00:00
$output = '<p>Use this utility to update your database whenever a new release of Drupal or a module is installed.</p><p>For more detailed information, see the <a href="http://drupal.org/node/258">Installation and upgrading handbook</a>. If you are unsure what these terms mean you should probably contact your hosting provider.</p>' ;
$output .= " <ol> \n " ;
$output .= " <li><strong>Back up your database</strong>. This process will change your database values and in case of emergency you may need to revert to a backup.</li> \n " ;
$output .= " <li><strong>Back up your code</strong>. Hint: when backing up module code, do not leave that backup in the 'modules' or 'sites/*/modules' directories as this may confuse Drupal's auto-discovery mechanism.</li> \n " ;
2008-04-14 17:48:46 +00:00
$output .= '<li>Put your site into <a href="' . base_path () . '?q=admin/settings/site-maintenance">maintenance mode</a>.</li>' . " \n " ;
2007-07-15 05:57:40 +00:00
$output .= " <li>Install your new files in the appropriate location, as described in the handbook.</li> \n " ;
$output .= " </ol> \n " ;
$output .= " <p>When you have performed the steps above, you may proceed.</p> \n " ;
2009-01-21 14:47:12 +00:00
$output .= '<form method="post" action="update.php?op=selection&token=' . $token . '"><input type="submit" value="Continue" /></form>' ;
2007-07-15 05:57:40 +00:00
$output .= " \n " ;
2005-08-17 01:44:14 +00:00
return $output ;
}
function update_access_denied_page () {
drupal_set_title ( 'Access denied' );
2007-08-28 11:42:56 +00:00
return ' < p > Access denied . You are not authorized to access this page . Please log in as the admin user ( the first user you created ) . If you cannot log in , you will have to edit < code > settings . php </ code > to bypass this access check . To do this :</ p >
2005-08-17 01:44:14 +00:00
< ol >
2007-08-28 11:42:56 +00:00
< li > With a text editor find the settings . php file on your system . From the main Drupal directory that you installed all the files into , go to < code > sites / your_site_name </ code > if such directory exists , or else to < code > sites / default </ code > which applies otherwise .</ li >
< li > There is a line inside your settings . php file that says < code > $update_free_access = FALSE ; </ code >. Change it to < code > $update_free_access = TRUE ; </ code >.</ li >
< li > As soon as the update . php script is done , you must change the settings . php file back to its original form with < code > $update_free_access = FALSE ; </ code >.</ li >
2005-08-17 01:44:14 +00:00
< li > To avoid having this problem in future , remember to log in to your website as the admin user ( the user you first created ) before you backup your database at the beginning of the update process .</ li >
</ ol > ' ;
2001-11-15 22:53:06 +00:00
}
2002-05-11 17:23:45 +00:00
2007-05-04 09:41:37 +00:00
/**
* Create the batch table .
*
* This is part of the Drupal 5. x to 6. x migration .
*/
function update_create_batch_table () {
// If batch table exists, update is not necessary
if ( db_table_exists ( 'batch' )) {
return ;
}
2007-09-14 17:46:32 +00:00
$schema [ 'batch' ] = array (
'fields' => array (
'bid' => array ( 'type' => 'serial' , 'unsigned' => TRUE , 'not null' => TRUE ),
'token' => array ( 'type' => 'varchar' , 'length' => 64 , 'not null' => TRUE ),
'timestamp' => array ( 'type' => 'int' , 'not null' => TRUE ),
'batch' => array ( 'type' => 'text' , 'not null' => FALSE , 'size' => 'big' )
),
'primary key' => array ( 'bid' ),
'indexes' => array ( 'token' => array ( 'token' )),
);
2007-05-04 09:41:37 +00:00
$ret = array ();
2007-09-14 17:46:32 +00:00
db_create_table ( $ret , 'batch' , $schema [ 'batch' ]);
2007-05-04 09:41:37 +00:00
return $ret ;
}
2007-06-08 05:50:58 +00:00
/**
* Disable anything in the { system } table that is not compatible with the
* current version of Drupal core .
*/
function update_fix_compatibility () {
$ret = array ();
$incompatible = array ();
$query = db_query ( " SELECT name, type, status FROM { system} WHERE status = 1 AND type IN ('module','theme') " );
while ( $result = db_fetch_object ( $query )) {
2007-12-17 12:23:01 +00:00
if ( update_check_incompatibility ( $result -> name , $result -> type )) {
2007-12-18 15:48:14 +00:00
$incompatible [] = $result -> name ;
2007-06-08 05:50:58 +00:00
}
}
if ( ! empty ( $incompatible )) {
2008-04-14 17:48:46 +00:00
$ret [] = update_sql ( " UPDATE { system} SET status = 0 WHERE name IN (' " . implode ( " ',' " , $incompatible ) . " ') " );
2007-06-08 05:50:58 +00:00
}
return $ret ;
}
2007-12-17 12:23:01 +00:00
/**
* Helper function to test compatibility of a module or theme .
*/
function update_check_incompatibility ( $name , $type = 'module' ) {
static $themes , $modules ;
// Store values of expensive functions for future use.
if ( empty ( $themes ) || empty ( $modules )) {
2008-10-10 07:35:51 +00:00
$themes = _system_theme_data ();
2007-12-17 12:23:01 +00:00
$modules = module_rebuild_cache ();
}
if ( $type == 'module' && isset ( $modules [ $name ])) {
$file = $modules [ $name ];
}
2008-10-12 04:30:09 +00:00
elseif ( $type == 'theme' && isset ( $themes [ $name ])) {
2007-12-17 12:23:01 +00:00
$file = $themes [ $name ];
}
if ( ! isset ( $file )
|| ! isset ( $file -> info [ 'core' ])
|| $file -> info [ 'core' ] != DRUPAL_CORE_COMPATIBILITY
2008-11-20 07:07:59 +00:00
|| version_compare ( phpversion (), $file -> info [ 'php' ]) < 0
|| ( $type == 'module' && empty ( $file -> info [ 'files' ]))) {
2007-12-17 12:23:01 +00:00
return TRUE ;
}
return FALSE ;
}
2007-08-26 08:27:09 +00:00
/**
* Perform Drupal 5. x to 6. x updates that are required for update . php
* to function properly .
*
* This function runs when update . php is run the first time for 6. x ,
2008-12-20 18:24:41 +00:00
* even before updates are selected or performed . It is important
2007-08-26 08:27:09 +00:00
* that if updates are not ultimately performed that no changes are
* made which make it impossible to continue using the prior version .
2008-12-20 18:24:41 +00:00
* Just adding columns is safe . However , renaming the
* system . description column to owner is not . Therefore , we add the
2007-08-26 08:27:09 +00:00
* system . owner column and leave it to system_update_6008 () to copy
* the data from description and remove description . The same for
* renaming locales_target . locale to locales_target . language , which
* will be finished by locale_update_6002 () .
*/
function update_fix_d6_requirements () {
$ret = array ();
if ( drupal_get_installed_schema_version ( 'system' ) < 6000 && ! variable_get ( 'update_d6_requirements' , FALSE )) {
$spec = array ( 'type' => 'int' , 'size' => 'small' , 'default' => 0 , 'not null' => TRUE );
db_add_field ( $ret , 'cache' , 'serialized' , $spec );
db_add_field ( $ret , 'cache_filter' , 'serialized' , $spec );
db_add_field ( $ret , 'cache_page' , 'serialized' , $spec );
db_add_field ( $ret , 'cache_menu' , 'serialized' , $spec );
db_add_field ( $ret , 'system' , 'info' , array ( 'type' => 'text' ));
db_add_field ( $ret , 'system' , 'owner' , array ( 'type' => 'varchar' , 'length' => 255 , 'not null' => TRUE , 'default' => '' ));
if ( db_table_exists ( 'locales_target' )) {
db_add_field ( $ret , 'locales_target' , 'language' , array ( 'type' => 'varchar' , 'length' => 12 , 'not null' => TRUE , 'default' => '' ));
}
if ( db_table_exists ( 'locales_source' )) {
db_add_field ( $ret , 'locales_source' , 'textgroup' , array ( 'type' => 'varchar' , 'length' => 255 , 'not null' => TRUE , 'default' => 'default' ));
2007-09-02 15:19:16 +00:00
db_add_field ( $ret , 'locales_source' , 'version' , array ( 'type' => 'varchar' , 'length' => 20 , 'not null' => TRUE , 'default' => 'none' ));
2007-08-26 08:27:09 +00:00
}
variable_set ( 'update_d6_requirements' , TRUE );
2007-10-09 16:08:37 +00:00
// Create the cache_block table. See system_update_6027() for more details.
$schema [ 'cache_block' ] = array (
'fields' => array (
'cid' => array ( 'type' => 'varchar' , 'length' => 255 , 'not null' => TRUE , 'default' => '' ),
'data' => array ( 'type' => 'blob' , 'not null' => FALSE , 'size' => 'big' ),
'expire' => array ( 'type' => 'int' , 'not null' => TRUE , 'default' => 0 ),
'created' => array ( 'type' => 'int' , 'not null' => TRUE , 'default' => 0 ),
'headers' => array ( 'type' => 'text' , 'not null' => FALSE ),
'serialized' => array ( 'type' => 'int' , 'size' => 'small' , 'not null' => TRUE , 'default' => 0 )
),
'indexes' => array ( 'expire' => array ( 'expire' )),
'primary key' => array ( 'cid' ),
);
db_create_table ( $ret , 'cache_block' , $schema [ 'cache_block' ]);
2007-08-26 08:27:09 +00:00
}
return $ret ;
}
2008-11-03 05:55:57 +00:00
/**
* Users who still have a Drupal 6 database ( and are in the process of
* updating to Drupal 7 ) need extra help before a full bootstrap can be
* achieved . This function does the necessary preliminary work that allows
* the bootstrap to be successful .
*
* No access check has been performed when this function is called , so no
* changes to the database should be made here .
*/
function update_prepare_d7_bootstrap () {
// Allow the database system to work even though the registry has not
// been created yet.
drupal_bootstrap ( DRUPAL_BOOTSTRAP_DATABASE );
include_once DRUPAL_ROOT . '/includes/install.inc' ;
drupal_install_init_database ();
spl_autoload_unregister ( 'drupal_autoload_class' );
spl_autoload_unregister ( 'drupal_autoload_interface' );
// The new {blocked_ips} table is used in Drupal 7 to store a list of
// banned IP addresses. If this table doesn't exist then we are still
// running on a Drupal 6 database, so suppress the unavoidable errors
// that occur.
try {
drupal_bootstrap ( DRUPAL_BOOTSTRAP_ACCESS );
}
catch ( Exception $e ) {
if ( db_table_exists ( 'blocked_ips' )) {
throw $e ;
}
}
}
2007-03-02 09:40:27 +00:00
/**
* Add the update task list to the current page .
*/
function update_task_list ( $active = NULL ) {
// Default list of tasks.
$tasks = array (
'info' => 'Overview' ,
2008-08-31 12:45:41 +00:00
'select' => 'Review updates' ,
2007-03-02 09:40:27 +00:00
'run' => 'Run updates' ,
'finished' => 'Review log' ,
);
2007-11-30 12:19:10 +00:00
drupal_set_content ( 'left' , theme ( 'task_list' , $tasks , $active ));
2007-03-02 09:40:27 +00:00
}
2008-01-16 10:37:43 +00:00
/**
* Check update requirements and report any errors .
*/
function update_check_requirements () {
// Check the system module requirements only.
$requirements = module_invoke ( 'system' , 'requirements' , 'update' );
$severity = drupal_requirements_severity ( $requirements );
// If there are issues, report them.
if ( $severity != REQUIREMENT_OK ) {
foreach ( $requirements as $requirement ) {
if ( isset ( $requirement [ 'severity' ]) && $requirement [ 'severity' ] != REQUIREMENT_OK ) {
$message = isset ( $requirement [ 'description' ]) ? $requirement [ 'description' ] : '' ;
if ( isset ( $requirement [ 'value' ]) && $requirement [ 'value' ]) {
2008-04-14 17:48:46 +00:00
$message .= ' (Currently using ' . $requirement [ 'title' ] . ' ' . $requirement [ 'value' ] . ')' ;
2008-01-16 10:37:43 +00:00
}
drupal_set_message ( $message , 'warning' );
}
}
}
}
2006-03-11 13:45:41 +00:00
// Some unavoidable errors happen because the database is not yet up-to-date.
2006-04-11 11:33:15 +00:00
// Our custom error handler is not yet installed, so we just suppress them.
2006-03-01 22:19:24 +00:00
ini_set ( 'display_errors' , FALSE );
2008-09-20 20:22:25 +00:00
require_once DRUPAL_ROOT . '/includes/bootstrap.inc' ;
2008-01-16 10:37:43 +00:00
// We only load DRUPAL_BOOTSTRAP_CONFIGURATION for the update requirements
// check to avoid reaching the PHP memory limit.
$op = isset ( $_REQUEST [ 'op' ]) ? $_REQUEST [ 'op' ] : '' ;
if ( empty ( $op )) {
// Minimum load of components.
drupal_bootstrap ( DRUPAL_BOOTSTRAP_CONFIGURATION );
2008-09-20 20:22:25 +00:00
require_once DRUPAL_ROOT . '/includes/install.inc' ;
require_once DRUPAL_ROOT . '/includes/file.inc' ;
require_once DRUPAL_ROOT . '/modules/system/system.install' ;
2008-01-16 10:37:43 +00:00
// Load module basics.
2008-09-20 20:22:25 +00:00
include_once DRUPAL_ROOT . '/includes/module.inc' ;
2008-01-16 10:37:43 +00:00
$module_list [ 'system' ][ 'filename' ] = 'modules/system/system.module' ;
$module_list [ 'filter' ][ 'filename' ] = 'modules/filter/filter.module' ;
2008-11-24 10:41:40 +00:00
module_list ( TRUE , FALSE , $module_list );
2008-01-16 10:37:43 +00:00
drupal_load ( 'module' , 'system' );
drupal_load ( 'module' , 'filter' );
// Set up $language, since the installer components require it.
drupal_init_language ();
// Set up theme system for the maintenance page.
drupal_maintenance_theme ();
// Check the update requirements for Drupal.
update_check_requirements ();
// Display the warning messages (if any) in a dedicated maintenance page,
// or redirect to the update information page if no message.
$messages = drupal_set_message ();
if ( ! empty ( $messages [ 'warning' ])) {
drupal_maintenance_theme ();
print theme ( 'update_page' , '<form method="post" action="update.php?op=info"><input type="submit" value="Continue" /></form>' , FALSE );
exit ;
}
install_goto ( 'update.php?op=info' );
}
2006-03-28 09:29:23 +00:00
2008-11-03 05:55:57 +00:00
update_prepare_d7_bootstrap ();
2005-12-06 09:25:22 +00:00
drupal_bootstrap ( DRUPAL_BOOTSTRAP_FULL );
2005-07-29 20:31:05 +00:00
drupal_maintenance_theme ();
2005-08-31 17:56:07 +00:00
2006-03-28 09:29:23 +00:00
// Turn error reporting back on. From now on, only fatal errors (which are
// not passed through the error handler) will cause a message to be printed.
ini_set ( 'display_errors' , TRUE );
2005-12-06 09:25:22 +00:00
// Access check:
2007-08-28 11:42:56 +00:00
if ( ! empty ( $update_free_access ) || $user -> uid == 1 ) {
2006-03-28 09:29:23 +00:00
2008-09-20 20:22:25 +00:00
include_once DRUPAL_ROOT . '/includes/install.inc' ;
include_once DRUPAL_ROOT . '/includes/batch.inc' ;
2006-07-31 19:24:16 +00:00
drupal_load_updates ();
2003-01-07 05:56:47 +00:00
2007-08-26 08:27:09 +00:00
update_fix_d6_requirements ();
2007-06-08 05:50:58 +00:00
update_fix_compatibility ();
2005-08-17 01:44:14 +00:00
2005-12-06 09:25:22 +00:00
$op = isset ( $_REQUEST [ 'op' ]) ? $_REQUEST [ 'op' ] : '' ;
switch ( $op ) {
2007-05-04 09:41:37 +00:00
// update.php ops
2005-12-06 09:25:22 +00:00
2007-05-04 09:41:37 +00:00
case 'selection' :
2009-01-21 14:47:12 +00:00
if ( isset ( $_GET [ 'token' ]) && $_GET [ 'token' ] == drupal_get_token ( 'update' )) {
$output = update_selection_page ();
break ;
}
2005-12-06 09:25:22 +00:00
2009-03-01 09:17:53 +00:00
case 'Apply pending updates' :
2009-01-21 14:47:12 +00:00
if ( isset ( $_GET [ 'token' ]) && $_GET [ 'token' ] == drupal_get_token ( 'update' )) {
update_batch ();
break ;
}
case 'info' :
$output = update_info_page ();
2005-12-06 09:25:22 +00:00
break ;
2007-05-04 09:41:37 +00:00
case 'results' :
$output = update_results_page ();
2005-12-06 09:25:22 +00:00
break ;
2007-05-04 09:41:37 +00:00
// Regular batch ops : defer to batch processing API
2005-12-06 09:25:22 +00:00
default :
2007-05-04 09:41:37 +00:00
update_task_list ( 'run' );
$output = _batch_page ();
2005-12-06 09:25:22 +00:00
break ;
2002-05-15 22:36:30 +00:00
}
}
else {
2005-12-06 09:25:22 +00:00
$output = update_access_denied_page ();
2005-08-17 01:44:14 +00:00
}
2007-05-04 09:41:37 +00:00
if ( isset ( $output ) && $output ) {
2007-12-20 11:57:20 +00:00
// We defer the display of messages until all updates are done.
$progress_page = ( $batch = batch_get ()) && isset ( $batch [ 'running' ]);
print theme ( 'update_page' , $output , ! $progress_page );
2006-03-14 21:19:41 +00:00
}