From 9915a2930b14c484a43c8f5ed0429b1717e91373 Mon Sep 17 00:00:00 2001 From: Maelan LE BORGNE Date: Wed, 19 Jun 2024 10:45:37 +0200 Subject: [PATCH 01/24] Add ability to generate asynchronously using webhooks --- config/builder_pdf.php | 6 + config/builder_screenshot.php | 3 + config/services.php | 11 ++ src/Builder/AsyncBuilderInterface.php | 11 ++ src/Builder/AsyncBuilderTrait.php | 88 ++++++++++++++ .../Pdf/AbstractChromiumPdfBuilder.php | 1 + src/Builder/Pdf/AbstractPdfBuilder.php | 5 +- .../Screenshot/AbstractScreenshotBuilder.php | 5 +- src/Client/GotenbergClient.php | 2 +- src/Debug/Builder/TraceablePdfBuilder.php | 27 +++++ .../Builder/TraceableScreenshotBuilder.php | 41 +++++-- src/DependencyInjection/Configuration.php | 99 +++++++++++++++ .../SensiolabsGotenbergExtension.php | 72 ++++++++--- .../WebhookConfigurationRegistry.php | 77 ++++++++++++ .../WebhookConfigurationRegistryInterface.php | 19 +++ .../WebhookConfigurationException.php | 7 ++ .../DependencyInjection/ConfigurationTest.php | 48 ++++++++ .../SensiolabsGotenbergExtensionTest.php | 106 +++++++++++++++- .../WebhookConfigurationRegistryTest.php | 114 ++++++++++++++++++ 19 files changed, 711 insertions(+), 31 deletions(-) create mode 100644 src/Builder/AsyncBuilderInterface.php create mode 100644 src/Builder/AsyncBuilderTrait.php create mode 100644 src/DependencyInjection/WebhookConfiguration/WebhookConfigurationRegistry.php create mode 100644 src/DependencyInjection/WebhookConfiguration/WebhookConfigurationRegistryInterface.php create mode 100644 src/Exception/WebhookConfigurationException.php create mode 100644 tests/DependencyInjection/WebhookConfigurationRegistryTest.php diff --git a/config/builder_pdf.php b/config/builder_pdf.php index a150f137..4b60b1b4 100644 --- a/config/builder_pdf.php +++ b/config/builder_pdf.php @@ -25,6 +25,7 @@ service('twig')->nullOnInvalid(), ]) ->call('setLogger', [service('logger')->nullOnInvalid()]) + ->call('setWebhookConfigurationRegistry', [service('.sensiolabs_gotenberg.webhook_configuration_registry')->nullOnInvalid()]) ->tag('sensiolabs_gotenberg.pdf_builder') ; @@ -38,6 +39,7 @@ service('router')->nullOnInvalid(), ]) ->call('setLogger', [service('logger')->nullOnInvalid()]) + ->call('setWebhookConfigurationRegistry', [service('.sensiolabs_gotenberg.webhook_configuration_registry')->nullOnInvalid()]) ->call('setRequestContext', [service('.sensiolabs_gotenberg.request_context')->nullOnInvalid()]) ->tag('sensiolabs_gotenberg.pdf_builder') ; @@ -50,6 +52,7 @@ service('request_stack'), service('twig')->nullOnInvalid(), ]) + ->call('setWebhookConfigurationRegistry', [service('.sensiolabs_gotenberg.webhook_configuration_registry')->nullOnInvalid()]) ->call('setLogger', [service('logger')->nullOnInvalid()]) ->tag('sensiolabs_gotenberg.pdf_builder') ; @@ -61,6 +64,7 @@ service('sensiolabs_gotenberg.asset.base_dir_formatter'), ]) ->call('setLogger', [service('logger')->nullOnInvalid()]) + ->call('setWebhookConfigurationRegistry', [service('.sensiolabs_gotenberg.webhook_configuration_registry')->nullOnInvalid()]) ->tag('sensiolabs_gotenberg.pdf_builder') ; @@ -71,6 +75,7 @@ service('sensiolabs_gotenberg.asset.base_dir_formatter'), ]) ->call('setLogger', [service('logger')->nullOnInvalid()]) + ->call('setWebhookConfigurationRegistry', [service('.sensiolabs_gotenberg.webhook_configuration_registry')->nullOnInvalid()]) ->tag('sensiolabs_gotenberg.pdf_builder') ; @@ -81,6 +86,7 @@ service('sensiolabs_gotenberg.asset.base_dir_formatter'), ]) ->call('setLogger', [service('logger')->nullOnInvalid()]) + ->call('setWebhookConfigurationRegistry', [service('.sensiolabs_gotenberg.webhook_configuration_registry')->nullOnInvalid()]) ->tag('sensiolabs_gotenberg.pdf_builder') ; }; diff --git a/config/builder_screenshot.php b/config/builder_screenshot.php index 7e04c109..2c2d4fa7 100644 --- a/config/builder_screenshot.php +++ b/config/builder_screenshot.php @@ -22,6 +22,7 @@ service('twig')->nullOnInvalid(), ]) ->call('setLogger', [service('logger')->nullOnInvalid()]) + ->call('setWebhookConfigurationRegistry', [service('.sensiolabs_gotenberg.webhook_configuration_registry')->nullOnInvalid()]) ->tag('sensiolabs_gotenberg.screenshot_builder') ; @@ -35,6 +36,7 @@ service('router')->nullOnInvalid(), ]) ->call('setLogger', [service('logger')->nullOnInvalid()]) + ->call('setWebhookConfigurationRegistry', [service('.sensiolabs_gotenberg.webhook_configuration_registry')->nullOnInvalid()]) ->call('setRequestContext', [service('.sensiolabs_gotenberg.request_context')->nullOnInvalid()]) ->tag('sensiolabs_gotenberg.screenshot_builder') ; @@ -48,6 +50,7 @@ service('twig')->nullOnInvalid(), ]) ->call('setLogger', [service('logger')->nullOnInvalid()]) + ->call('setWebhookConfigurationRegistry', [service('.sensiolabs_gotenberg.webhook_configuration_registry')->nullOnInvalid()]) ->tag('sensiolabs_gotenberg.screenshot_builder') ; }; diff --git a/config/services.php b/config/services.php index 1bea2636..d678cb27 100644 --- a/config/services.php +++ b/config/services.php @@ -2,6 +2,8 @@ use Sensiolabs\GotenbergBundle\Client\GotenbergClient; use Sensiolabs\GotenbergBundle\Client\GotenbergClientInterface; +use Sensiolabs\GotenbergBundle\DependencyInjection\WebhookConfiguration\WebhookConfigurationRegistry; +use Sensiolabs\GotenbergBundle\DependencyInjection\WebhookConfiguration\WebhookConfigurationRegistryInterface; use Sensiolabs\GotenbergBundle\Formatter\AssetBaseDirFormatter; use Sensiolabs\GotenbergBundle\Gotenberg; use Sensiolabs\GotenbergBundle\GotenbergInterface; @@ -63,4 +65,13 @@ ]) ->alias(GotenbergInterface::class, 'sensiolabs_gotenberg') ; + + $services->set('.sensiolabs_gotenberg.webhook_configuration_registry', WebhookConfigurationRegistry::class) + ->args([ + service('router'), + service('.sensiolabs_gotenberg.request_context')->nullOnInvalid(), + ]) + ->tag('sensiolabs_gotenberg.webhook_configuration_registry') + ->alias(WebhookConfigurationRegistryInterface::class, '.sensiolabs_gotenberg.webhook_configuration_registry') + ; }; diff --git a/src/Builder/AsyncBuilderInterface.php b/src/Builder/AsyncBuilderInterface.php new file mode 100644 index 00000000..ca5d8e25 --- /dev/null +++ b/src/Builder/AsyncBuilderInterface.php @@ -0,0 +1,11 @@ + + */ + private array $webhookExtraHeaders = []; + private \Closure $operationIdGenerator; + private WebhookConfigurationRegistry|null $webhookConfigurationRegistry = null; + + public function generateAsync(): string + { + $operationId = ($this->operationIdGenerator ?? self::defaultOperationIdGenerator(...))(); + $this->logger?->debug('Generating a file asynchronously with operation id {sensiolabs_gotenberg.operation_id} using {sensiolabs_gotenberg.builder} builder.', [ + 'sensiolabs_gotenberg.operation_id' => $operationId, + 'sensiolabs_gotenberg.builder' => $this::class, + ]); + + $this->webhookExtraHeaders['X-Gotenberg-Operation-Id'] = $operationId; + $headers = [ + 'Gotenberg-Webhook-Url' => $this->webhookUrl, + 'Gotenberg-Webhook-Error-Url' => $this->errorWebhookUrl, + 'Gotenberg-Webhook-Extra-Http-Headers' => json_encode($this->webhookExtraHeaders, \JSON_THROW_ON_ERROR), + ]; + if (null !== $this->fileName) { + $headers['Gotenberg-Output-Filename'] = basename($this->fileName, '.pdf'); + } + $this->client->call($this->getEndpoint(), $this->getMultipartFormData(), $headers); + + return $operationId; + } + + public function setWebhookConfigurationRegistry(WebhookConfigurationRegistry $registry): static + { + $this->webhookConfigurationRegistry = $registry; + + return $this; + } + + public function webhookConfiguration(string $webhook): static + { + if (null === $this->webhookConfigurationRegistry) { + throw new WebhookConfigurationException('The WebhookConfigurationRegistry is not available.'); + } + $webhookConfiguration = $this->webhookConfigurationRegistry->get($webhook); + + return $this->webhookUrls($webhookConfiguration['success'], $webhookConfiguration['error']); + } + + public function webhookUrls(string $successWebhook, string|null $errorWebhook = null): static + { + $this->webhookUrl = $successWebhook; + $this->errorWebhookUrl = $errorWebhook ?? $successWebhook; + + return $this; + } + + /** + * @param array $extraHeaders + */ + public function webhookExtraHeaders(array $extraHeaders): static + { + $this->webhookExtraHeaders = array_merge($this->webhookExtraHeaders, $extraHeaders); + + return $this; + } + + public function operationIdGenerator(\Closure $operationIdGenerator): static + { + $this->operationIdGenerator = $operationIdGenerator; + + return $this; + } + + protected static function defaultOperationIdGenerator(): string + { + return 'gotenberg_'.bin2hex(random_bytes(16)).microtime(true); + } +} diff --git a/src/Builder/Pdf/AbstractChromiumPdfBuilder.php b/src/Builder/Pdf/AbstractChromiumPdfBuilder.php index f5a9386c..3d607852 100644 --- a/src/Builder/Pdf/AbstractChromiumPdfBuilder.php +++ b/src/Builder/Pdf/AbstractChromiumPdfBuilder.php @@ -586,6 +586,7 @@ protected function addConfiguration(string $configurationName, mixed $value): vo 'fail_on_console_exceptions' => $this->failOnConsoleExceptions($value), 'skip_network_idle_event' => $this->skipNetworkIdleEvent($value), 'metadata' => $this->metadata($value), + 'webhook' => null, default => throw new InvalidBuilderConfiguration(sprintf('Invalid option "%s": no method does not exist in class "%s" to configured it.', $configurationName, static::class)), }; } diff --git a/src/Builder/Pdf/AbstractPdfBuilder.php b/src/Builder/Pdf/AbstractPdfBuilder.php index 9eddae3d..6435ff75 100644 --- a/src/Builder/Pdf/AbstractPdfBuilder.php +++ b/src/Builder/Pdf/AbstractPdfBuilder.php @@ -2,12 +2,15 @@ namespace Sensiolabs\GotenbergBundle\Builder\Pdf; +use Sensiolabs\GotenbergBundle\Builder\AsyncBuilderInterface; +use Sensiolabs\GotenbergBundle\Builder\AsyncBuilderTrait; use Sensiolabs\GotenbergBundle\Builder\DefaultBuilderTrait; use Sensiolabs\GotenbergBundle\Client\GotenbergClientInterface; use Sensiolabs\GotenbergBundle\Formatter\AssetBaseDirFormatter; -abstract class AbstractPdfBuilder implements PdfBuilderInterface +abstract class AbstractPdfBuilder implements PdfBuilderInterface, AsyncBuilderInterface { + use AsyncBuilderTrait; use DefaultBuilderTrait; public function __construct( diff --git a/src/Builder/Screenshot/AbstractScreenshotBuilder.php b/src/Builder/Screenshot/AbstractScreenshotBuilder.php index dc6a25c9..8d203663 100644 --- a/src/Builder/Screenshot/AbstractScreenshotBuilder.php +++ b/src/Builder/Screenshot/AbstractScreenshotBuilder.php @@ -2,14 +2,17 @@ namespace Sensiolabs\GotenbergBundle\Builder\Screenshot; +use Sensiolabs\GotenbergBundle\Builder\AsyncBuilderInterface; +use Sensiolabs\GotenbergBundle\Builder\AsyncBuilderTrait; use Sensiolabs\GotenbergBundle\Builder\DefaultBuilderTrait; use Sensiolabs\GotenbergBundle\Client\GotenbergClientInterface; use Sensiolabs\GotenbergBundle\Enumeration\Part; use Sensiolabs\GotenbergBundle\Formatter\AssetBaseDirFormatter; use Symfony\Component\Mime\Part\DataPart; -abstract class AbstractScreenshotBuilder implements ScreenshotBuilderInterface +abstract class AbstractScreenshotBuilder implements ScreenshotBuilderInterface, AsyncBuilderInterface { + use AsyncBuilderTrait; use DefaultBuilderTrait; public function __construct( diff --git a/src/Client/GotenbergClient.php b/src/Client/GotenbergClient.php index 96d3ad5b..31312279 100644 --- a/src/Client/GotenbergClient.php +++ b/src/Client/GotenbergClient.php @@ -28,7 +28,7 @@ public function call(string $endpoint, array $multipartFormData, array $headers ], ); - if (200 !== $response->getStatusCode()) { + if (!\in_array($response->getStatusCode(), [200, 204], true)) { throw new ClientException($response->getContent(false), $response->getStatusCode()); } diff --git a/src/Debug/Builder/TraceablePdfBuilder.php b/src/Debug/Builder/TraceablePdfBuilder.php index ccb5e785..32059713 100644 --- a/src/Debug/Builder/TraceablePdfBuilder.php +++ b/src/Debug/Builder/TraceablePdfBuilder.php @@ -2,6 +2,7 @@ namespace Sensiolabs\GotenbergBundle\Debug\Builder; +use Sensiolabs\GotenbergBundle\Builder\AsyncBuilderInterface; use Sensiolabs\GotenbergBundle\Builder\GotenbergFileResult; use Sensiolabs\GotenbergBundle\Builder\Pdf\PdfBuilderInterface; use Symfony\Component\Stopwatch\Stopwatch; @@ -50,6 +51,32 @@ public function generate(): GotenbergFileResult return $response; } + public function generateAsync(): string + { + if (!$this->inner instanceof AsyncBuilderInterface) { + throw new \LogicException(sprintf('The inner builder of %s must implement %s.', self::class, AsyncBuilderInterface::class)); + } + + $name = self::$count.'.'.$this->inner::class.'::'.__FUNCTION__; + ++self::$count; + + $swEvent = $this->stopwatch?->start($name, 'gotenberg.generate_pdf'); + $operationId = $this->inner->generateAsync(); + $swEvent?->stop(); + + $this->pdfs[] = [ + 'calls' => $this->calls, + 'time' => $swEvent?->getDuration(), + 'memory' => $swEvent?->getMemory(), + 'size' => null, + 'fileName' => null, + ]; + + ++$this->totalGenerated; + + return $operationId; + } + /** * @param array $arguments */ diff --git a/src/Debug/Builder/TraceableScreenshotBuilder.php b/src/Debug/Builder/TraceableScreenshotBuilder.php index 69abeaf5..4f9ff72e 100644 --- a/src/Debug/Builder/TraceableScreenshotBuilder.php +++ b/src/Debug/Builder/TraceableScreenshotBuilder.php @@ -2,6 +2,7 @@ namespace Sensiolabs\GotenbergBundle\Debug\Builder; +use Sensiolabs\GotenbergBundle\Builder\AsyncBuilderInterface; use Sensiolabs\GotenbergBundle\Builder\GotenbergFileResult; use Sensiolabs\GotenbergBundle\Builder\Screenshot\ScreenshotBuilderInterface; use Symfony\Component\Stopwatch\Stopwatch; @@ -9,7 +10,7 @@ final class TraceableScreenshotBuilder implements ScreenshotBuilderInterface { /** - * @var list|null, 'fileName': string, 'calls': list, 'arguments': array}>}> + * @var list|null, 'fileName': string|null, 'calls': list, 'arguments': array}>}> */ private array $screenshots = []; @@ -24,7 +25,7 @@ final class TraceableScreenshotBuilder implements ScreenshotBuilderInterface public function __construct( private readonly ScreenshotBuilderInterface $inner, - private readonly Stopwatch $stopwatch, + private readonly Stopwatch|null $stopwatch, ) { } @@ -33,9 +34,9 @@ public function generate(): GotenbergFileResult $name = self::$count.'.'.$this->inner::class.'::'.__FUNCTION__; ++self::$count; - $swEvent = $this->stopwatch->start($name, 'gotenberg.generate_screenshot'); + $swEvent = $this->stopwatch?->start($name, 'gotenberg.generate_screenshot'); $response = $this->inner->generate(); - $swEvent->stop(); + $swEvent?->stop(); $fileName = 'Unknown'; if ($response->getHeaders()->has('Content-Disposition')) { @@ -53,8 +54,8 @@ public function generate(): GotenbergFileResult $this->screenshots[] = [ 'calls' => $this->calls, - 'time' => $swEvent->getDuration(), - 'memory' => $swEvent->getMemory(), + 'time' => $swEvent?->getDuration(), + 'memory' => $swEvent?->getMemory(), 'status' => $response->getStatusCode(), 'size' => $lengthInBytes, 'fileName' => $fileName, @@ -65,6 +66,32 @@ public function generate(): GotenbergFileResult return $response; } + public function generateAsync(): string + { + if (!$this->inner instanceof AsyncBuilderInterface) { + throw new \LogicException(sprintf('The inner builder of %s must implement %s.', self::class, AsyncBuilderInterface::class)); + } + + $name = self::$count.'.'.$this->inner::class.'::'.__FUNCTION__; + ++self::$count; + + $swEvent = $this->stopwatch?->start($name, 'gotenberg.generate_screenshot'); + $operationId = $this->inner->generateAsync(); + $swEvent?->stop(); + + $this->screenshots[] = [ + 'calls' => $this->calls, + 'time' => $swEvent?->getDuration(), + 'memory' => $swEvent?->getMemory(), + 'size' => null, + 'fileName' => null, + ]; + + ++$this->totalGenerated; + + return $operationId; + } + /** * @param array $arguments */ @@ -86,7 +113,7 @@ public function __call(string $name, array $arguments): mixed } /** - * @return list|null, 'fileName': string, 'calls': list, 'method': string, 'arguments': array}>}> + * @return list|null, 'fileName': string|null, 'calls': list, 'method': string, 'arguments': array}>}> */ public function getFiles(): array { diff --git a/src/DependencyInjection/Configuration.php b/src/DependencyInjection/Configuration.php index 70a3ba34..59cd609a 100644 --- a/src/DependencyInjection/Configuration.php +++ b/src/DependencyInjection/Configuration.php @@ -37,9 +37,13 @@ public function getConfigTreeBuilder(): TreeBuilder ->end() ->end() ->end() + ->append($this->addNamedWebhookDefinition()) ->arrayNode('default_options') ->addDefaultsIfNotSet() ->children() + ->scalarNode('webhook') + ->info('Webhook configuration name.') + ->end() ->arrayNode('pdf') ->addDefaultsIfNotSet() ->append($this->addPdfHtmlNode()) @@ -73,6 +77,7 @@ private function addPdfHtmlNode(): NodeDefinition ; $this->addChromiumPdfOptionsNode($treebuilder->getRootNode()); + $this->addWebhookDeclarationNode($treebuilder->getRootNode()); return $treebuilder->getRootNode(); } @@ -87,6 +92,7 @@ private function addPdfUrlNode(): NodeDefinition ; $this->addChromiumPdfOptionsNode($treebuilder->getRootNode()); + $this->addWebhookDeclarationNode($treebuilder->getRootNode()); return $treebuilder->getRootNode(); } @@ -101,6 +107,7 @@ private function addPdfMarkdownNode(): NodeDefinition ; $this->addChromiumPdfOptionsNode($treebuilder->getRootNode()); + $this->addWebhookDeclarationNode($treebuilder->getRootNode()); return $treebuilder->getRootNode(); } @@ -115,6 +122,7 @@ private function addScreenshotHtmlNode(): NodeDefinition ; $this->addChromiumScreenshotOptionsNode($treebuilder->getRootNode()); + $this->addWebhookDeclarationNode($treebuilder->getRootNode()); return $treebuilder->getRootNode(); } @@ -129,6 +137,7 @@ private function addScreenshotUrlNode(): NodeDefinition ; $this->addChromiumScreenshotOptionsNode($treebuilder->getRootNode()); + $this->addWebhookDeclarationNode($treebuilder->getRootNode()); return $treebuilder->getRootNode(); } @@ -143,6 +152,7 @@ private function addScreenshotMarkdownNode(): NodeDefinition ; $this->addChromiumScreenshotOptionsNode($treebuilder->getRootNode()); + $this->addWebhookDeclarationNode($treebuilder->getRootNode()); return $treebuilder->getRootNode(); } @@ -651,4 +661,93 @@ private function addPdfMetadata(): NodeDefinition ->end() ; } + + private function addNamedWebhookDefinition(): NodeDefinition + { + $treeBuilder = new TreeBuilder('webhook'); + + return $treeBuilder->getRootNode() + ->defaultValue([]) + ->useAttributeAsKey('name') + ->arrayPrototype() + ->children() + ->scalarNode('name') + ->validate() + ->ifTrue(static function ($option) { + return !\is_string($option); + }) + ->thenInvalid('Invalid header name %s') + ->end() + ->end() + ->append($this->addWebhookConfigurationNode('success')) + ->append($this->addWebhookConfigurationNode('error')) + ->end() + ->validate() + ->ifTrue(static function ($option): bool { + return !isset($option['success']); + }) + ->thenInvalid('Invalid webhook configuration : At least a "success" key is required.') + ->end() + ->end(); + } + + private function addWebhookDeclarationNode(ArrayNodeDefinition $parent): void + { + $parent + ->children() + ->arrayNode('webhook') + ->info('Webhook configuration name or definition.') + ->beforeNormalization() + ->ifString() + ->then(static function (string $v): array { + return ['config_name' => $v]; + }) + ->end() + ->children() + ->append($this->addWebhookConfigurationNode('success')) + ->append($this->addWebhookConfigurationNode('error')) + ->scalarNode('config_name') + ->info('The name of the webhook configuration to use.') + ->end() + ->end() + ->validate() + ->ifTrue(static function ($option): bool { + return !isset($option['config_name']) && !isset($option['success']); + }) + ->thenInvalid('Invalid webhook configuration : either reference an existing webhook configuration or declare a new one with "success" and optionally "error" keys.') + ->end() + ->end(); + } + + private function addWebhookConfigurationNode(string $name): NodeDefinition + { + $treeBuilder = new TreeBuilder($name); + + return $treeBuilder->getRootNode() + ->children() + ->scalarNode('url') + ->info('The URL to call.') + ->end() + ->variableNode('route') + ->info('Route configuration.') + ->beforeNormalization() + ->ifArray() + ->then(function (array $v): array { + return [$v[0], $v[1] ?? []]; + }) + ->ifString() + ->then(function (string $v): array { + return [$v, []]; + }) + ->end() + ->validate() + ->ifTrue(function ($v): bool { + return !\is_array($v) || \count($v) !== 2 || !\is_string($v[0]) || !\is_array($v[1]); + }) + ->thenInvalid('The "route" parameter must be a string or an array containing a string and an array.') + ->end() + ->end() + ->end() + ; + } } diff --git a/src/DependencyInjection/SensiolabsGotenbergExtension.php b/src/DependencyInjection/SensiolabsGotenbergExtension.php index c33f3316..66abfb2e 100644 --- a/src/DependencyInjection/SensiolabsGotenbergExtension.php +++ b/src/DependencyInjection/SensiolabsGotenbergExtension.php @@ -4,6 +4,7 @@ use Sensiolabs\GotenbergBundle\Builder\Pdf\PdfBuilderInterface; use Sensiolabs\GotenbergBundle\Builder\Screenshot\ScreenshotBuilderInterface; +use Sensiolabs\GotenbergBundle\DependencyInjection\WebhookConfiguration\WebhookConfigurationRegistryInterface; use Symfony\Component\Config\FileLocator; use Symfony\Component\DependencyInjection\Alias; use Symfony\Component\DependencyInjection\ContainerBuilder; @@ -12,13 +13,16 @@ use Symfony\Component\HttpKernel\DependencyInjection\Extension; use Symfony\Component\Routing\RequestContext; +/** + * @phpstan-type WebhookDefinition array{url?: string, route?: array{0: string, 1: array}} + */ class SensiolabsGotenbergExtension extends Extension { public function load(array $configs, ContainerBuilder $container): void { $configuration = new Configuration(); - /** @var array{base_uri: string, http_client: string|null, request_context?: array{base_uri?: string}, assets_directory: string, default_options: array{pdf: array{html: array, url: array, markdown: array, office: array, merge: array, convert: array}, screenshot: array{html: array, url: array, markdown: array}}} $config */ + /** @var array{base_uri: string, http_client: string|null, request_context?: array{base_uri?: string}, assets_directory: string, webhook: array, default_options: array{pdf: array{html: array, url: array, markdown: array, office: array, merge: array, convert: array}, screenshot: array{html: array, url: array, markdown: array}, webhook?: string}} $config */ $config = $this->processConfiguration($configuration, $configs); $loader = new PhpFileLoader($container, new FileLocator(__DIR__.'/../../config')); @@ -48,9 +52,14 @@ public function load(array $configs, ContainerBuilder $container): void ->addTag('sensiolabs_gotenberg.screenshot_builder') ; + $container->registerForAutoconfiguration(WebhookConfigurationRegistryInterface::class) + ->addTag('sensiolabs_gotenberg.webhook_configuration_registry') + ; + $container->setAlias('sensiolabs_gotenberg.http_client', new Alias($config['http_client'] ?? 'http_client', false)); $baseUri = $config['request_context']['base_uri'] ?? null; + $defaultWebhookConfig = $config['default_options']['webhook'] ?? null; if (null !== $baseUri) { $requestContextDefinition = new Definition(RequestContext::class); @@ -60,32 +69,28 @@ public function load(array $configs, ContainerBuilder $container): void $container->setDefinition('.sensiolabs_gotenberg.request_context', $requestContextDefinition); } - $definition = $container->getDefinition('.sensiolabs_gotenberg.pdf_builder.html'); - $definition->addMethodCall('setConfigurations', [$this->cleanUserOptions($config['default_options']['pdf']['html'])]); + foreach ($config['webhook'] as $name => $configuration) { + $container->getDefinition('.sensiolabs_gotenberg.webhook_configuration_registry') + ->addMethodCall('add', [$name, $configuration]); + } + + $this->processDefaultOptions('.sensiolabs_gotenberg.pdf_builder.html', $container, $config['default_options']['pdf']['html'], $defaultWebhookConfig); - $definition = $container->getDefinition('.sensiolabs_gotenberg.pdf_builder.url'); - $definition->addMethodCall('setConfigurations', [$this->cleanUserOptions($config['default_options']['pdf']['url'])]); + $this->processDefaultOptions('.sensiolabs_gotenberg.pdf_builder.url', $container, $config['default_options']['pdf']['url'], $defaultWebhookConfig); - $definition = $container->getDefinition('.sensiolabs_gotenberg.pdf_builder.markdown'); - $definition->addMethodCall('setConfigurations', [$this->cleanUserOptions($config['default_options']['pdf']['markdown'])]); + $this->processDefaultOptions('.sensiolabs_gotenberg.pdf_builder.markdown', $container, $config['default_options']['pdf']['markdown'], $defaultWebhookConfig); - $definition = $container->getDefinition('.sensiolabs_gotenberg.pdf_builder.office'); - $definition->addMethodCall('setConfigurations', [$this->cleanUserOptions($config['default_options']['pdf']['office'])]); + $this->processDefaultOptions('.sensiolabs_gotenberg.pdf_builder.office', $container, $config['default_options']['pdf']['office'], $defaultWebhookConfig); - $definition = $container->getDefinition('.sensiolabs_gotenberg.pdf_builder.merge'); - $definition->addMethodCall('setConfigurations', [$this->cleanUserOptions($config['default_options']['pdf']['merge'])]); + $this->processDefaultOptions('.sensiolabs_gotenberg.pdf_builder.merge', $container, $config['default_options']['pdf']['merge'], $defaultWebhookConfig); - $definition = $container->getDefinition('.sensiolabs_gotenberg.pdf_builder.convert'); - $definition->addMethodCall('setConfigurations', [$this->cleanUserOptions($config['default_options']['pdf']['convert'])]); + $this->processDefaultOptions('.sensiolabs_gotenberg.pdf_builder.convert', $container, $config['default_options']['pdf']['convert'], $defaultWebhookConfig); - $definition = $container->getDefinition('.sensiolabs_gotenberg.screenshot_builder.html'); - $definition->addMethodCall('setConfigurations', [$this->cleanUserOptions($config['default_options']['screenshot']['html'])]); + $this->processDefaultOptions('.sensiolabs_gotenberg.screenshot_builder.html', $container, $config['default_options']['screenshot']['html'], $defaultWebhookConfig); - $definition = $container->getDefinition('.sensiolabs_gotenberg.screenshot_builder.url'); - $definition->addMethodCall('setConfigurations', [$this->cleanUserOptions($config['default_options']['screenshot']['url'])]); + $this->processDefaultOptions('.sensiolabs_gotenberg.screenshot_builder.url', $container, $config['default_options']['screenshot']['url'], $defaultWebhookConfig); - $definition = $container->getDefinition('.sensiolabs_gotenberg.screenshot_builder.markdown'); - $definition->addMethodCall('setConfigurations', [$this->cleanUserOptions($config['default_options']['screenshot']['markdown'])]); + $this->processDefaultOptions('.sensiolabs_gotenberg.screenshot_builder.markdown', $container, $config['default_options']['screenshot']['markdown'], $defaultWebhookConfig); $definition = $container->getDefinition('sensiolabs_gotenberg.asset.base_dir_formatter'); $definition->replaceArgument(2, $config['assets_directory']); @@ -104,4 +109,33 @@ private function cleanUserOptions(array $userConfigurations): array return null !== $config; }); } + + /** + * @param array $config + */ + private function processDefaultOptions(string $serviceId, ContainerBuilder $container, array $config, string|null $defaultWebhookName): void + { + $definition = $container->getDefinition($serviceId); + $definition->addMethodCall('setConfigurations', [$this->cleanUserOptions($config)]); + + $webhookConfig = $config['webhook'] ?? null; + if (null === $webhookConfig && null === $defaultWebhookName) { + return; + } + + if (null === $webhookConfig) { + $definition->addMethodCall('webhookConfiguration', [$defaultWebhookName], true); + + return; + } + + if (\array_key_exists('config_name', $webhookConfig) && \is_string($webhookConfig['config_name'])) { + $name = $webhookConfig['config_name']; + } else { + $name = $serviceId.'_webhook_config'; + $container->getDefinition('.sensiolabs_gotenberg.webhook_configuration_registry') + ->addMethodCall('add', [$name, $webhookConfig]); + } + $definition->addMethodCall('webhookConfiguration', [$name], true); + } } diff --git a/src/DependencyInjection/WebhookConfiguration/WebhookConfigurationRegistry.php b/src/DependencyInjection/WebhookConfiguration/WebhookConfigurationRegistry.php new file mode 100644 index 00000000..40685d4e --- /dev/null +++ b/src/DependencyInjection/WebhookConfiguration/WebhookConfigurationRegistry.php @@ -0,0 +1,77 @@ +}} + */ +final class WebhookConfigurationRegistry implements WebhookConfigurationRegistryInterface +{ + /** + * @var array + */ + private array $configurations = []; + + public function __construct( + private readonly UrlGeneratorInterface $urlGenerator, + private readonly RequestContext|null $requestContext, + ) { + } + + /** + * @param array{success: WebhookDefinition, error?: WebhookDefinition} $configuration + */ + public function add(string $name, array $configuration): void + { + $requestContext = $this->urlGenerator->getContext(); + if (null !== $this->requestContext) { + $this->urlGenerator->setContext($this->requestContext); + } + + try { + $success = $this->processWebhookConfiguration($configuration['success']); + $error = $success; + if (isset($configuration['error'])) { + $error = $this->processWebhookConfiguration($configuration['error']); + } + $this->configurations[$name] = ['success' => $success, 'error' => $error]; + } finally { + $this->urlGenerator->setContext($requestContext); + } + } + + /** + * @return array{success: string, error: string} + */ + public function get(string $name): array + { + if (!\array_key_exists($name, $this->configurations)) { + throw new WebhookConfigurationException(sprintf('Webhook configuration "%s" not found.', $name)); + } + + return $this->configurations[$name]; + } + + /** + * @param WebhookDefinition $webhookDefinition + * + * @throws \InvalidArgumentException + */ + private function processWebhookConfiguration(array $webhookDefinition): string + { + if (isset($webhookDefinition['url'])) { + return $webhookDefinition['url']; + } + if (isset($webhookDefinition['route'])) { + return $this->urlGenerator->generate($webhookDefinition['route'][0], $webhookDefinition['route'][1], UrlGeneratorInterface::ABSOLUTE_URL); + } + + throw new WebhookConfigurationException('Invalid webhook configuration'); + } +} diff --git a/src/DependencyInjection/WebhookConfiguration/WebhookConfigurationRegistryInterface.php b/src/DependencyInjection/WebhookConfiguration/WebhookConfigurationRegistryInterface.php new file mode 100644 index 00000000..de030c64 --- /dev/null +++ b/src/DependencyInjection/WebhookConfiguration/WebhookConfigurationRegistryInterface.php @@ -0,0 +1,19 @@ +}} + */ +interface WebhookConfigurationRegistryInterface +{ + /** + * @param array{success: WebhookDefinition, error?: WebhookDefinition} $configuration + */ + public function add(string $name, array $configuration): void; + + /** + * @return array{success: string, error: string} + */ + public function get(string $name): array; +} diff --git a/src/Exception/WebhookConfigurationException.php b/src/Exception/WebhookConfigurationException.php new file mode 100644 index 00000000..67875280 --- /dev/null +++ b/src/Exception/WebhookConfigurationException.php @@ -0,0 +1,7 @@ +>}}> + */ + public static function invalidWebhookConfigurationProvider(): \Generator + { + yield 'webhook definition without "success" and "error" keys' => [ + [['webhook' => ['foo' => ['some_key' => ['url' => 'http://example.com']]]]], + ]; + yield 'webhook definition without "success" key' => [ + [['webhook' => ['foo' => ['error' => ['url' => 'http://example.com']]]]], + ]; + yield 'webhook definition without name' => [ + [['webhook' => [['success' => ['url' => 'http://example.com']], ['error' => ['url' => 'http://example.com/error']]]]], + ]; + yield 'webhook definition with invalid "url" key' => [ + [['webhook' => ['foo' => ['success' => ['url' => ['array_element']]]]]], + ]; + yield 'webhook definition with array of string as "route" key' => [ + [['webhook' => ['foo' => ['success' => ['route' => ['array_element']]]]]], + ]; + yield 'webhook definition with array of two strings as "route" key' => [ + [['webhook' => ['foo' => ['success' => ['route' => ['array_element', 'array_element_2']]]]]], + ]; + yield 'webhook definition in default webhook declaration' => [ + [['default_options' => ['webhook' => ['success' => ['url' => 'http://example.com']]]]], + ]; + } + + /** + * @param array> $config + * + * @dataProvider invalidWebhookConfigurationProvider + */ + #[DataProvider('invalidWebhookConfigurationProvider')] + public function testInvalidWebhookConfiguration(array $config): void + { + $this->expectException(InvalidConfigurationException::class); + $processor = new Processor(); + $processor->processConfiguration( + new Configuration(), + $config, + ); + } + /** * @return array{ + * 'assets_directory': string, + * 'http_client': string, + * 'webhook': array, * 'default_options': array{ * 'pdf': array{ * 'html': array, @@ -101,6 +148,7 @@ private static function getBundleDefaultConfig(): array return [ 'assets_directory' => '%kernel.project_dir%/assets', 'http_client' => 'http_client', + 'webhook' => [], 'default_options' => [ 'pdf' => [ 'html' => [ diff --git a/tests/DependencyInjection/SensiolabsGotenbergExtensionTest.php b/tests/DependencyInjection/SensiolabsGotenbergExtensionTest.php index 123a7026..98d4e0ca 100644 --- a/tests/DependencyInjection/SensiolabsGotenbergExtensionTest.php +++ b/tests/DependencyInjection/SensiolabsGotenbergExtensionTest.php @@ -29,7 +29,8 @@ public function testGotenbergConfiguredWithValidConfig(): void $extension = new SensiolabsGotenbergExtension(); $containerBuilder = $this->getContainerBuilder(); - $extension->load(self::getValidConfig(), $containerBuilder); + $validConfig = self::getValidConfig(); + $extension->load($validConfig, $containerBuilder); $list = [ 'pdf' => [ @@ -64,6 +65,7 @@ public function testGotenbergConfiguredWithValidConfig(): void 'skip_network_idle_event' => true, 'pdf_format' => 'PDF/A-1b', 'pdf_universal_access' => true, + 'webhook' => ['config_name' => 'bar'], ], 'url' => [ 'paper_width' => 21, @@ -255,7 +257,7 @@ public function testUrlBuildersCanChangeTheirRequestContext(string $serviceName) self::assertSame('https://sensiolabs.com', $requestContextDefinition->getArgument(0)); $urlBuilderDefinition = $containerBuilder->getDefinition($serviceName); - self::assertCount(3, $urlBuilderDefinition->getMethodCalls()); + self::assertCount(4, $urlBuilderDefinition->getMethodCalls()); $indexedMethodCalls = []; foreach ($urlBuilderDefinition->getMethodCalls() as $methodCall) { @@ -387,9 +389,102 @@ public function testDataCollectorIsProperlyConfiguredIfEnabled(): void ], $dataCollectorOptions); } + public function testBuilderWebhookConfiguredWithDefaultConfiguration(): void + { + $extension = new SensiolabsGotenbergExtension(); + + $containerBuilder = $this->getContainerBuilder(); + $extension->load([['http_client' => 'http_client']], $containerBuilder); + + self::assertEmpty($containerBuilder->getDefinition('.sensiolabs_gotenberg.webhook_configuration_registry')->getMethodCalls()); + + $buildersIds = [ + '.sensiolabs_gotenberg.pdf_builder.html', + '.sensiolabs_gotenberg.pdf_builder.url', + '.sensiolabs_gotenberg.pdf_builder.markdown', + '.sensiolabs_gotenberg.pdf_builder.office', + '.sensiolabs_gotenberg.screenshot_builder.html', + '.sensiolabs_gotenberg.screenshot_builder.url', + '.sensiolabs_gotenberg.screenshot_builder.markdown', + ]; + + foreach ($buildersIds as $builderId) { + $builderDefinition = $containerBuilder->getDefinition($builderId); + $methodCalls = $builderDefinition->getMethodCalls(); + self::assertNotContains('webhookConfiguration', $methodCalls); + } + } + + public function testBuilderWebhookConfiguredWithValidConfiguration(): void + { + $extension = new SensiolabsGotenbergExtension(); + + $containerBuilder = $this->getContainerBuilder(); + $extension->load([[ + 'http_client' => 'http_client', + 'webhook' => [ + 'foo' => ['success' => ['url' => 'https://sensiolabs.com/webhook'], 'error' => ['route' => 'simple_route']], + 'baz' => ['success' => ['route' => ['array_route', ['param1', 'param2']]]], + ], + 'default_options' => [ + 'webhook' => 'foo', + 'pdf' => [ + 'html' => ['webhook' => 'bar'], + 'url' => ['webhook' => 'baz'], + 'markdown' => ['webhook' => ['success' => ['url' => 'https://sensiolabs.com/webhook-on-the-fly']]], + ], + 'screenshot' => [ + 'html' => ['webhook' => 'foo'], + 'url' => ['webhook' => 'bar'], + 'markdown' => ['webhook' => 'baz'], + ], + ], + ]], $containerBuilder); + + $expectedConfigurationMapping = [ + '.sensiolabs_gotenberg.pdf_builder.html' => 'bar', + '.sensiolabs_gotenberg.pdf_builder.url' => 'baz', + '.sensiolabs_gotenberg.pdf_builder.markdown' => '.sensiolabs_gotenberg.pdf_builder.markdown_webhook_config', + '.sensiolabs_gotenberg.pdf_builder.office' => 'foo', + '.sensiolabs_gotenberg.screenshot_builder.html' => 'foo', + '.sensiolabs_gotenberg.screenshot_builder.url' => 'bar', + '.sensiolabs_gotenberg.screenshot_builder.markdown' => 'baz', + ]; + array_map(static function (string $builderId, string $expectedConfigurationName) use ($containerBuilder): void { + foreach ($containerBuilder->getDefinition($builderId)->getMethodCalls() as $methodCall) { + [$name, $arguments] = $methodCall; + if ('webhookConfiguration' === $name) { + self::assertSame($expectedConfigurationName, $arguments[0]); + + return; + } + } + }, array_keys($expectedConfigurationMapping), array_values($expectedConfigurationMapping)); + + $webhookConfigurationRegistryDefinition = $containerBuilder->getDefinition('.sensiolabs_gotenberg.webhook_configuration_registry'); + $methodCalls = $webhookConfigurationRegistryDefinition->getMethodCalls(); + self::assertCount(3, $methodCalls); + foreach ($methodCalls as $methodCall) { + [$name, $arguments] = $methodCall; + self::assertSame('add', $name); + self::assertContains($arguments[0], ['foo', 'baz', '.sensiolabs_gotenberg.pdf_builder.markdown_webhook_config']); + self::assertSame(match ($arguments[0]) { + 'foo' => ['success' => ['url' => 'https://sensiolabs.com/webhook'], 'error' => ['route' => ['simple_route', []]]], + 'baz' => ['success' => ['route' => ['array_route', ['param1', 'param2']]]], + '.sensiolabs_gotenberg.pdf_builder.markdown_webhook_config' => ['success' => ['url' => 'https://sensiolabs.com/webhook-on-the-fly']], + default => self::fail('Unexpected webhook configuration'), + }, $arguments[1]); + } + } + /** * @return array}, 'webhook'?: string}, + * 'error'?: array{'url'?: string, 'route'?: string|array{0: string, 1: list}, 'webhook'?: string} + * }>, * 'default_options': array{ + * 'webhook': string, * 'pdf': array{ * 'html': array, * 'url': array, @@ -411,7 +506,12 @@ private static function getValidConfig(): array return [ [ 'http_client' => 'http_client', + 'webhook' => [ + 'foo' => ['success' => ['url' => 'https://sensiolabs.com/webhook'], 'error' => ['route' => 'simple_route']], + 'baz' => ['success' => ['url' => 'https://sensiolabs.com/single-url-webhook']], + ], 'default_options' => [ + 'webhook' => 'foo', 'pdf' => [ 'html' => [ 'paper_width' => 33.1, @@ -443,6 +543,7 @@ private static function getValidConfig(): array 'skip_network_idle_event' => true, 'pdf_format' => PdfFormat::Pdf1b->value, 'pdf_universal_access' => true, + 'webhook' => 'bar', ], 'url' => [ 'paper_width' => 21, @@ -466,6 +567,7 @@ private static function getValidConfig(): array 'skip_network_idle_event' => false, 'pdf_format' => PdfFormat::Pdf2b->value, 'pdf_universal_access' => false, + // 'webhook' => ['success' => ''] ], 'markdown' => [ 'paper_width' => 30, diff --git a/tests/DependencyInjection/WebhookConfigurationRegistryTest.php b/tests/DependencyInjection/WebhookConfigurationRegistryTest.php new file mode 100644 index 00000000..31edb976 --- /dev/null +++ b/tests/DependencyInjection/WebhookConfigurationRegistryTest.php @@ -0,0 +1,114 @@ +}} + */ +#[CoversClass(WebhookConfigurationRegistry::class)] +final class WebhookConfigurationRegistryTest extends TestCase +{ + public function testGetUndefinedConfiguration(): void + { + $this->expectException(WebhookConfigurationException::class); + $this->expectExceptionMessage('Webhook configuration "undefined" not found.'); + + $registry = new WebhookConfigurationRegistry($this->createMock(UrlGeneratorInterface::class), null); + $registry->get('undefined'); + } + + public function testAddConfigurationUsingCustomContext(): void + { + $requestContext = $this->createMock(RequestContext::class); + $urlGenerator = $this->getUrlGenerator($requestContext); + $registry = new WebhookConfigurationRegistry($urlGenerator, $requestContext); + $registry->add('test', ['success' => ['url' => 'http://example.com/success']]); + } + + public function testOverrideConfiguration(): void + { + $registry = new WebhookConfigurationRegistry($this->createMock(UrlGeneratorInterface::class), null); + $registry->add('test', ['success' => ['url' => 'http://example.com/success']]); + $this->assertSame(['success' => 'http://example.com/success', 'error' => 'http://example.com/success'], $registry->get('test')); + $registry->add('test', ['success' => ['url' => 'http://example.com/override']]); + $this->assertSame(['success' => 'http://example.com/override', 'error' => 'http://example.com/override'], $registry->get('test')); + } + + /** + * @return \Generator + */ + public static function configurationProvider(): \Generator + { + yield 'full definition with urls' => [ + ['success' => ['url' => 'http://example.com/success'], 'error' => ['url' => 'http://example.com/error']], + ['success' => 'http://example.com/success', 'error' => 'http://example.com/error'], + ]; + yield 'full definition with routes' => [ + ['success' => ['route' => ['test_route_success', ['param' => 'value']]], 'error' => ['route' => ['test_route_error', ['param' => 'value']]]], + ['success' => 'http://localhost/test_route?param=value', 'error' => 'http://localhost/test_route?param=value'], + ]; + yield 'partial definition with urls' => [ + ['success' => ['url' => 'http://example.com/success']], + ['success' => 'http://example.com/success', 'error' => 'http://example.com/success'], + ]; + yield 'partial definition with routes' => [ + ['success' => ['route' => ['test_route_success', ['param' => 'value']]], + 'error' => ['route' => ['test_route_error', ['param' => 'value']]], + ], + ['success' => 'http://localhost/test_route?param=value', 'error' => 'http://localhost/test_route?param=value'], + ]; + yield 'mixed definition with url and route' => [ + ['success' => ['url' => 'http://example.com/success'], 'error' => ['route' => ['test_route_error', ['param' => 'value']]], + ], + ['success' => 'http://example.com/success', 'error' => 'http://localhost/test_route?param=value'], + ]; + } + + /** + * @param array{success: WebhookDefinition, error?: WebhookDefinition} $configuration + * @param array{success: string, error: string} $expectedUrls + * + * @throws Exception + */ + #[DataProvider('configurationProvider')] + public function testAddConfiguration(array $configuration, array $expectedUrls): void + { + $registry = new WebhookConfigurationRegistry($this->getUrlGenerator(), null); + $registry->add('test', $configuration); + + $this->assertSame($expectedUrls, $registry->get('test')); + } + + private function getUrlGenerator(RequestContext|null $requestContext = null): UrlGeneratorInterface&MockObject + { + $urlGenerator = $this->createMock(UrlGeneratorInterface::class); + $originalContext = $this->createMock(RequestContext::class); + $urlGenerator->expects(self::once())->method('getContext')->willReturn($originalContext); + $urlGenerator->expects(self::exactly(null !== $requestContext ? 2 : 1)) + ->method('setContext') + ->willReturnCallback(function (RequestContext $context) use ($originalContext, $requestContext): void { + match ($context) { + $requestContext, $originalContext => null, + default => self::fail('setContext was called with an unexpected context.'), + }; + }); + $urlGenerator->method('generate')->willReturnMap([ + ['test_route_success', ['param' => 'value'], UrlGeneratorInterface::ABSOLUTE_URL, 'http://localhost/test_route?param=value'], + ['test_route_error', ['param' => 'value'], UrlGeneratorInterface::ABSOLUTE_URL, 'http://localhost/test_route?param=value'], + ['_webhook_controller', ['type' => 'my_success_webhook'], UrlGeneratorInterface::ABSOLUTE_URL, 'http://localhost/webhook/success'], + ['_webhook_controller', ['type' => 'my_error_webhook'], UrlGeneratorInterface::ABSOLUTE_URL, 'http://localhost/webhook/error'], + ]); + + return $urlGenerator; + } +} From ec46e92212acec30af0da4c15e6d334213985691 Mon Sep 17 00:00:00 2001 From: Maelan LE BORGNE Date: Mon, 9 Sep 2024 10:22:01 +0200 Subject: [PATCH 02/24] switch to constructor injection --- config/builder_pdf.php | 12 ++++++------ config/builder_screenshot.php | 6 +++--- src/Builder/AsyncBuilderTrait.php | 7 ++----- src/Builder/Pdf/AbstractChromiumPdfBuilder.php | 4 +++- src/Builder/Pdf/AbstractPdfBuilder.php | 3 +++ src/Builder/Pdf/UrlPdfBuilder.php | 4 +++- .../Screenshot/AbstractChromiumScreenshotBuilder.php | 4 +++- src/Builder/Screenshot/AbstractScreenshotBuilder.php | 3 +++ src/Builder/Screenshot/UrlScreenshotBuilder.php | 4 +++- .../SensiolabsGotenbergExtension.php | 5 ----- tests/Builder/AbstractBuilderTestCase.php | 7 +++++++ tests/Builder/Pdf/AbstractChromiumPdfBuilderTest.php | 2 +- tests/Builder/Pdf/AbstractPdfBuilderTest.php | 7 ++++--- tests/Builder/Pdf/ConvertPdfBuilderTest.php | 2 +- tests/Builder/Pdf/HtmlPdfBuilderTest.php | 2 +- tests/Builder/Pdf/LibreOfficePdfBuilderTest.php | 2 +- tests/Builder/Pdf/MarkdownPdfBuilderTest.php | 2 +- tests/Builder/Pdf/MergePdfBuilderTest.php | 2 +- tests/Builder/Pdf/UrlPdfBuilderTest.php | 2 +- .../AbstractChromiumScreenshotBuilderTest.php | 2 +- .../Screenshot/AbstractScreenshotBuilderTest.php | 7 ++++--- .../Builder/Screenshot/HtmlScreenshotBuilderTest.php | 2 +- .../Screenshot/MarkdownScreenshotBuilderTest.php | 2 +- .../Builder/Screenshot/UrlScreenshotBuilderTest.php | 1 + .../SensiolabsGotenbergExtensionTest.php | 2 +- 25 files changed, 56 insertions(+), 40 deletions(-) diff --git a/config/builder_pdf.php b/config/builder_pdf.php index 4b60b1b4..8fcb7008 100644 --- a/config/builder_pdf.php +++ b/config/builder_pdf.php @@ -23,9 +23,9 @@ service('sensiolabs_gotenberg.asset.base_dir_formatter'), service('request_stack'), service('twig')->nullOnInvalid(), + service('.sensiolabs_gotenberg.webhook_configuration_registry'), ]) ->call('setLogger', [service('logger')->nullOnInvalid()]) - ->call('setWebhookConfigurationRegistry', [service('.sensiolabs_gotenberg.webhook_configuration_registry')->nullOnInvalid()]) ->tag('sensiolabs_gotenberg.pdf_builder') ; @@ -37,9 +37,9 @@ service('request_stack'), service('twig')->nullOnInvalid(), service('router')->nullOnInvalid(), + service('.sensiolabs_gotenberg.webhook_configuration_registry'), ]) ->call('setLogger', [service('logger')->nullOnInvalid()]) - ->call('setWebhookConfigurationRegistry', [service('.sensiolabs_gotenberg.webhook_configuration_registry')->nullOnInvalid()]) ->call('setRequestContext', [service('.sensiolabs_gotenberg.request_context')->nullOnInvalid()]) ->tag('sensiolabs_gotenberg.pdf_builder') ; @@ -51,8 +51,8 @@ service('sensiolabs_gotenberg.asset.base_dir_formatter'), service('request_stack'), service('twig')->nullOnInvalid(), + service('.sensiolabs_gotenberg.webhook_configuration_registry'), ]) - ->call('setWebhookConfigurationRegistry', [service('.sensiolabs_gotenberg.webhook_configuration_registry')->nullOnInvalid()]) ->call('setLogger', [service('logger')->nullOnInvalid()]) ->tag('sensiolabs_gotenberg.pdf_builder') ; @@ -62,9 +62,9 @@ ->args([ service('sensiolabs_gotenberg.client'), service('sensiolabs_gotenberg.asset.base_dir_formatter'), + service('.sensiolabs_gotenberg.webhook_configuration_registry'), ]) ->call('setLogger', [service('logger')->nullOnInvalid()]) - ->call('setWebhookConfigurationRegistry', [service('.sensiolabs_gotenberg.webhook_configuration_registry')->nullOnInvalid()]) ->tag('sensiolabs_gotenberg.pdf_builder') ; @@ -73,9 +73,9 @@ ->args([ service('sensiolabs_gotenberg.client'), service('sensiolabs_gotenberg.asset.base_dir_formatter'), + service('.sensiolabs_gotenberg.webhook_configuration_registry'), ]) ->call('setLogger', [service('logger')->nullOnInvalid()]) - ->call('setWebhookConfigurationRegistry', [service('.sensiolabs_gotenberg.webhook_configuration_registry')->nullOnInvalid()]) ->tag('sensiolabs_gotenberg.pdf_builder') ; @@ -84,9 +84,9 @@ ->args([ service('sensiolabs_gotenberg.client'), service('sensiolabs_gotenberg.asset.base_dir_formatter'), + service('.sensiolabs_gotenberg.webhook_configuration_registry'), ]) ->call('setLogger', [service('logger')->nullOnInvalid()]) - ->call('setWebhookConfigurationRegistry', [service('.sensiolabs_gotenberg.webhook_configuration_registry')->nullOnInvalid()]) ->tag('sensiolabs_gotenberg.pdf_builder') ; }; diff --git a/config/builder_screenshot.php b/config/builder_screenshot.php index 2c2d4fa7..e61e6382 100644 --- a/config/builder_screenshot.php +++ b/config/builder_screenshot.php @@ -20,9 +20,9 @@ service('sensiolabs_gotenberg.asset.base_dir_formatter'), service('request_stack'), service('twig')->nullOnInvalid(), + service('.sensiolabs_gotenberg.webhook_configuration_registry'), ]) ->call('setLogger', [service('logger')->nullOnInvalid()]) - ->call('setWebhookConfigurationRegistry', [service('.sensiolabs_gotenberg.webhook_configuration_registry')->nullOnInvalid()]) ->tag('sensiolabs_gotenberg.screenshot_builder') ; @@ -34,9 +34,9 @@ service('request_stack'), service('twig')->nullOnInvalid(), service('router')->nullOnInvalid(), + service('.sensiolabs_gotenberg.webhook_configuration_registry'), ]) ->call('setLogger', [service('logger')->nullOnInvalid()]) - ->call('setWebhookConfigurationRegistry', [service('.sensiolabs_gotenberg.webhook_configuration_registry')->nullOnInvalid()]) ->call('setRequestContext', [service('.sensiolabs_gotenberg.request_context')->nullOnInvalid()]) ->tag('sensiolabs_gotenberg.screenshot_builder') ; @@ -48,9 +48,9 @@ service('sensiolabs_gotenberg.asset.base_dir_formatter'), service('request_stack'), service('twig')->nullOnInvalid(), + service('.sensiolabs_gotenberg.webhook_configuration_registry'), ]) ->call('setLogger', [service('logger')->nullOnInvalid()]) - ->call('setWebhookConfigurationRegistry', [service('.sensiolabs_gotenberg.webhook_configuration_registry')->nullOnInvalid()]) ->tag('sensiolabs_gotenberg.screenshot_builder') ; }; diff --git a/src/Builder/AsyncBuilderTrait.php b/src/Builder/AsyncBuilderTrait.php index 71a15f45..9d1c534f 100644 --- a/src/Builder/AsyncBuilderTrait.php +++ b/src/Builder/AsyncBuilderTrait.php @@ -3,7 +3,7 @@ namespace Sensiolabs\GotenbergBundle\Builder; use Sensiolabs\GotenbergBundle\DependencyInjection\WebhookConfiguration\WebhookConfigurationRegistry; -use Sensiolabs\GotenbergBundle\Exception\WebhookConfigurationException; +use Sensiolabs\GotenbergBundle\DependencyInjection\WebhookConfiguration\WebhookConfigurationRegistryInterface; trait AsyncBuilderTrait { @@ -15,7 +15,7 @@ trait AsyncBuilderTrait */ private array $webhookExtraHeaders = []; private \Closure $operationIdGenerator; - private WebhookConfigurationRegistry|null $webhookConfigurationRegistry = null; + private WebhookConfigurationRegistryInterface $webhookConfigurationRegistry; public function generateAsync(): string { @@ -48,9 +48,6 @@ public function setWebhookConfigurationRegistry(WebhookConfigurationRegistry $re public function webhookConfiguration(string $webhook): static { - if (null === $this->webhookConfigurationRegistry) { - throw new WebhookConfigurationException('The WebhookConfigurationRegistry is not available.'); - } $webhookConfiguration = $this->webhookConfigurationRegistry->get($webhook); return $this->webhookUrls($webhookConfiguration['success'], $webhookConfiguration['error']); diff --git a/src/Builder/Pdf/AbstractChromiumPdfBuilder.php b/src/Builder/Pdf/AbstractChromiumPdfBuilder.php index 3d607852..5dccd7b1 100644 --- a/src/Builder/Pdf/AbstractChromiumPdfBuilder.php +++ b/src/Builder/Pdf/AbstractChromiumPdfBuilder.php @@ -4,6 +4,7 @@ use Sensiolabs\GotenbergBundle\Builder\CookieAwareTrait; use Sensiolabs\GotenbergBundle\Client\GotenbergClientInterface; +use Sensiolabs\GotenbergBundle\DependencyInjection\WebhookConfiguration\WebhookConfigurationRegistryInterface; use Sensiolabs\GotenbergBundle\Enumeration\EmulatedMediaType; use Sensiolabs\GotenbergBundle\Enumeration\PaperSizeInterface; use Sensiolabs\GotenbergBundle\Enumeration\Part; @@ -28,8 +29,9 @@ public function __construct( AssetBaseDirFormatter $asset, private readonly RequestStack $requestStack, private readonly Environment|null $twig = null, + WebhookConfigurationRegistryInterface $webhookConfigurationRegistry, ) { - parent::__construct($gotenbergClient, $asset); + parent::__construct($gotenbergClient, $asset, $webhookConfigurationRegistry); $normalizers = [ 'extraHttpHeaders' => function (mixed $value): array { diff --git a/src/Builder/Pdf/AbstractPdfBuilder.php b/src/Builder/Pdf/AbstractPdfBuilder.php index 6435ff75..3d483508 100644 --- a/src/Builder/Pdf/AbstractPdfBuilder.php +++ b/src/Builder/Pdf/AbstractPdfBuilder.php @@ -6,6 +6,7 @@ use Sensiolabs\GotenbergBundle\Builder\AsyncBuilderTrait; use Sensiolabs\GotenbergBundle\Builder\DefaultBuilderTrait; use Sensiolabs\GotenbergBundle\Client\GotenbergClientInterface; +use Sensiolabs\GotenbergBundle\DependencyInjection\WebhookConfiguration\WebhookConfigurationRegistryInterface; use Sensiolabs\GotenbergBundle\Formatter\AssetBaseDirFormatter; abstract class AbstractPdfBuilder implements PdfBuilderInterface, AsyncBuilderInterface @@ -16,9 +17,11 @@ abstract class AbstractPdfBuilder implements PdfBuilderInterface, AsyncBuilderIn public function __construct( GotenbergClientInterface $gotenbergClient, AssetBaseDirFormatter $asset, + WebhookConfigurationRegistryInterface $webhookConfigurationRegistry, ) { $this->client = $gotenbergClient; $this->asset = $asset; + $this->webhookConfigurationRegistry = $webhookConfigurationRegistry; $this->normalizers = [ 'metadata' => function (mixed $value): array { diff --git a/src/Builder/Pdf/UrlPdfBuilder.php b/src/Builder/Pdf/UrlPdfBuilder.php index 4d6c3fce..b957de2e 100644 --- a/src/Builder/Pdf/UrlPdfBuilder.php +++ b/src/Builder/Pdf/UrlPdfBuilder.php @@ -3,6 +3,7 @@ namespace Sensiolabs\GotenbergBundle\Builder\Pdf; use Sensiolabs\GotenbergBundle\Client\GotenbergClientInterface; +use Sensiolabs\GotenbergBundle\DependencyInjection\WebhookConfiguration\WebhookConfigurationRegistryInterface; use Sensiolabs\GotenbergBundle\Exception\MissingRequiredFieldException; use Sensiolabs\GotenbergBundle\Formatter\AssetBaseDirFormatter; use Symfony\Component\HttpFoundation\RequestStack; @@ -22,8 +23,9 @@ public function __construct( RequestStack $requestStack, Environment|null $twig = null, private readonly UrlGeneratorInterface|null $urlGenerator = null, + WebhookConfigurationRegistryInterface $webhookConfigurationRegistry, ) { - parent::__construct($gotenbergClient, $asset, $requestStack, $twig); + parent::__construct($gotenbergClient, $asset, $requestStack, $twig, $webhookConfigurationRegistry); $this->addNormalizer('route', $this->generateUrlFromRoute(...)); } diff --git a/src/Builder/Screenshot/AbstractChromiumScreenshotBuilder.php b/src/Builder/Screenshot/AbstractChromiumScreenshotBuilder.php index 81776220..6b74df7b 100644 --- a/src/Builder/Screenshot/AbstractChromiumScreenshotBuilder.php +++ b/src/Builder/Screenshot/AbstractChromiumScreenshotBuilder.php @@ -4,6 +4,7 @@ use Sensiolabs\GotenbergBundle\Builder\CookieAwareTrait; use Sensiolabs\GotenbergBundle\Client\GotenbergClientInterface; +use Sensiolabs\GotenbergBundle\DependencyInjection\WebhookConfiguration\WebhookConfigurationRegistryInterface; use Sensiolabs\GotenbergBundle\Enumeration\EmulatedMediaType; use Sensiolabs\GotenbergBundle\Enumeration\Part; use Sensiolabs\GotenbergBundle\Enumeration\ScreenshotFormat; @@ -26,8 +27,9 @@ public function __construct( AssetBaseDirFormatter $asset, private readonly RequestStack $requestStack, private readonly Environment|null $twig = null, + WebhookConfigurationRegistryInterface $webhookConfigurationRegistry, ) { - parent::__construct($gotenbergClient, $asset); + parent::__construct($gotenbergClient, $asset, $webhookConfigurationRegistry); $normalizers = [ 'extraHttpHeaders' => function (mixed $value): array { diff --git a/src/Builder/Screenshot/AbstractScreenshotBuilder.php b/src/Builder/Screenshot/AbstractScreenshotBuilder.php index 8d203663..15fd3061 100644 --- a/src/Builder/Screenshot/AbstractScreenshotBuilder.php +++ b/src/Builder/Screenshot/AbstractScreenshotBuilder.php @@ -6,6 +6,7 @@ use Sensiolabs\GotenbergBundle\Builder\AsyncBuilderTrait; use Sensiolabs\GotenbergBundle\Builder\DefaultBuilderTrait; use Sensiolabs\GotenbergBundle\Client\GotenbergClientInterface; +use Sensiolabs\GotenbergBundle\DependencyInjection\WebhookConfiguration\WebhookConfigurationRegistryInterface; use Sensiolabs\GotenbergBundle\Enumeration\Part; use Sensiolabs\GotenbergBundle\Formatter\AssetBaseDirFormatter; use Symfony\Component\Mime\Part\DataPart; @@ -18,9 +19,11 @@ abstract class AbstractScreenshotBuilder implements ScreenshotBuilderInterface, public function __construct( GotenbergClientInterface $gotenbergClient, AssetBaseDirFormatter $asset, + WebhookConfigurationRegistryInterface $webhookConfigurationRegistry, ) { $this->client = $gotenbergClient; $this->asset = $asset; + $this->webhookConfigurationRegistry = $webhookConfigurationRegistry; $this->normalizers = [ 'extraHttpHeaders' => function (mixed $value): array { diff --git a/src/Builder/Screenshot/UrlScreenshotBuilder.php b/src/Builder/Screenshot/UrlScreenshotBuilder.php index ff797e7e..df70cf21 100644 --- a/src/Builder/Screenshot/UrlScreenshotBuilder.php +++ b/src/Builder/Screenshot/UrlScreenshotBuilder.php @@ -3,6 +3,7 @@ namespace Sensiolabs\GotenbergBundle\Builder\Screenshot; use Sensiolabs\GotenbergBundle\Client\GotenbergClientInterface; +use Sensiolabs\GotenbergBundle\DependencyInjection\WebhookConfiguration\WebhookConfigurationRegistryInterface; use Sensiolabs\GotenbergBundle\Exception\MissingRequiredFieldException; use Sensiolabs\GotenbergBundle\Formatter\AssetBaseDirFormatter; use Symfony\Component\HttpFoundation\RequestStack; @@ -22,8 +23,9 @@ public function __construct( RequestStack $requestStack, Environment|null $twig = null, private readonly UrlGeneratorInterface|null $urlGenerator = null, + WebhookConfigurationRegistryInterface $webhookConfigurationRegistry, ) { - parent::__construct($gotenbergClient, $asset, $requestStack, $twig); + parent::__construct($gotenbergClient, $asset, $requestStack, $twig, $webhookConfigurationRegistry); $this->addNormalizer('route', $this->generateUrlFromRoute(...)); } diff --git a/src/DependencyInjection/SensiolabsGotenbergExtension.php b/src/DependencyInjection/SensiolabsGotenbergExtension.php index 66abfb2e..8790e8aa 100644 --- a/src/DependencyInjection/SensiolabsGotenbergExtension.php +++ b/src/DependencyInjection/SensiolabsGotenbergExtension.php @@ -4,7 +4,6 @@ use Sensiolabs\GotenbergBundle\Builder\Pdf\PdfBuilderInterface; use Sensiolabs\GotenbergBundle\Builder\Screenshot\ScreenshotBuilderInterface; -use Sensiolabs\GotenbergBundle\DependencyInjection\WebhookConfiguration\WebhookConfigurationRegistryInterface; use Symfony\Component\Config\FileLocator; use Symfony\Component\DependencyInjection\Alias; use Symfony\Component\DependencyInjection\ContainerBuilder; @@ -52,10 +51,6 @@ public function load(array $configs, ContainerBuilder $container): void ->addTag('sensiolabs_gotenberg.screenshot_builder') ; - $container->registerForAutoconfiguration(WebhookConfigurationRegistryInterface::class) - ->addTag('sensiolabs_gotenberg.webhook_configuration_registry') - ; - $container->setAlias('sensiolabs_gotenberg.http_client', new Alias($config['http_client'] ?? 'http_client', false)); $baseUri = $config['request_context']['base_uri'] ?? null; diff --git a/tests/Builder/AbstractBuilderTestCase.php b/tests/Builder/AbstractBuilderTestCase.php index 241bbdfa..f95665e3 100644 --- a/tests/Builder/AbstractBuilderTestCase.php +++ b/tests/Builder/AbstractBuilderTestCase.php @@ -5,6 +5,7 @@ use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use Sensiolabs\GotenbergBundle\Client\GotenbergClientInterface; +use Sensiolabs\GotenbergBundle\DependencyInjection\WebhookConfiguration\WebhookConfigurationRegistryInterface; use Sensiolabs\GotenbergBundle\Formatter\AssetBaseDirFormatter; use Sensiolabs\GotenbergBundle\Twig\GotenbergAssetExtension; use Symfony\Component\Filesystem\Filesystem; @@ -25,6 +26,11 @@ abstract class AbstractBuilderTestCase extends TestCase */ protected GotenbergClientInterface $gotenbergClient; + /** + * @var MockObject&WebhookConfigurationRegistryInterface + */ + protected WebhookConfigurationRegistryInterface $webhookConfigurationRegistry; + public static function setUpBeforeClass(): void { self::$twig = new Environment(new FilesystemLoader(self::FIXTURE_DIR), [ @@ -37,6 +43,7 @@ public static function setUpBeforeClass(): void protected function setUp(): void { $this->gotenbergClient = $this->createMock(GotenbergClientInterface::class); + $this->webhookConfigurationRegistry = $this->createMock(WebhookConfigurationRegistryInterface::class); } /** diff --git a/tests/Builder/Pdf/AbstractChromiumPdfBuilderTest.php b/tests/Builder/Pdf/AbstractChromiumPdfBuilderTest.php index 29cc3a86..379873f7 100644 --- a/tests/Builder/Pdf/AbstractChromiumPdfBuilderTest.php +++ b/tests/Builder/Pdf/AbstractChromiumPdfBuilderTest.php @@ -446,7 +446,7 @@ public function testThrowIfTwigTemplateIsInvalid(): void private function getChromiumPdfBuilder(bool $twig = true, RequestStack $requestStack = new RequestStack()): AbstractChromiumPdfBuilder { - return new class($this->gotenbergClient, self::$assetBaseDirFormatter, $requestStack, true === $twig ? self::$twig : null) extends AbstractChromiumPdfBuilder { + return new class($this->gotenbergClient, self::$assetBaseDirFormatter, $requestStack, true === $twig ? self::$twig : null, $this->webhookConfigurationRegistry) extends AbstractChromiumPdfBuilder { protected function getEndpoint(): string { return '/fake/endpoint'; diff --git a/tests/Builder/Pdf/AbstractPdfBuilderTest.php b/tests/Builder/Pdf/AbstractPdfBuilderTest.php index c69de4f4..c567a8a4 100644 --- a/tests/Builder/Pdf/AbstractPdfBuilderTest.php +++ b/tests/Builder/Pdf/AbstractPdfBuilderTest.php @@ -11,6 +11,7 @@ use Sensiolabs\GotenbergBundle\Client\GotenbergClient; use Sensiolabs\GotenbergBundle\Client\GotenbergClientInterface; use Sensiolabs\GotenbergBundle\Client\GotenbergResponse; +use Sensiolabs\GotenbergBundle\DependencyInjection\WebhookConfiguration\WebhookConfigurationRegistryInterface; use Sensiolabs\GotenbergBundle\Formatter\AssetBaseDirFormatter; use Sensiolabs\GotenbergBundle\Processor\NullProcessor; use Sensiolabs\GotenbergBundle\Tests\Builder\AbstractBuilderTestCase; @@ -76,13 +77,13 @@ public function testNativeNormalizers(string $key, mixed $raw, mixed $expected): */ private function getPdfBuilder(array $formFields = []): AbstractPdfBuilder { - return (new class($this->gotenbergClient, self::$assetBaseDirFormatter, $formFields) extends AbstractPdfBuilder { + return (new class($this->gotenbergClient, self::$assetBaseDirFormatter, $this->webhookConfigurationRegistry, $formFields) extends AbstractPdfBuilder { /** * @param array $formFields */ - public function __construct(GotenbergClientInterface $gotenbergClient, AssetBaseDirFormatter $asset, array $formFields = []) + public function __construct(GotenbergClientInterface $gotenbergClient, AssetBaseDirFormatter $asset, WebhookConfigurationRegistryInterface $webhookConfigurationRegistry, array $formFields = []) { - parent::__construct($gotenbergClient, $asset); + parent::__construct($gotenbergClient, $asset, $webhookConfigurationRegistry); $this->formFields = $formFields; } diff --git a/tests/Builder/Pdf/ConvertPdfBuilderTest.php b/tests/Builder/Pdf/ConvertPdfBuilderTest.php index b2384d63..ce7cc4a4 100644 --- a/tests/Builder/Pdf/ConvertPdfBuilderTest.php +++ b/tests/Builder/Pdf/ConvertPdfBuilderTest.php @@ -91,7 +91,7 @@ public function testRequiredPdfFile(): void private function getConvertPdfBuilder(): ConvertPdfBuilder { - return (new ConvertPdfBuilder($this->gotenbergClient, self::$assetBaseDirFormatter)) + return (new ConvertPdfBuilder($this->gotenbergClient, self::$assetBaseDirFormatter, $this->webhookConfigurationRegistry)) ->processor(new NullProcessor()) ; } diff --git a/tests/Builder/Pdf/HtmlPdfBuilderTest.php b/tests/Builder/Pdf/HtmlPdfBuilderTest.php index 1ce3dcab..6635ed41 100644 --- a/tests/Builder/Pdf/HtmlPdfBuilderTest.php +++ b/tests/Builder/Pdf/HtmlPdfBuilderTest.php @@ -111,7 +111,7 @@ public function testRequiredFormData(): void private function getHtmlPdfBuilder(bool $twig = true): HtmlPdfBuilder { - return (new HtmlPdfBuilder($this->gotenbergClient, self::$assetBaseDirFormatter, new RequestStack(), true === $twig ? self::$twig : null)) + return (new HtmlPdfBuilder($this->gotenbergClient, self::$assetBaseDirFormatter, new RequestStack(), true === $twig ? self::$twig : null, $this->webhookConfigurationRegistry)) ->processor(new NullProcessor()) ; } diff --git a/tests/Builder/Pdf/LibreOfficePdfBuilderTest.php b/tests/Builder/Pdf/LibreOfficePdfBuilderTest.php index d5742ac3..f854c8a7 100644 --- a/tests/Builder/Pdf/LibreOfficePdfBuilderTest.php +++ b/tests/Builder/Pdf/LibreOfficePdfBuilderTest.php @@ -165,7 +165,7 @@ public function testRequiredFormData(): void private function getLibreOfficePdfBuilder(): LibreOfficePdfBuilder { - return (new LibreOfficePdfBuilder($this->gotenbergClient, self::$assetBaseDirFormatter)) + return (new LibreOfficePdfBuilder($this->gotenbergClient, self::$assetBaseDirFormatter, $this->webhookConfigurationRegistry)) ->processor(new NullProcessor()) ; } diff --git a/tests/Builder/Pdf/MarkdownPdfBuilderTest.php b/tests/Builder/Pdf/MarkdownPdfBuilderTest.php index cccfc05d..d50baead 100644 --- a/tests/Builder/Pdf/MarkdownPdfBuilderTest.php +++ b/tests/Builder/Pdf/MarkdownPdfBuilderTest.php @@ -68,7 +68,7 @@ public function testRequiredMarkdownFile(): void private function getMarkdownPdfBuilder(bool $twig = true): MarkdownPdfBuilder { - return (new MarkdownPdfBuilder($this->gotenbergClient, self::$assetBaseDirFormatter, new RequestStack(), true === $twig ? self::$twig : null)) + return (new MarkdownPdfBuilder($this->gotenbergClient, self::$assetBaseDirFormatter, new RequestStack(), true === $twig ? self::$twig : null, $this->webhookConfigurationRegistry)) ->processor(new NullProcessor()) ; } diff --git a/tests/Builder/Pdf/MergePdfBuilderTest.php b/tests/Builder/Pdf/MergePdfBuilderTest.php index d1fff0d5..89cbc2ad 100644 --- a/tests/Builder/Pdf/MergePdfBuilderTest.php +++ b/tests/Builder/Pdf/MergePdfBuilderTest.php @@ -85,7 +85,7 @@ public function testRequiredFormData(): void private function getMergePdfBuilder(): MergePdfBuilder { - return (new MergePdfBuilder($this->gotenbergClient, self::$assetBaseDirFormatter)) + return (new MergePdfBuilder($this->gotenbergClient, self::$assetBaseDirFormatter, $this->webhookConfigurationRegistry)) ->processor(new NullProcessor()) ; } diff --git a/tests/Builder/Pdf/UrlPdfBuilderTest.php b/tests/Builder/Pdf/UrlPdfBuilderTest.php index f16b38e2..54633536 100644 --- a/tests/Builder/Pdf/UrlPdfBuilderTest.php +++ b/tests/Builder/Pdf/UrlPdfBuilderTest.php @@ -132,7 +132,7 @@ public function testRequiredEitherUrlOrRouteNotBoth(): void private function getUrlPdfBuilder(UrlGeneratorInterface|null $urlGenerator = null): UrlPdfBuilder { - return (new UrlPdfBuilder($this->gotenbergClient, self::$assetBaseDirFormatter, new RequestStack(), urlGenerator: $urlGenerator)) + return (new UrlPdfBuilder($this->gotenbergClient, self::$assetBaseDirFormatter, new RequestStack(), null, $urlGenerator, $this->webhookConfigurationRegistry)) ->processor(new NullProcessor()) ; } diff --git a/tests/Builder/Screenshot/AbstractChromiumScreenshotBuilderTest.php b/tests/Builder/Screenshot/AbstractChromiumScreenshotBuilderTest.php index 0fb50301..def63793 100644 --- a/tests/Builder/Screenshot/AbstractChromiumScreenshotBuilderTest.php +++ b/tests/Builder/Screenshot/AbstractChromiumScreenshotBuilderTest.php @@ -85,7 +85,7 @@ public function testConfigurationIsCorrectlySet(string $key, mixed $value, array private function getChromiumScreenshotBuilder(bool $twig = true): AbstractChromiumScreenshotBuilder { - return new class($this->gotenbergClient, self::$assetBaseDirFormatter, new RequestStack(), true === $twig ? self::$twig : null) extends AbstractChromiumScreenshotBuilder { + return new class($this->gotenbergClient, self::$assetBaseDirFormatter, new RequestStack(), true === $twig ? self::$twig : null, $this->webhookConfigurationRegistry) extends AbstractChromiumScreenshotBuilder { protected function getEndpoint(): string { return '/fake/endpoint'; diff --git a/tests/Builder/Screenshot/AbstractScreenshotBuilderTest.php b/tests/Builder/Screenshot/AbstractScreenshotBuilderTest.php index f34bf50d..051b1557 100644 --- a/tests/Builder/Screenshot/AbstractScreenshotBuilderTest.php +++ b/tests/Builder/Screenshot/AbstractScreenshotBuilderTest.php @@ -11,6 +11,7 @@ use Sensiolabs\GotenbergBundle\Client\GotenbergClient; use Sensiolabs\GotenbergBundle\Client\GotenbergClientInterface; use Sensiolabs\GotenbergBundle\Client\GotenbergResponse; +use Sensiolabs\GotenbergBundle\DependencyInjection\WebhookConfiguration\WebhookConfigurationRegistryInterface; use Sensiolabs\GotenbergBundle\Formatter\AssetBaseDirFormatter; use Sensiolabs\GotenbergBundle\Processor\NullProcessor; use Sensiolabs\GotenbergBundle\Tests\Builder\AbstractBuilderTestCase; @@ -74,13 +75,13 @@ public function testNativeNormalizers(string $key, mixed $raw, mixed $expected): */ private function getScreenshotBuilder(array $formFields = []): AbstractScreenshotBuilder { - return (new class($this->gotenbergClient, self::$assetBaseDirFormatter, $formFields) extends AbstractScreenshotBuilder { + return (new class($this->gotenbergClient, self::$assetBaseDirFormatter, $this->webhookConfigurationRegistry, $formFields) extends AbstractScreenshotBuilder { /** * @param array $formFields */ - public function __construct(GotenbergClientInterface $gotenbergClient, AssetBaseDirFormatter $asset, array $formFields = []) + public function __construct(GotenbergClientInterface $gotenbergClient, AssetBaseDirFormatter $asset, WebhookConfigurationRegistryInterface $webhookConfigurationRegistry, array $formFields = []) { - parent::__construct($gotenbergClient, $asset); + parent::__construct($gotenbergClient, $asset, $webhookConfigurationRegistry); $this->formFields = $formFields; } diff --git a/tests/Builder/Screenshot/HtmlScreenshotBuilderTest.php b/tests/Builder/Screenshot/HtmlScreenshotBuilderTest.php index 8fe7aeae..78e016ad 100644 --- a/tests/Builder/Screenshot/HtmlScreenshotBuilderTest.php +++ b/tests/Builder/Screenshot/HtmlScreenshotBuilderTest.php @@ -111,7 +111,7 @@ public function testRequiredFormData(): void private function getHtmlScreenshotBuilder(bool $twig = true): HtmlScreenshotBuilder { - return (new HtmlScreenshotBuilder($this->gotenbergClient, self::$assetBaseDirFormatter, new RequestStack(), true === $twig ? self::$twig : null)) + return (new HtmlScreenshotBuilder($this->gotenbergClient, self::$assetBaseDirFormatter, new RequestStack(), true === $twig ? self::$twig : null, $this->webhookConfigurationRegistry)) ->processor(new NullProcessor()) ; } diff --git a/tests/Builder/Screenshot/MarkdownScreenshotBuilderTest.php b/tests/Builder/Screenshot/MarkdownScreenshotBuilderTest.php index d8511b2d..7ae83cc0 100644 --- a/tests/Builder/Screenshot/MarkdownScreenshotBuilderTest.php +++ b/tests/Builder/Screenshot/MarkdownScreenshotBuilderTest.php @@ -96,7 +96,7 @@ public function testRequiredMarkdownFile(): void private function getMarkdownScreenshotBuilder(bool $twig = true): MarkdownScreenshotBuilder { - return (new MarkdownScreenshotBuilder($this->gotenbergClient, self::$assetBaseDirFormatter, new RequestStack(), true === $twig ? self::$twig : null)) + return (new MarkdownScreenshotBuilder($this->gotenbergClient, self::$assetBaseDirFormatter, new RequestStack(), true === $twig ? self::$twig : null, $this->webhookConfigurationRegistry)) ->processor(new NullProcessor()) ; } diff --git a/tests/Builder/Screenshot/UrlScreenshotBuilderTest.php b/tests/Builder/Screenshot/UrlScreenshotBuilderTest.php index 9cc4e7ca..9f2720f0 100644 --- a/tests/Builder/Screenshot/UrlScreenshotBuilderTest.php +++ b/tests/Builder/Screenshot/UrlScreenshotBuilderTest.php @@ -80,6 +80,7 @@ private function getUrlScreenshotBuilder(bool $twig = true): UrlScreenshotBuilde new RequestStack(), true === $twig ? self::$twig : null, $this->router, + $this->webhookConfigurationRegistry, )) ->processor(new NullProcessor()) ; diff --git a/tests/DependencyInjection/SensiolabsGotenbergExtensionTest.php b/tests/DependencyInjection/SensiolabsGotenbergExtensionTest.php index 98d4e0ca..135c8f40 100644 --- a/tests/DependencyInjection/SensiolabsGotenbergExtensionTest.php +++ b/tests/DependencyInjection/SensiolabsGotenbergExtensionTest.php @@ -257,7 +257,7 @@ public function testUrlBuildersCanChangeTheirRequestContext(string $serviceName) self::assertSame('https://sensiolabs.com', $requestContextDefinition->getArgument(0)); $urlBuilderDefinition = $containerBuilder->getDefinition($serviceName); - self::assertCount(4, $urlBuilderDefinition->getMethodCalls()); + self::assertCount(3, $urlBuilderDefinition->getMethodCalls()); $indexedMethodCalls = []; foreach ($urlBuilderDefinition->getMethodCalls() as $methodCall) { From b26c12f927155cce257478e462ee99c144564144 Mon Sep 17 00:00:00 2001 From: Maelan LE BORGNE Date: Thu, 3 Oct 2024 16:01:37 +0200 Subject: [PATCH 03/24] cleanup after review --- src/Builder/AsyncBuilderTrait.php | 9 ++++++++- src/Builder/Pdf/AbstractChromiumPdfBuilder.php | 1 - src/DependencyInjection/Configuration.php | 6 +++--- src/DependencyInjection/SensiolabsGotenbergExtension.php | 6 +++--- .../SensiolabsGotenbergExtensionTest.php | 1 - 5 files changed, 14 insertions(+), 9 deletions(-) diff --git a/src/Builder/AsyncBuilderTrait.php b/src/Builder/AsyncBuilderTrait.php index 9d1c534f..20cf2574 100644 --- a/src/Builder/AsyncBuilderTrait.php +++ b/src/Builder/AsyncBuilderTrait.php @@ -14,6 +14,9 @@ trait AsyncBuilderTrait * @var array */ private array $webhookExtraHeaders = []; + /** + * @var \Closure(): string + */ private \Closure $operationIdGenerator; private WebhookConfigurationRegistryInterface $webhookConfigurationRegistry; @@ -32,7 +35,8 @@ public function generateAsync(): string 'Gotenberg-Webhook-Extra-Http-Headers' => json_encode($this->webhookExtraHeaders, \JSON_THROW_ON_ERROR), ]; if (null !== $this->fileName) { - $headers['Gotenberg-Output-Filename'] = basename($this->fileName, '.pdf'); + // Gotenberg will add the extension to the file name (e.g. filename : "file.pdf" => generated file : "file.pdf.pdf"). + $headers['Gotenberg-Output-Filename'] = $this->fileName; } $this->client->call($this->getEndpoint(), $this->getMultipartFormData(), $headers); @@ -71,6 +75,9 @@ public function webhookExtraHeaders(array $extraHeaders): static return $this; } + /** + * @param \Closure(): string $operationIdGenerator + */ public function operationIdGenerator(\Closure $operationIdGenerator): static { $this->operationIdGenerator = $operationIdGenerator; diff --git a/src/Builder/Pdf/AbstractChromiumPdfBuilder.php b/src/Builder/Pdf/AbstractChromiumPdfBuilder.php index 5dccd7b1..68f6cb4a 100644 --- a/src/Builder/Pdf/AbstractChromiumPdfBuilder.php +++ b/src/Builder/Pdf/AbstractChromiumPdfBuilder.php @@ -588,7 +588,6 @@ protected function addConfiguration(string $configurationName, mixed $value): vo 'fail_on_console_exceptions' => $this->failOnConsoleExceptions($value), 'skip_network_idle_event' => $this->skipNetworkIdleEvent($value), 'metadata' => $this->metadata($value), - 'webhook' => null, default => throw new InvalidBuilderConfiguration(sprintf('Invalid option "%s": no method does not exist in class "%s" to configured it.', $configurationName, static::class)), }; } diff --git a/src/DependencyInjection/Configuration.php b/src/DependencyInjection/Configuration.php index 59cd609a..c05b8e24 100644 --- a/src/DependencyInjection/Configuration.php +++ b/src/DependencyInjection/Configuration.php @@ -673,17 +673,17 @@ private function addNamedWebhookDefinition(): NodeDefinition ->children() ->scalarNode('name') ->validate() - ->ifTrue(static function ($option) { + ->ifTrue(static function (mixed $option): bool { return !\is_string($option); }) - ->thenInvalid('Invalid header name %s') + ->thenInvalid('Invalid webhook configuration name %s') ->end() ->end() ->append($this->addWebhookConfigurationNode('success')) ->append($this->addWebhookConfigurationNode('error')) ->end() ->validate() - ->ifTrue(static function ($option): bool { + ->ifTrue(static function (mixed $option): bool { return !isset($option['success']); }) ->thenInvalid('Invalid webhook configuration : At least a "success" key is required.') diff --git a/src/DependencyInjection/SensiolabsGotenbergExtension.php b/src/DependencyInjection/SensiolabsGotenbergExtension.php index 8790e8aa..e6db866d 100644 --- a/src/DependencyInjection/SensiolabsGotenbergExtension.php +++ b/src/DependencyInjection/SensiolabsGotenbergExtension.php @@ -100,9 +100,9 @@ public function load(array $configs, ContainerBuilder $container): void */ private function cleanUserOptions(array $userConfigurations): array { - return array_filter($userConfigurations, static function ($config): bool { - return null !== $config; - }); + return array_filter($userConfigurations, static function ($config, $configName): bool { + return null !== $config && 'webhook' !== $configName; + }, \ARRAY_FILTER_USE_BOTH); } /** diff --git a/tests/DependencyInjection/SensiolabsGotenbergExtensionTest.php b/tests/DependencyInjection/SensiolabsGotenbergExtensionTest.php index 135c8f40..eac569be 100644 --- a/tests/DependencyInjection/SensiolabsGotenbergExtensionTest.php +++ b/tests/DependencyInjection/SensiolabsGotenbergExtensionTest.php @@ -65,7 +65,6 @@ public function testGotenbergConfiguredWithValidConfig(): void 'skip_network_idle_event' => true, 'pdf_format' => 'PDF/A-1b', 'pdf_universal_access' => true, - 'webhook' => ['config_name' => 'bar'], ], 'url' => [ 'paper_width' => 21, From abd6e4764ceea2d6136abe6f67a6f6196ddef38b Mon Sep 17 00:00:00 2001 From: Adrien Roches Date: Thu, 24 Oct 2024 15:49:13 +0200 Subject: [PATCH 04/24] [UPDATE] Allow to set extra headers when using webhook --- config/services.php | 4 +- src/Builder/AsyncBuilderTrait.php | 21 ++++++-- .../Pdf/AbstractChromiumPdfBuilder.php | 2 +- src/Builder/Pdf/AbstractPdfBuilder.php | 2 +- src/Builder/Pdf/UrlPdfBuilder.php | 2 +- .../AbstractChromiumScreenshotBuilder.php | 2 +- .../Screenshot/AbstractScreenshotBuilder.php | 2 +- .../Screenshot/UrlScreenshotBuilder.php | 2 +- src/Debug/Builder/TraceablePdfBuilder.php | 2 +- .../Builder/TraceableScreenshotBuilder.php | 2 +- src/DependencyInjection/Configuration.php | 52 ++++++++++++++++++- .../WebhookConfigurationRegistry.php | 29 +++++++---- .../WebhookConfigurationRegistryInterface.php | 12 ++++- tests/Builder/AbstractBuilderTestCase.php | 2 +- tests/Builder/Pdf/AbstractPdfBuilderTest.php | 2 +- .../AbstractScreenshotBuilderTest.php | 2 +- .../SensiolabsGotenbergExtensionTest.php | 6 +-- .../WebhookConfigurationRegistryTest.php | 2 +- tests/GotenbergPdfTest.php | 2 +- tests/GotenbergScreenshotTest.php | 2 +- 20 files changed, 114 insertions(+), 38 deletions(-) rename src/{DependencyInjection/WebhookConfiguration => Webhook}/WebhookConfigurationRegistry.php (69%) rename src/{DependencyInjection/WebhookConfiguration => Webhook}/WebhookConfigurationRegistryInterface.php (55%) diff --git a/config/services.php b/config/services.php index e5593615..f82d71fd 100644 --- a/config/services.php +++ b/config/services.php @@ -2,8 +2,6 @@ use Sensiolabs\GotenbergBundle\Client\GotenbergClient; use Sensiolabs\GotenbergBundle\Client\GotenbergClientInterface; -use Sensiolabs\GotenbergBundle\DependencyInjection\WebhookConfiguration\WebhookConfigurationRegistry; -use Sensiolabs\GotenbergBundle\DependencyInjection\WebhookConfiguration\WebhookConfigurationRegistryInterface; use Sensiolabs\GotenbergBundle\EventListener\ProcessBuilderOnControllerResponse; use Sensiolabs\GotenbergBundle\Formatter\AssetBaseDirFormatter; use Sensiolabs\GotenbergBundle\Gotenberg; @@ -13,6 +11,8 @@ use Sensiolabs\GotenbergBundle\GotenbergScreenshot; use Sensiolabs\GotenbergBundle\GotenbergScreenshotInterface; use Sensiolabs\GotenbergBundle\Twig\GotenbergAssetExtension; +use Sensiolabs\GotenbergBundle\Webhook\WebhookConfigurationRegistry; +use Sensiolabs\GotenbergBundle\Webhook\WebhookConfigurationRegistryInterface; use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator; use Symfony\Component\Filesystem\Filesystem; use function Symfony\Component\DependencyInjection\Loader\Configurator\abstract_arg; diff --git a/src/Builder/AsyncBuilderTrait.php b/src/Builder/AsyncBuilderTrait.php index 20cf2574..976f2f36 100644 --- a/src/Builder/AsyncBuilderTrait.php +++ b/src/Builder/AsyncBuilderTrait.php @@ -2,22 +2,27 @@ namespace Sensiolabs\GotenbergBundle\Builder; -use Sensiolabs\GotenbergBundle\DependencyInjection\WebhookConfiguration\WebhookConfigurationRegistry; -use Sensiolabs\GotenbergBundle\DependencyInjection\WebhookConfiguration\WebhookConfigurationRegistryInterface; +use Sensiolabs\GotenbergBundle\Webhook\WebhookConfigurationRegistry; +use Sensiolabs\GotenbergBundle\Webhook\WebhookConfigurationRegistryInterface; trait AsyncBuilderTrait { use DefaultBuilderTrait; + private string $webhookUrl; + private string $errorWebhookUrl; + /** * @var array */ private array $webhookExtraHeaders = []; + /** - * @var \Closure(): string + * @var (\Closure(): string) */ private \Closure $operationIdGenerator; + private WebhookConfigurationRegistryInterface $webhookConfigurationRegistry; public function generateAsync(): string @@ -54,7 +59,13 @@ public function webhookConfiguration(string $webhook): static { $webhookConfiguration = $this->webhookConfigurationRegistry->get($webhook); - return $this->webhookUrls($webhookConfiguration['success'], $webhookConfiguration['error']); + $result = $this->webhookUrls($webhookConfiguration['success'], $webhookConfiguration['error']); + + if (\array_key_exists('extra_http_headers', $webhookConfiguration)) { + $result = $result->webhookExtraHeaders($webhookConfiguration['extra_http_headers']); + } + + return $result; } public function webhookUrls(string $successWebhook, string|null $errorWebhook = null): static @@ -76,7 +87,7 @@ public function webhookExtraHeaders(array $extraHeaders): static } /** - * @param \Closure(): string $operationIdGenerator + * @param (\Closure(): string) $operationIdGenerator */ public function operationIdGenerator(\Closure $operationIdGenerator): static { diff --git a/src/Builder/Pdf/AbstractChromiumPdfBuilder.php b/src/Builder/Pdf/AbstractChromiumPdfBuilder.php index 9f02baa9..b718ead6 100644 --- a/src/Builder/Pdf/AbstractChromiumPdfBuilder.php +++ b/src/Builder/Pdf/AbstractChromiumPdfBuilder.php @@ -4,7 +4,6 @@ use Sensiolabs\GotenbergBundle\Builder\CookieAwareTrait; use Sensiolabs\GotenbergBundle\Client\GotenbergClientInterface; -use Sensiolabs\GotenbergBundle\DependencyInjection\WebhookConfiguration\WebhookConfigurationRegistryInterface; use Sensiolabs\GotenbergBundle\Enumeration\EmulatedMediaType; use Sensiolabs\GotenbergBundle\Enumeration\PaperSize; use Sensiolabs\GotenbergBundle\Enumeration\PaperSizeInterface; @@ -15,6 +14,7 @@ use Sensiolabs\GotenbergBundle\Exception\InvalidBuilderConfiguration; use Sensiolabs\GotenbergBundle\Exception\PdfPartRenderingException; use Sensiolabs\GotenbergBundle\Formatter\AssetBaseDirFormatter; +use Sensiolabs\GotenbergBundle\Webhook\WebhookConfigurationRegistryInterface; use Symfony\Component\HttpFoundation\Cookie; use Symfony\Component\HttpFoundation\RequestStack; use Symfony\Component\Mime\Part\DataPart; diff --git a/src/Builder/Pdf/AbstractPdfBuilder.php b/src/Builder/Pdf/AbstractPdfBuilder.php index 3d483508..7529d016 100644 --- a/src/Builder/Pdf/AbstractPdfBuilder.php +++ b/src/Builder/Pdf/AbstractPdfBuilder.php @@ -6,8 +6,8 @@ use Sensiolabs\GotenbergBundle\Builder\AsyncBuilderTrait; use Sensiolabs\GotenbergBundle\Builder\DefaultBuilderTrait; use Sensiolabs\GotenbergBundle\Client\GotenbergClientInterface; -use Sensiolabs\GotenbergBundle\DependencyInjection\WebhookConfiguration\WebhookConfigurationRegistryInterface; use Sensiolabs\GotenbergBundle\Formatter\AssetBaseDirFormatter; +use Sensiolabs\GotenbergBundle\Webhook\WebhookConfigurationRegistryInterface; abstract class AbstractPdfBuilder implements PdfBuilderInterface, AsyncBuilderInterface { diff --git a/src/Builder/Pdf/UrlPdfBuilder.php b/src/Builder/Pdf/UrlPdfBuilder.php index 0826eea2..fd43d844 100644 --- a/src/Builder/Pdf/UrlPdfBuilder.php +++ b/src/Builder/Pdf/UrlPdfBuilder.php @@ -3,9 +3,9 @@ namespace Sensiolabs\GotenbergBundle\Builder\Pdf; use Sensiolabs\GotenbergBundle\Client\GotenbergClientInterface; -use Sensiolabs\GotenbergBundle\DependencyInjection\WebhookConfiguration\WebhookConfigurationRegistryInterface; use Sensiolabs\GotenbergBundle\Exception\MissingRequiredFieldException; use Sensiolabs\GotenbergBundle\Formatter\AssetBaseDirFormatter; +use Sensiolabs\GotenbergBundle\Webhook\WebhookConfigurationRegistryInterface; use Symfony\Component\HttpFoundation\RequestStack; use Symfony\Component\Routing\Generator\UrlGeneratorInterface; use Symfony\Component\Routing\RequestContext; diff --git a/src/Builder/Screenshot/AbstractChromiumScreenshotBuilder.php b/src/Builder/Screenshot/AbstractChromiumScreenshotBuilder.php index 944dc15b..1fdac8de 100644 --- a/src/Builder/Screenshot/AbstractChromiumScreenshotBuilder.php +++ b/src/Builder/Screenshot/AbstractChromiumScreenshotBuilder.php @@ -4,7 +4,6 @@ use Sensiolabs\GotenbergBundle\Builder\CookieAwareTrait; use Sensiolabs\GotenbergBundle\Client\GotenbergClientInterface; -use Sensiolabs\GotenbergBundle\DependencyInjection\WebhookConfiguration\WebhookConfigurationRegistryInterface; use Sensiolabs\GotenbergBundle\Enumeration\EmulatedMediaType; use Sensiolabs\GotenbergBundle\Enumeration\Part; use Sensiolabs\GotenbergBundle\Enumeration\ScreenshotFormat; @@ -12,6 +11,7 @@ use Sensiolabs\GotenbergBundle\Exception\InvalidBuilderConfiguration; use Sensiolabs\GotenbergBundle\Exception\ScreenshotPartRenderingException; use Sensiolabs\GotenbergBundle\Formatter\AssetBaseDirFormatter; +use Sensiolabs\GotenbergBundle\Webhook\WebhookConfigurationRegistryInterface; use Symfony\Component\HttpFoundation\Cookie; use Symfony\Component\HttpFoundation\RequestStack; use Symfony\Component\Mime\Part\DataPart; diff --git a/src/Builder/Screenshot/AbstractScreenshotBuilder.php b/src/Builder/Screenshot/AbstractScreenshotBuilder.php index 15fd3061..dca92fb4 100644 --- a/src/Builder/Screenshot/AbstractScreenshotBuilder.php +++ b/src/Builder/Screenshot/AbstractScreenshotBuilder.php @@ -6,9 +6,9 @@ use Sensiolabs\GotenbergBundle\Builder\AsyncBuilderTrait; use Sensiolabs\GotenbergBundle\Builder\DefaultBuilderTrait; use Sensiolabs\GotenbergBundle\Client\GotenbergClientInterface; -use Sensiolabs\GotenbergBundle\DependencyInjection\WebhookConfiguration\WebhookConfigurationRegistryInterface; use Sensiolabs\GotenbergBundle\Enumeration\Part; use Sensiolabs\GotenbergBundle\Formatter\AssetBaseDirFormatter; +use Sensiolabs\GotenbergBundle\Webhook\WebhookConfigurationRegistryInterface; use Symfony\Component\Mime\Part\DataPart; abstract class AbstractScreenshotBuilder implements ScreenshotBuilderInterface, AsyncBuilderInterface diff --git a/src/Builder/Screenshot/UrlScreenshotBuilder.php b/src/Builder/Screenshot/UrlScreenshotBuilder.php index da886f1f..a7dd3ca5 100644 --- a/src/Builder/Screenshot/UrlScreenshotBuilder.php +++ b/src/Builder/Screenshot/UrlScreenshotBuilder.php @@ -3,9 +3,9 @@ namespace Sensiolabs\GotenbergBundle\Builder\Screenshot; use Sensiolabs\GotenbergBundle\Client\GotenbergClientInterface; -use Sensiolabs\GotenbergBundle\DependencyInjection\WebhookConfiguration\WebhookConfigurationRegistryInterface; use Sensiolabs\GotenbergBundle\Exception\MissingRequiredFieldException; use Sensiolabs\GotenbergBundle\Formatter\AssetBaseDirFormatter; +use Sensiolabs\GotenbergBundle\Webhook\WebhookConfigurationRegistryInterface; use Symfony\Component\HttpFoundation\RequestStack; use Symfony\Component\Routing\Generator\UrlGeneratorInterface; use Symfony\Component\Routing\RequestContext; diff --git a/src/Debug/Builder/TraceablePdfBuilder.php b/src/Debug/Builder/TraceablePdfBuilder.php index 32059713..c92bca08 100644 --- a/src/Debug/Builder/TraceablePdfBuilder.php +++ b/src/Debug/Builder/TraceablePdfBuilder.php @@ -54,7 +54,7 @@ public function generate(): GotenbergFileResult public function generateAsync(): string { if (!$this->inner instanceof AsyncBuilderInterface) { - throw new \LogicException(sprintf('The inner builder of %s must implement %s.', self::class, AsyncBuilderInterface::class)); + throw new \LogicException(\sprintf('The inner builder of %s must implement %s.', self::class, AsyncBuilderInterface::class)); } $name = self::$count.'.'.$this->inner::class.'::'.__FUNCTION__; diff --git a/src/Debug/Builder/TraceableScreenshotBuilder.php b/src/Debug/Builder/TraceableScreenshotBuilder.php index 22d85521..1e6964fb 100644 --- a/src/Debug/Builder/TraceableScreenshotBuilder.php +++ b/src/Debug/Builder/TraceableScreenshotBuilder.php @@ -55,7 +55,7 @@ public function generate(): GotenbergFileResult public function generateAsync(): string { if (!$this->inner instanceof AsyncBuilderInterface) { - throw new \LogicException(sprintf('The inner builder of %s must implement %s.', self::class, AsyncBuilderInterface::class)); + throw new \LogicException(\sprintf('The inner builder of %s must implement %s.', self::class, AsyncBuilderInterface::class)); } $name = self::$count.'.'.$this->inner::class.'::'.__FUNCTION__; diff --git a/src/DependencyInjection/Configuration.php b/src/DependencyInjection/Configuration.php index f9cb2a52..10f53be6 100644 --- a/src/DependencyInjection/Configuration.php +++ b/src/DependencyInjection/Configuration.php @@ -697,6 +697,30 @@ private function addNamedWebhookDefinition(): NodeDefinition ->end() ->append($this->addWebhookConfigurationNode('success')) ->append($this->addWebhookConfigurationNode('error')) + ->arrayNode('extra_http_headers') + ->info('HTTP headers to send by Chromium while loading the HTML document - default None. https://gotenberg.dev/docs/routes#custom-http-headers') + ->useAttributeAsKey('name') + ->arrayPrototype() + ->children() + ->scalarNode('name') + ->validate() + ->ifTrue(static function ($option) { + return !\is_string($option); + }) + ->thenInvalid('Invalid header name %s') + ->end() + ->end() + ->scalarNode('value') + ->validate() + ->ifTrue(static function ($option) { + return !\is_string($option); + }) + ->thenInvalid('Invalid header value %s') + ->end() + ->end() + ->end() + ->end() + ->end() ->end() ->validate() ->ifTrue(static function (mixed $option): bool { @@ -720,11 +744,35 @@ private function addWebhookDeclarationNode(ArrayNodeDefinition $parent): void }) ->end() ->children() - ->append($this->addWebhookConfigurationNode('success')) - ->append($this->addWebhookConfigurationNode('error')) ->scalarNode('config_name') ->info('The name of the webhook configuration to use.') ->end() + ->append($this->addWebhookConfigurationNode('success')) + ->append($this->addWebhookConfigurationNode('error')) + ->arrayNode('extra_http_headers') + ->info('HTTP headers to send by Chromium while loading the HTML document - default None. https://gotenberg.dev/docs/routes#custom-http-headers') + ->useAttributeAsKey('name') + ->arrayPrototype() + ->children() + ->scalarNode('name') + ->validate() + ->ifTrue(static function ($option) { + return !\is_string($option); + }) + ->thenInvalid('Invalid header name %s') + ->end() + ->end() + ->scalarNode('value') + ->validate() + ->ifTrue(static function ($option) { + return !\is_string($option); + }) + ->thenInvalid('Invalid header value %s') + ->end() + ->end() + ->end() + ->end() + ->end() ->end() ->validate() ->ifTrue(static function ($option): bool { diff --git a/src/DependencyInjection/WebhookConfiguration/WebhookConfigurationRegistry.php b/src/Webhook/WebhookConfigurationRegistry.php similarity index 69% rename from src/DependencyInjection/WebhookConfiguration/WebhookConfigurationRegistry.php rename to src/Webhook/WebhookConfigurationRegistry.php index 40685d4e..04f3af52 100644 --- a/src/DependencyInjection/WebhookConfiguration/WebhookConfigurationRegistry.php +++ b/src/Webhook/WebhookConfigurationRegistry.php @@ -1,6 +1,6 @@ }} + * @phpstan-import-type WebhookDefinition from WebhookConfigurationRegistryInterface */ final class WebhookConfigurationRegistry implements WebhookConfigurationRegistryInterface { /** - * @var array + * @var array + * }> */ private array $configurations = []; @@ -25,7 +29,7 @@ public function __construct( } /** - * @param array{success: WebhookDefinition, error?: WebhookDefinition} $configuration + * @param array{success: WebhookDefinition, error?: WebhookDefinition, extra_http_headers?: array} $configuration */ public function add(string $name, array $configuration): void { @@ -40,19 +44,23 @@ public function add(string $name, array $configuration): void if (isset($configuration['error'])) { $error = $this->processWebhookConfiguration($configuration['error']); } - $this->configurations[$name] = ['success' => $success, 'error' => $error]; + + $namedConfiguration = ['success' => $success, 'error' => $error]; + + if (\array_key_exists('extra_http_headers', $configuration) && [] !== $configuration['extra_http_headers']) { + $namedConfiguration['extra_http_headers'] = $configuration['extra_http_headers']; + } + + $this->configurations[$name] = $namedConfiguration; } finally { $this->urlGenerator->setContext($requestContext); } } - /** - * @return array{success: string, error: string} - */ public function get(string $name): array { if (!\array_key_exists($name, $this->configurations)) { - throw new WebhookConfigurationException(sprintf('Webhook configuration "%s" not found.', $name)); + throw new WebhookConfigurationException("Webhook configuration \"{$name}\" not found."); } return $this->configurations[$name]; @@ -61,13 +69,14 @@ public function get(string $name): array /** * @param WebhookDefinition $webhookDefinition * - * @throws \InvalidArgumentException + * @throws WebhookConfigurationException */ private function processWebhookConfiguration(array $webhookDefinition): string { if (isset($webhookDefinition['url'])) { return $webhookDefinition['url']; } + if (isset($webhookDefinition['route'])) { return $this->urlGenerator->generate($webhookDefinition['route'][0], $webhookDefinition['route'][1], UrlGeneratorInterface::ABSOLUTE_URL); } diff --git a/src/DependencyInjection/WebhookConfiguration/WebhookConfigurationRegistryInterface.php b/src/Webhook/WebhookConfigurationRegistryInterface.php similarity index 55% rename from src/DependencyInjection/WebhookConfiguration/WebhookConfigurationRegistryInterface.php rename to src/Webhook/WebhookConfigurationRegistryInterface.php index de030c64..ec67792e 100644 --- a/src/DependencyInjection/WebhookConfiguration/WebhookConfigurationRegistryInterface.php +++ b/src/Webhook/WebhookConfigurationRegistryInterface.php @@ -1,6 +1,8 @@ }} @@ -13,7 +15,13 @@ interface WebhookConfigurationRegistryInterface public function add(string $name, array $configuration): void; /** - * @return array{success: string, error: string} + * @return array{ + * success: string, + * error: string, + * extra_http_headers?: array + * } + * + * @throws WebhookConfigurationException if configuration not found */ public function get(string $name): array; } diff --git a/tests/Builder/AbstractBuilderTestCase.php b/tests/Builder/AbstractBuilderTestCase.php index f95665e3..da3e0d2c 100644 --- a/tests/Builder/AbstractBuilderTestCase.php +++ b/tests/Builder/AbstractBuilderTestCase.php @@ -5,9 +5,9 @@ use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use Sensiolabs\GotenbergBundle\Client\GotenbergClientInterface; -use Sensiolabs\GotenbergBundle\DependencyInjection\WebhookConfiguration\WebhookConfigurationRegistryInterface; use Sensiolabs\GotenbergBundle\Formatter\AssetBaseDirFormatter; use Sensiolabs\GotenbergBundle\Twig\GotenbergAssetExtension; +use Sensiolabs\GotenbergBundle\Webhook\WebhookConfigurationRegistryInterface; use Symfony\Component\Filesystem\Filesystem; use Symfony\Component\Mime\Part\DataPart; use Twig\Environment; diff --git a/tests/Builder/Pdf/AbstractPdfBuilderTest.php b/tests/Builder/Pdf/AbstractPdfBuilderTest.php index c567a8a4..d9a63641 100644 --- a/tests/Builder/Pdf/AbstractPdfBuilderTest.php +++ b/tests/Builder/Pdf/AbstractPdfBuilderTest.php @@ -11,10 +11,10 @@ use Sensiolabs\GotenbergBundle\Client\GotenbergClient; use Sensiolabs\GotenbergBundle\Client\GotenbergClientInterface; use Sensiolabs\GotenbergBundle\Client\GotenbergResponse; -use Sensiolabs\GotenbergBundle\DependencyInjection\WebhookConfiguration\WebhookConfigurationRegistryInterface; use Sensiolabs\GotenbergBundle\Formatter\AssetBaseDirFormatter; use Sensiolabs\GotenbergBundle\Processor\NullProcessor; use Sensiolabs\GotenbergBundle\Tests\Builder\AbstractBuilderTestCase; +use Sensiolabs\GotenbergBundle\Webhook\WebhookConfigurationRegistryInterface; use Symfony\Component\HttpClient\MockHttpClient; use Symfony\Component\HttpClient\Response\MockResponse; use Symfony\Component\HttpFoundation\HeaderUtils; diff --git a/tests/Builder/Screenshot/AbstractScreenshotBuilderTest.php b/tests/Builder/Screenshot/AbstractScreenshotBuilderTest.php index 051b1557..c47f2911 100644 --- a/tests/Builder/Screenshot/AbstractScreenshotBuilderTest.php +++ b/tests/Builder/Screenshot/AbstractScreenshotBuilderTest.php @@ -11,10 +11,10 @@ use Sensiolabs\GotenbergBundle\Client\GotenbergClient; use Sensiolabs\GotenbergBundle\Client\GotenbergClientInterface; use Sensiolabs\GotenbergBundle\Client\GotenbergResponse; -use Sensiolabs\GotenbergBundle\DependencyInjection\WebhookConfiguration\WebhookConfigurationRegistryInterface; use Sensiolabs\GotenbergBundle\Formatter\AssetBaseDirFormatter; use Sensiolabs\GotenbergBundle\Processor\NullProcessor; use Sensiolabs\GotenbergBundle\Tests\Builder\AbstractBuilderTestCase; +use Sensiolabs\GotenbergBundle\Webhook\WebhookConfigurationRegistryInterface; use Symfony\Component\HttpClient\MockHttpClient; use Symfony\Component\HttpClient\Response\MockResponse; use Symfony\Component\HttpFoundation\HeaderUtils; diff --git a/tests/DependencyInjection/SensiolabsGotenbergExtensionTest.php b/tests/DependencyInjection/SensiolabsGotenbergExtensionTest.php index 49149717..d9c95660 100644 --- a/tests/DependencyInjection/SensiolabsGotenbergExtensionTest.php +++ b/tests/DependencyInjection/SensiolabsGotenbergExtensionTest.php @@ -467,9 +467,9 @@ public function testBuilderWebhookConfiguredWithValidConfiguration(): void self::assertSame('add', $name); self::assertContains($arguments[0], ['foo', 'baz', '.sensiolabs_gotenberg.pdf_builder.markdown_webhook_config']); self::assertSame(match ($arguments[0]) { - 'foo' => ['success' => ['url' => 'https://sensiolabs.com/webhook'], 'error' => ['route' => ['simple_route', []]]], - 'baz' => ['success' => ['route' => ['array_route', ['param1', 'param2']]]], - '.sensiolabs_gotenberg.pdf_builder.markdown_webhook_config' => ['success' => ['url' => 'https://sensiolabs.com/webhook-on-the-fly']], + 'foo' => ['success' => ['url' => 'https://sensiolabs.com/webhook'], 'error' => ['route' => ['simple_route', []]], 'extra_http_headers' => []], + 'baz' => ['success' => ['route' => ['array_route', ['param1', 'param2']]], 'extra_http_headers' => []], + '.sensiolabs_gotenberg.pdf_builder.markdown_webhook_config' => ['success' => ['url' => 'https://sensiolabs.com/webhook-on-the-fly'], 'extra_http_headers' => []], default => self::fail('Unexpected webhook configuration'), }, $arguments[1]); } diff --git a/tests/DependencyInjection/WebhookConfigurationRegistryTest.php b/tests/DependencyInjection/WebhookConfigurationRegistryTest.php index 31edb976..38271e93 100644 --- a/tests/DependencyInjection/WebhookConfigurationRegistryTest.php +++ b/tests/DependencyInjection/WebhookConfigurationRegistryTest.php @@ -7,8 +7,8 @@ use PHPUnit\Framework\MockObject\Exception; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; -use Sensiolabs\GotenbergBundle\DependencyInjection\WebhookConfiguration\WebhookConfigurationRegistry; use Sensiolabs\GotenbergBundle\Exception\WebhookConfigurationException; +use Sensiolabs\GotenbergBundle\Webhook\WebhookConfigurationRegistry; use Symfony\Component\Routing\Generator\UrlGeneratorInterface; use Symfony\Component\Routing\RequestContext; diff --git a/tests/GotenbergPdfTest.php b/tests/GotenbergPdfTest.php index 76ef435e..0c7d56a5 100644 --- a/tests/GotenbergPdfTest.php +++ b/tests/GotenbergPdfTest.php @@ -16,12 +16,12 @@ use Sensiolabs\GotenbergBundle\DependencyInjection\CompilerPass\GotenbergPass; use Sensiolabs\GotenbergBundle\DependencyInjection\Configuration; use Sensiolabs\GotenbergBundle\DependencyInjection\SensiolabsGotenbergExtension; -use Sensiolabs\GotenbergBundle\DependencyInjection\WebhookConfiguration\WebhookConfigurationRegistry; use Sensiolabs\GotenbergBundle\Enumeration\Unit; use Sensiolabs\GotenbergBundle\Formatter\AssetBaseDirFormatter; use Sensiolabs\GotenbergBundle\GotenbergPdf; use Sensiolabs\GotenbergBundle\GotenbergPdfInterface; use Sensiolabs\GotenbergBundle\SensiolabsGotenbergBundle; +use Sensiolabs\GotenbergBundle\Webhook\WebhookConfigurationRegistry; use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase; use Symfony\Component\Filesystem\Filesystem; use Symfony\Component\Mime\Part\DataPart; diff --git a/tests/GotenbergScreenshotTest.php b/tests/GotenbergScreenshotTest.php index b27140db..82fcb68e 100644 --- a/tests/GotenbergScreenshotTest.php +++ b/tests/GotenbergScreenshotTest.php @@ -12,10 +12,10 @@ use Sensiolabs\GotenbergBundle\Client\GotenbergClient; use Sensiolabs\GotenbergBundle\Debug\Builder\TraceableScreenshotBuilder; use Sensiolabs\GotenbergBundle\Debug\TraceableGotenbergScreenshot; -use Sensiolabs\GotenbergBundle\DependencyInjection\WebhookConfiguration\WebhookConfigurationRegistry; use Sensiolabs\GotenbergBundle\Formatter\AssetBaseDirFormatter; use Sensiolabs\GotenbergBundle\GotenbergScreenshot; use Sensiolabs\GotenbergBundle\GotenbergScreenshotInterface; +use Sensiolabs\GotenbergBundle\Webhook\WebhookConfigurationRegistry; use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase; use Symfony\Component\Filesystem\Filesystem; use Symfony\Component\Mime\Part\DataPart; From 0c6cb61ac15a153b798f706d6eb865b6906b699b Mon Sep 17 00:00:00 2001 From: Adrien Roches Date: Thu, 24 Oct 2024 15:49:42 +0200 Subject: [PATCH 05/24] [UPDATE] Auto docs --- docs/pdf/builders_api/HtmlPdfBuilder.md | 12 ++++++++++++ docs/pdf/builders_api/LibreOfficePdfBuilder.md | 12 ++++++++++++ docs/pdf/builders_api/MarkdownPdfBuilder.md | 12 ++++++++++++ docs/pdf/builders_api/UrlPdfBuilder.md | 12 ++++++++++++ .../screenshot/builders_api/HtmlScreenshotBuilder.md | 12 ++++++++++++ .../builders_api/MarkdownScreenshotBuilder.md | 12 ++++++++++++ docs/screenshot/builders_api/UrlScreenshotBuilder.md | 12 ++++++++++++ 7 files changed, 84 insertions(+) diff --git a/docs/pdf/builders_api/HtmlPdfBuilder.md b/docs/pdf/builders_api/HtmlPdfBuilder.md index 2598b015..272a5c7d 100644 --- a/docs/pdf/builders_api/HtmlPdfBuilder.md +++ b/docs/pdf/builders_api/HtmlPdfBuilder.md @@ -127,6 +127,18 @@ Resets the metadata. * `addMetadata(string $key, string $value)`: The metadata to write. +* `generateAsync()`: + +* `setWebhookConfigurationRegistry(Sensiolabs\GotenbergBundle\Webhook\WebhookConfigurationRegistry $registry)`: + +* `webhookConfiguration(string $webhook)`: + +* `webhookUrls(string $successWebhook, ?string $errorWebhook)`: + +* `webhookExtraHeaders(array $extraHeaders)`: + +* `operationIdGenerator(Closure $operationIdGenerator)`: + * `fileName(string $fileName, string $headerDisposition)`: * `processor(Sensiolabs\GotenbergBundle\Processor\ProcessorInterface $processor)`: diff --git a/docs/pdf/builders_api/LibreOfficePdfBuilder.md b/docs/pdf/builders_api/LibreOfficePdfBuilder.md index 0c1eb061..f794b55e 100644 --- a/docs/pdf/builders_api/LibreOfficePdfBuilder.md +++ b/docs/pdf/builders_api/LibreOfficePdfBuilder.md @@ -82,6 +82,18 @@ Specify if the resolution of each image is reduced to the resolution specified b * `maxImageResolution(Sensiolabs\GotenbergBundle\Enumeration\ImageResolutionDPI $resolution)`: If the form field reduceImageResolution is set to true, tell if all images will be reduced to the given value in DPI. Possible values are: 75, 150, 300, 600 and 1200. +* `generateAsync()`: + +* `setWebhookConfigurationRegistry(Sensiolabs\GotenbergBundle\Webhook\WebhookConfigurationRegistry $registry)`: + +* `webhookConfiguration(string $webhook)`: + +* `webhookUrls(string $successWebhook, ?string $errorWebhook)`: + +* `webhookExtraHeaders(array $extraHeaders)`: + +* `operationIdGenerator(Closure $operationIdGenerator)`: + * `fileName(string $fileName, string $headerDisposition)`: * `processor(Sensiolabs\GotenbergBundle\Processor\ProcessorInterface $processor)`: diff --git a/docs/pdf/builders_api/MarkdownPdfBuilder.md b/docs/pdf/builders_api/MarkdownPdfBuilder.md index e47d72a4..5ed2e805 100644 --- a/docs/pdf/builders_api/MarkdownPdfBuilder.md +++ b/docs/pdf/builders_api/MarkdownPdfBuilder.md @@ -130,6 +130,18 @@ Resets the metadata. * `addMetadata(string $key, string $value)`: The metadata to write. +* `generateAsync()`: + +* `setWebhookConfigurationRegistry(Sensiolabs\GotenbergBundle\Webhook\WebhookConfigurationRegistry $registry)`: + +* `webhookConfiguration(string $webhook)`: + +* `webhookUrls(string $successWebhook, ?string $errorWebhook)`: + +* `webhookExtraHeaders(array $extraHeaders)`: + +* `operationIdGenerator(Closure $operationIdGenerator)`: + * `fileName(string $fileName, string $headerDisposition)`: * `processor(Sensiolabs\GotenbergBundle\Processor\ProcessorInterface $processor)`: diff --git a/docs/pdf/builders_api/UrlPdfBuilder.md b/docs/pdf/builders_api/UrlPdfBuilder.md index 60608be5..69684168 100644 --- a/docs/pdf/builders_api/UrlPdfBuilder.md +++ b/docs/pdf/builders_api/UrlPdfBuilder.md @@ -129,6 +129,18 @@ Resets the metadata. * `addMetadata(string $key, string $value)`: The metadata to write. +* `generateAsync()`: + +* `setWebhookConfigurationRegistry(Sensiolabs\GotenbergBundle\Webhook\WebhookConfigurationRegistry $registry)`: + +* `webhookConfiguration(string $webhook)`: + +* `webhookUrls(string $successWebhook, ?string $errorWebhook)`: + +* `webhookExtraHeaders(array $extraHeaders)`: + +* `operationIdGenerator(Closure $operationIdGenerator)`: + * `fileName(string $fileName, string $headerDisposition)`: * `processor(Sensiolabs\GotenbergBundle\Processor\ProcessorInterface $processor)`: diff --git a/docs/screenshot/builders_api/HtmlScreenshotBuilder.md b/docs/screenshot/builders_api/HtmlScreenshotBuilder.md index 75627e28..5c950e18 100644 --- a/docs/screenshot/builders_api/HtmlScreenshotBuilder.md +++ b/docs/screenshot/builders_api/HtmlScreenshotBuilder.md @@ -72,6 +72,18 @@ Adds additional files, like images, fonts, stylesheets, and so on (overrides any * `addAsset(string $path)`: Adds a file, like an image, font, stylesheet, and so on. +* `generateAsync()`: + +* `setWebhookConfigurationRegistry(Sensiolabs\GotenbergBundle\Webhook\WebhookConfigurationRegistry $registry)`: + +* `webhookConfiguration(string $webhook)`: + +* `webhookUrls(string $successWebhook, ?string $errorWebhook)`: + +* `webhookExtraHeaders(array $extraHeaders)`: + +* `operationIdGenerator(Closure $operationIdGenerator)`: + * `fileName(string $fileName, string $headerDisposition)`: * `processor(Sensiolabs\GotenbergBundle\Processor\ProcessorInterface $processor)`: diff --git a/docs/screenshot/builders_api/MarkdownScreenshotBuilder.md b/docs/screenshot/builders_api/MarkdownScreenshotBuilder.md index c7e0d8d4..d24cc871 100644 --- a/docs/screenshot/builders_api/MarkdownScreenshotBuilder.md +++ b/docs/screenshot/builders_api/MarkdownScreenshotBuilder.md @@ -75,6 +75,18 @@ Adds additional files, like images, fonts, stylesheets, and so on (overrides any * `addAsset(string $path)`: Adds a file, like an image, font, stylesheet, and so on. +* `generateAsync()`: + +* `setWebhookConfigurationRegistry(Sensiolabs\GotenbergBundle\Webhook\WebhookConfigurationRegistry $registry)`: + +* `webhookConfiguration(string $webhook)`: + +* `webhookUrls(string $successWebhook, ?string $errorWebhook)`: + +* `webhookExtraHeaders(array $extraHeaders)`: + +* `operationIdGenerator(Closure $operationIdGenerator)`: + * `fileName(string $fileName, string $headerDisposition)`: * `processor(Sensiolabs\GotenbergBundle\Processor\ProcessorInterface $processor)`: diff --git a/docs/screenshot/builders_api/UrlScreenshotBuilder.md b/docs/screenshot/builders_api/UrlScreenshotBuilder.md index 65496b31..8ad9c9c7 100644 --- a/docs/screenshot/builders_api/UrlScreenshotBuilder.md +++ b/docs/screenshot/builders_api/UrlScreenshotBuilder.md @@ -74,6 +74,18 @@ Adds additional files, like images, fonts, stylesheets, and so on (overrides any * `addAsset(string $path)`: Adds a file, like an image, font, stylesheet, and so on. +* `generateAsync()`: + +* `setWebhookConfigurationRegistry(Sensiolabs\GotenbergBundle\Webhook\WebhookConfigurationRegistry $registry)`: + +* `webhookConfiguration(string $webhook)`: + +* `webhookUrls(string $successWebhook, ?string $errorWebhook)`: + +* `webhookExtraHeaders(array $extraHeaders)`: + +* `operationIdGenerator(Closure $operationIdGenerator)`: + * `fileName(string $fileName, string $headerDisposition)`: * `processor(Sensiolabs\GotenbergBundle\Processor\ProcessorInterface $processor)`: From 9fb37d7abc797cc2d3a17cd3bfebcd42bf639404 Mon Sep 17 00:00:00 2001 From: Adrien Roches Date: Thu, 31 Oct 2024 14:48:16 +0100 Subject: [PATCH 06/24] [UPDATE] Remove custom id generator for the moment --- src/Builder/AsyncBuilderInterface.php | 2 +- src/Builder/AsyncBuilderTrait.php | 31 +------------------ src/Debug/Builder/TraceablePdfBuilder.php | 6 ++-- .../Builder/TraceableScreenshotBuilder.php | 6 ++-- 4 files changed, 6 insertions(+), 39 deletions(-) diff --git a/src/Builder/AsyncBuilderInterface.php b/src/Builder/AsyncBuilderInterface.php index ca5d8e25..52eee111 100644 --- a/src/Builder/AsyncBuilderInterface.php +++ b/src/Builder/AsyncBuilderInterface.php @@ -7,5 +7,5 @@ interface AsyncBuilderInterface /** * Generates a file asynchronously. */ - public function generateAsync(): string; + public function generateAsync(): void; } diff --git a/src/Builder/AsyncBuilderTrait.php b/src/Builder/AsyncBuilderTrait.php index 976f2f36..e9fbc1fc 100644 --- a/src/Builder/AsyncBuilderTrait.php +++ b/src/Builder/AsyncBuilderTrait.php @@ -18,22 +18,10 @@ trait AsyncBuilderTrait */ private array $webhookExtraHeaders = []; - /** - * @var (\Closure(): string) - */ - private \Closure $operationIdGenerator; - private WebhookConfigurationRegistryInterface $webhookConfigurationRegistry; - public function generateAsync(): string + public function generateAsync(): void { - $operationId = ($this->operationIdGenerator ?? self::defaultOperationIdGenerator(...))(); - $this->logger?->debug('Generating a file asynchronously with operation id {sensiolabs_gotenberg.operation_id} using {sensiolabs_gotenberg.builder} builder.', [ - 'sensiolabs_gotenberg.operation_id' => $operationId, - 'sensiolabs_gotenberg.builder' => $this::class, - ]); - - $this->webhookExtraHeaders['X-Gotenberg-Operation-Id'] = $operationId; $headers = [ 'Gotenberg-Webhook-Url' => $this->webhookUrl, 'Gotenberg-Webhook-Error-Url' => $this->errorWebhookUrl, @@ -44,8 +32,6 @@ public function generateAsync(): string $headers['Gotenberg-Output-Filename'] = $this->fileName; } $this->client->call($this->getEndpoint(), $this->getMultipartFormData(), $headers); - - return $operationId; } public function setWebhookConfigurationRegistry(WebhookConfigurationRegistry $registry): static @@ -85,19 +71,4 @@ public function webhookExtraHeaders(array $extraHeaders): static return $this; } - - /** - * @param (\Closure(): string) $operationIdGenerator - */ - public function operationIdGenerator(\Closure $operationIdGenerator): static - { - $this->operationIdGenerator = $operationIdGenerator; - - return $this; - } - - protected static function defaultOperationIdGenerator(): string - { - return 'gotenberg_'.bin2hex(random_bytes(16)).microtime(true); - } } diff --git a/src/Debug/Builder/TraceablePdfBuilder.php b/src/Debug/Builder/TraceablePdfBuilder.php index c92bca08..5a19090b 100644 --- a/src/Debug/Builder/TraceablePdfBuilder.php +++ b/src/Debug/Builder/TraceablePdfBuilder.php @@ -51,7 +51,7 @@ public function generate(): GotenbergFileResult return $response; } - public function generateAsync(): string + public function generateAsync(): void { if (!$this->inner instanceof AsyncBuilderInterface) { throw new \LogicException(\sprintf('The inner builder of %s must implement %s.', self::class, AsyncBuilderInterface::class)); @@ -61,7 +61,7 @@ public function generateAsync(): string ++self::$count; $swEvent = $this->stopwatch?->start($name, 'gotenberg.generate_pdf'); - $operationId = $this->inner->generateAsync(); + $this->inner->generateAsync(); $swEvent?->stop(); $this->pdfs[] = [ @@ -73,8 +73,6 @@ public function generateAsync(): string ]; ++$this->totalGenerated; - - return $operationId; } /** diff --git a/src/Debug/Builder/TraceableScreenshotBuilder.php b/src/Debug/Builder/TraceableScreenshotBuilder.php index 1e6964fb..ba2c99c4 100644 --- a/src/Debug/Builder/TraceableScreenshotBuilder.php +++ b/src/Debug/Builder/TraceableScreenshotBuilder.php @@ -52,7 +52,7 @@ public function generate(): GotenbergFileResult return $response; } - public function generateAsync(): string + public function generateAsync(): void { if (!$this->inner instanceof AsyncBuilderInterface) { throw new \LogicException(\sprintf('The inner builder of %s must implement %s.', self::class, AsyncBuilderInterface::class)); @@ -62,7 +62,7 @@ public function generateAsync(): string ++self::$count; $swEvent = $this->stopwatch?->start($name, 'gotenberg.generate_screenshot'); - $operationId = $this->inner->generateAsync(); + $this->inner->generateAsync(); $swEvent?->stop(); $this->screenshots[] = [ @@ -74,8 +74,6 @@ public function generateAsync(): string ]; ++$this->totalGenerated; - - return $operationId; } /** From ed70e51c0c6aa9ad210b3db8f2ae095f78135c07 Mon Sep 17 00:00:00 2001 From: Adrien Roches Date: Thu, 31 Oct 2024 15:34:21 +0100 Subject: [PATCH 07/24] [UPDATE] Remove strict types --- src/EventListener/ProcessBuilderOnControllerResponse.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/EventListener/ProcessBuilderOnControllerResponse.php b/src/EventListener/ProcessBuilderOnControllerResponse.php index c24d6c89..5de2dad0 100644 --- a/src/EventListener/ProcessBuilderOnControllerResponse.php +++ b/src/EventListener/ProcessBuilderOnControllerResponse.php @@ -1,7 +1,5 @@ Date: Thu, 31 Oct 2024 15:43:57 +0100 Subject: [PATCH 08/24] [UPDATE] Docs --- docs/pdf/builders_api/HtmlPdfBuilder.md | 2 -- docs/pdf/builders_api/LibreOfficePdfBuilder.md | 2 -- docs/pdf/builders_api/MarkdownPdfBuilder.md | 2 -- docs/pdf/builders_api/UrlPdfBuilder.md | 2 -- docs/screenshot/builders_api/HtmlScreenshotBuilder.md | 2 -- docs/screenshot/builders_api/MarkdownScreenshotBuilder.md | 2 -- docs/screenshot/builders_api/UrlScreenshotBuilder.md | 2 -- 7 files changed, 14 deletions(-) diff --git a/docs/pdf/builders_api/HtmlPdfBuilder.md b/docs/pdf/builders_api/HtmlPdfBuilder.md index 272a5c7d..5cb96024 100644 --- a/docs/pdf/builders_api/HtmlPdfBuilder.md +++ b/docs/pdf/builders_api/HtmlPdfBuilder.md @@ -137,8 +137,6 @@ The metadata to write. * `webhookExtraHeaders(array $extraHeaders)`: -* `operationIdGenerator(Closure $operationIdGenerator)`: - * `fileName(string $fileName, string $headerDisposition)`: * `processor(Sensiolabs\GotenbergBundle\Processor\ProcessorInterface $processor)`: diff --git a/docs/pdf/builders_api/LibreOfficePdfBuilder.md b/docs/pdf/builders_api/LibreOfficePdfBuilder.md index f794b55e..c6d85ba6 100644 --- a/docs/pdf/builders_api/LibreOfficePdfBuilder.md +++ b/docs/pdf/builders_api/LibreOfficePdfBuilder.md @@ -92,8 +92,6 @@ If the form field reduceImageResolution is set to true, tell if all images will * `webhookExtraHeaders(array $extraHeaders)`: -* `operationIdGenerator(Closure $operationIdGenerator)`: - * `fileName(string $fileName, string $headerDisposition)`: * `processor(Sensiolabs\GotenbergBundle\Processor\ProcessorInterface $processor)`: diff --git a/docs/pdf/builders_api/MarkdownPdfBuilder.md b/docs/pdf/builders_api/MarkdownPdfBuilder.md index 5ed2e805..42806f3a 100644 --- a/docs/pdf/builders_api/MarkdownPdfBuilder.md +++ b/docs/pdf/builders_api/MarkdownPdfBuilder.md @@ -140,8 +140,6 @@ The metadata to write. * `webhookExtraHeaders(array $extraHeaders)`: -* `operationIdGenerator(Closure $operationIdGenerator)`: - * `fileName(string $fileName, string $headerDisposition)`: * `processor(Sensiolabs\GotenbergBundle\Processor\ProcessorInterface $processor)`: diff --git a/docs/pdf/builders_api/UrlPdfBuilder.md b/docs/pdf/builders_api/UrlPdfBuilder.md index 69684168..95ad8d98 100644 --- a/docs/pdf/builders_api/UrlPdfBuilder.md +++ b/docs/pdf/builders_api/UrlPdfBuilder.md @@ -139,8 +139,6 @@ The metadata to write. * `webhookExtraHeaders(array $extraHeaders)`: -* `operationIdGenerator(Closure $operationIdGenerator)`: - * `fileName(string $fileName, string $headerDisposition)`: * `processor(Sensiolabs\GotenbergBundle\Processor\ProcessorInterface $processor)`: diff --git a/docs/screenshot/builders_api/HtmlScreenshotBuilder.md b/docs/screenshot/builders_api/HtmlScreenshotBuilder.md index 5c950e18..26fd3985 100644 --- a/docs/screenshot/builders_api/HtmlScreenshotBuilder.md +++ b/docs/screenshot/builders_api/HtmlScreenshotBuilder.md @@ -82,8 +82,6 @@ Adds a file, like an image, font, stylesheet, and so on. * `webhookExtraHeaders(array $extraHeaders)`: -* `operationIdGenerator(Closure $operationIdGenerator)`: - * `fileName(string $fileName, string $headerDisposition)`: * `processor(Sensiolabs\GotenbergBundle\Processor\ProcessorInterface $processor)`: diff --git a/docs/screenshot/builders_api/MarkdownScreenshotBuilder.md b/docs/screenshot/builders_api/MarkdownScreenshotBuilder.md index d24cc871..e0c9e89a 100644 --- a/docs/screenshot/builders_api/MarkdownScreenshotBuilder.md +++ b/docs/screenshot/builders_api/MarkdownScreenshotBuilder.md @@ -85,8 +85,6 @@ Adds a file, like an image, font, stylesheet, and so on. * `webhookExtraHeaders(array $extraHeaders)`: -* `operationIdGenerator(Closure $operationIdGenerator)`: - * `fileName(string $fileName, string $headerDisposition)`: * `processor(Sensiolabs\GotenbergBundle\Processor\ProcessorInterface $processor)`: diff --git a/docs/screenshot/builders_api/UrlScreenshotBuilder.md b/docs/screenshot/builders_api/UrlScreenshotBuilder.md index 8ad9c9c7..6a789f0d 100644 --- a/docs/screenshot/builders_api/UrlScreenshotBuilder.md +++ b/docs/screenshot/builders_api/UrlScreenshotBuilder.md @@ -84,8 +84,6 @@ Adds a file, like an image, font, stylesheet, and so on. * `webhookExtraHeaders(array $extraHeaders)`: -* `operationIdGenerator(Closure $operationIdGenerator)`: - * `fileName(string $fileName, string $headerDisposition)`: * `processor(Sensiolabs\GotenbergBundle\Processor\ProcessorInterface $processor)`: From a40ec717c759bd1018bd5bbf63b1dce62573310d Mon Sep 17 00:00:00 2001 From: Adrien Roches Date: Fri, 1 Nov 2024 12:48:16 +0100 Subject: [PATCH 09/24] [UPDATE] Doc & doc generation --- docs/builders_api.md | 16 +++++----- docs/generate.php | 26 ++++++++++++++-- docs/pdf/builders_api/ConvertPdfBuilder.md | 22 ++++++++++++++ docs/pdf/builders_api/HtmlPdfBuilder.md | 2 -- .../pdf/builders_api/LibreOfficePdfBuilder.md | 2 -- docs/pdf/builders_api/MarkdownPdfBuilder.md | 2 -- docs/pdf/builders_api/MergePdfBuilder.md | 30 +++++++++++++++++++ docs/pdf/builders_api/UrlPdfBuilder.md | 2 -- .../builders_api/HtmlScreenshotBuilder.md | 2 -- .../builders_api/MarkdownScreenshotBuilder.md | 2 -- .../builders_api/UrlScreenshotBuilder.md | 2 -- src/Builder/Pdf/MergePdfBuilder.php | 3 ++ 12 files changed, 87 insertions(+), 24 deletions(-) create mode 100644 docs/pdf/builders_api/ConvertPdfBuilder.md create mode 100644 docs/pdf/builders_api/MergePdfBuilder.md diff --git a/docs/builders_api.md b/docs/builders_api.md index 55a2b193..5842431b 100644 --- a/docs/builders_api.md +++ b/docs/builders_api.md @@ -2,14 +2,16 @@ ## Pdf -* [HtmlPdfBuilder](./pdf/builders_api/HtmlPdfBuilder.md) -* [UrlPdfBuilder](./pdf/builders_api/UrlPdfBuilder.md) -* [MarkdownPdfBuilder](./pdf/builders_api/MarkdownPdfBuilder.md) -* [LibreOfficePdfBuilder](./pdf/builders_api/LibreOfficePdfBuilder.md) +* [HtmlPdfBuilder](./Pdf/builders_api/HtmlPdfBuilder.md) +* [UrlPdfBuilder](./Pdf/builders_api/UrlPdfBuilder.md) +* [MarkdownPdfBuilder](./Pdf/builders_api/MarkdownPdfBuilder.md) +* [LibreOfficePdfBuilder](./Pdf/builders_api/LibreOfficePdfBuilder.md) +* [MergePdfBuilder](./Pdf/builders_api/MergePdfBuilder.md) +* [ConvertPdfBuilder](./Pdf/builders_api/ConvertPdfBuilder.md) ## Screenshot -* [HtmlScreenshotBuilder](./screenshot/builders_api/HtmlScreenshotBuilder.md) -* [UrlScreenshotBuilder](./screenshot/builders_api/UrlScreenshotBuilder.md) -* [MarkdownScreenshotBuilder](./screenshot/builders_api/MarkdownScreenshotBuilder.md) +* [HtmlScreenshotBuilder](./Screenshot/builders_api/HtmlScreenshotBuilder.md) +* [UrlScreenshotBuilder](./Screenshot/builders_api/UrlScreenshotBuilder.md) +* [MarkdownScreenshotBuilder](./Screenshot/builders_api/MarkdownScreenshotBuilder.md) diff --git a/docs/generate.php b/docs/generate.php index 7e11acfd..f35e02dd 100755 --- a/docs/generate.php +++ b/docs/generate.php @@ -1,9 +1,11 @@ #!/usr/bin/env php [ HtmlScreenshotBuilder::class, @@ -36,6 +40,7 @@ 'setLogger', 'setConfigurations', 'generate', + 'generateAsync', 'getMultipartFormData', ]; @@ -59,7 +64,7 @@ function parseDocComment(string $rawDocComment): string { $result = ''; - $lines = explode("\n", $rawDocComment); + $lines = explode("\n", trim($rawDocComment, "\n")); array_shift($lines); array_pop($lines); @@ -89,13 +94,28 @@ function parseBuilder(ReflectionClass $builder): string $builderName = $builder->getShortName(); $markdown .= "# {$builderName}\n\n"; + $builderComment = $builder->getDocComment(); + + if (false !== $builderComment) { + $markdown .= parseDocComment($builderComment) . "\n"; + } + + $methods = []; + foreach ($builder->getInterfaces() as $interface) { + foreach ($interface->getMethods() as $method) { + if (($method->getDocComment() ?: '') !== '') { + $methods[$method->getName()] = parseDocComment($method->getDocComment()); + } + } + } + foreach ($builder->getMethods(ReflectionMethod::IS_PUBLIC) as $method) { if (\in_array($method->getName(), EXCLUDED_METHODS, true) === true) { continue; } $methodSignature = parseMethodSignature($method); - $docComment = parseDocComment($method->getDocComment() ?: ''); + $docComment = parseDocComment($methods[$method->getShortName()] ?? $method->getDocComment() ?: ''); $markdown .= <<<"MARKDOWN" * `{$methodSignature}`: @@ -118,7 +138,7 @@ function saveFile(InputInterface $input, string $filename, string $contents): vo $summary = "# Builders API\n\n"; foreach (BUILDERS as $type => $builderClasses) { - $subDirectory = strtolower($type).'/builders_api'; + $subDirectory = "{$type}/builders_api"; $directory = __DIR__.'/'.$subDirectory; if (!@mkdir($directory, recursive: true) && !is_dir($directory)) { diff --git a/docs/pdf/builders_api/ConvertPdfBuilder.md b/docs/pdf/builders_api/ConvertPdfBuilder.md new file mode 100644 index 00000000..32f82dc7 --- /dev/null +++ b/docs/pdf/builders_api/ConvertPdfBuilder.md @@ -0,0 +1,22 @@ +# ConvertPdfBuilder + +* `pdfFormat(Sensiolabs\GotenbergBundle\Enumeration\PdfFormat $format)`: +Convert the resulting PDF into the given PDF/A format. + +* `pdfUniversalAccess(bool $bool)`: +Enable PDF for Universal Access for optimal accessibility. + +* `files(string $paths)`: + +* `setWebhookConfigurationRegistry(Sensiolabs\GotenbergBundle\Webhook\WebhookConfigurationRegistry $registry)`: + +* `webhookConfiguration(string $webhook)`: + +* `webhookUrls(string $successWebhook, ?string $errorWebhook)`: + +* `webhookExtraHeaders(array $extraHeaders)`: + +* `fileName(string $fileName, string $headerDisposition)`: + +* `processor(Sensiolabs\GotenbergBundle\Processor\ProcessorInterface $processor)`: + diff --git a/docs/pdf/builders_api/HtmlPdfBuilder.md b/docs/pdf/builders_api/HtmlPdfBuilder.md index 5cb96024..b105e62f 100644 --- a/docs/pdf/builders_api/HtmlPdfBuilder.md +++ b/docs/pdf/builders_api/HtmlPdfBuilder.md @@ -127,8 +127,6 @@ Resets the metadata. * `addMetadata(string $key, string $value)`: The metadata to write. -* `generateAsync()`: - * `setWebhookConfigurationRegistry(Sensiolabs\GotenbergBundle\Webhook\WebhookConfigurationRegistry $registry)`: * `webhookConfiguration(string $webhook)`: diff --git a/docs/pdf/builders_api/LibreOfficePdfBuilder.md b/docs/pdf/builders_api/LibreOfficePdfBuilder.md index c6d85ba6..b1fdfcf2 100644 --- a/docs/pdf/builders_api/LibreOfficePdfBuilder.md +++ b/docs/pdf/builders_api/LibreOfficePdfBuilder.md @@ -82,8 +82,6 @@ Specify if the resolution of each image is reduced to the resolution specified b * `maxImageResolution(Sensiolabs\GotenbergBundle\Enumeration\ImageResolutionDPI $resolution)`: If the form field reduceImageResolution is set to true, tell if all images will be reduced to the given value in DPI. Possible values are: 75, 150, 300, 600 and 1200. -* `generateAsync()`: - * `setWebhookConfigurationRegistry(Sensiolabs\GotenbergBundle\Webhook\WebhookConfigurationRegistry $registry)`: * `webhookConfiguration(string $webhook)`: diff --git a/docs/pdf/builders_api/MarkdownPdfBuilder.md b/docs/pdf/builders_api/MarkdownPdfBuilder.md index 42806f3a..b7f35302 100644 --- a/docs/pdf/builders_api/MarkdownPdfBuilder.md +++ b/docs/pdf/builders_api/MarkdownPdfBuilder.md @@ -130,8 +130,6 @@ Resets the metadata. * `addMetadata(string $key, string $value)`: The metadata to write. -* `generateAsync()`: - * `setWebhookConfigurationRegistry(Sensiolabs\GotenbergBundle\Webhook\WebhookConfigurationRegistry $registry)`: * `webhookConfiguration(string $webhook)`: diff --git a/docs/pdf/builders_api/MergePdfBuilder.md b/docs/pdf/builders_api/MergePdfBuilder.md new file mode 100644 index 00000000..7b4e076a --- /dev/null +++ b/docs/pdf/builders_api/MergePdfBuilder.md @@ -0,0 +1,30 @@ +# MergePdfBuilder + +Merge `n` pdf files into a single one. + +* `pdfFormat(Sensiolabs\GotenbergBundle\Enumeration\PdfFormat $format)`: +Convert the resulting PDF into the given PDF/A format. + +* `pdfUniversalAccess(bool $bool)`: +Enable PDF for Universal Access for optimal accessibility. + +* `files(string $paths)`: + +* `metadata(array $metadata)`: +Resets the metadata. + +* `addMetadata(string $key, string $value)`: +The metadata to write. + +* `setWebhookConfigurationRegistry(Sensiolabs\GotenbergBundle\Webhook\WebhookConfigurationRegistry $registry)`: + +* `webhookConfiguration(string $webhook)`: + +* `webhookUrls(string $successWebhook, ?string $errorWebhook)`: + +* `webhookExtraHeaders(array $extraHeaders)`: + +* `fileName(string $fileName, string $headerDisposition)`: + +* `processor(Sensiolabs\GotenbergBundle\Processor\ProcessorInterface $processor)`: + diff --git a/docs/pdf/builders_api/UrlPdfBuilder.md b/docs/pdf/builders_api/UrlPdfBuilder.md index 95ad8d98..7aa1d441 100644 --- a/docs/pdf/builders_api/UrlPdfBuilder.md +++ b/docs/pdf/builders_api/UrlPdfBuilder.md @@ -129,8 +129,6 @@ Resets the metadata. * `addMetadata(string $key, string $value)`: The metadata to write. -* `generateAsync()`: - * `setWebhookConfigurationRegistry(Sensiolabs\GotenbergBundle\Webhook\WebhookConfigurationRegistry $registry)`: * `webhookConfiguration(string $webhook)`: diff --git a/docs/screenshot/builders_api/HtmlScreenshotBuilder.md b/docs/screenshot/builders_api/HtmlScreenshotBuilder.md index 26fd3985..6a9f9e70 100644 --- a/docs/screenshot/builders_api/HtmlScreenshotBuilder.md +++ b/docs/screenshot/builders_api/HtmlScreenshotBuilder.md @@ -72,8 +72,6 @@ Adds additional files, like images, fonts, stylesheets, and so on (overrides any * `addAsset(string $path)`: Adds a file, like an image, font, stylesheet, and so on. -* `generateAsync()`: - * `setWebhookConfigurationRegistry(Sensiolabs\GotenbergBundle\Webhook\WebhookConfigurationRegistry $registry)`: * `webhookConfiguration(string $webhook)`: diff --git a/docs/screenshot/builders_api/MarkdownScreenshotBuilder.md b/docs/screenshot/builders_api/MarkdownScreenshotBuilder.md index e0c9e89a..e907a938 100644 --- a/docs/screenshot/builders_api/MarkdownScreenshotBuilder.md +++ b/docs/screenshot/builders_api/MarkdownScreenshotBuilder.md @@ -75,8 +75,6 @@ Adds additional files, like images, fonts, stylesheets, and so on (overrides any * `addAsset(string $path)`: Adds a file, like an image, font, stylesheet, and so on. -* `generateAsync()`: - * `setWebhookConfigurationRegistry(Sensiolabs\GotenbergBundle\Webhook\WebhookConfigurationRegistry $registry)`: * `webhookConfiguration(string $webhook)`: diff --git a/docs/screenshot/builders_api/UrlScreenshotBuilder.md b/docs/screenshot/builders_api/UrlScreenshotBuilder.md index 6a789f0d..16d4790f 100644 --- a/docs/screenshot/builders_api/UrlScreenshotBuilder.md +++ b/docs/screenshot/builders_api/UrlScreenshotBuilder.md @@ -74,8 +74,6 @@ Adds additional files, like images, fonts, stylesheets, and so on (overrides any * `addAsset(string $path)`: Adds a file, like an image, font, stylesheet, and so on. -* `generateAsync()`: - * `setWebhookConfigurationRegistry(Sensiolabs\GotenbergBundle\Webhook\WebhookConfigurationRegistry $registry)`: * `webhookConfiguration(string $webhook)`: diff --git a/src/Builder/Pdf/MergePdfBuilder.php b/src/Builder/Pdf/MergePdfBuilder.php index b59d892d..99800ef8 100644 --- a/src/Builder/Pdf/MergePdfBuilder.php +++ b/src/Builder/Pdf/MergePdfBuilder.php @@ -8,6 +8,9 @@ use Symfony\Component\Mime\Part\DataPart; use Symfony\Component\Mime\Part\File as DataPartFile; +/** + * Merge `n` pdf files into a single one. + */ final class MergePdfBuilder extends AbstractPdfBuilder { private const ENDPOINT = '/forms/pdfengines/merge'; From 967bfad63b84bc41ab10e4e1691d79b825b8dd53 Mon Sep 17 00:00:00 2001 From: Adrien Roches Date: Fri, 1 Nov 2024 13:03:40 +0100 Subject: [PATCH 10/24] [Fix] A few stuff --- config/builder_pdf.php | 6 +++--- config/builder_screenshot.php | 6 +++--- docs/generate.php | 4 ++-- src/Builder/Pdf/AbstractChromiumPdfBuilder.php | 2 +- src/Builder/Pdf/UrlPdfBuilder.php | 4 ++-- .../Screenshot/AbstractChromiumScreenshotBuilder.php | 2 +- src/Builder/Screenshot/AbstractScreenshotBuilder.php | 1 - src/Builder/Screenshot/UrlScreenshotBuilder.php | 4 ++-- tests/Builder/Pdf/AbstractChromiumPdfBuilderTest.php | 2 +- tests/Builder/Pdf/HtmlPdfBuilderTest.php | 2 +- tests/Builder/Pdf/MarkdownPdfBuilderTest.php | 2 +- tests/Builder/Pdf/UrlPdfBuilderTest.php | 9 ++++++++- .../Screenshot/AbstractChromiumScreenshotBuilderTest.php | 2 +- tests/Builder/Screenshot/HtmlScreenshotBuilderTest.php | 2 +- .../Builder/Screenshot/MarkdownScreenshotBuilderTest.php | 2 +- tests/Builder/Screenshot/UrlScreenshotBuilderTest.php | 2 +- 16 files changed, 29 insertions(+), 23 deletions(-) diff --git a/config/builder_pdf.php b/config/builder_pdf.php index 96919f1a..349c960d 100644 --- a/config/builder_pdf.php +++ b/config/builder_pdf.php @@ -21,8 +21,8 @@ ->args([ service('sensiolabs_gotenberg.client'), service('sensiolabs_gotenberg.asset.base_dir_formatter'), - service('request_stack'), service('.sensiolabs_gotenberg.webhook_configuration_registry'), + service('request_stack'), service('twig')->nullOnInvalid(), ]) ->call('setLogger', [service('logger')->nullOnInvalid()]) @@ -34,8 +34,8 @@ ->args([ service('sensiolabs_gotenberg.client'), service('sensiolabs_gotenberg.asset.base_dir_formatter'), - service('request_stack'), service('.sensiolabs_gotenberg.webhook_configuration_registry'), + service('request_stack'), service('twig')->nullOnInvalid(), service('router')->nullOnInvalid(), ]) @@ -49,8 +49,8 @@ ->args([ service('sensiolabs_gotenberg.client'), service('sensiolabs_gotenberg.asset.base_dir_formatter'), - service('request_stack'), service('.sensiolabs_gotenberg.webhook_configuration_registry'), + service('request_stack'), service('twig')->nullOnInvalid(), ]) ->call('setLogger', [service('logger')->nullOnInvalid()]) diff --git a/config/builder_screenshot.php b/config/builder_screenshot.php index 7f6e864b..7ecb4cb2 100644 --- a/config/builder_screenshot.php +++ b/config/builder_screenshot.php @@ -18,8 +18,8 @@ ->args([ service('sensiolabs_gotenberg.client'), service('sensiolabs_gotenberg.asset.base_dir_formatter'), - service('request_stack'), service('.sensiolabs_gotenberg.webhook_configuration_registry'), + service('request_stack'), service('twig')->nullOnInvalid(), ]) ->call('setLogger', [service('logger')->nullOnInvalid()]) @@ -31,8 +31,8 @@ ->args([ service('sensiolabs_gotenberg.client'), service('sensiolabs_gotenberg.asset.base_dir_formatter'), - service('request_stack'), service('.sensiolabs_gotenberg.webhook_configuration_registry'), + service('request_stack'), service('twig')->nullOnInvalid(), service('router')->nullOnInvalid(), ]) @@ -46,8 +46,8 @@ ->args([ service('sensiolabs_gotenberg.client'), service('sensiolabs_gotenberg.asset.base_dir_formatter'), - service('request_stack'), service('.sensiolabs_gotenberg.webhook_configuration_registry'), + service('request_stack'), service('twig')->nullOnInvalid(), ]) ->call('setLogger', [service('logger')->nullOnInvalid()]) diff --git a/docs/generate.php b/docs/generate.php index f35e02dd..0fabaedc 100755 --- a/docs/generate.php +++ b/docs/generate.php @@ -97,13 +97,13 @@ function parseBuilder(ReflectionClass $builder): string $builderComment = $builder->getDocComment(); if (false !== $builderComment) { - $markdown .= parseDocComment($builderComment) . "\n"; + $markdown .= parseDocComment($builderComment)."\n"; } $methods = []; foreach ($builder->getInterfaces() as $interface) { foreach ($interface->getMethods() as $method) { - if (($method->getDocComment() ?: '') !== '') { + if ('' !== ($method->getDocComment() ?: '')) { $methods[$method->getName()] = parseDocComment($method->getDocComment()); } } diff --git a/src/Builder/Pdf/AbstractChromiumPdfBuilder.php b/src/Builder/Pdf/AbstractChromiumPdfBuilder.php index 543f03c5..4cb8968b 100644 --- a/src/Builder/Pdf/AbstractChromiumPdfBuilder.php +++ b/src/Builder/Pdf/AbstractChromiumPdfBuilder.php @@ -28,8 +28,8 @@ abstract class AbstractChromiumPdfBuilder extends AbstractPdfBuilder public function __construct( GotenbergClientInterface $gotenbergClient, AssetBaseDirFormatter $asset, - private readonly RequestStack $requestStack, WebhookConfigurationRegistryInterface $webhookConfigurationRegistry, + private readonly RequestStack $requestStack, private readonly Environment|null $twig = null, ) { parent::__construct($gotenbergClient, $asset, $webhookConfigurationRegistry); diff --git a/src/Builder/Pdf/UrlPdfBuilder.php b/src/Builder/Pdf/UrlPdfBuilder.php index fd43d844..e72cc8e3 100644 --- a/src/Builder/Pdf/UrlPdfBuilder.php +++ b/src/Builder/Pdf/UrlPdfBuilder.php @@ -20,12 +20,12 @@ final class UrlPdfBuilder extends AbstractChromiumPdfBuilder public function __construct( GotenbergClientInterface $gotenbergClient, AssetBaseDirFormatter $asset, - RequestStack $requestStack, WebhookConfigurationRegistryInterface $webhookConfigurationRegistry, + RequestStack $requestStack, Environment|null $twig = null, private readonly UrlGeneratorInterface|null $urlGenerator = null, ) { - parent::__construct($gotenbergClient, $asset, $requestStack, $webhookConfigurationRegistry, $twig); + parent::__construct($gotenbergClient, $asset, $webhookConfigurationRegistry, $requestStack, $twig); $this->addNormalizer('route', $this->generateUrlFromRoute(...)); } diff --git a/src/Builder/Screenshot/AbstractChromiumScreenshotBuilder.php b/src/Builder/Screenshot/AbstractChromiumScreenshotBuilder.php index ca867bf9..82d592c4 100644 --- a/src/Builder/Screenshot/AbstractChromiumScreenshotBuilder.php +++ b/src/Builder/Screenshot/AbstractChromiumScreenshotBuilder.php @@ -25,8 +25,8 @@ abstract class AbstractChromiumScreenshotBuilder extends AbstractScreenshotBuild public function __construct( GotenbergClientInterface $gotenbergClient, AssetBaseDirFormatter $asset, - private readonly RequestStack $requestStack, WebhookConfigurationRegistryInterface $webhookConfigurationRegistry, + private readonly RequestStack $requestStack, private readonly Environment|null $twig = null, ) { parent::__construct($gotenbergClient, $asset, $webhookConfigurationRegistry); diff --git a/src/Builder/Screenshot/AbstractScreenshotBuilder.php b/src/Builder/Screenshot/AbstractScreenshotBuilder.php index 4eeb8c5a..0d68221a 100644 --- a/src/Builder/Screenshot/AbstractScreenshotBuilder.php +++ b/src/Builder/Screenshot/AbstractScreenshotBuilder.php @@ -9,7 +9,6 @@ use Sensiolabs\GotenbergBundle\Client\GotenbergClientInterface; use Sensiolabs\GotenbergBundle\Formatter\AssetBaseDirFormatter; use Sensiolabs\GotenbergBundle\Webhook\WebhookConfigurationRegistryInterface; -use Symfony\Component\Mime\Part\DataPart; abstract class AbstractScreenshotBuilder implements ScreenshotBuilderInterface, AsyncBuilderInterface { diff --git a/src/Builder/Screenshot/UrlScreenshotBuilder.php b/src/Builder/Screenshot/UrlScreenshotBuilder.php index a7dd3ca5..3442affa 100644 --- a/src/Builder/Screenshot/UrlScreenshotBuilder.php +++ b/src/Builder/Screenshot/UrlScreenshotBuilder.php @@ -20,12 +20,12 @@ final class UrlScreenshotBuilder extends AbstractChromiumScreenshotBuilder public function __construct( GotenbergClientInterface $gotenbergClient, AssetBaseDirFormatter $asset, - RequestStack $requestStack, WebhookConfigurationRegistryInterface $webhookConfigurationRegistry, + RequestStack $requestStack, Environment|null $twig = null, private readonly UrlGeneratorInterface|null $urlGenerator = null, ) { - parent::__construct($gotenbergClient, $asset, $requestStack, $webhookConfigurationRegistry, $twig); + parent::__construct($gotenbergClient, $asset, $webhookConfigurationRegistry, $requestStack, $twig); $this->addNormalizer('route', $this->generateUrlFromRoute(...)); } diff --git a/tests/Builder/Pdf/AbstractChromiumPdfBuilderTest.php b/tests/Builder/Pdf/AbstractChromiumPdfBuilderTest.php index 4f797821..5bcc7ffc 100644 --- a/tests/Builder/Pdf/AbstractChromiumPdfBuilderTest.php +++ b/tests/Builder/Pdf/AbstractChromiumPdfBuilderTest.php @@ -453,7 +453,7 @@ public function testThrowIfTwigTemplateIsInvalid(): void private function getChromiumPdfBuilder(bool $twig = true, RequestStack $requestStack = new RequestStack()): AbstractChromiumPdfBuilder { - return new class($this->gotenbergClient, self::$assetBaseDirFormatter, $requestStack, $this->webhookConfigurationRegistry, true === $twig ? self::$twig : null) extends AbstractChromiumPdfBuilder { + return new class($this->gotenbergClient, self::$assetBaseDirFormatter, $this->webhookConfigurationRegistry, $requestStack, true === $twig ? self::$twig : null) extends AbstractChromiumPdfBuilder { protected function getEndpoint(): string { return '/fake/endpoint'; diff --git a/tests/Builder/Pdf/HtmlPdfBuilderTest.php b/tests/Builder/Pdf/HtmlPdfBuilderTest.php index 042fe9d0..1366fd5b 100644 --- a/tests/Builder/Pdf/HtmlPdfBuilderTest.php +++ b/tests/Builder/Pdf/HtmlPdfBuilderTest.php @@ -111,7 +111,7 @@ public function testRequiredFormData(): void private function getHtmlPdfBuilder(bool $twig = true): HtmlPdfBuilder { - return (new HtmlPdfBuilder($this->gotenbergClient, self::$assetBaseDirFormatter, new RequestStack(), $this->webhookConfigurationRegistry, true === $twig ? self::$twig : null)) + return (new HtmlPdfBuilder($this->gotenbergClient, self::$assetBaseDirFormatter, $this->webhookConfigurationRegistry, new RequestStack(), true === $twig ? self::$twig : null)) ->processor(new NullProcessor()) ; } diff --git a/tests/Builder/Pdf/MarkdownPdfBuilderTest.php b/tests/Builder/Pdf/MarkdownPdfBuilderTest.php index da072963..668fddef 100644 --- a/tests/Builder/Pdf/MarkdownPdfBuilderTest.php +++ b/tests/Builder/Pdf/MarkdownPdfBuilderTest.php @@ -68,7 +68,7 @@ public function testRequiredMarkdownFile(): void private function getMarkdownPdfBuilder(bool $twig = true): MarkdownPdfBuilder { - return (new MarkdownPdfBuilder($this->gotenbergClient, self::$assetBaseDirFormatter, new RequestStack(), $this->webhookConfigurationRegistry, true === $twig ? self::$twig : null)) + return (new MarkdownPdfBuilder($this->gotenbergClient, self::$assetBaseDirFormatter, $this->webhookConfigurationRegistry, new RequestStack(), true === $twig ? self::$twig : null)) ->processor(new NullProcessor()) ; } diff --git a/tests/Builder/Pdf/UrlPdfBuilderTest.php b/tests/Builder/Pdf/UrlPdfBuilderTest.php index 370961c4..b4fa54ca 100644 --- a/tests/Builder/Pdf/UrlPdfBuilderTest.php +++ b/tests/Builder/Pdf/UrlPdfBuilderTest.php @@ -132,7 +132,14 @@ public function testRequiredEitherUrlOrRouteNotBoth(): void private function getUrlPdfBuilder(UrlGeneratorInterface|null $urlGenerator = null): UrlPdfBuilder { - return (new UrlPdfBuilder($this->gotenbergClient, self::$assetBaseDirFormatter, new RequestStack(), $this->webhookConfigurationRegistry, null, $urlGenerator)) + return (new UrlPdfBuilder( + $this->gotenbergClient, + self::$assetBaseDirFormatter, + $this->webhookConfigurationRegistry, + new RequestStack(), + null, + $urlGenerator) + ) ->processor(new NullProcessor()) ; } diff --git a/tests/Builder/Screenshot/AbstractChromiumScreenshotBuilderTest.php b/tests/Builder/Screenshot/AbstractChromiumScreenshotBuilderTest.php index 5daa2327..a9a1bf61 100644 --- a/tests/Builder/Screenshot/AbstractChromiumScreenshotBuilderTest.php +++ b/tests/Builder/Screenshot/AbstractChromiumScreenshotBuilderTest.php @@ -85,7 +85,7 @@ public function testConfigurationIsCorrectlySet(string $key, mixed $value, array private function getChromiumScreenshotBuilder(bool $twig = true): AbstractChromiumScreenshotBuilder { - return new class($this->gotenbergClient, self::$assetBaseDirFormatter, new RequestStack(), $this->webhookConfigurationRegistry, true === $twig ? self::$twig : null) extends AbstractChromiumScreenshotBuilder { + return new class($this->gotenbergClient, self::$assetBaseDirFormatter, $this->webhookConfigurationRegistry, new RequestStack(), true === $twig ? self::$twig : null) extends AbstractChromiumScreenshotBuilder { protected function getEndpoint(): string { return '/fake/endpoint'; diff --git a/tests/Builder/Screenshot/HtmlScreenshotBuilderTest.php b/tests/Builder/Screenshot/HtmlScreenshotBuilderTest.php index 9d09d6f2..63f59909 100644 --- a/tests/Builder/Screenshot/HtmlScreenshotBuilderTest.php +++ b/tests/Builder/Screenshot/HtmlScreenshotBuilderTest.php @@ -111,7 +111,7 @@ public function testRequiredFormData(): void private function getHtmlScreenshotBuilder(bool $twig = true): HtmlScreenshotBuilder { - return (new HtmlScreenshotBuilder($this->gotenbergClient, self::$assetBaseDirFormatter, new RequestStack(), $this->webhookConfigurationRegistry, true === $twig ? self::$twig : null)) + return (new HtmlScreenshotBuilder($this->gotenbergClient, self::$assetBaseDirFormatter, $this->webhookConfigurationRegistry, new RequestStack(), true === $twig ? self::$twig : null)) ->processor(new NullProcessor()) ; } diff --git a/tests/Builder/Screenshot/MarkdownScreenshotBuilderTest.php b/tests/Builder/Screenshot/MarkdownScreenshotBuilderTest.php index e63a0eab..7d7edaa8 100644 --- a/tests/Builder/Screenshot/MarkdownScreenshotBuilderTest.php +++ b/tests/Builder/Screenshot/MarkdownScreenshotBuilderTest.php @@ -96,7 +96,7 @@ public function testRequiredMarkdownFile(): void private function getMarkdownScreenshotBuilder(bool $twig = true): MarkdownScreenshotBuilder { - return (new MarkdownScreenshotBuilder($this->gotenbergClient, self::$assetBaseDirFormatter, new RequestStack(), $this->webhookConfigurationRegistry, true === $twig ? self::$twig : null)) + return (new MarkdownScreenshotBuilder($this->gotenbergClient, self::$assetBaseDirFormatter, $this->webhookConfigurationRegistry, new RequestStack(), true === $twig ? self::$twig : null)) ->processor(new NullProcessor()) ; } diff --git a/tests/Builder/Screenshot/UrlScreenshotBuilderTest.php b/tests/Builder/Screenshot/UrlScreenshotBuilderTest.php index 3d097f41..0f70d257 100644 --- a/tests/Builder/Screenshot/UrlScreenshotBuilderTest.php +++ b/tests/Builder/Screenshot/UrlScreenshotBuilderTest.php @@ -77,8 +77,8 @@ private function getUrlScreenshotBuilder(bool $twig = true): UrlScreenshotBuilde return (new UrlScreenshotBuilder( $this->gotenbergClient, self::$assetBaseDirFormatter, - new RequestStack(), $this->webhookConfigurationRegistry, + new RequestStack(), true === $twig ? self::$twig : null, $this->router, )) From 823faba3b7d5e701b9ede7332283a99e9b8e12fd Mon Sep 17 00:00:00 2001 From: Adrien Roches Date: Fri, 1 Nov 2024 13:29:34 +0100 Subject: [PATCH 11/24] [UPDATE] A few stuff --- config/builder_pdf.php | 12 ++++----- config/builder_screenshot.php | 6 ++--- config/services.php | 4 +-- docs/pdf/builders_api/ConvertPdfBuilder.md | 5 ++-- docs/pdf/builders_api/HtmlPdfBuilder.md | 5 ++-- .../pdf/builders_api/LibreOfficePdfBuilder.md | 5 ++-- docs/pdf/builders_api/MarkdownPdfBuilder.md | 5 ++-- docs/pdf/builders_api/MergePdfBuilder.md | 5 ++-- docs/pdf/builders_api/UrlPdfBuilder.md | 5 ++-- .../builders_api/HtmlScreenshotBuilder.md | 5 ++-- .../builders_api/MarkdownScreenshotBuilder.md | 5 ++-- .../builders_api/UrlScreenshotBuilder.md | 5 ++-- src/Builder/AsyncBuilderTrait.php | 25 ++++++++++++------- .../SensiolabsGotenbergExtension.php | 4 +-- .../SensiolabsGotenbergExtensionTest.php | 4 +-- 15 files changed, 58 insertions(+), 42 deletions(-) diff --git a/config/builder_pdf.php b/config/builder_pdf.php index 349c960d..74d83e9a 100644 --- a/config/builder_pdf.php +++ b/config/builder_pdf.php @@ -21,7 +21,7 @@ ->args([ service('sensiolabs_gotenberg.client'), service('sensiolabs_gotenberg.asset.base_dir_formatter'), - service('.sensiolabs_gotenberg.webhook_configuration_registry'), + service('sensiolabs_gotenberg.webhook_configuration_registry'), service('request_stack'), service('twig')->nullOnInvalid(), ]) @@ -34,7 +34,7 @@ ->args([ service('sensiolabs_gotenberg.client'), service('sensiolabs_gotenberg.asset.base_dir_formatter'), - service('.sensiolabs_gotenberg.webhook_configuration_registry'), + service('sensiolabs_gotenberg.webhook_configuration_registry'), service('request_stack'), service('twig')->nullOnInvalid(), service('router')->nullOnInvalid(), @@ -49,7 +49,7 @@ ->args([ service('sensiolabs_gotenberg.client'), service('sensiolabs_gotenberg.asset.base_dir_formatter'), - service('.sensiolabs_gotenberg.webhook_configuration_registry'), + service('sensiolabs_gotenberg.webhook_configuration_registry'), service('request_stack'), service('twig')->nullOnInvalid(), ]) @@ -62,7 +62,7 @@ ->args([ service('sensiolabs_gotenberg.client'), service('sensiolabs_gotenberg.asset.base_dir_formatter'), - service('.sensiolabs_gotenberg.webhook_configuration_registry'), + service('sensiolabs_gotenberg.webhook_configuration_registry'), ]) ->call('setLogger', [service('logger')->nullOnInvalid()]) ->tag('sensiolabs_gotenberg.pdf_builder') @@ -73,7 +73,7 @@ ->args([ service('sensiolabs_gotenberg.client'), service('sensiolabs_gotenberg.asset.base_dir_formatter'), - service('.sensiolabs_gotenberg.webhook_configuration_registry'), + service('sensiolabs_gotenberg.webhook_configuration_registry'), ]) ->call('setLogger', [service('logger')->nullOnInvalid()]) ->tag('sensiolabs_gotenberg.pdf_builder') @@ -84,7 +84,7 @@ ->args([ service('sensiolabs_gotenberg.client'), service('sensiolabs_gotenberg.asset.base_dir_formatter'), - service('.sensiolabs_gotenberg.webhook_configuration_registry'), + service('sensiolabs_gotenberg.webhook_configuration_registry'), ]) ->call('setLogger', [service('logger')->nullOnInvalid()]) ->tag('sensiolabs_gotenberg.pdf_builder') diff --git a/config/builder_screenshot.php b/config/builder_screenshot.php index 7ecb4cb2..bd782808 100644 --- a/config/builder_screenshot.php +++ b/config/builder_screenshot.php @@ -18,7 +18,7 @@ ->args([ service('sensiolabs_gotenberg.client'), service('sensiolabs_gotenberg.asset.base_dir_formatter'), - service('.sensiolabs_gotenberg.webhook_configuration_registry'), + service('sensiolabs_gotenberg.webhook_configuration_registry'), service('request_stack'), service('twig')->nullOnInvalid(), ]) @@ -31,7 +31,7 @@ ->args([ service('sensiolabs_gotenberg.client'), service('sensiolabs_gotenberg.asset.base_dir_formatter'), - service('.sensiolabs_gotenberg.webhook_configuration_registry'), + service('sensiolabs_gotenberg.webhook_configuration_registry'), service('request_stack'), service('twig')->nullOnInvalid(), service('router')->nullOnInvalid(), @@ -46,7 +46,7 @@ ->args([ service('sensiolabs_gotenberg.client'), service('sensiolabs_gotenberg.asset.base_dir_formatter'), - service('.sensiolabs_gotenberg.webhook_configuration_registry'), + service('sensiolabs_gotenberg.webhook_configuration_registry'), service('request_stack'), service('twig')->nullOnInvalid(), ]) diff --git a/config/services.php b/config/services.php index f82d71fd..382478b6 100644 --- a/config/services.php +++ b/config/services.php @@ -71,12 +71,12 @@ ->tag('kernel.event_listener', ['method' => 'streamBuilder', 'event' => 'kernel.view']) ; - $services->set('.sensiolabs_gotenberg.webhook_configuration_registry', WebhookConfigurationRegistry::class) + $services->set('sensiolabs_gotenberg.webhook_configuration_registry', WebhookConfigurationRegistry::class) ->args([ service('router'), service('.sensiolabs_gotenberg.request_context')->nullOnInvalid(), ]) ->tag('sensiolabs_gotenberg.webhook_configuration_registry') - ->alias(WebhookConfigurationRegistryInterface::class, '.sensiolabs_gotenberg.webhook_configuration_registry') + ->alias(WebhookConfigurationRegistryInterface::class, 'sensiolabs_gotenberg.webhook_configuration_registry') ; }; diff --git a/docs/pdf/builders_api/ConvertPdfBuilder.md b/docs/pdf/builders_api/ConvertPdfBuilder.md index 8a6572b4..a774ff28 100644 --- a/docs/pdf/builders_api/ConvertPdfBuilder.md +++ b/docs/pdf/builders_api/ConvertPdfBuilder.md @@ -10,13 +10,14 @@ Enable PDF for Universal Access for optimal accessibility. * `downloadFrom(array $downloadFrom)`: -* `setWebhookConfigurationRegistry(Sensiolabs\GotenbergBundle\Webhook\WebhookConfigurationRegistry $registry)`: - * `webhookConfiguration(string $webhook)`: +Providing an existing $webhook from the configuration file, it will correctly set both success and error webhook URLs as well as extra_http_headers if defined. * `webhookUrls(string $successWebhook, ?string $errorWebhook)`: +Allows to set both $successWebhook and $errorWebhook URLs. If $errorWebhook is not provided, it will fallback to $successWebhook one. * `webhookExtraHeaders(array $extraHeaders)`: +Extra headers that will be provided to the webhook endpoint. May it either be Success or Error. * `fileName(string $fileName, string $headerDisposition)`: diff --git a/docs/pdf/builders_api/HtmlPdfBuilder.md b/docs/pdf/builders_api/HtmlPdfBuilder.md index 62efb5b6..9776a50b 100644 --- a/docs/pdf/builders_api/HtmlPdfBuilder.md +++ b/docs/pdf/builders_api/HtmlPdfBuilder.md @@ -129,13 +129,14 @@ The metadata to write. * `downloadFrom(array $downloadFrom)`: -* `setWebhookConfigurationRegistry(Sensiolabs\GotenbergBundle\Webhook\WebhookConfigurationRegistry $registry)`: - * `webhookConfiguration(string $webhook)`: +Providing an existing $webhook from the configuration file, it will correctly set both success and error webhook URLs as well as extra_http_headers if defined. * `webhookUrls(string $successWebhook, ?string $errorWebhook)`: +Allows to set both $successWebhook and $errorWebhook URLs. If $errorWebhook is not provided, it will fallback to $successWebhook one. * `webhookExtraHeaders(array $extraHeaders)`: +Extra headers that will be provided to the webhook endpoint. May it either be Success or Error. * `fileName(string $fileName, string $headerDisposition)`: diff --git a/docs/pdf/builders_api/LibreOfficePdfBuilder.md b/docs/pdf/builders_api/LibreOfficePdfBuilder.md index e2f4878f..c8a6fc0c 100644 --- a/docs/pdf/builders_api/LibreOfficePdfBuilder.md +++ b/docs/pdf/builders_api/LibreOfficePdfBuilder.md @@ -87,13 +87,14 @@ If the form field reduceImageResolution is set to true, tell if all images will * `downloadFrom(array $downloadFrom)`: -* `setWebhookConfigurationRegistry(Sensiolabs\GotenbergBundle\Webhook\WebhookConfigurationRegistry $registry)`: - * `webhookConfiguration(string $webhook)`: +Providing an existing $webhook from the configuration file, it will correctly set both success and error webhook URLs as well as extra_http_headers if defined. * `webhookUrls(string $successWebhook, ?string $errorWebhook)`: +Allows to set both $successWebhook and $errorWebhook URLs. If $errorWebhook is not provided, it will fallback to $successWebhook one. * `webhookExtraHeaders(array $extraHeaders)`: +Extra headers that will be provided to the webhook endpoint. May it either be Success or Error. * `fileName(string $fileName, string $headerDisposition)`: diff --git a/docs/pdf/builders_api/MarkdownPdfBuilder.md b/docs/pdf/builders_api/MarkdownPdfBuilder.md index e359da71..978e8b2e 100644 --- a/docs/pdf/builders_api/MarkdownPdfBuilder.md +++ b/docs/pdf/builders_api/MarkdownPdfBuilder.md @@ -132,13 +132,14 @@ The metadata to write. * `downloadFrom(array $downloadFrom)`: -* `setWebhookConfigurationRegistry(Sensiolabs\GotenbergBundle\Webhook\WebhookConfigurationRegistry $registry)`: - * `webhookConfiguration(string $webhook)`: +Providing an existing $webhook from the configuration file, it will correctly set both success and error webhook URLs as well as extra_http_headers if defined. * `webhookUrls(string $successWebhook, ?string $errorWebhook)`: +Allows to set both $successWebhook and $errorWebhook URLs. If $errorWebhook is not provided, it will fallback to $successWebhook one. * `webhookExtraHeaders(array $extraHeaders)`: +Extra headers that will be provided to the webhook endpoint. May it either be Success or Error. * `fileName(string $fileName, string $headerDisposition)`: diff --git a/docs/pdf/builders_api/MergePdfBuilder.md b/docs/pdf/builders_api/MergePdfBuilder.md index aa3fcd6c..e3f2b42b 100644 --- a/docs/pdf/builders_api/MergePdfBuilder.md +++ b/docs/pdf/builders_api/MergePdfBuilder.md @@ -18,13 +18,14 @@ The metadata to write. * `downloadFrom(array $downloadFrom)`: -* `setWebhookConfigurationRegistry(Sensiolabs\GotenbergBundle\Webhook\WebhookConfigurationRegistry $registry)`: - * `webhookConfiguration(string $webhook)`: +Providing an existing $webhook from the configuration file, it will correctly set both success and error webhook URLs as well as extra_http_headers if defined. * `webhookUrls(string $successWebhook, ?string $errorWebhook)`: +Allows to set both $successWebhook and $errorWebhook URLs. If $errorWebhook is not provided, it will fallback to $successWebhook one. * `webhookExtraHeaders(array $extraHeaders)`: +Extra headers that will be provided to the webhook endpoint. May it either be Success or Error. * `fileName(string $fileName, string $headerDisposition)`: diff --git a/docs/pdf/builders_api/UrlPdfBuilder.md b/docs/pdf/builders_api/UrlPdfBuilder.md index 57db2e89..ac10a30d 100644 --- a/docs/pdf/builders_api/UrlPdfBuilder.md +++ b/docs/pdf/builders_api/UrlPdfBuilder.md @@ -131,13 +131,14 @@ The metadata to write. * `downloadFrom(array $downloadFrom)`: -* `setWebhookConfigurationRegistry(Sensiolabs\GotenbergBundle\Webhook\WebhookConfigurationRegistry $registry)`: - * `webhookConfiguration(string $webhook)`: +Providing an existing $webhook from the configuration file, it will correctly set both success and error webhook URLs as well as extra_http_headers if defined. * `webhookUrls(string $successWebhook, ?string $errorWebhook)`: +Allows to set both $successWebhook and $errorWebhook URLs. If $errorWebhook is not provided, it will fallback to $successWebhook one. * `webhookExtraHeaders(array $extraHeaders)`: +Extra headers that will be provided to the webhook endpoint. May it either be Success or Error. * `fileName(string $fileName, string $headerDisposition)`: diff --git a/docs/screenshot/builders_api/HtmlScreenshotBuilder.md b/docs/screenshot/builders_api/HtmlScreenshotBuilder.md index 3ec7c7aa..d760191a 100644 --- a/docs/screenshot/builders_api/HtmlScreenshotBuilder.md +++ b/docs/screenshot/builders_api/HtmlScreenshotBuilder.md @@ -74,13 +74,14 @@ Adds a file, like an image, font, stylesheet, and so on. * `downloadFrom(array $downloadFrom)`: -* `setWebhookConfigurationRegistry(Sensiolabs\GotenbergBundle\Webhook\WebhookConfigurationRegistry $registry)`: - * `webhookConfiguration(string $webhook)`: +Providing an existing $webhook from the configuration file, it will correctly set both success and error webhook URLs as well as extra_http_headers if defined. * `webhookUrls(string $successWebhook, ?string $errorWebhook)`: +Allows to set both $successWebhook and $errorWebhook URLs. If $errorWebhook is not provided, it will fallback to $successWebhook one. * `webhookExtraHeaders(array $extraHeaders)`: +Extra headers that will be provided to the webhook endpoint. May it either be Success or Error. * `fileName(string $fileName, string $headerDisposition)`: diff --git a/docs/screenshot/builders_api/MarkdownScreenshotBuilder.md b/docs/screenshot/builders_api/MarkdownScreenshotBuilder.md index 9bd27eb4..c83e0abe 100644 --- a/docs/screenshot/builders_api/MarkdownScreenshotBuilder.md +++ b/docs/screenshot/builders_api/MarkdownScreenshotBuilder.md @@ -77,13 +77,14 @@ Adds a file, like an image, font, stylesheet, and so on. * `downloadFrom(array $downloadFrom)`: -* `setWebhookConfigurationRegistry(Sensiolabs\GotenbergBundle\Webhook\WebhookConfigurationRegistry $registry)`: - * `webhookConfiguration(string $webhook)`: +Providing an existing $webhook from the configuration file, it will correctly set both success and error webhook URLs as well as extra_http_headers if defined. * `webhookUrls(string $successWebhook, ?string $errorWebhook)`: +Allows to set both $successWebhook and $errorWebhook URLs. If $errorWebhook is not provided, it will fallback to $successWebhook one. * `webhookExtraHeaders(array $extraHeaders)`: +Extra headers that will be provided to the webhook endpoint. May it either be Success or Error. * `fileName(string $fileName, string $headerDisposition)`: diff --git a/docs/screenshot/builders_api/UrlScreenshotBuilder.md b/docs/screenshot/builders_api/UrlScreenshotBuilder.md index ecbda24d..c9f244d5 100644 --- a/docs/screenshot/builders_api/UrlScreenshotBuilder.md +++ b/docs/screenshot/builders_api/UrlScreenshotBuilder.md @@ -76,13 +76,14 @@ Adds a file, like an image, font, stylesheet, and so on. * `downloadFrom(array $downloadFrom)`: -* `setWebhookConfigurationRegistry(Sensiolabs\GotenbergBundle\Webhook\WebhookConfigurationRegistry $registry)`: - * `webhookConfiguration(string $webhook)`: +Providing an existing $webhook from the configuration file, it will correctly set both success and error webhook URLs as well as extra_http_headers if defined. * `webhookUrls(string $successWebhook, ?string $errorWebhook)`: +Allows to set both $successWebhook and $errorWebhook URLs. If $errorWebhook is not provided, it will fallback to $successWebhook one. * `webhookExtraHeaders(array $extraHeaders)`: +Extra headers that will be provided to the webhook endpoint. May it either be Success or Error. * `fileName(string $fileName, string $headerDisposition)`: diff --git a/src/Builder/AsyncBuilderTrait.php b/src/Builder/AsyncBuilderTrait.php index e9fbc1fc..0889ea96 100644 --- a/src/Builder/AsyncBuilderTrait.php +++ b/src/Builder/AsyncBuilderTrait.php @@ -2,7 +2,7 @@ namespace Sensiolabs\GotenbergBundle\Builder; -use Sensiolabs\GotenbergBundle\Webhook\WebhookConfigurationRegistry; +use Sensiolabs\GotenbergBundle\Exception\MissingRequiredFieldException; use Sensiolabs\GotenbergBundle\Webhook\WebhookConfigurationRegistryInterface; trait AsyncBuilderTrait @@ -22,9 +22,15 @@ trait AsyncBuilderTrait public function generateAsync(): void { + if (!isset($this->webhookUrl)) { + throw new MissingRequiredFieldException('->webhookUrls() was never called.'); + } + + $errorWebhookUrl = $this->errorWebhookUrl ?? $this->webhookUrl; + $headers = [ 'Gotenberg-Webhook-Url' => $this->webhookUrl, - 'Gotenberg-Webhook-Error-Url' => $this->errorWebhookUrl, + 'Gotenberg-Webhook-Error-Url' => $errorWebhookUrl, 'Gotenberg-Webhook-Extra-Http-Headers' => json_encode($this->webhookExtraHeaders, \JSON_THROW_ON_ERROR), ]; if (null !== $this->fileName) { @@ -34,13 +40,9 @@ public function generateAsync(): void $this->client->call($this->getEndpoint(), $this->getMultipartFormData(), $headers); } - public function setWebhookConfigurationRegistry(WebhookConfigurationRegistry $registry): static - { - $this->webhookConfigurationRegistry = $registry; - - return $this; - } - + /** + * Providing an existing $webhook from the configuration file, it will correctly set both success and error webhook URLs as well as extra_http_headers if defined. + */ public function webhookConfiguration(string $webhook): static { $webhookConfiguration = $this->webhookConfigurationRegistry->get($webhook); @@ -54,6 +56,9 @@ public function webhookConfiguration(string $webhook): static return $result; } + /** + * Allows to set both $successWebhook and $errorWebhook URLs. If $errorWebhook is not provided, it will fallback to $successWebhook one. + */ public function webhookUrls(string $successWebhook, string|null $errorWebhook = null): static { $this->webhookUrl = $successWebhook; @@ -63,6 +68,8 @@ public function webhookUrls(string $successWebhook, string|null $errorWebhook = } /** + * Extra headers that will be provided to the webhook endpoint. May it either be Success or Error. + * * @param array $extraHeaders */ public function webhookExtraHeaders(array $extraHeaders): static diff --git a/src/DependencyInjection/SensiolabsGotenbergExtension.php b/src/DependencyInjection/SensiolabsGotenbergExtension.php index 36062d0a..3647ac06 100644 --- a/src/DependencyInjection/SensiolabsGotenbergExtension.php +++ b/src/DependencyInjection/SensiolabsGotenbergExtension.php @@ -69,7 +69,7 @@ public function load(array $configs, ContainerBuilder $container): void } foreach ($config['webhook'] as $name => $configuration) { - $container->getDefinition('.sensiolabs_gotenberg.webhook_configuration_registry') + $container->getDefinition('sensiolabs_gotenberg.webhook_configuration_registry') ->addMethodCall('add', [$name, $configuration]); } @@ -130,7 +130,7 @@ private function processDefaultOptions(string $serviceId, ContainerBuilder $cont $name = $webhookConfig['config_name']; } else { $name = $serviceId.'_webhook_config'; - $container->getDefinition('.sensiolabs_gotenberg.webhook_configuration_registry') + $container->getDefinition('sensiolabs_gotenberg.webhook_configuration_registry') ->addMethodCall('add', [$name, $webhookConfig]); } $definition->addMethodCall('webhookConfiguration', [$name], true); diff --git a/tests/DependencyInjection/SensiolabsGotenbergExtensionTest.php b/tests/DependencyInjection/SensiolabsGotenbergExtensionTest.php index bb95dc8f..de914c0b 100644 --- a/tests/DependencyInjection/SensiolabsGotenbergExtensionTest.php +++ b/tests/DependencyInjection/SensiolabsGotenbergExtensionTest.php @@ -415,7 +415,7 @@ public function testBuilderWebhookConfiguredWithDefaultConfiguration(): void $containerBuilder = $this->getContainerBuilder(); $extension->load([['http_client' => 'http_client']], $containerBuilder); - self::assertEmpty($containerBuilder->getDefinition('.sensiolabs_gotenberg.webhook_configuration_registry')->getMethodCalls()); + self::assertEmpty($containerBuilder->getDefinition('sensiolabs_gotenberg.webhook_configuration_registry')->getMethodCalls()); $buildersIds = [ '.sensiolabs_gotenberg.pdf_builder.html', @@ -480,7 +480,7 @@ public function testBuilderWebhookConfiguredWithValidConfiguration(): void } }, array_keys($expectedConfigurationMapping), array_values($expectedConfigurationMapping)); - $webhookConfigurationRegistryDefinition = $containerBuilder->getDefinition('.sensiolabs_gotenberg.webhook_configuration_registry'); + $webhookConfigurationRegistryDefinition = $containerBuilder->getDefinition('sensiolabs_gotenberg.webhook_configuration_registry'); $methodCalls = $webhookConfigurationRegistryDefinition->getMethodCalls(); self::assertCount(3, $methodCalls); foreach ($methodCalls as $methodCall) { From 83e1d26fbe303e2f287c47c0197e4eb2bed4b8ed Mon Sep 17 00:00:00 2001 From: Adrien Roches Date: Sun, 3 Nov 2024 11:22:07 +0100 Subject: [PATCH 12/24] [UPDATE] Add webhook methods --- docs/pdf/builders_api/ConvertPdfBuilder.md | 14 ++- docs/pdf/builders_api/HtmlPdfBuilder.md | 14 ++- .../pdf/builders_api/LibreOfficePdfBuilder.md | 14 ++- docs/pdf/builders_api/MarkdownPdfBuilder.md | 14 ++- docs/pdf/builders_api/MergePdfBuilder.md | 14 ++- docs/pdf/builders_api/UrlPdfBuilder.md | 14 ++- .../builders_api/HtmlScreenshotBuilder.md | 14 ++- .../builders_api/MarkdownScreenshotBuilder.md | 14 ++- .../builders_api/UrlScreenshotBuilder.md | 14 ++- src/Builder/AsyncBuilderInterface.php | 4 + src/Builder/AsyncBuilderTrait.php | 90 ++++++++++++++++--- src/DependencyInjection/Configuration.php | 5 ++ .../SensiolabsGotenbergExtension.php | 2 +- src/Webhook/WebhookConfigurationRegistry.php | 25 ++++-- .../WebhookConfigurationRegistryInterface.php | 12 ++- .../SensiolabsGotenbergExtensionTest.php | 28 +++++- .../WebhookConfigurationRegistryTest.php | 16 ++-- 17 files changed, 246 insertions(+), 62 deletions(-) diff --git a/docs/pdf/builders_api/ConvertPdfBuilder.md b/docs/pdf/builders_api/ConvertPdfBuilder.md index a774ff28..b38e7360 100644 --- a/docs/pdf/builders_api/ConvertPdfBuilder.md +++ b/docs/pdf/builders_api/ConvertPdfBuilder.md @@ -10,10 +10,18 @@ Enable PDF for Universal Access for optimal accessibility. * `downloadFrom(array $downloadFrom)`: -* `webhookConfiguration(string $webhook)`: -Providing an existing $webhook from the configuration file, it will correctly set both success and error webhook URLs as well as extra_http_headers if defined. +* `webhookConfiguration(string $name)`: +Providing an existing $name from the configuration file, it will correctly set both success and error webhook URLs as well as extra_http_headers if defined. -* `webhookUrls(string $successWebhook, ?string $errorWebhook)`: +* `webhookUrl(string $url, ?string $method)`: +Sets the webhook for cases of success. +Optionaly sets a custom HTTP method for such endpoint among : POST, PUT or PATCH. + +* `errorWebhookUrl(?string $url, ?string $method)`: +Sets the webhook for cases of error. +Optionaly sets a custom HTTP method for such endpoint among : POST, PUT or PATCH. + +* `webhookUrls(string $successWebhook, ?string $errorWebhook, ?string $successMethod, ?string $errorMethod)`: Allows to set both $successWebhook and $errorWebhook URLs. If $errorWebhook is not provided, it will fallback to $successWebhook one. * `webhookExtraHeaders(array $extraHeaders)`: diff --git a/docs/pdf/builders_api/HtmlPdfBuilder.md b/docs/pdf/builders_api/HtmlPdfBuilder.md index 9776a50b..12011a5f 100644 --- a/docs/pdf/builders_api/HtmlPdfBuilder.md +++ b/docs/pdf/builders_api/HtmlPdfBuilder.md @@ -129,10 +129,18 @@ The metadata to write. * `downloadFrom(array $downloadFrom)`: -* `webhookConfiguration(string $webhook)`: -Providing an existing $webhook from the configuration file, it will correctly set both success and error webhook URLs as well as extra_http_headers if defined. +* `webhookConfiguration(string $name)`: +Providing an existing $name from the configuration file, it will correctly set both success and error webhook URLs as well as extra_http_headers if defined. -* `webhookUrls(string $successWebhook, ?string $errorWebhook)`: +* `webhookUrl(string $url, ?string $method)`: +Sets the webhook for cases of success. +Optionaly sets a custom HTTP method for such endpoint among : POST, PUT or PATCH. + +* `errorWebhookUrl(?string $url, ?string $method)`: +Sets the webhook for cases of error. +Optionaly sets a custom HTTP method for such endpoint among : POST, PUT or PATCH. + +* `webhookUrls(string $successWebhook, ?string $errorWebhook, ?string $successMethod, ?string $errorMethod)`: Allows to set both $successWebhook and $errorWebhook URLs. If $errorWebhook is not provided, it will fallback to $successWebhook one. * `webhookExtraHeaders(array $extraHeaders)`: diff --git a/docs/pdf/builders_api/LibreOfficePdfBuilder.md b/docs/pdf/builders_api/LibreOfficePdfBuilder.md index c8a6fc0c..476f3db4 100644 --- a/docs/pdf/builders_api/LibreOfficePdfBuilder.md +++ b/docs/pdf/builders_api/LibreOfficePdfBuilder.md @@ -87,10 +87,18 @@ If the form field reduceImageResolution is set to true, tell if all images will * `downloadFrom(array $downloadFrom)`: -* `webhookConfiguration(string $webhook)`: -Providing an existing $webhook from the configuration file, it will correctly set both success and error webhook URLs as well as extra_http_headers if defined. +* `webhookConfiguration(string $name)`: +Providing an existing $name from the configuration file, it will correctly set both success and error webhook URLs as well as extra_http_headers if defined. -* `webhookUrls(string $successWebhook, ?string $errorWebhook)`: +* `webhookUrl(string $url, ?string $method)`: +Sets the webhook for cases of success. +Optionaly sets a custom HTTP method for such endpoint among : POST, PUT or PATCH. + +* `errorWebhookUrl(?string $url, ?string $method)`: +Sets the webhook for cases of error. +Optionaly sets a custom HTTP method for such endpoint among : POST, PUT or PATCH. + +* `webhookUrls(string $successWebhook, ?string $errorWebhook, ?string $successMethod, ?string $errorMethod)`: Allows to set both $successWebhook and $errorWebhook URLs. If $errorWebhook is not provided, it will fallback to $successWebhook one. * `webhookExtraHeaders(array $extraHeaders)`: diff --git a/docs/pdf/builders_api/MarkdownPdfBuilder.md b/docs/pdf/builders_api/MarkdownPdfBuilder.md index 978e8b2e..e3da8bfd 100644 --- a/docs/pdf/builders_api/MarkdownPdfBuilder.md +++ b/docs/pdf/builders_api/MarkdownPdfBuilder.md @@ -132,10 +132,18 @@ The metadata to write. * `downloadFrom(array $downloadFrom)`: -* `webhookConfiguration(string $webhook)`: -Providing an existing $webhook from the configuration file, it will correctly set both success and error webhook URLs as well as extra_http_headers if defined. +* `webhookConfiguration(string $name)`: +Providing an existing $name from the configuration file, it will correctly set both success and error webhook URLs as well as extra_http_headers if defined. -* `webhookUrls(string $successWebhook, ?string $errorWebhook)`: +* `webhookUrl(string $url, ?string $method)`: +Sets the webhook for cases of success. +Optionaly sets a custom HTTP method for such endpoint among : POST, PUT or PATCH. + +* `errorWebhookUrl(?string $url, ?string $method)`: +Sets the webhook for cases of error. +Optionaly sets a custom HTTP method for such endpoint among : POST, PUT or PATCH. + +* `webhookUrls(string $successWebhook, ?string $errorWebhook, ?string $successMethod, ?string $errorMethod)`: Allows to set both $successWebhook and $errorWebhook URLs. If $errorWebhook is not provided, it will fallback to $successWebhook one. * `webhookExtraHeaders(array $extraHeaders)`: diff --git a/docs/pdf/builders_api/MergePdfBuilder.md b/docs/pdf/builders_api/MergePdfBuilder.md index e3f2b42b..5876cdf0 100644 --- a/docs/pdf/builders_api/MergePdfBuilder.md +++ b/docs/pdf/builders_api/MergePdfBuilder.md @@ -18,10 +18,18 @@ The metadata to write. * `downloadFrom(array $downloadFrom)`: -* `webhookConfiguration(string $webhook)`: -Providing an existing $webhook from the configuration file, it will correctly set both success and error webhook URLs as well as extra_http_headers if defined. +* `webhookConfiguration(string $name)`: +Providing an existing $name from the configuration file, it will correctly set both success and error webhook URLs as well as extra_http_headers if defined. -* `webhookUrls(string $successWebhook, ?string $errorWebhook)`: +* `webhookUrl(string $url, ?string $method)`: +Sets the webhook for cases of success. +Optionaly sets a custom HTTP method for such endpoint among : POST, PUT or PATCH. + +* `errorWebhookUrl(?string $url, ?string $method)`: +Sets the webhook for cases of error. +Optionaly sets a custom HTTP method for such endpoint among : POST, PUT or PATCH. + +* `webhookUrls(string $successWebhook, ?string $errorWebhook, ?string $successMethod, ?string $errorMethod)`: Allows to set both $successWebhook and $errorWebhook URLs. If $errorWebhook is not provided, it will fallback to $successWebhook one. * `webhookExtraHeaders(array $extraHeaders)`: diff --git a/docs/pdf/builders_api/UrlPdfBuilder.md b/docs/pdf/builders_api/UrlPdfBuilder.md index ac10a30d..59fe16bd 100644 --- a/docs/pdf/builders_api/UrlPdfBuilder.md +++ b/docs/pdf/builders_api/UrlPdfBuilder.md @@ -131,10 +131,18 @@ The metadata to write. * `downloadFrom(array $downloadFrom)`: -* `webhookConfiguration(string $webhook)`: -Providing an existing $webhook from the configuration file, it will correctly set both success and error webhook URLs as well as extra_http_headers if defined. +* `webhookConfiguration(string $name)`: +Providing an existing $name from the configuration file, it will correctly set both success and error webhook URLs as well as extra_http_headers if defined. -* `webhookUrls(string $successWebhook, ?string $errorWebhook)`: +* `webhookUrl(string $url, ?string $method)`: +Sets the webhook for cases of success. +Optionaly sets a custom HTTP method for such endpoint among : POST, PUT or PATCH. + +* `errorWebhookUrl(?string $url, ?string $method)`: +Sets the webhook for cases of error. +Optionaly sets a custom HTTP method for such endpoint among : POST, PUT or PATCH. + +* `webhookUrls(string $successWebhook, ?string $errorWebhook, ?string $successMethod, ?string $errorMethod)`: Allows to set both $successWebhook and $errorWebhook URLs. If $errorWebhook is not provided, it will fallback to $successWebhook one. * `webhookExtraHeaders(array $extraHeaders)`: diff --git a/docs/screenshot/builders_api/HtmlScreenshotBuilder.md b/docs/screenshot/builders_api/HtmlScreenshotBuilder.md index d760191a..9a63c1cd 100644 --- a/docs/screenshot/builders_api/HtmlScreenshotBuilder.md +++ b/docs/screenshot/builders_api/HtmlScreenshotBuilder.md @@ -74,10 +74,18 @@ Adds a file, like an image, font, stylesheet, and so on. * `downloadFrom(array $downloadFrom)`: -* `webhookConfiguration(string $webhook)`: -Providing an existing $webhook from the configuration file, it will correctly set both success and error webhook URLs as well as extra_http_headers if defined. +* `webhookConfiguration(string $name)`: +Providing an existing $name from the configuration file, it will correctly set both success and error webhook URLs as well as extra_http_headers if defined. -* `webhookUrls(string $successWebhook, ?string $errorWebhook)`: +* `webhookUrl(string $url, ?string $method)`: +Sets the webhook for cases of success. +Optionaly sets a custom HTTP method for such endpoint among : POST, PUT or PATCH. + +* `errorWebhookUrl(?string $url, ?string $method)`: +Sets the webhook for cases of error. +Optionaly sets a custom HTTP method for such endpoint among : POST, PUT or PATCH. + +* `webhookUrls(string $successWebhook, ?string $errorWebhook, ?string $successMethod, ?string $errorMethod)`: Allows to set both $successWebhook and $errorWebhook URLs. If $errorWebhook is not provided, it will fallback to $successWebhook one. * `webhookExtraHeaders(array $extraHeaders)`: diff --git a/docs/screenshot/builders_api/MarkdownScreenshotBuilder.md b/docs/screenshot/builders_api/MarkdownScreenshotBuilder.md index c83e0abe..6ee8de42 100644 --- a/docs/screenshot/builders_api/MarkdownScreenshotBuilder.md +++ b/docs/screenshot/builders_api/MarkdownScreenshotBuilder.md @@ -77,10 +77,18 @@ Adds a file, like an image, font, stylesheet, and so on. * `downloadFrom(array $downloadFrom)`: -* `webhookConfiguration(string $webhook)`: -Providing an existing $webhook from the configuration file, it will correctly set both success and error webhook URLs as well as extra_http_headers if defined. +* `webhookConfiguration(string $name)`: +Providing an existing $name from the configuration file, it will correctly set both success and error webhook URLs as well as extra_http_headers if defined. -* `webhookUrls(string $successWebhook, ?string $errorWebhook)`: +* `webhookUrl(string $url, ?string $method)`: +Sets the webhook for cases of success. +Optionaly sets a custom HTTP method for such endpoint among : POST, PUT or PATCH. + +* `errorWebhookUrl(?string $url, ?string $method)`: +Sets the webhook for cases of error. +Optionaly sets a custom HTTP method for such endpoint among : POST, PUT or PATCH. + +* `webhookUrls(string $successWebhook, ?string $errorWebhook, ?string $successMethod, ?string $errorMethod)`: Allows to set both $successWebhook and $errorWebhook URLs. If $errorWebhook is not provided, it will fallback to $successWebhook one. * `webhookExtraHeaders(array $extraHeaders)`: diff --git a/docs/screenshot/builders_api/UrlScreenshotBuilder.md b/docs/screenshot/builders_api/UrlScreenshotBuilder.md index c9f244d5..c1be7cb4 100644 --- a/docs/screenshot/builders_api/UrlScreenshotBuilder.md +++ b/docs/screenshot/builders_api/UrlScreenshotBuilder.md @@ -76,10 +76,18 @@ Adds a file, like an image, font, stylesheet, and so on. * `downloadFrom(array $downloadFrom)`: -* `webhookConfiguration(string $webhook)`: -Providing an existing $webhook from the configuration file, it will correctly set both success and error webhook URLs as well as extra_http_headers if defined. +* `webhookConfiguration(string $name)`: +Providing an existing $name from the configuration file, it will correctly set both success and error webhook URLs as well as extra_http_headers if defined. -* `webhookUrls(string $successWebhook, ?string $errorWebhook)`: +* `webhookUrl(string $url, ?string $method)`: +Sets the webhook for cases of success. +Optionaly sets a custom HTTP method for such endpoint among : POST, PUT or PATCH. + +* `errorWebhookUrl(?string $url, ?string $method)`: +Sets the webhook for cases of error. +Optionaly sets a custom HTTP method for such endpoint among : POST, PUT or PATCH. + +* `webhookUrls(string $successWebhook, ?string $errorWebhook, ?string $successMethod, ?string $errorMethod)`: Allows to set both $successWebhook and $errorWebhook URLs. If $errorWebhook is not provided, it will fallback to $successWebhook one. * `webhookExtraHeaders(array $extraHeaders)`: diff --git a/src/Builder/AsyncBuilderInterface.php b/src/Builder/AsyncBuilderInterface.php index 52eee111..3daedb50 100644 --- a/src/Builder/AsyncBuilderInterface.php +++ b/src/Builder/AsyncBuilderInterface.php @@ -2,10 +2,14 @@ namespace Sensiolabs\GotenbergBundle\Builder; +use Sensiolabs\GotenbergBundle\Exception\MissingRequiredFieldException; + interface AsyncBuilderInterface { /** * Generates a file asynchronously. + * + * @throws MissingRequiredFieldException if webhook URL was not configured */ public function generateAsync(): void; } diff --git a/src/Builder/AsyncBuilderTrait.php b/src/Builder/AsyncBuilderTrait.php index 0889ea96..5500e5ee 100644 --- a/src/Builder/AsyncBuilderTrait.php +++ b/src/Builder/AsyncBuilderTrait.php @@ -9,9 +9,19 @@ trait AsyncBuilderTrait { use DefaultBuilderTrait; - private string $webhookUrl; + private string|null $successWebhookUrl = null; - private string $errorWebhookUrl; + /** + * @var 'POST'|'PATCH'|'PUT'|null + */ + private string|null $successWebhookMethod = null; + + private string|null $errorWebhookUrl = null; + + /** + * @var 'POST'|'PATCH'|'PUT'|null + */ + private string|null $errorWebhookMethod = null; /** * @var array @@ -22,17 +32,29 @@ trait AsyncBuilderTrait public function generateAsync(): void { - if (!isset($this->webhookUrl)) { + if (null === $this->successWebhookUrl) { throw new MissingRequiredFieldException('->webhookUrls() was never called.'); } - $errorWebhookUrl = $this->errorWebhookUrl ?? $this->webhookUrl; + $errorWebhookUrl = $this->errorWebhookUrl ?? $this->successWebhookUrl; $headers = [ - 'Gotenberg-Webhook-Url' => $this->webhookUrl, + 'Gotenberg-Webhook-Url' => $this->successWebhookUrl, 'Gotenberg-Webhook-Error-Url' => $errorWebhookUrl, - 'Gotenberg-Webhook-Extra-Http-Headers' => json_encode($this->webhookExtraHeaders, \JSON_THROW_ON_ERROR), ]; + + if (null !== $this->successWebhookMethod) { + $headers['Gotenberg-Webhook-Method'] = $this->successWebhookMethod; + } + + if (null !== $this->errorWebhookMethod) { + $headers['Gotenberg-Webhook-Error-Method'] = $this->errorWebhookMethod; + } + + if ([] !== $this->webhookExtraHeaders) { + $headers['Gotenberg-Webhook-Extra-Http-Headers'] = json_encode($this->webhookExtraHeaders, \JSON_THROW_ON_ERROR); + } + if (null !== $this->fileName) { // Gotenberg will add the extension to the file name (e.g. filename : "file.pdf" => generated file : "file.pdf.pdf"). $headers['Gotenberg-Output-Filename'] = $this->fileName; @@ -41,13 +63,18 @@ public function generateAsync(): void } /** - * Providing an existing $webhook from the configuration file, it will correctly set both success and error webhook URLs as well as extra_http_headers if defined. + * Providing an existing $name from the configuration file, it will correctly set both success and error webhook URLs as well as extra_http_headers if defined. */ - public function webhookConfiguration(string $webhook): static + public function webhookConfiguration(string $name): static { - $webhookConfiguration = $this->webhookConfigurationRegistry->get($webhook); + $webhookConfiguration = $this->webhookConfigurationRegistry->get($name); - $result = $this->webhookUrls($webhookConfiguration['success'], $webhookConfiguration['error']); + $result = $this->webhookUrls( + $webhookConfiguration['success']['url'], + $webhookConfiguration['error']['url'], + $webhookConfiguration['success']['method'], + $webhookConfiguration['error']['method'], + ); if (\array_key_exists('extra_http_headers', $webhookConfiguration)) { $result = $result->webhookExtraHeaders($webhookConfiguration['extra_http_headers']); @@ -57,16 +84,51 @@ public function webhookConfiguration(string $webhook): static } /** - * Allows to set both $successWebhook and $errorWebhook URLs. If $errorWebhook is not provided, it will fallback to $successWebhook one. + * Sets the webhook for cases of success. + * Optionaly sets a custom HTTP method for such endpoint among : POST, PUT or PATCH. + * + * @param 'POST'|'PATCH'|'PUT'|null $method + * + * @see https://gotenberg.dev/docs/webhook */ - public function webhookUrls(string $successWebhook, string|null $errorWebhook = null): static + public function webhookUrl(string $url, string|null $method = null): static { - $this->webhookUrl = $successWebhook; - $this->errorWebhookUrl = $errorWebhook ?? $successWebhook; + $this->successWebhookUrl = $url; + $this->successWebhookMethod = $method; return $this; } + /** + * Sets the webhook for cases of error. + * Optionaly sets a custom HTTP method for such endpoint among : POST, PUT or PATCH. + * + * @param 'POST'|'PATCH'|'PUT'|null $method + * + * @see https://gotenberg.dev/docs/webhook + */ + public function errorWebhookUrl(string|null $url = null, string|null $method = null): static + { + $this->errorWebhookUrl = $url; + $this->errorWebhookMethod = $method; + + return $this; + } + + /** + * Allows to set both $successWebhook and $errorWebhook URLs. If $errorWebhook is not provided, it will fallback to $successWebhook one. + * + * @param 'POST'|'PATCH'|'PUT'|null $successMethod + * @param 'POST'|'PATCH'|'PUT'|null $errorMethod + */ + public function webhookUrls(string $successWebhook, string|null $errorWebhook = null, string|null $successMethod = null, string|null $errorMethod = null): static + { + return $this + ->webhookUrl($successWebhook, $successMethod) + ->errorWebhookUrl($errorWebhook, $errorMethod) + ; + } + /** * Extra headers that will be provided to the webhook endpoint. May it either be Success or Error. * diff --git a/src/DependencyInjection/Configuration.php b/src/DependencyInjection/Configuration.php index 50e353d8..ec089164 100644 --- a/src/DependencyInjection/Configuration.php +++ b/src/DependencyInjection/Configuration.php @@ -774,6 +774,11 @@ private function addWebhookConfigurationNode(string $name): NodeDefinition ->thenInvalid('The "route" parameter must be a string or an array containing a string and an array.') ->end() ->end() + ->enumNode('method') + ->info('HTTP method to use on that endpoint.') + ->values(['POST', 'PUT', 'PATCH']) + ->defaultNull() + ->end() ->end() ; } diff --git a/src/DependencyInjection/SensiolabsGotenbergExtension.php b/src/DependencyInjection/SensiolabsGotenbergExtension.php index 3647ac06..6e955344 100644 --- a/src/DependencyInjection/SensiolabsGotenbergExtension.php +++ b/src/DependencyInjection/SensiolabsGotenbergExtension.php @@ -13,7 +13,7 @@ use Symfony\Component\Routing\RequestContext; /** - * @phpstan-type WebhookDefinition array{url?: string, route?: array{0: string, 1: array}} + * @phpstan-type WebhookDefinition array{url?: string, route?: array{0: string, 1: array}, method?: 'POST'|'PUT'|'PATCH'|null} */ class SensiolabsGotenbergExtension extends Extension { diff --git a/src/Webhook/WebhookConfigurationRegistry.php b/src/Webhook/WebhookConfigurationRegistry.php index 04f3af52..e243940b 100644 --- a/src/Webhook/WebhookConfigurationRegistry.php +++ b/src/Webhook/WebhookConfigurationRegistry.php @@ -15,10 +15,16 @@ final class WebhookConfigurationRegistry implements WebhookConfigurationRegistry { /** * @var array - * }> + * success: array{ + * url: string, + * method: 'POST'|'PUT'|'PATCH'|null, + * }, + * error: array{ + * url: string, + * method: 'POST'|'PUT'|'PATCH'|null, + * }, + * extra_http_headers?: array + * }> */ private array $configurations = []; @@ -39,10 +45,17 @@ public function add(string $name, array $configuration): void } try { - $success = $this->processWebhookConfiguration($configuration['success']); + $success = [ + 'url' => $this->processWebhookConfiguration($configuration['success']), + 'method' => $configuration['success']['method'] ?? null, + ]; $error = $success; + if (isset($configuration['error'])) { - $error = $this->processWebhookConfiguration($configuration['error']); + $error = [ + 'url' => $this->processWebhookConfiguration($configuration['error']), + 'method' => $configuration['error']['method'] ?? null, + ]; } $namedConfiguration = ['success' => $success, 'error' => $error]; diff --git a/src/Webhook/WebhookConfigurationRegistryInterface.php b/src/Webhook/WebhookConfigurationRegistryInterface.php index ec67792e..48f2dd22 100644 --- a/src/Webhook/WebhookConfigurationRegistryInterface.php +++ b/src/Webhook/WebhookConfigurationRegistryInterface.php @@ -5,7 +5,7 @@ use Sensiolabs\GotenbergBundle\Exception\WebhookConfigurationException; /** - * @phpstan-type WebhookDefinition array{url?: string, route?: array{0: string, 1: array}} + * @phpstan-type WebhookDefinition array{url?: string, route?: array{0: string, 1: array}, method?: 'POST'|'PUT'|'PATCH'|null} */ interface WebhookConfigurationRegistryInterface { @@ -16,8 +16,14 @@ public function add(string $name, array $configuration): void; /** * @return array{ - * success: string, - * error: string, + * success: array{ + * url: string, + * method: 'POST'|'PUT'|'PATCH'|null, + * }, + * error: array{ + * url: string, + * method: 'POST'|'PUT'|'PATCH'|null, + * }, * extra_http_headers?: array * } * diff --git a/tests/DependencyInjection/SensiolabsGotenbergExtensionTest.php b/tests/DependencyInjection/SensiolabsGotenbergExtensionTest.php index de914c0b..9769eb6c 100644 --- a/tests/DependencyInjection/SensiolabsGotenbergExtensionTest.php +++ b/tests/DependencyInjection/SensiolabsGotenbergExtensionTest.php @@ -488,9 +488,31 @@ public function testBuilderWebhookConfiguredWithValidConfiguration(): void self::assertSame('add', $name); self::assertContains($arguments[0], ['foo', 'baz', '.sensiolabs_gotenberg.pdf_builder.markdown_webhook_config']); self::assertSame(match ($arguments[0]) { - 'foo' => ['success' => ['url' => 'https://sensiolabs.com/webhook'], 'error' => ['route' => ['simple_route', []]], 'extra_http_headers' => []], - 'baz' => ['success' => ['route' => ['array_route', ['param1', 'param2']]], 'extra_http_headers' => []], - '.sensiolabs_gotenberg.pdf_builder.markdown_webhook_config' => ['success' => ['url' => 'https://sensiolabs.com/webhook-on-the-fly'], 'extra_http_headers' => []], + 'foo' => [ + 'success' => [ + 'url' => 'https://sensiolabs.com/webhook', + 'method' => null, + ], + 'error' => [ + 'route' => ['simple_route', []], + 'method' => null, + ], + 'extra_http_headers' => [], + ], + 'baz' => [ + 'success' => [ + 'route' => ['array_route', ['param1', 'param2']], + 'method' => null, + ], + 'extra_http_headers' => [], + ], + '.sensiolabs_gotenberg.pdf_builder.markdown_webhook_config' => [ + 'success' => [ + 'url' => 'https://sensiolabs.com/webhook-on-the-fly', + 'method' => null, + ], + 'extra_http_headers' => [], + ], default => self::fail('Unexpected webhook configuration'), }, $arguments[1]); } diff --git a/tests/DependencyInjection/WebhookConfigurationRegistryTest.php b/tests/DependencyInjection/WebhookConfigurationRegistryTest.php index 38271e93..7ad4c678 100644 --- a/tests/DependencyInjection/WebhookConfigurationRegistryTest.php +++ b/tests/DependencyInjection/WebhookConfigurationRegistryTest.php @@ -39,38 +39,38 @@ public function testOverrideConfiguration(): void { $registry = new WebhookConfigurationRegistry($this->createMock(UrlGeneratorInterface::class), null); $registry->add('test', ['success' => ['url' => 'http://example.com/success']]); - $this->assertSame(['success' => 'http://example.com/success', 'error' => 'http://example.com/success'], $registry->get('test')); + $this->assertSame(['success' => ['url' => 'http://example.com/success', 'method' => null], 'error' => ['url' => 'http://example.com/success', 'method' => null]], $registry->get('test')); $registry->add('test', ['success' => ['url' => 'http://example.com/override']]); - $this->assertSame(['success' => 'http://example.com/override', 'error' => 'http://example.com/override'], $registry->get('test')); + $this->assertSame(['success' => ['url' => 'http://example.com/override', 'method' => null], 'error' => ['url' => 'http://example.com/override', 'method' => null]], $registry->get('test')); } /** - * @return \Generator + * @return \Generator */ public static function configurationProvider(): \Generator { yield 'full definition with urls' => [ ['success' => ['url' => 'http://example.com/success'], 'error' => ['url' => 'http://example.com/error']], - ['success' => 'http://example.com/success', 'error' => 'http://example.com/error'], + ['success' => ['url' => 'http://example.com/success', 'method' => null], 'error' => ['url' => 'http://example.com/error', 'method' => null]], ]; yield 'full definition with routes' => [ ['success' => ['route' => ['test_route_success', ['param' => 'value']]], 'error' => ['route' => ['test_route_error', ['param' => 'value']]]], - ['success' => 'http://localhost/test_route?param=value', 'error' => 'http://localhost/test_route?param=value'], + ['success' => ['url' => 'http://localhost/test_route?param=value', 'method' => null], 'error' => ['url' => 'http://localhost/test_route?param=value', 'method' => null]], ]; yield 'partial definition with urls' => [ ['success' => ['url' => 'http://example.com/success']], - ['success' => 'http://example.com/success', 'error' => 'http://example.com/success'], + ['success' => ['url' => 'http://example.com/success', 'method' => null], 'error' => ['url' => 'http://example.com/success', 'method' => null]], ]; yield 'partial definition with routes' => [ ['success' => ['route' => ['test_route_success', ['param' => 'value']]], 'error' => ['route' => ['test_route_error', ['param' => 'value']]], ], - ['success' => 'http://localhost/test_route?param=value', 'error' => 'http://localhost/test_route?param=value'], + ['success' => ['url' => 'http://localhost/test_route?param=value', 'method' => null], 'error' => ['url' => 'http://localhost/test_route?param=value', 'method' => null]], ]; yield 'mixed definition with url and route' => [ ['success' => ['url' => 'http://example.com/success'], 'error' => ['route' => ['test_route_error', ['param' => 'value']]], ], - ['success' => 'http://example.com/success', 'error' => 'http://localhost/test_route?param=value'], + ['success' => ['url' => 'http://example.com/success', 'method' => null], 'error' => ['url' => 'http://localhost/test_route?param=value', 'method' => null]], ]; } From 42a8544530b9462d7789d88209000f1113f21159 Mon Sep 17 00:00:00 2001 From: Adrien Roches Date: Sun, 3 Nov 2024 11:23:22 +0100 Subject: [PATCH 13/24] [UPDATE] Exclude some methods to auto docs --- docs/generate.php | 3 ++- docs/pdf/builders_api/ConvertPdfBuilder.md | 6 ++---- docs/pdf/builders_api/HtmlPdfBuilder.md | 6 ++---- docs/pdf/builders_api/LibreOfficePdfBuilder.md | 6 ++---- docs/pdf/builders_api/MarkdownPdfBuilder.md | 6 ++---- docs/pdf/builders_api/MergePdfBuilder.md | 6 ++---- docs/pdf/builders_api/UrlPdfBuilder.md | 6 ++---- docs/screenshot/builders_api/HtmlScreenshotBuilder.md | 6 ++---- docs/screenshot/builders_api/MarkdownScreenshotBuilder.md | 6 ++---- docs/screenshot/builders_api/UrlScreenshotBuilder.md | 6 ++---- 10 files changed, 20 insertions(+), 37 deletions(-) diff --git a/docs/generate.php b/docs/generate.php index 0fabaedc..fe617fd3 100755 --- a/docs/generate.php +++ b/docs/generate.php @@ -41,7 +41,8 @@ 'setConfigurations', 'generate', 'generateAsync', - 'getMultipartFormData', + 'fileName', + 'processor', ]; function parseMethodSignature(ReflectionMethod $method): string diff --git a/docs/pdf/builders_api/ConvertPdfBuilder.md b/docs/pdf/builders_api/ConvertPdfBuilder.md index b38e7360..afc4bcf2 100644 --- a/docs/pdf/builders_api/ConvertPdfBuilder.md +++ b/docs/pdf/builders_api/ConvertPdfBuilder.md @@ -8,6 +8,8 @@ Enable PDF for Universal Access for optimal accessibility. * `files(string $paths)`: +* `getMultipartFormData()`: + * `downloadFrom(array $downloadFrom)`: * `webhookConfiguration(string $name)`: @@ -27,7 +29,3 @@ Allows to set both $successWebhook and $errorWebhook URLs. If $errorWebhook is n * `webhookExtraHeaders(array $extraHeaders)`: Extra headers that will be provided to the webhook endpoint. May it either be Success or Error. -* `fileName(string $fileName, string $headerDisposition)`: - -* `processor(Sensiolabs\GotenbergBundle\Processor\ProcessorInterface $processor)`: - diff --git a/docs/pdf/builders_api/HtmlPdfBuilder.md b/docs/pdf/builders_api/HtmlPdfBuilder.md index 12011a5f..b4e76df3 100644 --- a/docs/pdf/builders_api/HtmlPdfBuilder.md +++ b/docs/pdf/builders_api/HtmlPdfBuilder.md @@ -5,6 +5,8 @@ * `contentFile(string $path)`: The HTML file to convert into PDF. +* `getMultipartFormData()`: + * `cookies(array $cookies)`: * `setCookie(string $key, Symfony\Component\HttpFoundation\Cookie|array $cookie)`: @@ -146,10 +148,6 @@ Allows to set both $successWebhook and $errorWebhook URLs. If $errorWebhook is n * `webhookExtraHeaders(array $extraHeaders)`: Extra headers that will be provided to the webhook endpoint. May it either be Success or Error. -* `fileName(string $fileName, string $headerDisposition)`: - -* `processor(Sensiolabs\GotenbergBundle\Processor\ProcessorInterface $processor)`: - * `addCookies(array $cookies)`: Add cookies to store in the Chromium cookie jar. diff --git a/docs/pdf/builders_api/LibreOfficePdfBuilder.md b/docs/pdf/builders_api/LibreOfficePdfBuilder.md index 476f3db4..6ed63592 100644 --- a/docs/pdf/builders_api/LibreOfficePdfBuilder.md +++ b/docs/pdf/builders_api/LibreOfficePdfBuilder.md @@ -85,6 +85,8 @@ Specify if the resolution of each image is reduced to the resolution specified b * `maxImageResolution(Sensiolabs\GotenbergBundle\Enumeration\ImageResolutionDPI $resolution)`: If the form field reduceImageResolution is set to true, tell if all images will be reduced to the given value in DPI. Possible values are: 75, 150, 300, 600 and 1200. +* `getMultipartFormData()`: + * `downloadFrom(array $downloadFrom)`: * `webhookConfiguration(string $name)`: @@ -104,7 +106,3 @@ Allows to set both $successWebhook and $errorWebhook URLs. If $errorWebhook is n * `webhookExtraHeaders(array $extraHeaders)`: Extra headers that will be provided to the webhook endpoint. May it either be Success or Error. -* `fileName(string $fileName, string $headerDisposition)`: - -* `processor(Sensiolabs\GotenbergBundle\Processor\ProcessorInterface $processor)`: - diff --git a/docs/pdf/builders_api/MarkdownPdfBuilder.md b/docs/pdf/builders_api/MarkdownPdfBuilder.md index e3da8bfd..f402e53e 100644 --- a/docs/pdf/builders_api/MarkdownPdfBuilder.md +++ b/docs/pdf/builders_api/MarkdownPdfBuilder.md @@ -8,6 +8,8 @@ The HTML file that wraps the markdown content. * `files(string $paths)`: +* `getMultipartFormData()`: + * `cookies(array $cookies)`: * `setCookie(string $key, Symfony\Component\HttpFoundation\Cookie|array $cookie)`: @@ -149,10 +151,6 @@ Allows to set both $successWebhook and $errorWebhook URLs. If $errorWebhook is n * `webhookExtraHeaders(array $extraHeaders)`: Extra headers that will be provided to the webhook endpoint. May it either be Success or Error. -* `fileName(string $fileName, string $headerDisposition)`: - -* `processor(Sensiolabs\GotenbergBundle\Processor\ProcessorInterface $processor)`: - * `addCookies(array $cookies)`: Add cookies to store in the Chromium cookie jar. diff --git a/docs/pdf/builders_api/MergePdfBuilder.md b/docs/pdf/builders_api/MergePdfBuilder.md index 5876cdf0..b38c0f7c 100644 --- a/docs/pdf/builders_api/MergePdfBuilder.md +++ b/docs/pdf/builders_api/MergePdfBuilder.md @@ -16,6 +16,8 @@ Resets the metadata. * `addMetadata(string $key, string $value)`: The metadata to write. +* `getMultipartFormData()`: + * `downloadFrom(array $downloadFrom)`: * `webhookConfiguration(string $name)`: @@ -35,7 +37,3 @@ Allows to set both $successWebhook and $errorWebhook URLs. If $errorWebhook is n * `webhookExtraHeaders(array $extraHeaders)`: Extra headers that will be provided to the webhook endpoint. May it either be Success or Error. -* `fileName(string $fileName, string $headerDisposition)`: - -* `processor(Sensiolabs\GotenbergBundle\Processor\ProcessorInterface $processor)`: - diff --git a/docs/pdf/builders_api/UrlPdfBuilder.md b/docs/pdf/builders_api/UrlPdfBuilder.md index 59fe16bd..cef03fa3 100644 --- a/docs/pdf/builders_api/UrlPdfBuilder.md +++ b/docs/pdf/builders_api/UrlPdfBuilder.md @@ -7,6 +7,8 @@ URL of the page you want to convert into PDF. * `route(string $name, array $parameters)`: +* `getMultipartFormData()`: + * `cookies(array $cookies)`: * `setCookie(string $key, Symfony\Component\HttpFoundation\Cookie|array $cookie)`: @@ -148,10 +150,6 @@ Allows to set both $successWebhook and $errorWebhook URLs. If $errorWebhook is n * `webhookExtraHeaders(array $extraHeaders)`: Extra headers that will be provided to the webhook endpoint. May it either be Success or Error. -* `fileName(string $fileName, string $headerDisposition)`: - -* `processor(Sensiolabs\GotenbergBundle\Processor\ProcessorInterface $processor)`: - * `addCookies(array $cookies)`: Add cookies to store in the Chromium cookie jar. diff --git a/docs/screenshot/builders_api/HtmlScreenshotBuilder.md b/docs/screenshot/builders_api/HtmlScreenshotBuilder.md index 9a63c1cd..92c31d7d 100644 --- a/docs/screenshot/builders_api/HtmlScreenshotBuilder.md +++ b/docs/screenshot/builders_api/HtmlScreenshotBuilder.md @@ -5,6 +5,8 @@ * `contentFile(string $path)`: The HTML file to convert into Screenshot. +* `getMultipartFormData()`: + * `cookies(array $cookies)`: * `setCookie(string $key, Symfony\Component\HttpFoundation\Cookie|array $cookie)`: @@ -91,10 +93,6 @@ Allows to set both $successWebhook and $errorWebhook URLs. If $errorWebhook is n * `webhookExtraHeaders(array $extraHeaders)`: Extra headers that will be provided to the webhook endpoint. May it either be Success or Error. -* `fileName(string $fileName, string $headerDisposition)`: - -* `processor(Sensiolabs\GotenbergBundle\Processor\ProcessorInterface $processor)`: - * `addCookies(array $cookies)`: Add cookies to store in the Chromium cookie jar. diff --git a/docs/screenshot/builders_api/MarkdownScreenshotBuilder.md b/docs/screenshot/builders_api/MarkdownScreenshotBuilder.md index 6ee8de42..6ee86f54 100644 --- a/docs/screenshot/builders_api/MarkdownScreenshotBuilder.md +++ b/docs/screenshot/builders_api/MarkdownScreenshotBuilder.md @@ -8,6 +8,8 @@ The HTML file that wraps the markdown content. * `files(string $paths)`: +* `getMultipartFormData()`: + * `cookies(array $cookies)`: * `setCookie(string $key, Symfony\Component\HttpFoundation\Cookie|array $cookie)`: @@ -94,10 +96,6 @@ Allows to set both $successWebhook and $errorWebhook URLs. If $errorWebhook is n * `webhookExtraHeaders(array $extraHeaders)`: Extra headers that will be provided to the webhook endpoint. May it either be Success or Error. -* `fileName(string $fileName, string $headerDisposition)`: - -* `processor(Sensiolabs\GotenbergBundle\Processor\ProcessorInterface $processor)`: - * `addCookies(array $cookies)`: Add cookies to store in the Chromium cookie jar. diff --git a/docs/screenshot/builders_api/UrlScreenshotBuilder.md b/docs/screenshot/builders_api/UrlScreenshotBuilder.md index c1be7cb4..34d68654 100644 --- a/docs/screenshot/builders_api/UrlScreenshotBuilder.md +++ b/docs/screenshot/builders_api/UrlScreenshotBuilder.md @@ -7,6 +7,8 @@ URL of the page you want to screenshot. * `route(string $name, array $parameters)`: +* `getMultipartFormData()`: + * `cookies(array $cookies)`: * `setCookie(string $key, Symfony\Component\HttpFoundation\Cookie|array $cookie)`: @@ -93,10 +95,6 @@ Allows to set both $successWebhook and $errorWebhook URLs. If $errorWebhook is n * `webhookExtraHeaders(array $extraHeaders)`: Extra headers that will be provided to the webhook endpoint. May it either be Success or Error. -* `fileName(string $fileName, string $headerDisposition)`: - -* `processor(Sensiolabs\GotenbergBundle\Processor\ProcessorInterface $processor)`: - * `addCookies(array $cookies)`: Add cookies to store in the Chromium cookie jar. From a574f5109f24168fe1c379a5c2ffbdc354475d42 Mon Sep 17 00:00:00 2001 From: Adrien Roches Date: Sun, 3 Nov 2024 11:23:58 +0100 Subject: [PATCH 14/24] [UPDATE] Exclude some methods to auto docs --- docs/generate.php | 1 + docs/pdf/builders_api/ConvertPdfBuilder.md | 2 -- docs/pdf/builders_api/HtmlPdfBuilder.md | 2 -- docs/pdf/builders_api/LibreOfficePdfBuilder.md | 2 -- docs/pdf/builders_api/MarkdownPdfBuilder.md | 2 -- docs/pdf/builders_api/MergePdfBuilder.md | 2 -- docs/pdf/builders_api/UrlPdfBuilder.md | 2 -- docs/screenshot/builders_api/HtmlScreenshotBuilder.md | 2 -- docs/screenshot/builders_api/MarkdownScreenshotBuilder.md | 2 -- docs/screenshot/builders_api/UrlScreenshotBuilder.md | 2 -- 10 files changed, 1 insertion(+), 18 deletions(-) diff --git a/docs/generate.php b/docs/generate.php index fe617fd3..0b826131 100755 --- a/docs/generate.php +++ b/docs/generate.php @@ -41,6 +41,7 @@ 'setConfigurations', 'generate', 'generateAsync', + 'getMultipartFormData', 'fileName', 'processor', ]; diff --git a/docs/pdf/builders_api/ConvertPdfBuilder.md b/docs/pdf/builders_api/ConvertPdfBuilder.md index afc4bcf2..0c49bf7a 100644 --- a/docs/pdf/builders_api/ConvertPdfBuilder.md +++ b/docs/pdf/builders_api/ConvertPdfBuilder.md @@ -8,8 +8,6 @@ Enable PDF for Universal Access for optimal accessibility. * `files(string $paths)`: -* `getMultipartFormData()`: - * `downloadFrom(array $downloadFrom)`: * `webhookConfiguration(string $name)`: diff --git a/docs/pdf/builders_api/HtmlPdfBuilder.md b/docs/pdf/builders_api/HtmlPdfBuilder.md index b4e76df3..bea69e5e 100644 --- a/docs/pdf/builders_api/HtmlPdfBuilder.md +++ b/docs/pdf/builders_api/HtmlPdfBuilder.md @@ -5,8 +5,6 @@ * `contentFile(string $path)`: The HTML file to convert into PDF. -* `getMultipartFormData()`: - * `cookies(array $cookies)`: * `setCookie(string $key, Symfony\Component\HttpFoundation\Cookie|array $cookie)`: diff --git a/docs/pdf/builders_api/LibreOfficePdfBuilder.md b/docs/pdf/builders_api/LibreOfficePdfBuilder.md index 6ed63592..c27100ea 100644 --- a/docs/pdf/builders_api/LibreOfficePdfBuilder.md +++ b/docs/pdf/builders_api/LibreOfficePdfBuilder.md @@ -85,8 +85,6 @@ Specify if the resolution of each image is reduced to the resolution specified b * `maxImageResolution(Sensiolabs\GotenbergBundle\Enumeration\ImageResolutionDPI $resolution)`: If the form field reduceImageResolution is set to true, tell if all images will be reduced to the given value in DPI. Possible values are: 75, 150, 300, 600 and 1200. -* `getMultipartFormData()`: - * `downloadFrom(array $downloadFrom)`: * `webhookConfiguration(string $name)`: diff --git a/docs/pdf/builders_api/MarkdownPdfBuilder.md b/docs/pdf/builders_api/MarkdownPdfBuilder.md index f402e53e..47ea0711 100644 --- a/docs/pdf/builders_api/MarkdownPdfBuilder.md +++ b/docs/pdf/builders_api/MarkdownPdfBuilder.md @@ -8,8 +8,6 @@ The HTML file that wraps the markdown content. * `files(string $paths)`: -* `getMultipartFormData()`: - * `cookies(array $cookies)`: * `setCookie(string $key, Symfony\Component\HttpFoundation\Cookie|array $cookie)`: diff --git a/docs/pdf/builders_api/MergePdfBuilder.md b/docs/pdf/builders_api/MergePdfBuilder.md index b38c0f7c..db2a32f6 100644 --- a/docs/pdf/builders_api/MergePdfBuilder.md +++ b/docs/pdf/builders_api/MergePdfBuilder.md @@ -16,8 +16,6 @@ Resets the metadata. * `addMetadata(string $key, string $value)`: The metadata to write. -* `getMultipartFormData()`: - * `downloadFrom(array $downloadFrom)`: * `webhookConfiguration(string $name)`: diff --git a/docs/pdf/builders_api/UrlPdfBuilder.md b/docs/pdf/builders_api/UrlPdfBuilder.md index cef03fa3..30d74ae3 100644 --- a/docs/pdf/builders_api/UrlPdfBuilder.md +++ b/docs/pdf/builders_api/UrlPdfBuilder.md @@ -7,8 +7,6 @@ URL of the page you want to convert into PDF. * `route(string $name, array $parameters)`: -* `getMultipartFormData()`: - * `cookies(array $cookies)`: * `setCookie(string $key, Symfony\Component\HttpFoundation\Cookie|array $cookie)`: diff --git a/docs/screenshot/builders_api/HtmlScreenshotBuilder.md b/docs/screenshot/builders_api/HtmlScreenshotBuilder.md index 92c31d7d..a3b678ae 100644 --- a/docs/screenshot/builders_api/HtmlScreenshotBuilder.md +++ b/docs/screenshot/builders_api/HtmlScreenshotBuilder.md @@ -5,8 +5,6 @@ * `contentFile(string $path)`: The HTML file to convert into Screenshot. -* `getMultipartFormData()`: - * `cookies(array $cookies)`: * `setCookie(string $key, Symfony\Component\HttpFoundation\Cookie|array $cookie)`: diff --git a/docs/screenshot/builders_api/MarkdownScreenshotBuilder.md b/docs/screenshot/builders_api/MarkdownScreenshotBuilder.md index 6ee86f54..5180bb8b 100644 --- a/docs/screenshot/builders_api/MarkdownScreenshotBuilder.md +++ b/docs/screenshot/builders_api/MarkdownScreenshotBuilder.md @@ -8,8 +8,6 @@ The HTML file that wraps the markdown content. * `files(string $paths)`: -* `getMultipartFormData()`: - * `cookies(array $cookies)`: * `setCookie(string $key, Symfony\Component\HttpFoundation\Cookie|array $cookie)`: diff --git a/docs/screenshot/builders_api/UrlScreenshotBuilder.md b/docs/screenshot/builders_api/UrlScreenshotBuilder.md index 34d68654..3eb4deb2 100644 --- a/docs/screenshot/builders_api/UrlScreenshotBuilder.md +++ b/docs/screenshot/builders_api/UrlScreenshotBuilder.md @@ -7,8 +7,6 @@ URL of the page you want to screenshot. * `route(string $name, array $parameters)`: -* `getMultipartFormData()`: - * `cookies(array $cookies)`: * `setCookie(string $key, Symfony\Component\HttpFoundation\Cookie|array $cookie)`: From a9694cb1cd4413f60c88750108f5e9ff293a9ff6 Mon Sep 17 00:00:00 2001 From: Adrien Roches Date: Sun, 3 Nov 2024 11:29:18 +0100 Subject: [PATCH 15/24] [UPDATE] Change equality check --- src/DependencyInjection/SensiolabsGotenbergExtension.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/DependencyInjection/SensiolabsGotenbergExtension.php b/src/DependencyInjection/SensiolabsGotenbergExtension.php index 6e955344..bd1288d3 100644 --- a/src/DependencyInjection/SensiolabsGotenbergExtension.php +++ b/src/DependencyInjection/SensiolabsGotenbergExtension.php @@ -120,7 +120,7 @@ private function processDefaultOptions(string $serviceId, ContainerBuilder $cont return; } - if (null === $webhookConfig) { + if (null !== $defaultWebhookName) { $definition->addMethodCall('webhookConfiguration', [$defaultWebhookName], true); return; From 8d39bd958d54fd1f48a7f7051f6fc0a92ee1c03f Mon Sep 17 00:00:00 2001 From: Adrien Roches Date: Fri, 15 Nov 2024 20:43:00 +0100 Subject: [PATCH 16/24] Update profiler icons + Fix webhook configuration + fix some tests --- config/builder_pdf.php | 12 +-- config/builder_screenshot.php | 6 +- config/services.php | 5 +- src/DataCollector/GotenbergDataCollector.php | 1 + src/Debug/Builder/TraceablePdfBuilder.php | 6 +- .../Builder/TraceableScreenshotBuilder.php | 6 +- .../SensiolabsGotenbergExtension.php | 95 +++++++++++++------ .../Collector/sensiolabs_gotenberg.html.twig | 17 ++-- templates/Icon/file-async.svg | 1 + templates/Icon/file-sync.svg | 1 + .../SensiolabsGotenbergExtensionTest.php | 18 ++-- 11 files changed, 109 insertions(+), 59 deletions(-) create mode 100644 templates/Icon/file-async.svg create mode 100644 templates/Icon/file-sync.svg diff --git a/config/builder_pdf.php b/config/builder_pdf.php index 74d83e9a..349c960d 100644 --- a/config/builder_pdf.php +++ b/config/builder_pdf.php @@ -21,7 +21,7 @@ ->args([ service('sensiolabs_gotenberg.client'), service('sensiolabs_gotenberg.asset.base_dir_formatter'), - service('sensiolabs_gotenberg.webhook_configuration_registry'), + service('.sensiolabs_gotenberg.webhook_configuration_registry'), service('request_stack'), service('twig')->nullOnInvalid(), ]) @@ -34,7 +34,7 @@ ->args([ service('sensiolabs_gotenberg.client'), service('sensiolabs_gotenberg.asset.base_dir_formatter'), - service('sensiolabs_gotenberg.webhook_configuration_registry'), + service('.sensiolabs_gotenberg.webhook_configuration_registry'), service('request_stack'), service('twig')->nullOnInvalid(), service('router')->nullOnInvalid(), @@ -49,7 +49,7 @@ ->args([ service('sensiolabs_gotenberg.client'), service('sensiolabs_gotenberg.asset.base_dir_formatter'), - service('sensiolabs_gotenberg.webhook_configuration_registry'), + service('.sensiolabs_gotenberg.webhook_configuration_registry'), service('request_stack'), service('twig')->nullOnInvalid(), ]) @@ -62,7 +62,7 @@ ->args([ service('sensiolabs_gotenberg.client'), service('sensiolabs_gotenberg.asset.base_dir_formatter'), - service('sensiolabs_gotenberg.webhook_configuration_registry'), + service('.sensiolabs_gotenberg.webhook_configuration_registry'), ]) ->call('setLogger', [service('logger')->nullOnInvalid()]) ->tag('sensiolabs_gotenberg.pdf_builder') @@ -73,7 +73,7 @@ ->args([ service('sensiolabs_gotenberg.client'), service('sensiolabs_gotenberg.asset.base_dir_formatter'), - service('sensiolabs_gotenberg.webhook_configuration_registry'), + service('.sensiolabs_gotenberg.webhook_configuration_registry'), ]) ->call('setLogger', [service('logger')->nullOnInvalid()]) ->tag('sensiolabs_gotenberg.pdf_builder') @@ -84,7 +84,7 @@ ->args([ service('sensiolabs_gotenberg.client'), service('sensiolabs_gotenberg.asset.base_dir_formatter'), - service('sensiolabs_gotenberg.webhook_configuration_registry'), + service('.sensiolabs_gotenberg.webhook_configuration_registry'), ]) ->call('setLogger', [service('logger')->nullOnInvalid()]) ->tag('sensiolabs_gotenberg.pdf_builder') diff --git a/config/builder_screenshot.php b/config/builder_screenshot.php index bd782808..7ecb4cb2 100644 --- a/config/builder_screenshot.php +++ b/config/builder_screenshot.php @@ -18,7 +18,7 @@ ->args([ service('sensiolabs_gotenberg.client'), service('sensiolabs_gotenberg.asset.base_dir_formatter'), - service('sensiolabs_gotenberg.webhook_configuration_registry'), + service('.sensiolabs_gotenberg.webhook_configuration_registry'), service('request_stack'), service('twig')->nullOnInvalid(), ]) @@ -31,7 +31,7 @@ ->args([ service('sensiolabs_gotenberg.client'), service('sensiolabs_gotenberg.asset.base_dir_formatter'), - service('sensiolabs_gotenberg.webhook_configuration_registry'), + service('.sensiolabs_gotenberg.webhook_configuration_registry'), service('request_stack'), service('twig')->nullOnInvalid(), service('router')->nullOnInvalid(), @@ -46,7 +46,7 @@ ->args([ service('sensiolabs_gotenberg.client'), service('sensiolabs_gotenberg.asset.base_dir_formatter'), - service('sensiolabs_gotenberg.webhook_configuration_registry'), + service('.sensiolabs_gotenberg.webhook_configuration_registry'), service('request_stack'), service('twig')->nullOnInvalid(), ]) diff --git a/config/services.php b/config/services.php index 382478b6..422b6e73 100644 --- a/config/services.php +++ b/config/services.php @@ -71,12 +71,11 @@ ->tag('kernel.event_listener', ['method' => 'streamBuilder', 'event' => 'kernel.view']) ; - $services->set('sensiolabs_gotenberg.webhook_configuration_registry', WebhookConfigurationRegistry::class) + $services->set('.sensiolabs_gotenberg.webhook_configuration_registry', WebhookConfigurationRegistry::class) ->args([ service('router'), service('.sensiolabs_gotenberg.request_context')->nullOnInvalid(), ]) - ->tag('sensiolabs_gotenberg.webhook_configuration_registry') - ->alias(WebhookConfigurationRegistryInterface::class, 'sensiolabs_gotenberg.webhook_configuration_registry') + ->alias(WebhookConfigurationRegistryInterface::class, '.sensiolabs_gotenberg.webhook_configuration_registry') ; }; diff --git a/src/DataCollector/GotenbergDataCollector.php b/src/DataCollector/GotenbergDataCollector.php index 99e44301..a047b679 100644 --- a/src/DataCollector/GotenbergDataCollector.php +++ b/src/DataCollector/GotenbergDataCollector.php @@ -87,6 +87,7 @@ private function lateCollectFiles(array $builders, string $type): void 'default_options' => $this->cloneVar($this->defaultOptions[$id] ?? []), ], 'type' => $type, + 'request_type' => $request['type'], 'time' => $request['time'], 'memory' => $request['memory'], 'size' => $this->formatSize($request['size'] ?? 0), diff --git a/src/Debug/Builder/TraceablePdfBuilder.php b/src/Debug/Builder/TraceablePdfBuilder.php index 5a19090b..318c45bf 100644 --- a/src/Debug/Builder/TraceablePdfBuilder.php +++ b/src/Debug/Builder/TraceablePdfBuilder.php @@ -10,7 +10,7 @@ final class TraceablePdfBuilder implements PdfBuilderInterface { /** - * @var list|null, 'fileName': string|null, 'calls': list, 'arguments': array}>}> + * @var list|null, 'fileName': string|null, 'calls': list, 'arguments': array}>}> */ private array $pdfs = []; @@ -39,6 +39,7 @@ public function generate(): GotenbergFileResult $swEvent?->stop(); $this->pdfs[] = [ + 'type' => 'sync', 'calls' => $this->calls, 'time' => $swEvent?->getDuration(), 'memory' => $swEvent?->getMemory(), @@ -65,6 +66,7 @@ public function generateAsync(): void $swEvent?->stop(); $this->pdfs[] = [ + 'type' => 'async', 'calls' => $this->calls, 'time' => $swEvent?->getDuration(), 'memory' => $swEvent?->getMemory(), @@ -96,7 +98,7 @@ public function __call(string $name, array $arguments): mixed } /** - * @return list|null, 'fileName': string|null, 'calls': list, 'method': string, 'arguments': array}>}> + * @return list|null, 'fileName': string|null, 'calls': list, 'method': string, 'arguments': array}>}> */ public function getFiles(): array { diff --git a/src/Debug/Builder/TraceableScreenshotBuilder.php b/src/Debug/Builder/TraceableScreenshotBuilder.php index ba2c99c4..fdedbaec 100644 --- a/src/Debug/Builder/TraceableScreenshotBuilder.php +++ b/src/Debug/Builder/TraceableScreenshotBuilder.php @@ -10,7 +10,7 @@ final class TraceableScreenshotBuilder implements ScreenshotBuilderInterface { /** - * @var list|null, 'fileName': string|null, 'calls': list, 'arguments': array}>}> + * @var list|null, 'fileName': string|null, 'calls': list, 'arguments': array}>}> */ private array $screenshots = []; @@ -39,6 +39,7 @@ public function generate(): GotenbergFileResult $swEvent?->stop(); $this->screenshots[] = [ + 'type' => 'sync', 'calls' => $this->calls, 'time' => $swEvent?->getDuration(), 'memory' => $swEvent?->getMemory(), @@ -66,6 +67,7 @@ public function generateAsync(): void $swEvent?->stop(); $this->screenshots[] = [ + 'type' => 'async', 'calls' => $this->calls, 'time' => $swEvent?->getDuration(), 'memory' => $swEvent?->getMemory(), @@ -97,7 +99,7 @@ public function __call(string $name, array $arguments): mixed } /** - * @return list|null, 'fileName': string|null, 'calls': list, 'method': string, 'arguments': array}>}> + * @return list|null, 'fileName': string|null, 'calls': list, 'method': string, 'arguments': array}>}> */ public function getFiles(): array { diff --git a/src/DependencyInjection/SensiolabsGotenbergExtension.php b/src/DependencyInjection/SensiolabsGotenbergExtension.php index bd1288d3..0ba0da28 100644 --- a/src/DependencyInjection/SensiolabsGotenbergExtension.php +++ b/src/DependencyInjection/SensiolabsGotenbergExtension.php @@ -21,7 +21,34 @@ public function load(array $configs, ContainerBuilder $container): void { $configuration = new Configuration(); - /** @var array{base_uri: string, http_client: string, controller_listener: bool, request_context?: array{base_uri?: string}, assets_directory: string, webhook: array, default_options: array{pdf: array{html: array, url: array, markdown: array, office: array, merge: array, convert: array}, screenshot: array{html: array, url: array, markdown: array}, webhook?: string}} $config */ + /** @var array{ + * base_uri: string, + * http_client: string, + * controller_listener: bool, + * request_context?: array{base_uri?: string}, + * assets_directory: string, + * webhook: array + * }>, + * default_options: array{ + * webhook?: string, + * pdf: array{ + * html: array, + * url: array, + * markdown: array, + * office: array, + * merge: array, + * convert: array + * }, + * screenshot: array{ + * html: array, + * url: array, + * markdown: array + * } + * } $config + */ $config = $this->processConfiguration($configuration, $configs); $loader = new PhpFileLoader($container, new FileLocator(__DIR__.'/../../config')); @@ -58,7 +85,6 @@ public function load(array $configs, ContainerBuilder $container): void $container->setAlias('sensiolabs_gotenberg.http_client', new Alias($config['http_client'], false)); $baseUri = $config['request_context']['base_uri'] ?? null; - $defaultWebhookConfig = $config['default_options']['webhook'] ?? null; if (null !== $baseUri) { $requestContextDefinition = new Definition(RequestContext::class); @@ -69,27 +95,27 @@ public function load(array $configs, ContainerBuilder $container): void } foreach ($config['webhook'] as $name => $configuration) { - $container->getDefinition('sensiolabs_gotenberg.webhook_configuration_registry') + $container->getDefinition('.sensiolabs_gotenberg.webhook_configuration_registry') ->addMethodCall('add', [$name, $configuration]); } - $this->processDefaultOptions('.sensiolabs_gotenberg.pdf_builder.html', $container, $config['default_options']['pdf']['html'], $defaultWebhookConfig); + $this->processDefaultOptions($container, $config, '.sensiolabs_gotenberg.pdf_builder.html', $config['default_options']['pdf']['html']); - $this->processDefaultOptions('.sensiolabs_gotenberg.pdf_builder.url', $container, $config['default_options']['pdf']['url'], $defaultWebhookConfig); + $this->processDefaultOptions($container, $config, '.sensiolabs_gotenberg.pdf_builder.url', $config['default_options']['pdf']['url']); - $this->processDefaultOptions('.sensiolabs_gotenberg.pdf_builder.markdown', $container, $config['default_options']['pdf']['markdown'], $defaultWebhookConfig); + $this->processDefaultOptions($container, $config, '.sensiolabs_gotenberg.pdf_builder.markdown', $config['default_options']['pdf']['markdown']); - $this->processDefaultOptions('.sensiolabs_gotenberg.pdf_builder.office', $container, $config['default_options']['pdf']['office'], $defaultWebhookConfig); + $this->processDefaultOptions($container, $config, '.sensiolabs_gotenberg.pdf_builder.office', $config['default_options']['pdf']['office']); - $this->processDefaultOptions('.sensiolabs_gotenberg.pdf_builder.merge', $container, $config['default_options']['pdf']['merge'], $defaultWebhookConfig); + $this->processDefaultOptions($container, $config, '.sensiolabs_gotenberg.pdf_builder.merge', $config['default_options']['pdf']['merge']); - $this->processDefaultOptions('.sensiolabs_gotenberg.pdf_builder.convert', $container, $config['default_options']['pdf']['convert'], $defaultWebhookConfig); + $this->processDefaultOptions($container, $config, '.sensiolabs_gotenberg.pdf_builder.convert', $config['default_options']['pdf']['convert']); - $this->processDefaultOptions('.sensiolabs_gotenberg.screenshot_builder.html', $container, $config['default_options']['screenshot']['html'], $defaultWebhookConfig); + $this->processDefaultOptions($container, $config, '.sensiolabs_gotenberg.screenshot_builder.html', $config['default_options']['screenshot']['html']); - $this->processDefaultOptions('.sensiolabs_gotenberg.screenshot_builder.url', $container, $config['default_options']['screenshot']['url'], $defaultWebhookConfig); + $this->processDefaultOptions($container, $config, '.sensiolabs_gotenberg.screenshot_builder.url', $config['default_options']['screenshot']['url']); - $this->processDefaultOptions('.sensiolabs_gotenberg.screenshot_builder.markdown', $container, $config['default_options']['screenshot']['markdown'], $defaultWebhookConfig); + $this->processDefaultOptions($container, $config, '.sensiolabs_gotenberg.screenshot_builder.markdown', $config['default_options']['screenshot']['markdown']); $definition = $container->getDefinition('sensiolabs_gotenberg.asset.base_dir_formatter'); $definition->replaceArgument(2, $config['assets_directory']); @@ -107,32 +133,43 @@ private function cleanUserOptions(array $userConfigurations): array }, \ARRAY_FILTER_USE_BOTH); } + private function processDefaultOptions(ContainerBuilder $container, array $config, string $serviceId, array $serviceConfig): void + { + $definition = $container->getDefinition($serviceId); + + $definition->addMethodCall('setConfigurations', [$this->cleanUserOptions($serviceConfig)]); + + $this->processWebhookOptions($container, $serviceId, $config['webhook'], $config['default_options']['webhook'] ?? null, $serviceConfig); + } + /** - * @param array $config + * @param array}> $webhookConfig */ - private function processDefaultOptions(string $serviceId, ContainerBuilder $container, array $config, string|null $defaultWebhookName): void + private function processWebhookOptions(ContainerBuilder $container, string $serviceId, array $webhookConfig, string|null $webhookDefaultConfigName, array $config): void { $definition = $container->getDefinition($serviceId); - $definition->addMethodCall('setConfigurations', [$this->cleanUserOptions($config)]); - $webhookConfig = $config['webhook'] ?? null; - if (null === $webhookConfig && null === $defaultWebhookName) { - return; - } + $serviceWebhookConfig = $config['webhook'] ?? []; + $webhookConfigName = $serviceWebhookConfig['config_name'] ?? $webhookDefaultConfigName ?? null; + unset($serviceWebhookConfig['config_name']); - if (null !== $defaultWebhookName) { - $definition->addMethodCall('webhookConfiguration', [$defaultWebhookName], true); + if ([] !== $serviceWebhookConfig && ['extra_http_headers' => []] !== $serviceWebhookConfig) { + $webhookConfig = array_merge($webhookConfig[$webhookConfigName] ?? [], $serviceWebhookConfig); - return; + $webhookConfigName = ltrim($serviceId, '.'); + $webhookConfigName = ".{$webhookConfigName}.webhook_configuration"; + + $registryDefinition = $container->getDefinition('.sensiolabs_gotenberg.webhook_configuration_registry'); + $registryDefinition->addMethodCall('add', [ + $webhookConfigName, + $webhookConfig, + ]); } - if (\array_key_exists('config_name', $webhookConfig) && \is_string($webhookConfig['config_name'])) { - $name = $webhookConfig['config_name']; - } else { - $name = $serviceId.'_webhook_config'; - $container->getDefinition('sensiolabs_gotenberg.webhook_configuration_registry') - ->addMethodCall('add', [$name, $webhookConfig]); + if (null === $webhookConfigName) { + return; } - $definition->addMethodCall('webhookConfiguration', [$name], true); + + $definition->addMethodCall('webhookConfiguration', [$webhookConfigName]); } } diff --git a/templates/Collector/sensiolabs_gotenberg.html.twig b/templates/Collector/sensiolabs_gotenberg.html.twig index f239df90..2156a138 100644 --- a/templates/Collector/sensiolabs_gotenberg.html.twig +++ b/templates/Collector/sensiolabs_gotenberg.html.twig @@ -102,13 +102,16 @@ {% for index, file in collector.files %} - - {% if file.type == 'pdf' %} - {{ source('@SensiolabsGotenberg/Icon/file-type-pdf.svg') }} - {% elseif file.type == 'screenshot' %} - {{ source('@SensiolabsGotenberg/Icon/file-type-screenshot.svg') }} - {% endif %} - + + {% if file.type == 'pdf' %} + {{ source('@SensiolabsGotenberg/Icon/file-type-pdf.svg') }} + {% elseif file.type == 'screenshot' %} + {{ source('@SensiolabsGotenberg/Icon/file-type-screenshot.svg') }} + {% endif %} + + + {{ source('@SensiolabsGotenberg/Icon/file-' ~ file.request_type ~ '.svg') }} + {{ file.fileName }} diff --git a/templates/Icon/file-async.svg b/templates/Icon/file-async.svg new file mode 100644 index 00000000..b4a49c3a --- /dev/null +++ b/templates/Icon/file-async.svg @@ -0,0 +1 @@ +Async diff --git a/templates/Icon/file-sync.svg b/templates/Icon/file-sync.svg new file mode 100644 index 00000000..9c704b8f --- /dev/null +++ b/templates/Icon/file-sync.svg @@ -0,0 +1 @@ +Sync diff --git a/tests/DependencyInjection/SensiolabsGotenbergExtensionTest.php b/tests/DependencyInjection/SensiolabsGotenbergExtensionTest.php index 9769eb6c..5a55ebd1 100644 --- a/tests/DependencyInjection/SensiolabsGotenbergExtensionTest.php +++ b/tests/DependencyInjection/SensiolabsGotenbergExtensionTest.php @@ -415,7 +415,7 @@ public function testBuilderWebhookConfiguredWithDefaultConfiguration(): void $containerBuilder = $this->getContainerBuilder(); $extension->load([['http_client' => 'http_client']], $containerBuilder); - self::assertEmpty($containerBuilder->getDefinition('sensiolabs_gotenberg.webhook_configuration_registry')->getMethodCalls()); + self::assertEmpty($containerBuilder->getDefinition('.sensiolabs_gotenberg.webhook_configuration_registry')->getMethodCalls()); $buildersIds = [ '.sensiolabs_gotenberg.pdf_builder.html', @@ -463,7 +463,7 @@ public function testBuilderWebhookConfiguredWithValidConfiguration(): void $expectedConfigurationMapping = [ '.sensiolabs_gotenberg.pdf_builder.html' => 'bar', '.sensiolabs_gotenberg.pdf_builder.url' => 'baz', - '.sensiolabs_gotenberg.pdf_builder.markdown' => '.sensiolabs_gotenberg.pdf_builder.markdown_webhook_config', + '.sensiolabs_gotenberg.pdf_builder.markdown' => '.sensiolabs_gotenberg.pdf_builder.markdown.webhook_configuration', '.sensiolabs_gotenberg.pdf_builder.office' => 'foo', '.sensiolabs_gotenberg.screenshot_builder.html' => 'foo', '.sensiolabs_gotenberg.screenshot_builder.url' => 'bar', @@ -473,20 +473,20 @@ public function testBuilderWebhookConfiguredWithValidConfiguration(): void foreach ($containerBuilder->getDefinition($builderId)->getMethodCalls() as $methodCall) { [$name, $arguments] = $methodCall; if ('webhookConfiguration' === $name) { - self::assertSame($expectedConfigurationName, $arguments[0]); + self::assertSame($expectedConfigurationName, $arguments[0], "Wrong expected configuration for builder '{$builderId}'."); return; } } }, array_keys($expectedConfigurationMapping), array_values($expectedConfigurationMapping)); - $webhookConfigurationRegistryDefinition = $containerBuilder->getDefinition('sensiolabs_gotenberg.webhook_configuration_registry'); + $webhookConfigurationRegistryDefinition = $containerBuilder->getDefinition('.sensiolabs_gotenberg.webhook_configuration_registry'); $methodCalls = $webhookConfigurationRegistryDefinition->getMethodCalls(); self::assertCount(3, $methodCalls); foreach ($methodCalls as $methodCall) { [$name, $arguments] = $methodCall; self::assertSame('add', $name); - self::assertContains($arguments[0], ['foo', 'baz', '.sensiolabs_gotenberg.pdf_builder.markdown_webhook_config']); + self::assertContains($arguments[0], ['foo', 'baz', '.sensiolabs_gotenberg.pdf_builder.markdown.webhook_configuration']); self::assertSame(match ($arguments[0]) { 'foo' => [ 'success' => [ @@ -506,15 +506,19 @@ public function testBuilderWebhookConfiguredWithValidConfiguration(): void ], 'extra_http_headers' => [], ], - '.sensiolabs_gotenberg.pdf_builder.markdown_webhook_config' => [ + '.sensiolabs_gotenberg.pdf_builder.markdown.webhook_configuration' => [ 'success' => [ 'url' => 'https://sensiolabs.com/webhook-on-the-fly', 'method' => null, ], + 'error' => [ + 'route' => ['simple_route', []], + 'method' => null, + ], 'extra_http_headers' => [], ], default => self::fail('Unexpected webhook configuration'), - }, $arguments[1]); + }, $arguments[1], "Configuration mismatch for webhook '{$arguments[0]}'."); } } From ebb4656fbd7ab8a866bf12c180292681a96c20ea Mon Sep 17 00:00:00 2001 From: Adrien Roches Date: Fri, 15 Nov 2024 21:12:34 +0100 Subject: [PATCH 17/24] [Update] a few things --- .gitignore | 1 + docs/pdf/builders_api/ConvertPdfBuilder.md | 3 -- docs/pdf/builders_api/HtmlPdfBuilder.md | 3 -- .../pdf/builders_api/LibreOfficePdfBuilder.md | 3 -- docs/pdf/builders_api/MarkdownPdfBuilder.md | 3 -- docs/pdf/builders_api/MergePdfBuilder.md | 3 -- docs/pdf/builders_api/UrlPdfBuilder.md | 3 -- .../builders_api/HtmlScreenshotBuilder.md | 3 -- .../builders_api/MarkdownScreenshotBuilder.md | 3 -- .../builders_api/UrlScreenshotBuilder.md | 3 -- phpstan.neon => phpstan.dist.neon | 0 src/Builder/AsyncBuilderTrait.php | 30 +++++++------------ .../SensiolabsGotenbergExtension.php | 3 +- 13 files changed, 13 insertions(+), 48 deletions(-) rename phpstan.neon => phpstan.dist.neon (100%) diff --git a/.gitignore b/.gitignore index 1a16dd58..f32bcb1e 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,4 @@ .php-cs-fixer.cache .phpunit.result.cache composer.lock +phpstan.neon diff --git a/docs/pdf/builders_api/ConvertPdfBuilder.md b/docs/pdf/builders_api/ConvertPdfBuilder.md index 0c49bf7a..c507ac59 100644 --- a/docs/pdf/builders_api/ConvertPdfBuilder.md +++ b/docs/pdf/builders_api/ConvertPdfBuilder.md @@ -21,9 +21,6 @@ Optionaly sets a custom HTTP method for such endpoint among : POST, PUT or PATCH Sets the webhook for cases of error. Optionaly sets a custom HTTP method for such endpoint among : POST, PUT or PATCH. -* `webhookUrls(string $successWebhook, ?string $errorWebhook, ?string $successMethod, ?string $errorMethod)`: -Allows to set both $successWebhook and $errorWebhook URLs. If $errorWebhook is not provided, it will fallback to $successWebhook one. - * `webhookExtraHeaders(array $extraHeaders)`: Extra headers that will be provided to the webhook endpoint. May it either be Success or Error. diff --git a/docs/pdf/builders_api/HtmlPdfBuilder.md b/docs/pdf/builders_api/HtmlPdfBuilder.md index bea69e5e..b9f22407 100644 --- a/docs/pdf/builders_api/HtmlPdfBuilder.md +++ b/docs/pdf/builders_api/HtmlPdfBuilder.md @@ -140,9 +140,6 @@ Optionaly sets a custom HTTP method for such endpoint among : POST, PUT or PATCH Sets the webhook for cases of error. Optionaly sets a custom HTTP method for such endpoint among : POST, PUT or PATCH. -* `webhookUrls(string $successWebhook, ?string $errorWebhook, ?string $successMethod, ?string $errorMethod)`: -Allows to set both $successWebhook and $errorWebhook URLs. If $errorWebhook is not provided, it will fallback to $successWebhook one. - * `webhookExtraHeaders(array $extraHeaders)`: Extra headers that will be provided to the webhook endpoint. May it either be Success or Error. diff --git a/docs/pdf/builders_api/LibreOfficePdfBuilder.md b/docs/pdf/builders_api/LibreOfficePdfBuilder.md index c27100ea..d4570045 100644 --- a/docs/pdf/builders_api/LibreOfficePdfBuilder.md +++ b/docs/pdf/builders_api/LibreOfficePdfBuilder.md @@ -98,9 +98,6 @@ Optionaly sets a custom HTTP method for such endpoint among : POST, PUT or PATCH Sets the webhook for cases of error. Optionaly sets a custom HTTP method for such endpoint among : POST, PUT or PATCH. -* `webhookUrls(string $successWebhook, ?string $errorWebhook, ?string $successMethod, ?string $errorMethod)`: -Allows to set both $successWebhook and $errorWebhook URLs. If $errorWebhook is not provided, it will fallback to $successWebhook one. - * `webhookExtraHeaders(array $extraHeaders)`: Extra headers that will be provided to the webhook endpoint. May it either be Success or Error. diff --git a/docs/pdf/builders_api/MarkdownPdfBuilder.md b/docs/pdf/builders_api/MarkdownPdfBuilder.md index 47ea0711..ce31f9c8 100644 --- a/docs/pdf/builders_api/MarkdownPdfBuilder.md +++ b/docs/pdf/builders_api/MarkdownPdfBuilder.md @@ -143,9 +143,6 @@ Optionaly sets a custom HTTP method for such endpoint among : POST, PUT or PATCH Sets the webhook for cases of error. Optionaly sets a custom HTTP method for such endpoint among : POST, PUT or PATCH. -* `webhookUrls(string $successWebhook, ?string $errorWebhook, ?string $successMethod, ?string $errorMethod)`: -Allows to set both $successWebhook and $errorWebhook URLs. If $errorWebhook is not provided, it will fallback to $successWebhook one. - * `webhookExtraHeaders(array $extraHeaders)`: Extra headers that will be provided to the webhook endpoint. May it either be Success or Error. diff --git a/docs/pdf/builders_api/MergePdfBuilder.md b/docs/pdf/builders_api/MergePdfBuilder.md index db2a32f6..477c8815 100644 --- a/docs/pdf/builders_api/MergePdfBuilder.md +++ b/docs/pdf/builders_api/MergePdfBuilder.md @@ -29,9 +29,6 @@ Optionaly sets a custom HTTP method for such endpoint among : POST, PUT or PATCH Sets the webhook for cases of error. Optionaly sets a custom HTTP method for such endpoint among : POST, PUT or PATCH. -* `webhookUrls(string $successWebhook, ?string $errorWebhook, ?string $successMethod, ?string $errorMethod)`: -Allows to set both $successWebhook and $errorWebhook URLs. If $errorWebhook is not provided, it will fallback to $successWebhook one. - * `webhookExtraHeaders(array $extraHeaders)`: Extra headers that will be provided to the webhook endpoint. May it either be Success or Error. diff --git a/docs/pdf/builders_api/UrlPdfBuilder.md b/docs/pdf/builders_api/UrlPdfBuilder.md index 30d74ae3..22219eea 100644 --- a/docs/pdf/builders_api/UrlPdfBuilder.md +++ b/docs/pdf/builders_api/UrlPdfBuilder.md @@ -142,9 +142,6 @@ Optionaly sets a custom HTTP method for such endpoint among : POST, PUT or PATCH Sets the webhook for cases of error. Optionaly sets a custom HTTP method for such endpoint among : POST, PUT or PATCH. -* `webhookUrls(string $successWebhook, ?string $errorWebhook, ?string $successMethod, ?string $errorMethod)`: -Allows to set both $successWebhook and $errorWebhook URLs. If $errorWebhook is not provided, it will fallback to $successWebhook one. - * `webhookExtraHeaders(array $extraHeaders)`: Extra headers that will be provided to the webhook endpoint. May it either be Success or Error. diff --git a/docs/screenshot/builders_api/HtmlScreenshotBuilder.md b/docs/screenshot/builders_api/HtmlScreenshotBuilder.md index a3b678ae..8a87f455 100644 --- a/docs/screenshot/builders_api/HtmlScreenshotBuilder.md +++ b/docs/screenshot/builders_api/HtmlScreenshotBuilder.md @@ -85,9 +85,6 @@ Optionaly sets a custom HTTP method for such endpoint among : POST, PUT or PATCH Sets the webhook for cases of error. Optionaly sets a custom HTTP method for such endpoint among : POST, PUT or PATCH. -* `webhookUrls(string $successWebhook, ?string $errorWebhook, ?string $successMethod, ?string $errorMethod)`: -Allows to set both $successWebhook and $errorWebhook URLs. If $errorWebhook is not provided, it will fallback to $successWebhook one. - * `webhookExtraHeaders(array $extraHeaders)`: Extra headers that will be provided to the webhook endpoint. May it either be Success or Error. diff --git a/docs/screenshot/builders_api/MarkdownScreenshotBuilder.md b/docs/screenshot/builders_api/MarkdownScreenshotBuilder.md index 5180bb8b..3f7df2e1 100644 --- a/docs/screenshot/builders_api/MarkdownScreenshotBuilder.md +++ b/docs/screenshot/builders_api/MarkdownScreenshotBuilder.md @@ -88,9 +88,6 @@ Optionaly sets a custom HTTP method for such endpoint among : POST, PUT or PATCH Sets the webhook for cases of error. Optionaly sets a custom HTTP method for such endpoint among : POST, PUT or PATCH. -* `webhookUrls(string $successWebhook, ?string $errorWebhook, ?string $successMethod, ?string $errorMethod)`: -Allows to set both $successWebhook and $errorWebhook URLs. If $errorWebhook is not provided, it will fallback to $successWebhook one. - * `webhookExtraHeaders(array $extraHeaders)`: Extra headers that will be provided to the webhook endpoint. May it either be Success or Error. diff --git a/docs/screenshot/builders_api/UrlScreenshotBuilder.md b/docs/screenshot/builders_api/UrlScreenshotBuilder.md index 3eb4deb2..09185dcd 100644 --- a/docs/screenshot/builders_api/UrlScreenshotBuilder.md +++ b/docs/screenshot/builders_api/UrlScreenshotBuilder.md @@ -87,9 +87,6 @@ Optionaly sets a custom HTTP method for such endpoint among : POST, PUT or PATCH Sets the webhook for cases of error. Optionaly sets a custom HTTP method for such endpoint among : POST, PUT or PATCH. -* `webhookUrls(string $successWebhook, ?string $errorWebhook, ?string $successMethod, ?string $errorMethod)`: -Allows to set both $successWebhook and $errorWebhook URLs. If $errorWebhook is not provided, it will fallback to $successWebhook one. - * `webhookExtraHeaders(array $extraHeaders)`: Extra headers that will be provided to the webhook endpoint. May it either be Success or Error. diff --git a/phpstan.neon b/phpstan.dist.neon similarity index 100% rename from phpstan.neon rename to phpstan.dist.neon diff --git a/src/Builder/AsyncBuilderTrait.php b/src/Builder/AsyncBuilderTrait.php index 5500e5ee..df074c77 100644 --- a/src/Builder/AsyncBuilderTrait.php +++ b/src/Builder/AsyncBuilderTrait.php @@ -69,12 +69,16 @@ public function webhookConfiguration(string $name): static { $webhookConfiguration = $this->webhookConfigurationRegistry->get($name); - $result = $this->webhookUrls( - $webhookConfiguration['success']['url'], - $webhookConfiguration['error']['url'], - $webhookConfiguration['success']['method'], - $webhookConfiguration['error']['method'], - ); + $result = $this + ->webhookUrl( + $webhookConfiguration['success']['url'], + $webhookConfiguration['error']['url'], + ) + ->errorWebhookUrl( + $webhookConfiguration['error']['url'], + $webhookConfiguration['error']['method'], + ) + ; if (\array_key_exists('extra_http_headers', $webhookConfiguration)) { $result = $result->webhookExtraHeaders($webhookConfiguration['extra_http_headers']); @@ -115,20 +119,6 @@ public function errorWebhookUrl(string|null $url = null, string|null $method = n return $this; } - /** - * Allows to set both $successWebhook and $errorWebhook URLs. If $errorWebhook is not provided, it will fallback to $successWebhook one. - * - * @param 'POST'|'PATCH'|'PUT'|null $successMethod - * @param 'POST'|'PATCH'|'PUT'|null $errorMethod - */ - public function webhookUrls(string $successWebhook, string|null $errorWebhook = null, string|null $successMethod = null, string|null $errorMethod = null): static - { - return $this - ->webhookUrl($successWebhook, $successMethod) - ->errorWebhookUrl($errorWebhook, $errorMethod) - ; - } - /** * Extra headers that will be provided to the webhook endpoint. May it either be Success or Error. * diff --git a/src/DependencyInjection/SensiolabsGotenbergExtension.php b/src/DependencyInjection/SensiolabsGotenbergExtension.php index 0ba0da28..5863bbfc 100644 --- a/src/DependencyInjection/SensiolabsGotenbergExtension.php +++ b/src/DependencyInjection/SensiolabsGotenbergExtension.php @@ -47,7 +47,8 @@ public function load(array $configs, ContainerBuilder $container): void * url: array, * markdown: array * } - * } $config + * } + * } $config */ $config = $this->processConfiguration($configuration, $configs); From 0f00fdfe8f062d16eb155edf27c9fe40b7a6d910 Mon Sep 17 00:00:00 2001 From: Adrien Roches Date: Fri, 15 Nov 2024 21:29:09 +0100 Subject: [PATCH 18/24] fix typo --- src/Builder/AsyncBuilderTrait.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Builder/AsyncBuilderTrait.php b/src/Builder/AsyncBuilderTrait.php index df074c77..8d53b3d5 100644 --- a/src/Builder/AsyncBuilderTrait.php +++ b/src/Builder/AsyncBuilderTrait.php @@ -72,7 +72,7 @@ public function webhookConfiguration(string $name): static $result = $this ->webhookUrl( $webhookConfiguration['success']['url'], - $webhookConfiguration['error']['url'], + $webhookConfiguration['error']['method'], ) ->errorWebhookUrl( $webhookConfiguration['error']['url'], From ee72e1290bec8886d5666fcb34222c14604c85a8 Mon Sep 17 00:00:00 2001 From: Adrien Roches Date: Fri, 15 Nov 2024 21:31:08 +0100 Subject: [PATCH 19/24] fix typo --- src/Builder/AsyncBuilderTrait.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Builder/AsyncBuilderTrait.php b/src/Builder/AsyncBuilderTrait.php index 8d53b3d5..23fa3c96 100644 --- a/src/Builder/AsyncBuilderTrait.php +++ b/src/Builder/AsyncBuilderTrait.php @@ -72,7 +72,7 @@ public function webhookConfiguration(string $name): static $result = $this ->webhookUrl( $webhookConfiguration['success']['url'], - $webhookConfiguration['error']['method'], + $webhookConfiguration['success']['method'], ) ->errorWebhookUrl( $webhookConfiguration['error']['url'], From eb474ad0426c36106bc99d2d33dd114f294b5416 Mon Sep 17 00:00:00 2001 From: Adrien Roches Date: Sat, 16 Nov 2024 09:29:53 +0100 Subject: [PATCH 20/24] Add documentation for webhook --- docs/configuration.md | 1268 ++++++++++++++++++--- src/DependencyInjection/Configuration.php | 11 +- 2 files changed, 1094 insertions(+), 185 deletions(-) diff --git a/docs/configuration.md b/docs/configuration.md index e34802c1..b6cc90da 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -24,210 +24,1103 @@ Then ```yaml # app/config/sensiolabs_gotenberg.yaml +# Default configuration for extension with alias: "sensiolabs_gotenberg" sensiolabs_gotenberg: - assets_directory: '%kernel.project_dir%/assets' - controller_listener: true # Will convert any GotenbergFileResult to stream automatically as a controller return. - http_client: 'gotenberg.client' # Required and must have a `base_uri`. + + # Base directory will be used for assets, files, markdown + assets_directory: '%kernel.project_dir%/assets' + + # HTTP Client reference to use. (Must have a base_uri) + http_client: ~ # Required + # Override the request Gotenberg will make to call one of your routes. request_context: + # Used only when using `->route()`. Overrides the guessed `base_url` from the request. May be useful in CLI. - base_uri: null # None + base_uri: ~ + + # Enables the listener on kernel.view to stream GotenbergFileResult object. + controller_listener: true + webhook: + + # Prototype + name: + name: ~ + success: + + # The URL to call. + url: ~ + + # Route configuration. + route: ~ + + # HTTP method to use on that endpoint. + method: null # One of "POST"; "PUT"; "PATCH" + error: + + # The URL to call. + url: ~ + + # Route configuration. + route: ~ + + # HTTP method to use on that endpoint. + method: null # One of "POST"; "PUT"; "PATCH" + + # HTTP headers to send by Chromium while loading the HTML document - default None. https://gotenberg.dev/docs/routes#custom-http-headers + extra_http_headers: + + # Prototype + name: + name: ~ + value: ~ default_options: + + # Webhook configuration name. + webhook: ~ pdf: html: + + # Add default header to the builder. header: - template: null # None - context: null # None + + # Default header twig template to apply. + template: null + + # Default context for header twig template. + context: [] + + # Add default footer to the builder. footer: - template: null # None - context: null # None - single_page: null # false - paper_standard_size: null # None - paper_width: null # 8.5 - paper_height: null # 11 - margin_top: null # 0.39 - margin_bottom: null # 0.39 - margin_left: null # 0.39 - margin_right: null # 0.39 - prefer_css_page_size: null # false - print_background: null # false - omit_background: null # false - landscape: null # false - scale: null # 1.0 - native_page_ranges: null # All pages - wait_delay: null # None - wait_for_expression: null # None - emulated_media_type: null # 'print' - cookies: null # None - user_agent: null # None - extra_http_headers: null # None - fail_on_http_status_codes: null # [499-599] - fail_on_console_exceptions: null # false - skip_network_idle_event: null # false - pdf_format: null # None - pdf_universal_access: null # false - metadata: null # None - download_from: null # None + + # Default footer twig template to apply. + template: null + + # Default context for footer twig template. + context: [] + + # Define whether to print the entire content in one single page. - default false. https://gotenberg.dev/docs/routes#page-properties-chromium + single_page: null + + # The standard paper size to use, either "letter", "legal", "tabloid", "ledger", "A0", "A1", "A2", "A3", "A4", "A5", "A6" - default None. + paper_standard_size: null # One of "letter"; "legal"; "tabloid"; "ledger"; "A0"; "A1"; "A2"; "A3"; "A4"; "A5"; "A6" + + # Paper width, in inches - default 8.5. https://gotenberg.dev/docs/routes#page-properties-chromium + paper_width: null + + # Paper height, in inches - default 11. https://gotenberg.dev/docs/routes#page-properties-chromium + paper_height: null + + # Top margin, in inches - default 0.39. https://gotenberg.dev/docs/routes#page-properties-chromium + margin_top: null + + # Bottom margin, in inches - default 0.39. https://gotenberg.dev/docs/routes#page-properties-chromium + margin_bottom: null + + # Left margin, in inches - default 0.39. https://gotenberg.dev/docs/routes#page-properties-chromium + margin_left: null + + # Right margin, in inches - default 0.39. https://gotenberg.dev/docs/routes#page-properties-chromium + margin_right: null + + # Define whether to prefer page size as defined by CSS - default false. https://gotenberg.dev/docs/routes#page-properties-chromium + prefer_css_page_size: null + + # Print the background graphics - default false. https://gotenberg.dev/docs/routes#page-properties-chromium + print_background: null + + # Hide the default white background and allow generating PDFs with transparency - default false. https://gotenberg.dev/docs/routes#page-properties-chromium + omit_background: null + + # The paper orientation to landscape - default false. https://gotenberg.dev/docs/routes#page-properties-chromium + landscape: null + + # The scale of the page rendering (e.g., 1.0) - default 1.0. https://gotenberg.dev/docs/routes#page-properties-chromium + scale: null + + # Page ranges to print, e.g., "1-5, 8, 11-13" - default All pages. https://gotenberg.dev/docs/routes#page-properties-chromium + native_page_ranges: null + + # Duration (e.g, "5s") to wait when loading an HTML document before converting it into PDF - default None. https://gotenberg.dev/docs/routes#wait-before-rendering + wait_delay: null + + # The JavaScript expression to wait before converting an HTML document into PDF until it returns true - default None. https://gotenberg.dev/docs/routes#wait-before-rendering + wait_for_expression: null + + # The media type to emulate, either "screen" or "print" - default "print". https://gotenberg.dev/docs/routes#emulated-media-type + emulated_media_type: null # One of "print"; "screen" + + # Cookies to store in the Chromium cookie jar - default None. https://gotenberg.dev/docs/routes#cookies-chromium + cookies: + + # Prototype + - + name: ~ + value: ~ + domain: ~ + path: null + secure: null + httpOnly: null + + # Accepted values are "Strict", "Lax" or "None". https://gotenberg.dev/docs/routes#cookies-chromium + sameSite: null # One of "Strict"; "Lax"; "None" + + # Override the default User-Agent HTTP header. - default None. https://gotenberg.dev/docs/routes#custom-http-headers-chromium + user_agent: null + + # HTTP headers to send by Chromium while loading the HTML document - default None. https://gotenberg.dev/docs/routes#custom-http-headers + extra_http_headers: + + # Prototype + name: + name: ~ + value: ~ + + # Return a 409 Conflict response if the HTTP status code from the main page is not acceptable. - default [499,599]. https://gotenberg.dev/docs/routes#invalid-http-status-codes-chromium + fail_on_http_status_codes: + + # Defaults: + - 499 + - 599 + + # Return a 409 Conflict response if there are exceptions in the Chromium console - default false. https://gotenberg.dev/docs/routes#console-exceptions + fail_on_console_exceptions: null + + # Do not wait for Chromium network to be idle. - default false. https://gotenberg.dev/docs/routes#performance-mode-chromium + skip_network_idle_event: null + + # The metadata to write. Not all metadata are writable. Consider taking a look at https://exiftool.org/TagNames/XMP.html#pdf for an (exhaustive?) list of available metadata. + metadata: + Author: ~ + Copyright: ~ + CreationDate: ~ + Creator: ~ + Keywords: ~ + Marked: ~ + ModDate: ~ + PDFVersion: ~ + Producer: ~ + Subject: ~ + Title: ~ + Trapped: ~ # One of "True"; "False"; "Unknown" + + # URLs to download files from (JSON format). - default None. https://gotenberg.dev/docs/routes#download-from + download_from: + + # Prototype + - + url: ~ + extraHttpHeaders: + + # Prototype + name: + name: ~ + value: ~ + + # Convert PDF into the given PDF/A format - default None. + pdf_format: null # One of "PDF\/A-1b"; "PDF\/A-2b"; "PDF\/A-3b" + + # Enable PDF for Universal Access for optimal accessibility - default false. + pdf_universal_access: null + + # Webhook configuration name or definition. + webhook: + + # The name of the webhook configuration to use. + config_name: ~ + success: + + # The URL to call. + url: ~ + + # Route configuration. + route: ~ + + # HTTP method to use on that endpoint. + method: null # One of "POST"; "PUT"; "PATCH" + error: + + # The URL to call. + url: ~ + + # Route configuration. + route: ~ + + # HTTP method to use on that endpoint. + method: null # One of "POST"; "PUT"; "PATCH" + + # HTTP headers to send by Chromium while loading the HTML document - default None. https://gotenberg.dev/docs/routes#custom-http-headers + extra_http_headers: + + # Prototype + name: + name: ~ + value: ~ url: + + # Add default header to the builder. header: - template: null # None - context: null # None + + # Default header twig template to apply. + template: null + + # Default context for header twig template. + context: [] + + # Add default footer to the builder. footer: - template: null # None - context: null # None - single_page: null # false - paper_standard_size: null # None - paper_width: null # 8.5 - paper_height: null # 11 - margin_top: null # 0.39 - margin_bottom: null # 0.39 - margin_left: null # 0.39 - margin_right: null # 0.39 - prefer_css_page_size: null # false - print_background: null # false - omit_background: null # false - landscape: null # false - scale: null # 1.0 - native_page_ranges: null # All pages - wait_delay: null # None - wait_for_expression: null # None - emulated_media_type: null # 'print' - cookies: null # None - user_agent: null # None - extra_http_headers: null # None - fail_on_http_status_codes: null # [499-599] - fail_on_console_exceptions: null # false - skip_network_idle_event: null # false - pdf_format: null # None - pdf_universal_access: null # false - metadata: null # None - download_from: null # None + + # Default footer twig template to apply. + template: null + + # Default context for footer twig template. + context: [] + + # Define whether to print the entire content in one single page. - default false. https://gotenberg.dev/docs/routes#page-properties-chromium + single_page: null + + # The standard paper size to use, either "letter", "legal", "tabloid", "ledger", "A0", "A1", "A2", "A3", "A4", "A5", "A6" - default None. + paper_standard_size: null # One of "letter"; "legal"; "tabloid"; "ledger"; "A0"; "A1"; "A2"; "A3"; "A4"; "A5"; "A6" + + # Paper width, in inches - default 8.5. https://gotenberg.dev/docs/routes#page-properties-chromium + paper_width: null + + # Paper height, in inches - default 11. https://gotenberg.dev/docs/routes#page-properties-chromium + paper_height: null + + # Top margin, in inches - default 0.39. https://gotenberg.dev/docs/routes#page-properties-chromium + margin_top: null + + # Bottom margin, in inches - default 0.39. https://gotenberg.dev/docs/routes#page-properties-chromium + margin_bottom: null + + # Left margin, in inches - default 0.39. https://gotenberg.dev/docs/routes#page-properties-chromium + margin_left: null + + # Right margin, in inches - default 0.39. https://gotenberg.dev/docs/routes#page-properties-chromium + margin_right: null + + # Define whether to prefer page size as defined by CSS - default false. https://gotenberg.dev/docs/routes#page-properties-chromium + prefer_css_page_size: null + + # Print the background graphics - default false. https://gotenberg.dev/docs/routes#page-properties-chromium + print_background: null + + # Hide the default white background and allow generating PDFs with transparency - default false. https://gotenberg.dev/docs/routes#page-properties-chromium + omit_background: null + + # The paper orientation to landscape - default false. https://gotenberg.dev/docs/routes#page-properties-chromium + landscape: null + + # The scale of the page rendering (e.g., 1.0) - default 1.0. https://gotenberg.dev/docs/routes#page-properties-chromium + scale: null + + # Page ranges to print, e.g., "1-5, 8, 11-13" - default All pages. https://gotenberg.dev/docs/routes#page-properties-chromium + native_page_ranges: null + + # Duration (e.g, "5s") to wait when loading an HTML document before converting it into PDF - default None. https://gotenberg.dev/docs/routes#wait-before-rendering + wait_delay: null + + # The JavaScript expression to wait before converting an HTML document into PDF until it returns true - default None. https://gotenberg.dev/docs/routes#wait-before-rendering + wait_for_expression: null + + # The media type to emulate, either "screen" or "print" - default "print". https://gotenberg.dev/docs/routes#emulated-media-type + emulated_media_type: null # One of "print"; "screen" + + # Cookies to store in the Chromium cookie jar - default None. https://gotenberg.dev/docs/routes#cookies-chromium + cookies: + + # Prototype + - + name: ~ + value: ~ + domain: ~ + path: null + secure: null + httpOnly: null + + # Accepted values are "Strict", "Lax" or "None". https://gotenberg.dev/docs/routes#cookies-chromium + sameSite: null # One of "Strict"; "Lax"; "None" + + # Override the default User-Agent HTTP header. - default None. https://gotenberg.dev/docs/routes#custom-http-headers-chromium + user_agent: null + + # HTTP headers to send by Chromium while loading the HTML document - default None. https://gotenberg.dev/docs/routes#custom-http-headers + extra_http_headers: + + # Prototype + name: + name: ~ + value: ~ + + # Return a 409 Conflict response if the HTTP status code from the main page is not acceptable. - default [499,599]. https://gotenberg.dev/docs/routes#invalid-http-status-codes-chromium + fail_on_http_status_codes: + + # Defaults: + - 499 + - 599 + + # Return a 409 Conflict response if there are exceptions in the Chromium console - default false. https://gotenberg.dev/docs/routes#console-exceptions + fail_on_console_exceptions: null + + # Do not wait for Chromium network to be idle. - default false. https://gotenberg.dev/docs/routes#performance-mode-chromium + skip_network_idle_event: null + + # The metadata to write. Not all metadata are writable. Consider taking a look at https://exiftool.org/TagNames/XMP.html#pdf for an (exhaustive?) list of available metadata. + metadata: + Author: ~ + Copyright: ~ + CreationDate: ~ + Creator: ~ + Keywords: ~ + Marked: ~ + ModDate: ~ + PDFVersion: ~ + Producer: ~ + Subject: ~ + Title: ~ + Trapped: ~ # One of "True"; "False"; "Unknown" + + # URLs to download files from (JSON format). - default None. https://gotenberg.dev/docs/routes#download-from + download_from: + + # Prototype + - + url: ~ + extraHttpHeaders: + + # Prototype + name: + name: ~ + value: ~ + + # Convert PDF into the given PDF/A format - default None. + pdf_format: null # One of "PDF\/A-1b"; "PDF\/A-2b"; "PDF\/A-3b" + + # Enable PDF for Universal Access for optimal accessibility - default false. + pdf_universal_access: null + + # Webhook configuration name or definition. + webhook: + + # The name of the webhook configuration to use. + config_name: ~ + success: + + # The URL to call. + url: ~ + + # Route configuration. + route: ~ + + # HTTP method to use on that endpoint. + method: null # One of "POST"; "PUT"; "PATCH" + error: + + # The URL to call. + url: ~ + + # Route configuration. + route: ~ + + # HTTP method to use on that endpoint. + method: null # One of "POST"; "PUT"; "PATCH" + + # HTTP headers to send by Chromium while loading the HTML document - default None. https://gotenberg.dev/docs/routes#custom-http-headers + extra_http_headers: + + # Prototype + name: + name: ~ + value: ~ markdown: + + # Add default header to the builder. header: - template: null # None - context: null # None + + # Default header twig template to apply. + template: null + + # Default context for header twig template. + context: [] + + # Add default footer to the builder. footer: - template: null # None - context: null # None - single_page: null # false - paper_standard_size: null # None - paper_width: null # 8.5 - paper_height: null # 11 - margin_top: null # 0.39 - margin_bottom: null # 0.39 - margin_left: null # 0.39 - margin_right: null # 0.39 - prefer_css_page_size: null # false - print_background: null # false - omit_background: null # false - landscape: null # false - scale: null # 1.0 - native_page_ranges: null # All pages - wait_delay: null # None - wait_for_expression: null # None - emulated_media_type: null # 'print' - cookies: null # None - user_agent: null # None - extra_http_headers: null # None - fail_on_http_status_codes: null # [499-599] - fail_on_console_exceptions: null # false - skip_network_idle_event: null # false - pdf_format: null # None - pdf_universal_access: null # false - metadata: null # None - download_from: null # None + + # Default footer twig template to apply. + template: null + + # Default context for footer twig template. + context: [] + + # Define whether to print the entire content in one single page. - default false. https://gotenberg.dev/docs/routes#page-properties-chromium + single_page: null + + # The standard paper size to use, either "letter", "legal", "tabloid", "ledger", "A0", "A1", "A2", "A3", "A4", "A5", "A6" - default None. + paper_standard_size: null # One of "letter"; "legal"; "tabloid"; "ledger"; "A0"; "A1"; "A2"; "A3"; "A4"; "A5"; "A6" + + # Paper width, in inches - default 8.5. https://gotenberg.dev/docs/routes#page-properties-chromium + paper_width: null + + # Paper height, in inches - default 11. https://gotenberg.dev/docs/routes#page-properties-chromium + paper_height: null + + # Top margin, in inches - default 0.39. https://gotenberg.dev/docs/routes#page-properties-chromium + margin_top: null + + # Bottom margin, in inches - default 0.39. https://gotenberg.dev/docs/routes#page-properties-chromium + margin_bottom: null + + # Left margin, in inches - default 0.39. https://gotenberg.dev/docs/routes#page-properties-chromium + margin_left: null + + # Right margin, in inches - default 0.39. https://gotenberg.dev/docs/routes#page-properties-chromium + margin_right: null + + # Define whether to prefer page size as defined by CSS - default false. https://gotenberg.dev/docs/routes#page-properties-chromium + prefer_css_page_size: null + + # Print the background graphics - default false. https://gotenberg.dev/docs/routes#page-properties-chromium + print_background: null + + # Hide the default white background and allow generating PDFs with transparency - default false. https://gotenberg.dev/docs/routes#page-properties-chromium + omit_background: null + + # The paper orientation to landscape - default false. https://gotenberg.dev/docs/routes#page-properties-chromium + landscape: null + + # The scale of the page rendering (e.g., 1.0) - default 1.0. https://gotenberg.dev/docs/routes#page-properties-chromium + scale: null + + # Page ranges to print, e.g., "1-5, 8, 11-13" - default All pages. https://gotenberg.dev/docs/routes#page-properties-chromium + native_page_ranges: null + + # Duration (e.g, "5s") to wait when loading an HTML document before converting it into PDF - default None. https://gotenberg.dev/docs/routes#wait-before-rendering + wait_delay: null + + # The JavaScript expression to wait before converting an HTML document into PDF until it returns true - default None. https://gotenberg.dev/docs/routes#wait-before-rendering + wait_for_expression: null + + # The media type to emulate, either "screen" or "print" - default "print". https://gotenberg.dev/docs/routes#emulated-media-type + emulated_media_type: null # One of "print"; "screen" + + # Cookies to store in the Chromium cookie jar - default None. https://gotenberg.dev/docs/routes#cookies-chromium + cookies: + + # Prototype + - + name: ~ + value: ~ + domain: ~ + path: null + secure: null + httpOnly: null + + # Accepted values are "Strict", "Lax" or "None". https://gotenberg.dev/docs/routes#cookies-chromium + sameSite: null # One of "Strict"; "Lax"; "None" + + # Override the default User-Agent HTTP header. - default None. https://gotenberg.dev/docs/routes#custom-http-headers-chromium + user_agent: null + + # HTTP headers to send by Chromium while loading the HTML document - default None. https://gotenberg.dev/docs/routes#custom-http-headers + extra_http_headers: + + # Prototype + name: + name: ~ + value: ~ + + # Return a 409 Conflict response if the HTTP status code from the main page is not acceptable. - default [499,599]. https://gotenberg.dev/docs/routes#invalid-http-status-codes-chromium + fail_on_http_status_codes: + + # Defaults: + - 499 + - 599 + + # Return a 409 Conflict response if there are exceptions in the Chromium console - default false. https://gotenberg.dev/docs/routes#console-exceptions + fail_on_console_exceptions: null + + # Do not wait for Chromium network to be idle. - default false. https://gotenberg.dev/docs/routes#performance-mode-chromium + skip_network_idle_event: null + + # The metadata to write. Not all metadata are writable. Consider taking a look at https://exiftool.org/TagNames/XMP.html#pdf for an (exhaustive?) list of available metadata. + metadata: + Author: ~ + Copyright: ~ + CreationDate: ~ + Creator: ~ + Keywords: ~ + Marked: ~ + ModDate: ~ + PDFVersion: ~ + Producer: ~ + Subject: ~ + Title: ~ + Trapped: ~ # One of "True"; "False"; "Unknown" + + # URLs to download files from (JSON format). - default None. https://gotenberg.dev/docs/routes#download-from + download_from: + + # Prototype + - + url: ~ + extraHttpHeaders: + + # Prototype + name: + name: ~ + value: ~ + + # Convert PDF into the given PDF/A format - default None. + pdf_format: null # One of "PDF\/A-1b"; "PDF\/A-2b"; "PDF\/A-3b" + + # Enable PDF for Universal Access for optimal accessibility - default false. + pdf_universal_access: null + + # Webhook configuration name or definition. + webhook: + + # The name of the webhook configuration to use. + config_name: ~ + success: + + # The URL to call. + url: ~ + + # Route configuration. + route: ~ + + # HTTP method to use on that endpoint. + method: null # One of "POST"; "PUT"; "PATCH" + error: + + # The URL to call. + url: ~ + + # Route configuration. + route: ~ + + # HTTP method to use on that endpoint. + method: null # One of "POST"; "PUT"; "PATCH" + + # HTTP headers to send by Chromium while loading the HTML document - default None. https://gotenberg.dev/docs/routes#custom-http-headers + extra_http_headers: + + # Prototype + name: + name: ~ + value: ~ office: - landscape: null # false - native_page_ranges: null # All pages - do_not_export_form_fields: null # true - single_page_sheets: null # false - merge: null # false - pdf_format: null # None - pdf_universal_access: null # false - metadata: null # None - allow_duplicate_field_names: null # false - do_not_export_bookmarks: null # true - export_bookmarks_to_pdf_destination: null # false - export_placeholders: null # false - export_notes: null # false - export_notes_pages: null # false - export_only_notes_pages: null # false - export_notes_in_margin: null # false - convert_ooo_target_to_pdf_target: null # false - export_links_relative_fsys: null # false - export_hidden_slides: null # false - skip_empty_pages: null # false - add_original_document_as_stream: null # false - lossless_image_compression: null # false - quality: null # 90 - reduce_image_resolution: null # false - max_image_resolution: null # 300 - password: null # None - download_from: null # None + + # Set the password for opening the source file. https://gotenberg.dev/docs/routes#page-properties-libreoffice + password: null + + # The paper orientation to landscape - default false. https://gotenberg.dev/docs/routes#page-properties-chromium + landscape: null + + # Page ranges to print, e.g., "1-5, 8, 11-13" - default All pages. https://gotenberg.dev/docs/routes#page-properties-chromium + native_page_ranges: null + + # Set whether to export the form fields or to use the inputted/selected content of the fields. - default true. https://gotenberg.dev/docs/routes#page-properties-libreoffice + do_not_export_form_fields: null + + # Set whether to render the entire spreadsheet as a single page. - default false. https://gotenberg.dev/docs/routes#page-properties-libreoffice + single_page_sheets: null + + # Merge alphanumerically the resulting PDFs. - default false. https://gotenberg.dev/docs/routes#merge-libreoffice + merge: null + + # The metadata to write. Not all metadata are writable. Consider taking a look at https://exiftool.org/TagNames/XMP.html#pdf for an (exhaustive?) list of available metadata. + metadata: + Author: ~ + Copyright: ~ + CreationDate: ~ + Creator: ~ + Keywords: ~ + Marked: ~ + ModDate: ~ + PDFVersion: ~ + Producer: ~ + Subject: ~ + Title: ~ + Trapped: ~ # One of "True"; "False"; "Unknown" + + # Specify whether multiple form fields exported are allowed to have the same field name. - default false. https://gotenberg.dev/docs/routes#page-properties-libreoffice + allow_duplicate_field_names: null + + # Specify if bookmarks are exported to PDF. - default true. https://gotenberg.dev/docs/routes#page-properties-libreoffice + do_not_export_bookmarks: null + + # Specify that the bookmarks contained in the source LibreOffice file should be exported to the PDF file as Named Destination. - default false. https://gotenberg.dev/docs/routes#page-properties-libreoffice + export_bookmarks_to_pdf_destination: null + + # Export the placeholders fields visual markings only. The exported placeholder is ineffective. - default false. https://gotenberg.dev/docs/routes#page-properties-libreoffice + export_placeholders: null + + # Specify if notes are exported to PDF. - default false. https://gotenberg.dev/docs/routes#page-properties-libreoffice + export_notes: null + + # Specify if notes pages are exported to PDF. Notes pages are available in Impress documents only. - default false. https://gotenberg.dev/docs/routes#page-properties-libreoffice + export_notes_pages: null + + # Specify, if the form field exportNotesPages is set to true, if only notes pages are exported to PDF. - default false. https://gotenberg.dev/docs/routes#page-properties-libreoffice + export_only_notes_pages: null + + # Specify if notes in margin are exported to PDF. - default false. https://gotenberg.dev/docs/routes#page-properties-libreoffice + export_notes_in_margin: null + + # Specify that the target documents with .od[tpgs] extension, will have that extension changed to .pdf when the link is exported to PDF. The source document remains untouched. - default false. https://gotenberg.dev/docs/routes#page-properties-libreoffice + convert_ooo_target_to_pdf_target: null + + # Specify that the file system related hyperlinks (file:// protocol) present in the document will be exported as relative to the source document location. - default false. https://gotenberg.dev/docs/routes#page-properties-libreoffice + export_links_relative_fsys: null + + # Export, for LibreOffice Impress, slides that are not included in slide shows. - default false. https://gotenberg.dev/docs/routes#page-properties-libreoffice + export_hidden_slides: null + + # Specify that automatically inserted empty pages are suppressed. This option is active only if storing Writer documents. - default false. https://gotenberg.dev/docs/routes#page-properties-libreoffice + skip_empty_pages: null + + # Specify that a stream is inserted to the PDF file which contains the original document for archiving purposes. - default false. https://gotenberg.dev/docs/routes#page-properties-libreoffice + add_original_document_as_stream: null + + # Specify if images are exported to PDF using a lossless compression format like PNG or compressed using the JPEG format. - default false. https://gotenberg.dev/docs/routes#images-libreoffice + lossless_image_compression: null + + # Specify the quality of the JPG export. A higher value produces a higher-quality image and a larger file. Between 1 and 100. - default 90. https://gotenberg.dev/docs/routes#images-libreoffice + quality: null + + # Specify if the resolution of each image is reduced to the resolution specified by the form field maxImageResolution. - default false. https://gotenberg.dev/docs/routes#images-libreoffice + reduce_image_resolution: null + + # If the form field reduceImageResolution is set to true, tell if all images will be reduced to the given value in DPI. Possible values are: 75, 150, 300, 600 and 1200. - default 300. https://gotenberg.dev/docs/routes#images-libreoffice + max_image_resolution: null # One of 75; 150; 300; 600; 1200 + + # URLs to download files from (JSON format). - default None. https://gotenberg.dev/docs/routes#download-from + download_from: + + # Prototype + - + url: ~ + extraHttpHeaders: + + # Prototype + name: + name: ~ + value: ~ + + # Convert PDF into the given PDF/A format - default None. + pdf_format: null # One of "PDF\/A-1b"; "PDF\/A-2b"; "PDF\/A-3b" + + # Enable PDF for Universal Access for optimal accessibility - default false. + pdf_universal_access: null merge: - pdf_format: null # None - pdf_universal_access: null # false - metadata: null # None - download_from: null # None + + # Convert PDF into the given PDF/A format - default None. + pdf_format: null # One of "PDF\/A-1b"; "PDF\/A-2b"; "PDF\/A-3b" + + # Enable PDF for Universal Access for optimal accessibility - default false. + pdf_universal_access: null + + # The metadata to write. Not all metadata are writable. Consider taking a look at https://exiftool.org/TagNames/XMP.html#pdf for an (exhaustive?) list of available metadata. + metadata: + Author: ~ + Copyright: ~ + CreationDate: ~ + Creator: ~ + Keywords: ~ + Marked: ~ + ModDate: ~ + PDFVersion: ~ + Producer: ~ + Subject: ~ + Title: ~ + Trapped: ~ # One of "True"; "False"; "Unknown" + + # URLs to download files from (JSON format). - default None. https://gotenberg.dev/docs/routes#download-from + download_from: + + # Prototype + - + url: ~ + extraHttpHeaders: + + # Prototype + name: + name: ~ + value: ~ convert: - pdf_format: null # None - pdf_universal_access: null # false - download_from: null # None + + # Convert PDF into the given PDF/A format - default None. + pdf_format: null # One of "PDF\/A-1b"; "PDF\/A-2b"; "PDF\/A-3b" + + # Enable PDF for Universal Access for optimal accessibility - default false. + pdf_universal_access: null + + # URLs to download files from (JSON format). - default None. https://gotenberg.dev/docs/routes#download-from + download_from: + + # Prototype + - + url: ~ + extraHttpHeaders: + + # Prototype + name: + name: ~ + value: ~ screenshot: html: - width: null # 800 - height: null # 600 - clip: null # false - format: null # png - quality: null # 100 - omit_background: null # false - optimize_for_speed: null # false - wait_delay: null # None - wait_for_expression: null # None - emulated_media_type: null # 'print' - cookies: null # None - user_agent: null # None - extra_http_headers: null # None - fail_on_http_status_codes: null # [499-599] - fail_on_console_exceptions: null # false - skip_network_idle_event: null # false - download_from: null # None + + # The device screen width in pixels. - default 800. https://gotenberg.dev/docs/routes#screenshots-route + width: null + + # The device screen height in pixels. - default 600. https://gotenberg.dev/docs/routes#screenshots-route + height: null + + # Define whether to clip the screenshot according to the device dimensions - default false. https://gotenberg.dev/docs/routes#screenshots-route + clip: null + + # The image compression format, either "png", "jpeg" or "webp" - default png. https://gotenberg.dev/docs/routes#screenshots-route + format: null # One of "png"; "jpeg"; "webp" + + # The compression quality from range 0 to 100 (jpeg only) - default 100. https://gotenberg.dev/docs/routes#screenshots-route + quality: null + + # Hide the default white background and allow generating PDFs with transparency - default false. https://gotenberg.dev/docs/routes#page-properties-chromium + omit_background: null + + # Define whether to optimize image encoding for speed, not for resulting size. - default false. https://gotenberg.dev/docs/routes#page-properties-chromium + optimize_for_speed: null + + # Duration (e.g, "5s") to wait when loading an HTML document before converting it into PDF - default None. https://gotenberg.dev/docs/routes#wait-before-rendering + wait_delay: null + + # The JavaScript expression to wait before converting an HTML document into PDF until it returns true - default None. https://gotenberg.dev/docs/routes#wait-before-rendering + wait_for_expression: null + + # The media type to emulate, either "screen" or "print" - default "print". https://gotenberg.dev/docs/routes#emulated-media-type + emulated_media_type: null # One of "print"; "screen" + + # Cookies to store in the Chromium cookie jar - default None. https://gotenberg.dev/docs/routes#cookies-chromium + cookies: + + # Prototype + - + name: ~ + value: ~ + domain: ~ + path: null + secure: null + httpOnly: null + + # Accepted values are "Strict", "Lax" or "None". https://gotenberg.dev/docs/routes#cookies-chromium + sameSite: null # One of "Strict"; "Lax"; "None" + + # Override the default User-Agent HTTP header. - default None. https://gotenberg.dev/docs/routes#custom-http-headers-chromium + user_agent: null + + # HTTP headers to send by Chromium while loading the HTML document - default None. https://gotenberg.dev/docs/routes#custom-http-headers + extra_http_headers: + + # Prototype + name: + name: ~ + value: ~ + + # Return a 409 Conflict response if the HTTP status code from the main page is not acceptable. - default [499,599]. https://gotenberg.dev/docs/routes#invalid-http-status-codes-chromium + fail_on_http_status_codes: + + # Defaults: + - 499 + - 599 + + # Return a 409 Conflict response if there are exceptions in the Chromium console - default false. https://gotenberg.dev/docs/routes#console-exceptions + fail_on_console_exceptions: null + + # Do not wait for Chromium network to be idle. - default false. https://gotenberg.dev/docs/routes#performance-mode-chromium + skip_network_idle_event: null + + # URLs to download files from (JSON format). - default None. https://gotenberg.dev/docs/routes#download-from + download_from: + + # Prototype + - + url: ~ + extraHttpHeaders: + + # Prototype + name: + name: ~ + value: ~ + + # Webhook configuration name or definition. + webhook: + + # The name of the webhook configuration to use. + config_name: ~ + success: + + # The URL to call. + url: ~ + + # Route configuration. + route: ~ + + # HTTP method to use on that endpoint. + method: null # One of "POST"; "PUT"; "PATCH" + error: + + # The URL to call. + url: ~ + + # Route configuration. + route: ~ + + # HTTP method to use on that endpoint. + method: null # One of "POST"; "PUT"; "PATCH" + + # HTTP headers to send by Chromium while loading the HTML document - default None. https://gotenberg.dev/docs/routes#custom-http-headers + extra_http_headers: + + # Prototype + name: + name: ~ + value: ~ url: - width: null # 800 - height: null # 600 - clip: null # false - format: null # png - quality: null # 100 - omit_background: null # false - optimize_for_speed: null # false - wait_delay: null # None - wait_for_expression: null # None - emulated_media_type: null # 'print' - cookies: null # None - user_agent: null # None - extra_http_headers: null # None - fail_on_http_status_codes: null # [499-599] - fail_on_console_exceptions: null # false - skip_network_idle_event: null # false - download_from: null # None + + # The device screen width in pixels. - default 800. https://gotenberg.dev/docs/routes#screenshots-route + width: null + + # The device screen height in pixels. - default 600. https://gotenberg.dev/docs/routes#screenshots-route + height: null + + # Define whether to clip the screenshot according to the device dimensions - default false. https://gotenberg.dev/docs/routes#screenshots-route + clip: null + + # The image compression format, either "png", "jpeg" or "webp" - default png. https://gotenberg.dev/docs/routes#screenshots-route + format: null # One of "png"; "jpeg"; "webp" + + # The compression quality from range 0 to 100 (jpeg only) - default 100. https://gotenberg.dev/docs/routes#screenshots-route + quality: null + + # Hide the default white background and allow generating PDFs with transparency - default false. https://gotenberg.dev/docs/routes#page-properties-chromium + omit_background: null + + # Define whether to optimize image encoding for speed, not for resulting size. - default false. https://gotenberg.dev/docs/routes#page-properties-chromium + optimize_for_speed: null + + # Duration (e.g, "5s") to wait when loading an HTML document before converting it into PDF - default None. https://gotenberg.dev/docs/routes#wait-before-rendering + wait_delay: null + + # The JavaScript expression to wait before converting an HTML document into PDF until it returns true - default None. https://gotenberg.dev/docs/routes#wait-before-rendering + wait_for_expression: null + + # The media type to emulate, either "screen" or "print" - default "print". https://gotenberg.dev/docs/routes#emulated-media-type + emulated_media_type: null # One of "print"; "screen" + + # Cookies to store in the Chromium cookie jar - default None. https://gotenberg.dev/docs/routes#cookies-chromium + cookies: + + # Prototype + - + name: ~ + value: ~ + domain: ~ + path: null + secure: null + httpOnly: null + + # Accepted values are "Strict", "Lax" or "None". https://gotenberg.dev/docs/routes#cookies-chromium + sameSite: null # One of "Strict"; "Lax"; "None" + + # Override the default User-Agent HTTP header. - default None. https://gotenberg.dev/docs/routes#custom-http-headers-chromium + user_agent: null + + # HTTP headers to send by Chromium while loading the HTML document - default None. https://gotenberg.dev/docs/routes#custom-http-headers + extra_http_headers: + + # Prototype + name: + name: ~ + value: ~ + + # Return a 409 Conflict response if the HTTP status code from the main page is not acceptable. - default [499,599]. https://gotenberg.dev/docs/routes#invalid-http-status-codes-chromium + fail_on_http_status_codes: + + # Defaults: + - 499 + - 599 + + # Return a 409 Conflict response if there are exceptions in the Chromium console - default false. https://gotenberg.dev/docs/routes#console-exceptions + fail_on_console_exceptions: null + + # Do not wait for Chromium network to be idle. - default false. https://gotenberg.dev/docs/routes#performance-mode-chromium + skip_network_idle_event: null + + # URLs to download files from (JSON format). - default None. https://gotenberg.dev/docs/routes#download-from + download_from: + + # Prototype + - + url: ~ + extraHttpHeaders: + + # Prototype + name: + name: ~ + value: ~ + + # Webhook configuration name or definition. + webhook: + + # The name of the webhook configuration to use. + config_name: ~ + success: + + # The URL to call. + url: ~ + + # Route configuration. + route: ~ + + # HTTP method to use on that endpoint. + method: null # One of "POST"; "PUT"; "PATCH" + error: + + # The URL to call. + url: ~ + + # Route configuration. + route: ~ + + # HTTP method to use on that endpoint. + method: null # One of "POST"; "PUT"; "PATCH" + + # HTTP headers to send by Chromium while loading the HTML document - default None. https://gotenberg.dev/docs/routes#custom-http-headers + extra_http_headers: + + # Prototype + name: + name: ~ + value: ~ markdown: - width: null # 800 - height: null # 600 - clip: null # false - format: null # png - quality: null # 100 - omit_background: null # false - optimize_for_speed: null # false - wait_delay: null # None - wait_for_expression: null # None - emulated_media_type: null # 'print' - cookies: null # None - user_agent: null # None - extra_http_headers: null # None - fail_on_http_status_codes: null # [499-599] - fail_on_console_exceptions: null # false - skip_network_idle_event: null # false - download_from: null # None + + # The device screen width in pixels. - default 800. https://gotenberg.dev/docs/routes#screenshots-route + width: null + + # The device screen height in pixels. - default 600. https://gotenberg.dev/docs/routes#screenshots-route + height: null + + # Define whether to clip the screenshot according to the device dimensions - default false. https://gotenberg.dev/docs/routes#screenshots-route + clip: null + + # The image compression format, either "png", "jpeg" or "webp" - default png. https://gotenberg.dev/docs/routes#screenshots-route + format: null # One of "png"; "jpeg"; "webp" + + # The compression quality from range 0 to 100 (jpeg only) - default 100. https://gotenberg.dev/docs/routes#screenshots-route + quality: null + + # Hide the default white background and allow generating PDFs with transparency - default false. https://gotenberg.dev/docs/routes#page-properties-chromium + omit_background: null + + # Define whether to optimize image encoding for speed, not for resulting size. - default false. https://gotenberg.dev/docs/routes#page-properties-chromium + optimize_for_speed: null + + # Duration (e.g, "5s") to wait when loading an HTML document before converting it into PDF - default None. https://gotenberg.dev/docs/routes#wait-before-rendering + wait_delay: null + + # The JavaScript expression to wait before converting an HTML document into PDF until it returns true - default None. https://gotenberg.dev/docs/routes#wait-before-rendering + wait_for_expression: null + + # The media type to emulate, either "screen" or "print" - default "print". https://gotenberg.dev/docs/routes#emulated-media-type + emulated_media_type: null # One of "print"; "screen" + + # Cookies to store in the Chromium cookie jar - default None. https://gotenberg.dev/docs/routes#cookies-chromium + cookies: + + # Prototype + - + name: ~ + value: ~ + domain: ~ + path: null + secure: null + httpOnly: null + + # Accepted values are "Strict", "Lax" or "None". https://gotenberg.dev/docs/routes#cookies-chromium + sameSite: null # One of "Strict"; "Lax"; "None" + + # Override the default User-Agent HTTP header. - default None. https://gotenberg.dev/docs/routes#custom-http-headers-chromium + user_agent: null + + # HTTP headers to send by Chromium while loading the HTML document - default None. https://gotenberg.dev/docs/routes#custom-http-headers + extra_http_headers: + + # Prototype + name: + name: ~ + value: ~ + + # Return a 409 Conflict response if the HTTP status code from the main page is not acceptable. - default [499,599]. https://gotenberg.dev/docs/routes#invalid-http-status-codes-chromium + fail_on_http_status_codes: + + # Defaults: + - 499 + - 599 + + # Return a 409 Conflict response if there are exceptions in the Chromium console - default false. https://gotenberg.dev/docs/routes#console-exceptions + fail_on_console_exceptions: null + + # Do not wait for Chromium network to be idle. - default false. https://gotenberg.dev/docs/routes#performance-mode-chromium + skip_network_idle_event: null + + # URLs to download files from (JSON format). - default None. https://gotenberg.dev/docs/routes#download-from + download_from: + + # Prototype + - + url: ~ + extraHttpHeaders: + + # Prototype + name: + name: ~ + value: ~ + + # Webhook configuration name or definition. + webhook: + + # The name of the webhook configuration to use. + config_name: ~ + success: + + # The URL to call. + url: ~ + + # Route configuration. + route: ~ + + # HTTP method to use on that endpoint. + method: null # One of "POST"; "PUT"; "PATCH" + error: + + # The URL to call. + url: ~ + + # Route configuration. + route: ~ + + # HTTP method to use on that endpoint. + method: null # One of "POST"; "PUT"; "PATCH" + + # HTTP headers to send by Chromium while loading the HTML document - default None. https://gotenberg.dev/docs/routes#custom-http-headers + extra_http_headers: + + # Prototype + name: + name: ~ + value: ~ ``` > [!TIP] @@ -238,6 +1131,16 @@ sensiolabs_gotenberg: HTTP headers to send by Chromium while loading the HTML document. +```yaml +sensiolabs_gotenberg: + webhook: + default: + extra_http_headers: + - { name: 'My-Header', value: 'MyValue' } +``` + +Or Headers to send to your webhook endpoint + ```yaml sensiolabs_gotenberg: default_options: @@ -334,4 +1237,3 @@ sensiolabs_gotenberg: > [!TIP] > For more information go to [Gotenberg documentations](https://gotenberg.dev/docs/routes#download-from). - diff --git a/src/DependencyInjection/Configuration.php b/src/DependencyInjection/Configuration.php index ec089164..c069e323 100644 --- a/src/DependencyInjection/Configuration.php +++ b/src/DependencyInjection/Configuration.php @@ -661,7 +661,7 @@ private function addNamedWebhookDefinition(): NodeDefinition ->append($this->addWebhookConfigurationNode('success')) ->append($this->addWebhookConfigurationNode('error')) ->arrayNode('extra_http_headers') - ->info('HTTP headers to send by Chromium while loading the HTML document - default None. https://gotenberg.dev/docs/routes#custom-http-headers') + ->info('HTTP headers to send back to both success and error endpoints - default None. https://gotenberg.dev/docs/webhook') ->useAttributeAsKey('name') ->arrayPrototype() ->children() @@ -713,7 +713,10 @@ private function addWebhookDeclarationNode(ArrayNodeDefinition $parent): void ->append($this->addWebhookConfigurationNode('success')) ->append($this->addWebhookConfigurationNode('error')) ->arrayNode('extra_http_headers') - ->info('HTTP headers to send by Chromium while loading the HTML document - default None. https://gotenberg.dev/docs/routes#custom-http-headers') + ->info('HTTP headers to send back to both success and error endpoints - default None. https://gotenberg.dev/docs/webhook') + ->example([ + ['name' => 'X-Custom-Header', 'value' => 'custom-header-value'], + ]) ->useAttributeAsKey('name') ->arrayPrototype() ->children() @@ -773,6 +776,10 @@ private function addWebhookConfigurationNode(string $name): NodeDefinition }) ->thenInvalid('The "route" parameter must be a string or an array containing a string and an array.') ->end() + ->example([ + 'https://webhook.site/#!/view/{some-token}', + ['my_route', ['param1' => 'value1', 'param2' => 'value2']], + ]) ->end() ->enumNode('method') ->info('HTTP method to use on that endpoint.') From 44764ddaf7640b40b972fdfb79beddcba44a921e Mon Sep 17 00:00:00 2001 From: Adrien Roches Date: Sat, 16 Nov 2024 10:48:06 +0100 Subject: [PATCH 21/24] Update docs for webhooks --- README.md | 1 + docs/async/native.md | 191 ++++++++++++++++++++++++++++++++++++++++++ docs/configuration.md | 108 ++++++++++++++++++++---- docs/webhook.md | 3 + 4 files changed, 286 insertions(+), 17 deletions(-) create mode 100644 docs/async/native.md create mode 100644 docs/webhook.md diff --git a/README.md b/README.md index 6a85ce5e..a115ae25 100644 --- a/README.md +++ b/README.md @@ -221,6 +221,7 @@ class YourController 1. [Configuration](./docs/configuration.md) 2. [Working with assets](./docs/assets.md) 3. [Builders API](./docs/builders_api.md) +4. [Async & Webhooks](./docs/webhook.md) #### PDF diff --git a/docs/async/native.md b/docs/async/native.md new file mode 100644 index 00000000..abb31984 --- /dev/null +++ b/docs/async/native.md @@ -0,0 +1,191 @@ +## Using the native feature + +Gotenberg [allows](https://gotenberg.dev/docs/configuration#webhook) to defer the generation of your files through webhooks. +When it is done creating your file, it calls back whatever header you sent. + +To use this feature you need two things : +- Send the appropriate headers +- use `->generateAsync()` method + +### Through Bundle configuration + +Using bundle configuration you can define : +- named configurations +- default named configuration +- per context (PDF+HTML, PDF+URL, SCREENSHOT+MARKDOWN) + +```yaml +# config/packages/sensiolabs_gotenberg.yaml + +sensiolabs_gotenberg: + + webhook: + + # Prototype + name: + name: ~ + success: + + # The URL to call. + url: ~ + + # Route configuration. + route: ~ + + # Examples: + # - 'https://webhook.site/#!/view/{some-token}' + # - [my_route, { param1: value1, param2: value2 }] + + # HTTP method to use on that endpoint. + method: null # One of "POST"; "PUT"; "PATCH" + error: + + # The URL to call. + url: ~ + + # Route configuration. + route: ~ + + # Examples: + # - 'https://webhook.site/#!/view/{some-token}' + # - [my_route, { param1: value1, param2: value2 }] + + # HTTP method to use on that endpoint. + method: null # One of "POST"; "PUT"; "PATCH" + + # HTTP headers to send back to both success and error endpoints - default None. https://gotenberg.dev/docs/webhook + extra_http_headers: + + # Prototype + name: + name: ~ + value: ~ + default_options: + + # Webhook configuration name. + webhook: ~ +``` + +Each named configuration requires at least a `success` URL which can be set either through a plain URL (`sensiolabs_gotenberg.webhook.{name}.success.url`) or by using a defined route in your application (`sensiolabs_gotenberg.webhook.{name}.success.route`). +Here are some examples : + +```yaml +sensiolabs_gotenberg: + webhook: + default: + success: + url: 'https://webhook.site/#!/view/{some-uuid}' +``` +or +```yaml +sensiolabs_gotenberg: + webhook: + default: + success: + route: ['my_route', {'param1': 'value1'}] +``` + +Once a named configuration has been set, you can set it as a global default for all your builders : + +```yaml +sensiolabs_gotenberg: + default_options: + webhook: 'default' +``` + +or set it per builder : + +```yaml +sensiolabs_gotenberg: + webhook: + default: + success: + url: 'https://webhook.site/#!/view/{some-uuid}' + pdf_html: + success: + url: 'https://webhook.site/#!/view/{some-other-uuid}' + default_options: + pdf: + html: + webhook: + config_name: 'pdf_html' +``` + +finally you can do it like so : + +```yaml +sensiolabs_gotenberg: + default_options: + pdf: + html: + webhook: + success: + url: 'https://webhook.site/#!/view/{some-uuid}' +``` + +> [!WARNING] +> When using both `config_name` and a custom configuration on a builder, +> it will load the named configuration and merge it with the builder's configuration. +> See the following example : + +```yaml +sensiolabs_gotenberg: + webhook: + default: + success: + url: 'https://webhook.site/#!/view/{some-success-uuid}' + error: + url: 'https://webhook.site/#!/view/{some-error-uuid}' + default_options: + pdf: + html: + webhook: + config_name: 'default' + success: + url: 'https://webhook.site/#!/view/{some-other-uuid}' +``` + +is equivalent to : + +```yaml +sensiolabs_gotenberg: + default_options: + pdf: + html: + webhook: + success: + url: 'https://webhook.site/#!/view/{some-other-uuid}' + error: + url: 'https://webhook.site/#!/view/{some-error-uuid}' +``` + +### At runtime + +You can define webhook configuration at runtime. + +If you defined some named configuration like seen earlier, the simplest way is then to do the following: + +```diff +$builder = $this->gotenberg->pdf()->html() ++ ->webhookConfiguration('default') + ->header('header.html.twig') + ->content('html.html.twig', ['name' => 'Plop']) + ->fileName('html.pdf') +; +``` + +Or you can also define manually using : + +```diff +$builder = $this->gotenberg->pdf()->html() ++ ->webhookUrl($this->router->generate('my_route')) + ->header('header.html.twig') + ->content('html.html.twig', ['name' => 'Plop']) + ->fileName('html.pdf') +; +``` + +> [!WARNING] +> If combining both `->webhookConfiguration()` & `->webhookUrl()`, the order is important +> If calling `->webhookConfiguration()` first then `->webhookUrl()` will override only the "success" part. +> If calling `->webhookUrl()` first then `->webhookConfiguration()` totally overrides previously set values. diff --git a/docs/configuration.md b/docs/configuration.md index b6cc90da..5fc78fda 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -54,6 +54,10 @@ sensiolabs_gotenberg: # Route configuration. route: ~ + # Examples: + # - 'https://webhook.site/#!/view/{some-token}' + # - [my_route, { param1: value1, param2: value2 }] + # HTTP method to use on that endpoint. method: null # One of "POST"; "PUT"; "PATCH" error: @@ -64,10 +68,14 @@ sensiolabs_gotenberg: # Route configuration. route: ~ + # Examples: + # - 'https://webhook.site/#!/view/{some-token}' + # - [my_route, { param1: value1, param2: value2 }] + # HTTP method to use on that endpoint. method: null # One of "POST"; "PUT"; "PATCH" - # HTTP headers to send by Chromium while loading the HTML document - default None. https://gotenberg.dev/docs/routes#custom-http-headers + # HTTP headers to send back to both success and error endpoints - default None. https://gotenberg.dev/docs/webhook extra_http_headers: # Prototype @@ -236,6 +244,10 @@ sensiolabs_gotenberg: # Route configuration. route: ~ + # Examples: + # - 'https://webhook.site/#!/view/{some-token}' + # - [my_route, { param1: value1, param2: value2 }] + # HTTP method to use on that endpoint. method: null # One of "POST"; "PUT"; "PATCH" error: @@ -246,12 +258,19 @@ sensiolabs_gotenberg: # Route configuration. route: ~ + # Examples: + # - 'https://webhook.site/#!/view/{some-token}' + # - [my_route, { param1: value1, param2: value2 }] + # HTTP method to use on that endpoint. method: null # One of "POST"; "PUT"; "PATCH" - # HTTP headers to send by Chromium while loading the HTML document - default None. https://gotenberg.dev/docs/routes#custom-http-headers + # HTTP headers to send back to both success and error endpoints - default None. https://gotenberg.dev/docs/webhook extra_http_headers: + # Example: + # - { name: X-Custom-Header, value: custom-header-value } + # Prototype name: name: ~ @@ -413,6 +432,10 @@ sensiolabs_gotenberg: # Route configuration. route: ~ + # Examples: + # - 'https://webhook.site/#!/view/{some-token}' + # - [my_route, { param1: value1, param2: value2 }] + # HTTP method to use on that endpoint. method: null # One of "POST"; "PUT"; "PATCH" error: @@ -423,12 +446,19 @@ sensiolabs_gotenberg: # Route configuration. route: ~ + # Examples: + # - 'https://webhook.site/#!/view/{some-token}' + # - [my_route, { param1: value1, param2: value2 }] + # HTTP method to use on that endpoint. method: null # One of "POST"; "PUT"; "PATCH" - # HTTP headers to send by Chromium while loading the HTML document - default None. https://gotenberg.dev/docs/routes#custom-http-headers + # HTTP headers to send back to both success and error endpoints - default None. https://gotenberg.dev/docs/webhook extra_http_headers: + # Example: + # - { name: X-Custom-Header, value: custom-header-value } + # Prototype name: name: ~ @@ -590,6 +620,10 @@ sensiolabs_gotenberg: # Route configuration. route: ~ + # Examples: + # - 'https://webhook.site/#!/view/{some-token}' + # - [my_route, { param1: value1, param2: value2 }] + # HTTP method to use on that endpoint. method: null # One of "POST"; "PUT"; "PATCH" error: @@ -600,12 +634,19 @@ sensiolabs_gotenberg: # Route configuration. route: ~ + # Examples: + # - 'https://webhook.site/#!/view/{some-token}' + # - [my_route, { param1: value1, param2: value2 }] + # HTTP method to use on that endpoint. method: null # One of "POST"; "PUT"; "PATCH" - # HTTP headers to send by Chromium while loading the HTML document - default None. https://gotenberg.dev/docs/routes#custom-http-headers + # HTTP headers to send back to both success and error endpoints - default None. https://gotenberg.dev/docs/webhook extra_http_headers: + # Example: + # - { name: X-Custom-Header, value: custom-header-value } + # Prototype name: name: ~ @@ -867,6 +908,10 @@ sensiolabs_gotenberg: # Route configuration. route: ~ + # Examples: + # - 'https://webhook.site/#!/view/{some-token}' + # - [my_route, { param1: value1, param2: value2 }] + # HTTP method to use on that endpoint. method: null # One of "POST"; "PUT"; "PATCH" error: @@ -877,12 +922,19 @@ sensiolabs_gotenberg: # Route configuration. route: ~ + # Examples: + # - 'https://webhook.site/#!/view/{some-token}' + # - [my_route, { param1: value1, param2: value2 }] + # HTTP method to use on that endpoint. method: null # One of "POST"; "PUT"; "PATCH" - # HTTP headers to send by Chromium while loading the HTML document - default None. https://gotenberg.dev/docs/routes#custom-http-headers + # HTTP headers to send back to both success and error endpoints - default None. https://gotenberg.dev/docs/webhook extra_http_headers: + # Example: + # - { name: X-Custom-Header, value: custom-header-value } + # Prototype name: name: ~ @@ -984,6 +1036,10 @@ sensiolabs_gotenberg: # Route configuration. route: ~ + # Examples: + # - 'https://webhook.site/#!/view/{some-token}' + # - [my_route, { param1: value1, param2: value2 }] + # HTTP method to use on that endpoint. method: null # One of "POST"; "PUT"; "PATCH" error: @@ -994,12 +1050,19 @@ sensiolabs_gotenberg: # Route configuration. route: ~ + # Examples: + # - 'https://webhook.site/#!/view/{some-token}' + # - [my_route, { param1: value1, param2: value2 }] + # HTTP method to use on that endpoint. method: null # One of "POST"; "PUT"; "PATCH" - # HTTP headers to send by Chromium while loading the HTML document - default None. https://gotenberg.dev/docs/routes#custom-http-headers + # HTTP headers to send back to both success and error endpoints - default None. https://gotenberg.dev/docs/webhook extra_http_headers: + # Example: + # - { name: X-Custom-Header, value: custom-header-value } + # Prototype name: name: ~ @@ -1101,6 +1164,10 @@ sensiolabs_gotenberg: # Route configuration. route: ~ + # Examples: + # - 'https://webhook.site/#!/view/{some-token}' + # - [my_route, { param1: value1, param2: value2 }] + # HTTP method to use on that endpoint. method: null # One of "POST"; "PUT"; "PATCH" error: @@ -1111,12 +1178,19 @@ sensiolabs_gotenberg: # Route configuration. route: ~ + # Examples: + # - 'https://webhook.site/#!/view/{some-token}' + # - [my_route, { param1: value1, param2: value2 }] + # HTTP method to use on that endpoint. method: null # One of "POST"; "PUT"; "PATCH" - # HTTP headers to send by Chromium while loading the HTML document - default None. https://gotenberg.dev/docs/routes#custom-http-headers + # HTTP headers to send back to both success and error endpoints - default None. https://gotenberg.dev/docs/webhook extra_http_headers: + # Example: + # - { name: X-Custom-Header, value: custom-header-value } + # Prototype name: name: ~ @@ -1133,25 +1207,25 @@ HTTP headers to send by Chromium while loading the HTML document. ```yaml sensiolabs_gotenberg: - webhook: - default: - extra_http_headers: - - { name: 'My-Header', value: 'MyValue' } + default_options: + pdf: + html: + extra_http_headers: + - { name: 'My-Header', value: 'MyValue' } ``` Or Headers to send to your webhook endpoint ```yaml sensiolabs_gotenberg: - default_options: - pdf: - html: - extra_http_headers: - - { name: 'My-Header', value: 'MyValue' } + webhook: + default: + extra_http_headers: + - { name: 'My-Header', value: 'MyValue' } ``` > [!TIP] -> For more information about [custom HTTP headers](https://gotenberg.dev/docs/routes#custom-http-headers). +> For more information about [custom HTTP headers](https://gotenberg.dev/docs/routes#custom-http-headers) & [webhook custom HTTP headers](https://gotenberg.dev/docs/configuration#webhook). ## Invalid HTTP Status Codes diff --git a/docs/webhook.md b/docs/webhook.md new file mode 100644 index 00000000..75a349ac --- /dev/null +++ b/docs/webhook.md @@ -0,0 +1,3 @@ +# Going async + +* [Native](./async/native.md) From f8a1de95209818b79892657bd91da89d27a92a5a Mon Sep 17 00:00:00 2001 From: Adrien Roches Date: Sat, 16 Nov 2024 10:50:28 +0100 Subject: [PATCH 22/24] Update docs for webhooks --- docs/async/native.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/docs/async/native.md b/docs/async/native.md index abb31984..d25990af 100644 --- a/docs/async/native.md +++ b/docs/async/native.md @@ -67,6 +67,7 @@ sensiolabs_gotenberg: ``` Each named configuration requires at least a `success` URL which can be set either through a plain URL (`sensiolabs_gotenberg.webhook.{name}.success.url`) or by using a defined route in your application (`sensiolabs_gotenberg.webhook.{name}.success.route`). + Here are some examples : ```yaml @@ -126,6 +127,7 @@ sensiolabs_gotenberg: > [!WARNING] > When using both `config_name` and a custom configuration on a builder, > it will load the named configuration and merge it with the builder's configuration. +> > See the following example : ```yaml @@ -186,6 +188,8 @@ $builder = $this->gotenberg->pdf()->html() ``` > [!WARNING] -> If combining both `->webhookConfiguration()` & `->webhookUrl()`, the order is important +> If combining both `->webhookConfiguration()` & `->webhookUrl()`, the order is important : +> > If calling `->webhookConfiguration()` first then `->webhookUrl()` will override only the "success" part. +> > If calling `->webhookUrl()` first then `->webhookConfiguration()` totally overrides previously set values. From c461a88bd2de8da82f115c0868fd15a181a4b132 Mon Sep 17 00:00:00 2001 From: Adrien Roches Date: Sat, 16 Nov 2024 13:07:16 +0100 Subject: [PATCH 23/24] Add tests on async trait --- docs/async/native.md | 4 + src/Builder/AsyncBuilderTrait.php | 2 +- tests/Builder/AsyncBuilderTraitTest.php | 210 ++++++++++++++++++++++++ 3 files changed, 215 insertions(+), 1 deletion(-) create mode 100644 tests/Builder/AsyncBuilderTraitTest.php diff --git a/docs/async/native.md b/docs/async/native.md index d25990af..3200fc5d 100644 --- a/docs/async/native.md +++ b/docs/async/native.md @@ -193,3 +193,7 @@ $builder = $this->gotenberg->pdf()->html() > If calling `->webhookConfiguration()` first then `->webhookUrl()` will override only the "success" part. > > If calling `->webhookUrl()` first then `->webhookConfiguration()` totally overrides previously set values. + + +> [!NOTE] +> If only success URL is set, error URL will fallback to the success one. diff --git a/src/Builder/AsyncBuilderTrait.php b/src/Builder/AsyncBuilderTrait.php index 23fa3c96..b71646ef 100644 --- a/src/Builder/AsyncBuilderTrait.php +++ b/src/Builder/AsyncBuilderTrait.php @@ -33,7 +33,7 @@ trait AsyncBuilderTrait public function generateAsync(): void { if (null === $this->successWebhookUrl) { - throw new MissingRequiredFieldException('->webhookUrls() was never called.'); + throw new MissingRequiredFieldException('->webhookUrl() was never called.'); } $errorWebhookUrl = $this->errorWebhookUrl ?? $this->successWebhookUrl; diff --git a/tests/Builder/AsyncBuilderTraitTest.php b/tests/Builder/AsyncBuilderTraitTest.php new file mode 100644 index 00000000..9aff1238 --- /dev/null +++ b/tests/Builder/AsyncBuilderTraitTest.php @@ -0,0 +1,210 @@ +getBuilder(new MockHttpClient([])); + + $this->expectException(MissingRequiredFieldException::class); + $this->expectExceptionMessage('->webhookUrl() was never called.'); + + $builder->generateAsync(); + } + + public function testItGenerateWithJustTheSuccessWebhookUrlSet(): void + { + $callback = function ($method, $url, $options): MockResponse { + $this->assertSame('POST', $method); + $this->assertSame('https://example.com/fake/endpoint', $url); + $this->assertContains('Gotenberg-Webhook-Url: https://webhook.local', $options['headers']); + $this->assertContains('Gotenberg-Webhook-Error-Url: https://webhook.local', $options['headers']); + $this->assertArrayNotHasKey('gotenberg-webhook-method', $options['normalized_headers']); + $this->assertArrayNotHasKey('gotenberg-webhook-error-method', $options['normalized_headers']); + + return new MockResponse('', [ + 'response_headers' => [ + 'Content-Type' => 'text/plain; charset=UTF-8', + 'Gotenberg-Trace' => '{trace}', + ], + ]); + }; + + $builder = $this->getBuilder(new MockHttpClient($callback)); + $builder->webhookUrl('https://webhook.local'); + + $builder->generateAsync(); + } + + public function testItAlsoAcceptsADifferentErrorWebhookUrl(): void + { + $callback = function ($method, $url, $options): MockResponse { + $this->assertContains('Gotenberg-Webhook-Url: https://webhook.local', $options['headers']); + $this->assertContains('Gotenberg-Webhook-Error-Url: https://webhook.local/error', $options['headers']); + + return new MockResponse('', [ + 'response_headers' => [ + 'Content-Type' => 'text/plain; charset=UTF-8', + 'Gotenberg-Trace' => '{trace}', + ], + ]); + }; + + $builder = $this->getBuilder(new MockHttpClient($callback)); + $builder->webhookUrl('https://webhook.local'); + $builder->errorWebhookUrl('https://webhook.local/error'); + + $builder->generateAsync(); + } + + public function testWebhookUrlsCanChangeTheirRespectiveHttpMethods(): void + { + $callback = function ($method, $url, $options): MockResponse { + $this->assertContains('Gotenberg-Webhook-Url: https://webhook.local', $options['headers']); + $this->assertContains('Gotenberg-Webhook-Method: PUT', $options['headers']); + $this->assertContains('Gotenberg-Webhook-Error-Url: https://webhook.local/error', $options['headers']); + $this->assertContains('Gotenberg-Webhook-Error-Method: PATCH', $options['headers']); + + return new MockResponse('', [ + 'response_headers' => [ + 'Content-Type' => 'text/plain; charset=UTF-8', + 'Gotenberg-Trace' => '{trace}', + ], + ]); + }; + + $builder = $this->getBuilder(new MockHttpClient($callback)); + $builder->webhookUrl('https://webhook.local', 'PUT'); + $builder->errorWebhookUrl('https://webhook.local/error', 'PATCH'); + + $builder->generateAsync(); + } + + public function testWebhookUrlsCanSendCustomHttpHeaderToEndpoint(): void + { + $callback = function ($method, $url, $options): MockResponse { + $this->assertContains('Gotenberg-Webhook-Extra-Http-Headers: {"plop":"plop"}', $options['headers']); + + return new MockResponse('', [ + 'response_headers' => [ + 'Content-Type' => 'text/plain; charset=UTF-8', + 'Gotenberg-Trace' => '{trace}', + ], + ]); + }; + + $builder = $this->getBuilder(new MockHttpClient($callback)); + $builder->webhookUrl('https://webhook.local'); + $builder->webhookExtraHeaders(['plop' => 'plop']); + + $builder->generateAsync(); + } + + public function testWebhookUrlsCanBeSetUsingTheRegistry(): void + { + $registry = new class($this) implements WebhookConfigurationRegistryInterface { + public function __construct(private AsyncBuilderTraitTest $assert) + { + } + + public function add(string $name, array $configuration): void + { + // TODO: Implement add() method. + } + + public function get(string $name): array + { + $this->assert->assertSame('fake', $name); + + return [ + 'success' => [ + 'url' => 'https://webhook.local', + 'method' => 'PUT', + ], + 'error' => [ + 'url' => 'https://webhook.local/error', + 'method' => 'PATCH', + ], + 'extra_http_headers' => [ + 'plop' => 'plop', + ], + ]; + } + }; + + $callback = function ($method, $url, $options): MockResponse { + $this->assertContains('Gotenberg-Webhook-Url: https://webhook.local', $options['headers']); + $this->assertContains('Gotenberg-Webhook-Method: PUT', $options['headers']); + $this->assertContains('Gotenberg-Webhook-Error-Url: https://webhook.local/error', $options['headers']); + $this->assertContains('Gotenberg-Webhook-Error-Method: PATCH', $options['headers']); + + return new MockResponse('', [ + 'response_headers' => [ + 'Content-Type' => 'text/plain; charset=UTF-8', + 'Gotenberg-Trace' => '{trace}', + ], + ]); + }; + + $builder = $this->getBuilder(new MockHttpClient($callback), $registry); + $builder->webhookConfiguration('fake'); + + $builder->generateAsync(); + } + + private function getBuilder(MockHttpClient $httpClient, WebhookConfigurationRegistryInterface|null $registry = null): object + { + $registry ??= new class implements WebhookConfigurationRegistryInterface { + public function add(string $name, array $configuration): void + { + // TODO: Implement add() method. + } + + public function get(string $name): array + { + // TODO: Implement get() method. + } + }; + + return new class($httpClient, $registry) { + use AsyncBuilderTrait; + + public function __construct(HttpClientInterface $httpClient, WebhookConfigurationRegistryInterface $registry) + { + $this->client = new GotenbergClient($httpClient); + $this->webhookConfigurationRegistry = $registry; + } + + protected function getEndpoint(): string + { + return '/fake/endpoint'; + } + + public function setConfigurations(array $configurations): static + { + // TODO: Implement setConfigurations() method. + } + }; + } +} From 931943a9947ca3dcc56b0fb12214d1970d1eab6e Mon Sep 17 00:00:00 2001 From: Adrien Roches Date: Tue, 19 Nov 2024 23:24:40 +0100 Subject: [PATCH 24/24] [FIX] CI --- phpstan.dist.neon | 20 ++++++ .../SensiolabsGotenbergExtension.php | 61 ++++++++++--------- tests/Builder/AsyncBuilderTraitTest.php | 23 +++++-- 3 files changed, 72 insertions(+), 32 deletions(-) diff --git a/phpstan.dist.neon b/phpstan.dist.neon index 2c0de7e2..d8c860ef 100644 --- a/phpstan.dist.neon +++ b/phpstan.dist.neon @@ -53,3 +53,23 @@ parameters: message: "#^Parameter \\#2 \\$cookie of method Sensiolabs\\\\GotenbergBundle\\\\Builder\\\\Screenshot\\\\AbstractChromiumScreenshotBuilder\\:\\:setCookie\\(\\) expects array\\{name\\: string, value\\: string, domain\\: string, path\\?\\: string\\|null, secure\\?\\: bool\\|null, httpOnly\\?\\: bool\\|null, sameSite\\?\\: 'Lax'\\|'Strict'\\|null\\}\\|Symfony\\\\Component\\\\HttpFoundation\\\\Cookie, array\\{name\\: string, value\\: string\\|null, domain\\: string\\} given\\.$#" count: 1 path: src/Builder/Screenshot/AbstractChromiumScreenshotBuilder.php + + - + message: "#^Call to an undefined method Sensiolabs\\\\GotenbergBundle\\\\Builder\\\\AsyncBuilderInterface\\:\\:errorWebhookUrl\\(\\)\\.$#" + count: 2 + path: tests/Builder/AsyncBuilderTraitTest.php + + - + message: "#^Call to an undefined method Sensiolabs\\\\GotenbergBundle\\\\Builder\\\\AsyncBuilderInterface\\:\\:webhookConfiguration\\(\\)\\.$#" + count: 1 + path: tests/Builder/AsyncBuilderTraitTest.php + + - + message: "#^Call to an undefined method Sensiolabs\\\\GotenbergBundle\\\\Builder\\\\AsyncBuilderInterface\\:\\:webhookExtraHeaders\\(\\)\\.$#" + count: 1 + path: tests/Builder/AsyncBuilderTraitTest.php + + - + message: "#^Call to an undefined method Sensiolabs\\\\GotenbergBundle\\\\Builder\\\\AsyncBuilderInterface\\:\\:webhookUrl\\(\\)\\.$#" + count: 4 + path: tests/Builder/AsyncBuilderTraitTest.php diff --git a/src/DependencyInjection/SensiolabsGotenbergExtension.php b/src/DependencyInjection/SensiolabsGotenbergExtension.php index 5863bbfc..b9c490fa 100644 --- a/src/DependencyInjection/SensiolabsGotenbergExtension.php +++ b/src/DependencyInjection/SensiolabsGotenbergExtension.php @@ -13,6 +13,33 @@ use Symfony\Component\Routing\RequestContext; /** + * @phpstan-type SensiolabsGotenbergConfiguration array{ + * assets_directory: string, + * http_client: string, + * request_context?: array{base_uri?: string}, + * controller_listener: bool, + * webhook: array + * }>, + * default_options: array{ + * webhook?: string, + * pdf: array{ + * html: array, + * url: array, + * markdown: array, + * office: array, + * merge: array, + * convert: array + * }, + * screenshot: array{ + * html: array, + * url: array, + * markdown: array + * } + * } + * } * @phpstan-type WebhookDefinition array{url?: string, route?: array{0: string, 1: array}, method?: 'POST'|'PUT'|'PATCH'|null} */ class SensiolabsGotenbergExtension extends Extension @@ -21,34 +48,7 @@ public function load(array $configs, ContainerBuilder $container): void { $configuration = new Configuration(); - /** @var array{ - * base_uri: string, - * http_client: string, - * controller_listener: bool, - * request_context?: array{base_uri?: string}, - * assets_directory: string, - * webhook: array - * }>, - * default_options: array{ - * webhook?: string, - * pdf: array{ - * html: array, - * url: array, - * markdown: array, - * office: array, - * merge: array, - * convert: array - * }, - * screenshot: array{ - * html: array, - * url: array, - * markdown: array - * } - * } - * } $config + /** @var SensiolabsGotenbergConfiguration $config */ $config = $this->processConfiguration($configuration, $configs); @@ -134,6 +134,10 @@ private function cleanUserOptions(array $userConfigurations): array }, \ARRAY_FILTER_USE_BOTH); } + /** + * @param SensiolabsGotenbergConfiguration $config + * @param array $serviceConfig + */ private function processDefaultOptions(ContainerBuilder $container, array $config, string $serviceId, array $serviceConfig): void { $definition = $container->getDefinition($serviceId); @@ -145,6 +149,7 @@ private function processDefaultOptions(ContainerBuilder $container, array $confi /** * @param array}> $webhookConfig + * @param array $config */ private function processWebhookOptions(ContainerBuilder $container, string $serviceId, array $webhookConfig, string|null $webhookDefaultConfigName, array $config): void { diff --git a/tests/Builder/AsyncBuilderTraitTest.php b/tests/Builder/AsyncBuilderTraitTest.php index 9aff1238..18801ba6 100644 --- a/tests/Builder/AsyncBuilderTraitTest.php +++ b/tests/Builder/AsyncBuilderTraitTest.php @@ -5,6 +5,7 @@ use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\Attributes\UsesClass; use PHPUnit\Framework\TestCase; +use Sensiolabs\GotenbergBundle\Builder\AsyncBuilderInterface; use Sensiolabs\GotenbergBundle\Builder\AsyncBuilderTrait; use Sensiolabs\GotenbergBundle\Builder\DefaultBuilderTrait; use Sensiolabs\GotenbergBundle\Client\GotenbergClient; @@ -12,6 +13,7 @@ use Sensiolabs\GotenbergBundle\Exception\MissingRequiredFieldException; use Sensiolabs\GotenbergBundle\Formatter\AssetBaseDirFormatter; use Sensiolabs\GotenbergBundle\Webhook\WebhookConfigurationRegistryInterface; +use Symfony\Component\Filesystem\Filesystem; use Symfony\Component\HttpClient\MockHttpClient; use Symfony\Component\HttpClient\Response\MockResponse; use Symfony\Contracts\HttpClient\HttpClientInterface; @@ -173,7 +175,7 @@ public function get(string $name): array $builder->generateAsync(); } - private function getBuilder(MockHttpClient $httpClient, WebhookConfigurationRegistryInterface|null $registry = null): object + private function getBuilder(MockHttpClient $httpClient, WebhookConfigurationRegistryInterface|null $registry = null): AsyncBuilderInterface { $registry ??= new class implements WebhookConfigurationRegistryInterface { public function add(string $name, array $configuration): void @@ -183,17 +185,27 @@ public function add(string $name, array $configuration): void public function get(string $name): array { - // TODO: Implement get() method. + return [ + 'success' => [ + 'url' => 'https://webhook.local', + 'method' => 'POST', + ], + 'error' => [ + 'url' => 'https://webhook.local/error', + 'method' => 'POST', + ], + ]; } }; - return new class($httpClient, $registry) { + return new class($httpClient, $registry) implements AsyncBuilderInterface { use AsyncBuilderTrait; public function __construct(HttpClientInterface $httpClient, WebhookConfigurationRegistryInterface $registry) { $this->client = new GotenbergClient($httpClient); $this->webhookConfigurationRegistry = $registry; + $this->asset = new AssetBaseDirFormatter(new Filesystem(), '', ''); } protected function getEndpoint(): string @@ -201,9 +213,12 @@ protected function getEndpoint(): string return '/fake/endpoint'; } + /** + * @param array $configurations + */ public function setConfigurations(array $configurations): static { - // TODO: Implement setConfigurations() method. + return $this; } }; }