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();
}
}
}