22
33namespace think \annotation ;
44
5- use Ergebnis \Classy \Constructs ;
65use ReflectionClass ;
76use ReflectionMethod ;
87use think \annotation \route \Group ;
@@ -56,7 +55,7 @@ protected function registerAnnotationRoute()
5655 }
5756
5857 if (is_dir ($ dir )) {
59- $ this ->scanDir ($ dir , $ options );
58+ $ this ->scanDir (realpath ( $ dir) , $ options );
6059 }
6160 }
6261 });
@@ -66,8 +65,36 @@ protected function registerAnnotationRoute()
6665 protected function scanDir ($ dir , $ options = [])
6766 {
6867 $ groups = [];
69- foreach (Constructs::fromDirectory ($ dir ) as $ construct ) {
70- $ class = $ construct ->name ();
68+
69+ $ iterator = new \RecursiveIteratorIterator (new \RecursiveDirectoryIterator (
70+ $ dir ,
71+ \FilesystemIterator::FOLLOW_SYMLINKS ,
72+ ));
73+
74+ $ namespace = Arr::pull ($ options , 'namespace ' ) ?: $ this ->getNamespace ($ dir , $ this ->controllerDir , "{$ this ->app ->getNamespace ()}\\controller " );
75+
76+ if (empty ($ namespace )) {
77+ return ;
78+ }
79+
80+ foreach ($ iterator as $ fileInfo ) {
81+ /** @var \SplFileInfo $fileInfo */
82+ if (!$ fileInfo ->isFile ()) {
83+ continue ;
84+ }
85+
86+ if ($ fileInfo ->getBasename ('.php ' ) === $ fileInfo ->getBasename ()) {
87+ continue ;
88+ }
89+
90+ $ filename = $ fileInfo ->getRealPath ();
91+
92+ $ classNamespace = $ this ->getNamespace (dirname ($ filename ), $ dir , $ namespace );
93+ if (empty ($ namespace )) {
94+ continue ;
95+ }
96+
97+ $ class = "\\{$ classNamespace }\\{$ fileInfo ->getBasename ('.php ' )}" ;
7198
7299 if (in_array ($ class , $ this ->parsedClass )) {
73100 continue ;
@@ -81,8 +108,6 @@ protected function scanDir($dir, $options = [])
81108 continue ;
82109 }
83110
84- $ filename = $ construct ->fileNames ()[0 ];
85-
86111 $ prefix = $ class ;
87112
88113 if (Str::startsWith ($ filename , $ this ->controllerDir )) {
@@ -180,4 +205,37 @@ protected function scanDir($dir, $options = [])
180205 }
181206 }
182207
208+ /**
209+ * Calculate the namespace based on the relative path between directories
210+ *
211+ * @param string $dir The directory to get the namespace for
212+ * @param string $base The base directory
213+ * @param string $baseNamespace The base namespace
214+ * @return string|null The calculated namespace or null if $dir is not a subdirectory of $base
215+ */
216+ protected function getNamespace ($ dir , $ base , $ baseNamespace )
217+ {
218+ // Normalize directory separators
219+ $ dir = rtrim (str_replace ('\\' , '/ ' , $ dir ), '/ ' ) . '/ ' ;
220+ $ base = rtrim (str_replace ('\\' , '/ ' , $ base ), '/ ' ) . '/ ' ;
221+
222+ // Check if $dir is a subdirectory of $base
223+ if (!str_starts_with ($ dir , $ base )) {
224+ return null ;
225+ }
226+
227+ // Get the relative path
228+ $ relativePath = substr ($ dir , strlen ($ base ));
229+
230+ // If the relative path is empty, return the base namespace
231+ if (empty ($ relativePath ) || $ relativePath === '/ ' ) {
232+ return $ baseNamespace ;
233+ }
234+
235+ // Convert directory separators to namespace separators
236+ $ namespace = str_replace ('/ ' , '\\' , rtrim ($ relativePath , '/ ' ));
237+
238+ // Combine with the base namespace
239+ return $ baseNamespace . '\\' . $ namespace ;
240+ }
183241}
0 commit comments