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
function update_selection_page () {
2006-08-18 18:58:47 +00:00
drupal_set_title ( 'Drupal database update' );
2009-05-12 08:37:45 +00:00
$output = drupal_render ( 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 ();
2009-08-21 06:40:05 +00:00
$updates = update_get_update_list ();
foreach ( $updates as $module => $update ) {
if ( ! isset ( $update [ 'start' ])) {
$form [ 'start' ][ $module ] = array (
'#title' => $module ,
'#item' => $update [ 'warning' ],
'#prefix' => '<div class="warning">' ,
'#suffix' => '</div>' ,
);
continue ;
}
if ( ! empty ( $update [ 'pending' ])) {
$form [ 'start' ][ $module ] = array (
'#type' => 'hidden' ,
'#value' => $update [ 'start' ],
);
$form [ 'start' ][ $module . '_updates' ] = array (
'#markup' => theme ( 'item_list' , $update [ 'pending' ], $module . ' module' ),
);
}
if ( isset ( $update [ 'pending' ])) {
$count = $count + count ( $update [ '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 ,
);
$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
}
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 " ;
2009-08-11 17:26:33 +00:00
$output .= '<li>Put your site into <a href="' . base_path () . '?q=admin/config/development/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-03-09 20:58:19 +00:00
$output .= '<form method="post" action="update.php?op=selection&token=' . $token . '"><p><input type="submit" value="Continue" /></p></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-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 (
2009-05-09 18:35:01 +00:00
'requirements' => 'Verify requirements' ,
2007-03-02 09:40:27 +00:00
'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' ,
);
2009-08-11 12:20:26 +00:00
drupal_add_region_content ( 'sidebar_first' , theme ( 'task_list' , $tasks , $active ));
2007-03-02 09:40:27 +00:00
}
2008-01-16 10:37:43 +00:00
/**
2009-05-09 18:35:01 +00:00
* Returns ( and optionally stores ) extra requirements that only apply during
* particular parts of the update . php process .
2008-01-16 10:37:43 +00:00
*/
2009-05-09 18:35:01 +00:00
function update_extra_requirements ( $requirements = NULL ) {
static $extra_requirements = array ();
if ( isset ( $requirements )) {
$extra_requirements += $requirements ;
2008-01-16 10:37:43 +00:00
}
2009-05-09 18:35:01 +00:00
return $extra_requirements ;
2009-03-01 09:32:17 +00:00
}
/**
2009-05-09 18:35:01 +00:00
* Check update requirements and report any errors .
2009-03-01 09:32:17 +00:00
*/
2009-05-09 18:35:01 +00:00
function update_check_requirements () {
// Check the system module and update.php requirements only.
$requirements = module_invoke ( 'system' , 'requirements' , 'update' );
$requirements += update_extra_requirements ();
$severity = drupal_requirements_severity ( $requirements );
// If there are issues, report them.
if ( $severity == REQUIREMENT_ERROR ) {
update_task_list ( 'requirements' );
drupal_set_title ( 'Requirements problem' );
$status_report = theme ( 'status_report' , $requirements );
$status_report .= 'Please check the error messages and <a href="' . request_uri () . '">try again</a>.' ;
print theme ( 'update_page' , $status_report );
exit ();
2009-03-01 09:32:17 +00:00
}
2008-01-16 10:37:43 +00:00
}
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 );
2009-05-09 18:35:01 +00:00
// We prepare a minimal bootstrap for the update requirements check to avoid
// reaching the PHP memory limit.
2008-09-20 20:22:25 +00:00
require_once DRUPAL_ROOT . '/includes/bootstrap.inc' ;
2009-07-29 05:59:59 +00:00
require_once DRUPAL_ROOT . '/includes/update.inc' ;
2009-05-09 18:35:01 +00:00
update_prepare_d7_bootstrap ();
2008-01-16 10:37:43 +00:00
2009-05-09 18:35:01 +00:00
// Determine if the current user has access to run update.php.
drupal_bootstrap ( DRUPAL_BOOTSTRAP_SESSION );
$update_access_allowed = ! empty ( $update_free_access ) || $user -> uid == 1 ;
2008-01-16 10:37:43 +00:00
2009-05-09 18:35:01 +00:00
// Only allow the requirements check to proceed if the current user has access
// to run updates (since it may expose sensitive information about the site's
// configuration).
$op = isset ( $_REQUEST [ 'op' ]) ? $_REQUEST [ 'op' ] : '' ;
if ( empty ( $op ) && $update_access_allowed ) {
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' ;
2009-08-24 00:14:23 +00:00
module_list ( TRUE , FALSE , 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.
2009-07-14 10:22:17 +00:00
drupal_language_initialize ();
2008-01-16 10:37:43 +00:00
// Set up theme system for the maintenance page.
drupal_maintenance_theme ();
// Check the update requirements for Drupal.
2009-05-09 18:35:01 +00:00
update_check_requirements ();
2009-03-01 09:32:17 +00:00
2009-05-09 18:35:01 +00:00
// Redirect to the update information page if all requirements were met.
2008-01-16 10:37:43 +00:00
install_goto ( 'update.php?op=info' );
}
2006-03-28 09:29:23 +00:00
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 );
2009-05-09 18:35:01 +00:00
// Only proceed with updates if the user is allowed to run them.
if ( $update_access_allowed ) {
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
2009-05-09 18:35:01 +00:00
update_fix_d7_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' )) {
2009-08-03 19:37:38 +00:00
update_batch ( $_POST [ 'start' ], $base_url . '/update.php?op=results' , $base_url . '/update.php' );
2009-01-21 14:47:12 +00:00
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
}