Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add convert endpoint #80

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,8 @@ to the method ``content``.
`wk1`, `wks`, `wmf`, `wpd`, `wpg`, `wps`, `xbm`, `xhtml`, `xls`, `xlsb`, `xlsm`, `xlsx`, `xlt`, `xltm`,
`xltx`, `xlw`, `xml`, `xpm`, `zabw`
6. [Merge Builder](./docs/pdf/merge-builder.md)
7. [PDF customization](./docs/pdf/customization.md) (available for every builder except LibreOffice and Merge)
7. [Convert Builder](./docs/pdf/convert-builder.md)
8. [PDF customization](./docs/pdf/customization.md) (available for every builder except LibreOffice and Merge)

#### Screenshot

Expand Down
11 changes: 11 additions & 0 deletions config/builder_pdf.php
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<?php

use Sensiolabs\GotenbergBundle\Builder\Pdf\ConvertPdfBuilder;
use Sensiolabs\GotenbergBundle\Builder\Pdf\HtmlPdfBuilder;
use Sensiolabs\GotenbergBundle\Builder\Pdf\LibreOfficePdfBuilder;
use Sensiolabs\GotenbergBundle\Builder\Pdf\MarkdownPdfBuilder;
Expand Down Expand Up @@ -69,4 +70,14 @@
->call('setLogger', [service('logger')->nullOnInvalid()])
->tag('sensiolabs_gotenberg.pdf_builder')
;

$services->set('.sensiolabs_gotenberg.pdf_builder.convert', ConvertPdfBuilder::class)
->share(false)
->args([
service('sensiolabs_gotenberg.client'),
service('sensiolabs_gotenberg.asset.base_dir_formatter'),
])
->call('setLogger', [service('logger')->nullOnInvalid()])
->tag('sensiolabs_gotenberg.pdf_builder')
;
};
27 changes: 20 additions & 7 deletions docs/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,27 @@ The default configuration for the bundle looks like :
> If you don't configure anything or configure `null` / `[]`,
> the defaults values on Gotenberg API will be used.

Assuming you have the following client configured.

```yaml
# app/config/sensiolabs_gotenberg.yml

# app/config/framework.yaml

framework:
http_client:
scoped_clients:
gotenberg.client:
base_uri: 'http://localhost:3000'
```

Then

```yaml
# app/config/sensiolabs_gotenberg.yaml

sensiolabs_gotenberg:
base_uri: 'http://localhost:3000'
assets_directory: '%kernel.project_dir%/assets'
http_client: 'http_client'
http_client: 'gotenberg.client'
# 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.
Expand Down Expand Up @@ -125,6 +139,9 @@ sensiolabs_gotenberg:
pdf_format: null # None
pdf_universal_access: null # false
metadata: null # None
convert:
pdf_format: null # None
pdf_universal_access: null # false
screenshot:
html:
width: null # 800
Expand Down Expand Up @@ -186,7 +203,6 @@ HTTP headers to send by Chromium while loading the HTML document.

```yaml
sensiolabs_gotenberg:
base_uri: 'http://localhost:3000'
default_options:
pdf:
html:
Expand All @@ -204,7 +220,6 @@ page is not acceptable.

```yaml
sensiolabs_gotenberg:
base_uri: 'http://localhost:3000'
default_options:
pdf:
html:
Expand All @@ -219,7 +234,6 @@ Cookies to store in the Chromium cookie jar.

``` yaml
sensiolabs_gotenberg:
base_uri: 'http://localhost:3000'
default_options:
pdf:
html:
Expand All @@ -237,7 +251,6 @@ Metadata for the generated document.

``` yaml
sensiolabs_gotenberg:
base_uri: 'http://localhost:3000'
default_options:
pdf:
html:
Expand Down
92 changes: 92 additions & 0 deletions docs/pdf/convert-builder.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
# Convert Builder

You may have the possibility to convert several PDF document.

## Basic usage

> [!WARNING]
> As assets files, by default the PDF files are fetch in the assets folder of
> your application.
> For more information about path resolution go to [assets documentation](../assets.md).


> [!WARNING]
> If you provide multiple PDF files you will get ZIP folder containing all the converted PDF.


```php
namespace App\Controller;

use Sensiolabs\GotenbergBundle\GotenbergPdfInterface;

class YourController
{
public function yourControllerMethod(GotenbergPdfInterface $gotenberg): Response
{
return $gotenberg->convert()
->files(
'document.pdf',
'document_2.pdf',
)
->generate()
;
}
}
```

> [!TIP]
> For more information go to [Gotenberg documentations](https://gotenberg.dev/docs/routes#convert-into-pdfa--pdfua-route).

## pdfFormat

Default: `None`

Convert the resulting PDF into the given PDF/A format.

```php
namespace App\Controller;

use Sensiolabs\GotenbergBundle\Enum\PdfFormat;use Sensiolabs\GotenbergBundle\GotenbergPdfInterface;

class YourController
{
public function yourControllerMethod(GotenbergPdfInterface $gotenberg): Response
{
return $gotenberg->convert()
->files(
'document.pdf',
'document_2.pdf',
)
->pdfFormat(PdfFormat::Pdf1b)
->generate()
;
}
}
```

## pdfUniversalAccess

Default: `false`

Enable PDF for Universal Access for optimal accessibility.

```php
namespace App\Controller;

use Sensiolabs\GotenbergBundle\Enum\PdfFormat;use Sensiolabs\GotenbergBundle\GotenbergPdfInterface;

class YourController
{
public function yourControllerMethod(GotenbergPdfInterface $gotenberg): Response
{
return $gotenberg->convert()
->files(
'document.pdf',
'document_2.pdf',
)
->pdfUniversalAccess() // is same as `->pdfUniversalAccess(true)`
->generate()
;
}
}
```
90 changes: 90 additions & 0 deletions src/Builder/Pdf/ConvertPdfBuilder.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
<?php

namespace Sensiolabs\GotenbergBundle\Builder\Pdf;

use Sensiolabs\GotenbergBundle\Enumeration\PdfFormat;
use Sensiolabs\GotenbergBundle\Exception\InvalidBuilderConfiguration;
use Sensiolabs\GotenbergBundle\Exception\MissingRequiredFieldException;
use Symfony\Component\Mime\Part\DataPart;
use Symfony\Component\Mime\Part\File as DataPartFile;

final class ConvertPdfBuilder extends AbstractPdfBuilder
{
private const ENDPOINT = '/forms/pdfengines/convert';

/**
* To set configurations by an array of configurations.
*
* @param array<string, mixed> $configurations
*/
public function setConfigurations(array $configurations): self
{
foreach ($configurations as $property => $value) {
$this->addConfiguration($property, $value);
}

return $this;
}

/**
* Convert the resulting PDF into the given PDF/A format.
*/
public function pdfFormat(PdfFormat $format): self
{
$this->formFields['pdfa'] = $format->value;

return $this;
}

/**
* Enable PDF for Universal Access for optimal accessibility.
*/
public function pdfUniversalAccess(bool $bool = true): self
{
$this->formFields['pdfua'] = $bool;

return $this;
}

public function files(string ...$paths): self
{
$this->formFields['files'] = [];

foreach ($paths as $path) {
$this->assertFileExtension($path, ['pdf']);

$dataPart = new DataPart(new DataPartFile($this->asset->resolve($path)));

$this->formFields['files'][$path] = $dataPart;
}

return $this;
}

public function getMultipartFormData(): array
{
if (!\array_key_exists('pdfa', $this->formFields) && !\array_key_exists('pdfua', $this->formFields)) {
throw new MissingRequiredFieldException('At least "pdfa" or "pdfua" must be provided.');
}

if ([] === ($this->formFields['files'] ?? [])) {
throw new MissingRequiredFieldException('At least one PDF file is required');
}

return parent::getMultipartFormData();
}

protected function getEndpoint(): string
{
return self::ENDPOINT;
}

private function addConfiguration(string $configurationName, mixed $value): void
{
match ($configurationName) {
'pdf_format' => $this->pdfFormat(PdfFormat::from($value)),
'pdf_universal_access' => $this->pdfUniversalAccess($value),
default => throw new InvalidBuilderConfiguration(sprintf('Invalid option "%s": no method does not exist in class "%s" to configured it.', $configurationName, static::class)),
};
}
}
18 changes: 18 additions & 0 deletions src/Debug/TraceableGotenbergPdf.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace Sensiolabs\GotenbergBundle\Debug;

use Sensiolabs\GotenbergBundle\Builder\Pdf\ConvertPdfBuilder;
use Sensiolabs\GotenbergBundle\Builder\Pdf\HtmlPdfBuilder;
use Sensiolabs\GotenbergBundle\Builder\Pdf\LibreOfficePdfBuilder;
use Sensiolabs\GotenbergBundle\Builder\Pdf\MarkdownPdfBuilder;
Expand Down Expand Up @@ -121,6 +122,23 @@ public function merge(): PdfBuilderInterface
return $traceableBuilder;
}

/**
* @return ConvertPdfBuilder|TraceablePdfBuilder
*/
public function convert(): PdfBuilderInterface
{
/** @var ConvertPdfBuilder|TraceablePdfBuilder $traceableBuilder */
$traceableBuilder = $this->inner->convert();

if (!$traceableBuilder instanceof TraceablePdfBuilder) {
return $traceableBuilder;
}

$this->builders[] = ['convert', $traceableBuilder];

return $traceableBuilder;
}

/**
* @return list<array{string, TraceablePdfBuilder}>
*/
Expand Down
35 changes: 16 additions & 19 deletions src/DependencyInjection/Configuration.php
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ public function getConfigTreeBuilder(): TreeBuilder
->append($this->addPdfMarkdownNode())
->append($this->addPdfOfficeNode())
->append($this->addPdfMergeNode())
->append($this->addPdfConvertNode())
->end()
->arrayNode('screenshot')
->addDefaultsIfNotSet()
Expand Down Expand Up @@ -321,18 +322,11 @@ private function addChromiumPdfOptionsNode(ArrayNodeDefinition $parent): void
->info('Do not wait for Chromium network to be idle. - default false. https://gotenberg.dev/docs/routes#performance-mode-chromium')
->defaultNull()
->end()
->enumNode('pdf_format')
->info('Convert the resulting PDF into the given PDF/A format - default None. https://gotenberg.dev/docs/routes#pdfa-chromium')
->values(array_map(static fn (PdfFormat $case): string => $case->value, PdfFormat::cases()))
->defaultNull()
->end()
->booleanNode('pdf_universal_access')
->info('Enable PDF for Universal Access for optimal accessibility - default false. https://gotenberg.dev/docs/routes#console-exceptions')
->defaultNull()
->end()
->append($this->addPdfMetadata())
->end()
;

$this->addPdfFormat($parent);
}

private function addChromiumScreenshotOptionsNode(ArrayNodeDefinition $parent): void
Expand Down Expand Up @@ -467,7 +461,7 @@ private function addPdfOfficeNode(): NodeDefinition
{
$treeBuilder = new TreeBuilder('office');

return $treeBuilder->getRootNode()
$treeBuilder->getRootNode()
->addDefaultsIfNotSet()
->children()
->booleanNode('landscape')
Expand Down Expand Up @@ -496,18 +490,21 @@ private function addPdfOfficeNode(): NodeDefinition
->info('Merge alphanumerically the resulting PDFs. - default false. https://gotenberg.dev/docs/routes#merge-libreoffice')
->defaultNull()
->end()
->enumNode('pdf_format')
->info('Convert the resulting PDF into the given PDF/A format - default None. https://gotenberg.dev/docs/routes#pdfa-chromium')
->values(array_map(static fn (PdfFormat $case): string => $case->value, PdfFormat::cases()))
->defaultNull()
->end()
->booleanNode('pdf_universal_access')
->info('Enable PDF for Universal Access for optimal accessibility - default false. https://gotenberg.dev/docs/routes#console-exceptions')
->defaultNull()
->end()
->append($this->addPdfMetadata())
->end()
;

$this->addPdfFormat($treeBuilder->getRootNode());

return $treeBuilder->getRootNode();
}

private function addPdfConvertNode(): NodeDefinition
{
$treeBuilder = new TreeBuilder('convert');
$this->addPdfFormat($treeBuilder->getRootNode());

return $treeBuilder->getRootNode();
}

private function addPdfMergeNode(): NodeDefinition
Expand Down
Loading