10000 Option to make asset manifests strict on missing item · symfony/symfony@39b825b · GitHub
[go: up one dir, main page]

Skip to content

Commit 39b825b

Browse files
committed
Option to make asset manifests strict on missing item
1 parent 896f4a6 commit 39b825b

File tree

14 files changed

+186
-18
lines changed

14 files changed

+186
-18
lines changed

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -696,6 +696,10 @@ private function addAssetsSection(ArrayNodeDefinition $rootNode, callable $enabl
696696
->{$enableIfStandalone('symfony/asset', Package::class)}()
697697
->fixXmlConfig('base_url')
698698
->children()
699+
->booleanNode('strict_mode')
700+
->info('Throw an exception if an entry is missing from the manifest.json')
701+
->defaultFalse()
702+
->end()
699703
->scalarNode('version_strategy')->defaultNull()->end()
700704
->scalarNode('version')->defaultNull()->end()
701705
->scalarNode('version_format')->defaultValue('%%s?%%s')->end()
@@ -733,6 +737,10 @@ private function addAssetsSection(ArrayNodeDefinition $rootNode, callable $enabl
733737
->prototype('array')
734738
->fixXmlConfig('base_url')
735739
->children()
740+
->booleanNode('strict_mode')
741+
->info('Throw an exception if an entry is missing from the manifest.json')
742+
->defaultFalse()
743+
->end()
736744
->scalarNode('version_strategy')->defaultNull()->end()
737745
->scalarNode('version')
738746
->beforeNormalization()

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

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1148,7 +1148,7 @@ private function registerAssetsConfiguration(array $config, ContainerBuilder $co
11481148
if ($config['version_strategy']) {
11491149
$defaultVersion = new Reference($config['version_strategy']);
11501150
} else {
1151-
$defaultVersion = $this->createVersion($container, $config['version'], $config['version_format'], $config['json_manifest_path'], '_default');
1151+
$defaultVersion = $this->createVersion($container, $config['version'], $config['version_format'], $config['json_manifest_path'], '_default', $config['strict_mode']);
11521152
}
11531153

11541154
$defaultPackage = $this->createPackageDefinition($config['base_path'], $config['base_urls'], $defaultVersion);
@@ -1164,7 +1164,7 @@ private function registerAssetsConfiguration(array $config, ContainerBuilder $co
11641164
// let format fallback to main version_format
11651165
$format = $package['version_format'] ?: $config['version_format'];
11661166
$version = $package['version'] ?? null;
1167-
$version = $this->createVersion($container, $version, $format, $package['json_manifest_path'], $name);
1167+
$version = $this->createVersion($container, $version, $format, $package['json_manifest_path'], $name, $package['strict_mode']);
11681168
}
11691169

11701170
$packageDefinition = $this->createPackageDefinition($package['base_path'], $package['base_urls'], $version)
@@ -1193,7 +1193,7 @@ private function createPackageDefinition(?string $basePath, array $baseUrls, Ref
11931193
return $package;
11941194
}
11951195

1196-
private function createVersion(ContainerBuilder $container, ?string $version, ?string $format, ?string $jsonManifestPath, string $name): Reference
1196+
private function createVersion(ContainerBuilder $container, ?string $version, ?string $format, ?string $jsonManifestPath, string $name, bool $strictMode): Reference
11971197
{
11981198
// Configuration prevents $version and $jsonManifestPath from being set
11991199
if (null !== $version) {
@@ -1210,6 +1210,7 @@ private function createVersion(ContainerBuilder $container, ?string $version, ?s
12101210
if (null !== $jsonManifestPath) {
12111211
$def = new ChildDefinition('assets.json_manifest_version_strategy');
12121212
$def->replaceArgument(0, $jsonManifestPath);
1213+
$def->replaceArgument(2, $strictMode);
12131214
$container->setDefinition('assets._version_'.$name, $def);
12141215

12151216
return new Reference('assets._version_'.$name);

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@
8080
->args([
8181
abstract_arg('manifest path'),
8282
service('http_client')->nullOnInvalid(),
83+
false,
8384
])
8485

8586
->set('assets.remote_json_manifest_version_strategy', RemoteJsonManifestVersionStrategy::class)

src/Symfony/Bundle/FrameworkBundle/Resources/config/schema/symfony-1.0.xsd

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,7 @@
155155
<xsd:attribute name="version" type="xsd:string" />
156156
<xsd:attribute name="version-format" type="xsd:string" />
157157
<xsd:attribute name="json-manifest-path" type="xsd:string" />
158+
<xsd:attribute name="strict-mode" type="xsd:boolean" />
158159
</xsd:complexType>
159160

160161
<xsd:complexType name="package">
@@ -168,6 +169,7 @@
168169
<xsd:attribute name="version" type="xsd:string" />
169170
<xsd:attribute name="version-format" type="xsd:string" />
170171
<xsd:attribute name="json-manifest-path" type="xsd:string" />
172+
<xsd:attribute name="strict-mode" type="xsd:boolean" />
171173
</xsd:complexType>
172174

173175
<xsd:complexType name="translator">

src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/ConfigurationTest.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ public function testAssetsCanBeEnabled()
8585
'base_urls' => [],
8686
'packages' => [],
8787
'json_manifest_path' => null,
88+
'strict_mode' => false,
8889
];
8990

9091
$this->assertEquals($defaultConfig, $config['assets']);
@@ -488,6 +489,7 @@ protected static function getBundleDefaultConfig()
488489
'base_urls' => [],
489490
'packages' => [],
490491
'json_manifest_path' => null,
492+
'strict_mode' => false,
491493
],
492494
'cache' => [
493495
'pools' => [],

src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/assets.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,10 @@
3636
'env_manifest' => [
3737
'json_manifest_path' => '%env(env_manifest)%',
3838
],
39+
'strict_manifest_strategy' => [
40+
'json_manifest_path' => '/path/to/manifest.json',
41+
'strict_mode' => true,
42+
],
3943
],
4044
],
4145
]);

src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/assets.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
<framework:package name="remote_manifest" json-manifest-path="https://cdn.example.com/manifest.json" />
2626
<framework:package name="var_manifest" json-manifest-path="%var_json_manifest_path%" />
2727
<framework:package name="env_manifest" json-manifest-path="%env(env_manifest)%" />
28+
<framework:package name="strict_manifest_strategy" json-manifest-path="/path/to/manifest.json" strict-mode="true" />
2829
</framework:assets>
2930
</framework:config>
3031

src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/assets.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@ framework:
2525
json_manifest_path: '%var_json_manifest_path%'
2626
env_manifest:
2727
json_manifest_path: '%env(env_manifest)%'
28+
strict_manifest_strategy:
29+
json_manifest_path: '/path/to/manifest.json'
30+
strict_mode: true
2831

2932
parameters:
3033
var_json_manifest_path: 'https://cdn.example.com/manifest.json'

src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -632,7 +632,7 @@ public function testAssets()
632632

633633
// packages
634634
$packageTags = $container->findTaggedServiceIds('assets.package');
635-
$this->assertCount(9, $packageTags);
635+
$this->assertCount(10, $packageTags);
636636

637637
$packages = [];
638638
foreach ($packageTags as $serviceId => $tagAttributes) {
@@ -658,6 +658,7 @@ public function testAssets()
658658
$versionStrategy = $container->getDefinition((string) $package->getArgument(1));
659659
$this->assertEquals('assets.json_manifest_version_strategy', $versionStrategy->getParent());
660660
$this->assertEquals('/path/to/manifest.json', $versionStrategy->getArgument(0));
661+
$this->assertFalse($versionStrategy->getArgument(2));
661662

662663
$package = $container->getDefinition($packages['remote_manifest']);
663664
$versionStrategy = $container->getDefinition($package->getArgument(1));
@@ -668,11 +669,19 @@ public function testAssets()
668669
$versionStrategy = $container->getDefinition($package->getArgument(1));
669670
$this->assertSame('assets.json_manifest_version_strategy', $versionStrategy->getParent());
670671
$this->assertSame('https://cdn.example.com/manifest.json', $versionStrategy->getArgument(0));
672+
$this->assertFalse($versionStrategy->getArgument(2));
671673

672674
$package = $container->getDefinition($packages['env_manifest']);
673675
$versionStrategy = $container->getDefinition($package->getArgument(1));
674676
$this->assertSame('assets.json_manifest_version_strategy', $versionStrategy->getParent());
675677
$this->assertStringMatchesFormat('env_%s', $versionStrategy->getArgument(0));
678+
$this->assertFalse($versionStrategy->getArgument(2));
679+
680+
$package = $container->getDefinition((string) $packages['strict_manifest_strategy']);
681+
$versionStrategy = $container->getDefinition((string) $package->getArgument(1));
682+
$this->assertEquals('assets.json_manifest_version_strategy', $versionStrategy->getParent());
683+
$this->assertEquals('/path/to/manifest.json', $versionStrategy->getArgument(0));
684+
$this->assertTrue($versionStrategy->getArgument(2));
676685
}
677686

678687
public function testAssetsDefaultVersionStrategyAsService()
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
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\Asset\Exception;
13+
14+
/**
15+
* Represents an asset not found in a manifest.
16+
*/
17+
class AssetNotFoundException extends RuntimeException
18+
{
19+
private $alternatives;
20+
21+
/**
22+
* @param string $message Exception message to throw
23+
* @param array $alternatives List of similar defined names
24+
* @param int $code Exception code
25+
* @param \Throwable $previous Previous exception used for the exception chaining
26+
*/
27+
public function __construct(string $message, array $alternatives = [], int $code = 0, \Throwable $previous = null)
28+
{
29+
parent::__construct($message, $code, $previous);
30+
31+
$this->alternatives = $alternatives;
32+
}
33+
34+
/**
35+
* @return array A list of similar defined names
36+
*/
37+
public function getAlternatives(): array
38+
{
39+
return $this->alternatives;
40+
}
41+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
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\Asset\Exception;
13+
14+
/**
15+
* Base RuntimeException for the Asset component.
16+
*/
17+
class RuntimeException extends \RuntimeException implements ExceptionInterface
18+
{
19+
}

src/Symfony/Component/Asset/Tests/VersionStrategy/JsonManifestVersionStrategyTest.php

Lines changed: 37 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,51 +12,64 @@
1212
namespace Symfony\Component\Asset\Tests\VersionStrategy;
1313

1414
use PHPUnit\Framework\TestCase;
15+
use Symfony\Component\Asset\Exception\AssetNotFoundException;
16+
use Symfony\Component\Asset\Exception\RuntimeException;
1517
use Symfony\Component\Asset\VersionStrategy\JsonManifestVersionStrategy;
1618
use Symfony\Component\HttpClient\MockHttpClient;
1719
use Symfony\Component\HttpClient\Response\MockResponse;
1820

1921
class JsonManifestVersionStrategyTest extends TestCase
2022
{
2123
/**
22-
* @dataProvider ProvideValidStrategies
24+
* @dataProvider provideValidStrategies
2325
*/
2426
public function testGetVersion(JsonManifestVersionStrategy $strategy)
2527
{
2628
$this->assertSame('main.123abc.js', $strategy->getVersion('main.js'));
2729
}
2830

2931
/**
30-
* @dataProvider ProvideValidStrategies
32+
* @dataProvider provideValidStrategies
3133
*/
3234
public function testApplyVersion(JsonManifestVersionStrategy $strategy)
3335
{
3436
$this->assertSame('css/styles.555def.css', $strategy->applyVersion('css/styles.css'));
3537
}
3638

3739
/**
38-
* @dataProvider ProvideValidStrategies
40+
* @dataProvider provideValidStrategies
3941
*/
4042
public function testApplyVersionWhenKeyDoesNotExistInManifest(JsonManifestVersionStrategy $strategy)
4143
{
4244
$this->assertSame('css/other.css', $strategy->applyVersion('css/other.css'));
4345
}
4446

4547
/**
46-
* @dataProvider ProvideMissingStrategies
48+
* @dataProvider provideStrictStrategies
49+
*/
50+
public function testStrictExceptionWhenKeyDoesNotExistInManifest(JsonManifestVersionStrategy $strategy, $path, $message)
51+
{
52+
$this->expectException(AssetNotFoundException::class);
53+
$this->expectExceptionMessageMatches($message);
54+
55+
$strategy->getVersion($path);
56+
}
57+
58+
/**
59+
* @dataProvider provideMissingStrategies
4760
*/
4861
public function testMissingManifestFileThrowsException(JsonManifestVersionStrategy $strategy)
4962
{
50-
$this->expectException(\RuntimeException::class);
63+
$this->expectException(RuntimeException::class);
5164
$strategy->getVersion('main.js');
5265
}
5366

5467
/**
55-
* @dataProvider ProvideInvalidStrategies
68+
* @dataProvider provideInvalidStrategies
5669
*/
5770
public function testManifestFileWithBadJSONThrowsException(JsonManifestVersionStrategy $strategy)
5871
{
59-
$this->expectException(\RuntimeException::class);
72+
$this->expectException(RuntimeException::class);
6073
$this->expectExceptionMessage('Error parsing JSON');
6174
$strategy->getVersion('main.js');
6275
}
@@ -100,4 +113,21 @@ public function provideStrategies(string $manifestPath)
100113

101114
yield [new JsonManifestVersionStrategy(__DIR__.'/../fixtures/'.$manifestPath)];
102115
}
116+
117+
public function provideStrictStrategies()
118+
{
119+
$strategy = new JsonManifestVersionStrategy(__DIR__.'/../fixtures/manifest-valid.json', null, true);
120+
121+
yield [
122+
$strategy,
123+
'css/styles.555def.css',
124+
'~Asset "css/styles.555def.css" not found in manifest "(.*)/manifest-valid.json"\. Did you mean one of these\? "css/styles.css", "css/style.css".~',
125+
];
126+
127+
yield [
128+
$strategy,
129+
'img/avatar.png',
130+
'~Asset "img/avatar.png" not found in manifest "(.*)/manifest-valid.json"\.~',
131+
];
132+
}
103133
}
Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
{
22
"main.js": "main.123abc.js",
3-
"css/styles.css": "css/styles.555def.css"
3+
"css/styles.css": "css/styles.555def.css",
4+
"css/style.css": "css/style.abcdef.css",
5+
"main/home.css": "main/home.css"
46
}

0 commit comments

Comments
 (0)
0