Allow env variables in json_manifest_path

This commit is contained in:
Jérémy Derussé 2020-12-13 19:17:49 +01:00
parent c82567b02f
commit 4e4a81c346
No known key found for this signature in database
GPG Key ID: 2083FA5758C473D2
15 changed files with 138 additions and 33 deletions

View File

@ -1,6 +1,11 @@
UPGRADE FROM 5.2 to 5.3 UPGRADE FROM 5.2 to 5.3
======================= =======================
Asset
-----
* Deprecated `RemoteJsonManifestVersionStrategy`, use `JsonManifestVersionStrategy` instead.
Form Form
---- ----

View File

@ -1,6 +1,11 @@
UPGRADE FROM 5.x to 6.0 UPGRADE FROM 5.x to 6.0
======================= =======================
Asset
-----
* Removed `RemoteJsonManifestVersionStrategy`, use `JsonManifestVersionStrategy` instead.
Config Config
------ ------

View File

@ -1129,12 +1129,7 @@ class FrameworkExtension extends Extension
} }
if (null !== $jsonManifestPath) { if (null !== $jsonManifestPath) {
$definitionName = 'assets.json_manifest_version_strategy'; $def = new ChildDefinition('assets.json_manifest_version_strategy');
if (0 === strpos(parse_url($jsonManifestPath, \PHP_URL_SCHEME), 'http')) {
$definitionName = 'assets.remote_json_manifest_version_strategy';
}
$def = new ChildDefinition($definitionName);
$def->replaceArgument(0, $jsonManifestPath); $def->replaceArgument(0, $jsonManifestPath);
$container->setDefinition('assets._version_'.$name, $def); $container->setDefinition('assets._version_'.$name, $def);

View File

@ -77,10 +77,12 @@ return static function (ContainerConfigurator $container) {
->abstract() ->abstract()
->args([ ->args([
abstract_arg('manifest path'), abstract_arg('manifest path'),
service('http_client'),
]) ])
->set('assets.remote_json_manifest_version_strategy', RemoteJsonManifestVersionStrategy::class) ->set('assets.remote_json_manifest_version_strategy', RemoteJsonManifestVersionStrategy::class)
->abstract() ->abstract()
->deprecate('symfony/framework-bundle', '5.3', 'The "%service_id%" service is deprecated, use "assets.json_manifest_version_strategy" instead.')
->args([ ->args([
abstract_arg('manifest url'), abstract_arg('manifest url'),
service('http_client'), service('http_client'),

View File

@ -30,6 +30,15 @@ $container->loadFromExtension('framework', [
'remote_manifest' => [ 'remote_manifest' => [
'json_manifest_path' => 'https://cdn.example.com/manifest.json', 'json_manifest_path' => 'https://cdn.example.com/manifest.json',
], ],
'var_manifest' => [
'json_manifest_path' => '%var_json_manifest_path%',
],
'env_manifest' => [
'json_manifest_path' => '%env(env_manifest)%',
],
], ],
], ],
]); ]);
$container->setParameter('var_json_manifest_path', 'https://cdn.example.com/manifest.json');
$container->setParameter('env(env_manifest)', 'https://cdn.example.com/manifest.json');

View File

@ -23,6 +23,13 @@
</framework:package> </framework:package>
<framework:package name="json_manifest_strategy" json-manifest-path="/path/to/manifest.json" /> <framework:package name="json_manifest_strategy" json-manifest-path="/path/to/manifest.json" />
<framework:package name="remote_manifest" json-manifest-path="https://cdn.example.com/manifest.json" /> <framework:package name="remote_manifest" json-manifest-path="https://cdn.example.com/manifest.json" />
<framework:package name="var_manifest" json-manifest-path="%var_json_manifest_path%" />
<framework:package name="env_manifest" json-manifest-path="%env(env_manifest)%" />
</framework:assets> </framework:assets>
</framework:config> </framework:config>
<parameters>
<parameter key="var_json_manifest_path">https://cdn.example.com/manifest.json</parameter>
<parameter key="env(env_manifest)">https://cdn.example.com/manifest.json</parameter>
</parameters>
</container> </container>

View File

@ -21,3 +21,11 @@ framework:
json_manifest_path: '/path/to/manifest.json' json_manifest_path: '/path/to/manifest.json'
remote_manifest: remote_manifest:
json_manifest_path: 'https://cdn.example.com/manifest.json' json_manifest_path: 'https://cdn.example.com/manifest.json'
var_manifest:
json_manifest_path: '%var_json_manifest_path%'
env_manifest:
json_manifest_path: '%env(env_manifest)%'
parameters:
var_json_manifest_path: 'https://cdn.example.com/manifest.json'
env(env_manifest): https://cdn.example.com/manifest.json

View File

@ -597,7 +597,7 @@ abstract class FrameworkExtensionTest extends TestCase
// packages // packages
$packages = $packages->getArgument(1); $packages = $packages->getArgument(1);
$this->assertCount(7, $packages); $this->assertCount(9, $packages);
$package = $container->getDefinition((string) $packages['images_path']); $package = $container->getDefinition((string) $packages['images_path']);
$this->assertPathPackage($container, $package, '/foo', 'SomeVersionScheme', '%%s?version=%%s'); $this->assertPathPackage($container, $package, '/foo', 'SomeVersionScheme', '%%s?version=%%s');
@ -621,8 +621,18 @@ abstract class FrameworkExtensionTest extends TestCase
$package = $container->getDefinition($packages['remote_manifest']); $package = $container->getDefinition($packages['remote_manifest']);
$versionStrategy = $container->getDefinition($package->getArgument(1)); $versionStrategy = $container->getDefinition($package->getArgument(1));
$this->assertSame('assets.remote_json_manifest_version_strategy', $versionStrategy->getParent()); $this->assertSame('assets.json_manifest_version_strategy', $versionStrategy->getParent());
$this->assertSame('https://cdn.example.com/manifest.json', $versionStrategy->getArgument(0)); $this->assertSame('https://cdn.example.com/manifest.json', $versionStrategy->getArgument(0));
$package = $container->getDefinition($packages['var_manifest']);
$versionStrategy = $container->getDefinition($package->getArgument(1));
$this->assertSame('assets.json_manifest_version_strategy', $versionStrategy->getParent());
$this->assertSame('https://cdn.example.com/manifest.json', $versionStrategy->getArgument(0));
$package = $container->getDefinition($packages['env_manifest']);
$versionStrategy = $container->getDefinition($package->getArgument(1));
$this->assertSame('assets.json_manifest_version_strategy', $versionStrategy->getParent());
$this->assertStringMatchesFormat('env_%s', $versionStrategy->getArgument(0));
} }
public function testAssetsDefaultVersionStrategyAsService() public function testAssetsDefaultVersionStrategyAsService()

View File

@ -34,7 +34,7 @@
"require-dev": { "require-dev": {
"doctrine/annotations": "~1.7", "doctrine/annotations": "~1.7",
"doctrine/cache": "~1.0", "doctrine/cache": "~1.0",
"symfony/asset": "^5.1", "symfony/asset": "^5.3",
"symfony/browser-kit": "^4.4|^5.0", "symfony/browser-kit": "^4.4|^5.0",
"symfony/console": "^5.2", "symfony/console": "^5.2",
"symfony/css-selector": "^4.4|^5.0", "symfony/css-selector": "^4.4|^5.0",
@ -71,7 +71,7 @@
"phpdocumentor/reflection-docblock": "<3.0", "phpdocumentor/reflection-docblock": "<3.0",
"phpdocumentor/type-resolver": "<0.2.1", "phpdocumentor/type-resolver": "<0.2.1",
"phpunit/phpunit": "<5.4.3", "phpunit/phpunit": "<5.4.3",
"symfony/asset": "<5.1", "symfony/asset": "<5.3",
"symfony/browser-kit": "<4.4", "symfony/browser-kit": "<4.4",
"symfony/console": "<5.2", "symfony/console": "<5.2",
"symfony/dotenv": "<5.1", "symfony/dotenv": "<5.1",

View File

@ -1,6 +1,11 @@
CHANGELOG CHANGELOG
========= =========
5.3.0
-----
* deprecated `RemoteJsonManifestVersionStrategy`, use `JsonManifestVersionStrategy` instead.
5.1.0 5.1.0
----- -----

View File

@ -13,47 +13,83 @@ namespace Symfony\Component\Asset\Tests\VersionStrategy;
use PHPUnit\Framework\TestCase; use PHPUnit\Framework\TestCase;
use Symfony\Component\Asset\VersionStrategy\JsonManifestVersionStrategy; use Symfony\Component\Asset\VersionStrategy\JsonManifestVersionStrategy;
use Symfony\Component\HttpClient\MockHttpClient;
use Symfony\Component\HttpClient\Response\MockResponse;
class JsonManifestVersionStrategyTest extends TestCase class JsonManifestVersionStrategyTest extends TestCase
{ {
public function testGetVersion() /**
* @dataProvider ProvideValidStrategies
*/
public function testGetVersion(JsonManifestVersionStrategy $strategy)
{ {
$strategy = $this->createStrategy('manifest-valid.json');
$this->assertSame('main.123abc.js', $strategy->getVersion('main.js')); $this->assertSame('main.123abc.js', $strategy->getVersion('main.js'));
} }
public function testApplyVersion() /**
* @dataProvider ProvideValidStrategies
*/
public function testApplyVersion(JsonManifestVersionStrategy $strategy)
{ {
$strategy = $this->createStrategy('manifest-valid.json');
$this->assertSame('css/styles.555def.css', $strategy->applyVersion('css/styles.css')); $this->assertSame('css/styles.555def.css', $strategy->applyVersion('css/styles.css'));
} }
public function testApplyVersionWhenKeyDoesNotExistInManifest() /**
* @dataProvider ProvideValidStrategies
*/
public function testApplyVersionWhenKeyDoesNotExistInManifest(JsonManifestVersionStrategy $strategy)
{ {
$strategy = $this->createStrategy('manifest-valid.json');
$this->assertSame('css/other.css', $strategy->applyVersion('css/other.css')); $this->assertSame('css/other.css', $strategy->applyVersion('css/other.css'));
} }
public function testMissingManifestFileThrowsException() /**
* @dataProvider ProvideMissingStrategies
*/
public function testMissingManifestFileThrowsException(JsonManifestVersionStrategy $strategy)
{ {
$this->expectException('RuntimeException'); $this->expectException('RuntimeException');
$strategy = $this->createStrategy('non-existent-file.json');
$strategy->getVersion('main.js'); $strategy->getVersion('main.js');
} }
public function testManifestFileWithBadJSONThrowsException() /**
* @dataProvider ProvideInvalidStrategies
*/
public function testManifestFileWithBadJSONThrowsException(JsonManifestVersionStrategy $strategy)
{ {
$this->expectException('RuntimeException'); $this->expectException('RuntimeException');
$this->expectExceptionMessage('Error parsing JSON'); $this->expectExceptionMessage('Error parsing JSON');
$strategy = $this->createStrategy('manifest-invalid.json');
$strategy->getVersion('main.js'); $strategy->getVersion('main.js');
} }
private function createStrategy($manifestFilename) public function provideValidStrategies()
{ {
return new JsonManifestVersionStrategy(__DIR__.'/../fixtures/'.$manifestFilename); yield from $this->provideStrategies('manifest-valid.json');
}
public function provideInvalidStrategies()
{
yield from $this->provideStrategies('manifest-invalid.json');
}
public function provideMissingStrategies()
{
yield from $this->provideStrategies('non-existent-file.json');
}
public function provideStrategies(string $manifestPath)
{
$httpClient = new MockHttpClient(function ($method, $url, $options) {
$filename = __DIR__.'/../fixtures/'.basename($url);
if (file_exists($filename)) {
return new MockResponse(file_get_contents($filename), ['http_headers' => ['content-type' => 'application/json']]);
}
return new MockResponse('{}', ['http_code' => 404]);
});
yield [new JsonManifestVersionStrategy('https://cdn.example.com/'.$manifestPath, $httpClient)];
yield [new JsonManifestVersionStrategy(__DIR__.'/../fixtures/'.$manifestPath)];
} }
} }

View File

@ -17,6 +17,9 @@ use Symfony\Component\HttpClient\Exception\JsonException;
use Symfony\Component\HttpClient\MockHttpClient; use Symfony\Component\HttpClient\MockHttpClient;
use Symfony\Component\HttpClient\Response\MockResponse; use Symfony\Component\HttpClient\Response\MockResponse;
/**
* @group legacy
*/
class RemoteJsonManifestVersionStrategyTest extends TestCase class RemoteJsonManifestVersionStrategyTest extends TestCase
{ {
public function testGetVersion() public function testGetVersion()

View File

@ -11,6 +11,9 @@
namespace Symfony\Component\Asset\VersionStrategy; namespace Symfony\Component\Asset\VersionStrategy;
use Symfony\Contracts\HttpClient\Exception\DecodingExceptionInterface;
use Symfony\Contracts\HttpClient\HttpClientInterface;
/** /**
* Reads the versioned path of an asset from a JSON manifest file. * Reads the versioned path of an asset from a JSON manifest file.
* *
@ -26,13 +29,15 @@ class JsonManifestVersionStrategy implements VersionStrategyInterface
{ {
private $manifestPath; private $manifestPath;
private $manifestData; private $manifestData;
private $httpClient;
/** /**
* @param string $manifestPath Absolute path to the manifest file * @param string $manifestPath Absolute path to the manifest file
*/ */
public function __construct(string $manifestPath) public function __construct(string $manifestPath, HttpClientInterface $httpClient = null)
{ {
$this->manifestPath = $manifestPath; $this->manifestPath = $manifestPath;
$this->httpClient = $httpClient;
} }
/** /**
@ -53,6 +58,15 @@ class JsonManifestVersionStrategy implements VersionStrategyInterface
private function getManifestPath(string $path): ?string private function getManifestPath(string $path): ?string
{ {
if (null === $this->manifestData) { if (null === $this->manifestData) {
if (null !== $this->httpClient && 0 === strpos(parse_url($this->manifestPath, \PHP_URL_SCHEME), 'http')) {
try {
$this->manifestData = $this->httpClient->request('GET', $this->manifestPath, [
'headers' => ['accept' => 'application/json'],
])->toArray();
} catch (DecodingExceptionInterface $e) {
throw new \RuntimeException(sprintf('Error parsing JSON from asset manifest URL "%s".', $this->manifestPath), 0, $e);
}
} else {
if (!is_file($this->manifestPath)) { if (!is_file($this->manifestPath)) {
throw new \RuntimeException(sprintf('Asset manifest file "%s" does not exist.', $this->manifestPath)); throw new \RuntimeException(sprintf('Asset manifest file "%s" does not exist.', $this->manifestPath));
} }
@ -62,6 +76,7 @@ class JsonManifestVersionStrategy implements VersionStrategyInterface
throw new \RuntimeException(sprintf('Error parsing JSON from asset manifest file "%s": ', $this->manifestPath).json_last_error_msg()); throw new \RuntimeException(sprintf('Error parsing JSON from asset manifest file "%s": ', $this->manifestPath).json_last_error_msg());
} }
} }
}
return isset($this->manifestData[$path]) ? $this->manifestData[$path] : null; return isset($this->manifestData[$path]) ? $this->manifestData[$path] : null;
} }

View File

@ -13,6 +13,8 @@ namespace Symfony\Component\Asset\VersionStrategy;
use Symfony\Contracts\HttpClient\HttpClientInterface; use Symfony\Contracts\HttpClient\HttpClientInterface;
trigger_deprecation('symfony/asset', '5.3', 'The "%s" class is deprecated, use "%s" instead.', RemoteJsonManifestVersionStrategy::class, JsonManifestVersionStrategy::class);
/** /**
* Reads the versioned path of an asset from a remote JSON manifest file. * Reads the versioned path of an asset from a remote JSON manifest file.
* *
@ -23,6 +25,8 @@ use Symfony\Contracts\HttpClient\HttpClientInterface;
* } * }
* *
* You could then ask for the version of "main.js" or "css/styles.css". * You could then ask for the version of "main.js" or "css/styles.css".
*
* @deprecated since Symfony 5.3, use JsonManifestVersionStrategy instead.
*/ */
class RemoteJsonManifestVersionStrategy implements VersionStrategyInterface class RemoteJsonManifestVersionStrategy implements VersionStrategyInterface
{ {

View File

@ -16,7 +16,8 @@
} }
], ],
"require": { "require": {
"php": ">=7.2.5" "php": ">=7.2.5",
"symfony/deprecation-contracts": "^2.1"
}, },
"suggest": { "suggest": {
"symfony/http-foundation": "" "symfony/http-foundation": ""