* * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\AssetMapper\Factory; use Symfony\Component\AssetMapper\MappedAsset; use Symfony\Component\Config\ConfigCache; use Symfony\Component\Config\Resource\DirectoryResource; use Symfony\Component\Config\Resource\FileExistenceResource; use Symfony\Component\Config\Resource\FileResource; use Symfony\Component\Config\Resource\ResourceInterface; use Symfony\Component\Filesystem\Filesystem; /** * Decorates the asset factory to load MappedAssets from cache when possible. */ class CachedMappedAssetFactory implements MappedAssetFactoryInterface { public function __construct( private readonly MappedAssetFactoryInterface $innerFactory, private readonly string $cacheDir, private readonly bool $debug, ) { } public function createMappedAsset(string $logicalPath, string $sourcePath): ?MappedAsset { $cachePath = $this->getCacheFilePath($logicalPath, $sourcePath); $configCache = new ConfigCache($cachePath, $this->debug); if ($configCache->isFresh()) { return unserialize((new Filesystem())->readFile($cachePath)); } $mappedAsset = $this->innerFactory->createMappedAsset($logicalPath, $sourcePath); if (!$mappedAsset) { return null; } $resources = $this->collectResourcesFromAsset($mappedAsset); $configCache->write(serialize($mappedAsset), $resources); return $mappedAsset; } private function getCacheFilePath(string $logicalPath, string $sourcePath): string { return $this->cacheDir.'/'.hash('xxh128', $logicalPath.':'.$sourcePath).'.php'; } /** * @return ResourceInterface[] */ private function collectResourcesFromAsset(MappedAsset $mappedAsset): array { $resources = array_map(fn (string $path) => is_dir($path) ? new DirectoryResource($path) : new FileResource($path), $mappedAsset->getFileDependencies()); $resources[] = new FileResource($mappedAsset->sourcePath); foreach ($mappedAsset->getDependencies() as $assetDependency) { $resources = array_merge($resources, $this->collectResourcesFromAsset($assetDependency)); } foreach ($mappedAsset->getJavaScriptImports() as $import) { $resources[] = new FileExistenceResource($import->assetSourcePath); } return $resources; } }