mirror of
https://github.com/bdnugget/magento2.git
synced 2026-11-07 09:17:35 +00:00
255 lines
7.6 KiB
PHP
255 lines
7.6 KiB
PHP
<?php
|
|
/**
|
|
* Copyright © Magento, Inc. All rights reserved.
|
|
* See COPYING.txt for license details.
|
|
*/
|
|
namespace Magento\Deploy\Service;
|
|
|
|
use Magento\Deploy\Config\BundleConfig;
|
|
use Magento\Deploy\Package\BundleInterface;
|
|
use Magento\Deploy\Package\BundleInterfaceFactory;
|
|
use Magento\Framework\App\Filesystem\DirectoryList;
|
|
use Magento\Framework\App\ObjectManager;
|
|
use Magento\Framework\Filesystem;
|
|
use Magento\Framework\App\Utility\Files;
|
|
use Magento\Framework\Filesystem\Io\File;
|
|
use Magento\Framework\View\Asset\Repository;
|
|
use Magento\Framework\View\Asset\RepositoryMap;
|
|
|
|
/**
|
|
* Deploy bundled static files service
|
|
*
|
|
* Read all static files from deployed packages and generate bundles. Bundle Factory can be configured to use
|
|
* bundle format different from RequireJS used out of the box
|
|
*/
|
|
class Bundle
|
|
{
|
|
/**
|
|
* Path to package subdirectory where bundle files are located
|
|
*/
|
|
public const BUNDLE_JS_DIR = 'js/bundle';
|
|
|
|
/**
|
|
* Matched file extension name for JavaScript files
|
|
*/
|
|
public const ASSET_TYPE_JS = 'js';
|
|
|
|
/**
|
|
* Matched file extension name for template files
|
|
*/
|
|
public const ASSET_TYPE_HTML = 'html';
|
|
|
|
/**
|
|
* Public static directory writable interface
|
|
*
|
|
* @var Filesystem\Directory\WriteInterface
|
|
*/
|
|
private $pubStaticDir;
|
|
|
|
/**
|
|
* Factory for Bundle object
|
|
*
|
|
* @see BundleInterface
|
|
* @var BundleInterfaceFactory
|
|
*/
|
|
private $bundleFactory;
|
|
|
|
/**
|
|
* Utility class for collecting files by specific pattern and location
|
|
*
|
|
* @var Files
|
|
*/
|
|
private $utilityFiles;
|
|
|
|
/**
|
|
* Cached data about files which must be excluded from bundling
|
|
*
|
|
* @var array
|
|
*/
|
|
private $excludedCache = [];
|
|
|
|
/**
|
|
* List of supported types of static files
|
|
*
|
|
* @var array
|
|
* */
|
|
public static $availableTypes = [
|
|
self::ASSET_TYPE_JS,
|
|
self::ASSET_TYPE_HTML
|
|
];
|
|
|
|
/**
|
|
* @var File|null
|
|
*/
|
|
private $file;
|
|
|
|
/**
|
|
* @var BundleConfig
|
|
*/
|
|
private $bundleConfig;
|
|
|
|
/**
|
|
* @param Filesystem $filesystem
|
|
* @param BundleInterfaceFactory $bundleFactory
|
|
* @param BundleConfig $bundleConfig
|
|
* @param Files $files
|
|
* @param File|null $file
|
|
*
|
|
* @throws \Magento\Framework\Exception\FileSystemException
|
|
*/
|
|
public function __construct(
|
|
Filesystem $filesystem,
|
|
BundleInterfaceFactory $bundleFactory,
|
|
BundleConfig $bundleConfig,
|
|
Files $files,
|
|
File $file = null
|
|
) {
|
|
$this->pubStaticDir = $filesystem->getDirectoryWrite(DirectoryList::STATIC_VIEW);
|
|
$this->bundleFactory = $bundleFactory;
|
|
$this->bundleConfig = $bundleConfig;
|
|
$this->utilityFiles = $files;
|
|
$this->file = $file ?: ObjectManager::getInstance()->get(
|
|
\Magento\Framework\Filesystem\Io\File::class
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Deploy bundles for the given area, theme and locale
|
|
*
|
|
* @param string $area
|
|
* @param string $theme
|
|
* @param string $locale
|
|
* @return void
|
|
*
|
|
* @throws \Magento\Framework\Exception\FileSystemException
|
|
* @throws \Magento\Framework\Exception\LocalizedException
|
|
*/
|
|
public function deploy($area, $theme, $locale)
|
|
{
|
|
$bundle = $this->bundleFactory->create(
|
|
[
|
|
'area' => $area,
|
|
'theme' => $theme,
|
|
'locale' => $locale
|
|
]
|
|
);
|
|
|
|
// delete all previously created bundle files
|
|
$bundle->clear();
|
|
$files = [];
|
|
$mapFilePath = $area . '/' . $theme . '/' . $locale . '/' . RepositoryMap::RESULT_MAP_NAME;
|
|
if ($this->pubStaticDir->isFile($mapFilePath)) {
|
|
// map file is available in compact mode, so no need to scan filesystem one more time
|
|
$resultMap = $this->pubStaticDir->readFile($mapFilePath);
|
|
if ($resultMap) {
|
|
$files = json_decode($resultMap, true);
|
|
}
|
|
} else {
|
|
$packageDir = $this->pubStaticDir->getAbsolutePath($area . '/' . $theme . '/' . $locale);
|
|
$files = $this->utilityFiles->getFiles([$packageDir], '*.*');
|
|
}
|
|
|
|
foreach ($files as $filePath => $sourcePath) {
|
|
if (is_array($sourcePath)) {
|
|
$filePath = str_replace(Repository::FILE_ID_SEPARATOR, '/', $filePath);
|
|
$sourcePath = $sourcePath['area']
|
|
. '/' . $sourcePath['theme']
|
|
. '/' . $sourcePath['locale']
|
|
. '/' . $filePath;
|
|
} else {
|
|
$sourcePath = str_replace('\\', '/', $sourcePath ?? '');
|
|
$sourcePath = $this->pubStaticDir->getRelativePath($sourcePath);
|
|
$filePath = substr($sourcePath, strlen($area . '/' . $theme . '/' . $locale) + 1);
|
|
}
|
|
|
|
$contentType = $this->file->getPathInfo($filePath);
|
|
if (!array_key_exists('extension', $contentType) ||
|
|
!in_array($contentType['extension'], self::$availableTypes)
|
|
) {
|
|
continue;
|
|
}
|
|
$contentType = $contentType['extension'];
|
|
|
|
if ($this->hasMinVersion($filePath) || $this->isExcluded($filePath, $area, $theme)) {
|
|
continue;
|
|
}
|
|
|
|
$bundle->addFile($filePath, $sourcePath, $contentType);
|
|
}
|
|
$bundle->flush();
|
|
}
|
|
|
|
/**
|
|
* Check if file is minified version or there is a minified version of the file
|
|
*
|
|
* @param string $filePath
|
|
* @return bool
|
|
*/
|
|
private function hasMinVersion($filePath)
|
|
{
|
|
if (in_array($filePath, $this->excludedCache)) {
|
|
return true;
|
|
}
|
|
|
|
$info = $this->file->getPathInfo($filePath);
|
|
if (strpos($filePath, '.min.') !== false) {
|
|
$this->excludedCache[] = str_replace(".min.{$info['extension']}", ".{$info['extension']}", $filePath);
|
|
} else {
|
|
$pathToMinVersion = $info['dirname'] . '/' . $info['filename'] . '.min.' . $info['extension'];
|
|
if ($this->pubStaticDir->isExist($pathToMinVersion)) {
|
|
$this->excludedCache[] = $filePath;
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Check if file is in exclude list
|
|
*
|
|
* @param string $filePath
|
|
* @param string $area
|
|
* @param string $theme
|
|
* @return bool
|
|
*/
|
|
private function isExcluded($filePath, $area, $theme)
|
|
{
|
|
$excludedFiles = $this->bundleConfig->getExcludedFiles($area, $theme);
|
|
foreach ($excludedFiles as $excludedFileId) {
|
|
$excludedFilePath = $this->prepareExcludePath($excludedFileId);
|
|
if ($excludedFilePath === $filePath || $excludedFilePath === str_replace('.min.js', '.js', $filePath)) {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
$excludedDirs = $this->bundleConfig->getExcludedDirectories($area, $theme);
|
|
foreach ($excludedDirs as $directoryId) {
|
|
$directoryPath = $this->prepareExcludePath($directoryId);
|
|
if (strpos($filePath, (string) $directoryPath) === 0) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Get excluded path
|
|
*
|
|
* @param string $path
|
|
* @return array|bool
|
|
*/
|
|
private function prepareExcludePath($path)
|
|
{
|
|
if ($path !== null && strpos($path, Repository::FILE_ID_SEPARATOR) !== false) {
|
|
list($excludedModule, $excludedPath) = explode(Repository::FILE_ID_SEPARATOR, $path);
|
|
if ($excludedModule == 'Lib') {
|
|
return $excludedPath;
|
|
} else {
|
|
return $excludedModule . '/' . $excludedPath;
|
|
}
|
|
}
|
|
return $path;
|
|
}
|
|
}
|