diff --git a/src/Composer/Repository/ArrayRepository.php b/src/Composer/Repository/ArrayRepository.php index 5f9eaf406..a78ee8f2f 100644 --- a/src/Composer/Repository/ArrayRepository.php +++ b/src/Composer/Repository/ArrayRepository.php @@ -24,7 +24,7 @@ use Composer\Semver\Constraint\Constraint; * * @author Nils Adermann */ -class ArrayRepository implements RepositoryInterface +class ArrayRepository extends BaseRepository { /** @var PackageInterface[] */ protected $packages; diff --git a/src/Composer/Repository/BaseRepository.php b/src/Composer/Repository/BaseRepository.php new file mode 100644 index 000000000..c28ffa791 --- /dev/null +++ b/src/Composer/Repository/BaseRepository.php @@ -0,0 +1,66 @@ + + * Jordi Boggiano + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Composer\Repository; + +use Composer\Package\RootPackageInterface; +use Composer\Semver\Constraint\ConstraintInterface; + +/** + * Common ancestor class for generic repository functionality. + * + * @author Niels Keurentjes + */ +abstract class BaseRepository implements RepositoryInterface +{ + /** + * Returns a list of links causing the requested needle packages to be installed, as an associative array with the + * dependent's name as key, and an array containing in order the PackageInterface and Link describing the relationship + * as values. If recursive lookup was requested a third value is returned containing an identically formed array up + * to the root package. + * + * @param string|string[] $needle The package name(s) to inspect. + * @param ConstraintInterface|null $constraint Optional constraint to filter by. + * @param bool $invert Whether to invert matches to discover reasons for the package *NOT* to be installed. + * @param bool $recurse Whether to recursively expand the requirement tree up to the root package. + * @return array An associative array of arrays as described above. + */ + private function getDependents($needle, $constraint = null, $invert = false, $recurse = true) + { + $needles = is_array($needle) ? $needle : array($needle); + $results = array(); + + // Loop over all currently installed packages. + foreach ($this->getPackages() as $package) { + // Requirements and replaces are both considered valid reasons for a package to be installed + $links = $package->getRequires() + $package->getReplaces(); + + // Require-dev is only relevant for the root package + if ($package instanceof RootPackageInterface) { + $links += $package->getDevRequires(); + } + + // Cross-reference all discovered links to the needles + foreach ($links as $link) { + foreach ($needles as $needle) { + if ($link->getTarget() === $needle) { + if (is_null($constraint) || (($link->getConstraint()->matches($constraint) === !$invert))) { + $results[$link->getSource()] = array($package, $link, $recurse ? $this->getDependents($link->getSource(), null, false, true) : array()); + } + } + } + } + } + ksort($results); + return $results; + } +} diff --git a/src/Composer/Repository/CompositeRepository.php b/src/Composer/Repository/CompositeRepository.php index 7f29385bf..a9342a5d1 100644 --- a/src/Composer/Repository/CompositeRepository.php +++ b/src/Composer/Repository/CompositeRepository.php @@ -19,7 +19,7 @@ use Composer\Package\PackageInterface; * * @author Beau Simensen */ -class CompositeRepository implements RepositoryInterface +class CompositeRepository extends BaseRepository { /** * List of repositories