Skip to content

Commit 54dfebb

Browse files
committed
[AssetMapper] Allowing for files to be written to some non-local location
1 parent d27190a commit 54dfebb

18 files changed

+301
-150
lines changed

src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1341,13 +1341,17 @@ private function registerAssetMapperConfiguration(array $config, ContainerBuilde
13411341
->setArgument(0, $paths)
13421342
->setArgument(2, $excludedPathPatterns);
13431343

1344-
$publicDirName = $this->getPublicDirectoryName($container);
13451344
$container->getDefinition('asset_mapper.public_assets_path_resolver')
1346-
->setArgument(1, $config['public_prefix'])
1347-
->setArgument(2, $publicDirName);
1345+
->setArgument(0, $config['public_prefix']);
13481346

1349-
$container->getDefinition('asset_mapper.command.compile')
1350-
->setArgument(5, $publicDirName);
1347+
$publicDirectory = $this->getPublicDirectory($container);
1348+
$publicAssetsDirectory = rtrim($publicDirectory.'/'.ltrim($config['public_prefix'], '/'), '/');
1349+
$container->getDefinition('asset_mapper.local_public_assets_filesystem')
1350+
->setArgument(0, $publicDirectory)
1351+
;
1352+
1353+
$container->getDefinition('asset_mapper.compiled_asset_mapper_config_reader')
1354+
->setArgument(0, $publicAssetsDirectory);
13511355

13521356
if (!$config['server']) {
13531357
$container->removeDefinition('asset_mapper.dev_server_subscriber');
@@ -3155,11 +3159,12 @@ private function writeConfigEnabled(string $path, bool $value, array &$config):
31553159
$config['enabled'] = $value;
31563160
}
31573161

3158-
private function getPublicDirectoryName(ContainerBuilder $container): string
3162+
private function getPublicDirectory(ContainerBuilder $container): string
31593163
{
3160-
$defaultPublicDir = 'public';
3164+
$projectDir = $container->getParameter('kernel.project_dir');
3165+
$defaultPublicDir = $projectDir.'/public';
31613166

3162-
$composerFilePath = $container->getParameter('kernel.project_dir').'/composer.json';
3167+
$composerFilePath = $projectDir.'/composer.json';
31633168

31643169
if (!file_exists($composerFilePath)) {
31653170
return $defaultPublicDir;
@@ -3168,6 +3173,6 @@ private function getPublicDirectoryName(ContainerBuilder $container): string
31683173
$container->addResource(new FileResource($composerFilePath));
31693174
$composerConfig = json_decode(file_get_contents($composerFilePath), true);
31703175

3171-
return $composerConfig['extra']['public-dir'] ?? $defaultPublicDir;
3176+
return isset($composerConfig['extra']['public-dir']) ? $projectDir . '/' . $composerConfig['extra']['public-dir'] : $defaultPublicDir;
31723177
}
31733178
}

src/Symfony/Bundle/FrameworkBundle/Resources/config/asset_mapper.php

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
use Symfony\Component\AssetMapper\Command\ImportMapRemoveCommand;
2424
use Symfony\Component\AssetMapper\Command\ImportMapRequireCommand;
2525
use Symfony\Component\AssetMapper\Command\ImportMapUpdateCommand;
26+
use Symfony\Component\AssetMapper\CompiledAssetMapperConfigReader;
2627
use Symfony\Component\AssetMapper\Compiler\CssAssetUrlCompiler;
2728
use Symfony\Component\AssetMapper\Compiler\JavaScriptImportPathCompiler;
2829
use Symfony\Component\AssetMapper\Compiler\SourceMappingUrlsCompiler;
@@ -36,6 +37,7 @@
3637
use Symfony\Component\AssetMapper\ImportMap\Resolver\JspmResolver;
3738
use Symfony\Component\AssetMapper\ImportMap\Resolver\PackageResolver;
3839
use Symfony\Component\AssetMapper\MapperAwareAssetPackage;
40+
use Symfony\Component\AssetMapper\Path\LocalPublicAssetsFilesystem;
3941
use Symfony\Component\AssetMapper\Path\PublicAssetsPathResolver;
4042
use Symfony\Component\HttpKernel\Event\RequestEvent;
4143

@@ -45,7 +47,7 @@
4547
->args([
4648
service('asset_mapper.repository'),
4749
service('asset_mapper.mapped_asset_factory'),
48-
service('asset_mapper.public_assets_path_resolver'),
50+
service('asset_mapper.compiled_asset_mapper_config_reader'),
4951
])
5052
->alias(AssetMapperInterface::class, 'asset_mapper')
5153

@@ -72,9 +74,17 @@
7274

7375
->set('asset_mapper.public_assets_path_resolver', PublicAssetsPathResolver::class)
7476
->args([
75-
param('kernel.project_dir'),
7677
abstract_arg('asset public prefix'),
77-
abstract_arg('public directory name'),
78+
])
79+
80+
->set('asset_mapper.local_public_assets_filesystem', LocalPublicAssetsFilesystem::class)
81+
->args([
82+
abstract_arg('public directory'),
83+
])
84+
85+
->set('asset_mapper.compiled_asset_mapper_config_reader', CompiledAssetMapperConfigReader::class)
86+
->args([
87+
abstract_arg('public assets directory'),
7888
])
7989

8090
->set('asset_mapper.asset_package', MapperAwareAssetPackage::class)
@@ -95,12 +105,11 @@
95105

96106
->set('asset_mapper.command.compile', AssetMapperCompileCommand::class)
97107
->args([
98-
service('asset_mapper.public_assets_path_resolver'),
108+
service('asset_mapper.compiled_asset_mapper_config_reader'),
99109
service('asset_mapper'),
100110
service('asset_mapper.importmap.manager'),
101-
service('filesystem'),
111+
service('asset_mapper.local_public_assets_filesystem'),
102112
param('kernel.project_dir'),
103-
abstract_arg('public directory name'),
104113
param('kernel.debug'),
105114
service('event_dispatcher')->nullOnInvalid(),
106115
])
@@ -148,7 +157,7 @@
148157
->set('asset_mapper.importmap.manager', ImportMapManager::class)
149158
->args([
150159
service('asset_mapper'),
151-
service('asset_mapper.public_assets_path_resolver'),
160+
service('asset_mapper.compiled_asset_mapper_config_reader'),
152161
service('asset_mapper.importmap.config_reader'),
153162
abstract_arg('vendor directory'),
154163
service('asset_mapper.importmap.resolver'),

src/Symfony/Component/AssetMapper/AssetMapper.php

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
namespace Symfony\Component\AssetMapper;
1313

1414
use Symfony\Component\AssetMapper\Factory\MappedAssetFactoryInterface;
15-
use Symfony\Component\AssetMapper\Path\PublicAssetsPathResolverInterface;
1615

1716
/**
1817
* Finds and returns assets in the pipeline.
@@ -28,7 +27,7 @@ class AssetMapper implements AssetMapperInterface
2827
public function __construct(
2928
private readonly AssetMapperRepository $mapperRepository,
3029
private readonly MappedAssetFactoryInterface $mappedAssetFactory,
31-
private readonly PublicAssetsPathResolverInterface $assetsPathResolver,
30+
private readonly CompiledAssetMapperConfigReader $compiledConfigReader,
3231
) {
3332
}
3433

@@ -78,12 +77,10 @@ public function getPublicPath(string $logicalPath): ?string
7877
private function loadManifest(): array
7978
{
8079
if (null === $this->manifestData) {
81-
$path = $this->assetsPathResolver->getPublicFilesystemPath().'/'.self::MANIFEST_FILE_NAME;
82-
83-
if (!is_file($path)) {
80+
if (!$this->compiledConfigReader->configExists(self::MANIFEST_FILE_NAME)) {
8481
$this->manifestData = [];
8582
} else {
86-
$this->manifestData = json_decode(file_get_contents($path), true);
83+
$this->manifestData = $this->compiledConfigReader->loadConfig(self::MANIFEST_FILE_NAME);
8784
}
8885
}
8986

src/Symfony/Component/AssetMapper/Command/AssetMapperCompileCommand.php

Lines changed: 24 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,10 @@
1313

1414
use Symfony\Component\AssetMapper\AssetMapper;
1515
use Symfony\Component\AssetMapper\AssetMapperInterface;
16+
use Symfony\Component\AssetMapper\CompiledAssetMapperConfigReader;
1617
use Symfony\Component\AssetMapper\Event\PreAssetsCompileEvent;
1718
use Symfony\Component\AssetMapper\ImportMap\ImportMapManager;
19+
use Symfony\Component\AssetMapper\Path\PublicAssetsFilesystemInterface;
1820
use Symfony\Component\AssetMapper\Path\PublicAssetsPathResolverInterface;
1921
use Symfony\Component\Console\Attribute\AsCommand;
2022
use Symfony\Component\Console\Command\Command;
@@ -36,12 +38,11 @@
3638
final class AssetMapperCompileCommand extends Command
3739
{
3840
public function __construct(
39-
private readonly PublicAssetsPathResolverInterface $publicAssetsPathResolver,
41+
private readonly CompiledAssetMapperConfigReader $compiledConfigReader,
4042
private readonly AssetMapperInterface $assetMapper,
4143
private readonly ImportMapManager $importMapManager,
42-
private readonly Filesystem $filesystem,
44+
private readonly PublicAssetsFilesystemInterface $assetsFilesystem,
4345
private readonly string $projectDir,
44-
private readonly string $publicDirName,
4546
private readonly bool $isDebug,
4647
private readonly ?EventDispatcherInterface $eventDispatcher = null,
4748
) {
@@ -51,7 +52,6 @@ public function __construct(
5152
protected function configure(): void
5253
{
5354
$this
54-
->addOption('clean', null, null, 'Whether to clean the public directory before compiling assets')
5555
->setHelp(<<<'EOT'
5656
The <info>%command.name%</info> command compiles and dumps all the assets in
5757
the asset mapper into the final public directory (usually <comment>public/assets</comment>).
@@ -64,61 +64,36 @@ protected function configure(): void
6464
protected function execute(InputInterface $input, OutputInterface $output): int
6565
{
6666
$io = new SymfonyStyle($input, $output);
67-
$publicDir = $this->projectDir.'/'.$this->publicDirName;
68-
if (!is_dir($publicDir)) {
69-
throw new InvalidArgumentException(sprintf('The public directory "%s" does not exist.', $publicDir));
70-
}
71-
72-
$outputDir = $this->publicAssetsPathResolver->getPublicFilesystemPath();
73-
if ($input->getOption('clean')) {
74-
$io->comment(sprintf('Cleaning <info>%s</info>', $outputDir));
75-
$this->filesystem->remove($outputDir);
76-
$this->filesystem->mkdir($outputDir);
77-
}
7867

79-
// set up the file paths
80-
$files = [];
81-
$manifestPath = $outputDir.'/'.AssetMapper::MANIFEST_FILE_NAME;
82-
$files[] = $manifestPath;
68+
$this->eventDispatcher?->dispatch(new PreAssetsCompileEvent($output));
8369

84-
$importMapPath = $outputDir.'/'.ImportMapManager::IMPORT_MAP_CACHE_FILENAME;
85-
$files[] = $importMapPath;
86-
87-
$entrypointFilePaths = [];
70+
// remove existing config files
71+
$this->compiledConfigReader->removeConfig(AssetMapper::MANIFEST_FILE_NAME);
72+
$this->compiledConfigReader->removeConfig(ImportMapManager::IMPORT_MAP_CACHE_FILENAME);
73+
$entrypointFiles = [];
8874
foreach ($this->importMapManager->getEntrypointNames() as $entrypointName) {
89-
$dumpedEntrypointPath = $outputDir.'/'.sprintf(ImportMapManager::ENTRYPOINT_CACHE_FILENAME_PATTERN, $entrypointName);
90-
$files[] = $dumpedEntrypointPath;
91-
$entrypointFilePaths[$entrypointName] = $dumpedEntrypointPath;
75+
$path = sprintf(ImportMapManager::ENTRYPOINT_CACHE_FILENAME_PATTERN, $entrypointName);
76+
$this->compiledConfigReader->removeConfig($path);
77+
$entrypointFiles[$entrypointName] = $path;
9278
}
9379

94-
// remove existing files
95-
foreach ($files as $file) {
96-
if (is_file($file)) {
97-
$this->filesystem->remove($file);
98-
}
99-
}
100-
101-
$this->eventDispatcher?->dispatch(new PreAssetsCompileEvent($outputDir, $output));
102-
103-
// dump new files
104-
$manifest = $this->createManifestAndWriteFiles($io, $publicDir);
105-
$this->filesystem->dumpFile($manifestPath, json_encode($manifest, \JSON_PRETTY_PRINT));
80+
$manifest = $this->createManifestAndWriteFiles($io);
81+
$manifestPath = $this->compiledConfigReader->saveConfig(AssetMapper::MANIFEST_FILE_NAME, $manifest);
10682
$io->comment(sprintf('Manifest written to <info>%s</info>', $this->shortenPath($manifestPath)));
10783

108-
$this->filesystem->dumpFile($importMapPath, json_encode($this->importMapManager->getRawImportMapData(), \JSON_THROW_ON_ERROR | \JSON_PRETTY_PRINT | \JSON_UNESCAPED_SLASHES | \JSON_HEX_TAG));
84+
$importMapPath = $this->compiledConfigReader->saveConfig(ImportMapManager::IMPORT_MAP_CACHE_FILENAME, $this->importMapManager->getRawImportMapData());
10985
$io->comment(sprintf('Import map data written to <info>%s</info>.', $this->shortenPath($importMapPath)));
11086

111-
$entrypointNames = $this->importMapManager->getEntrypointNames();
112-
foreach ($entrypointFilePaths as $entrypointName => $path) {
113-
$this->filesystem->dumpFile($path, json_encode($this->importMapManager->getEntrypointMetadata($entrypointName), \JSON_THROW_ON_ERROR | \JSON_PRETTY_PRINT | \JSON_UNESCAPED_SLASHES | \JSON_HEX_TAG));
87+
foreach ($entrypointFiles as $entrypointName => $path) {
88+
$this->compiledConfigReader->saveConfig($path, $this->importMapManager->getEntrypointMetadata($entrypointName));
11489
}
115-
$styledEntrypointNames = array_map(fn (string $entrypointName) => sprintf('<info>%s</>', $entrypointName), $entrypointNames);
116-
$io->comment(sprintf('Entrypoint metadata written for <comment>%d</> entrypoints (%s).', \count($entrypointNames), implode(', ', $styledEntrypointNames)));
90+
$styledEntrypointNames = array_map(fn (string $entrypointName) => sprintf('<info>%s</>', $entrypointName), array_keys($entrypointFiles));
91+
$io->comment(sprintf('Entrypoint metadata written for <comment>%d</> entrypoints (%s).', \count($entrypointFiles), implode(', ', $styledEntrypointNames)));
11792

11893
if ($this->isDebug) {
11994
$io->warning(sprintf(
120-
'You are compiling assets in development. Symfony will not serve any changed assets until you delete the "%s" directory.',
121-
$this->shortenPath($outputDir)
95+
'You are compiling assets in development. Symfony will not serve any changed assets until you delete the files in the "%s" directory.',
96+
$this->shortenPath(dirname($manifestPath))
12297
));
12398
}
12499

@@ -130,21 +105,14 @@ private function shortenPath(string $path): string
130105
return str_replace($this->projectDir.'/', '', $path);
131106
}
132107

133-
private function createManifestAndWriteFiles(SymfonyStyle $io, string $publicDir): array
108+
private function createManifestAndWriteFiles(SymfonyStyle $io): array
134109
{
135110
$allAssets = $this->assetMapper->allAssets();
136111

137-
$io->comment(sprintf('Compiling assets to <info>%s%s</info>', $publicDir, $this->publicAssetsPathResolver->resolvePublicPath('')));
112+
$io->comment(sprintf('Compiling and writing asset files to <info>%s</info>', $this->assetsFilesystem->getDestinationPathString()));
138113
$manifest = [];
139114
foreach ($allAssets as $asset) {
140-
// $asset->getPublicPath() will start with a "/"
141-
$targetPath = $publicDir.$asset->publicPath;
142-
143-
if (!is_dir($dir = \dirname($targetPath))) {
144-
$this->filesystem->mkdir($dir);
145-
}
146-
147-
$this->filesystem->dumpFile($targetPath, $asset->content);
115+
$this->assetsFilesystem->write($asset->publicPath, $asset->content);
148116
$manifest[$asset->logicalPath] = $asset->publicPath;
149117
}
150118
ksort($manifest);
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\AssetMapper;
13+
14+
/**
15+
* Reads and writes compiled configuration files for asset mapper.
16+
*/
17+
class CompiledAssetMapperConfigReader
18+
{
19+
public function __construct(private readonly string $directory)
20+
{
21+
}
22+
23+
public function configExists(string $filename): bool
24+
{
25+
return is_file($this->directory.'/'.$filename);
26+
}
27+
28+
public function loadConfig(string $filename): array
29+
{
30+
return json_decode(file_get_contents($this->directory.'/'.$filename), true, 512, \JSON_THROW_ON_ERROR);
31+
}
32+
33+
public function saveConfig(string $filename, array $data): string
34+
{
35+
$path = $this->directory.'/'.$filename;
36+
@mkdir(dirname($path), 0777, true);
37+
file_put_contents($path, json_encode($data, \JSON_PRETTY_PRINT | \JSON_THROW_ON_ERROR));
38+
39+
return $path;
40+
}
41+
42+
public function removeConfig(string $filename): void
43+
{
44+
$path = $this->directory.'/'.$filename;
45+
46+
if (is_file($path)) {
47+
unlink($path);
48+
}
49+
}
50+
}

src/Symfony/Component/AssetMapper/Event/PreAssetsCompileEvent.php

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -21,20 +21,13 @@
2121
*/
2222
class PreAssetsCompileEvent extends Event
2323
{
24-
private string $outputDir;
2524
private OutputInterface $output;
2625

27-
public function __construct(string $outputDir, OutputInterface $output)
26+
public function __construct(OutputInterface $output)
2827
{
29-
$this->outputDir = $outputDir;
3028
$this->output = $output;
3129
}
3230

33-
public function getOutputDir(): string
34-
{
35-
return $this->outputDir;
36-
}
37-
3831
public function getOutput(): OutputInterface
3932
{
4033
return $this->output;

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy