From 611ce8565ac3c5650dc0b3cf1956db1a9d7c84f2 Mon Sep 17 00:00:00 2001 From: AlessandroMinoccheri Date: Tue, 13 Sep 2022 22:04:27 +0200 Subject: [PATCH] added runOnlyThis option to ruleBuilder --- README.md | 12 ++++++++++++ src/CLI/Config.php | 18 ++++++++++++++++++ src/Rules/ArchRule.php | 25 +++++++++++++++++++++++-- src/Rules/DSL/ArchRule.php | 4 ++++ src/Rules/RuleBuilder.php | 13 ++++++++++++- tests/Unit/CLI/ConfigTest.php | 24 ++++++++++++++++++++++++ tests/Unit/Rules/RuleCheckerTest.php | 10 ++++++++++ 7 files changed, 103 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 94a87d5a..5c1be9a2 100644 --- a/README.md +++ b/README.md @@ -337,6 +337,18 @@ phparkitect check --config=/project/yourConfigFile.php Supported PHP versions are: 7.1, 7.2, 7.3, 7.4, 8.0, 8.1 * `--stop-on-failure`: With this option the process will end immediately after the first violation. +## Run only a specific rule +For some reasons, you might want to run only a specific rule, you can do it using `runOnlyThis` like this: + +```php +$rules[] = Rule::allClasses() + ->except('App\Controller\FolderController\*') + ->that(new ResideInOneOfTheseNamespaces('App\Controller')) + ->should(new HaveNameMatching('*Controller')) + ->because('we want uniform naming') + ->runOnlyThis(); +``` + # Integrations ## Laravel diff --git a/src/CLI/Config.php b/src/CLI/Config.php index 95ec960b..2ccd1809 100644 --- a/src/CLI/Config.php +++ b/src/CLI/Config.php @@ -11,14 +11,32 @@ class Config { /** @var array */ private $classSetRules; + /** @var bool */ + private $runOnlyARule; public function __construct() { $this->classSetRules = []; + $this->runOnlyARule = false; } public function add(ClassSet $classSet, ArchRule ...$rules): self { + if ($this->runOnlyARule) { + return $this; + } + + /** @var ArchRule $rule */ + foreach ($rules as $rule) { + if ($rule->isRunOnlyThis()) { + $rules = []; + $rules[] = $rule; + + $this->runOnlyARule = true; + break; + } + } + $this->classSetRules[] = ClassSetRules::create($classSet, ...$rules); return $this; diff --git a/src/Rules/ArchRule.php b/src/Rules/ArchRule.php index 8b1c4a23..2909d417 100644 --- a/src/Rules/ArchRule.php +++ b/src/Rules/ArchRule.php @@ -19,12 +19,21 @@ class ArchRule implements DSL\ArchRule /** @var array */ private $classesToBeExcluded; - public function __construct(Specs $specs, Constraints $constraints, string $because, array $classesToBeExcluded) - { + /** @var bool */ + private $runOnlyThis; + + public function __construct( + Specs $specs, + Constraints $constraints, + string $because, + array $classesToBeExcluded, + bool $runOnlyThis + ) { $this->thats = $specs; $this->shoulds = $constraints; $this->because = $because; $this->classesToBeExcluded = $classesToBeExcluded; + $this->runOnlyThis = $runOnlyThis; } public function check(ClassDescription $classDescription, Violations $violations): void @@ -39,4 +48,16 @@ public function check(ClassDescription $classDescription, Violations $violations $this->shoulds->checkAll($classDescription, $violations, $this->because); } + + public function isRunOnlyThis(): bool + { + return $this->runOnlyThis; + } + + public function runOnlyThis(): DSL\ArchRule + { + $this->runOnlyThis = true; + + return $this; + } } diff --git a/src/Rules/DSL/ArchRule.php b/src/Rules/DSL/ArchRule.php index 02af7707..80615e2a 100644 --- a/src/Rules/DSL/ArchRule.php +++ b/src/Rules/DSL/ArchRule.php @@ -9,4 +9,8 @@ interface ArchRule { public function check(ClassDescription $classDescription, Violations $violations): void; + + public function isRunOnlyThis(): bool; + + public function runOnlyThis(): self; } diff --git a/src/Rules/RuleBuilder.php b/src/Rules/RuleBuilder.php index 759e40a7..e6f12bf2 100644 --- a/src/Rules/RuleBuilder.php +++ b/src/Rules/RuleBuilder.php @@ -18,6 +18,8 @@ class RuleBuilder /** @var array */ private $classesToBeExcluded; + /** @var bool */ + private $runOnlyThis; public function __construct() { @@ -25,6 +27,7 @@ public function __construct() $this->shoulds = new Constraints(); $this->because = ''; $this->classesToBeExcluded = []; + $this->runOnlyThis = false; } public function addThat(Expression $that): self @@ -54,7 +57,8 @@ public function build(): ArchRule $this->thats, $this->shoulds, $this->because, - $this->classesToBeExcluded + $this->classesToBeExcluded, + $this->runOnlyThis ); } @@ -64,4 +68,11 @@ public function classesToBeExcluded(string ...$classesToBeExcluded): self return $this; } + + public function setRunOnlyThis(): self + { + $this->runOnlyThis = true; + + return $this; + } } diff --git a/tests/Unit/CLI/ConfigTest.php b/tests/Unit/CLI/ConfigTest.php index 658c0777..bf26d177 100644 --- a/tests/Unit/CLI/ConfigTest.php +++ b/tests/Unit/CLI/ConfigTest.php @@ -31,4 +31,28 @@ public function test_it_should_create_config(): void $classSetRulesExpected[] = ClassSetRules::create($classSet, ...[$rule]); $this->assertEquals($classSetRulesExpected, $config->getClassSetRules()); } + + public function test_it_should_create_config_with_only_one_rule_to_run(): void + { + $classSet = ClassSet::fromDir(__DIR__.'/foo'); + + $rule1 = Rule::allClasses() + ->that(new ResideInOneOfTheseNamespaces('App\Controller')) + ->should(new HaveNameMatching('*Controller')) + ->because('all controllers should be end name with Controller'); + + $rule2 = Rule::allClasses() + ->that(new ResideInOneOfTheseNamespaces('App\Service')) + ->should(new HaveNameMatching('*Service')) + ->because('all services should be end name with Service') + ->runOnlyThis(); + + $config = new Config(); + $config->add($classSet, ...[$rule1, $rule2]); + + $this->assertInstanceOf(Config::class, $config); + + $classSetRulesExpected[] = ClassSetRules::create($classSet, ...[$rule2]); + $this->assertEquals($classSetRulesExpected, $config->getClassSetRules()); + } } diff --git a/tests/Unit/Rules/RuleCheckerTest.php b/tests/Unit/Rules/RuleCheckerTest.php index 937bb978..b0b3b91f 100644 --- a/tests/Unit/Rules/RuleCheckerTest.php +++ b/tests/Unit/Rules/RuleCheckerTest.php @@ -69,6 +69,16 @@ public function check(ClassDescription $classDescription, Violations $violations { $violations->add(new Violation('fqcn', 'error')); } + + public function isRunOnlyThis(): bool + { + return false; + } + + public function runOnlyThis(): ArchRule + { + return $this; + } } class FakeParser implements Parser