3
3
4
4
namespace Arkitect \RuleBuilders \Architecture ;
5
5
6
- use Arkitect \Expression \Boolean \Andx ;
7
- use Arkitect \Expression \Boolean \Not ;
6
+ use Arkitect \Expression \Boolean \Orx ;
8
7
use Arkitect \Expression \Expression ;
9
- use Arkitect \Expression \ForClasses \DependsOnlyOnTheseNamespaces ;
10
- use Arkitect \Expression \ForClasses \NotDependsOnTheseNamespaces ;
8
+ use Arkitect \Expression \ForClasses \DependsOnlyOnTheseExpressions ;
11
9
use Arkitect \Expression \ForClasses \ResideInOneOfTheseNamespaces ;
12
10
use Arkitect \Rules \Rule ;
13
11
14
12
class Architecture implements Component, DefinedBy, Where, MayDependOnComponents, MayDependOnAnyComponent, ShouldNotDependOnAnyComponent, ShouldOnlyDependOnComponents, Rules
15
13
{
16
14
/** @var string */
17
15
private $ componentName ;
18
- /** @var array<string, string> */
16
+ /** @var array<string, Expression| string> */
19
17
private $ componentSelectors ;
20
18
/** @var array<string, string[]> */
21
19
private $ allowedDependencies ;
22
20
/** @var array<string, string[]> */
23
- private $ componentDependsOnlyOnTheseNamespaces ;
21
+ private $ componentDependsOnlyOnTheseComponents ;
24
22
25
23
private function __construct ()
26
24
{
27
25
$ this ->componentName = '' ;
28
26
$ this ->componentSelectors = [];
29
27
$ this ->allowedDependencies = [];
30
- $ this ->componentDependsOnlyOnTheseNamespaces = [];
28
+ $ this ->componentDependsOnlyOnTheseComponents = [];
31
29
}
32
30
33
31
public static function withComponents (): Component
@@ -72,7 +70,7 @@ public function shouldNotDependOnAnyComponent()
72
70
73
71
public function shouldOnlyDependOnComponents (string ...$ componentNames )
74
72
{
75
- $ this ->componentDependsOnlyOnTheseNamespaces [$ this ->componentName ] = $ componentNames ;
73
+ $ this ->componentDependsOnlyOnTheseComponents [$ this ->componentName ] = $ componentNames ;
76
74
77
75
return $ this ;
78
76
}
@@ -93,63 +91,61 @@ public function mayDependOnAnyComponent()
93
91
94
92
public function rules (): iterable
95
93
{
96
- $ layerNames = array_keys ($ this ->componentSelectors );
97
-
98
94
foreach ($ this ->componentSelectors as $ name => $ selector ) {
99
95
if (isset ($ this ->allowedDependencies [$ name ])) {
100
- $ forbiddenComponents = array_diff ($ layerNames , [$ name ], $ this ->allowedDependencies [$ name ]);
101
-
102
- if (!empty ($ forbiddenComponents )) {
103
- yield Rule::allClasses ()
104
- ->that (\is_string ($ selector ) ? new ResideInOneOfTheseNamespaces ($ selector ) : $ selector )
105
- ->should ($ this ->createForbiddenExpression ($ forbiddenComponents ))
106
- ->because ('of component architecture ' );
107
- }
96
+ yield Rule::allClasses ()
97
+ ->that (\is_string ($ selector ) ? new ResideInOneOfTheseNamespaces ($ selector ) : $ selector )
98
+ ->should ($ this ->createAllowedExpression (
99
+ array_merge ([$ name ], $ this ->allowedDependencies [$ name ])
100
+ ))
101
+ ->because ('of component architecture ' );
108
102
}
109
103
110
- if (!isset ($ this ->componentDependsOnlyOnTheseNamespaces [$ name ])) {
111
- continue ;
104
+ if (isset ($ this ->componentDependsOnlyOnTheseComponents [$ name ])) {
105
+ yield Rule::allClasses ()
106
+ ->that (\is_string ($ selector ) ? new ResideInOneOfTheseNamespaces ($ selector ) : $ selector )
107
+ ->should ($ this ->createAllowedExpression ($ this ->componentDependsOnlyOnTheseComponents [$ name ]))
108
+ ->because ('of component architecture ' );
112
109
}
110
+ }
111
+ }
113
112
114
- $ allowedDependencies = array_map (function (string $ componentName ): string {
115
- return $ this ->componentSelectors [$ componentName ];
116
- }, $ this ->componentDependsOnlyOnTheseNamespaces [$ name ]);
113
+ private function createAllowedExpression (array $ components ): Expression
114
+ {
115
+ $ namespaceSelectors = $ this ->extractComponentsNamespaceSelectors ($ components );
116
+
117
+ $ expressionSelectors = $ this ->extractComponentExpressionSelectors ($ components );
118
+
119
+ if ([] === $ namespaceSelectors && [] === $ expressionSelectors ) {
120
+ return new Orx (); // always true
121
+ }
117
122
118
- yield Rule::allClasses ()
119
- ->that (new ResideInOneOfTheseNamespaces ($ selector ))
120
- ->should (new DependsOnlyOnTheseNamespaces (...$ allowedDependencies ))
121
- ->because ('of component architecture ' );
123
+ if ([] !== $ namespaceSelectors ) {
124
+ $ expressionSelectors [] = new ResideInOneOfTheseNamespaces (...$ namespaceSelectors );
122
125
}
126
+
127
+ return new DependsOnlyOnTheseExpressions (...$ expressionSelectors );
123
128
}
124
129
125
- public function createForbiddenExpression (array $ forbiddenComponents ): Expression
130
+ private function extractComponentsNamespaceSelectors (array $ components ): array
126
131
{
127
- $ forbiddenNamespaceSelectors = array_filter (
132
+ return array_filter (
128
133
array_map (function (string $ componentName ): ?string {
129
134
$ selector = $ this ->componentSelectors [$ componentName ];
130
135
131
136
return \is_string ($ selector ) ? $ selector : null ;
132
- }, $ forbiddenComponents )
137
+ }, $ components )
133
138
);
139
+ }
134
140
135
- $ forbiddenExpressionSelectors = array_filter (
141
+ private function extractComponentExpressionSelectors (array $ components ): array
142
+ {
143
+ return array_filter (
136
144
array_map (function (string $ componentName ): ?Expression {
137
145
$ selector = $ this ->componentSelectors [$ componentName ];
138
146
139
147
return \is_string ($ selector ) ? null : $ selector ;
140
- }, $ forbiddenComponents )
148
+ }, $ components )
141
149
);
142
-
143
- $ forbiddenExpressionList = [];
144
- if ([] !== $ forbiddenNamespaceSelectors ) {
145
- $ forbiddenExpressionList [] = new NotDependsOnTheseNamespaces (...$ forbiddenNamespaceSelectors );
146
- }
147
- if ([] !== $ forbiddenExpressionSelectors ) {
148
- $ forbiddenExpressionList [] = new Not (new Andx (...$ forbiddenExpressionSelectors ));
149
- }
150
-
151
- return 1 === \count ($ forbiddenExpressionList )
152
- ? array_pop ($ forbiddenExpressionList )
153
- : new Andx (...$ forbiddenExpressionList );
154
150
}
155
151
}
0 commit comments