Skip to content

Commit

Permalink
Merge pull request #169 from Jibbarth/feature/new-composer-insights
Browse files Browse the repository at this point in the history
Add ComposerMustBeValid and ComposerLockMustBeFresh insights
  • Loading branch information
Jibbarth authored Jun 8, 2019
2 parents afe7b32 + e04b204 commit 5d0e1af
Show file tree
Hide file tree
Showing 19 changed files with 686 additions and 10 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@
.idea/*
.env
.phpunit.result.cache
composer.lock
/composer.lock
.php_cs.cache
3 changes: 2 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,9 @@
],
"require": {
"php": "^7.2",
"ext-json": "*",
"ext-iconv": "*",
"ext-json": "*",
"composer/composer": "^1.7",
"league/container": "^3.2",
"object-calisthenics/phpcs-calisthenics-rules": "^3.5",
"phploc/phploc": "^5.0",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,8 @@

declare(strict_types=1);

namespace NunoMaduro\PhpInsights\Domain\Insights;
namespace NunoMaduro\PhpInsights\Domain;

use NunoMaduro\PhpInsights\Domain\Collector;
use NunoMaduro\PhpInsights\Domain\Exceptions\ComposerNotFound;

final class ComposerFinder
Expand All @@ -15,11 +14,16 @@ final class ComposerFinder
* @return string
*/
public static function contents(Collector $collector): string
{
return (string) file_get_contents(self::getPath($collector));
}

public static function getPath(Collector $collector): string
{
$filePath = $collector->getDir() . '/composer.json';

if (file_exists($filePath)) {
return (string) file_get_contents($filePath);
return $filePath;
}

throw new ComposerNotFound('`composer.json` not found.');
Expand Down
21 changes: 21 additions & 0 deletions src/Domain/ComposerLoader.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?php

declare(strict_types=1);

namespace NunoMaduro\PhpInsights\Domain;

use Composer\Composer;
use Composer\Factory;
use Composer\IO\NullIO;

/**
* @internal
*/
final class ComposerLoader
{
public static function getInstance(Collector $collector): Composer
{
$io = new NullIO();
return Factory::create($io, ComposerFinder::getPath($collector));
}
}
34 changes: 34 additions & 0 deletions src/Domain/Insights/Composer/ComposerLockMustBeFresh.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?php

declare(strict_types=1);

namespace NunoMaduro\PhpInsights\Domain\Insights\Composer;

use NunoMaduro\PhpInsights\Domain\ComposerLoader;
use NunoMaduro\PhpInsights\Domain\Contracts\HasDetails;
use NunoMaduro\PhpInsights\Domain\Exceptions\ComposerNotFound;
use NunoMaduro\PhpInsights\Domain\Insights\Insight;

final class ComposerLockMustBeFresh extends Insight implements HasDetails
{
public function hasIssue(): bool
{
try {
$composer = ComposerLoader::getInstance($this->collector);

return ! $composer->getLocker()->isFresh();
} catch (ComposerNotFound $exception) {
return true;
}
}

public function getTitle(): string
{
return 'The lock file is not up to date with the latest changes in composer.json';
}

public function getDetails(): array
{
return ['You may be getting outdated dependencies. Run update to update them.'];
}
}
54 changes: 54 additions & 0 deletions src/Domain/Insights/Composer/ComposerMustBeValid.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
<?php

declare(strict_types=1);

namespace NunoMaduro\PhpInsights\Domain\Insights\Composer;

use Composer\IO\NullIO;
use Composer\Util\ConfigValidator;
use NunoMaduro\PhpInsights\Domain\ComposerFinder;
use NunoMaduro\PhpInsights\Domain\Contracts\HasDetails;
use NunoMaduro\PhpInsights\Domain\Insights\Insight;

final class ComposerMustBeValid extends Insight implements HasDetails
{
/**
* @var array<string>
*/
private $errors;
/**
* @var array<string>
*/
private $publishErrors;
/**
* @var array<string>
*/
private $warnings;

public function hasIssue(): bool
{
$validator = new ConfigValidator(new NullIO());
[$this->errors, $this->publishErrors, $this->warnings] = $validator->validate(ComposerFinder::getPath($this->collector));

return \count(\array_merge($this->errors, $this->publishErrors, $this->warnings)) > 0;
}

public function getTitle(): string
{
return 'Composer.json is not valid';
}

public function getDetails(): array
{
$details = [];

foreach (array_merge($this->errors, $this->publishErrors, $this->warnings) as $issue) {
if (strpos($issue, ' : ') !== false) {
$issue = explode(' : ', $issue)[1];
}
$details[] = 'composer.json: ' . $issue;
}

return $details;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@

declare(strict_types=1);

namespace NunoMaduro\PhpInsights\Domain\Insights;
namespace NunoMaduro\PhpInsights\Domain\Insights\Composer;

use NunoMaduro\PhpInsights\Domain\ComposerFinder;
use NunoMaduro\PhpInsights\Domain\Exceptions\ComposerNotFound;
use NunoMaduro\PhpInsights\Domain\Insights\Insight;

final class ComposerMustContainName extends Insight
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@

declare(strict_types=1);

namespace NunoMaduro\PhpInsights\Domain\Insights;
namespace NunoMaduro\PhpInsights\Domain\Insights\Composer;

use NunoMaduro\PhpInsights\Domain\ComposerFinder;
use NunoMaduro\PhpInsights\Domain\Exceptions\ComposerNotFound;
use NunoMaduro\PhpInsights\Domain\Insights\Insight;

final class ComposerMustExist extends Insight
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@

namespace NunoMaduro\PhpInsights\Domain\Insights\Laravel;

use NunoMaduro\PhpInsights\Domain\ComposerFinder;
use NunoMaduro\PhpInsights\Domain\Exceptions\ComposerNotFound;
use NunoMaduro\PhpInsights\Domain\Insights\ComposerFinder;
use NunoMaduro\PhpInsights\Domain\Insights\Insight;

final class ComposerCheckLaravelVersion extends Insight
Expand Down
8 changes: 6 additions & 2 deletions src/Domain/Metrics/Architecture/Composer.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@
namespace NunoMaduro\PhpInsights\Domain\Metrics\Architecture;

use NunoMaduro\PhpInsights\Domain\Contracts\HasInsights;
use NunoMaduro\PhpInsights\Domain\Insights\ComposerMustContainName;
use NunoMaduro\PhpInsights\Domain\Insights\ComposerMustExist;
use NunoMaduro\PhpInsights\Domain\Insights\Composer\ComposerLockMustBeFresh;
use NunoMaduro\PhpInsights\Domain\Insights\Composer\ComposerMustBeValid;
use NunoMaduro\PhpInsights\Domain\Insights\Composer\ComposerMustContainName;
use NunoMaduro\PhpInsights\Domain\Insights\Composer\ComposerMustExist;

final class Composer implements HasInsights
{
Expand All @@ -18,6 +20,8 @@ public function getInsights(): array
return [
ComposerMustExist::class,
ComposerMustContainName::class,
ComposerMustBeValid::class,
ComposerLockMustBeFresh::class,
];
}
}
32 changes: 32 additions & 0 deletions tests/Domain/ComposerFinderTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php

declare(strict_types=1);

namespace Tests\Domain;

use NunoMaduro\PhpInsights\Domain\Collector;
use NunoMaduro\PhpInsights\Domain\ComposerFinder;
use NunoMaduro\PhpInsights\Domain\Exceptions\ComposerNotFound;
use PHPUnit\Framework\TestCase;

final class ComposerFinderTest extends TestCase
{
public function testGetComposerPath(): void
{
$collector = new Collector(__DIR__ . '/Insights/Composer/Fixtures/Valid');
$path = ComposerFinder::getPath($collector);

self::assertEquals(
__DIR__ . '/Insights/Composer/Fixtures/Valid/composer.json',
$path
);
}

public function testGetComposerPathThrowExceptionIfNoComposerJsonExist(): void
{
self::expectException(ComposerNotFound::class);

$collector = new Collector(__DIR__ . '/Insights/Composer/Fixtures');
ComposerFinder::getPath($collector);
}
}
30 changes: 30 additions & 0 deletions tests/Domain/ComposerLoaderTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?php

declare(strict_types=1);

namespace Tests\Domain;

use Composer\Composer;
use NunoMaduro\PhpInsights\Domain\Collector;
use NunoMaduro\PhpInsights\Domain\ComposerLoader;
use NunoMaduro\PhpInsights\Domain\Exceptions\ComposerNotFound;
use PHPUnit\Framework\TestCase;

final class ComposerLoaderTest extends TestCase
{
public function testGetInstance(): void
{
$collector = new Collector(__DIR__ . '/Insights/Composer/Fixtures/Valid');
$composer = ComposerLoader::getInstance($collector);

self::assertEquals(Composer::class, get_class($composer));
}

public function testGetExceptionOnFolderWithoutComposerJson(): void
{
self::expectException(ComposerNotFound::class);

$collector = new Collector(__DIR__ . '/Insights/Composer/Fixtures');
ComposerLoader::getInstance($collector);
}
}
28 changes: 28 additions & 0 deletions tests/Domain/Insights/Composer/ComposerLockMustBeFreshTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?php

declare(strict_types=1);

namespace Tests\Domain\Insights\Composer;

use NunoMaduro\PhpInsights\Domain\Collector;
use NunoMaduro\PhpInsights\Domain\Insights\Composer\ComposerLockMustBeFresh;
use PHPUnit\Framework\TestCase;

final class ComposerLockMustBeFreshTest extends TestCase
{
public function testHasIssueWhenComposerLockWasntUpdateFromComposerJson(): void
{
$collector = new Collector(__DIR__ . '/Fixtures/Unfresh');
$insight = new ComposerLockMustBeFresh($collector, []);

self::assertTrue($insight->hasIssue());
}

public function testHasNoIssueWhenComposerLockUpToDate(): void
{
$collector = new Collector(__DIR__ . '/Fixtures/Fresh');
$insight = new ComposerLockMustBeFresh($collector, []);

self::assertFalse($insight->hasIssue());
}
}
32 changes: 32 additions & 0 deletions tests/Domain/Insights/Composer/ComposerMustBeValidTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php

declare(strict_types=1);

namespace Tests\Domain\Insights\Composer;

use NunoMaduro\PhpInsights\Domain\Collector;
use NunoMaduro\PhpInsights\Domain\Insights\Composer\ComposerMustBeValid;
use PHPUnit\Framework\TestCase;

final class ComposerMustBeValidTest extends TestCase
{
public function testComposerIsNotValid(): void
{
$collector = new Collector(__DIR__ . '/Fixtures/Fresh');
$insight = new ComposerMustBeValid($collector, []);

self::assertTrue($insight->hasIssue());
self::assertIsArray($insight->getDetails());
self::assertContains('composer.json: The property name is required', $insight->getDetails());
self::assertContains('composer.json: The property description is required', $insight->getDetails());
self::assertContains('composer.json: No license specified, it is recommended to do so. For closed-source software you may use "proprietary" as license.', $insight->getDetails());
}

public function testComposerIsValid(): void
{
$collector = new Collector(__DIR__ . '/Fixtures/Valid');
$insight = new ComposerMustBeValid($collector, []);

self::assertFalse($insight->hasIssue());
}
}
5 changes: 5 additions & 0 deletions tests/Domain/Insights/Composer/Fixtures/Fresh/composer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"require": {
"symfony/var-dumper": "^4.3"
}
}
Loading

0 comments on commit 5d0e1af

Please sign in to comment.