Skip to content

Commit

Permalink
Add ability to check for multiple NotExtends
Browse files Browse the repository at this point in the history
  • Loading branch information
kapersoft committed May 17, 2024
1 parent a7fe6f3 commit 45fae31
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 23 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -350,6 +350,8 @@ $rules[] = Rule::allClasses()
->that(new ResideInOneOfTheseNamespaces('App\Controller\Admin'))
->should(new NotExtend('App\Controller\AbstractController'))
->because('we want to be sure that all admin controllers not extend AbstractController for security reasons');

You can add multiple parameters, the violation will happen when one of them match
```

### Don't have dependency outside a namespace
Expand Down
36 changes: 18 additions & 18 deletions src/Expression/ForClasses/NotExtend.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,36 +13,36 @@

class NotExtend implements Expression
{
/** @var string */
private $className;
/** @var string[] */
private $classNames;

public function __construct(string $className)
public function __construct(string ...$classNames)
{
$this->className = $className;
$this->classNames = $classNames;
}

public function describe(ClassDescription $theClass, string $because): Description
{
return new Description("should not extend {$this->className}", $because);
$desc = implode(', ', $this->classNames);

return new Description("should not extend one of these classes: {$desc}", $because);
}

public function evaluate(ClassDescription $theClass, Violations $violations, string $because): void
{
$extends = $theClass->getExtends();

if (null === $extends) {
return;
}

if ($extends->toString() !== $this->className) {
return;
/** @var string $className */
foreach ($this->classNames as $className) {
if (null !== $extends && $extends->matches($className)) {
$violation = Violation::create(
$theClass->getFQCN(),
ViolationMessage::selfExplanatory($this->describe($theClass, $because))
);

$violations->add($violation);
return;
}
}

$violation = Violation::create(
$theClass->getFQCN(),
ViolationMessage::selfExplanatory($this->describe($theClass, $because))
);

$violations->add($violation);
}
}
8 changes: 4 additions & 4 deletions tests/E2E/Cli/DebugExpressionCommandTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,16 +36,16 @@ public function test_some_classes_found(): void
public function test_meaningful_errors_for_too_few_arguments_for_the_expression(): void
{
$appTester = $this->createAppTester();
$appTester->run(['debug:expression', 'expression' => 'NotExtend', 'arguments' => [], '--from-dir' => __DIR__.'/../_fixtures/mvc/Domain']);
$this->assertEquals("Error: Too few arguments for 'NotExtend'.\n", $appTester->getDisplay());
$appTester->run(['debug:expression', 'expression' => 'NotImplement', 'arguments' => [], '--from-dir' => __DIR__.'/../_fixtures/mvc/Domain']);
$this->assertEquals("Error: Too few arguments for 'NotImplement'.\n", $appTester->getDisplay());
$this->assertEquals(2, $appTester->getStatusCode());
}

public function test_meaningful_errors_for_too_many_arguments_for_the_expression(): void
{
$appTester = $this->createAppTester();
$appTester->run(['debug:expression', 'expression' => 'NotExtend', 'arguments' => ['First', 'Second'], '--from-dir' => __DIR__.'/../_fixtures/mvc/Domain']);
$this->assertEquals("Error: Too many arguments for 'NotExtend'.\n", $appTester->getDisplay());
$appTester->run(['debug:expression', 'expression' => 'NotImplement', 'arguments' => ['First', 'Second'], '--from-dir' => __DIR__.'/../_fixtures/mvc/Domain']);
$this->assertEquals("Error: Too many arguments for 'NotImplement'.\n", $appTester->getDisplay());
$this->assertEquals(2, $appTester->getStatusCode());
}

Expand Down
28 changes: 27 additions & 1 deletion tests/Unit/Expressions/ForClasses/NotExtendTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ public function test_it_should_return_violation_error(): void
$notExtend->evaluate($classDescription, $violations, $because);

self::assertEquals(1, $violations->count());
self::assertEquals('should not extend My\BaseClass because we want to add this rule for our software', $violationError);
self::assertEquals('should not extend one of these classes: My\BaseClass because we want to add this rule for our software', $violationError);
}

public function test_it_should_not_return_violation_error_if_extends_another_class(): void
Expand All @@ -62,4 +62,30 @@ public function test_it_should_not_return_violation_error_if_extends_another_cla

self::assertEquals(0, $violations->count());
}

public function test_it_should_return_violation_error_for_multiple_extends(): void
{
$notExtend = new NotExtend('My\FirstExtend', 'My\SecondExtend');

$classDescription = new ClassDescription(
FullyQualifiedClassName::fromString('HappyIsland'),
[],
[],
FullyQualifiedClassName::fromString('My\SecondExtend'),
false,
false,
false,
false,
false,
false
);
$because = 'we want to add this rule for our software';
$violationError = $notExtend->describe($classDescription, $because)->toString();

$violations = new Violations();
$notExtend->evaluate($classDescription, $violations, $because);

self::assertEquals(1, $violations->count());
self::assertEquals('should not extend one of these classes: My\FirstExtend, My\SecondExtend because we want to add this rule for our software', $violationError);
}
}

0 comments on commit 45fae31

Please sign in to comment.