UpdateManager.php in Lightning Core 8.5        
                          
                  
                        
  
  
  
  
File
  src/UpdateManager.php
  
    View source  
  <?php
namespace Drupal\lightning_core;
use Drupal\Component\Plugin\Discovery\DiscoveryInterface;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\DependencyInjection\ClassResolverInterface;
use Drupal\Core\Extension\ModuleExtensionList;
use Drupal\Core\Plugin\Discovery\AnnotatedClassDiscovery;
use Drupal\lightning_core\Annotation\Update;
use phpDocumentor\Reflection\DocBlockFactory;
use phpDocumentor\Reflection\DocBlockFactoryInterface;
use Symfony\Component\Console\Style\StyleInterface;
class UpdateManager {
  
  const CONFIG_NAME = 'lightning_core.versions';
  
  const VERSION_UNKNOWN = '0.0.0';
  
  protected $discovery;
  
  protected $classResolver;
  
  protected $configFactory;
  
  protected $moduleExtensionList;
  
  protected $docBlockFactory;
  
  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();
  }
  
  public function getVersion($module) {
    $info = $this->moduleExtensionList
      ->getAllAvailableInfo();
    if (isset($info[$module]['version'])) {
      return static::toSemanticVersion($info[$module]['version']);
    }
    else {
      
      $updates = $this
        ->getDefinitions($module);
      return $updates ? end($updates)['id'] : static::VERSION_UNKNOWN;
    }
  }
  
  public static function toSemanticVersion($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);
    }
  }
  
  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;
  }
  
  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);
  }
  
  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($method);
        if ($doc_block
          ->hasTag('update')) {
          (yield new UpdateTask($handler, $method, $doc_block));
        }
      }
    }
  }
  
  public function executeAllInConsole(StyleInterface $style) {
    $updates = $this
      ->getAvailable();
    if (count($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']);
      
      foreach ($this
        ->getTasks($handler) as $task) {
        $task
          ->execute($style);
      }
      $versions
        ->set($provider, $update['id'])
        ->save();
    }
  }
}