Skip to content

Commit

Permalink
Add Listener on kernel.view for GotenbergFileResult to automatically …
Browse files Browse the repository at this point in the history
…convert to stream. (#111)
  • Loading branch information
Neirda24 authored Oct 6, 2024
1 parent 456c79b commit 121d8d9
Show file tree
Hide file tree
Showing 9 changed files with 84 additions and 6 deletions.
5 changes: 5 additions & 0 deletions config/services.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

use Sensiolabs\GotenbergBundle\Client\GotenbergClient;
use Sensiolabs\GotenbergBundle\Client\GotenbergClientInterface;
use Sensiolabs\GotenbergBundle\EventListener\ProcessBuilderOnControllerResponse;
use Sensiolabs\GotenbergBundle\Formatter\AssetBaseDirFormatter;
use Sensiolabs\GotenbergBundle\Gotenberg;
use Sensiolabs\GotenbergBundle\GotenbergInterface;
Expand Down Expand Up @@ -63,4 +64,8 @@
])
->alias(GotenbergInterface::class, 'sensiolabs_gotenberg')
;

$services->set('sensiolabs_gotenberg.http_kernel.stream_builder', ProcessBuilderOnControllerResponse::class)
->tag('kernel.event_listener', ['method' => 'streamBuilder', 'event' => 'kernel.view'])
;
};
8 changes: 8 additions & 0 deletions docs/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ Then

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`.
# Override the request Gotenberg will make to call one of your routes.
request_context:
Expand Down Expand Up @@ -291,3 +292,10 @@ sensiolabs_gotenberg:

> [!TIP]
> For more information about [metadata](https://gotenberg.dev/docs/routes#metadata-chromium).

## Controller Listener

Whenever a controller returns something other than a `Response` object, the [`kernel.view`](https://symfony.com/doc/current/reference/events.html#kernel-view) event is fired.
That listener listen to this event and detects if it is a `GotenbergFileResult` object. If so it automatically calls the `->stream()` method to convert it to a Response object.

Enabled byd efault but can be disabled via the `sensiolabs_gotenberg.controller_listener` configuration.
9 changes: 9 additions & 0 deletions phpstan.neon
Original file line number Diff line number Diff line change
Expand Up @@ -44,3 +44,12 @@ parameters:
message: "#^Parameter \\#1 \\$iterator of function iterator_to_array expects Traversable, iterable given\\.$#"
count: 1
path: tests/Builder/AbstractBuilderTestCase.php
-
message: "#^Parameter \\#2 \\$cookie of method Sensiolabs\\\\GotenbergBundle\\\\Builder\\\\Pdf\\\\AbstractChromiumPdfBuilder\\:\\: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/Pdf/AbstractChromiumPdfBuilder.php

-
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
4 changes: 4 additions & 0 deletions src/DependencyInjection/Configuration.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@ public function getConfigTreeBuilder(): TreeBuilder
->end()
->end()
->end()
->booleanNode('controller_listener')
->defaultTrue()
->info('Enables the listener on kernel.view to stream GotenbergFileResult object.')
->end()
->arrayNode('default_options')
->addDefaultsIfNotSet()
->children()
Expand Down
14 changes: 8 additions & 6 deletions src/DependencyInjection/SensiolabsGotenbergExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,18 @@ 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<string, mixed>, url: array<string, mixed>, markdown: array<string, mixed>, office: array<string, mixed>, merge: array<string, mixed>, convert: array<string, mixed>}, screenshot: array{html: array<string, mixed>, url: array<string, mixed>, markdown: array<string, mixed>}}} $config */
/** @var array{base_uri: string, http_client: string, controller_listener: bool, request_context?: array{base_uri?: string}, assets_directory: string, default_options: array{pdf: array{html: array<string, mixed>, url: array<string, mixed>, markdown: array<string, mixed>, office: array<string, mixed>, merge: array<string, mixed>, convert: array<string, mixed>}, screenshot: array{html: array<string, mixed>, url: array<string, mixed>, markdown: array<string, mixed>}}} $config */
$config = $this->processConfiguration($configuration, $configs);

$loader = new PhpFileLoader($container, new FileLocator(__DIR__.'/../../config'));
$loader->load('builder_pdf.php');
$loader->load('builder_screenshot.php');
$loader->load('services.php');

if (false === $config['controller_listener']) {
$container->removeDefinition('sensiolabs_gotenberg.http_kernel.stream_builder');
}

if ($container->getParameter('kernel.debug') === true) {
$loader->load('debug.php');
$container->getDefinition('sensiolabs_gotenberg.data_collector')
Expand All @@ -48,7 +52,7 @@ public function load(array $configs, ContainerBuilder $container): void
->addTag('sensiolabs_gotenberg.screenshot_builder')
;

$container->setAlias('sensiolabs_gotenberg.http_client', new Alias($config['http_client'] ?? 'http_client', false));
$container->setAlias('sensiolabs_gotenberg.http_client', new Alias($config['http_client'], false));

$baseUri = $config['request_context']['base_uri'] ?? null;

Expand Down Expand Up @@ -92,11 +96,9 @@ public function load(array $configs, ContainerBuilder $container): void
}

/**
* @template T of array<string, mixed>
*
* @param T $userConfigurations
* @param array<string, mixed> $userConfigurations
*
* @return array<key-of<T>, value-of<T>>
* @return array<string, mixed>
*/
private function cleanUserOptions(array $userConfigurations): array
{
Expand Down
22 changes: 22 additions & 0 deletions src/EventListener/ProcessBuilderOnControllerResponse.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?php

declare(strict_types=1);

namespace Sensiolabs\GotenbergBundle\EventListener;

use Sensiolabs\GotenbergBundle\Builder\GotenbergFileResult;
use Symfony\Component\HttpKernel\Event\ViewEvent;

final class ProcessBuilderOnControllerResponse
{
public function streamBuilder(ViewEvent $event): void
{
$controllerResult = $event->getControllerResult();

if (!$controllerResult instanceof GotenbergFileResult) {
return;
}

$event->setResponse($controllerResult->stream());
}
}
2 changes: 2 additions & 0 deletions tests/Builder/Pdf/AbstractChromiumPdfBuilderTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
use PHPUnit\Framework\Attributes\UsesClass;
use Sensiolabs\GotenbergBundle\Builder\Pdf\AbstractChromiumPdfBuilder;
use Sensiolabs\GotenbergBundle\Builder\Pdf\AbstractPdfBuilder;
use Sensiolabs\GotenbergBundle\Enumeration\PaperSize;
use Sensiolabs\GotenbergBundle\Enumeration\PaperSizeInterface;
use Sensiolabs\GotenbergBundle\Enumeration\PdfFormat;
use Sensiolabs\GotenbergBundle\Enumeration\Unit;
Expand All @@ -24,6 +25,7 @@
#[UsesClass(Unit::class)]
#[UsesClass(AssetBaseDirFormatter::class)]
#[UsesClass(GotenbergAssetExtension::class)]
#[UsesClass(PaperSize::class)]
class AbstractChromiumPdfBuilderTest extends AbstractBuilderTestCase
{
public static function configurationIsCorrectlySetProvider(): \Generator
Expand Down
1 change: 1 addition & 0 deletions tests/DependencyInjection/ConfigurationTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,7 @@ private static function getBundleDefaultConfig(): array
return [
'assets_directory' => '%kernel.project_dir%/assets',
'http_client' => 'http_client',
'controller_listener' => true,
'default_options' => [
'pdf' => [
'html' => [
Expand Down
25 changes: 25 additions & 0 deletions tests/DependencyInjection/SensiolabsGotenbergExtensionTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -573,4 +573,29 @@ private static function getValidConfig(): array
],
];
}

public function testControllerListenerIsEnabledByDefault(): void
{
$extension = new SensiolabsGotenbergExtension();

$containerBuilder = $this->getContainerBuilder(kernelDebug: false);
$extension->load([[
'http_client' => 'http_client',
]], $containerBuilder);

self::assertContains('sensiolabs_gotenberg.http_kernel.stream_builder', $containerBuilder->getServiceIds());
}

public function testControllerListenerCanBeDisabled(): void
{
$extension = new SensiolabsGotenbergExtension();

$containerBuilder = $this->getContainerBuilder(kernelDebug: false);
$extension->load([[
'http_client' => 'http_client',
'controller_listener' => false,
]], $containerBuilder);

self::assertNotContains('sensiolabs_gotenberg.http_kernel.stream_builder', $containerBuilder->getServiceIds());
}
}

0 comments on commit 121d8d9

Please sign in to comment.