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 * Tries to optimize the constraints as much as possible, meaning
* reducing/collapsing congruent constraints etc. * reducing/collapsing congruent constraints etc.
* Does not necessarily return a MultiConstraint instance if * 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 ConstraintInterface[] $constraints A set of constraints
* @param bool $conjunctive Whether the constraints should be treated as conjunctive or disjunctive * @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\Installer\PackageEvents;
use Composer\IO\IOInterface; use Composer\IO\IOInterface;
use Composer\Plugin\PluginInterface; 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 Phabel\Composer\Repository\Repository;
use ReflectionClass;
use ReflectionObject; use ReflectionObject;
/** /**
@ -44,37 +39,35 @@ class Plugin implements PluginInterface, EventSubscriberInterface
$reflect->setAccessible(true); $reflect->setAccessible(true);
$reflect->setValue($repoManager, []); $reflect->setValue($repoManager, []);
foreach ($repos as $repo) { foreach ($repos as $repo) {
if ($repo instanceof ComposerComposerRepository) { $traits = [Repository::class];
$repo = new ComposerRepository($repo); $traitsStr = '';
} else { foreach ($traits as $trait) {
$traits = []; $traitsStr .= "use \\$trait;\n";
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;
};
}
} }
$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); $repoManager->prependRepository($repo);
} }
\var_dump(\array_map('get_class', $repoManager->getRepositories())); \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\Package;
use Composer\Package\PackageInterface; use Composer\Package\PackageInterface;
use Composer\Repository\PlatformRepository; use Composer\Repository\PlatformRepository;
use Composer\Repository\RepositoryInterface;
use Composer\Semver\Constraint\Constraint as ConstraintConstraint;
use Composer\Semver\Constraint\ConstraintInterface; use Composer\Semver\Constraint\ConstraintInterface;
use Composer\Semver\Constraint\MultiConstraint as ConstraintMultiConstraint; use Composer\Semver\Constraint\MultiConstraint as ConstraintMultiConstraint;
use Phabel\Composer\Constraint\Constraint; use Phabel\Composer\Constraint\Constraint;
use Phabel\Composer\Constraint\MultiConstraint; use Phabel\Composer\Constraint\MultiConstraint;
use ReflectionObject;
/** /**
* @author Daniil Gentili <daniil@daniil.it> * @author Daniil Gentili <daniil@daniil.it>
@ -22,34 +19,23 @@ use ReflectionObject;
trait Repository trait Repository
{ {
/** /**
* Previous repository . * TODO v3 should make this private once we can drop PHP 5.3 support.
*/
protected RepositoryInterface $repository;
/**
* Reflection object.
*/
protected ReflectionObject $reflect;
/**
* Constructor.
* *
* @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); self::prepareConstraint($constraint);
$this->repository = $repository; return parent::isVersionAcceptable($constraint, $name, $versionData, $acceptableStabilities, $stabilityFlags);
$this->packages = [];
} }
/** public function loadPackages(array $packageNameMap, array $acceptableStabilities, array $stabilityFlags, array $alreadyLoaded = [])
* Checks if specified package registered (installed).
*
* @param PackageInterface $package package instance
*
* @return bool
*/
public function hasPackage(PackageInterface $package): bool
{ {
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(); $constraint = $constraint->getPrevious();
return $config; return $config;
} }
return [];
/* /*
if (!$constraint instanceof ConstraintInterface && !\is_string($constraint)) { if (!$constraint instanceof ConstraintInterface && !\is_string($constraint)) {
return []; return [];
@ -142,7 +129,7 @@ trait Repository
public function findPackage($name, $constraint) public function findPackage($name, $constraint)
{ {
$config = self::prepareConstraint($constraint); $config = self::prepareConstraint($constraint);
if (!$package = $this->repository->findPackage($name, $constraint)) { if (!$package = parent::findPackage($name, $constraint)) {
return null; return null;
} }
return self::preparePackage($package, $config); return self::preparePackage($package, $config);
@ -159,7 +146,7 @@ trait Repository
public function findPackages($name, $constraint = null) public function findPackages($name, $constraint = null)
{ {
$config = self::prepareConstraint($constraint); $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); self::preparePackage($package, $config);
} }
return $packages; return $packages;
@ -172,23 +159,10 @@ trait Repository
*/ */
public function getPackages() public function getPackages()
{ {
$packages = $this->repository->getPackages(); $packages = parent::getPackages();
foreach ($packages as $package) { foreach ($packages as $package) {
self::preparePackage($package, []); self::preparePackage($package, []);
} }
return $packages; 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 * @return NameContext
*/ */

View File

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

View File

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