Skip to content

Commit c65fd95

Browse files
Merge pull request #30 from Phauthentic/attribute-rule
Implement Attribute Rule for PHP 8+ attributes validation
2 parents 9af22fc + 95207eb commit c65fd95

18 files changed

Lines changed: 1531 additions & 245 deletions

README.md

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,18 +18,19 @@ See individual rule documentation for detailed configuration examples. A [full c
1818

1919
### Architecture Rules
2020

21-
- [Dependency Constraints Rule](docs/rules/Dependency-Constraints-Rule.md)
22-
- [Modular Architecture Rule](docs/rules/Modular-Architecture-Rule.md)
21+
- [Attribute Rule](docs/rules/Attribute-Rule.md)
22+
- [Catch Exception Of Type Not Allowed Rule](docs/rules/Catch-Exception-Of-Type-Not-Allowed-Rule.md)
2323
- [Circular Module Dependency Rule](docs/rules/Circular-Module-Dependency-Rule.md)
24-
- [Forbidden Namespaces Rule](docs/rules/Forbidden-Namespaces-Rule.md)
25-
- [Class Must Be Readonly Rule](docs/rules/Class-Must-Be-Readonly-Rule.md)
2624
- [Class Must Be Final Rule](docs/rules/Class-Must-Be-Final-Rule.md)
27-
- [Classname Must Match Pattern Rule](docs/rules/Classname-Must-Match-Pattern-Rule.md)
28-
- [Catch Exception Of Type Not Allowed Rule](docs/rules/Catch-Exception-Of-Type-Not-Allowed-Rule.md)
25+
- [Class Must Be Readonly Rule](docs/rules/Class-Must-Be-Readonly-Rule.md)
2926
- [Class Must Have Specification Docblock Rule](docs/rules/Class-Must-Have-Specification-Docblock-Rule.md)
30-
- [Methods Returning Bool Must Follow Naming Convention Rule](docs/rules/Methods-Returning-Bool-Must-Follow-Naming-Convention-Rule.md)
31-
- [Method Signature Must Match Rule](docs/rules/Method-Signature-Must-Match-Rule.md)
27+
- [Classname Must Match Pattern Rule](docs/rules/Classname-Must-Match-Pattern-Rule.md)
28+
- [Dependency Constraints Rule](docs/rules/Dependency-Constraints-Rule.md)
29+
- [Forbidden Namespaces Rule](docs/rules/Forbidden-Namespaces-Rule.md)
3230
- [Method Must Return Type Rule](docs/rules/Method-Must-Return-Type-Rule.md)
31+
- [Method Signature Must Match Rule](docs/rules/Method-Signature-Must-Match-Rule.md)
32+
- [Methods Returning Bool Must Follow Naming Convention Rule](docs/rules/Methods-Returning-Bool-Must-Follow-Naming-Convention-Rule.md)
33+
- [Modular Architecture Rule](docs/rules/Modular-Architecture-Rule.md)
3334

3435
### Clean Code Rules
3536

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace App\Controller;
6+
7+
use Symfony\Component\Routing\Annotation\Route;
8+
9+
/**
10+
* Class with allowed attributes - should pass.
11+
*/
12+
#[Route('/api')]
13+
class AllowedClassAttributes
14+
{
15+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace App\Domain\Service;
6+
7+
use App\Attribute\FrameworkAttribute;
8+
use App\Attribute\DomainAttribute;
9+
10+
/**
11+
* Class in Domain layer - framework attributes should be forbidden on methods.
12+
*/
13+
class CombinedClassMethodPattern
14+
{
15+
/**
16+
* Method with forbidden framework attribute in domain - should fail.
17+
*/
18+
#[FrameworkAttribute]
19+
public function processData(): void
20+
{
21+
}
22+
23+
/**
24+
* Method with allowed domain attribute - should pass.
25+
*/
26+
#[DomainAttribute]
27+
public function handleDomain(): void
28+
{
29+
}
30+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace App\Domain\Entity;
6+
7+
use App\Attribute\FrameworkAttribute;
8+
use App\Attribute\DomainAttribute;
9+
10+
/**
11+
* Entity in Domain layer - framework attributes should be forbidden on properties.
12+
*/
13+
class CombinedClassPropertyPattern
14+
{
15+
/**
16+
* Property with forbidden framework attribute in domain - should fail.
17+
*/
18+
#[FrameworkAttribute]
19+
private string $forbiddenProperty;
20+
21+
/**
22+
* Property with allowed domain attribute - should pass.
23+
*/
24+
#[DomainAttribute]
25+
private string $allowedProperty;
26+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace App\Controller;
6+
7+
use App\Attribute\Deprecated;
8+
9+
/**
10+
* Class with forbidden attributes - should fail.
11+
*/
12+
#[Deprecated]
13+
class ForbiddenClassAttributes
14+
{
15+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace App\Controller;
6+
7+
use Symfony\Component\Routing\Annotation\Route;
8+
use App\Attribute\Deprecated;
9+
use App\Attribute\CustomAttribute;
10+
11+
/**
12+
* Class with method attributes for testing.
13+
*/
14+
class MethodAttributes
15+
{
16+
/**
17+
* Method with allowed attribute - should pass.
18+
*/
19+
#[Route('/users')]
20+
public function allowedAction(): void
21+
{
22+
}
23+
24+
/**
25+
* Method with forbidden attribute - should fail.
26+
*/
27+
#[Deprecated]
28+
public function forbiddenAction(): void
29+
{
30+
}
31+
32+
/**
33+
* Method with attribute not in allowed list - should fail.
34+
*/
35+
#[CustomAttribute]
36+
public function notAllowedAction(): void
37+
{
38+
}
39+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace App\Service;
6+
7+
/**
8+
* Class without any attributes - should always pass.
9+
*/
10+
class NoAttributesClass
11+
{
12+
private string $property;
13+
14+
public function doSomething(): void
15+
{
16+
}
17+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace App\Controller;
6+
7+
use App\Attribute\CustomAttribute;
8+
9+
/**
10+
* Class with attributes not in allowed list - should fail.
11+
*/
12+
#[CustomAttribute]
13+
class NotAllowedClassAttributes
14+
{
15+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace App\Entity;
6+
7+
use Doctrine\ORM\Mapping\Column;
8+
use Doctrine\ORM\Mapping\Id;
9+
use App\Attribute\Deprecated;
10+
use App\Attribute\CustomAttribute;
11+
12+
/**
13+
* Class with property attributes for testing.
14+
*/
15+
class PropertyAttributes
16+
{
17+
/**
18+
* Property with allowed attribute - should pass.
19+
*/
20+
#[Id]
21+
#[Column]
22+
private int $id;
23+
24+
/**
25+
* Property with forbidden attribute - should fail.
26+
*/
27+
#[Deprecated]
28+
private string $forbiddenProperty;
29+
30+
/**
31+
* Property with attribute not in allowed list - should fail.
32+
*/
33+
#[CustomAttribute]
34+
private string $notAllowedProperty;
35+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace App\Controller;
6+
7+
/**
8+
* Class missing required attribute - should fail.
9+
*/
10+
class RequiredClassAttribute
11+
{
12+
}

0 commit comments

Comments
 (0)