Skip to content
Snippets Groups Projects
automatic_updates.module 7.59 KiB
Newer Older
  • Learn to ignore specific revisions
  •  * Contains hook implementations for Automatic Updates.
    
    use Drupal\Core\Routing\RouteMatchInterface;
    
    use Drupal\automatic_updates\Validation\AdminReadinessMessages;
    use Drupal\Core\Form\FormStateInterface;
    
    use Drupal\system\Controller\DbUpdateController;
    
    /**
     * Implements hook_help().
     */
    function automatic_updates_help($route_name, RouteMatchInterface $route_match) {
      switch ($route_name) {
        case 'help.page.auto_updates':
          $output = '<h3>' . t('About') . '</h3>';
          $output .= '<p>' . t('Automatic Updates lets you update Drupal core.') . '</p>';
    
          $output .= '<p>';
          $output .= t('Automatic Updates will keep Drupal secure and up-to-date by automatically installing new patch-level updates, if available, when cron runs. It also provides a user interface to check if any updates are available and install them. You can <a href=":configure-form">configure Automatic Updates</a> to install all patch-level updates, only security updates, or no updates at all, during cron. By default, only security updates are installed during cron; this requires that you <a href=":update-form">install non-security updates through the user interface</a>.', [
            ':configure-form' => Url::fromRoute('update.settings')->toString(),
            ':update-form' => Url::fromRoute('automatic_updates.report_update')->toString(),
          ]);
          $output .= '</p>';
    
    Ted Bowman's avatar
    Ted Bowman committed
          $output .= '<p>' . t('Additionally, Automatic Updates periodically runs checks to ensure that updates can be installed, and will warn site administrators if problems are detected.') . '</p>';
    
          $output .= '<h3>' . t('Requirements') . '</h3>';
          $output .= '<p>' . t('Automatic Updates requires Composer @version or later available as an executable, and PHP must have permission to run it. The path to the executable may be set in the <code>package_manager.settings:executables.composer</code> config setting, or it will be automatically detected.', ['@version' => ComposerExecutableValidator::MINIMUM_COMPOSER_VERSION]) . '</p>';
    
          $output .= '<p>' . t('For more information, see the <a href=":automatic-updates-documentation">online documentation for the Automatic Updates module</a>.', [':automatic-updates-documentation' => 'https://www.drupal.org/docs/8/update/automatic-updates']) . '</p>';
          return $output;
      }
    }
    
    
    function automatic_updates_page_top() {
      /** @var \Drupal\automatic_updates\Validation\AdminReadinessMessages $readiness_messages */
      $readiness_messages = \Drupal::classResolver(AdminReadinessMessages::class);
      $readiness_messages->displayAdminPageMessages();
    
    
      // @todo Rely on the route option after https://www.drupal.org/i/3236497 is
      //   committed.
      // @todo Remove 'system.batch_page.html' after
      //   https://www.drupal.org/i/3238311 is committed.
      $skip_routes = [
        'system.batch_page.html',
        'automatic_updates.confirmation_page',
        'automatic_updates.report_update',
        'automatic_updates.module_update',
      ];
    
      // @see auto_updates_module_implements_alter()
    
      $route_name = \Drupal::routeMatch()->getRouteName();
      if (!in_array($route_name, $skip_routes, TRUE) && function_exists('update_page_top')) {
        update_page_top();
      }
    }
    
    /**
     * Implements hook_module_implements_alter().
     *
     * @todo Remove after https://www.drupal.org/i/3236497 is committed.
     */
    function automatic_updates_module_implements_alter(&$implementations, $hook) {
      if ($hook === 'page_top') {
        // Remove hook_page_top() implementation from the Update module. This '
        // implementation displays error messages about security releases. We call
        // this implementation in our own automatic_updates_page_top() except on our
    
        // own routes to avoid these messages while an update is in progress.
    
        unset($implementations['update']);
      }
    
    }
    
    /**
     * Implements hook_cron().
     */
    function automatic_updates_cron() {
    
      \Drupal::service('automatic_updates.cron_updater')->handleCron();
    
      /** @var \Drupal\automatic_updates\Validation\ReadinessValidationManager $checker_manager */
      $checker_manager = \Drupal::service('automatic_updates.readiness_validation_manager');
      $last_results = $checker_manager->getResults();
      $last_run_time = $checker_manager->getLastRunTime();
      // Do not run readiness checks more than once an hour unless there are no
      // results available.
      if ($last_results === NULL || !$last_run_time || \Drupal::time()->getRequestTime() - $last_run_time > 3600) {
        $checker_manager->run();
    
     * Implements hook_modules_installed().
    
    function automatic_updates_modules_installed() {
      // Run the readiness checkers if needed when any modules are installed in
      // case they provide readiness checker services.
      /** @var \Drupal\automatic_updates\Validation\ReadinessValidationManager $checker_manager */
      $checker_manager = \Drupal::service('automatic_updates.readiness_validation_manager');
    
     * Implements hook_modules_uninstalled().
    
    function automatic_updates_modules_uninstalled() {
      // Run the readiness checkers if needed when any modules are uninstalled in
      // case they provided readiness checker services.
      /** @var \Drupal\automatic_updates\Validation\ReadinessValidationManager $checker_manager */
      $checker_manager = \Drupal::service('automatic_updates.readiness_validation_manager');
    
     * Implements hook_form_FORM_ID_alter() for 'update_manager_update_form'.
    
    function automatic_updates_form_update_manager_update_form_alter(&$form, FormStateInterface $form_state, $form_id) {
      // Remove current message that core updates are not supported with a link to
    
      // use this module's form. The local task to 'update_manager_update_form' is
      // replaced by our own from but this original form would still accessible via
      // by its original URL.
    
      if (isset($form['manual_updates']['#rows']['drupal']['data']['title'])) {
    
        $current_route = \Drupal::routeMatch()->getRouteName();
        if ($current_route === 'update.module_update') {
          $redirect_route = 'automatic_updates.module_update';
        }
        elseif ($current_route === 'update.report_update') {
          $redirect_route = 'automatic_updates.report_update';
        }
        if (!empty($redirect_route)) {
          $core_updates_message = t(
            '<h2>Core updates required</h2>Drupal core updates are supported by the enabled <a href="@url">Automatic Updates module</a>',
            ['@url' => Url::fromRoute($redirect_route)->toString()]
          );
          $form['manual_updates']['#prefix'] = $core_updates_message;
        }
    
    
    /**
     * Implements hook_local_tasks_alter().
     */
    function automatic_updates_local_tasks_alter(array &$local_tasks) {
      // The Update module's update form only allows updating modules and themes
      // via archive files, which could produce unexpected results on a site using
      // our Composer-based updater.
      $new_routes = [
        'update.report_update' => 'automatic_updates.report_update',
        'update.module_update' => 'automatic_updates.module_update',
        'update.theme_update' => 'automatic_updates.theme_update',
      ];
      foreach ($new_routes as $local_task_id => $new_route) {
        if (!empty($local_tasks[$local_task_id])) {
          $local_tasks[$local_task_id]['route_name'] = $new_route;
        }
      }
    }
    
    
    /**
     * Implements hook_batch_alter().
     *
     * @todo Remove this in https://www.drupal.org/i/3267817.
     */
    function automatic_updates_batch_alter(array &$batch): void {
      foreach ($batch['sets'] as &$batch_set) {
        if (!empty($batch_set['finished']) && $batch_set['finished'] === [DbUpdateController::class, 'batchFinished']) {
          $batch_set['finished'] = [BatchProcessor::class, 'dbUpdateBatchFinished'];
        }
      }
    }