Skip to content

Commit

Permalink
[FEATURE] Allow changing url generator context for url*builder (#60)
Browse files Browse the repository at this point in the history
  • Loading branch information
Neirda24 authored Jun 5, 2024
1 parent 6f80a82 commit 8e75b85
Show file tree
Hide file tree
Showing 13 changed files with 510 additions and 303 deletions.
18 changes: 12 additions & 6 deletions composer.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{
"name": "sensiolabs/gotenberg-bundle",
"description": "Gotenberg support for Symfony",
"keywords": ["gotenberg", "symfony", "pdf", "screenshot", "office", "bundle"],
"type": "symfony-bundle",
"license": "MIT",
"autoload": {
Expand All @@ -20,24 +21,28 @@
}
],
"require": {
"php": ">=8.2",
"php": ">=8.1",
"ext-json": "*",
"symfony/config": "^6.4 || ^7.0",
"symfony/dependency-injection": "^6.4 || ^7.0",
"symfony/filesystem": "^6.4 || ^7.0",
"symfony/http-client": "^6.4 || ^7.0",
"symfony/http-foundation": "^6.4 || ^7.0",
"symfony/http-kernel": "^6.4 || ^7.0",
"symfony/mime": "^6.4 || ^7.0",
"symfony/string": "^6.4 || ^7.0",
"symfony/http-client": "^6.4 || ^7.0",
"symfony/filesystem": "^6.4 || ^7.0"
"symfony/string": "^6.4 || ^7.0"
},
"require-dev": {
"friendsofphp/php-cs-fixer": "^3.41",
"phpstan/phpstan": "^1.10",
"phpstan/extension-installer": "^1.3",
"phpstan/phpstan": "^1.10",
"phpstan/phpstan-symfony": "^1.3",
"phpunit/phpunit": "^10.4",
"symfony/framework-bundle": "^6.4 || ^7.0",
"symfony/monolog-bundle": "^3.10",
"symfony/stopwatch": "^6.4 || ^7.0",
"symfony/twig-bundle": "^6.4 || ^7.0",
"symfony/stopwatch": "^6.4 || ^7.0"
"symfony/var-dumper": "^6.4 || ^7.0"
},
"config": {
"allow-plugins": {
Expand All @@ -46,6 +51,7 @@
"sort-packages": true
},
"suggest": {
"symfony/monolog-bundle": "Enables logging througout the generating process.",
"symfony/twig-bundle": "Allows you to use Twig to render templates into PDF"
}
}
1 change: 1 addition & 0 deletions config/builder_pdf.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
service('twig')->nullOnInvalid(),
service('router')->nullOnInvalid(),
])
->call('setRequestContext', [service('.sensiolabs_gotenberg.request_context')->nullOnInvalid()])
->tag('sensiolabs_gotenberg.pdf_builder')
;

Expand Down
1 change: 1 addition & 0 deletions config/builder_screenshot.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
service('twig')->nullOnInvalid(),
service('router')->nullOnInvalid(),
])
->call('setRequestContext', [service('.sensiolabs_gotenberg.request_context')->nullOnInvalid()])
->tag('sensiolabs_gotenberg.screenshot_builder')
;

Expand Down
24 changes: 24 additions & 0 deletions phpstan.neon
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,30 @@ parameters:
- 'src'
- 'tests'
ignoreErrors:
-
message: "#^Cannot call method generate\\(\\) on Symfony\\\\Component\\\\Routing\\\\Generator\\\\UrlGeneratorInterface\\|null\\.$#"
count: 1
path: src/Builder/Pdf/UrlPdfBuilder.php
-
message: "#^Cannot call method getContext\\(\\) on Symfony\\\\Component\\\\Routing\\\\Generator\\\\UrlGeneratorInterface\\|null\\.$#"
count: 1
path: src/Builder/Pdf/UrlPdfBuilder.php
-
message: "#^Cannot call method setContext\\(\\) on Symfony\\\\Component\\\\Routing\\\\Generator\\\\UrlGeneratorInterface\\|null\\.$#"
count: 2
path: src/Builder/Pdf/UrlPdfBuilder.php
-
message: "#^Cannot call method generate\\(\\) on Symfony\\\\Component\\\\Routing\\\\Generator\\\\UrlGeneratorInterface\\|null\\.$#"
count: 1
path: src/Builder/Screenshot/UrlScreenshotBuilder.php
-
message: "#^Cannot call method getContext\\(\\) on Symfony\\\\Component\\\\Routing\\\\Generator\\\\UrlGeneratorInterface\\|null\\.$#"
count: 1
path: src/Builder/Screenshot/UrlScreenshotBuilder.php
-
message: "#^Cannot call method setContext\\(\\) on Symfony\\\\Component\\\\Routing\\\\Generator\\\\UrlGeneratorInterface\\|null\\.$#"
count: 2
path: src/Builder/Screenshot/UrlScreenshotBuilder.php
-
message: "#^Cannot use array destructuring on array\\<int, string\\|null\\>\\|null\\.$#"
count: 1
Expand Down
2 changes: 1 addition & 1 deletion src/Builder/Pdf/AbstractChromiumPdfBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -523,7 +523,7 @@ protected function withRenderedPart(Part $pdfPart, string $template, array $cont
return $this;
}

private function addConfiguration(string $configurationName, mixed $value): void
protected function addConfiguration(string $configurationName, mixed $value): void
{
match ($configurationName) {
'single_page' => $this->singlePage($value),
Expand Down
48 changes: 45 additions & 3 deletions src/Builder/Pdf/UrlPdfBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,31 @@
use Sensiolabs\GotenbergBundle\Exception\MissingRequiredFieldException;
use Sensiolabs\GotenbergBundle\Formatter\AssetBaseDirFormatter;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Symfony\Component\Routing\RequestContext;
use Twig\Environment;

final class UrlPdfBuilder extends AbstractChromiumPdfBuilder
{
private const ENDPOINT = '/forms/chromium/convert/url';

private RequestContext|null $requestContext = null;

public function __construct(
GotenbergClientInterface $gotenbergClient,
AssetBaseDirFormatter $asset,
Environment|null $twig = null,
private readonly UrlGeneratorInterface|null $urlGenerator = null,
) {
parent::__construct($gotenbergClient, $asset, $twig);

$this->addNormalizer('route', $this->generateUrlFromRoute(...));
}

public function setRequestContext(RequestContext|null $requestContext = null): self
{
$this->requestContext = $requestContext;

return $this;
}

/**
Expand All @@ -34,20 +46,50 @@ public function url(string $url): self
/**
* @param string $name #Route
* @param array<mixed> $parameters
*
* @phpstan-assert !null $this->urlGenerator
*/
public function route(string $name, array $parameters = []): self
{
if (null === $this->urlGenerator) {
throw new \LogicException(sprintf('Router is required to use "%s" method. Try to run "composer require symfony/routing".', __METHOD__));
}

return $this->url($this->urlGenerator->generate($name, $parameters, UrlGeneratorInterface::ABSOLUTE_URL));
$this->formFields['route'] = [$name, $parameters];

return $this;
}

/**
* @param array{string, array<mixed>} $value
*
* @return array{url: string}
*/
private function generateUrlFromRoute(array $value): array
{
[$route, $parameters] = $value;

$requestContext = $this->urlGenerator->getContext();

if (null !== $this->requestContext) {
$this->urlGenerator->setContext($this->requestContext);
}

try {
return ['url' => $this->urlGenerator->generate($route, $parameters, UrlGeneratorInterface::ABSOLUTE_URL)];
} finally {
$this->urlGenerator->setContext($requestContext);
}
}

public function getMultipartFormData(): array
{
if (!\array_key_exists('url', $this->formFields)) {
throw new MissingRequiredFieldException('URL is required');
if (!\array_key_exists('url', $this->formFields) && !\array_key_exists('route', $this->formFields)) {
throw new MissingRequiredFieldException('URL (or route) is required');
}

if (\array_key_exists('url', $this->formFields) && \array_key_exists('route', $this->formFields)) {
throw new MissingRequiredFieldException('Provide only one of ["route", "url"] parameter. Not both.');
}

return parent::getMultipartFormData();
Expand Down
52 changes: 47 additions & 5 deletions src/Builder/Screenshot/UrlScreenshotBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,31 @@
use Sensiolabs\GotenbergBundle\Exception\MissingRequiredFieldException;
use Sensiolabs\GotenbergBundle\Formatter\AssetBaseDirFormatter;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Symfony\Component\Routing\RequestContext;
use Twig\Environment;

final class UrlScreenshotBuilder extends AbstractChromiumScreenshotBuilder
{
private const ENDPOINT = '/forms/chromium/screenshot/url';

private RequestContext|null $requestContext = null;

public function __construct(
GotenbergClientInterface $gotenbergClient,
AssetBaseDirFormatter $asset,
Environment|null $twig = null,
private readonly UrlGeneratorInterface|null $urlGenerator = null,
) {
parent::__construct($gotenbergClient, $asset, $twig);

$this->addNormalizer('route', $this->generateUrlFromRoute(...));
}

public function setRequestContext(RequestContext|null $requestContext = null): self
{
$this->requestContext = $requestContext;

return $this;
}

/**
Expand All @@ -32,22 +44,52 @@ public function url(string $url): self
}

/**
* @param string $name #Route
* @param array<string, mixed> $parameters
* @param string $name #Route
* @param array<mixed> $parameters
*
* @phpstan-assert !null $this->urlGenerator
*/
public function route(string $name, array $parameters = []): self
{
if (null === $this->urlGenerator) {
throw new \LogicException(sprintf('Router is required to use "%s" method. Try to run "composer require symfony/routing".', __METHOD__));
}

return $this->url($this->urlGenerator->generate($name, $parameters, UrlGeneratorInterface::ABSOLUTE_URL));
$this->formFields['route'] = [$name, $parameters];

return $this;
}

/**
* @param array{string, array<mixed>} $value
*
* @return array{url: string}
*/
private function generateUrlFromRoute(array $value): array
{
[$route, $parameters] = $value;

$requestContext = $this->urlGenerator->getContext();

if (null !== $this->requestContext) {
$this->urlGenerator->setContext($this->requestContext);
}

try {
return ['url' => $this->urlGenerator->generate($route, $parameters, UrlGeneratorInterface::ABSOLUTE_URL)];
} finally {
$this->urlGenerator->setContext($requestContext);
}
}

public function getMultipartFormData(): array
{
if (!\array_key_exists('url', $this->formFields)) {
throw new MissingRequiredFieldException('URL is required');
if (!\array_key_exists('url', $this->formFields) && !\array_key_exists('route', $this->formFields)) {
throw new MissingRequiredFieldException('URL (or route) is required');
}

if (\array_key_exists('url', $this->formFields) && \array_key_exists('route', $this->formFields)) {
throw new MissingRequiredFieldException('Provide only one of ["route", "url"] parameter. Not both.');
}

return parent::getMultipartFormData();
Expand Down
Loading

0 comments on commit 8e75b85

Please sign in to comment.