You are here

class UpdateManager in Lightning Core 8.3

Same name and namespace in other branches
  1. 8.5 src/UpdateManager.php \Drupal\lightning_core\UpdateManager
  2. 8 src/UpdateManager.php \Drupal\lightning_core\UpdateManager
  3. 8.2 src/UpdateManager.php \Drupal\lightning_core\UpdateManager
  4. 8.4 src/UpdateManager.php \Drupal\lightning_core\UpdateManager

Hierarchy

Expanded class hierarchy of UpdateManager

11 files declare their use of UpdateManager
HooksTest.php in tests/src/Kernel/HooksTest.php
LightningCoreCommands.php in src/Commands/LightningCoreCommands.php
lightning_core.install in ./lightning_core.install
Contains install and update routines for Lightning.
lightning_core.module in ./lightning_core.module
Contains core functionality for the Lightning distribution.
ModuleInstallTest.php in tests/src/Kernel/ModuleInstallTest.php

... See full list

1 string reference to 'UpdateManager'
lightning_core.services.yml in ./lightning_core.services.yml
lightning_core.services.yml
1 service uses UpdateManager
lightning.update_manager in ./lightning_core.services.yml
\Drupal\lightning_core\UpdateManager

File

src/UpdateManager.php, line 15

Namespace

Drupal\lightning_core
View source
class UpdateManager {

  /**
   * Name of the config object which stores version numbers.
   *
   * @var string
   */
  const CONFIG_NAME = 'lightning_core.versions';

  /**
   * Fallback version number used when a module does not declare it.
   *
   * @var string
   */
  const VERSION_UNKNOWN = '0.0.0';

  /**
   * The update discovery object.
   *
   * @var \Drupal\Component\Plugin\Discovery\DiscoveryInterface
   */
  protected $discovery;

  /**
   * The class resolver service.
   *
   * @var \Drupal\Core\DependencyInjection\ClassResolverInterface
   */
  protected $classResolver;

  /**
   * The config factory service.
   *
   * @var \Drupal\Core\Config\ConfigFactoryInterface
   */
  protected $configFactory;

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

  /**
   * The doc block factory.
   *
   * @var \phpDocumentor\Reflection\DocBlockFactoryInterface
   */
  protected $docBlockFactory;

  /**
   * UpdateCommand constructor.
   *
   * @param \Traversable $namespaces
   *   The namespaces to scan for updates.
   * @param \Drupal\Core\DependencyInjection\ClassResolverInterface $class_resolver
   *   The class resolver service.
   * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
   *   The config factory service.
   * @param \Drupal\Core\Extension\ModuleExtensionList
   *   The module extension list.
   * @param \Drupal\Component\Plugin\Discovery\DiscoveryInterface $discovery
   *   (optional) The update discovery handler.
   * @param \phpDocumentor\Reflection\DocBlockFactoryInterface $doc_block_factory
   *   (optional) The doc block factory.
   */
  public function __construct(\Traversable $namespaces, ClassResolverInterface $class_resolver, ConfigFactoryInterface $config_factory, ModuleExtensionList $module_extension_list, DiscoveryInterface $discovery = NULL, DocBlockFactoryInterface $doc_block_factory = NULL) {
    $this->classResolver = $class_resolver;
    $this->configFactory = $config_factory;
    $this->moduleExtensionList = $module_extension_list;
    $this->discovery = $discovery ?: new AnnotatedClassDiscovery('Update', $namespaces, Update::class);
    $this->docBlockFactory = $doc_block_factory ?: DocBlockFactory::createInstance();
  }

  /**
   * Tries to determine the semantic version of a module.
   *
   * @param string $module
   *   The machine name of the module.
   *
   * @return string
   *   The semantic version of the module, or static::VERSION_UNKNOWN if it
   *   could not be determined.
   */
  public function getVersion($module) {
    $info = $this->moduleExtensionList
      ->getAllAvailableInfo();
    if (isset($info[$module]['version'])) {
      return static::toSemanticVersion($info[$module]['version']);
    }
    else {

      // Follow core's model and try to determine the target version of the
      // most recent update.
      $updates = $this
        ->getDefinitions($module);
      return $updates ? end($updates)['id'] : static::VERSION_UNKNOWN;
    }
  }

  /**
   * Converts a drupal.org version number to a semantic version.
   *
   * @param string $version
   *   The drupal.org version number, e.g. 8.x-1.12.
   *
   * @return string
   *   The version number in semantic version format.
   */
  public static function toSemanticVersion($version) {

    // Strip the 8.x prefix from the version.
    $semantic_version = preg_replace('/^' . \Drupal::CORE_COMPATIBILITY . '-/', NULL, $version);
    if (preg_match('/-dev$/', $semantic_version)) {
      return preg_replace('/^(\\d).+-dev$/', '$1.x-dev', $semantic_version);
    }
    else {
      return preg_replace('/^(\\d+\\.\\d+)(-.+)?$/', '$1.0$2', $semantic_version);
    }
  }

  /**
   * Returns all update definitions, optionally filtered by provider module.
   *
   * @param string $module
   *   (optional) The machine name of the module by which to filter updates.
   *
   * @return array[]
   *   The discovered update definitions.
   */
  public function getDefinitions($module = NULL) {
    $definitions = $this->discovery
      ->getDefinitions();
    ksort($definitions);
    if ($module) {
      $filter = function (array $definition) use ($module) {
        return $definition['provider'] === $module;
      };
      $definitions = array_filter($definitions, $filter);
    }
    return $definitions;
  }

  /**
   * Returns all available update definitions.
   *
   * @return array[]
   *   The available update definitions.
   */
  public function getAvailable() {
    $versions = $this->configFactory
      ->getEditable(static::CONFIG_NAME);
    $filter = function (array $definition) use ($versions) {
      $provider_version = $versions
        ->get($definition['provider']) ?: static::VERSION_UNKNOWN;
      return version_compare($definition['id'], $provider_version, '>');
    };
    return array_filter($this
      ->getDefinitions(), $filter);
  }

  /**
   * Returns all available tasks for a specific update.
   *
   * @param object $handler
   *   The task handler.
   *
   * @return \Generator
   *   An iterable of UpdateTask objects.
   */
  protected function getTasks($handler) {
    $methods = (new \ReflectionObject($handler))
      ->getMethods(\ReflectionMethod::IS_PUBLIC);
    foreach ($methods as $method) {
      $doc_comment = trim($method
        ->getDocComment());
      if ($doc_comment) {
        $doc_block = $this->docBlockFactory
          ->create($doc_comment);
        if ($doc_block
          ->hasTag('update')) {
          (yield new UpdateTask($handler, $method, $doc_block));
        }
      }
    }
  }

  /**
   * Executes all available updates in a console context.
   *
   * @param \Symfony\Component\Console\Style\StyleInterface $style
   *   The I/O style.
   */
  public function executeAllInConsole(StyleInterface $style) {
    $updates = $this
      ->getAvailable();
    if (sizeof($updates) === 0) {
      return $style
        ->text('There are no updates available.');
    }
    $style
      ->text("Executing all available updates...");
    $provider = NULL;
    $versions = $this->configFactory
      ->getEditable(static::CONFIG_NAME);
    foreach ($updates as $update) {
      if ($update['provider'] != $provider) {
        $provider = $update['provider'];
        $style
          ->text($provider . ' ' . $update['id']);
      }
      $handler = $this->classResolver
        ->getInstanceFromDefinition($update['class']);

      /** @var \Drupal\lightning_core\UpdateTask $task */
      foreach ($this
        ->getTasks($handler) as $task) {
        $task
          ->execute($style);
      }
      $versions
        ->set($provider, $update['id'])
        ->save();
    }
  }

}

Members

Namesort descending Modifiers Type Description Overrides
UpdateManager::$classResolver protected property The class resolver service.
UpdateManager::$configFactory protected property The config factory service.
UpdateManager::$discovery protected property The update discovery object.
UpdateManager::$docBlockFactory protected property The doc block factory.
UpdateManager::$moduleExtensionList protected property The module extension list.
UpdateManager::CONFIG_NAME constant Name of the config object which stores version numbers.
UpdateManager::executeAllInConsole public function Executes all available updates in a console context.
UpdateManager::getAvailable public function Returns all available update definitions.
UpdateManager::getDefinitions public function Returns all update definitions, optionally filtered by provider module.
UpdateManager::getTasks protected function Returns all available tasks for a specific update. 1
UpdateManager::getVersion public function Tries to determine the semantic version of a module.
UpdateManager::toSemanticVersion public static function Converts a drupal.org version number to a semantic version.
UpdateManager::VERSION_UNKNOWN constant Fallback version number used when a module does not declare it.
UpdateManager::__construct public function UpdateCommand constructor.