Skip to content

Commit

Permalink
Merge pull request #34 from mediact/issue/33-proposal-fix
Browse files Browse the repository at this point in the history
1.0.8 Issue/33 proposal fix
  • Loading branch information
ashokadewit authored Dec 10, 2018
2 parents 678f111 + 303ca1b commit 49ab1be
Show file tree
Hide file tree
Showing 9 changed files with 4,984 additions and 7 deletions.
5 changes: 3 additions & 2 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,11 @@
"minimum-stability": "stable",
"require": {
"php": "^7.1",
"composer/composer": "^1.6",
"composer-plugin-api": "^1.1",
"composer/composer": "^1.6",
"nikic/php-parser": "^3.0 | ^4.0",
"roave/better-reflection": "^2.0 | ^3.1"
"roave/better-reflection": "^2.0 | ^3.1",
"symfony/options-resolver": "^4.1"
},
"require-dev": {
"symfony/process": "@stable",
Expand Down
85 changes: 85 additions & 0 deletions src/Composer/Repository/DependentsResolver.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
<?php
/**
* Copyright MediaCT. All rights reserved.
* https://www.mediact.nl
*/

namespace Mediact\DependencyGuard\Composer\Repository;

use Composer\Repository\CompositeRepository;
use Composer\Repository\RepositoryInterface;

class DependentsResolver implements DependentsResolverInterface
{
/** @var CompositeRepository */
private $repository;

/**
* Constructor.
*
* @param RepositoryInterface $repository
*/
public function __construct(RepositoryInterface $repository)
{
$this->repository = new CompositeRepository([$repository]);
}

/**
* Resolves the dependents of the package.
*
* @param string $packageName
*
* @return array
*/
public function resolve(string $packageName): array
{
return $this->getDependents(
$packageName,
false,
[]
);
}

/**
* Retrieves the dependents of a package in a recursive way.
*
* @param string $packageName
* @param bool $returnContext
* @param array $context
*
* @return array
*/
private function getDependents(
string $packageName,
bool $returnContext,
array $context = []
): array {
if (!isset($context[$packageName])) {
$context[$packageName] = $this->repository->getDependents(
$packageName,
null,
false,
false
);

foreach ($context[$packageName] as $key => $dependent) {
$dependentContext = $this->getDependents($key, true, $context);
$context = array_merge(
$context,
$dependentContext
);

$context[$packageName] = array_merge(
$context[$packageName],
$dependentContext[$key]
);
}
}

if (!$returnContext) {
return $context[$packageName];
}

return $context;
}
}
19 changes: 19 additions & 0 deletions src/Composer/Repository/DependentsResolverInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?php
/**
* Copyright MediaCT. All rights reserved.
* https://www.mediact.nl
*/

namespace Mediact\DependencyGuard\Composer\Repository;

interface DependentsResolverInterface
{
/**
* Resolve dependents for a package.
*
* @param string $package
*
* @return array
*/
public function resolve(string $package): array;
}
13 changes: 8 additions & 5 deletions src/Violation/Filter/DependencyFilter.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@

namespace Mediact\DependencyGuard\Violation\Filter;

use Composer\Composer;
use Composer\Package\PackageInterface;
use Composer\Repository\CompositeRepository;
use Composer\Repository\RepositoryInterface;
use Mediact\DependencyGuard\Candidate\Candidate;
use Mediact\DependencyGuard\Composer\Repository\DependentsResolver;
use Mediact\DependencyGuard\Violation\Violation;
use Mediact\DependencyGuard\Violation\ViolationInterface;

Expand All @@ -22,6 +22,9 @@ class DependencyFilter implements ViolationFilterInterface
/** @var CompositeRepository */
private $repository;

/** @var DependentsResolver */
private $dependentsResolver;

/**
* Constructor.
*
Expand All @@ -32,8 +35,9 @@ public function __construct(
RepositoryInterface $repository,
ViolationFilterInterface $filter
) {
$this->filter = $filter;
$this->repository = new CompositeRepository([$repository]);
$this->filter = $filter;
$this->repository = new CompositeRepository([$repository]);
$this->dependentsResolver = new DependentsResolver($repository);
}

/**
Expand All @@ -52,7 +56,6 @@ function (
) use ($violation): ViolationInterface {
/** @var PackageInterface $package */
[$package] = $dependent;

return new Violation(
sprintf(
'Package "%s" provides violating package "%s".',
Expand All @@ -65,7 +68,7 @@ function (
)
);
},
$this->repository->getDependents(
$this->dependentsResolver->resolve(
$violation->getPackage()->getName()
)
),
Expand Down
226 changes: 226 additions & 0 deletions tests/Composer/Repository/DependentResolverTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,226 @@
<?php
/**
* Copyright MediaCT. All rights reserved.
* https://www.mediact.nl
*/

namespace Mediact\DependencyGuard\Tests\Composer\Repository;

use Composer\Repository\CompositeRepository;
use Composer\Repository\RepositoryInterface;
use Mediact\DependencyGuard\Composer\Repository\DependentsResolver;
use PHPUnit\Framework\TestCase;
use Composer\Package\Link;
use Composer\Package\PackageInterface;
use PHPUnit\Framework\MockObject\MockObject;

/**
* @coversDefaultClass \Mediact\DependencyGuard\Composer\Repository\DependentsResolver
*/
class DependentResolverTest extends TestCase
{
/**
* @return void
*
* @covers ::__construct
*/
public function testConstruct(): void
{
$this->assertInstanceOf(
DependentsResolver::class,
new DependentsResolver(
$this->createMock(RepositoryInterface::class)
)
);
}

/**
* @dataProvider repositoryProvider
*
* @param RepositoryInterface $repository
* @param string $packageName
* @param array $expected
*
* @return void
*
* @covers ::resolve
* @covers ::getDependents
*/
public function testResolve(
RepositoryInterface $repository,
string $packageName,
array $expected
): void {
$subject = new DependentsResolver($repository);
$this->assertEquals(
$expected,
array_keys($subject->resolve($packageName))
);
}

/**
* @dataProvider repositoryProvider
*
* @param RepositoryInterface $repository
* @param string $packageName
*
* @return void
*
* @covers ::getDependents
*/
public function testEqualBehaviour(
RepositoryInterface $repository,
string $packageName
): void {
$subject = new DependentsResolver($repository);
$legacy = new CompositeRepository([$repository]);
$this->assertEquals(
$legacy->getDependents($packageName),
$subject->resolve($packageName)
);
}

/**
* @param PackageInterface ...$packages
*
* @return RepositoryInterface
*/
private function createRepository(
PackageInterface ...$packages
): RepositoryInterface {
/** @var RepositoryInterface|MockObject $repository */
$repository = $this->createMock(RepositoryInterface::class);

$repository
->expects(self::any())
->method('getPackages')
->willReturn($packages);

return $repository;
}

/**
* @param string $name
* @param string ...$requires
*
* @return PackageInterface
*/
private function createPackage(
string $name,
string ...$requires
): PackageInterface {
/** @var PackageInterface|MockObject $package */
$package = $this->createMock(PackageInterface::class);

$package
->expects(self::any())
->method('getName')
->willReturn($name);

$package
->expects(self::any())
->method('getRequires')
->willReturn(
array_map(
function (string $target) use ($name): Link {
return $this->createLink($name, $target);
},
$requires
)
);

$package
->expects(self::any())
->method(
self::matchesRegularExpression(
'/^get(DevRequires|Replaces|Conflicts)$/'
)
)
->willReturn([]);

return $package;
}

/**
* @param string $source
* @param string $target
*
* @return Link
*/
private function createLink(string $source, string $target): Link
{
/** @var Link|MockObject $link */
$link = $this->createMock(Link::class);

$link
->expects(self::any())
->method('getSource')
->willReturn($source);

$link
->expects(self::any())
->method('getTarget')
->willReturn($target);

return $link;
}

/**
* @return array
*/
public function repositoryProvider(): array
{
return [
[
$this->createRepository(),
'foo/foo',
[]
],
[
$this->createRepository(
$this->createPackage('bar/bar')
),
'foo/foo',
[]
],
[
$this->createRepository(
$this->createPackage(
'bar/bar',
'foo/foo'
)
),
'foo/foo',
['bar/bar']
],
[
$this->createRepository(
$this->createPackage(
'bar/bar'
)
),
'foo/foo',
[]
],
[
$this->createRepository(
$this->createPackage(
'bar/bar',
'foo/foo',
'baz/baz'
),
$this->createPackage(
'baz/baz',
'qux/qux'
),
$this->createPackage(
'quz/quz',
'foo/foo'
)
),
'foo/foo',
['bar/bar', 'quz/quz']
]
];
}
}
Loading

0 comments on commit 49ab1be

Please sign in to comment.