11
11
12
12
use Magento \Framework \App \Utility \Files ;
13
13
use Magento \Framework \Config \Reader \Filesystem as ConfigReader ;
14
+ use Magento \Framework \Exception \ConfigurationMismatchException ;
14
15
use Magento \Framework \Exception \LocalizedException ;
15
16
use Magento \Framework \UrlInterface ;
16
17
use Magento \TestFramework \Dependency \Reader \ClassScanner ;
17
18
use Magento \TestFramework \Dependency \Route \RouteMapper ;
18
19
use Magento \TestFramework \Exception \NoSuchActionException ;
19
- use Magento \Test \Integrity \Dependency \Converter ;
20
- use PHPUnit \Framework \Exception ;
20
+ use Magento \TestFramework \Inspection \Exception ;
21
21
22
22
/**
23
23
* Rule to check the dependencies between modules based on references, getUrl and layout blocks
@@ -308,30 +308,28 @@ private function isPluginDependency($dependent, $dependency)
308
308
* @param string $file
309
309
* @return array
310
310
* @throws LocalizedException
311
- * @throws \Exception
312
- * @SuppressWarnings(PMD.CyclomaticComplexity)
313
311
*/
314
312
protected function _caseGetUrl (string $ currentModule , string &$ contents , string $ file ): array
315
313
{
316
314
$ dependencies = [];
317
- $ pattern = '#(\->|:)(?<source>getUrl\(([ \'"])(?<path>[a-zA-Z0-9\-_*\ /]+)\3)\s*[,)]# ' ;
315
+ $ pattern = '#(\->|:)(?<source>getUrl\(([ \'"])(?<path>[a-zA-Z0-9\-_*/]+)\3)\s*[,)]# ' ;
318
316
if (!preg_match_all ($ pattern , $ contents , $ matches , PREG_SET_ORDER )) {
319
317
return $ dependencies ;
320
318
}
321
319
try {
322
320
foreach ($ matches as $ item ) {
323
321
$ path = $ item ['path ' ];
324
- $ returnedDependencies = [];
322
+ $ modules = [];
325
323
if (strpos ($ path , '* ' ) !== false ) {
326
- $ returnedDependencies = $ this ->processWildcardUrl ($ path , $ file );
324
+ $ modules = $ this ->processWildcardUrl ($ path , $ file );
327
325
} elseif (preg_match ('#rest(?<service>/V1/.+)#i ' , $ path , $ apiMatch )) {
328
- $ returnedDependencies = $ this ->processApiUrl ($ apiMatch ['service ' ]);
326
+ $ modules = $ this ->processApiUrl ($ apiMatch ['service ' ]);
329
327
} else {
330
- $ returnedDependencies = $ this ->processStandardUrl ($ path );
328
+ $ modules = $ this ->processStandardUrl ($ path );
331
329
}
332
- if ($ returnedDependencies && !in_array ($ currentModule , $ returnedDependencies )) {
330
+ if ($ modules && !in_array ($ currentModule , $ modules )) {
333
331
$ dependencies [] = [
334
- 'modules ' => $ returnedDependencies ,
332
+ 'modules ' => $ modules ,
335
333
'type ' => RuleInterface::TYPE_HARD ,
336
334
'source ' => $ item ['source ' ],
337
335
];
@@ -352,55 +350,43 @@ protected function _caseGetUrl(string $currentModule, string &$contents, string
352
350
* @param string $filePath
353
351
* @return string[]
354
352
* @throws NoSuchActionException
355
- * @SuppressWarnings(PMD.CyclomaticComplexity)
356
353
*/
357
354
private function processWildcardUrl (string $ urlPath , string $ filePath )
358
355
{
359
356
$ filePath = strtolower ($ filePath );
360
357
$ urlRoutePieces = explode ('/ ' , $ urlPath );
361
358
$ routeId = array_shift ($ urlRoutePieces );
362
-
363
359
//Skip route wildcard processing as this requires using the routeMapper
364
360
if ('* ' === $ routeId ) {
365
361
return [];
366
362
}
367
- $ filePathInfo = pathinfo ($ filePath );
368
- $ fileActionName = $ filePathInfo ['filename ' ];
369
- $ filePathPieces = explode (DIRECTORY_SEPARATOR , $ filePathInfo ['dirname ' ]);
370
363
371
364
/**
372
365
* Only handle Controllers. ie: Ignore Blocks, Templates, and Models due to complexity in static resolution
373
366
* of route
374
367
*/
375
- if (in_array ('block ' , $ filePathPieces )
376
- || in_array ('model ' , $ filePathPieces )
377
- || $ filePathInfo ['extension ' ] === 'phtml '
378
- ) {
368
+ if (!preg_match (
369
+ '#controller/(adminhtml/)?(?<controller_name>.+)/(?<action_name>\w+).php$# ' ,
370
+ $ filePath ,
371
+ $ fileParts
372
+ )) {
379
373
return [];
380
374
}
381
- $ fileControllerIndex = array_search ('adminhtml ' , $ filePathPieces , true );
382
- if ($ fileControllerIndex === false ) {
383
- $ fileControllerIndex = array_search ('controller ' , $ filePathPieces , true );
384
- }
385
375
386
376
$ controllerName = array_shift ($ urlRoutePieces );
387
377
if ('* ' === $ controllerName ) {
388
- $ fileControllerName = implode ("_ " , array_slice ($ filePathPieces , $ fileControllerIndex + 1 ));
389
- $ controllerName = $ fileControllerName ;
378
+ $ controllerName = str_replace ('/ ' , '_ ' , $ fileParts ['controller_name ' ]);
390
379
}
391
380
392
381
if (empty ($ urlRoutePieces ) || !$ urlRoutePieces [0 ]) {
393
- return $ this ->routeMapper ->getDependencyByRoutePath (
394
- $ routeId ,
395
- $ controllerName ,
396
- UrlInterface::DEFAULT_ACTION_NAME
397
- );
382
+ $ actionName = UrlInterface::DEFAULT_ACTION_NAME ;
383
+ } else {
384
+ $ actionName = array_shift ($ urlRoutePieces );
385
+ if ('* ' === $ actionName ) {
386
+ $ actionName = $ fileParts ['action_name ' ];
387
+ }
398
388
}
399
389
400
- $ actionName = array_shift ($ urlRoutePieces );
401
- if ('* ' === $ actionName ) {
402
- $ actionName = $ fileActionName ;
403
- }
404
390
return $ this ->routeMapper ->getDependencyByRoutePath (
405
391
$ routeId ,
406
392
$ controllerName ,
@@ -418,7 +404,7 @@ private function processWildcardUrl(string $urlPath, string $filePath)
418
404
private function processStandardUrl (string $ path )
419
405
{
420
406
$ pattern = '#(?<route_id>[a-z0-9\-_]{3,}) '
421
- . '\/? (?<controller_name>[a-z0-9\-_]+)?\/? (?<action_name>[a-z0-9\-_]+)?#i ' ;
407
+ . '(/ (?<controller_name>[a-z0-9\-_]+))?(/ (?<action_name>[a-z0-9\-_]+) )?#i ' ;
422
408
if (!preg_match ($ pattern , $ path , $ match )) {
423
409
throw new NoSuchActionException ('Failed to parse standard url path: ' . $ path );
424
410
}
@@ -434,30 +420,37 @@ private function processStandardUrl(string $path)
434
420
}
435
421
436
422
/**
437
- * Helper method to get module dependencies used by an API URL
438
- *
439
- * @param string $path
440
- * @return string[]
441
- *
442
- * @throws NoSuchActionException
423
+ * Create regex patterns from service url paths
424
+ * @return array
443
425
*/
444
- private function processApiUrl ( string $ path ): array
426
+ private function getServiceMethodRegexps ( ): array
445
427
{
446
- /**
447
- * Create regex patterns from service url paths
448
- */
449
428
if (!$ this ->serviceMethods ) {
450
429
$ this ->serviceMethods = [];
451
430
$ serviceRoutes = $ this ->configReader ->read ()['routes ' ];
452
431
foreach ($ serviceRoutes as $ serviceRouteUrl => $ methods ) {
453
432
$ pattern = '#:\w+# ' ;
454
- $ replace = '\w ' ;
433
+ $ replace = '\w+ ' ;
455
434
$ serviceRouteUrlRegex = preg_replace ($ pattern , $ replace , $ serviceRouteUrl );
456
- $ serviceRouteUrlRegex = '# ' . $ serviceRouteUrlRegex . '# ' ;
435
+ $ serviceRouteUrlRegex = '#^ ' . $ serviceRouteUrlRegex . '$ # ' ;
457
436
$ this ->serviceMethods [$ serviceRouteUrlRegex ] = $ methods ;
458
437
}
459
438
}
460
- foreach ($ this ->serviceMethods as $ serviceRouteUrlRegex => $ methods ) {
439
+ return $ this ->serviceMethods ;
440
+ }
441
+
442
+ /**
443
+ * Helper method to get module dependencies used by an API URL
444
+ *
445
+ * @param string $path
446
+ * @return string[]
447
+ *
448
+ * @throws NoSuchActionException
449
+ * @throws Exception
450
+ */
451
+ private function processApiUrl (string $ path ): array
452
+ {
453
+ foreach ($ this ->getServiceMethodRegexps () as $ serviceRouteUrlRegex => $ methods ) {
461
454
/**
462
455
* Since we expect that every service method should be within the same module, we can use the class from
463
456
* any method
@@ -467,10 +460,10 @@ private function processApiUrl(string $path): array
467
460
468
461
$ className = $ method ['service ' ]['class ' ];
469
462
//get module from className
470
- if (preg_match ('#(?<module>\w+[ \\\]\w+).* # ' , $ className , $ match )) {
463
+ if (preg_match ('#^ (?<module>\w+[ \\\]\w+)# ' , $ className , $ match )) {
471
464
return [$ match ['module ' ]];
472
465
}
473
- throw new Exception ('Failed to parse class from className ' . $ className );
466
+ throw new Exception ('Failed to parse class from className: ' . $ className );
474
467
}
475
468
}
476
469
throw new NoSuchActionException ('Failed to match service with url path: ' . $ path );
0 commit comments