Improve composer API

This commit is contained in:
Daniil Gentili 2020-11-04 12:00:16 +01:00
parent e3409513c3
commit 6a3d3fec57
Signed by: danog
GPG Key ID: 8C1BE3B34B230CA7
10 changed files with 55 additions and 247 deletions

View File

@ -43,7 +43,7 @@ class MultiConstraint extends ComposerMultiConstraint
* Tries to optimize the constraints as much as possible, meaning
* reducing/collapsing congruent constraints etc.
* Does not necessarily return a MultiConstraint instance if
* things can be reduced to a simple constraint
* things can be reduced to a simple constraint.
*
* @param ConstraintInterface[] $constraints A set of constraints
* @param bool $conjunctive Whether the constraints should be treated as conjunctive or disjunctive

View File

@ -9,13 +9,8 @@ use Composer\Installer\PackageEvent;
use Composer\Installer\PackageEvents;
use Composer\IO\IOInterface;
use Composer\Plugin\PluginInterface;
use Composer\Repository\ArrayRepository as ComposerArrayRepository;
use Composer\Repository\ComposerRepository as ComposerComposerRepository;
use Composer\Repository\ConfigurableRepository as ComposerConfigurableRepository;
use Phabel\Composer\Repository\ArrayRepository;
use Phabel\Composer\Repository\ComposerRepository;
use Phabel\Composer\Repository\ConfigurableRepository;
use Phabel\Composer\Repository\Repository;
use ReflectionClass;
use ReflectionObject;
/**
@ -44,37 +39,35 @@ class Plugin implements PluginInterface, EventSubscriberInterface
$reflect->setAccessible(true);
$reflect->setValue($repoManager, []);
foreach ($repos as $repo) {
if ($repo instanceof ComposerComposerRepository) {
$repo = new ComposerRepository($repo);
} else {
$traits = [];
foreach ([
ComposerArrayRepository::class => ArrayRepository::class,
ComposerConfigurableRepository::class => ConfigurableRepository::class,
] as $class => $trait) {
if ($repo instanceof $class) {
$traits []= $trait;
}
}
\sort($traits);
if ($traits === [ArrayRepository::class]) {
$repo = new class($repo) extends ComposerArrayRepository {
use Repository;
use ArrayRepository;
};
} elseif ($traits === [ConfigurableRepository::class]) {
$repo = new class($repo) extends ComposerRepository {
use Repository;
use ConfigurableRepository;
};
} else {
$repo = new class($repo) extends ComposerArrayRepository {
use Repository;
use ArrayRepository;
use ConfigurableRepository;
};
}
$traits = [Repository::class];
$traitsStr = '';
foreach ($traits as $trait) {
$traitsStr .= "use \\$trait;\n";
}
$reflect = new ReflectionClass($repo);
$extend = "extends \\".\get_class($repo);
$eval = "\$newRepo = new class $extend {
$traitsStr
public function __construct() {}
};";
eval($eval);
$reflectNew = new ReflectionClass($newRepo);
$reflectNew = $reflectNew->getParentClass();
do {
foreach ($reflect->getProperties() as $prop) {
$propNew = $reflectNew->getProperty($prop->getName());
$propNew->setAccessible(true);
$prop->setAccessible(true);
$propNew->setValue($newRepo, $prop->getValue($repo));
}
$reflectNew = $reflectNew->getParentClass();
} while ($reflect = $reflect->getParentClass());
$repo = $newRepo;
$repoManager->prependRepository($repo);
}
\var_dump(\array_map('get_class', $repoManager->getRepositories()));

View File

@ -1,43 +0,0 @@
<?php
namespace Phabel\Composer\Repository;
use Composer\Package\Link;
use Composer\Package\Package;
use Composer\Package\PackageInterface;
use Composer\Repository\ComposerRepository;
use Composer\Repository\RepositoryInterface;
use Composer\Repository\ArrayRepository as ComposerArrayRepository;
use Composer\Semver\Constraint\Constraint;
use Composer\Semver\Constraint\ConstraintInterface;
/**
* @author Daniil Gentili <daniil@daniil.it>
* @license MIT
*
* @property ComposerArrayRepository $repository
*/
trait ArrayRepository
{
public function addPackage(PackageInterface $package)
{
$this->repository->addPackage($package);
}
public function getProviders($packageName)
{
return $this->repository->getProviders($packageName);
}
public function loadPackages(array $packageNameMap, array $acceptableStabilities, array $stabilityFlags, array $alreadyLoaded = array())
{
$packages = $this->repository->loadPackages($packageNameMap, $acceptableStabilities, $stabilityFlags, $alreadyLoaded);
foreach ($packages['packages'] as &$package) {
self::preparePackage($package, []);
}
return $packages;
}
public function getPackageNames($packageFilter = null)
{
return $this->getPackageNames($packageFilter);
}
}

View File

@ -1,85 +0,0 @@
<?php
namespace Phabel\Composer\Repository;
use Composer\DependencyResolver\Pool;
use Composer\Package\PackageInterface;
use Composer\Repository\ComposerRepository as ComposerComposerRepository;
use Composer\Repository\RepositoryInterface;
use ReflectionObject;
/**
* @author Daniil Gentili <daniil@daniil.it>
* @license MIT
*
* @property ComposerComposerRepository $repository
*/
class ComposerRepository extends ComposerComposerRepository
{
use Repository;
use ArrayRepository;
use ConfigurableRepository;
/**
* Configuration prefix.
*/
const CONFIG_PREFIX = 'phabel-config';
/**
* @param Pool $pool
* @param string $name package name
* @param bool $bypassFilters If set to true, this bypasses the stability filtering, and forces a recompute without cache
* @return array|mixed
*/
/*
public function whatProvides(Pool $pool, $name, $bypassFilters = false)
{
$whatProvides = $this->reflect->getMethod('whatProvides')->invokeArgs($this->repository, [$pool, $name, $bypassFilters]);
foreach ($whatProvides as $package => &$versions) {
foreach ($versions as &$version) {
if (!isset($version['require']['phabel/phabel'])) {
continue;
}
$config = $version['extra']['phabel'] ?? [];
if (!isset($config['target']) && isset($version['require']['php'])) {
$config['target'] = $version['require']['php'];
}
foreach ($version['require'] as $package => &$version) {
$version = self::CONFIG_PREFIX.\json_encode($config)."\n".$version;
}
}
}
return $whatProvides;
}*/
public function getProviderNames()
{
return $this->repository->getProviderNames();
}
public function hasProviders()
{
return $this->repository->hasProviders();
}
public function resetPackageIds()
{
return $this->repository->resetPackageIds();
}
public function createPackages(array $packages, $class = 'Composer\Package\CompletePackage')
{
return $this->repository->createPackages($packages, $class);
}
/**
* TODO v3 should make this private once we can drop PHP 5.3 support
*
* @param string $name package name (must be lowercased already)
* @private
*/
public function isVersionAcceptable($constraint, $name, $versionData, array $acceptableStabilities = null, array $stabilityFlags = null)
{
self::prepareConstraint($constraint);
return $this->isVersionAcceptable($constraint, $name, $versionData, $acceptableStabilities, $stabilityFlags);
}
}

View File

@ -1,31 +0,0 @@
<?php
namespace Phabel\Composer\Repository;
use Composer\Package\Link;
use Composer\Package\Package;
use Composer\Package\PackageInterface;
use Composer\Repository\ComposerRepository;
use Composer\Repository\RepositoryInterface;
use Composer\Repository\ConfigurableRepositoryInterface;
use Composer\Semver\Constraint\Constraint;
use Composer\Semver\Constraint\ConstraintInterface;
/**
* @author Daniil Gentili <daniil@daniil.it>
* @license MIT
*
* @property ConfigurableRepositoryInterface $repository
*/
trait ConfigurableRepository
{
/**
* Get repository configuration.
*
* @return mixed
*/
public function getRepoConfig()
{
return $this->repository->getRepoConfig();
}
}

View File

@ -7,13 +7,10 @@ use Composer\Package\Link;
use Composer\Package\Package;
use Composer\Package\PackageInterface;
use Composer\Repository\PlatformRepository;
use Composer\Repository\RepositoryInterface;
use Composer\Semver\Constraint\Constraint as ConstraintConstraint;
use Composer\Semver\Constraint\ConstraintInterface;
use Composer\Semver\Constraint\MultiConstraint as ConstraintMultiConstraint;
use Phabel\Composer\Constraint\Constraint;
use Phabel\Composer\Constraint\MultiConstraint;
use ReflectionObject;
/**
* @author Daniil Gentili <daniil@daniil.it>
@ -22,34 +19,23 @@ use ReflectionObject;
trait Repository
{
/**
* Previous repository .
*/
protected RepositoryInterface $repository;
/**
* Reflection object.
*/
protected ReflectionObject $reflect;
/**
* Constructor.
* TODO v3 should make this private once we can drop PHP 5.3 support.
*
* @param RepositoryInterface $repository Previous repository
* @param string $name package name (must be lowercased already)
* @private
*/
public function __construct(RepositoryInterface $repository)
public function isVersionAcceptable($constraint, $name, $versionData, array $acceptableStabilities = null, array $stabilityFlags = null)
{
$this->reflect = new ReflectionObject($repository);
$this->repository = $repository;
$this->packages = [];
self::prepareConstraint($constraint);
return parent::isVersionAcceptable($constraint, $name, $versionData, $acceptableStabilities, $stabilityFlags);
}
/**
* Checks if specified package registered (installed).
*
* @param PackageInterface $package package instance
*
* @return bool
*/
public function hasPackage(PackageInterface $package): bool
public function loadPackages(array $packageNameMap, array $acceptableStabilities, array $stabilityFlags, array $alreadyLoaded = [])
{
return $this->repository->hasPackage($package);
$packages = parent::loadPackages($packageNameMap, $acceptableStabilities, $stabilityFlags, $alreadyLoaded);
foreach ($packages['packages'] as &$package) {
self::preparePackage($package, []);
}
return $packages;
}
/**
@ -66,6 +52,7 @@ trait Repository
$constraint = $constraint->getPrevious();
return $config;
}
return [];
/*
if (!$constraint instanceof ConstraintInterface && !\is_string($constraint)) {
return [];
@ -142,7 +129,7 @@ trait Repository
public function findPackage($name, $constraint)
{
$config = self::prepareConstraint($constraint);
if (!$package = $this->repository->findPackage($name, $constraint)) {
if (!$package = parent::findPackage($name, $constraint)) {
return null;
}
return self::preparePackage($package, $config);
@ -159,7 +146,7 @@ trait Repository
public function findPackages($name, $constraint = null)
{
$config = self::prepareConstraint($constraint);
foreach ($packages = $this->repository->findPackages($name, $constraint) as $package) {
foreach ($packages = parent::findPackages($name, $constraint) as $package) {
self::preparePackage($package, $config);
}
return $packages;
@ -172,23 +159,10 @@ trait Repository
*/
public function getPackages()
{
$packages = $this->repository->getPackages();
$packages = parent::getPackages();
foreach ($packages as $package) {
self::preparePackage($package, []);
}
return $packages;
}
/**
* {@inheritDoc}
*/
public function search($query, $mode = 0, $type = null)
{
return $this->repository->search($query, $mode, $type);
}
public function getRepoName()
{
return $this->repository->getRepoName();
}
}

View File

@ -308,7 +308,7 @@ class Context
}
/**
* Gets name context
* Gets name context.
*
* @return NameContext
*/

View File

@ -62,7 +62,7 @@ class GraphInternal
* @param PackageContext $ctx Package context
*
* @psalm-param class-string<PluginInterface> $plugin Plugin to add
*
*
* @return Node[]
*/
public function addPlugin(string $plugin, array $config, PackageContext $ctx): array

View File

@ -3,7 +3,6 @@
namespace Phabel\Target;
use Phabel\Plugin;
use Phabel\Target\Php55\YieldDetector;
/**
* Makes changes necessary to polyfill syntaxes of various PHP versions.
@ -39,10 +38,10 @@ class Php extends Plugin
private static function getRange(array $config): array
{
$target = $config['target'] ?? PHP_MAJOR_VERSION.PHP_MINOR_VERSION;
if (preg_match(":^\D*(\d+\.\d+)\..*:", $config['target'], $matches)) {
if (\preg_match(":^\D*(\d+\.\d+)\..*:", $config['target'], $matches)) {
$target = $matches[1];
}
$key = \array_search(str_replace('.', '', $target), self::VERSIONS);
$key = \array_search(\str_replace('.', '', $target), self::VERSIONS);
return \array_slice(
self::VERSIONS,
$key === false ? self::DEFAULT_TARGET : $key
@ -59,9 +58,11 @@ class Php extends Plugin
{
$classes = [];
foreach (self::getRange($config) as $version) {
foreach (scandir(__DIR__."/Php$version") as $file) {
if (substr($file, -4) !== '.php') continue;
$class = basename($version, '.php');
foreach (\scandir(__DIR__."/Php$version") as $file) {
if (\substr($file, -4) !== '.php') {
continue;
}
$class = \basename($version, '.php');
$classes[$class] = $config[$class] ?? [];
}
}

View File

@ -3,7 +3,6 @@
namespace Phabel;
use PhpParser\Node;
use PhpParser\NodeTraverser;
use PhpParser\Parser;
use PhpParser\ParserFactory;
use SplQueue;