Drupal PHP Cross Reference Content Management Systems

Source: /modules/update/update.authorize.inc - 333 lines - 12111 bytes - Summary - Text - Print

   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

title

Description

title

Description

title

title

Body