Skip to content

Commit

Permalink
Update configuration (#24)
Browse files Browse the repository at this point in the history
* Update configuration
  • Loading branch information
StevenRenaux authored Apr 11, 2024
1 parent b3a547f commit 753149a
Show file tree
Hide file tree
Showing 9 changed files with 154 additions and 138 deletions.
61 changes: 5 additions & 56 deletions src/Builder/AbstractChromiumPdfBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

use Sensiolabs\GotenbergBundle\Client\GotenbergClientInterface;
use Sensiolabs\GotenbergBundle\Enum\PdfPart;
use Sensiolabs\GotenbergBundle\Exception\ExtraHttpHeadersJsonEncodingException;
use Sensiolabs\GotenbergBundle\Exception\InvalidBuilderConfiguration;
use Sensiolabs\GotenbergBundle\Exception\PdfPartRenderingException;
use Sensiolabs\GotenbergBundle\Formatter\AssetBaseDirFormatter;
Expand Down Expand Up @@ -194,7 +193,7 @@ public function nativePageRanges(string $range): static
}

/**
* @param string $template #Template
* @param string $template #Template
* @param array<string, mixed> $context
*
* @throws PdfPartRenderingException if the template could not be rendered
Expand All @@ -205,7 +204,7 @@ public function header(string $template, array $context = []): static
}

/**
* @param string $template #Template
* @param string $template #Template
* @param array<string, mixed> $context
*
* @throws PdfPartRenderingException if the template could not be rendered
Expand Down Expand Up @@ -313,7 +312,7 @@ public function userAgent(string $userAgent): static

/**
* Sets extra HTTP headers that Chromium will send when loading the HTML
* document. (default None).
* document. (default None). (overrides any previous headers).
*
* @see https://gotenberg.dev/docs/routes#custom-http-headers
*
Expand All @@ -336,10 +335,7 @@ public function extraHttpHeaders(array $headers): static
*/
public function addExtraHttpHeaders(array $headers): static
{
$this->formFields['extraHttpHeaders'] = [
...$this->formFields['extraHttpHeaders'],
...$headers,
];
$this->formFields['extraHttpHeaders'] = array_merge($this->formFields['extraHttpHeaders'] ?? [], $headers);

return $this;
}
Expand Down Expand Up @@ -381,53 +377,6 @@ public function pdfUniversalAccess(bool $bool = true): static
return $this;
}

/**
* @throws ExtraHttpHeadersJsonEncodingException
*/
public function getMultipartFormData(): array
{
$formFields = $this->formFields;
$multipartFormData = [];

$extraHttpHeaders = $this->formFields['extraHttpHeaders'] ?? [];
if ([] !== $extraHttpHeaders) {
try {
$extraHttpHeaders = json_encode($extraHttpHeaders, \JSON_THROW_ON_ERROR);
} catch (\JsonException $exception) {
throw new ExtraHttpHeadersJsonEncodingException('Could not encode extra HTTP headers into JSON', previous: $exception);
}

$multipartFormData[] = [
'extraHttpHeaders' => $extraHttpHeaders,
];
unset($formFields['extraHttpHeaders']);
}

foreach ($formFields as $key => $value) {
if (\is_bool($value)) {
$multipartFormData[] = [
$key => $value ? 'true' : 'false',
];
continue;
}

if (\is_array($value)) {
foreach ($value as $nestedValue) {
$multipartFormData[] = [
($nestedValue instanceof DataPart ? 'files' : $key) => $nestedValue,
];
}
continue;
}

$multipartFormData[] = [
($value instanceof DataPart ? 'files' : $key) => $value,
];
}

return $multipartFormData;
}

protected function withPdfPartFile(PdfPart $pdfPart, string $path): static
{
$dataPart = new DataPart(
Expand All @@ -441,7 +390,7 @@ protected function withPdfPartFile(PdfPart $pdfPart, string $path): static
}

/**
* @param string $template #Template
* @param string $template #Template
* @param array<string, mixed> $context
*
* @throws PdfPartRenderingException if the template could not be rendered
Expand Down
111 changes: 103 additions & 8 deletions src/Builder/AbstractPdfBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,12 @@

use Sensiolabs\GotenbergBundle\Client\GotenbergClientInterface;
use Sensiolabs\GotenbergBundle\Client\PdfResponse;
use Sensiolabs\GotenbergBundle\Enum\PdfPart;
use Sensiolabs\GotenbergBundle\Exception\ExtraHttpHeadersJsonEncodingException;
use Sensiolabs\GotenbergBundle\Formatter\AssetBaseDirFormatter;
use Symfony\Component\HttpFoundation\File\File;
use Symfony\Component\HttpFoundation\HeaderUtils;
use Symfony\Component\Mime\Part\DataPart;

abstract class AbstractPdfBuilder implements PdfBuilderInterface
{
Expand All @@ -19,19 +22,40 @@ abstract class AbstractPdfBuilder implements PdfBuilderInterface

private string $headerDisposition = HeaderUtils::DISPOSITION_INLINE;

/**
* @var array<string, (\Closure(mixed): array<string, array<string|int ,mixed>|non-empty-string|int|float|bool|DataPart>)>
*/
private array $normalizers;

public function __construct(
protected readonly GotenbergClientInterface $gotenbergClient,
protected readonly AssetBaseDirFormatter $asset,
) {
$this->normalizers = [
'extraHttpHeaders' => static function (mixed $value): array {
try {
$extraHttpHeaders = json_encode($value, \JSON_THROW_ON_ERROR);
} catch (\JsonException $exception) {
throw new ExtraHttpHeadersJsonEncodingException('Could not encode extra HTTP headers into JSON', previous: $exception);
}

return ['extraHttpHeaders' => $extraHttpHeaders];
},
'assets' => static function (array $value): array {
return ['files' => $value];
},
PdfPart::HeaderPart->value => static function (DataPart $value): array {
return ['files' => $value];
},
PdfPart::BodyPart->value => static function (DataPart $value): array {
return ['files' => $value];
},
PdfPart::FooterPart->value => static function (DataPart $value): array {
return ['files' => $value];
},
];
}

/**
* Compiles the form values into a multipart form data array to send to the HTTP client.
*
* @return list<array<string, string>>
*/
abstract public function getMultipartFormData(): array;

/**
* The Gotenberg API endpoint path.
*/
Expand Down Expand Up @@ -60,7 +84,7 @@ public function generate(): PdfResponse
if (null !== $this->fileName) {
$disposition = HeaderUtils::makeDisposition(
$this->headerDisposition,
$this->fileName
$this->fileName,
);

$pdfResponse
Expand All @@ -71,6 +95,77 @@ public function generate(): PdfResponse
return $pdfResponse;
}

/**
* Compiles the form values into a multipart form data array to send to the HTTP client.
*
* @return array<int, array<string, string>>
*/
public function getMultipartFormData(): array
{
$multipartFormData = [];

foreach ($this->formFields as $key => $value) {
$preCallback = null;

if (\array_key_exists($key, $this->normalizers)) {
$preCallback = $this->normalizers[$key](...);
}

foreach ($this->addToMultipart($key, $value, $preCallback) as $multiPart) {
$multipartFormData[] = $multiPart;
}
}

return $multipartFormData;
}

protected function addNormalizer(string $key, \Closure $normalizer): void
{
$this->normalizers[$key] = $normalizer;
}

/**
* @param array<int|string, mixed>|string|int|float|bool|DataPart $value
*
* @return list<array<string, mixed>>
*/
private function addToMultipart(string $key, array|string|int|float|bool|DataPart $value, \Closure|null $preCallback = null): array
{
if (null !== $preCallback) {
$result = [];
foreach ($preCallback($value) as $key => $value) {
$result[] = $this->addToMultipart($key, $value);

return array_merge(...$result);
}
}

if (\is_bool($value)) {
return [[
$key => $value ? 'true' : 'false',
]];
}

if (\is_int($value) || \is_float($value)) {
return [[
$key => (string) $value,
]];
}

if (\is_array($value)) {
$result = [];
foreach ($value as $nestedValue) {
$result[] = $this->addToMultipart($key, $nestedValue);
}

return array_merge(...$result);
}

return [[
$key => $value,
]];
}

/**
* @param non-empty-list<string> $validExtensions
*/
Expand Down
2 changes: 1 addition & 1 deletion src/Builder/HtmlPdfBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ final class HtmlPdfBuilder extends AbstractChromiumPdfBuilder
private const ENDPOINT = '/forms/chromium/convert/html';

/**
* @param string $template #Template
* @param string $template #Template
* @param array<string, mixed> $context
*
* @throws PdfPartRenderingException if the template could not be rendered
Expand Down
28 changes: 1 addition & 27 deletions src/Builder/LibreOfficePdfBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -110,33 +110,7 @@ public function getMultipartFormData(): array
throw new MissingRequiredFieldException('At least one office file is required');
}

$formFields = $this->formFields;
$multipartFormData = [];

$files = $this->formFields['files'] ?? [];
if ([] !== $files) {
foreach ($files as $dataPart) {
$multipartFormData[] = [
'files' => $dataPart,
];
}
unset($formFields['files']);
}

foreach ($formFields as $key => $value) {
if (\is_bool($value)) {
$multipartFormData[] = [
$key => $value ? 'true' : 'false',
];
continue;
}

$multipartFormData[] = [
$key => $value,
];
}

return $multipartFormData;
return parent::getMultipartFormData();
}

protected function getEndpoint(): string
Expand Down
2 changes: 1 addition & 1 deletion src/Builder/MarkdownPdfBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ final class MarkdownPdfBuilder extends AbstractChromiumPdfBuilder
/**
* The HTML file that wraps the markdown content, rendered from a Twig template.
*
* @param string $template #Template
* @param string $template #Template
* @param array<string, mixed> $context
*
* @throws PdfPartRenderingException if the template could not be rendered
Expand Down
3 changes: 3 additions & 0 deletions src/Pdf/GotenbergInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,10 @@ interface GotenbergInterface
public function get(string $builder): PdfBuilderInterface;

public function html(): HtmlPdfBuilder;

public function url(): UrlPdfBuilder;

public function office(): LibreOfficePdfBuilder;

public function markdown(): MarkdownPdfBuilder;
}
46 changes: 23 additions & 23 deletions tests/Builder/HtmlPdfBuilderTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,32 +30,32 @@ public function testWithConfigurations(): void

self::assertCount(21, $multipartFormData);

self::assertSame(['extraHttpHeaders' => '{"MyHeader":"Value","User-Agent":"MyValue"}'], $multipartFormData[0]);
self::assertSame(['paperWidth' => 33.1], $multipartFormData[2]);
self::assertSame(['paperHeight' => 46.8], $multipartFormData[3]);
self::assertSame(['marginTop' => 1.0], $multipartFormData[4]);
self::assertSame(['marginBottom' => 1.0], $multipartFormData[5]);
self::assertSame(['marginLeft' => 1.0], $multipartFormData[6]);
self::assertSame(['marginRight' => 1.0], $multipartFormData[7]);
self::assertSame(['preferCssPageSize' => 'true'], $multipartFormData[8]);
self::assertSame(['printBackground' => 'true'], $multipartFormData[9]);
self::assertSame(['omitBackground' => 'true'], $multipartFormData[10]);
self::assertSame(['landscape' => 'true'], $multipartFormData[11]);
self::assertSame(['scale' => 1.5], $multipartFormData[12]);
self::assertSame(['nativePageRanges' => '1-5'], $multipartFormData[13]);
self::assertSame(['waitDelay' => '10s'], $multipartFormData[14]);
self::assertSame(['waitForExpression' => 'window.globalVar === "ready"'], $multipartFormData[15]);
self::assertSame(['emulatedMediaType' => 'screen'], $multipartFormData[16]);
self::assertSame(['userAgent' => 'Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML => like Gecko) Version/11.0 Mobile/15A372 Safari/604.1'], $multipartFormData[17]);
self::assertIsArray($multipartFormData[0]);
self::assertCount(1, $multipartFormData[0]);
self::assertArrayHasKey('files', $multipartFormData[0]);
self::assertInstanceOf(DataPart::class, $multipartFormData[0]['files']);
self::assertSame('index.html', $multipartFormData[0]['files']->getFilename());

self::assertSame(['paperWidth' => '33.1'], $multipartFormData[1]);
self::assertSame(['paperHeight' => '46.8'], $multipartFormData[2]);
self::assertSame(['marginTop' => '1'], $multipartFormData[3]);
self::assertSame(['marginBottom' => '1'], $multipartFormData[4]);
self::assertSame(['marginLeft' => '1'], $multipartFormData[5]);
self::assertSame(['marginRight' => '1'], $multipartFormData[6]);
self::assertSame(['preferCssPageSize' => 'true'], $multipartFormData[7]);
self::assertSame(['printBackground' => 'true'], $multipartFormData[8]);
self::assertSame(['omitBackground' => 'true'], $multipartFormData[9]);
self::assertSame(['landscape' => 'true'], $multipartFormData[10]);
self::assertSame(['scale' => '1.5'], $multipartFormData[11]);
self::assertSame(['nativePageRanges' => '1-5'], $multipartFormData[12]);
self::assertSame(['waitDelay' => '10s'], $multipartFormData[13]);
self::assertSame(['waitForExpression' => 'window.globalVar === "ready"'], $multipartFormData[14]);
self::assertSame(['emulatedMediaType' => 'screen'], $multipartFormData[15]);
self::assertSame(['userAgent' => 'Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML => like Gecko) Version/11.0 Mobile/15A372 Safari/604.1'], $multipartFormData[16]);
self::assertSame(['extraHttpHeaders' => '{"MyHeader":"Value","User-Agent":"MyValue"}'], $multipartFormData[17]);
self::assertSame(['failOnConsoleExceptions' => 'true'], $multipartFormData[18]);
self::assertSame(['pdfa' => 'PDF/A-1a'], $multipartFormData[19]);
self::assertSame(['pdfua' => 'true'], $multipartFormData[20]);

self::assertIsArray($multipartFormData[1]);
self::assertCount(1, $multipartFormData[1]);
self::assertArrayHasKey('files', $multipartFormData[1]);
self::assertInstanceOf(DataPart::class, $multipartFormData[1]['files']);
self::assertSame('index.html', $multipartFormData[1]['files']->getFilename());
}

public function testWithTemplate(): void
Expand Down
Loading

0 comments on commit 753149a

Please sign in to comment.