Skip to content

Commit

Permalink
Merge pull request #23 from IonBazan/feature/hyperlinks
Browse files Browse the repository at this point in the history
Add hyperlinks support
  • Loading branch information
IonBazan authored May 11, 2022
2 parents 87063f9 + 41537c3 commit 6ac141b
Show file tree
Hide file tree
Showing 14 changed files with 277 additions and 61 deletions.
8 changes: 5 additions & 3 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -54,19 +54,21 @@ jobs:
restore-keys: ${{ runner.os }}-composer-
- name: Install Composer dependencies
run: composer update -n --prefer-dist ${{ matrix.composer-flags }}
- name: Set default branch for tests
run: git config --global init.defaultBranch main
- name: Run Tests
run: vendor/bin/simple-phpunit --coverage-clover coverage.xml
run: vendor/bin/simple-phpunit --coverage-clover coverage.xml --coverage-text
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v1
- name: Run mutation tests
if: ${{ matrix.php-versions == 8.0 && matrix.operating-system == 'ubuntu-latest' }}
if: ${{ matrix.php-versions == 8.1 && matrix.operating-system == 'ubuntu-latest' }}
env:
STRYKER_DASHBOARD_API_KEY: ${{ secrets.STRYKER_DASHBOARD_API_KEY }}
run: |
composer req infection/infection -W
vendor/bin/infection --ignore-msi-with-no-mutations --min-covered-msi=100 --min-msi=100 -s -j4
- name: Run phpstan
if: ${{ matrix.php-versions == 8.0 && matrix.operating-system == 'ubuntu-latest' }}
if: ${{ matrix.php-versions == 8.1 && matrix.operating-system == 'ubuntu-latest' }}
run: |
composer req phpstan/phpstan
vendor/bin/phpstan
7 changes: 6 additions & 1 deletion infection.json.dist
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"logs": {
"text": "infection.log",
"stryker": {
"badge": "master"
"badge": "main"
}
},
"mutators": {
Expand All @@ -16,6 +16,11 @@
"ignore": [
"IonBazan\\ComposerDiff\\Formatter\\JsonFormatter::format"
]
},
"Ternary": {
"ignore": [
"IonBazan\\ComposerDiff\\Formatter\\AbstractFormatter::terminalLink"
]
}
}
}
19 changes: 19 additions & 0 deletions src/Diff/DiffEntry.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
use Composer\DependencyResolver\Operation\OperationInterface;
use Composer\DependencyResolver\Operation\UninstallOperation;
use Composer\DependencyResolver\Operation\UpdateOperation;
use Composer\Package\PackageInterface;

class DiffEntry
{
Expand Down Expand Up @@ -83,6 +84,24 @@ public function isChange()
return self::TYPE_CHANGE === $this->type;
}

/**
* @return PackageInterface|null
*/
public function getPackage()
{
$operation = $this->getOperation();

if ($operation instanceof UpdateOperation) {
return $operation->getInitialPackage();
}

if ($operation instanceof InstallOperation || $operation instanceof UninstallOperation) {
return $operation->getPackage();
}

return null;
}

/**
* @return string
*/
Expand Down
40 changes: 17 additions & 23 deletions src/Formatter/AbstractFormatter.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
use Composer\DependencyResolver\Operation\OperationInterface;
use Composer\DependencyResolver\Operation\UninstallOperation;
use Composer\DependencyResolver\Operation\UpdateOperation;
use Composer\Package\PackageInterface;
use IonBazan\ComposerDiff\Diff\DiffEntry;
use IonBazan\ComposerDiff\Url\GeneratorContainer;
use Symfony\Component\Console\Output\OutputInterface;
Expand Down Expand Up @@ -37,11 +36,11 @@ public function getUrl(DiffEntry $entry)
$operation = $entry->getOperation();

if ($operation instanceof UpdateOperation) {
return $this->getCompareUrl($operation->getInitialPackage(), $operation->getTargetPackage());
return $this->generators->getCompareUrl($operation->getInitialPackage(), $operation->getTargetPackage());
}

if ($operation instanceof InstallOperation || $operation instanceof UninstallOperation) {
return $this->getReleaseUrl($operation->getPackage());
return $this->generators->getReleaseUrl($operation->getPackage());
}

return null;
Expand All @@ -64,40 +63,35 @@ public function getProjectUrl(OperationInterface $operation)
return null;
}

$generator = $this->generators->get($package);

if (!$generator) {
return null;
}

return $generator->getProjectUrl($package);
return $this->generators->getProjectUrl($package);
}

/**
* @return string|null
* @return string
*/
private function getCompareUrl(PackageInterface $basePackage, PackageInterface $targetPackage)
protected function getDecoratedPackageName(DiffEntry $entry)
{
$generator = $this->generators->get($targetPackage);
$package = $entry->getPackage();

if (!$generator) {
return null;
if (null === $package) {
return '';
}

return $generator->getCompareUrl($basePackage, $targetPackage);
return $this->terminalLink($this->getProjectUrl($entry->getOperation()), $package->getName());
}

/**
* @return string|null
* @param string|null $url
* @param string $title
*
* @return string
*/
private function getReleaseUrl(PackageInterface $package)
private function terminalLink($url, $title)
{
$generator = $this->generators->get($package);

if (!$generator) {
return null;
if (null === $url) {
return $title;
}

return $generator->getReleaseUrl($package);
return method_exists('Symfony\Component\Console\Formatter\OutputFormatterStyle', 'setHref') ? sprintf('<href=%s>%s</>', $url, $title) : $title;
}
}
14 changes: 4 additions & 10 deletions src/Formatter/MarkdownTableFormatter.php
Original file line number Diff line number Diff line change
Expand Up @@ -60,10 +60,10 @@ public function renderSingle(DiffEntries $entries, $title, $withUrls)
private function getTableRow(DiffEntry $entry, $withUrls)
{
$operation = $entry->getOperation();
if ($operation instanceof InstallOperation) {
$packageName = $operation->getPackage()->getName();
$packageUrl = $withUrls ? $this->formatUrl($this->getProjectUrl($operation), $packageName) : $packageName;
$packageName = $this->getDecoratedPackageName($entry);
$packageUrl = $withUrls ? $this->formatUrl($this->getProjectUrl($operation), $packageName) : $packageName;

if ($operation instanceof InstallOperation) {
return array(
$packageUrl ?: $packageName,
'<fg=green>New</>',
Expand All @@ -73,21 +73,15 @@ private function getTableRow(DiffEntry $entry, $withUrls)
}

if ($operation instanceof UpdateOperation) {
$packageName = $operation->getInitialPackage()->getName();
$projectUrl = $withUrls ? $this->formatUrl($this->getProjectUrl($operation), $packageName) : $packageName;

return array(
$projectUrl ?: $packageName,
$packageUrl ?: $packageName,
$entry->isChange() ? '<fg=magenta>Changed</>' : ($entry->isUpgrade() ? '<fg=cyan>Upgraded</>' : '<fg=yellow>Downgraded</>'),
$operation->getInitialPackage()->getFullPrettyVersion(),
$operation->getTargetPackage()->getFullPrettyVersion(),
);
}

if ($operation instanceof UninstallOperation) {
$packageName = $operation->getPackage()->getName();
$packageUrl = $withUrls ? $this->formatUrl($this->getProjectUrl($operation), $packageName) : $packageName;

return array(
$packageUrl ?: $packageName,
'<fg=red>Removed</>',
Expand Down
34 changes: 33 additions & 1 deletion src/Url/GeneratorContainer.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

use Composer\Package\PackageInterface;

class GeneratorContainer
class GeneratorContainer implements UrlGenerator
{
/**
* @var UrlGenerator[]
Expand Down Expand Up @@ -42,4 +42,36 @@ public function get(PackageInterface $package)

return null;
}

public function supportsPackage(PackageInterface $package)
{
return null !== $this->get($package);
}

public function getCompareUrl(PackageInterface $initialPackage, PackageInterface $targetPackage)
{
if (!$generator = $this->get($targetPackage)) {
return null;
}

return $generator->getCompareUrl($initialPackage, $targetPackage);
}

public function getReleaseUrl(PackageInterface $package)
{
if (!$generator = $this->get($package)) {
return null;
}

return $generator->getReleaseUrl($package);
}

public function getProjectUrl(PackageInterface $package)
{
if (!$generator = $this->get($package)) {
return null;
}

return $generator->getProjectUrl($package);
}
}
67 changes: 49 additions & 18 deletions tests/Formatter/FormatterTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace IonBazan\ComposerDiff\Tests\Formatter;

use Composer\DependencyResolver\Operation\InstallOperation;
use Composer\DependencyResolver\Operation\OperationInterface;
use Composer\DependencyResolver\Operation\UninstallOperation;
use Composer\DependencyResolver\Operation\UpdateOperation;
use Composer\Package\PackageInterface;
Expand Down Expand Up @@ -43,29 +44,22 @@ public function testGetProjectUrlReturnsNullForInvalidOperation()

/**
* @param bool $withUrls
* @param bool $decorated
*
* @testWith [false]
* [true]
* [false, true]
* [true, true]
*/
public function testItRendersTheListOfOperations($withUrls)
public function testItRendersTheListOfOperations($withUrls, $decorated = false)
{
$output = new StreamOutput(fopen('php://memory', 'wb', false));
$formatter = $this->getFormatter($output, $this->getGenerators());
$prodPackages = array(
new InstallOperation($this->getPackage('a/package-1', '1.0.0')),
new InstallOperation($this->getPackage('a/no-link-1', '1.0.0')),
new UpdateOperation($this->getPackage('a/package-2', '1.0.0'), $this->getPackage('a/package-2', '1.2.0')),
new UpdateOperation($this->getPackage('a/package-3', '2.0.0'), $this->getPackage('a/package-3', '1.1.1')),
new UpdateOperation($this->getPackage('a/no-link-2', '2.0.0'), $this->getPackage('a/no-link-2', '1.1.1')),
new UpdateOperation($this->getPackage('php', '>=7.4.6'), $this->getPackage('php', '^8.0')),
$output = new StreamOutput(fopen('php://memory', 'wb', false), OutputInterface::VERBOSITY_NORMAL, $decorated);
$this->getFormatter($output, $this->getGenerators())->render(
$this->getEntries($this->getSampleProdOperations()),
$this->getEntries($this->getSampleDevOperations()),
$withUrls
);
$devPackages = array(
new UpdateOperation($this->getPackage('a/package-5', 'dev-master', 'dev-master 1234567'), $this->getPackage('a/package-5', '1.1.1')),
new UninstallOperation($this->getPackage('a/package-4', '0.1.1')),
new UninstallOperation($this->getPackage('a/no-link-2', '0.1.1')),
);
$formatter->render($this->getEntries($prodPackages), $this->getEntries($devPackages), $withUrls);
$this->assertSame($this->getSampleOutput($withUrls), $this->getDisplay($output));
$this->assertSame($this->getSampleOutput($withUrls, $decorated), $this->getDisplay($output));
}

public function testItFailsWithInvalidOperation()
Expand All @@ -84,10 +78,11 @@ abstract protected function getFormatter(OutputInterface $output, GeneratorConta

/**
* @param bool $withUrls
* @param bool $decorated
*
* @return string
*/
abstract protected function getSampleOutput($withUrls);
abstract protected function getSampleOutput($withUrls, $decorated);

/**
* @return string
Expand All @@ -107,6 +102,14 @@ protected function getDisplay(OutputInterface $output)
return stream_get_contents($output->getStream());
}

/**
* @return bool
*/
protected function supportsLinks()
{
return method_exists('Symfony\Component\Console\Formatter\OutputFormatterStyle', 'setHref');
}

/**
* @return MockObject|GeneratorContainer
*/
Expand All @@ -125,6 +128,7 @@ protected function getGenerators()

$generators = $this->getMockBuilder('IonBazan\ComposerDiff\Url\GeneratorContainer')
->disableOriginalConstructor()
->setMethods(array('get'))
->getMock();
$generators->method('get')
->willReturnCallback(function (PackageInterface $package) use ($generator) {
Expand All @@ -137,4 +141,31 @@ protected function getGenerators()

return $generators;
}

/**
* @return OperationInterface[]
*/
private function getSampleProdOperations()
{
return array(
new InstallOperation($this->getPackage('a/package-1', '1.0.0')),
new InstallOperation($this->getPackage('a/no-link-1', '1.0.0')),
new UpdateOperation($this->getPackage('a/package-2', '1.0.0'), $this->getPackage('a/package-2', '1.2.0')),
new UpdateOperation($this->getPackage('a/package-3', '2.0.0'), $this->getPackage('a/package-3', '1.1.1')),
new UpdateOperation($this->getPackage('a/no-link-2', '2.0.0'), $this->getPackage('a/no-link-2', '1.1.1')),
new UpdateOperation($this->getPackage('php', '>=7.4.6'), $this->getPackage('php', '^8.0')),
);
}

/**
* @return OperationInterface[]
*/
private function getSampleDevOperations()
{
return array(
new UpdateOperation($this->getPackage('a/package-5', 'dev-master', 'dev-master 1234567'), $this->getPackage('a/package-5', '1.1.1')),
new UninstallOperation($this->getPackage('a/package-4', '0.1.1')),
new UninstallOperation($this->getPackage('a/no-link-2', '0.1.1')),
);
}
}
2 changes: 1 addition & 1 deletion tests/Formatter/GitHubFormatterTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

class GitHubFormatterTest extends FormatterTest
{
protected function getSampleOutput($withUrls)
protected function getSampleOutput($withUrls, $decorated)
{
if ($withUrls) {
return <<<OUTPUT
Expand Down
2 changes: 1 addition & 1 deletion tests/Formatter/JsonFormatterTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ public function testRenderSingle()
)), $this->getDisplay($output));
}

protected function getSampleOutput($withUrls)
protected function getSampleOutput($withUrls, $decorated)
{
if ($withUrls) {
return self::formatOutput(array(
Expand Down
Loading

0 comments on commit 6ac141b

Please sign in to comment.