184 lines
6.0 KiB
PHP
Executable File
184 lines
6.0 KiB
PHP
Executable File
<?php
|
|
/**
|
|
* Copyright © Magento, Inc. All rights reserved.
|
|
* See COPYING.txt for license details.
|
|
*/
|
|
namespace Magento\Test\Integrity\Library;
|
|
|
|
use Laminas\Code\Reflection\ClassReflection;
|
|
use Laminas\Code\Reflection\Exception\InvalidArgumentException;
|
|
use Magento\Framework\App\Utility\Files;
|
|
use Magento\Framework\Component\ComponentRegistrar;
|
|
use Magento\Setup\Module\Di\Code\Reader\FileClassScanner;
|
|
use Magento\TestFramework\Integrity\Library\Injectable;
|
|
use Magento\TestFramework\Integrity\Library\PhpParser\ParserFactory;
|
|
use Magento\TestFramework\Integrity\Library\PhpParser\Tokens;
|
|
use PHPUnit\Framework\TestCase;
|
|
|
|
/**
|
|
* Test check if Magento library components contain incorrect dependencies to application layer
|
|
*
|
|
*/
|
|
class DependencyTest extends TestCase
|
|
{
|
|
/**
|
|
* Collect errors
|
|
*
|
|
* @var array
|
|
*/
|
|
protected $errors = [];
|
|
|
|
/**
|
|
* Allowed sub namespaces
|
|
*
|
|
* @return array
|
|
*/
|
|
protected function getAllowedNamespaces()
|
|
{
|
|
return [
|
|
'Framework',
|
|
'SomeModule',
|
|
'ModuleName',
|
|
'Setup\Console\CommandList',
|
|
'Setup\Console\CompilerPreparation',
|
|
'Setup\Model\ObjectManagerProvider',
|
|
'Setup\Mvc\Bootstrap\InitParamListener',
|
|
'Store\Model\ScopeInterface',
|
|
'Store\Model\StoreManagerInterface',
|
|
'Directory\Model\CurrencyFactory',
|
|
'PageCache\Model\Cache\Type',
|
|
'Backup\Model\ResourceModel\Db',
|
|
'Backend\Block\Widget\Button',
|
|
'Ui\Component\Container',
|
|
'SalesRule\Model\Rule',
|
|
'SalesRule\Api\Data\RuleInterface',
|
|
'SalesRule\Model\Rule\Interceptor',
|
|
'SalesRule\Model\Rule\Proxy',
|
|
'Theme\Model\View\Design'
|
|
];
|
|
}
|
|
|
|
public function testCheckDependencies(): void
|
|
{
|
|
$invoker = new \Magento\Framework\App\Utility\AggregateInvoker($this);
|
|
$invoker(
|
|
/**
|
|
* @param string $file
|
|
*/
|
|
function ($file) {
|
|
$this->errors = [];
|
|
$componentRegistrar = new ComponentRegistrar();
|
|
$reflectedFilePath = $this->getFilePath($file);
|
|
$tokens = new Tokens(file_get_contents($reflectedFilePath), new ParserFactory());
|
|
$tokens->parseContent();
|
|
|
|
$fileScanner = new FileClassScanner($file);
|
|
$className = $fileScanner->getClassName();
|
|
if ($className) { // could be not a class but just a php-file
|
|
$class = new ClassReflection($className);
|
|
$classUses = (new Injectable())->getDependencies($class);
|
|
} else {
|
|
$classUses = [];
|
|
}
|
|
|
|
$dependencies = array_merge(
|
|
$classUses,
|
|
$tokens->getDependencies()
|
|
);
|
|
$allowedNamespaces = str_replace('\\', '\\\\', implode('|', $this->getAllowedNamespaces()));
|
|
$pattern = '#Magento\\\\(?!' . $allowedNamespaces . ').*#';
|
|
foreach ($dependencies as $dependency) {
|
|
$dependencyPaths = explode('\\', $dependency);
|
|
$dependencyPaths = array_slice($dependencyPaths, 2);
|
|
$dependencyPath = implode('\\', $dependencyPaths);
|
|
$libraryPaths = $componentRegistrar->getPaths(ComponentRegistrar::LIBRARY);
|
|
foreach ($libraryPaths as $libraryPath) {
|
|
$filePath = str_replace('\\', '/', $libraryPath . '/' . $dependencyPath . '.php');
|
|
if (preg_match($pattern, $dependency) && !file_exists($filePath)) {
|
|
$this->errors[basename($reflectedFilePath)][] = $dependency;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!empty($this->errors)) {
|
|
$this->fail($this->getFailMessage());
|
|
}
|
|
},
|
|
$this->libraryDataProvider()
|
|
);
|
|
}
|
|
|
|
/**
|
|
* copied from laminas-code 3.5.1
|
|
*
|
|
* @param string $filename
|
|
*
|
|
* @return string
|
|
*/
|
|
private function getFilePath(string $filename): string
|
|
{
|
|
if (($fileRealPath = realpath($filename)) === false) {
|
|
$fileRealPath = stream_resolve_include_path($filename);
|
|
}
|
|
|
|
if (! $fileRealPath) {
|
|
throw new InvalidArgumentException(sprintf(
|
|
'No file for %s was found.',
|
|
$filename
|
|
));
|
|
}
|
|
|
|
return $fileRealPath;
|
|
}
|
|
|
|
/**
|
|
* @inheritdoc
|
|
*/
|
|
protected function tearDown(): void
|
|
{
|
|
$this->errors = [];
|
|
}
|
|
|
|
/**
|
|
* Prepare failed message
|
|
*
|
|
* @return string
|
|
*/
|
|
protected function getFailMessage()
|
|
{
|
|
$failMessage = '';
|
|
foreach ($this->errors as $class => $dependencies) {
|
|
$failMessage .= $class . ' depends for non-library ' . (count($dependencies) > 1 ? 'classes ' : 'class ');
|
|
foreach ($dependencies as $dependency) {
|
|
$failMessage .= $dependency . ' ';
|
|
}
|
|
$failMessage = trim($failMessage) . PHP_EOL;
|
|
}
|
|
return $failMessage;
|
|
}
|
|
|
|
/**
|
|
* Contains all library files
|
|
*
|
|
* @return array
|
|
*/
|
|
public function libraryDataProvider()
|
|
{
|
|
// @TODO: remove this code when class Magento\Framework\Data\Collection will fixed
|
|
$componentRegistrar = new ComponentRegistrar();
|
|
include_once $componentRegistrar->getPath(ComponentRegistrar::LIBRARY, 'magento/framework')
|
|
. '/Option/ArrayInterface.php';
|
|
$blackList = Files::init()->readLists(__DIR__ . '/_files/blacklist*.txt');
|
|
$dataProvider = Files::init()->getPhpFiles(Files::INCLUDE_LIBS | Files::AS_DATA_SET);
|
|
|
|
foreach ($dataProvider as $key => $data) {
|
|
if (in_array($data[0], $blackList)) {
|
|
unset($dataProvider[$key]);
|
|
} else {
|
|
include_once $data[0];
|
|
}
|
|
}
|
|
return $dataProvider;
|
|
}
|
|
}
|