You are here

class UpdateManager in Drupal 8

Same name and namespace in other branches
  1. 9 core/modules/update/src/UpdateManager.php \Drupal\update\UpdateManager

Default implementation of UpdateManagerInterface.

Hierarchy

Expanded class hierarchy of UpdateManager

1 string reference to 'UpdateManager'
update.services.yml in core/modules/update/update.services.yml
core/modules/update/update.services.yml
1 service uses UpdateManager
update.manager in core/modules/update/update.services.yml
Drupal\update\UpdateManager

File

core/modules/update/src/UpdateManager.php, line 18

Namespace

Drupal\update
View source
class UpdateManager implements UpdateManagerInterface {
  use DependencySerializationTrait;
  use StringTranslationTrait;

  /**
   * The update settings
   *
   * @var \Drupal\Core\Config\Config
   */
  protected $updateSettings;

  /**
   * Module Handler Service.
   *
   * @var \Drupal\Core\Extension\ModuleHandlerInterface
   */
  protected $moduleHandler;

  /**
   * Update Processor Service.
   *
   * @var \Drupal\update\UpdateProcessorInterface
   */
  protected $updateProcessor;

  /**
   * An array of installed and enabled projects.
   *
   * @var array
   */
  protected $projects;

  /**
   * The key/value store.
   *
   * @var \Drupal\Core\KeyValueStore\KeyValueStoreExpirableInterface
   */
  protected $keyValueStore;

  /**
   * Update available releases key/value store.
   *
   * @var \Drupal\Core\KeyValueStore\KeyValueStoreExpirableInterface
   */
  protected $availableReleasesTempStore;

  /**
   * The theme handler.
   *
   * @var \Drupal\Core\Extension\ThemeHandlerInterface
   */
  protected $themeHandler;

  /**
   * The module extension list.
   *
   * @var \Drupal\Core\Extension\ModuleExtensionList
   */
  protected $moduleExtensionList;

  /**
   * Constructs a UpdateManager.
   *
   * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
   *   The config factory.
   * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
   *   The Module Handler service
   * @param \Drupal\update\UpdateProcessorInterface $update_processor
   *   The Update Processor service.
   * @param \Drupal\Core\StringTranslation\TranslationInterface $translation
   *   The translation service.
   * @param \Drupal\Core\KeyValueStore\KeyValueFactoryInterface $key_value_expirable_factory
   *   The expirable key/value factory.
   * @param \Drupal\Core\Extension\ThemeHandlerInterface $theme_handler
   *   The theme handler.
   * @param \Drupal\Core\Extension\ModuleExtensionList|null $extension_list_module
   *   The module extension list. This is left optional for BC reasons, but the
   *   optional usage is deprecated and will become required in Drupal 9.0.0.
   */
  public function __construct(ConfigFactoryInterface $config_factory, ModuleHandlerInterface $module_handler, UpdateProcessorInterface $update_processor, TranslationInterface $translation, KeyValueFactoryInterface $key_value_expirable_factory, ThemeHandlerInterface $theme_handler, ModuleExtensionList $extension_list_module = NULL) {
    $this->updateSettings = $config_factory
      ->get('update.settings');
    $this->moduleHandler = $module_handler;
    $this->updateProcessor = $update_processor;
    $this->stringTranslation = $translation;
    $this->keyValueStore = $key_value_expirable_factory
      ->get('update');
    $this->themeHandler = $theme_handler;
    $this->availableReleasesTempStore = $key_value_expirable_factory
      ->get('update_available_releases');
    $this->projects = [];
    if ($extension_list_module === NULL) {
      @trigger_error('Invoking the UpdateManager constructor without the module extension list parameter is deprecated in Drupal 8.8.0 and will no longer be supported in Drupal 9.0.0. The extension list parameter is now required in the ConfigImporter constructor. See https://www.drupal.org/node/2943918', E_USER_DEPRECATED);
      $extension_list_module = \Drupal::service('extension.list.module');
    }
    $this->moduleExtensionList = $extension_list_module;
  }

  /**
   * {@inheritdoc}
   */
  public function refreshUpdateData() {

    // Since we're fetching new available update data, we want to clear
    // of both the projects we care about, and the current update status of the
    // site. We do *not* want to clear the cache of available releases just yet,
    // since that data (even if it's stale) can be useful during
    // \Drupal\update\UpdateManager::getProjects(); for example, to modules
    // that implement hook_system_info_alter() such as cvs_deploy.
    $this->keyValueStore
      ->delete('update_project_projects');
    $this->keyValueStore
      ->delete('update_project_data');
    $projects = $this
      ->getProjects();

    // Now that we have the list of projects, we should also clear the available
    // release data, since even if we fail to fetch new data, we need to clear
    // out the stale data at this point.
    $this->availableReleasesTempStore
      ->deleteAll();
    foreach ($projects as $project) {
      $this->updateProcessor
        ->createFetchTask($project);
    }
  }

  /**
   * {@inheritdoc}
   */
  public function getProjects() {
    if (empty($this->projects)) {

      // Retrieve the projects from storage, if present.
      $this->projects = $this
        ->projectStorage('update_project_projects');
      if (empty($this->projects)) {

        // Still empty, so we have to rebuild.
        $module_data = $this->moduleExtensionList
          ->reset()
          ->getList();
        $theme_data = $this->themeHandler
          ->rebuildThemeData();
        $project_info = new ProjectInfo();
        $project_info
          ->processInfoList($this->projects, $module_data, 'module', TRUE);
        $project_info
          ->processInfoList($this->projects, $theme_data, 'theme', TRUE);
        if ($this->updateSettings
          ->get('check.disabled_extensions')) {
          $project_info
            ->processInfoList($this->projects, $module_data, 'module', FALSE);
          $project_info
            ->processInfoList($this->projects, $theme_data, 'theme', FALSE);
        }

        // Allow other modules to alter projects before fetching and comparing.
        $this->moduleHandler
          ->alter('update_projects', $this->projects);

        // Store the site's project data for at most 1 hour.
        $this->keyValueStore
          ->setWithExpire('update_project_projects', $this->projects, 3600);
      }
    }
    return $this->projects;
  }

  /**
   * {@inheritdoc}
   */
  public function projectStorage($key) {
    $projects = [];

    // On certain paths, we should clear the data and recompute the projects for
    // update status of the site to avoid presenting stale information.
    $route_names = [
      'update.theme_update',
      'system.modules_list',
      'system.theme_install',
      'update.module_update',
      'update.module_install',
      'update.status',
      'update.report_update',
      'update.report_install',
      'update.settings',
      'system.status',
      'update.manual_status',
      'update.confirmation_page',
      'system.themes_page',
    ];
    if (in_array(\Drupal::routeMatch()
      ->getRouteName(), $route_names)) {
      $this->keyValueStore
        ->delete($key);
    }
    else {
      $projects = $this->keyValueStore
        ->get($key, []);
    }
    return $projects;
  }

  /**
   * {@inheritdoc}
   */
  public function fetchDataBatch(&$context) {
    if (empty($context['sandbox']['max'])) {
      $context['finished'] = 0;
      $context['sandbox']['max'] = $this->updateProcessor
        ->numberOfQueueItems();
      $context['sandbox']['progress'] = 0;
      $context['message'] = $this
        ->t('Checking available update data ...');
      $context['results']['updated'] = 0;
      $context['results']['failures'] = 0;
      $context['results']['processed'] = 0;
    }

    // Grab another item from the fetch queue.
    for ($i = 0; $i < 5; $i++) {
      if ($item = $this->updateProcessor
        ->claimQueueItem()) {
        if ($this->updateProcessor
          ->processFetchTask($item->data)) {
          $context['results']['updated']++;
          $context['message'] = $this
            ->t('Checked available update data for %title.', [
            '%title' => $item->data['info']['name'],
          ]);
        }
        else {
          $context['message'] = $this
            ->t('Failed to check available update data for %title.', [
            '%title' => $item->data['info']['name'],
          ]);
          $context['results']['failures']++;
        }
        $context['sandbox']['progress']++;
        $context['results']['processed']++;
        $context['finished'] = $context['sandbox']['progress'] / $context['sandbox']['max'];
        $this->updateProcessor
          ->deleteQueueItem($item);
      }
      else {

        // If the queue is currently empty, we're done. It's possible that
        // another thread might have added new fetch tasks while we were
        // processing this batch. In that case, the usual 'finished' math could
        // get confused, since we'd end up processing more tasks that we thought
        // we had when we started and initialized 'max' with numberOfItems(). By
        // forcing 'finished' to be exactly 1 here, we ensure that batch
        // processing is terminated.
        $context['finished'] = 1;
        return;
      }
    }
  }

}

Members

Namesort descending Modifiers Type Description Overrides
DependencySerializationTrait::$_entityStorages protected property An array of entity type IDs keyed by the property name of their storages.
DependencySerializationTrait::$_serviceIds protected property An array of service IDs keyed by property name used for serialization.
DependencySerializationTrait::__sleep public function 1
DependencySerializationTrait::__wakeup public function 2
StringTranslationTrait::$stringTranslation protected property The string translation service. 1
StringTranslationTrait::formatPlural protected function Formats a string containing a count of items.
StringTranslationTrait::getNumberOfPlurals protected function Returns the number of plurals supported by a given language.
StringTranslationTrait::getStringTranslation protected function Gets the string translation service.
StringTranslationTrait::setStringTranslation public function Sets the string translation service to use. 2
StringTranslationTrait::t protected function Translates a string to the current language or to a given language.
UpdateManager::$availableReleasesTempStore protected property Update available releases key/value store.
UpdateManager::$keyValueStore protected property The key/value store.
UpdateManager::$moduleExtensionList protected property The module extension list.
UpdateManager::$moduleHandler protected property Module Handler Service.
UpdateManager::$projects protected property An array of installed and enabled projects.
UpdateManager::$themeHandler protected property The theme handler.
UpdateManager::$updateProcessor protected property Update Processor Service.
UpdateManager::$updateSettings protected property The update settings
UpdateManager::fetchDataBatch public function Processes a step in batch for fetching available update data. Overrides UpdateManagerInterface::fetchDataBatch
UpdateManager::getProjects public function Fetches an array of installed and enabled projects. Overrides UpdateManagerInterface::getProjects
UpdateManager::projectStorage public function Retrieves update storage data or empties it. Overrides UpdateManagerInterface::projectStorage
UpdateManager::refreshUpdateData public function Clears out all the available update data and initiates re-fetching. Overrides UpdateManagerInterface::refreshUpdateData
UpdateManager::__construct public function Constructs a UpdateManager.
UpdateManagerInterface::CURRENT constant Project is up to date.
UpdateManagerInterface::NOT_CURRENT constant Project has a new release available, but it is not a security release.
UpdateManagerInterface::NOT_SECURE constant Project is missing security update(s).
UpdateManagerInterface::NOT_SUPPORTED constant Current release is no longer supported by the project maintainer.
UpdateManagerInterface::REVOKED constant Current release has been unpublished and is no longer available.