![]() Server : Apache System : Linux server2.corals.io 4.18.0-348.2.1.el8_5.x86_64 #1 SMP Mon Nov 15 09:17:08 EST 2021 x86_64 User : corals ( 1002) PHP Version : 7.4.33 Disable Function : exec,passthru,shell_exec,system Directory : /home/corals/old/dev/tests/integration/testsuite/Magento/Test/Integrity/ |
<?php /** * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ namespace Magento\Test\Integrity; use Magento\Framework\App\Filesystem\DirectoryList; /** * An integrity test that searches for references to static files and asserts that they are resolved via fallback * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class StaticFilesTest extends \PHPUnit\Framework\TestCase { /** * @var \Magento\Framework\View\Design\FileResolution\Fallback\StaticFile */ private $fallback; /** * @var \Magento\Framework\View\Design\FileResolution\Fallback\Resolver\Simple */ private $explicitFallback; /** * @var \Magento\Framework\View\Design\Theme\FlyweightFactory */ private $themeRepo; /** * @var \Magento\Framework\View\DesignInterface */ private $design; /** * @var \Magento\Framework\View\Design\ThemeInterface */ private $baseTheme; /** * @var \Magento\Framework\View\Design\FileResolution\Fallback\Resolver\Alternative */ private $alternativeResolver; /** * Factory for simple rule * * @var \Magento\Framework\View\Design\Fallback\Rule\SimpleFactory */ private $simpleFactory; /** * @var \Magento\Framework\Filesystem */ private $filesystem; protected function setUp(): void { $om = \Magento\TestFramework\Helper\Bootstrap::getObjectmanager(); $this->fallback = $om->get(\Magento\Framework\View\Design\FileResolution\Fallback\StaticFile::class); $this->explicitFallback = $om->get( \Magento\Framework\View\Design\FileResolution\Fallback\Resolver\Simple::class ); $this->themeRepo = $om->get(\Magento\Framework\View\Design\Theme\FlyweightFactory::class); $this->design = $om->get(\Magento\Framework\View\DesignInterface::class); $this->baseTheme = $om->get(\Magento\Framework\View\Design\ThemeInterface::class); $this->alternativeResolver = $om->get( \Magento\Framework\View\Design\FileResolution\Fallback\Resolver\Alternative::class ); $this->simpleFactory = $om->get(\Magento\Framework\View\Design\Fallback\Rule\SimpleFactory::class); $this->filesystem = $om->get(\Magento\Framework\Filesystem::class); } /** * Scan references to files from other static files and assert they are correct * * The CSS or LESS files may refer to other resources using `import` or url() notation * We want to check integrity of all these references * Note that the references may have syntax specific to the Magento preprocessing subsystem * * @param string $area * @param string $themePath * @param string $locale * @param string $module * @param string $filePath * @param string $absolutePath * @dataProvider referencesFromStaticFilesDataProvider */ public function testReferencesFromStaticFiles($area, $themePath, $locale, $module, $filePath, $absolutePath) { $contents = file_get_contents($absolutePath); preg_match_all( \Magento\Framework\View\Url\CssResolver::REGEX_CSS_RELATIVE_URLS, $contents, $matches ); foreach ($matches[1] as $relatedResource) { if (false !== strpos($relatedResource, '@')) { // unable to parse paths with LESS variables/mixins continue; } list($relatedModule, $relatedPath) = \Magento\Framework\View\Asset\Repository::extractModule($relatedResource); if ($relatedModule) { $fallbackModule = $relatedModule; } else { if ('less' == pathinfo($filePath, PATHINFO_EXTENSION)) { /** * The LESS library treats the related resources with relative links not in the same way as CSS: * when another LESS file is included, it is embedded directly into the resulting document, but the * relative paths of related resources are not adjusted accordingly to the new root file. * Probably it is a bug of the LESS library. */ $this->markTestSkipped("Due to LESS library specifics, the '{$relatedResource}' cannot be tested."); } $fallbackModule = $module; $relatedPath = \Magento\Framework\View\FileSystem::getRelatedPath($filePath, $relatedResource); } // the $relatedPath will be suitable for feeding to the fallback system $staticFile = $this->getStaticFile($area, $themePath, $locale, $relatedPath, $fallbackModule); if (empty($staticFile) && substr($relatedPath, 0, 2) === '..') { //check if static file exists on lib level $path = substr($relatedPath, 2); $libDir = rtrim($this->filesystem->getDirectoryRead(DirectoryList::LIB_WEB)->getAbsolutePath(), '/'); $rule = $this->simpleFactory->create(['pattern' => $libDir]); $params = ['area' => $area, 'theme' => $themePath, 'locale' => $locale]; $staticFile = $this->alternativeResolver->resolveFile($rule, $path, $params); } $this->assertNotEmpty( $staticFile, "The related resource cannot be resolved through fallback: '{$relatedResource}'" ); } } /** * Get a default theme path for specified area * * @param string $area * @return string * @throws \LogicException */ private function getDefaultThemePath($area) { switch ($area) { case 'frontend': return $this->design->getConfigurationDesignTheme($area); case 'adminhtml': return $this->design->getConfigurationDesignTheme($area); case 'doc': return 'Magento/blank'; default: throw new \LogicException('Unable to determine theme path'); } } /** * Get static file through fallback system using specified params * * @param string $area * @param string|\Magento\Framework\View\Design\ThemeInterface $theme - either theme path (string) or theme object * @param string $locale * @param string $filePath * @param string $module * @param bool $isExplicit * @return bool|string */ private function getStaticFile($area, $theme, $locale, $filePath, $module = null, $isExplicit = false) { if ($area == 'base') { $theme = $this->baseTheme; } if (!is_object($theme)) { $themePath = $theme ?: $this->getDefaultThemePath($area); $theme = $this->themeRepo->create($themePath, $area); } if ($isExplicit) { $type = \Magento\Framework\View\Design\Fallback\RulePool::TYPE_STATIC_FILE; return $this->explicitFallback->resolve($type, $filePath, $area, $theme, $locale, $module); } return $this->fallback->getFile($area, $theme, $locale, $filePath, $module); } /** * @return array */ public function referencesFromStaticFilesDataProvider() { return \Magento\Framework\App\Utility\Files::init()->getStaticPreProcessingFiles('*.{less,css}'); } /** * There must be either .css or .less file, because if there are both, then .less will not be found by fallback * * @param string $area * @param string $themePath * @param string $locale * @param string $module * @param string $filePath * @dataProvider lessNotConfusedWithCssDataProvider */ public function testLessNotConfusedWithCss($area, $themePath, $locale, $module, $filePath) { if (false !== strpos($filePath, 'widgets.css')) { $filePath .= ''; } $fileName = pathinfo($filePath, PATHINFO_FILENAME); $dirName = dirname($filePath); if ('.' == $dirName) { $dirName = ''; } else { $dirName .= '/'; } $cssPath = $dirName . $fileName . '.css'; $lessPath = $dirName . $fileName . '.less'; $cssFile = $this->getStaticFile($area, $themePath, $locale, $cssPath, $module, true); $lessFile = $this->getStaticFile($area, $themePath, $locale, $lessPath, $module, true); $this->assertFalse( $cssFile && $lessFile, "A resource file of only one type must exist. Both found: '$cssFile' and '$lessFile'" ); } /** * @return array */ public function lessNotConfusedWithCssDataProvider() { return \Magento\Framework\App\Utility\Files::init()->getStaticPreProcessingFiles('*.{less,css}'); } /** * Test if references $this->getViewFileUrl() in .phtml-files are correct * * @param string $phtmlFile * @param string $area * @param string $themePath * @param string $fileId * @dataProvider referencesFromPhtmlFilesDataProvider */ public function testReferencesFromPhtmlFiles($phtmlFile, $area, $themePath, $fileId) { list($module, $filePath) = \Magento\Framework\View\Asset\Repository::extractModule($fileId); $this->assertNotEmpty( $this->getStaticFile($area, $themePath, 'en_US', $filePath, $module), "Unable to locate '{$fileId}' reference from {$phtmlFile}" ); } /** * @return array */ public function referencesFromPhtmlFilesDataProvider() { $result = []; foreach (\Magento\Framework\App\Utility\Files::init()->getPhtmlFiles(true, false) as $info) { list($area, $themePath, , , $file) = $info; foreach ($this->collectGetViewFileUrl($file) as $fileId) { $result[] = [$file, $area, $themePath, $fileId]; } } return $result; } /** * Find invocations of $block->getViewFileUrl() and extract the first argument value * * @param string $file * @return array */ private function collectGetViewFileUrl($file) { $result = []; if (preg_match_all('/\$block->getViewFileUrl\(\'([^\']+?)\'\)/', file_get_contents($file), $matches)) { foreach ($matches[1] as $fileId) { $result[] = $fileId; } } return $result; } /** * @param string $layoutFile * @param string $area * @param string $themePath * @param string $fileId * @dataProvider referencesFromLayoutFilesDataProvider */ public function testReferencesFromLayoutFiles($layoutFile, $area, $themePath, $fileId) { list($module, $filePath) = \Magento\Framework\View\Asset\Repository::extractModule($fileId); $this->assertNotEmpty( $this->getStaticFile($area, $themePath, 'en_US', $filePath, $module), "Unable to locate '{$fileId}' reference from layout XML in {$layoutFile}" ); } /** * @return array */ public function referencesFromLayoutFilesDataProvider() { $result = []; $files = \Magento\Framework\App\Utility\Files::init()->getLayoutFiles(['with_metainfo' => true], false); foreach ($files as $metaInfo) { list($area, $themePath, , , $file) = array_pad($metaInfo, 5, null); if (!is_string($file)) { $this->addWarning( 'Wrong layout file configuration provided. The `file` meta info must be the type of string' ); continue; } foreach ($this->collectFileIdsFromLayout($file) as $fileId) { $result[] = [$file, $area, $themePath, $fileId]; } } return $result; } /** * Collect view file declarations in layout XML-files * * @param string $file * @return array */ private function collectFileIdsFromLayout($file) { $xml = simplexml_load_file($file); $elements = $xml->xpath('//head/css|link|script'); $result = []; if ($elements) { foreach ($elements as $node) { $result[] = (string)$node; } } return $result; } }