From 826b264c20e35e82fb2aeb0ac928d70cde20d6b0 Mon Sep 17 00:00:00 2001 From: Florent Morselli Date: Thu, 25 Apr 2024 17:30:29 +0200 Subject: [PATCH] Refactor event listeners and service workers (#186) The code has been refactored to simplify event listeners and service workers. Redundant event listeners have been removed and replaced with a single FileCompileEventListener. The logic for serving manifest files and service workers has been abstracted into a FileCompilerInterface, which is implemented by ServiceWorkerCompiler and ManifestCompiler. This results in more modular and coherent architecture. --- src/Resources/config/services.php | 18 +- src/Service/Data.php | 29 +++ src/Service/FileCompilerInterface.php | 15 ++ .../ManifestCompiler.php} | 79 +++++--- src/Service/ServiceWorkerCompiler.php | 123 +++++++++++- src/SpomkyLabsPwaBundle.php | 3 + src/Subscriber/FileCompileEventListener.php | 40 ++++ src/Subscriber/PwaDevServerSubscriber.php | 186 ++---------------- .../ServiceWorkerCompileEventListener.php | 44 ----- .../WorkboxCompileEventListener.php | 57 ------ 10 files changed, 281 insertions(+), 313 deletions(-) create mode 100644 src/Service/Data.php create mode 100644 src/Service/FileCompilerInterface.php rename src/{Subscriber/ManifestCompileEventListener.php => Service/ManifestCompiler.php} (60%) create mode 100644 src/Subscriber/FileCompileEventListener.php delete mode 100644 src/Subscriber/ServiceWorkerCompileEventListener.php delete mode 100644 src/Subscriber/WorkboxCompileEventListener.php diff --git a/src/Resources/config/services.php b/src/Resources/config/services.php index f11b9ea..919c933 100644 --- a/src/Resources/config/services.php +++ b/src/Resources/config/services.php @@ -16,14 +16,14 @@ use SpomkyLabs\PwaBundle\ImageProcessor\GDImageProcessor; use SpomkyLabs\PwaBundle\ImageProcessor\ImagickImageProcessor; use SpomkyLabs\PwaBundle\MatchCallbackHandler\MatchCallbackHandlerInterface; +use SpomkyLabs\PwaBundle\Service\FileCompilerInterface; use SpomkyLabs\PwaBundle\Service\ManifestBuilder; +use SpomkyLabs\PwaBundle\Service\ManifestCompiler; use SpomkyLabs\PwaBundle\Service\ServiceWorkerBuilder; use SpomkyLabs\PwaBundle\Service\ServiceWorkerCompiler; use SpomkyLabs\PwaBundle\ServiceWorkerRule\ServiceWorkerRuleInterface; -use SpomkyLabs\PwaBundle\Subscriber\ManifestCompileEventListener; +use SpomkyLabs\PwaBundle\Subscriber\FileCompileEventListener; use SpomkyLabs\PwaBundle\Subscriber\PwaDevServerSubscriber; -use SpomkyLabs\PwaBundle\Subscriber\ServiceWorkerCompileEventListener; -use SpomkyLabs\PwaBundle\Subscriber\WorkboxCompileEventListener; use SpomkyLabs\PwaBundle\Twig\InstanceOfExtension; use SpomkyLabs\PwaBundle\Twig\PwaExtension; use SpomkyLabs\PwaBundle\Twig\PwaRuntime; @@ -43,6 +43,8 @@ ->autowire() ; + $container->instanceof(FileCompilerInterface::class)->tag('spomky_labs_pwa.compiler'); + /*** Manifest ***/ $container->set(ManifestBuilder::class) ->args([ @@ -52,6 +54,7 @@ $container->set(Manifest::class) ->factory([service(ManifestBuilder::class), 'create']) ; + $container->set(ManifestCompiler::class); /*** Service Worker ***/ $container->set(ServiceWorkerBuilder::class) @@ -62,8 +65,7 @@ $container->set(ServiceWorker::class) ->factory([service(ServiceWorkerBuilder::class), 'create']) ; - $container->set(ServiceWorkerCompiler::class) - ; + $container->set(ServiceWorkerCompiler::class); /*** Commands ***/ if (class_exists(Client::class) && class_exists(WebDriverDimension::class) && class_exists(MimeTypes::class)) { @@ -96,11 +98,7 @@ } /*** Event Listeners and Subscribers ***/ - $container->set(WorkboxCompileEventListener::class); - $container->set(ManifestCompileEventListener::class); - $container->set(ServiceWorkerCompileEventListener::class); - $container->set(ServiceWorkerCompiler::class); - + $container->set(FileCompileEventListener::class); $container->set(PwaDevServerSubscriber::class) ->args([ '$profiler' => service('profiler') diff --git a/src/Service/Data.php b/src/Service/Data.php new file mode 100644 index 0000000..be7c577 --- /dev/null +++ b/src/Service/Data.php @@ -0,0 +1,29 @@ + $headers + */ + public static function create(string $url, string $data, array $headers = []): self + { + return new self($url, $data, $headers); + } +} diff --git a/src/Service/FileCompilerInterface.php b/src/Service/FileCompilerInterface.php new file mode 100644 index 0000000..8bb7372 --- /dev/null +++ b/src/Service/FileCompilerInterface.php @@ -0,0 +1,15 @@ + + */ + public function supportedPublicUrls(): array; + + public function get(string $publicUrl): null|Data; +} diff --git a/src/Subscriber/ManifestCompileEventListener.php b/src/Service/ManifestCompiler.php similarity index 60% rename from src/Subscriber/ManifestCompileEventListener.php rename to src/Service/ManifestCompiler.php index 6f677fa..6eaa641 100644 --- a/src/Subscriber/ManifestCompileEventListener.php +++ b/src/Service/ManifestCompiler.php @@ -2,53 +2,49 @@ declare(strict_types=1); -namespace SpomkyLabs\PwaBundle\Subscriber; +namespace SpomkyLabs\PwaBundle\Service; use Psr\EventDispatcher\EventDispatcherInterface; use SpomkyLabs\PwaBundle\Dto\Manifest; use SpomkyLabs\PwaBundle\Event\NullEventDispatcher; use SpomkyLabs\PwaBundle\Event\PostManifestCompileEvent; use SpomkyLabs\PwaBundle\Event\PreManifestCompileEvent; -use Symfony\Component\AssetMapper\Event\PreAssetsCompileEvent; -use Symfony\Component\AssetMapper\Path\PublicAssetsFilesystemInterface; use Symfony\Component\DependencyInjection\Attribute\Autowire; -use Symfony\Component\EventDispatcher\Attribute\AsEventListener; use Symfony\Component\Serializer\Encoder\JsonEncode; use Symfony\Component\Serializer\Normalizer\AbstractNormalizer; use Symfony\Component\Serializer\Normalizer\AbstractObjectNormalizer; use Symfony\Component\Serializer\Normalizer\TranslatableNormalizer; use Symfony\Component\Serializer\SerializerInterface; use function assert; -use function count; use const JSON_PRETTY_PRINT; use const JSON_THROW_ON_ERROR; use const JSON_UNESCAPED_SLASHES; use const JSON_UNESCAPED_UNICODE; -#[AsEventListener(PreAssetsCompileEvent::class)] -final readonly class ManifestCompileEventListener +final class ManifestCompiler implements FileCompilerInterface { - private EventDispatcherInterface $dispatcher; + private readonly EventDispatcherInterface $dispatcher; - private string $manifestPublicUrl; + private readonly string $manifestPublicUrl; - private array $jsonOptions; + /** + * @var array + */ + private readonly array $jsonOptions; /** * @param array $locales */ public function __construct( - private SerializerInterface $serializer, - private Manifest $manifest, + private readonly SerializerInterface $serializer, + private readonly Manifest $manifest, #[Autowire('%spomky_labs_pwa.manifest.public_url%')] string $manifestPublicUrl, - #[Autowire('@asset_mapper.local_public_assets_filesystem')] - private PublicAssetsFilesystemInterface $assetsFilesystem, #[Autowire('%kernel.debug%')] bool $debug, null|EventDispatcherInterface $dispatcher, #[Autowire('%kernel.enabled_locales%')] - private array $locales, + private readonly array $locales, ) { $this->dispatcher = $dispatcher ?? new NullEventDispatcher(); $this->manifestPublicUrl = '/' . trim($manifestPublicUrl, '/'); @@ -64,24 +60,46 @@ public function __construct( $this->jsonOptions = $options; } - public function __invoke(PreAssetsCompileEvent $event): void + /** + * @return array + */ + public function supportedPublicUrls(): array { - if (! $this->manifest->enabled) { - return; + if ($this->manifest->enabled === false) { + return []; + } + + if ($this->locales === []) { + return [$this->manifestPublicUrl]; } - $manifest = clone $this->manifest; - if (count($this->locales) === 0 || ! str_contains($this->manifestPublicUrl, '{locale}')) { - $this->compileManifest($manifest, null); - } else { - foreach ($this->locales as $locale) { - $this->compileManifest($manifest, $locale); + return array_map( + fn (string $locale) => str_replace('{locale}', $locale, $this->manifestPublicUrl), + $this->locales + ); + } + + public function get(string $publicUrl): null|Data + { + if ($this->manifest->enabled === false) { + return null; + } + if ($this->locales === []) { + return $this->compileManifest(null); + } + + foreach ($this->locales as $locale) { + if ($publicUrl === str_replace('{locale}', $locale, $this->manifestPublicUrl)) { + return $this->compileManifest($locale); } } + + return null; } - private function compileManifest(Manifest $manifest, null|string $locale): void + private function compileManifest(null|string $locale): Data { + $manifest = clone $this->manifest; $preEvent = new PreManifestCompileEvent($manifest); $preEvent = $this->dispatcher->dispatch($preEvent); assert($preEvent instanceof PreManifestCompileEvent); @@ -98,6 +116,15 @@ private function compileManifest(Manifest $manifest, null|string $locale): void $postEvent = $this->dispatcher->dispatch($postEvent); assert($postEvent instanceof PostManifestCompileEvent); - $this->assetsFilesystem->write($manifestPublicUrl, $postEvent->data); + return Data::create( + $manifestPublicUrl, + $postEvent->data, + [ + 'Cache-Control' => 'public, max-age=604800, immutable', + 'Content-Type' => 'application/manifest+json', + 'X-Manifest-Dev' => true, + 'Etag' => hash('xxh128', $data), + ] + ); } } diff --git a/src/Service/ServiceWorkerCompiler.php b/src/Service/ServiceWorkerCompiler.php index cd8762f..9969270 100644 --- a/src/Service/ServiceWorkerCompiler.php +++ b/src/Service/ServiceWorkerCompiler.php @@ -7,13 +7,23 @@ use SpomkyLabs\PwaBundle\Dto\ServiceWorker; use SpomkyLabs\PwaBundle\ServiceWorkerRule\ServiceWorkerRuleInterface; use Symfony\Component\AssetMapper\AssetMapperInterface; +use Symfony\Component\Config\FileLocator; use Symfony\Component\DependencyInjection\Attribute\Autowire; use Symfony\Component\DependencyInjection\Attribute\TaggedIterator; use function assert; +use function count; +use function in_array; +use function is_array; use function is_string; -final readonly class ServiceWorkerCompiler +final readonly class ServiceWorkerCompiler implements FileCompilerInterface { + private string $serviceWorkerPublicUrl; + + private null|string $workboxPublicUrl; + + private null|string $workboxVersion; + /** * @param iterable $serviceworkerRules */ @@ -25,13 +35,40 @@ public function __construct( #[Autowire('%kernel.debug%')] public bool $debug, ) { + $serviceWorkerPublicUrl = $serviceWorker->dest; + $this->serviceWorkerPublicUrl = '/' . trim($serviceWorkerPublicUrl, '/'); + if ($serviceWorker->workbox->enabled === true) { + $this->workboxVersion = $serviceWorker->workbox->version; + $workboxPublicUrl = $serviceWorker->workbox->workboxPublicUrl; + $this->workboxPublicUrl = '/' . trim($workboxPublicUrl, '/'); + } else { + $this->workboxVersion = null; + $this->workboxPublicUrl = null; + } } - public function compile(): ?string + public function supportedPublicUrls(): array { - if ($this->serviceWorker->enabled === false) { + return [$this->serviceWorkerPublicUrl, ...$this->listWorkboxFiles()]; + } + + public function get(string $publicUrl): null|Data + { + if ($publicUrl === $this->serviceWorkerPublicUrl) { + return $this->compileSW(); + } + if ($this->workboxPublicUrl === null) { + return null; + } + if (! str_starts_with($publicUrl, $this->workboxPublicUrl)) { return null; } + + return $this->getWorkboxFile($publicUrl); + } + + private function compileSW(): Data + { $body = ''; foreach ($this->serviceworkerRules as $rule) { @@ -41,8 +78,17 @@ public function compile(): ?string } $body .= $ruleBody; } + $body .= $this->includeRootSW(); - return $body . $this->includeRootSW(); + return Data::create( + $this->serviceWorkerPublicUrl, + $body, + [ + 'Content-Type' => 'application/javascript', + 'X-SW-Dev' => true, + 'Etag' => hash('xxh128', $body), + ] + ); } private function includeRootSW(): string @@ -59,4 +105,73 @@ private function includeRootSW(): string } return is_string($body) ? $body : ''; } + + /** + * @return array + */ + private function listWorkboxFiles(): array + { + if ($this->serviceWorker->workbox->enabled === false) { + return []; + } + if ($this->serviceWorker->workbox->useCDN === true) { + return []; + } + $fileLocator = new FileLocator(__DIR__ . '/../Resources'); + $resourcePath = $fileLocator->locate(sprintf('workbox-v%s', $this->workboxVersion)); + + $publicUrls = []; + $files = scandir($resourcePath); + assert(is_array($files), 'Unable to list the files.'); + foreach ($files as $file) { + if (in_array($file, ['.', '..'], true)) { + continue; + } + if (str_contains($file, '.dev.') && $this->debug === false) { + continue; + } + $path = sprintf('%s/%s', $resourcePath, $file); + + if (! is_file($path) || ! is_readable($path)) { + continue; + } + $publicUrls[] = sprintf('%s/%s', $this->workboxPublicUrl, $file); + } + + return $publicUrls; + } + + private function getWorkboxFile(string $publicUrl): null|Data + { + $asset = mb_substr($publicUrl, mb_strlen((string) $this->workboxPublicUrl)); + $fileLocator = new FileLocator(__DIR__ . '/../Resources'); + $resource = sprintf('workbox-v%s%s', $this->workboxVersion, $asset); + $resourcePath = $fileLocator->locate($resource, null, false); + if (is_array($resourcePath)) { + if (count($resourcePath) === 1) { + $resourcePath = $resourcePath[0]; + } else { + return null; + } + } + if (! is_string($resourcePath)) { + return null; + } + if (! is_file($resourcePath) || ! is_readable($resourcePath)) { + return null; + } + + $body = file_get_contents($resourcePath); + assert(is_string($body), 'Unable to load the file content.'); + + return Data::create( + $publicUrl, + $body, + [ + 'Content-Type' => 'application/javascript', + 'X-SW-Dev' => true, + 'Etag' => hash('xxh128', $body), + ] + ); + } } diff --git a/src/SpomkyLabsPwaBundle.php b/src/SpomkyLabsPwaBundle.php index 6dd5843..2ed4dc5 100644 --- a/src/SpomkyLabsPwaBundle.php +++ b/src/SpomkyLabsPwaBundle.php @@ -50,6 +50,9 @@ public function loadExtension(array $config, ContainerConfigurator $container, C $builder->setParameter('spomky_labs_pwa.manifest.public_url', $config['manifest']['public_url'] ?? null); $builder->setParameter('spomky_labs_pwa.manifest.config', $manifestConfig); + /*** Favicons ***/ + $builder->setParameter('spomky_labs_pwa.favicons.config', $config['favicons']); + /*** Service Worker ***/ $builder->setParameter('spomky_labs_pwa.sw.enabled', $config['serviceworker']['enabled']); $builder->setParameter('spomky_labs_pwa.sw.public_url', $config['serviceworker']['dest'] ?? null); diff --git a/src/Subscriber/FileCompileEventListener.php b/src/Subscriber/FileCompileEventListener.php new file mode 100644 index 0000000..14cbec8 --- /dev/null +++ b/src/Subscriber/FileCompileEventListener.php @@ -0,0 +1,40 @@ + $fileCompilers + */ + public function __construct( + #[TaggedIterator('spomky_labs_pwa.compiler')] + private iterable $fileCompilers, + #[Autowire('@asset_mapper.local_public_assets_filesystem')] + private PublicAssetsFilesystemInterface $assetsFilesystem, + ) { + } + + public function __invoke(PreAssetsCompileEvent $event): void + { + foreach ($this->fileCompilers as $fileCompiler) { + foreach ($fileCompiler->supportedPublicUrls() as $publicUrl) { + $data = $fileCompiler->get($publicUrl); + if ($data === null) { + continue; + } + $this->assetsFilesystem->write($data->url, $data->data); + } + } + } +} diff --git a/src/Subscriber/PwaDevServerSubscriber.php b/src/Subscriber/PwaDevServerSubscriber.php index 010b70e..f5ea1d4 100644 --- a/src/Subscriber/PwaDevServerSubscriber.php +++ b/src/Subscriber/PwaDevServerSubscriber.php @@ -4,90 +4,27 @@ namespace SpomkyLabs\PwaBundle\Subscriber; -use Psr\EventDispatcher\EventDispatcherInterface; -use SpomkyLabs\PwaBundle\Dto\Manifest; -use SpomkyLabs\PwaBundle\Dto\ServiceWorker; -use SpomkyLabs\PwaBundle\Event\NullEventDispatcher; -use SpomkyLabs\PwaBundle\Event\PostManifestCompileEvent; -use SpomkyLabs\PwaBundle\Event\PreManifestCompileEvent; -use SpomkyLabs\PwaBundle\Service\ServiceWorkerCompiler; -use Symfony\Component\Config\FileLocator; -use Symfony\Component\DependencyInjection\Attribute\Autowire; +use SpomkyLabs\PwaBundle\Service\Data; +use SpomkyLabs\PwaBundle\Service\FileCompilerInterface; +use Symfony\Component\DependencyInjection\Attribute\TaggedIterator; use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\Event\RequestEvent; use Symfony\Component\HttpKernel\Event\ResponseEvent; use Symfony\Component\HttpKernel\KernelEvents; use Symfony\Component\HttpKernel\Profiler\Profiler; -use Symfony\Component\Serializer\Encoder\JsonEncode; -use Symfony\Component\Serializer\Normalizer\AbstractNormalizer; -use Symfony\Component\Serializer\Normalizer\AbstractObjectNormalizer; -use Symfony\Component\Serializer\Normalizer\TranslatableNormalizer; -use Symfony\Component\Serializer\SerializerInterface; -use function assert; -use function count; use function in_array; -use function is_array; -use function is_string; -use function mb_strlen; -use const JSON_PRETTY_PRINT; -use const JSON_THROW_ON_ERROR; -use const JSON_UNESCAPED_SLASHES; -use const JSON_UNESCAPED_UNICODE; final readonly class PwaDevServerSubscriber implements EventSubscriberInterface { - private EventDispatcherInterface $dispatcher; - - private string $manifestPublicUrl; - - private null|string $serviceWorkerPublicUrl; - - private null|string $workboxPublicUrl; - - private null|string $workboxVersion; - - private array $jsonOptions; - /** - * @param array $locales + * @param iterable $fileCompilers */ public function __construct( - private ServiceWorkerCompiler $serviceWorkerBuilder, - private SerializerInterface $serializer, - private Manifest $manifest, - ServiceWorker $serviceWorker, - #[Autowire('%spomky_labs_pwa.manifest.public_url%')] - string $manifestPublicUrl, + #[TaggedIterator('spomky_labs_pwa.compiler')] + private iterable $fileCompilers, private null|Profiler $profiler, - #[Autowire('%kernel.debug%')] - bool $debug, - null|EventDispatcherInterface $dispatcher, - #[Autowire('%kernel.enabled_locales%')] - private array $locales, ) { - $this->dispatcher = $dispatcher ?? new NullEventDispatcher(); - $this->manifestPublicUrl = '/' . trim($manifestPublicUrl, '/'); - $serviceWorkerPublicUrl = $serviceWorker->dest; - $this->serviceWorkerPublicUrl = '/' . trim($serviceWorkerPublicUrl, '/'); - if ($serviceWorker->workbox->enabled === true) { - $this->workboxVersion = $serviceWorker->workbox->version; - $workboxPublicUrl = $serviceWorker->workbox->workboxPublicUrl; - $this->workboxPublicUrl = '/' . trim($workboxPublicUrl, '/'); - } else { - $this->workboxVersion = null; - $this->workboxPublicUrl = null; - } - $options = [ - AbstractObjectNormalizer::SKIP_UNINITIALIZED_VALUES => true, - AbstractObjectNormalizer::SKIP_NULL_VALUES => true, - AbstractNormalizer::IGNORED_ATTRIBUTES => ['useCredentials', 'locales'], - JsonEncode::OPTIONS => JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE | JSON_THROW_ON_ERROR, - ]; - if ($debug === true) { - $options[JsonEncode::OPTIONS] |= JSON_PRETTY_PRINT; - } - $this->jsonOptions = $options; } public function onKernelRequest(RequestEvent $event): void @@ -98,38 +35,12 @@ public function onKernelRequest(RequestEvent $event): void $request = $event->getRequest(); $pathInfo = $request->getPathInfo(); - $localizedManifestPublicUrls = []; - foreach ($this->locales as $locale) { - $localizedManifestPublicUrls[$locale] = str_replace('{locale}', $locale, $this->manifestPublicUrl); - } - - switch (true) { - case $this->manifest->enabled === true && str_contains($this->manifestPublicUrl, '{locale}') && in_array( - $pathInfo, - $localizedManifestPublicUrls, - true - ): - $locale = array_search($pathInfo, $localizedManifestPublicUrls, true); - assert(is_string($locale), 'Locale not found.'); - $this->serveManifest($event, $locale); - break; - case $this->manifest->enabled === true && ! str_contains( - $this->manifestPublicUrl, - '{locale}' - ) && $pathInfo === $this->manifestPublicUrl: - $this->serveManifest($event); - break; - case $this->manifest->serviceWorker?->enabled === true && $pathInfo === $this->serviceWorkerPublicUrl: - $this->serveServiceWorker($event); - break; - case $this->manifest->serviceWorker?->enabled === true && $this->workboxVersion !== null && $this->workboxPublicUrl !== null && str_starts_with( - $pathInfo, - $this->workboxPublicUrl - ): - $this->serveWorkboxFile($event, $pathInfo); - break; - default: - // Do nothing + foreach ($this->fileCompilers as $fileCompiler) { + if (in_array($pathInfo, $fileCompiler->supportedPublicUrls(), true)) { + $data = $fileCompiler->get($pathInfo); + assert($data !== null); + $this->serveFile($event, $data); + } } } @@ -152,79 +63,10 @@ public static function getSubscribedEvents(): array ]; } - private function serveManifest(RequestEvent $event, null|string $locale = null): void - { - $this->profiler?->disable(); - $manifest = clone $this->manifest; - $options = $this->jsonOptions; - if ($locale !== null) { - $options[TranslatableNormalizer::NORMALIZATION_LOCALE_KEY] = $locale; - } - $preEvent = new PreManifestCompileEvent($manifest); - $preEvent = $this->dispatcher->dispatch($preEvent); - assert($preEvent instanceof PreManifestCompileEvent); - $data = $this->serializer->serialize($preEvent->manifest, 'json', $options); - $postEvent = new PostManifestCompileEvent($manifest, $data); - $postEvent = $this->dispatcher->dispatch($postEvent); - assert($postEvent instanceof PostManifestCompileEvent); - - $response = new Response($postEvent->data, Response::HTTP_OK, [ - 'Cache-Control' => 'public, max-age=604800, immutable', - 'Content-Type' => 'application/manifest+json', - 'X-Manifest-Dev' => true, - 'Etag' => hash('xxh128', $data), - ]); - - $event->setResponse($response); - $event->stopPropagation(); - } - - private function serveServiceWorker(RequestEvent $event): void + private function serveFile(RequestEvent $event, Data $data): void { - $data = $this->serviceWorkerBuilder->compile(); - if ($data === null) { - return; - } $this->profiler?->disable(); - - $response = new Response($data, Response::HTTP_OK, [ - 'Content-Type' => 'application/javascript', - 'X-SW-Dev' => true, - 'Etag' => hash('xxh128', $data), - ]); - - $event->setResponse($response); - $event->stopPropagation(); - } - - private function serveWorkboxFile(RequestEvent $event, string $pathInfo): void - { - if (str_contains($pathInfo, '/..')) { - return; - } - $asset = mb_substr($pathInfo, mb_strlen((string) $this->workboxPublicUrl)); - $fileLocator = new FileLocator(__DIR__ . '/../Resources'); - $resource = sprintf('workbox-v%s%s', $this->workboxVersion, $asset); - $resourcePath = $fileLocator->locate($resource, null, false); - if (is_array($resourcePath)) { - if (count($resourcePath) === 1) { - $resourcePath = $resourcePath[0]; - } else { - return; - } - } - if (! is_string($resourcePath)) { - return; - } - - $body = file_get_contents($resourcePath); - assert(is_string($body), 'Unable to load the file content.'); - $response = new Response($body, Response::HTTP_OK, [ - 'Content-Type' => 'application/javascript', - 'X-SW-Dev' => true, - 'Etag' => hash('xxh128', $body), - ]); - + $response = new Response($data->data, Response::HTTP_OK, $data->headers); $event->setResponse($response); $event->stopPropagation(); } diff --git a/src/Subscriber/ServiceWorkerCompileEventListener.php b/src/Subscriber/ServiceWorkerCompileEventListener.php deleted file mode 100644 index 8f678b9..0000000 --- a/src/Subscriber/ServiceWorkerCompileEventListener.php +++ /dev/null @@ -1,44 +0,0 @@ -serviceWorkerPublicUrl = $serviceWorkerPublicUrl === null ? null : '/' . trim( - $serviceWorkerPublicUrl, - '/' - ); - } - - public function __invoke(PreAssetsCompileEvent $event): void - { - if (! $this->serviceWorker->enabled) { - return; - } - $data = $this->serviceWorkerBuilder->compile(); - if ($data === null || $this->serviceWorkerPublicUrl === null) { - return; - } - $this->assetsFilesystem->write($this->serviceWorkerPublicUrl, $data); - } -} diff --git a/src/Subscriber/WorkboxCompileEventListener.php b/src/Subscriber/WorkboxCompileEventListener.php deleted file mode 100644 index 291dc03..0000000 --- a/src/Subscriber/WorkboxCompileEventListener.php +++ /dev/null @@ -1,57 +0,0 @@ -manifest->serviceWorker; - if ($serviceWorker === null || $serviceWorker->enabled !== true || $serviceWorker->workbox->enabled !== true || $serviceWorker->workbox->useCDN === true) { - return; - } - $workboxVersion = $serviceWorker->workbox->version; - $workboxPublicUrl = '/' . trim($serviceWorker->workbox->workboxPublicUrl, '/'); - - $fileLocator = new FileLocator(__DIR__ . '/../Resources'); - $resourcePath = $fileLocator->locate(sprintf('workbox-v%s', $workboxVersion)); - if (! is_string($resourcePath)) { - return; - } - - $files = scandir($resourcePath); - assert(is_array($files), 'Unable to list the files.'); - foreach ($files as $file) { - if (in_array($file, ['.', '..'], true)) { - continue; - } - if (str_contains($file, '.dev.')) { - continue; - } - $content = file_get_contents(sprintf('%s/%s', $resourcePath, $file)); - assert(is_string($content), 'Unable to load the file content.'); - $this->assetsFilesystem->write(sprintf('%s/%s', $workboxPublicUrl, $file), $content); - } - } -}