Skip to content

Commit b9c257f

Browse files
committed
Fixes
Removed escaping Renamed namespace_restriction to namespace_constraints
1 parent 9b1b674 commit b9c257f

28 files changed

+413
-133
lines changed

README.md

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
# PHPStan Namespace Constraints Rule
2+
3+
This repository contains the code for the namespace_constraints rule for PHPStan.
4+
5+
## Why?
6+
In the most architectures you should not depend on everything.
7+
With this rule you can ensure that a source namespace (RegEx Pattern) can only depend on code that lives in the target
8+
namespaces.
9+
10+
## Installation
11+
```bash
12+
$ composer require --dev mintware-de/phpstan-namespace-constraints
13+
```
14+
15+
## Configuration
16+
17+
Add this to your `phpstan.neon`
18+
19+
```neon
20+
# phpstan.neon
21+
includes:
22+
- vendor/mintware-de/phpstan-namespace-constraints/src/Rules/rules.neon
23+
24+
parameters:
25+
namespace_constraints:
26+
constraints:
27+
- from: App\\SourceNamespace\\.* # Everything inside this namespace has access to
28+
to: [App\\TargetNamespace\\.*] # this namespace
29+
```
30+
31+
## Examples
32+
33+
### Simple
34+
35+
```mermaid
36+
graph TD;
37+
App\Data-->App\Core;
38+
App\UserInterface-->App\Data;
39+
```
40+
41+
```neon
42+
# phpstan.neon
43+
includes:
44+
- vendor/mintware-de/phpstan-namespace-constraints/src/Rules/rules.neon
45+
46+
parameters:
47+
namespace_constraints:
48+
constraints:
49+
- from: App\\Core(\\.*)?
50+
to: [App\\Core(\\.*)?]
51+
- from: App\\Data(\\.*)?
52+
to:
53+
- App\\Core(\\.*)?
54+
- App\\Data(\\.*)?
55+
- from: App\\UserInterface(\\.*)?
56+
to:
57+
- App\\Core(\\.*)?
58+
- App\\Data(\\.*)?
59+
- App\\UserInterface(\\.*)?
60+
```
61+
62+
### Advanced
63+
64+
```mermaid
65+
graph TD;
66+
App\User\Core-->App\Shared\Core
67+
App\Blog\Core-->App\Shared\Core
68+
App\*\Core-->App\Shared\Core
69+
```
70+
71+
72+
```neon
73+
# phpstan.neon
74+
includes:
75+
- vendor/mintware-de/phpstan-namespace-constraints/src/Rules/rules.neon
76+
77+
parameters:
78+
namespace_constraints:
79+
constraints:
80+
# App\User Constraints
81+
- from: App\\User\\Core(\\.*)?
82+
to: [App\\User\\Core(\\.*)?]
83+
# App\\Blog\ Constraints
84+
- from: App\\Blog\\Core(\\.*)?
85+
to: [App\\Blog\\Core(\\.*)?]
86+
# App\*\Core -> App\Shared\Core
87+
- from: App\\(\w+)\\Core(\\.*)?
88+
to: [App\\Shared\\Core(\\.*)?]
89+
```

composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
"description": "A PHPStan rule for restricting namespace usings to control dependency inheritance.",
44
"type": "library",
55
"require": {
6-
"php": "^7.0 || ^8.0",
6+
"php": "^7.1 || ^8.0",
77
"phpstan/phpstan": "^0.12.99",
88
"nikic/php-parser": "^4.13"
99
},

src/Rules/NamespaceRestrictionRule.php

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -51,12 +51,8 @@ public function processNode(Node $node, Scope $scope): array
5151
if ($constraint[self::CONSTRAINT_FROM] === null && $scope->getNamespace() !== null) {
5252
continue;
5353
}
54-
$escaped = addcslashes($constraint[self::CONSTRAINT_FROM] ?? '', '\\');
55-
if ($escaped == null) {
56-
$constraints[$constraint[self::CONSTRAINT_FROM]][] = [];
57-
continue;
58-
}
59-
if (preg_match('~^'.$escaped.'$~', $scope->getNamespace() ?? '')) {
54+
55+
if (preg_match('~^'.$constraint[self::CONSTRAINT_FROM].'$~', $scope->getNamespace() ?? '')) {
6056
if (!isset($constraints[$constraint[self::CONSTRAINT_FROM]])) {
6157
$constraints[$constraint[self::CONSTRAINT_FROM]] = [];
6258
}
@@ -85,7 +81,7 @@ public function processNode(Node $node, Scope $scope): array
8581

8682
$fullPattern = '~^('.implode('|', $values).')$~';
8783

88-
if (!preg_match(addcslashes($fullPattern, '\\'), $name)) {
84+
if (!preg_match($fullPattern, $name)) {
8985
if (!isset($this->builtInChecks[$name])) {
9086
$reflection = null;
9187
if (class_exists($name)) {

src/Rules/rules.neon

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,12 @@ services:
55
-
66
class: \MintwareDe\PhpStanNamespaceConstraints\Rules\NamespaceRestrictionRule
77
arguments:
8-
constraints: '%namespace_restriction.constraints%'
8+
constraints: '%namespace_constraints.constraints%'
99
tags:
1010
- phpstan.rules.rule
1111

1212
parametersSchema:
13-
namespace_restriction: structure([
13+
namespace_constraints: structure([
1414
constraints: listOf(structure([
1515
from: anyOf(null, string())
1616
to: listOf(string())
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 MintwareDe\Tests\PhpStanNamespaceConstraints\Advanced\Blog\Core;
6+
7+
use MintwareDe\Tests\PhpStanNamespaceConstraints\Advanced\Shared\Core\Entity\BlogEntry;
8+
9+
class BlogService
10+
{
11+
public function getEntry(): BlogEntry
12+
{
13+
return new BlogEntry();
14+
}
15+
}
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 MintwareDe\Tests\PhpStanNamespaceConstraints\Advanced\Blog\Core;
6+
7+
use MintwareDe\Tests\PhpStanNamespaceConstraints\Advanced\User\Core\UserService;
8+
9+
class InvalidBlogService
10+
{
11+
public function __construct(UserService $userService)
12+
{
13+
$userService->getUser();
14+
}
15+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace MintwareDe\Tests\PhpStanNamespaceConstraints\Advanced\Shared\Core\Entity;
6+
7+
class BlogEntry
8+
{
9+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace MintwareDe\Tests\PhpStanNamespaceConstraints\Advanced\Shared\Core\Entity;
6+
7+
class User
8+
{
9+
}
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 MintwareDe\Tests\PhpStanNamespaceConstraints\Advanced\Shared\Core;
6+
7+
use MintwareDe\Tests\PhpStanNamespaceConstraints\Advanced\Blog\Core\BlogService;
8+
use MintwareDe\Tests\PhpStanNamespaceConstraints\Advanced\User\Core\UserService;
9+
10+
class InvalidService
11+
{
12+
public function __construct(BlogService $blogService, UserService $userService)
13+
{
14+
$blogService->getEntry();
15+
$userService->getUser();
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 MintwareDe\Tests\PhpStanNamespaceConstraints\Advanced\User\Core;
6+
7+
use MintwareDe\Tests\PhpStanNamespaceConstraints\Advanced\Blog\Core\BlogService;
8+
9+
class InvalidUserService
10+
{
11+
public function __construct(BlogService $blogService)
12+
{
13+
$blogService->getEntry();
14+
}
15+
}

0 commit comments

Comments
 (0)