Viewing file: UpdateHelper.php (10.14 KB) -rw-rw-r-- Select action/file-type: (+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
<?php
namespace UpdateHelper;
use Composer\Composer; use Composer\EventDispatcher\Event; use Composer\Installer\PackageEvent; use Composer\IO\IOInterface; use Composer\Json\JsonFile; use Composer\Script\Event as ScriptEvent; use Composer\Semver\Semver; use Exception; use InvalidArgumentException; use RuntimeException; use Throwable;
class UpdateHelper { /** @var Event */ private $event; /** @var IOInterface|null */ private $io; /** @var Composer */ private $composer; /** @var array */ private $dependencies = array(); /** @var string */ private $composerFilePath; /** @var JsonFile */ private $file;
protected static function appendConfig(&$classes, $directory, $key = null) { $file = $directory.DIRECTORY_SEPARATOR.'composer.json'; $json = new JsonFile($file); $key = $key ? $key : 'update-helper';
try { $dependencyConfig = $json->read(); } catch (Exception $e) { $dependencyConfig = null; }
if (is_array($dependencyConfig) && isset($dependencyConfig['extra'], $dependencyConfig['extra'][$key])) { $classes[$file] = $dependencyConfig['extra'][$key]; } }
protected static function getUpdateHelperConfig(Composer $composer, $key = null) { $vendorDir = $composer->getConfig()->get('vendor-dir');
$npm = array();
foreach (scandir($vendorDir) as $namespace) { if ($namespace === '.' || $namespace === '..' || !is_dir($directory = $vendorDir.DIRECTORY_SEPARATOR.$namespace)) { continue; }
foreach (scandir($directory) as $dependency) { if ($dependency === '.' || $dependency === '..' || !is_dir($subDirectory = $directory.DIRECTORY_SEPARATOR.$dependency)) { continue; }
static::appendConfig($npm, $subDirectory, $key); } }
static::appendConfig($npm, dirname($vendorDir), $key);
return $npm; }
/** * @param Event $event * @param IOInterface $io * @param Composer $composer * @param string[] $subClasses */ protected static function checkHelper($event, IOInterface $io, $composer, $class) { if (!is_string($class) || !class_exists($class)) { throw new NotUpdateInterfaceInstanceException(); }
try { $helper = new $class(); } catch (Exception $e) { throw new InvalidArgumentException($e->getMessage(), 1000, $e); } catch (Throwable $e) { throw new InvalidArgumentException($e->getMessage(), 1000, $e); }
if (!($helper instanceof UpdateHelperInterface)) { throw new NotUpdateInterfaceInstanceException(); }
$helper->check(new static($event, $io, $composer)); }
/** * @param string $file * @param Event $event * @param IOInterface $io * @param Composer $composer * @param string[] $subClasses */ protected static function checkFileHelpers($file, $event, IOInterface $io, $composer, array $subClasses) { foreach ($subClasses as $class) { try { static::checkHelper($event, $io, $composer, $class); } catch (InvalidArgumentException $exception) { $io->writeError(static::getErrorMessage($exception, $file, $class)); continue; } } }
protected static function getErrorMessage(InvalidArgumentException $exception, $file, $class) { if ($exception instanceof NotUpdateInterfaceInstanceException) { return 'UpdateHelper error in '.$file.":\n".JsonFile::encode($class).' is not an instance of UpdateHelperInterface.'; }
return 'UpdateHelper error: '.$exception->getPrevious()->getMessage(). "\nFile: ".$exception->getPrevious()->getFile(). "\nLine:".$exception->getPrevious()->getLine(). "\n\n".$exception->getPrevious()->getTraceAsString(); }
public static function check(Event $event) { if (!($event instanceof ScriptEvent) && !($event instanceof PackageEvent)) { return; }
$io = $event->getIO(); $composer = $event->getComposer(); $autoload = $composer->getConfig()->get('vendor-dir').'/autoload.php';
if (file_exists($autoload)) { include_once $autoload; }
$classes = static::getUpdateHelperConfig($composer);
foreach ($classes as $file => $subClasses) { static::checkFileHelpers($file, $event, $io, $composer, (array) $subClasses); } }
public function __construct(Event $event, IOInterface $io = null, Composer $composer = null) { $this->event = $event; $this->io = $io ?: (method_exists($event, 'getIO') ? $event->getIO() : null); $this->composer = $composer ?: (method_exists($event, 'getComposer') ? $event->getComposer() : null);
if ($this->composer && ($directory = $this->composer->getConfig()->get('archive-dir')) && file_exists($file = $directory.'/composer.json') ) { $this->composerFilePath = $file; $this->file = new JsonFile($this->composerFilePath); $this->dependencies = $this->file->read(); } }
/** * @return JsonFile */ public function getFile() { return $this->file; }
/** * @return string */ public function getComposerFilePath() { return $this->composerFilePath; }
/** * @return Composer */ public function getComposer() { return $this->composer; }
/** * @return Event */ public function getEvent() { return $this->event; }
/** * @return IOInterface|null */ public function getIo() { return $this->io; }
/** * @return array */ public function getDependencies() { return $this->dependencies; }
/** * @return array */ public function getDevDependencies() { return isset($this->dependencies['require-dev']) ? $this->dependencies['require-dev'] : array(); }
/** * @return array */ public function getProdDependencies() { return isset($this->dependencies['require']) ? $this->dependencies['require'] : array(); }
/** * @return array */ public function getFlattenDependencies() { return array_merge($this->getDevDependencies(), $this->getProdDependencies()); }
/** * @param string $dependency * * @return bool */ public function hasAsDevDependency($dependency) { return isset($this->dependencies['require-dev'][$dependency]); }
/** * @param string $dependency * * @return bool */ public function hasAsProdDependency($dependency) { return isset($this->dependencies['require'][$dependency]); }
/** * @param string $dependency * * @return bool */ public function hasAsDependency($dependency) { return $this->hasAsDevDependency($dependency) || $this->hasAsProdDependency($dependency); }
/** * @param string $dependency * @param string $version * * @return bool */ public function isDependencyAtLeast($dependency, $version) { if ($this->hasAsProdDependency($dependency)) { return Semver::satisfies($version, $this->dependencies['require'][$dependency]); }
if ($this->hasAsDevDependency($dependency)) { return Semver::satisfies($version, $this->dependencies['require-dev'][$dependency]); }
return false; }
/** * @param string $dependency * @param string $version * * @return bool */ public function isDependencyLesserThan($dependency, $version) { return !$this->isDependencyAtLeast($dependency, $version); }
/** * @param string $dependency * @param string $version * @param array $environments * * @throws Exception * * @return $this */ public function setDependencyVersion($dependency, $version, $environments = array('require', 'require-dev')) { return $this->setDependencyVersions(array($dependency => $version), $environments); }
/** * @param array $dependencies * @param array $environments * * @throws Exception * * @return $this */ public function setDependencyVersions($dependencies, $environments = array('require', 'require-dev')) { if (!$this->composerFilePath) { throw new RuntimeException('No composer instance detected.'); }
$touched = false;
foreach ($environments as $environment) { foreach ($dependencies as $dependency => $version) { if (isset($this->dependencies[$environment], $this->dependencies[$environment][$dependency])) { $this->dependencies[$environment][$dependency] = $version; $touched = true; } } }
if ($touched) { if (!$this->composerFilePath) { throw new RuntimeException('composer.json not found (custom vendor-dir are not yet supported).'); }
$file = new JsonFile($this->composerFilePath); $file->write($this->dependencies); }
return $this; }
/** * @return $this */ public function update() { $output = shell_exec('composer update --no-scripts');
if (!empty($output)) { $this->write($output); }
return $this; }
/** * @param string|array $text */ public function write($text) { if ($this->io) { $this->io->write($text);
return; }
if (is_array($text)) { $text = implode("\n", $text); }
echo $text; }
/** * @return bool */ public function isInteractive() { return $this->io && $this->io->isInteractive(); } }
|