| Drupal | PHP Cross Reference | Content Management Systems |
1 <?php 2 3 /** 4 * @file 5 * Callbacks and related functions invoked by authorize.php to update projects. 6 * 7 * We use the Batch API to actually update each individual project on the site. 8 * All of the code in this file is run at a low bootstrap level (modules are not 9 * loaded), so these functions cannot assume access to the rest of the code of 10 * the Update Manager module. 11 */ 12 13 /** 14 * Updates existing projects when invoked by authorize.php. 15 * 16 * Callback for system_authorized_init() in 17 * update_manager_update_ready_form_submit(). 18 * 19 * @param $filetransfer 20 * The FileTransfer object created by authorize.php for use during this 21 * operation. 22 * @param $projects 23 * A nested array of projects to install into the live webroot, keyed by 24 * project name. Each subarray contains the following keys: 25 * - project: The canonical project short name. 26 * - updater_name: The name of the Updater class to use for this project. 27 * - local_url: The locally installed location of new code to update with. 28 */ 29 function update_authorize_run_update($filetransfer, $projects) { 30 $operations = array(); 31 foreach ($projects as $project => $project_info) { 32 $operations[] = array( 33 'update_authorize_batch_copy_project', 34 array( 35 $project_info['project'], 36 $project_info['updater_name'], 37 $project_info['local_url'], 38 $filetransfer, 39 ), 40 ); 41 } 42 43 $batch = array( 44 'title' => t('Installing updates'), 45 'init_message' => t('Preparing to update your site'), 46 'operations' => $operations, 47 'finished' => 'update_authorize_update_batch_finished', 48 'file' => drupal_get_path('module', 'update') . '/update.authorize.inc', 49 ); 50 51 batch_set($batch); 52 // Invoke the batch via authorize.php. 53 system_authorized_batch_process(); 54 } 55 56 /** 57 * Installs a new project when invoked by authorize.php. 58 * 59 * Callback for system_authorized_init() in 60 * update_manager_install_form_submit(). 61 * 62 * @param FileTransfer $filetransfer 63 * The FileTransfer object created by authorize.php for use during this 64 * operation. 65 * @param string $project 66 * The canonical project short name (e.g., {system}.name). 67 * @param string $updater_name 68 * The name of the Updater class to use for installing this project. 69 * @param string $local_url 70 * The URL to the locally installed temp directory where the project has 71 * already been downloaded and extracted into. 72 */ 73 function update_authorize_run_install($filetransfer, $project, $updater_name, $local_url) { 74 $operations[] = array( 75 'update_authorize_batch_copy_project', 76 array( 77 $project, 78 $updater_name, 79 $local_url, 80 $filetransfer, 81 ), 82 ); 83 84 // @todo Instantiate our Updater to set the human-readable title? 85 $batch = array( 86 'title' => t('Installing %project', array('%project' => $project)), 87 'init_message' => t('Preparing to install'), 88 'operations' => $operations, 89 // @todo Use a different finished callback for different messages? 90 'finished' => 'update_authorize_install_batch_finished', 91 'file' => drupal_get_path('module', 'update') . '/update.authorize.inc', 92 ); 93 batch_set($batch); 94 95 // Invoke the batch via authorize.php. 96 system_authorized_batch_process(); 97 } 98 99 /** 100 * Batch callback: Copies project to its proper place when authorized to do so. 101 * 102 * @param string $project 103 * The canonical short name of the project being installed. 104 * @param string $updater_name 105 * The name of the Updater class to use for installing this project. 106 * @param string $local_url 107 * The URL to the locally installed temp directory where the project has 108 * already been downloaded and extracted into. 109 * @param FileTransfer $filetransfer 110 * The FileTransfer object to use for performing this operation. 111 * @param array $context 112 * Reference to an array used for Batch API storage. 113 */ 114 function update_authorize_batch_copy_project($project, $updater_name, $local_url, $filetransfer, &$context) { 115 116 // Initialize some variables in the Batch API $context array. 117 if (!isset($context['results']['log'])) { 118 $context['results']['log'] = array(); 119 } 120 if (!isset($context['results']['log'][$project])) { 121 $context['results']['log'][$project] = array(); 122 } 123 124 if (!isset($context['results']['tasks'])) { 125 $context['results']['tasks'] = array(); 126 } 127 128 // The batch API uses a session, and since all the arguments are serialized 129 // and unserialized between requests, although the FileTransfer object itself 130 // will be reconstructed, the connection pointer itself will be lost. However, 131 // the FileTransfer object will still have the connection variable, even 132 // though the connection itself is now gone. So, although it's ugly, we have 133 // to unset the connection variable at this point so that the FileTransfer 134 // object will re-initiate the actual connection. 135 unset($filetransfer->connection); 136 137 if (!empty($context['results']['log'][$project]['#abort'])) { 138 $context['finished'] = 1; 139 return; 140 } 141 142 $updater = new $updater_name($local_url); 143 144 try { 145 if ($updater->isInstalled()) { 146 // This is an update. 147 $tasks = $updater->update($filetransfer); 148 } 149 else { 150 $tasks = $updater->install($filetransfer); 151 } 152 } 153 catch (UpdaterException $e) { 154 _update_batch_create_message($context['results']['log'][$project], t('Error installing / updating'), FALSE); 155 _update_batch_create_message($context['results']['log'][$project], $e->getMessage(), FALSE); 156 $context['results']['log'][$project]['#abort'] = TRUE; 157 return; 158 } 159 160 _update_batch_create_message($context['results']['log'][$project], t('Installed %project_name successfully', array('%project_name' => $project))); 161 if (!empty($tasks)) { 162 $context['results']['tasks'] += $tasks; 163 } 164 165 // This particular operation is now complete, even though the batch might 166 // have other operations to perform. 167 $context['finished'] = 1; 168 } 169 170 /** 171 * Batch callback: Performs actions when the authorized update batch is done. 172 * 173 * This processes the results and stashes them into SESSION such that 174 * authorize.php will render a report. Also responsible for putting the site 175 * back online and clearing the update status cache after a successful update. 176 * 177 * @param $success 178 * TRUE if the batch operation was successful; FALSE if there were errors. 179 * @param $results 180 * An associative array of results from the batch operation. 181 */ 182 function update_authorize_update_batch_finished($success, $results) { 183 foreach ($results['log'] as $project => $messages) { 184 if (!empty($messages['#abort'])) { 185 $success = FALSE; 186 } 187 } 188 $offline = variable_get('maintenance_mode', FALSE); 189 if ($success) { 190 // Now that the update completed, we need to clear the cache of available 191 // update data and recompute our status, so prevent show bogus results. 192 _update_authorize_clear_update_status(); 193 194 // Take the site out of maintenance mode if it was previously that way. 195 if ($offline && isset($_SESSION['maintenance_mode']) && $_SESSION['maintenance_mode'] == FALSE) { 196 variable_set('maintenance_mode', FALSE); 197 $page_message = array( 198 'message' => t('Update was completed successfully. Your site has been taken out of maintenance mode.'), 199 'type' => 'status', 200 ); 201 } 202 else { 203 $page_message = array( 204 'message' => t('Update was completed successfully.'), 205 'type' => 'status', 206 ); 207 } 208 } 209 elseif (!$offline) { 210 $page_message = array( 211 'message' => t('Update failed! See the log below for more information.'), 212 'type' => 'error', 213 ); 214 } 215 else { 216 $page_message = array( 217 'message' => t('Update failed! See the log below for more information. Your site is still in maintenance mode.'), 218 'type' => 'error', 219 ); 220 } 221 // Since we're doing an update of existing code, always add a task for 222 // running update.php. 223 $results['tasks'][] = t('Your modules have been downloaded and updated.'); 224 $results['tasks'][] = t('<a href="@update">Run database updates</a>', array('@update' => base_path() . 'update.php')); 225 226 // Unset the variable since it is no longer needed. 227 unset($_SESSION['maintenance_mode']); 228 229 // Set all these values into the SESSION so authorize.php can display them. 230 $_SESSION['authorize_results']['success'] = $success; 231 $_SESSION['authorize_results']['page_message'] = $page_message; 232 $_SESSION['authorize_results']['messages'] = $results['log']; 233 $_SESSION['authorize_results']['tasks'] = $results['tasks']; 234 $_SESSION['authorize_operation']['page_title'] = t('Update manager'); 235 } 236 237 /** 238 * Batch callback: Performs actions when the authorized install batch is done. 239 * 240 * This processes the results and stashes them into SESSION such that 241 * authorize.php will render a report. Also responsible for putting the site 242 * back online after a successful install if necessary. 243 * 244 * @param $success 245 * TRUE if the batch operation was a success; FALSE if there were errors. 246 * @param $results 247 * An associative array of results from the batch operation. 248 */ 249 function update_authorize_install_batch_finished($success, $results) { 250 foreach ($results['log'] as $project => $messages) { 251 if (!empty($messages['#abort'])) { 252 $success = FALSE; 253 } 254 } 255 $offline = variable_get('maintenance_mode', FALSE); 256 if ($success) { 257 // Take the site out of maintenance mode if it was previously that way. 258 if ($offline && isset($_SESSION['maintenance_mode']) && $_SESSION['maintenance_mode'] == FALSE) { 259 variable_set('maintenance_mode', FALSE); 260 $page_message = array( 261 'message' => t('Installation was completed successfully. Your site has been taken out of maintenance mode.'), 262 'type' => 'status', 263 ); 264 } 265 else { 266 $page_message = array( 267 'message' => t('Installation was completed successfully.'), 268 'type' => 'status', 269 ); 270 } 271 } 272 elseif (!$success && !$offline) { 273 $page_message = array( 274 'message' => t('Installation failed! See the log below for more information.'), 275 'type' => 'error', 276 ); 277 } 278 else { 279 $page_message = array( 280 'message' => t('Installation failed! See the log below for more information. Your site is still in maintenance mode.'), 281 'type' => 'error', 282 ); 283 } 284 285 // Unset the variable since it is no longer needed. 286 unset($_SESSION['maintenance_mode']); 287 288 // Set all these values into the SESSION so authorize.php can display them. 289 $_SESSION['authorize_results']['success'] = $success; 290 $_SESSION['authorize_results']['page_message'] = $page_message; 291 $_SESSION['authorize_results']['messages'] = $results['log']; 292 $_SESSION['authorize_results']['tasks'] = $results['tasks']; 293 $_SESSION['authorize_operation']['page_title'] = t('Update manager'); 294 } 295 296 /** 297 * Creates a structure of log messages. 298 * 299 * @param array $project_results 300 * An associative array of results from the batch operation. 301 * @param string $message 302 * A string containing a log message. 303 * @param bool $success 304 * (optional) TRUE if the operation the message is about was a success, FALSE 305 * if there were errors. Defaults to TRUE. 306 */ 307 function _update_batch_create_message(&$project_results, $message, $success = TRUE) { 308 $project_results[] = array('message' => $message, 'success' => $success); 309 } 310 311 /** 312 * Clears cached available update status data. 313 * 314 * Since this function is run at such a low bootstrap level, the Update Manager 315 * module is not loaded. So, we can't just call _update_cache_clear(). However, 316 * the database is bootstrapped, so we can do a query ourselves to clear out 317 * what we want to clear. 318 * 319 * Note that we do not want to just truncate the table, since that would remove 320 * items related to currently pending fetch attempts. 321 * 322 * @see update_authorize_update_batch_finished() 323 * @see _update_cache_clear() 324 */ 325 function _update_authorize_clear_update_status() { 326 $query = db_delete('cache_update'); 327 $query->condition( 328 db_or() 329 ->condition('cid', 'update_project_%', 'LIKE') 330 ->condition('cid', 'available_releases::%', 'LIKE') 331 ); 332 $query->execute(); 333 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
title