diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index 095f8dc..01bd3c0 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -100,6 +100,31 @@ parameters: count: 1 path: src/Command/CreateServiceWorkerCommand.php + - + message: "#^Class SpomkyLabs\\\\PwaBundle\\\\Dto\\\\BackgroundSync has an uninitialized property \\$forceSyncFallback\\. Give it default value or assign it in the constructor\\.$#" + count: 1 + path: src/Dto/BackgroundSync.php + + - + message: "#^Class SpomkyLabs\\\\PwaBundle\\\\Dto\\\\BackgroundSync has an uninitialized property \\$maxRetentionTime\\. Give it default value or assign it in the constructor\\.$#" + count: 1 + path: src/Dto/BackgroundSync.php + + - + message: "#^Class SpomkyLabs\\\\PwaBundle\\\\Dto\\\\BackgroundSync has an uninitialized property \\$method\\. Give it default value or assign it in the constructor\\.$#" + count: 1 + path: src/Dto/BackgroundSync.php + + - + message: "#^Class SpomkyLabs\\\\PwaBundle\\\\Dto\\\\BackgroundSync has an uninitialized property \\$queueName\\. Give it default value or assign it in the constructor\\.$#" + count: 1 + path: src/Dto/BackgroundSync.php + + - + message: "#^Class SpomkyLabs\\\\PwaBundle\\\\Dto\\\\BackgroundSync has an uninitialized property \\$regex\\. Give it default value or assign it in the constructor\\.$#" + count: 1 + path: src/Dto/BackgroundSync.php + - message: "#^Class SpomkyLabs\\\\PwaBundle\\\\Dto\\\\File has an uninitialized property \\$accept\\. Give it default value or assign it in the constructor\\.$#" count: 1 @@ -655,6 +680,11 @@ parameters: count: 1 path: src/Service/ServiceWorkerCompiler.php + - + message: "#^Strict comparison using \\!\\=\\= between bool\\|int and null will always evaluate to true\\.$#" + count: 1 + path: src/Service/ServiceWorkerCompiler.php + - message: "#^Cannot access offset 'public_prefix' on mixed\\.$#" count: 1 diff --git a/src/Dto/BackgroundSync.php b/src/Dto/BackgroundSync.php new file mode 100644 index 0000000..7d34b71 --- /dev/null +++ b/src/Dto/BackgroundSync.php @@ -0,0 +1,23 @@ + + */ + #[SerializedName('background_sync')] + public array $backgroundSync = []; + #[SerializedName('clear_cache')] public bool $clearCache = true; } diff --git a/src/Resources/config/definition/service_worker.php b/src/Resources/config/definition/service_worker.php index 1b1e614..abbb1fa 100644 --- a/src/Resources/config/definition/service_worker.php +++ b/src/Resources/config/definition/service_worker.php @@ -32,6 +32,16 @@ ->defaultFalse() ->info('Whether to skip waiting for the service worker to be activated.') ->end() + ->scalarNode('scope') + ->cannotBeEmpty() + ->defaultValue('/') + ->info('The scope of the service worker.') + ->example('/app/') + ->end() + ->booleanNode('use_cache') + ->defaultTrue() + ->info('Whether the service worker should use the cache.') + ->end() ->arrayNode('workbox') ->info('The configuration of the workbox.') ->canBeDisabled() @@ -310,6 +320,39 @@ ->end() ->end() ->end() + ->arrayNode('background_sync') + ->treatNullLike([]) + ->treatFalseLike([]) + ->treatTrueLike([]) + ->info('The background sync configuration.') + ->arrayPrototype() + ->children() + ->scalarNode('queue_name') + ->isRequired() + ->info('The name of the queue.') + ->example(['api-requests', 'image-uploads']) + ->end() + ->scalarNode('regex') + ->isRequired() + ->info('The regex to match the URLs.') + ->example(['/\/api\//']) + ->end() + ->scalarNode('method') + ->defaultValue('POST') + ->info('The HTTP method.') + ->example(['POST', 'PUT', 'PATCH', 'DELETE']) + ->end() + ->integerNode('max_retention_time') + ->defaultValue(60 * 24 * 5) + ->info('The maximum retention time in minutes.') + ->end() + ->booleanNode('force_sync_callback') + ->defaultFalse() + ->info('Whether to force the sync callback.') + ->end() + ->end() + ->end() + ->end() ->scalarNode('image_cache_name') ->defaultValue('images') ->info('The name of the image cache.') @@ -464,16 +507,6 @@ ->end() ->end() ->end() - ->scalarNode('scope') - ->cannotBeEmpty() - ->defaultValue('/') - ->info('The scope of the service worker.') - ->example('/app/') - ->end() - ->booleanNode('use_cache') - ->defaultTrue() - ->info('Whether the service worker should use the cache.') - ->end() ->end() ->end() ->end() diff --git a/src/Service/ServiceWorkerCompiler.php b/src/Service/ServiceWorkerCompiler.php index 070446b..f0e0bd5 100644 --- a/src/Service/ServiceWorkerCompiler.php +++ b/src/Service/ServiceWorkerCompiler.php @@ -102,6 +102,7 @@ private function processWorkbox(Workbox $workbox, string $body): string $body = $this->processImageCacheRule($workbox, $body); $body = $this->processCacheRootFilesRule($workbox, $body); $body = $this->processCacheGoogleFontsRule($workbox, $body); + $body = $this->processBackgroundSyncRule($workbox, $body); return $this->processOfflineFallback($workbox, $body); } @@ -316,6 +317,32 @@ private function processCacheGoogleFontsRule(Workbox $workbox, string $body): st return $body . PHP_EOL . PHP_EOL . trim($declaration); } + private function processBackgroundSyncRule(Workbox $workbox, string $body): string + { + if ($workbox->backgroundSync === []) { + return $body; + } + + $declaration = ''; + foreach ($workbox->backgroundSync as $sync) { + $options = [ + 'maxRetentionTime' => $sync->maxRetentionTime, + 'forceSyncCallback' => $sync->forceSyncFallback, + ]; + $options = array_filter($options, static fn (mixed $v): bool => $v !== null); + $options = count($options) === 0 ? '' : $this->serializer->serialize($options, 'json', $this->jsonOptions); + $declaration .= <<regex}', + new workbox.strategies.NetworkOnly({plugins: [new workbox.backgroundSync.BackgroundSyncPlugin('{$sync->queueName}',{$options})] }), + '{$sync->method}' +); +BACKGROUND_SYNC_RULE_STRATEGY; + } + + return $body . PHP_EOL . PHP_EOL . trim($declaration); + } + private function processOfflineFallback(Workbox $workbox, string $body): string { if ($workbox->offlineFallback->enabled === false) {