123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215 |
- <?php
- /**
- * Copyright © Magento, Inc. All rights reserved.
- * See COPYING.txt for license details.
- */
- namespace Magento\Deploy\Package\Processor\PreProcessor;
- use Magento\Deploy\Console\DeployStaticOptions;
- use Magento\Deploy\Package\Package;
- use Magento\Deploy\Package\PackageFile;
- use Magento\Deploy\Package\Processor\ProcessorInterface;
- use Magento\Framework\Filesystem;
- use Magento\Framework\Filesystem\Directory\ReadInterface;
- use Magento\Framework\App\Filesystem\DirectoryList;
- use Magento\Framework\View\Url\CssResolver;
- use Magento\Framework\View\Asset\Minification;
- /**
- * Pre-processor for speeding up deployment of CSS files
- *
- * If there is a CSS file overridden in target theme and there are files in ancestor theme where this file was imported,
- * then all such parent files must be copied into target theme.
- */
- class Css implements ProcessorInterface
- {
- /**
- * @var ReadInterface
- */
- private $staticDir;
- /**
- * @var Minification
- */
- private $minification;
- /**
- * CssUrls constructor
- *
- * @param Filesystem $filesystem
- * @param Minification $minification
- */
- public function __construct(Filesystem $filesystem, Minification $minification)
- {
- $this->staticDir = $filesystem->getDirectoryRead(DirectoryList::STATIC_VIEW);
- $this->minification = $minification;
- }
- /**
- * CSS files map
- *
- * Collect information about CSS files which have been imported in other CSS files
- *
- * @var []
- */
- private $map = [];
- /**
- * Deployment procedure options
- *
- * @var array
- */
- private $options = [];
- /**
- * @inheritdoc
- */
- public function process(Package $package, array $options)
- {
- $this->options = $options;
- if ($this->options[DeployStaticOptions::NO_CSS] === true) {
- return false;
- }
- if ($package->getArea() !== Package::BASE_AREA && $package->getTheme() !== Package::BASE_THEME) {
- $files = $package->getParentFiles('css');
- foreach ($files as $file) {
- $packageFile = $package->getFile($file->getFileId());
- if ($packageFile && $packageFile->getPackage() === $package) {
- continue;
- }
- if ($this->hasOverrides($file, $package)) {
- $file = clone $file;
- $file->setArea($package->getArea());
- $file->setTheme($package->getTheme());
- $file->setLocale($package->getLocale());
- $file->setPackage($package);
- $package->addFileToMap($file);
- }
- }
- }
- return true;
- }
- /**
- * Checks if there are imports of CSS files or images within the given CSS file
- * which exists in the current package
- *
- * @param PackageFile $parentFile
- * @param Package $package
- * @return bool
- */
- private function hasOverrides(PackageFile $parentFile, Package $package)
- {
- $this->buildMap(
- $parentFile->getPackage()->getPath(),
- $parentFile->getDeployedFileName(),
- $parentFile->getDeployedFilePath()
- );
- $parentFiles = $this->collectFileMap($parentFile->getDeployedFilePath());
- $currentPackageFiles = $package->getFiles();
- $intersections = array_intersect_key($parentFiles, $currentPackageFiles);
- if ($intersections) {
- return true;
- }
- return false;
- }
- /**
- * Build map file
- *
- * @param string $packagePath
- * @param string $filePath
- * @param string $fullPath
- * @return void
- */
- private function buildMap($packagePath, $filePath, $fullPath)
- {
- if (!isset($this->map[$fullPath])) {
- $imports = [];
- $this->map[$fullPath] = [];
- $content = $this->staticDir->readFile($this->minification->addMinifiedSign($fullPath));
- $callback = function ($matchContent) use ($packagePath, $filePath, & $imports) {
- $importRelPath = $this->normalize(pathinfo($filePath, PATHINFO_DIRNAME) . '/' . $matchContent['path']);
- $imports[$importRelPath] = $this->normalize(
- $packagePath . '/' . pathinfo($filePath, PATHINFO_DIRNAME) . '/' . $matchContent['path']
- );
- };
- preg_replace_callback(
- \Magento\Framework\Css\PreProcessor\Instruction\Import::REPLACE_PATTERN,
- $callback,
- $content
- );
- preg_match_all(CssResolver::REGEX_CSS_RELATIVE_URLS, $content, $matches);
- if (!empty($matches[0]) && !empty($matches[1])) {
- $urls = array_combine($matches[0], $matches[1]);
- foreach ($urls as $url) {
- $importRelPath = $this->normalize(pathinfo($filePath, PATHINFO_DIRNAME) . '/' . $url);
- $imports[$importRelPath] = $this->normalize(
- $packagePath . '/' . pathinfo($filePath, PATHINFO_DIRNAME) . '/' . $url
- );
- }
- }
- $this->map[$fullPath] = $imports;
- foreach ($imports as $importRelPath => $importFullPath) {
- // only inner CSS files are concerned
- if (strtolower(pathinfo($importFullPath, PATHINFO_EXTENSION)) === 'css') {
- $this->buildMap($packagePath, $importRelPath, $importFullPath);
- }
- }
- }
- }
- /**
- * Flatten map tree into simple array
- *
- * Original map file information structure in form of tree,
- * and to have checking of overridden files simpler we need to flatten that tree
- *
- * @param string $fileName
- * @return array
- */
- private function collectFileMap($fileName)
- {
- $result = isset($this->map[$fileName]) ? $this->map[$fileName] : [];
- foreach ($result as $path) {
- $result = array_merge($result, $this->collectFileMap($path));
- }
- return array_unique($result);
- }
- /**
- * Return normalized path
- *
- * @param string $path
- * @return string
- */
- private function normalize($path)
- {
- if (strpos($path, '/../') === false) {
- return $path;
- }
- $pathParts = explode('/', $path);
- $realPath = [];
- foreach ($pathParts as $pathPart) {
- if ($pathPart == '.') {
- continue;
- }
- if ($pathPart == '..') {
- array_pop($realPath);
- continue;
- }
- $realPath[] = $pathPart;
- }
- return implode('/', $realPath);
- }
- }
|