@@ -52,18 +52,29 @@ public function process(File $file, $position)
5252 $ entityType = $ code === T_TRAIT ? 'trait ' : 'interface ' ;
5353 }
5454
55- $ this ->exclude = $ this ->normalizeExcluded ($ this ->exclude );
55+ if (!$ this ->psr4 || !is_array ($ this ->psr4 )) {
56+ $ this ->checkFilenameOnly ($ file , $ position , $ className , $ entityType );
5657
57- $ validNamespace = is_array ($ this ->psr4 ) && $ this ->psr4
58- ? $ this ->checkNamespace ($ file , $ position , $ entityType , $ className )
59- : true ;
60-
61- if (!$ validNamespace ) {
6258 return ;
6359 }
6460
65- $ fileName = basename ($ file ->getFilename ());
66- if ($ fileName === "{$ className }.php " ) {
61+ $ this ->exclude = is_array ($ this ->exclude ) ? $ this ->normalizeExcluded ($ this ->exclude ) : [];
62+ $ this ->checkPsr4 ($ file , $ position , $ entityType , $ className );
63+ }
64+
65+ /**
66+ * @param File $file
67+ * @param int $position
68+ * @param string $className
69+ * @param string $entityType
70+ */
71+ private function checkFilenameOnly (
72+ File $ file ,
73+ int $ position ,
74+ string $ className ,
75+ string $ entityType
76+ ) {
77+ if (basename ($ file ->getFilename ()) === "{$ className }.php " ) {
6778 return ;
6879 }
6980
@@ -72,7 +83,7 @@ public function process(File $file, $position)
7283 "File containing %s '%s' is named '%s' instead of '%s'. " ,
7384 $ entityType ,
7485 $ className ,
75- $ fileName ,
86+ $ file -> getFilename () ,
7687 "{$ className }.php "
7788 ),
7889 $ position ,
@@ -87,55 +98,57 @@ public function process(File $file, $position)
8798 * @param string $className
8899 * @return bool
89100 */
90- private function checkNamespace (
101+ private function checkPsr4 (
91102 File $ file ,
92103 int $ position ,
93104 string $ entityType ,
94105 string $ className
95106 ) {
96107
97- list ($ namespacePos , $ namespace ) = PhpcsHelpers::findNamespace ($ file , $ position );
108+ list (, $ namespace ) = PhpcsHelpers::findNamespace ($ file , $ position );
98109
99110 $ fullyQualifiedName = "{$ namespace }\\{$ className }" ;
100111 if (in_array ($ fullyQualifiedName , $ this ->exclude , true )) {
101112 return true ;
102113 }
103114
104- list ( $ baseNamespace , $ baseFolder ) = $ this -> classPsr4Info ( $ namespace );
115+ $ filePath = str_replace ( '\\' , ' / ' , $ file -> getFilename () );
105116
106- if (!$ baseNamespace || !$ namespacePos ) {
107- $ file ->addError (
108- sprintf (
109- "Namespace '%s' is not compliant with given PSR-4 configuration. " ,
110- $ namespace
111- ),
112- $ namespacePos ,
113- 'NotInPSR4 '
114- );
117+ foreach ($ this ->psr4 as $ baseNamespace => $ folder ) {
118+ $ baseNamespace = trim ($ baseNamespace , '\\' );
119+ if (strpos ($ namespace , $ baseNamespace ) !== 0 ) {
120+ continue ;
121+ }
115122
116- return false ;
117- }
123+ $ folder = trim (str_replace ('\\' , '/ ' , $ folder ), './ ' );
124+ $ folderSplit = explode ("/ {$ folder }/ " , $ filePath );
125+ if (count ($ folderSplit ) < 2 ) {
126+ continue ;
127+ }
118128
119- $ namespaceRemain = trim (substr ($ namespace , strlen ($ baseNamespace )), '\\' );
120- $ expectedDirChunks = explode ('\\' , $ namespaceRemain );
121- array_unshift ($ expectedDirChunks , $ baseFolder );
129+ $ relativePath = array_pop ($ folderSplit );
130+ if (basename ($ relativePath ) !== "{$ className }.php " ) {
131+ continue ;
132+ }
122133
123- $ classPath = dirname ($ file ->getFilename ());
124- $ classDirChunks = explode ('/ ' , str_replace ('\\' , '/ ' , $ classPath ));
125- $ actualDirChunks = array_slice ($ classDirChunks , -1 * count ($ expectedDirChunks ));
134+ $ relativeNamespace = str_replace ('/ ' , '\\' , dirname ($ relativePath ));
135+ $ expectedNamespace = $ relativeNamespace === '. '
136+ ? $ baseNamespace
137+ : "{$ baseNamespace }\\{$ relativeNamespace }" ;
126138
127- if ($ expectedDirChunks === $ actualDirChunks ) {
128- return true ;
139+ if ("{$ expectedNamespace }\\{$ className }" === "{$ namespace }\\{$ className }" ) {
140+ return true ;
141+ }
129142 }
130143
131144 $ file ->addError (
132145 sprintf (
133- "%s '%s', located in folder '%s', is not compliant with PSR-4 configuration. " ,
146+ "%s '%s', located at '%s', is not compliant with PSR-4 configuration. " ,
134147 ucfirst ($ entityType ),
135148 $ fullyQualifiedName ,
136- $ classPath
149+ $ filePath
137150 ),
138- $ namespacePos ,
151+ $ position ,
139152 'InvalidPSR4 '
140153 );
141154
@@ -155,24 +168,4 @@ function (string $className): string {
155168 $ excluded
156169 );
157170 }
158-
159- /**
160- * @param string $namespace
161- * @return array
162- */
163- private function classPsr4Info (string $ namespace ): array
164- {
165- $ classBaseNamespace = null ;
166- $ classBaseFolder = null ;
167- foreach ($ this ->psr4 as $ baseNamespace => $ folder ) {
168- $ baseNamespace = trim ($ baseNamespace , '\\' );
169- if (strpos ($ namespace , $ baseNamespace ) === 0 ) {
170- $ classBaseNamespace = $ baseNamespace ;
171- $ classBaseFolder = trim (str_replace ('\\' , '/ ' , $ folder ), './ ' );
172- break ;
173- }
174- }
175-
176- return [$ classBaseNamespace , $ classBaseFolder ];
177- }
178171}
0 commit comments