3
3
* Copyright © Magento, Inc. All rights reserved.
4
4
* See COPYING.txt for license details.
5
5
*/
6
+ declare (strict_types=1 );
7
+
6
8
namespace Magento \Setup \Module \Di \Code \Scanner ;
7
9
8
10
use Magento \Framework \Api \Code \Generator \ExtensionAttributesGenerator ;
9
11
use Magento \Framework \Api \Code \Generator \ExtensionAttributesInterfaceGenerator ;
10
12
use Magento \Framework \ObjectManager \Code \Generator \Factory as FactoryGenerator ;
13
+ use Magento \Framework \Reflection \TypeProcessor ;
11
14
use Magento \Setup \Module \Di \Compiler \Log \Log ;
12
- use \Magento \Framework \Reflection \TypeProcessor ;
13
15
14
16
/**
15
- * Class PhpScanner
16
- *
17
- * @package Magento\Setup\Module\Di\Code\Scanner
17
+ * Finds factory and extension attributes classes which require auto-generation.
18
18
*/
19
19
class PhpScanner implements ScannerInterface
20
20
{
@@ -50,18 +50,31 @@ public function __construct(Log $log, TypeProcessor $typeProcessor = null)
50
50
* @param string $entityType
51
51
* @return string[]
52
52
*/
53
- protected function _findMissingClasses ($ file , $ classReflection , $ methodName , $ entityType )
53
+ private function findMissingFactories ($ file , $ classReflection , $ methodName , $ entityType )
54
54
{
55
55
$ missingClasses = [];
56
- if ($ classReflection ->hasMethod ($ methodName )) {
57
- $ constructor = $ classReflection ->getMethod ($ methodName );
58
- $ parameters = $ constructor ->getParameters ();
59
- /** @var $parameter \ReflectionParameter */
60
- foreach ($ parameters as $ parameter ) {
61
- preg_match ('/\[\s\<\w+?>\s([\w \\\\]+)/s ' , $ parameter ->__toString (), $ matches );
62
- if (isset ($ matches [1 ]) && substr ($ matches [1 ], -strlen ($ entityType )) == $ entityType ) {
63
- $ missingClassName = $ matches [1 ];
64
- if ($ this ->shouldGenerateClass ($ missingClassName , $ entityType , $ file )) {
56
+ if (!$ classReflection ->hasMethod ($ methodName )) {
57
+ return $ missingClasses ;
58
+ }
59
+
60
+ $ factorySuffix = '\\' . ucfirst (FactoryGenerator::ENTITY_TYPE );
61
+ $ constructor = $ classReflection ->getMethod ($ methodName );
62
+ $ parameters = $ constructor ->getParameters ();
63
+ /** @var $parameter \ReflectionParameter */
64
+ foreach ($ parameters as $ parameter ) {
65
+ preg_match ('/\[\s\<\w+?>\s([\w \\\\]+)/s ' , $ parameter ->__toString (), $ matches );
66
+ if (isset ($ matches [1 ]) && substr ($ matches [1 ], -strlen ($ entityType )) == $ entityType ) {
67
+ $ missingClassName = $ matches [1 ];
68
+ if ($ this ->shouldGenerateClass ($ missingClassName , $ entityType , $ file )) {
69
+
70
+ if (substr ($ missingClassName , -strlen ($ factorySuffix )) == $ factorySuffix ) {
71
+ $ entityName = rtrim (substr ($ missingClassName , 0 , -strlen ($ factorySuffix )), '\\' );
72
+ $ this ->_log ->add (
73
+ Log::CONFIGURATION_ERROR ,
74
+ $ missingClassName ,
75
+ 'Invalid Factory declaration for class ' . $ entityName . ' in file ' . $ file
76
+ );
77
+ } else {
65
78
$ missingClasses [] = $ missingClassName ;
66
79
}
67
80
}
@@ -110,24 +123,12 @@ protected function getSourceClassName($missingClassName, $entityType)
110
123
*/
111
124
protected function _fetchFactories ($ reflectionClass , $ file )
112
125
{
113
- $ factorySuffix = '\\' . ucfirst (FactoryGenerator::ENTITY_TYPE );
114
- $ absentFactories = $ this ->_findMissingClasses (
126
+ $ absentFactories = $ this ->findMissingFactories (
115
127
$ file ,
116
128
$ reflectionClass ,
117
129
'__construct ' ,
118
130
ucfirst (FactoryGenerator::ENTITY_TYPE )
119
131
);
120
- foreach ($ absentFactories as $ key => $ absentFactory ) {
121
- if (substr ($ absentFactory , -strlen ($ factorySuffix )) == $ factorySuffix ) {
122
- $ entityName = rtrim (substr ($ absentFactory , 0 , -strlen ($ factorySuffix )), '\\' );
123
- $ this ->_log ->add (
124
- Log::CONFIGURATION_ERROR ,
125
- $ absentFactory ,
126
- 'Invalid Factory declaration for class ' . $ entityName . ' in file ' . $ file
127
- );
128
- unset($ absentFactories [$ key ]);
129
- }
130
- }
131
132
return $ absentFactories ;
132
133
}
133
134
@@ -150,21 +151,19 @@ protected function _fetchMissingExtensionAttributesClasses($reflectionClass, $fi
150
151
$ missingClassName = $ returnType ['type ' ];
151
152
if ($ this ->shouldGenerateClass ($ missingClassName , $ entityType , $ file )) {
152
153
$ missingExtensionInterfaces [] = $ missingClassName ;
154
+
155
+ $ extension = rtrim (substr ($ missingClassName , 0 , -strlen ('Interface ' )), '\\' );
156
+ if (!class_exists ($ extension )) {
157
+ $ missingExtensionInterfaces [] = $ extension ;
158
+ }
159
+ $ extensionFactory = $ extension . 'Factory ' ;
160
+ if (!class_exists ($ extensionFactory )) {
161
+ $ missingExtensionInterfaces [] = $ extensionFactory ;
162
+ }
153
163
}
154
164
}
155
- $ missingExtensionClasses = [];
156
- $ missingExtensionFactories = [];
157
- foreach ($ missingExtensionInterfaces as $ missingExtensionInterface ) {
158
- $ extension = rtrim (substr ($ missingExtensionInterface , 0 , -strlen ('Interface ' )), '\\' );
159
- if (!class_exists ($ extension )) {
160
- $ missingExtensionClasses [] = $ extension ;
161
- }
162
- $ extensionFactory = $ extension . 'Factory ' ;
163
- if (!class_exists ($ extensionFactory )) {
164
- $ missingExtensionFactories [] = $ extensionFactory ;
165
- }
166
- }
167
- return array_merge ($ missingExtensionInterfaces , $ missingExtensionClasses , $ missingExtensionFactories );
165
+
166
+ return $ missingExtensionInterfaces ;
168
167
}
169
168
170
169
/**
@@ -178,11 +177,11 @@ public function collectEntities(array $files)
178
177
{
179
178
$ output = [[]];
180
179
foreach ($ files as $ file ) {
181
- $ classes = $ this ->_getDeclaredClasses ($ file );
180
+ $ classes = $ this ->getDeclaredClasses ($ file );
182
181
foreach ($ classes as $ className ) {
183
182
$ reflectionClass = new \ReflectionClass ($ className );
184
- $ output [] = $ this ->_fetchFactories ($ reflectionClass , $ file );
185
- $ output [] = $ this ->_fetchMissingExtensionAttributesClasses ($ reflectionClass , $ file );
183
+ $ output [] = $ this ->_fetchFactories ($ reflectionClass , $ file );
184
+ $ output [] = $ this ->_fetchMissingExtensionAttributesClasses ($ reflectionClass , $ file );
186
185
}
187
186
}
188
187
return array_unique (array_merge (...$ output ));
@@ -211,23 +210,30 @@ protected function _fetchNamespace($tokenIterator, $count, $tokens)
211
210
}
212
211
213
212
/**
214
- * Fetch class names from tokenized PHP file
213
+ * Fetches class name from tokenized PHP file.
215
214
*
216
215
* @param string $namespace
217
216
* @param int $tokenIterator
218
217
* @param int $count
219
218
* @param array $tokens
220
- * @return array
219
+ * @return string|null
221
220
*/
222
- protected function _fetchClasses ($ namespace , $ tokenIterator , $ count , $ tokens )
221
+ private function fetchClass ($ namespace , $ tokenIterator , $ count , $ tokens ):? string
223
222
{
224
- $ classes = [];
223
+ // anonymous classes should be omitted
224
+ if (is_array ($ tokens [$ tokenIterator - 2 ]) && $ tokens [$ tokenIterator - 2 ][0 ] === T_NEW ) {
225
+ return null ;
226
+ }
227
+
225
228
for ($ tokenOffset = $ tokenIterator + 1 ; $ tokenOffset < $ count ; ++$ tokenOffset ) {
226
- if ($ tokens [$ tokenOffset ] = == '{ ' ) {
227
- $ classes [] = $ namespace . "\\" . $ tokens [ $ tokenIterator + 2 ][ 1 ] ;
229
+ if ($ tokens [$ tokenOffset ] ! == '{ ' ) {
230
+ continue ;
228
231
}
232
+
233
+ return $ namespace . "\\" . $ tokens [$ tokenIterator + 2 ][1 ];
229
234
}
230
- return $ classes ;
235
+
236
+ return null ;
231
237
}
232
238
233
239
/**
@@ -236,9 +242,9 @@ protected function _fetchClasses($namespace, $tokenIterator, $count, $tokens)
236
242
* @param string $file
237
243
* @return array
238
244
*/
239
- protected function _getDeclaredClasses ($ file )
245
+ private function getDeclaredClasses ($ file ): array
240
246
{
241
- $ classes = [[] ];
247
+ $ classes = [];
242
248
$ namespaceParts = [];
243
249
// phpcs:ignore
244
250
$ tokens = token_get_all (file_get_contents ($ file ));
@@ -252,10 +258,13 @@ protected function _getDeclaredClasses($file)
252
258
if (($ tokens [$ tokenIterator ][0 ] == T_CLASS || $ tokens [$ tokenIterator ][0 ] == T_INTERFACE )
253
259
&& $ tokens [$ tokenIterator - 1 ][0 ] != T_DOUBLE_COLON
254
260
) {
255
- $ classes [] = $ this ->_fetchClasses (join ('' , $ namespaceParts ), $ tokenIterator , $ count , $ tokens );
261
+ $ class = $ this ->fetchClass (join ('' , $ namespaceParts ), $ tokenIterator , $ count , $ tokens );
262
+ if ($ class !== null && !in_array ($ class , $ classes )) {
263
+ $ classes [] = $ class ;
264
+ }
256
265
}
257
266
}
258
- return array_unique ( array_merge (... $ classes)) ;
267
+ return $ classes ;
259
268
}
260
269
261
270
/**
0 commit comments