@@ -80,8 +80,14 @@ private function discover(callable $cb): array
80
80
);
81
81
82
82
try {
83
+ $ path = $ appPath .DIRECTORY_SEPARATOR .$ relativePath ;
84
+
85
+ if (! $ this ->fileHasClassLike ($ path )) {
86
+ continue ;
87
+ }
88
+
83
89
if (class_exists ($ className )) {
84
- self ::$ classes [$ className ] = $ appPath . DIRECTORY_SEPARATOR . $ relativePath ;
90
+ self ::$ classes [$ className ] = $ path ;
85
91
}
86
92
} catch (\Throwable ) {
87
93
// Ignore exceptions and errors from class loading/reflection
@@ -98,6 +104,38 @@ private function discover(callable $cb): array
98
104
return $ classes ;
99
105
}
100
106
107
+ public function fileHasClassLike (string $ path ): bool
108
+ {
109
+ static $ cache = [];
110
+
111
+ if (isset ($ cache [$ path ])) {
112
+ return $ cache [$ path ];
113
+ }
114
+
115
+ $ code = file_get_contents ($ path );
116
+ if ($ code === false ) {
117
+ return $ cache [$ path ] = false ;
118
+ }
119
+
120
+ if (stripos ($ code , 'class ' ) === false
121
+ && stripos ($ code , 'interface ' ) === false
122
+ && stripos ($ code , 'trait ' ) === false
123
+ && stripos ($ code , 'enum ' ) === false ) {
124
+ return $ cache [$ path ] = false ;
125
+ }
126
+
127
+ $ tokens = token_get_all ($ code );
128
+ foreach ($ tokens as $ token ) {
129
+ if (is_array ($ token )) {
130
+ if (in_array ($ token [0 ], [T_CLASS , T_INTERFACE , T_TRAIT , T_ENUM ], true )) {
131
+ return $ cache [$ path ] = true ;
132
+ }
133
+ }
134
+ }
135
+
136
+ return $ cache [$ path ] = false ;
137
+ }
138
+
101
139
public function shouldEnforceStrictTypes (): bool
102
140
{
103
141
if (empty ($ this ->modelPaths )) {
0 commit comments