@@ -32,9 +32,10 @@ class Project
3232
3333 use LogTrait;
3434
35- public ProjectNamespace $ globalNamespace ;
36-
37- public ProjectNamespace $ rootNamespace ;
35+ /**
36+ * @var array<string, \Cake\ApiDocs\ProjectNamespace>
37+ */
38+ public array $ namespaces ;
3839
3940 protected Loader $ loader ;
4041
@@ -54,8 +55,9 @@ public function __construct(string $projectPath, array $config)
5455 {
5556 $ this ->setConfig ($ config );
5657
57- $ this ->globalNamespace = new ProjectNamespace (null , 'Global ' );
58- $ this ->rootNamespace = new ProjectNamespace ($ this ->_config ['namespace ' ], $ this ->_config ['namespace ' ]);
58+ foreach ((array )$ this ->_config ['namespaces ' ] as $ namespace ) {
59+ $ this ->namespaces [$ namespace ] = new ProjectNamespace ($ namespace );
60+ }
5961
6062 $ this ->loader = new Loader ($ projectPath );
6163 $ this ->classLoader = $ this ->createClassLoader ($ projectPath );
@@ -69,10 +71,11 @@ public function __construct(string $projectPath, array $config)
6971 $ this ->cache [$ node ->qualifiedName ()] = $ node ;
7072 }
7173
72- $ namespace = $ this ->findNamespace ($ node ->context ->namespace );
74+ $ namespace = $ this ->getNamespace ($ node ->context ->namespace );
7375 $ namespace ->addNode ($ node );
7476 }
7577 }
78+ ksort ($ this ->namespaces );
7679
7780 $ this ->mergeInherited ();
7881 }
@@ -131,8 +134,7 @@ protected function mergeInherited(): void
131134 }
132135 };
133136
134- $ namespaceMerger ($ this ->globalNamespace );
135- $ namespaceMerger ($ this ->rootNamespace );
137+ array_walk ($ this ->namespaces , fn ($ namespace ) => $ namespaceMerger ($ namespace ));
136138 }
137139
138140 /**
@@ -188,42 +190,44 @@ protected function createClassLoader(string $projectPath): ?ClassLoader
188190 /**
189191 * Finds or creates project namespace.
190192 *
191- * @param string|null $name Namespace name
193+ * @param string|null $qualifiedName Qualified name
192194 * @return self|null
193195 */
194- protected function findNamespace (?string $ name ): ProjectNamespace
196+ protected function getNamespace (?string $ qualifiedName ): ProjectNamespace
195197 {
196- if ($ name === null ) {
197- return $ this ->globalNamespace ;
198+ if ($ qualifiedName === null ) {
199+ return $ this ->namespaces ['' ] ??= new ProjectNamespace (null );
200+ }
201+
202+ $ namespace = null ;
203+ foreach ($ this ->namespaces as $ root ) {
204+ if (str_starts_with ($ qualifiedName , $ root ->qualifiedName )) {
205+ $ namespace = $ root ;
206+ break ;
207+ }
198208 }
199209
200- if (!str_starts_with ($ name , $ this ->rootNamespace ->name )) {
201- throw new RuntimeException (sprintf (
202- 'Namespace `%s` is not a child of the project namespace `%s`. ' ,
203- $ name ,
204- $ this ->rootNamespace ->name
205- ));
210+ if ($ namespace === null ) {
211+ throw new RuntimeException (sprintf ('Namespace `%s` is part of the project namespaces. ' , $ qualifiedName ));
206212 }
207213
208- $ remainder = substr ($ name , strlen ($ this ->rootNamespace ->name ) + 1 );
209- if (!$ remainder ) {
210- return $ this ->rootNamespace ;
214+ if ($ namespace ->qualifiedName === $ qualifiedName ) {
215+ return $ namespace ;
211216 }
212217
213- $ ns = $ this ->rootNamespace ;
214- $ parts = preg_split ('/ \\\\/ ' , $ remainder );
215- foreach ($ parts as $ part ) {
216- if (isset ($ ns ->children [$ part ])) {
217- $ ns = $ ns ->children [$ part ];
218+ $ names = explode ('\\' , substr ($ qualifiedName , strlen ($ namespace ->qualifiedName ) + 1 ));
219+ foreach ($ names as $ name ) {
220+ if (isset ($ namespace ->children [$ name ])) {
221+ $ namespace = $ namespace ->children [$ name ];
218222 continue ;
219223 }
220224
221- $ ns ->children [$ part ] = new ProjectNamespace ($ ns -> name . '\\' . $ part , $ part );
222- ksort ($ ns ->children );
225+ $ child = $ namespace ->children [$ name ] = new ProjectNamespace ($ namespace -> qualifiedName . '\\' . $ name );
226+ ksort ($ namespace ->children );
223227
224- $ ns = $ ns -> children [ $ part ] ;
228+ $ namespace = $ child ;
225229 }
226230
227- return $ ns ;
231+ return $ namespace ;
228232 }
229233}
0 commit comments