From 2025c41bc577a8410b8e1e21a4aef33764e52843 Mon Sep 17 00:00:00 2001 From: Arnaud RITTI Date: Wed, 12 Jan 2022 17:24:26 +0100 Subject: [PATCH 1/3] Fix missing integrity hash on preload Signed-off-by: Hugo Alliaume --- src/Asset/TagRenderer.php | 23 ++++++++++++---- .../PreLoadAssetsEventListener.php | 26 +++++++++++++------ tests/Asset/TagRendererTest.php | 18 +++++++++++++ .../PreLoadAssetsEventListenerTest.php | 19 +++++++++++--- 4 files changed, 70 insertions(+), 16 deletions(-) diff --git a/src/Asset/TagRenderer.php b/src/Asset/TagRenderer.php index bff66db..f7a050a 100644 --- a/src/Asset/TagRenderer.php +++ b/src/Asset/TagRenderer.php @@ -29,6 +29,7 @@ class TagRenderer implements ResetInterface private $eventDispatcher; private $renderedFiles = []; + private $renderedFilesWithAttributes = []; public function __construct( EntrypointLookupCollectionInterface $entrypointLookupCollection, @@ -48,7 +49,7 @@ public function __construct( $this->reset(); } - public function renderWebpackScriptTags(string $entryName, ?string $packageName = null, ?string $entrypointName = null, array $extraAttributes = []): string + public function renderWebpackScriptTags(string $entryName, ?string $packageName = null, ?string $entrypointName = null, array $extraAttributes = [], bool $includeAttributes = false): string { $entrypointName = $entrypointName ?: '_default'; $scriptTags = []; @@ -79,13 +80,14 @@ public function renderWebpackScriptTags(string $entryName, ?string $packageName $this->convertArrayToAttributes($attributes) ); - $this->renderedFiles['scripts'][] = $attributes['src']; + $this->renderedFiles['scripts'][] = $attributes["src"]; + $this->renderedFilesWithAttributes['scripts'][] = $attributes; } return implode('', $scriptTags); } - public function renderWebpackLinkTags(string $entryName, ?string $packageName = null, ?string $entrypointName = null, array $extraAttributes = []): string + public function renderWebpackLinkTags(string $entryName, ?string $packageName = null, ?string $entrypointName = null, array $extraAttributes = [], bool $includeAttributes = false): string { $entrypointName = $entrypointName ?: '_default'; $scriptTags = []; @@ -117,7 +119,8 @@ public function renderWebpackLinkTags(string $entryName, ?string $packageName = $this->convertArrayToAttributes($attributes) ); - $this->renderedFiles['styles'][] = $attributes['href']; + $this->renderedFiles['styles'][] = $attributes["href"]; + $this->renderedFilesWithAttributes['styles'][] = $attributes; } return implode('', $scriptTags); @@ -133,6 +136,16 @@ public function getRenderedStyles(): array return $this->renderedFiles['styles']; } + public function getRenderedScriptsWithAttributes(): array + { + return $this->renderedFilesWithAttributes['scripts']; + } + + public function getRenderedStylesWithAttributes(): array + { + return $this->renderedFilesWithAttributes['styles']; + } + public function getDefaultAttributes(): array { return $this->defaultAttributes; @@ -140,7 +153,7 @@ public function getDefaultAttributes(): array public function reset(): void { - $this->renderedFiles = [ + $this->renderedFiles = $this->renderedFilesWithAttributes = [ 'scripts' => [], 'styles' => [], ]; diff --git a/src/EventListener/PreLoadAssetsEventListener.php b/src/EventListener/PreLoadAssetsEventListener.php index 635496b..b0af22b 100644 --- a/src/EventListener/PreLoadAssetsEventListener.php +++ b/src/EventListener/PreLoadAssetsEventListener.php @@ -49,21 +49,31 @@ public function onKernelResponse(ResponseEvent $event): void $defaultAttributes = $this->tagRenderer->getDefaultAttributes(); $crossOrigin = $defaultAttributes['crossorigin'] ?? false; - foreach ($this->tagRenderer->getRenderedScripts() as $href) { - $link = $this->createLink('preload', $href)->withAttribute('as', 'script'); + foreach ($this->tagRenderer->getRenderedScriptsWithAttributes() as $attributes) { + $attributes = array_merge($defaultAttributes, $attributes); - if (false !== $crossOrigin) { - $link = $link->withAttribute('crossorigin', $crossOrigin); + $link = ($this->createLink('preload', $attributes['src']))->withAttribute('as', 'script'); + + if (!empty($attributes['crossorigin']) && false !== $attributes['crossorigin']) { + $link = $link->withAttribute('crossorigin', $attributes['crossorigin']); + } + if (!empty($attributes['integrity'])) { + $link = $link->withAttribute('integrity', $attributes['integrity']); } $linkProvider = $linkProvider->withLink($link); } - foreach ($this->tagRenderer->getRenderedStyles() as $href) { - $link = $this->createLink('preload', $href)->withAttribute('as', 'style'); + foreach ($this->tagRenderer->getRenderedStylesWithAttributes() as $attributes) { + $attributes = array_merge($defaultAttributes, $attributes); - if (false !== $crossOrigin) { - $link = $link->withAttribute('crossorigin', $crossOrigin); + $link = ($this->createLink('preload', $attributes['href']))->withAttribute('as', 'style'); + + if (!empty($attributes['crossorigin']) && false !== $attributes['crossorigin']) { + $link = $link->withAttribute('crossorigin', $attributes['crossorigin']); + } + if (!empty($attributes['integrity'])) { + $link = $link->withAttribute('integrity', $attributes['integrity']); } $linkProvider = $linkProvider->withLink($link); diff --git a/tests/Asset/TagRendererTest.php b/tests/Asset/TagRendererTest.php index 8daaace..18f05ee 100644 --- a/tests/Asset/TagRendererTest.php +++ b/tests/Asset/TagRendererTest.php @@ -301,8 +301,26 @@ public function testGetRenderedFilesAndReset() $this->assertSame(['http://localhost:8080/build/file1.js', 'http://localhost:8080/build/file2.js'], $renderer->getRenderedScripts()); $this->assertSame(['http://localhost:8080/build/file1.css'], $renderer->getRenderedStyles()); + $this->assertSame([ + [ + 'src' => 'http://localhost:8080/build/file1.js', + ], + [ + 'src' => 'http://localhost:8080/build/file2.js', + ], + ], $renderer->getRenderedScriptsWithAttributes()); + $this->assertSame([ + [ + 'rel' => 'stylesheet', + 'href' => 'http://localhost:8080/build/file1.css', + ], + ], $renderer->getRenderedStylesWithAttributes()); + + $renderer->reset(); $this->assertEmpty($renderer->getRenderedScripts()); $this->assertEmpty($renderer->getRenderedStyles()); + $this->assertEmpty($renderer->getRenderedScriptsWithAttributes()); + $this->assertEmpty($renderer->getRenderedStylesWithAttributes()); } } diff --git a/tests/EventListener/PreLoadAssetsEventListenerTest.php b/tests/EventListener/PreLoadAssetsEventListenerTest.php index 4c5e72e..66bfe49 100644 --- a/tests/EventListener/PreLoadAssetsEventListenerTest.php +++ b/tests/EventListener/PreLoadAssetsEventListenerTest.php @@ -30,8 +30,17 @@ public function testItPreloadsAssets() { $tagRenderer = $this->createMock(TagRenderer::class); $tagRenderer->expects($this->once())->method('getDefaultAttributes')->willReturn(['crossorigin' => 'anonymous']); - $tagRenderer->expects($this->once())->method('getRenderedScripts')->willReturn(['/file1.js']); - $tagRenderer->expects($this->once())->method('getRenderedStyles')->willReturn(['/css/file1.css']); + $tagRenderer->expects($this->once())->method('getRenderedScripts')->willReturn([ + [ + 'src' => '/file1.js', + ], + ]); + $tagRenderer->expects($this->once())->method('getRenderedStyles')->willReturn([ + [ + 'rel' => 'stylesheet', + 'href' => '/css/file1.css', + ], + ]); $request = new Request(); $response = new Response(); @@ -60,7 +69,11 @@ public function testItReusesExistingLinkProvider() { $tagRenderer = $this->createMock(TagRenderer::class); $tagRenderer->expects($this->once())->method('getDefaultAttributes')->willReturn(['crossorigin' => 'anonymous']); - $tagRenderer->expects($this->once())->method('getRenderedScripts')->willReturn(['/file1.js']); + $tagRenderer->expects($this->once())->method('getRenderedScripts')->willReturn([ + [ + 'src' => '/file1.js', + ], + ]); $tagRenderer->expects($this->once())->method('getRenderedStyles')->willReturn([]); $request = new Request(); From 707cd495444a56714f67c0e58503bf5aaf235ed5 Mon Sep 17 00:00:00 2001 From: Hugo Alliaume Date: Tue, 1 Oct 2024 18:02:17 +0200 Subject: [PATCH 2/3] style: php-cs-fixer --- src/Asset/TagRenderer.php | 4 ++-- src/EventListener/PreLoadAssetsEventListener.php | 4 ++-- tests/Asset/TagRendererTest.php | 1 - 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/Asset/TagRenderer.php b/src/Asset/TagRenderer.php index f7a050a..e1e7dd2 100644 --- a/src/Asset/TagRenderer.php +++ b/src/Asset/TagRenderer.php @@ -80,7 +80,7 @@ public function renderWebpackScriptTags(string $entryName, ?string $packageName $this->convertArrayToAttributes($attributes) ); - $this->renderedFiles['scripts'][] = $attributes["src"]; + $this->renderedFiles['scripts'][] = $attributes['src']; $this->renderedFilesWithAttributes['scripts'][] = $attributes; } @@ -119,7 +119,7 @@ public function renderWebpackLinkTags(string $entryName, ?string $packageName = $this->convertArrayToAttributes($attributes) ); - $this->renderedFiles['styles'][] = $attributes["href"]; + $this->renderedFiles['styles'][] = $attributes['href']; $this->renderedFilesWithAttributes['styles'][] = $attributes; } diff --git a/src/EventListener/PreLoadAssetsEventListener.php b/src/EventListener/PreLoadAssetsEventListener.php index b0af22b..38cf2b3 100644 --- a/src/EventListener/PreLoadAssetsEventListener.php +++ b/src/EventListener/PreLoadAssetsEventListener.php @@ -52,7 +52,7 @@ public function onKernelResponse(ResponseEvent $event): void foreach ($this->tagRenderer->getRenderedScriptsWithAttributes() as $attributes) { $attributes = array_merge($defaultAttributes, $attributes); - $link = ($this->createLink('preload', $attributes['src']))->withAttribute('as', 'script'); + $link = $this->createLink('preload', $attributes['src'])->withAttribute('as', 'script'); if (!empty($attributes['crossorigin']) && false !== $attributes['crossorigin']) { $link = $link->withAttribute('crossorigin', $attributes['crossorigin']); @@ -67,7 +67,7 @@ public function onKernelResponse(ResponseEvent $event): void foreach ($this->tagRenderer->getRenderedStylesWithAttributes() as $attributes) { $attributes = array_merge($defaultAttributes, $attributes); - $link = ($this->createLink('preload', $attributes['href']))->withAttribute('as', 'style'); + $link = $this->createLink('preload', $attributes['href'])->withAttribute('as', 'style'); if (!empty($attributes['crossorigin']) && false !== $attributes['crossorigin']) { $link = $link->withAttribute('crossorigin', $attributes['crossorigin']); diff --git a/tests/Asset/TagRendererTest.php b/tests/Asset/TagRendererTest.php index 18f05ee..99442fa 100644 --- a/tests/Asset/TagRendererTest.php +++ b/tests/Asset/TagRendererTest.php @@ -316,7 +316,6 @@ public function testGetRenderedFilesAndReset() ], ], $renderer->getRenderedStylesWithAttributes()); - $renderer->reset(); $this->assertEmpty($renderer->getRenderedScripts()); $this->assertEmpty($renderer->getRenderedStyles()); From b8219a818c1057a079aa6fda66388e5e6eaa73bc Mon Sep 17 00:00:00 2001 From: Hugo Alliaume Date: Tue, 1 Oct 2024 22:48:09 +0200 Subject: [PATCH 3/3] Pass all attributes to `Link` header Signed-off-by: Hugo Alliaume --- CHANGELOG.md | 6 +++ src/Asset/TagRenderer.php | 38 +++++++++++-------- .../PreLoadAssetsEventListener.php | 32 ++++++++-------- tests/Asset/TagRendererTest.php | 8 ++-- .../PreLoadAssetsEventListenerTest.php | 6 +-- 5 files changed, 51 insertions(+), 39 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 046d163..83acd95 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## v2.2.0 + +- #236 Allow entrypoints.json to be hosted remotely (@rlvdx & @Kocal) +- #232 fix: correctly wire the build-time file into kernel.build_dir (@dkarlovi) +- #237 Fix missing integrity hash on preload (@arnaud-ritti & @Kocal) + ## v2.1.0 - #233 Add support for PHP 8.3 and PHP 8.4 (@Kocal) diff --git a/src/Asset/TagRenderer.php b/src/Asset/TagRenderer.php index e1e7dd2..a422356 100644 --- a/src/Asset/TagRenderer.php +++ b/src/Asset/TagRenderer.php @@ -28,7 +28,9 @@ class TagRenderer implements ResetInterface private $defaultLinkAttributes; private $eventDispatcher; + // TODO WebpackEncoreBundle 3.0: remove this property private $renderedFiles = []; + // TODO WebpackEncoreBundle 3.0: rename this property to $renderedFiles private $renderedFilesWithAttributes = []; public function __construct( @@ -87,7 +89,7 @@ public function renderWebpackScriptTags(string $entryName, ?string $packageName return implode('', $scriptTags); } - public function renderWebpackLinkTags(string $entryName, ?string $packageName = null, ?string $entrypointName = null, array $extraAttributes = [], bool $includeAttributes = false): string + public function renderWebpackLinkTags(string $entryName, ?string $packageName = null, ?string $entrypointName = null, array $extraAttributes = []): string { $entrypointName = $entrypointName ?: '_default'; $scriptTags = []; @@ -126,24 +128,30 @@ public function renderWebpackLinkTags(string $entryName, ?string $packageName = return implode('', $scriptTags); } - public function getRenderedScripts(): array + /** + * @param bool $includeAttributes Whether to include the attributes or not. + * In WebpackEncoreBundle 3.0, this parameter will be removed, + * and the attributes will always be included. + * TODO WebpackEncoreBundle 3.0 + * + * @return ($includeAttributes is true ? list> : list) + */ + public function getRenderedScripts(bool $includeAttributes = false): array { - return $this->renderedFiles['scripts']; + return $includeAttributes ? $this->renderedFilesWithAttributes['scripts'] : $this->renderedFiles['scripts']; } - public function getRenderedStyles(): array + /** + * @param bool $includeAttributes Whether to include the attributes or not. + * In WebpackEncoreBundle 3.0, this parameter will be removed, + * and the attributes will always be included. + * TODO WebpackEncoreBundle 3.0 + * + * @return ($includeAttributes is true ? list> : list) + */ + public function getRenderedStyles(bool $includeAttributes = false): array { - return $this->renderedFiles['styles']; - } - - public function getRenderedScriptsWithAttributes(): array - { - return $this->renderedFilesWithAttributes['scripts']; - } - - public function getRenderedStylesWithAttributes(): array - { - return $this->renderedFilesWithAttributes['styles']; + return $includeAttributes ? $this->renderedFilesWithAttributes['styles'] : $this->renderedFiles['styles']; } public function getDefaultAttributes(): array diff --git a/src/EventListener/PreLoadAssetsEventListener.php b/src/EventListener/PreLoadAssetsEventListener.php index 38cf2b3..cd54e48 100644 --- a/src/EventListener/PreLoadAssetsEventListener.php +++ b/src/EventListener/PreLoadAssetsEventListener.php @@ -47,33 +47,31 @@ public function onKernelResponse(ResponseEvent $event): void /** @var GenericLinkProvider $linkProvider */ $linkProvider = $request->attributes->get('_links'); $defaultAttributes = $this->tagRenderer->getDefaultAttributes(); - $crossOrigin = $defaultAttributes['crossorigin'] ?? false; - foreach ($this->tagRenderer->getRenderedScriptsWithAttributes() as $attributes) { - $attributes = array_merge($defaultAttributes, $attributes); + foreach ($this->tagRenderer->getRenderedScripts(true) as $attributes) { + $src = $attributes['src']; + unset($attributes['src']); + $attributes = [...$defaultAttributes, ...$attributes]; - $link = $this->createLink('preload', $attributes['src'])->withAttribute('as', 'script'); + $link = $this->createLink('preload', $src) + ->withAttribute('as', 'script'); - if (!empty($attributes['crossorigin']) && false !== $attributes['crossorigin']) { - $link = $link->withAttribute('crossorigin', $attributes['crossorigin']); - } - if (!empty($attributes['integrity'])) { - $link = $link->withAttribute('integrity', $attributes['integrity']); + foreach ($attributes as $k => $v) { + $link = $link->withAttribute($k, $v); } $linkProvider = $linkProvider->withLink($link); } - foreach ($this->tagRenderer->getRenderedStylesWithAttributes() as $attributes) { - $attributes = array_merge($defaultAttributes, $attributes); + foreach ($this->tagRenderer->getRenderedStyles(true) as $attributes) { + $href = $attributes['href']; + unset($attributes['href']); + $attributes = [...$defaultAttributes, ...$attributes]; - $link = $this->createLink('preload', $attributes['href'])->withAttribute('as', 'style'); + $link = $this->createLink('preload', $href)->withAttribute('as', 'style'); - if (!empty($attributes['crossorigin']) && false !== $attributes['crossorigin']) { - $link = $link->withAttribute('crossorigin', $attributes['crossorigin']); - } - if (!empty($attributes['integrity'])) { - $link = $link->withAttribute('integrity', $attributes['integrity']); + foreach ($attributes as $k => $v) { + $link = $link->withAttribute($k, $v); } $linkProvider = $linkProvider->withLink($link); diff --git a/tests/Asset/TagRendererTest.php b/tests/Asset/TagRendererTest.php index 99442fa..9d18a6c 100644 --- a/tests/Asset/TagRendererTest.php +++ b/tests/Asset/TagRendererTest.php @@ -308,18 +308,18 @@ public function testGetRenderedFilesAndReset() [ 'src' => 'http://localhost:8080/build/file2.js', ], - ], $renderer->getRenderedScriptsWithAttributes()); + ], $renderer->getRenderedScripts(true)); $this->assertSame([ [ 'rel' => 'stylesheet', 'href' => 'http://localhost:8080/build/file1.css', ], - ], $renderer->getRenderedStylesWithAttributes()); + ], $renderer->getRenderedStyles(true)); $renderer->reset(); $this->assertEmpty($renderer->getRenderedScripts()); $this->assertEmpty($renderer->getRenderedStyles()); - $this->assertEmpty($renderer->getRenderedScriptsWithAttributes()); - $this->assertEmpty($renderer->getRenderedStylesWithAttributes()); + $this->assertEmpty($renderer->getRenderedScripts(true)); + $this->assertEmpty($renderer->getRenderedStyles(true)); } } diff --git a/tests/EventListener/PreLoadAssetsEventListenerTest.php b/tests/EventListener/PreLoadAssetsEventListenerTest.php index 66bfe49..5e42e7f 100644 --- a/tests/EventListener/PreLoadAssetsEventListenerTest.php +++ b/tests/EventListener/PreLoadAssetsEventListenerTest.php @@ -30,12 +30,12 @@ public function testItPreloadsAssets() { $tagRenderer = $this->createMock(TagRenderer::class); $tagRenderer->expects($this->once())->method('getDefaultAttributes')->willReturn(['crossorigin' => 'anonymous']); - $tagRenderer->expects($this->once())->method('getRenderedScripts')->willReturn([ + $tagRenderer->expects($this->once())->method('getRenderedScripts')->with(true)->willReturn([ [ 'src' => '/file1.js', ], ]); - $tagRenderer->expects($this->once())->method('getRenderedStyles')->willReturn([ + $tagRenderer->expects($this->once())->method('getRenderedStyles')->with(true)->willReturn([ [ 'rel' => 'stylesheet', 'href' => '/css/file1.css', @@ -62,7 +62,7 @@ public function testItPreloadsAssets() $this->assertSame('/css/file1.css', $links[1]->getHref()); $this->assertSame(['preload'], $links[1]->getRels()); - $this->assertSame(['as' => 'style', 'crossorigin' => 'anonymous'], $links[1]->getAttributes()); + $this->assertSame(['as' => 'style', 'crossorigin' => 'anonymous', 'rel' => 'stylesheet'], $links[1]->getAttributes()); } public function testItReusesExistingLinkProvider()