From cc96450fb4e14c84ca7fd8269eeea13dbb6322c7 Mon Sep 17 00:00:00 2001 From: Steven Renaux Date: Fri, 3 Jan 2025 13:54:21 +0100 Subject: [PATCH] [RELEASE_8.15.0] Add split feature --- README.md | 3 +- config/builder_pdf.php | 12 + docs/Pdf/builders_api/ConvertPdfBuilder.md | 26 ++ docs/Pdf/builders_api/HtmlPdfBuilder.md | 168 ++++++++ .../Pdf/builders_api/LibreOfficePdfBuilder.md | 112 +++++ docs/Pdf/builders_api/MarkdownPdfBuilder.md | 171 ++++++++ docs/Pdf/builders_api/MergePdfBuilder.md | 34 ++ docs/Pdf/builders_api/SplitPdfBuilder.md | 31 ++ docs/Pdf/builders_api/UrlPdfBuilder.md | 170 ++++++++ .../builders_api/HtmlScreenshotBuilder.md | 101 +++++ .../builders_api/MarkdownScreenshotBuilder.md | 104 +++++ .../builders_api/UrlScreenshotBuilder.md | 103 +++++ docs/builders_api.md | 1 + docs/configuration.md | 45 ++ docs/generate.php | 2 + docs/pdf/customization.md | 93 +++++ docs/pdf/office-builder.md | 395 ++++++++++++------ docs/pdf/split-builder.md | 125 ++++++ .../Pdf/AbstractChromiumPdfBuilder.php | 46 ++ src/Builder/Pdf/LibreOfficePdfBuilder.php | 46 ++ src/Builder/Pdf/SplitPdfBuilder.php | 116 +++++ src/Debug/TraceableGotenbergPdf.php | 18 + src/DependencyInjection/Configuration.php | 46 ++ .../SensiolabsGotenbergExtension.php | 6 +- src/Enumeration/SplitMode.php | 9 + src/GotenbergPdf.php | 9 +- src/GotenbergPdfInterface.php | 6 + tests/Builder/Pdf/SplitPdfBuilderTest.php | 120 ++++++ .../DependencyInjection/ConfigurationTest.php | 17 + .../SensiolabsGotenbergExtensionTest.php | 1 + tests/Fixtures/pdf/multi_page.pdf | Bin 0 -> 139349 bytes 31 files changed, 2003 insertions(+), 133 deletions(-) create mode 100644 docs/Pdf/builders_api/ConvertPdfBuilder.md create mode 100644 docs/Pdf/builders_api/HtmlPdfBuilder.md create mode 100644 docs/Pdf/builders_api/LibreOfficePdfBuilder.md create mode 100644 docs/Pdf/builders_api/MarkdownPdfBuilder.md create mode 100644 docs/Pdf/builders_api/MergePdfBuilder.md create mode 100644 docs/Pdf/builders_api/SplitPdfBuilder.md create mode 100644 docs/Pdf/builders_api/UrlPdfBuilder.md create mode 100644 docs/Screenshot/builders_api/HtmlScreenshotBuilder.md create mode 100644 docs/Screenshot/builders_api/MarkdownScreenshotBuilder.md create mode 100644 docs/Screenshot/builders_api/UrlScreenshotBuilder.md create mode 100644 docs/pdf/split-builder.md create mode 100644 src/Builder/Pdf/SplitPdfBuilder.php create mode 100644 src/Enumeration/SplitMode.php create mode 100644 tests/Builder/Pdf/SplitPdfBuilderTest.php create mode 100644 tests/Fixtures/pdf/multi_page.pdf diff --git a/README.md b/README.md index a115ae25..a3bb7b81 100644 --- a/README.md +++ b/README.md @@ -242,7 +242,8 @@ class YourController `xltx`, `xlw`, `xml`, `xpm`, `zabw` 6. [Merge Builder](./docs/pdf/merge-builder.md) 7. [Convert Builder](./docs/pdf/convert-builder.md) -8. [PDF customization](./docs/pdf/customization.md) (available for every builder except LibreOffice and Merge) +8. [Split Builder](./docs/pdf/split-builder.md) +9. [PDF customization](./docs/pdf/customization.md) (available for every builder except LibreOffice, Merge and Split) #### Screenshot diff --git a/config/builder_pdf.php b/config/builder_pdf.php index 349c960d..33bcd231 100644 --- a/config/builder_pdf.php +++ b/config/builder_pdf.php @@ -5,6 +5,7 @@ use Sensiolabs\GotenbergBundle\Builder\Pdf\LibreOfficePdfBuilder; use Sensiolabs\GotenbergBundle\Builder\Pdf\MarkdownPdfBuilder; use Sensiolabs\GotenbergBundle\Builder\Pdf\MergePdfBuilder; +use Sensiolabs\GotenbergBundle\Builder\Pdf\SplitPdfBuilder; use Sensiolabs\GotenbergBundle\Builder\Pdf\UrlPdfBuilder; use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator; use function Symfony\Component\DependencyInjection\Loader\Configurator\service; @@ -89,4 +90,15 @@ ->call('setLogger', [service('logger')->nullOnInvalid()]) ->tag('sensiolabs_gotenberg.pdf_builder') ; + + $services->set('.sensiolabs_gotenberg.pdf_builder.split', SplitPdfBuilder::class) + ->share(false) + ->args([ + service('sensiolabs_gotenberg.client'), + service('sensiolabs_gotenberg.asset.base_dir_formatter'), + service('.sensiolabs_gotenberg.webhook_configuration_registry'), + ]) + ->call('setLogger', [service('logger')->nullOnInvalid()]) + ->tag('sensiolabs_gotenberg.pdf_builder') + ; }; diff --git a/docs/Pdf/builders_api/ConvertPdfBuilder.md b/docs/Pdf/builders_api/ConvertPdfBuilder.md new file mode 100644 index 00000000..c507ac59 --- /dev/null +++ b/docs/Pdf/builders_api/ConvertPdfBuilder.md @@ -0,0 +1,26 @@ +# 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)`: + +* `downloadFrom(array $downloadFrom)`: + +* `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. + +* `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. + +* `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 new file mode 100644 index 00000000..5161d58d --- /dev/null +++ b/docs/Pdf/builders_api/HtmlPdfBuilder.md @@ -0,0 +1,168 @@ +# HtmlPdfBuilder + +* `content(string $template, array $context)`: + +* `contentFile(string $path)`: +The HTML file to convert into PDF. + +* `cookies(array $cookies)`: + +* `setCookie(string $key, Symfony\Component\HttpFoundation\Cookie|array $cookie)`: + +* `forwardCookie(string $name)`: + +* `singlePage(bool $bool)`: +Define whether to print the entire content in one single page. +If the singlePage form field is set to true, it automatically overrides the values from the paperHeight and nativePageRanges form fields. + +* `paperSize(float $width, float $height, Sensiolabs\GotenbergBundle\Enumeration\Unit $unit)`: +Overrides the default paper size, in inches. +Examples of paper size (width x height): +Letter - 8.5 x 11 (default) +Legal - 8.5 x 14 +Tabloid - 11 x 17 +Ledger - 17 x 11 +A0 - 33.1 x 46.8 +A1 - 23.4 x 33.1 +A2 - 16.54 x 23.4 +A3 - 11.7 x 16.54 +A4 - 8.27 x 11.7 +A5 - 5.83 x 8.27 +A6 - 4.13 x 5.83 + +* `paperStandardSize(Sensiolabs\GotenbergBundle\Enumeration\PaperSizeInterface $paperSize)`: + +* `paperWidth(float $width, Sensiolabs\GotenbergBundle\Enumeration\Unit $unit)`: + +* `paperHeight(float $height, Sensiolabs\GotenbergBundle\Enumeration\Unit $unit)`: + +* `margins(float $top, float $bottom, float $left, float $right, Sensiolabs\GotenbergBundle\Enumeration\Unit $unit)`: +Overrides the default margins (e.g., 0.39), in inches. + +* `marginTop(float $top, Sensiolabs\GotenbergBundle\Enumeration\Unit $unit)`: + +* `marginBottom(float $bottom, Sensiolabs\GotenbergBundle\Enumeration\Unit $unit)`: + +* `marginLeft(float $left, Sensiolabs\GotenbergBundle\Enumeration\Unit $unit)`: + +* `marginRight(float $right, Sensiolabs\GotenbergBundle\Enumeration\Unit $unit)`: + +* `preferCssPageSize(bool $bool)`: +Define whether to prefer page size as defined by CSS. (Default false). + +* `generateDocumentOutline(bool $bool)`: +Define whether the document outline should be embedded into the PDF. (Default false). + +* `printBackground(bool $bool)`: +Prints the background graphics. (Default false). + +* `omitBackground(bool $bool)`: +Hides default white background and allows generating PDFs with +transparency. (Default false). + +* `landscape(bool $bool)`: +Sets the paper orientation to landscape. (Default false). + +* `scale(float $scale)`: +The scale of the page rendering (e.g., 1.0). (Default 1.0). + +* `nativePageRanges(string $range)`: +Page ranges to print, e.g., '1-5, 8, 11-13'. (default All pages). + +* `header(string $template, array $context)`: + +* `footer(string $template, array $context)`: + +* `headerFile(string $path)`: +HTML file containing the header. (default None). + +* `footerFile(string $path)`: +HTML file containing the footer. (default None). + +* `assets(string $paths)`: +Adds additional files, like images, fonts, stylesheets, and so on (overrides any previous files). + +* `addAsset(string $path)`: +Adds a file, like an image, font, stylesheet, and so on. + +* `waitDelay(string $delay)`: +Sets the duration (i.e., "1s", "2ms", etc.) to wait when loading an HTML +document before converting it to PDF. (default None). + +* `waitForExpression(string $expression)`: +Sets the JavaScript expression to wait before converting an HTML +document to PDF until it returns true. (default None). +For instance: "window.status === 'ready'". + +* `emulatedMediaType(Sensiolabs\GotenbergBundle\Enumeration\EmulatedMediaType $mediaType)`: +Forces Chromium to emulate, either "screen" or "print". (default "print"). + +* `userAgent(string $userAgent)`: +Override the default User-Agent HTTP header. (default None). + +* `extraHttpHeaders(array $headers)`: +Sets extra HTTP headers that Chromium will send when loading the HTML +document. (default None). (overrides any previous headers). + +* `addExtraHttpHeaders(array $headers)`: +Adds extra HTTP headers that Chromium will send when loading the HTML +document. (default None). + +* `failOnHttpStatusCodes(array $statusCodes)`: +Return a 409 Conflict response if the HTTP status code from +the main page is not acceptable. (default [499,599]). (overrides any previous configuration). + +* `failOnResourceHttpStatusCodes(array $statusCodes)`: +Return a 409 Conflict response if the HTTP status code from at least one resource is not acceptable. +(default None). (overrides any previous configuration). + +* `failOnResourceLoadingFailed(bool $bool)`: +Forces GotenbergScreenshot to return a 409 Conflict response if there are +exceptions load at least one resource. (default false). + +* `failOnConsoleExceptions(bool $bool)`: +Forces GotenbergPdf to return a 409 Conflict response if there are +exceptions in the Chromium console. (default false). + +* `skipNetworkIdleEvent(bool $bool)`: + +* `pdfFormat(?Sensiolabs\GotenbergBundle\Enumeration\PdfFormat $format)`: +Sets the PDF format of the resulting PDF. (default None). + +* `pdfUniversalAccess(bool $bool)`: +Enable PDF for Universal Access for optimal accessibility. (default false). + +* `metadata(array $metadata)`: +Resets the metadata. + +* `addMetadata(string $key, string $value)`: +The metadata to write. + +* `splitMode(?Sensiolabs\GotenbergBundle\Enumeration\SplitMode $splitMode)`: +Either intervals or pages. (default None). + +* `splitSpan(string $splitSpan)`: +Either the intervals or the page ranges to extract, depending on the selected mode. (default None). + +* `splitUnify(bool $bool)`: +Specify whether to put extracted pages into a single file or as many files as there are page ranges. Only works with pages mode. (default false). + +* `downloadFrom(array $downloadFrom)`: + +* `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. + +* `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. + +* `webhookExtraHeaders(array $extraHeaders)`: +Extra headers that will be provided to the webhook endpoint. May it either be Success or Error. + +* `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 new file mode 100644 index 00000000..244296a9 --- /dev/null +++ b/docs/Pdf/builders_api/LibreOfficePdfBuilder.md @@ -0,0 +1,112 @@ +# LibreOfficePdfBuilder + +* `password(string $password)`: +Set the password for opening the source file. + +* `landscape(bool $bool)`: +Sets the paper orientation to landscape. + +* `nativePageRanges(string $range)`: +Page ranges to print, e.g., '1-4' - empty means all pages. +If multiple files are provided, the page ranges will be applied independently to each file. + +* `doNotExportFormFields(bool $bool)`: +Set whether to export the form fields or to use the inputted/selected content of the fields. + +* `singlePageSheets(bool $bool)`: +Set whether to render the entire spreadsheet as a single page. + +* `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. + +* `merge(bool $bool)`: +Merge alphanumerically the resulting PDFs. + +* `files(string $paths)`: +Adds office files to convert (overrides any previous files). + +* `metadata(array $metadata)`: +Resets the metadata. + +* `addMetadata(string $key, string $value)`: +The metadata to write. + +* `allowDuplicateFieldNames(bool $bool)`: +Specify whether multiple form fields exported are allowed to have the same field name. + +* `doNotExportBookmarks(bool $bool)`: +Specify if bookmarks are exported to PDF. + +* `exportBookmarksToPdfDestination(bool $bool)`: +Specify that the bookmarks contained in the source LibreOffice file should be exported to the PDF file as Named Destination. + +* `exportPlaceholders(bool $bool)`: +Export the placeholders fields visual markings only. The exported placeholder is ineffective. + +* `exportNotes(bool $bool)`: +Specify if notes are exported to PDF. + +* `exportNotesPages(bool $bool)`: +Specify if notes pages are exported to PDF. Notes pages are available in Impress documents only. + +* `exportOnlyNotesPages(bool $bool)`: +Specify, if the form field exportNotesPages is set to true, if only notes pages are exported to PDF. + +* `exportNotesInMargin(bool $bool)`: +Specify if notes in margin are exported to PDF. + +* `convertOooTargetToPdfTarget(bool $bool)`: +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. + +* `exportLinksRelativeFsys(bool $bool)`: +Specify that the file system related hyperlinks (file:// protocol) present in the document will be exported as relative to the source document location. + +* `exportHiddenSlides(bool $bool)`: +Export, for LibreOffice Impress, slides that are not included in slide shows. + +* `skipEmptyPages(bool $bool)`: +Specify that automatically inserted empty pages are suppressed. This option is active only if storing Writer documents. + +* `addOriginalDocumentAsStream(bool $bool)`: +Specify that a stream is inserted to the PDF file which contains the original document for archiving purposes. + +* `losslessImageCompression(bool $bool)`: +Specify if images are exported to PDF using a lossless compression format like PNG or compressed using the JPEG format. + +* `quality(int $quality)`: +Specify the quality of the JPG export. A higher value produces a higher-quality image and a larger file. Between 1 and 100. + +* `reduceImageResolution(bool $bool)`: +Specify if the resolution of each image is reduced to the resolution specified by the form field maxImageResolution. + +* `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. + +* `splitMode(?Sensiolabs\GotenbergBundle\Enumeration\SplitMode $splitMode)`: +Either intervals or pages. (default None). + +* `splitSpan(string $splitSpan)`: +Either the intervals or the page ranges to extract, depending on the selected mode. (default None). + +* `splitUnify(bool $bool)`: +Specify whether to put extracted pages into a single file or as many files as there are page ranges. Only works with pages mode. (default false). + +* `downloadFrom(array $downloadFrom)`: + +* `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. + +* `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. + +* `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 new file mode 100644 index 00000000..7af5eba4 --- /dev/null +++ b/docs/Pdf/builders_api/MarkdownPdfBuilder.md @@ -0,0 +1,171 @@ +# MarkdownPdfBuilder + +* `wrapper(string $template, array $context)`: +The HTML file that wraps the markdown content, rendered from a Twig template. + +* `wrapperFile(string $path)`: +The HTML file that wraps the markdown content. + +* `files(string $paths)`: + +* `cookies(array $cookies)`: + +* `setCookie(string $key, Symfony\Component\HttpFoundation\Cookie|array $cookie)`: + +* `forwardCookie(string $name)`: + +* `singlePage(bool $bool)`: +Define whether to print the entire content in one single page. +If the singlePage form field is set to true, it automatically overrides the values from the paperHeight and nativePageRanges form fields. + +* `paperSize(float $width, float $height, Sensiolabs\GotenbergBundle\Enumeration\Unit $unit)`: +Overrides the default paper size, in inches. +Examples of paper size (width x height): +Letter - 8.5 x 11 (default) +Legal - 8.5 x 14 +Tabloid - 11 x 17 +Ledger - 17 x 11 +A0 - 33.1 x 46.8 +A1 - 23.4 x 33.1 +A2 - 16.54 x 23.4 +A3 - 11.7 x 16.54 +A4 - 8.27 x 11.7 +A5 - 5.83 x 8.27 +A6 - 4.13 x 5.83 + +* `paperStandardSize(Sensiolabs\GotenbergBundle\Enumeration\PaperSizeInterface $paperSize)`: + +* `paperWidth(float $width, Sensiolabs\GotenbergBundle\Enumeration\Unit $unit)`: + +* `paperHeight(float $height, Sensiolabs\GotenbergBundle\Enumeration\Unit $unit)`: + +* `margins(float $top, float $bottom, float $left, float $right, Sensiolabs\GotenbergBundle\Enumeration\Unit $unit)`: +Overrides the default margins (e.g., 0.39), in inches. + +* `marginTop(float $top, Sensiolabs\GotenbergBundle\Enumeration\Unit $unit)`: + +* `marginBottom(float $bottom, Sensiolabs\GotenbergBundle\Enumeration\Unit $unit)`: + +* `marginLeft(float $left, Sensiolabs\GotenbergBundle\Enumeration\Unit $unit)`: + +* `marginRight(float $right, Sensiolabs\GotenbergBundle\Enumeration\Unit $unit)`: + +* `preferCssPageSize(bool $bool)`: +Define whether to prefer page size as defined by CSS. (Default false). + +* `generateDocumentOutline(bool $bool)`: +Define whether the document outline should be embedded into the PDF. (Default false). + +* `printBackground(bool $bool)`: +Prints the background graphics. (Default false). + +* `omitBackground(bool $bool)`: +Hides default white background and allows generating PDFs with +transparency. (Default false). + +* `landscape(bool $bool)`: +Sets the paper orientation to landscape. (Default false). + +* `scale(float $scale)`: +The scale of the page rendering (e.g., 1.0). (Default 1.0). + +* `nativePageRanges(string $range)`: +Page ranges to print, e.g., '1-5, 8, 11-13'. (default All pages). + +* `header(string $template, array $context)`: + +* `footer(string $template, array $context)`: + +* `headerFile(string $path)`: +HTML file containing the header. (default None). + +* `footerFile(string $path)`: +HTML file containing the footer. (default None). + +* `assets(string $paths)`: +Adds additional files, like images, fonts, stylesheets, and so on (overrides any previous files). + +* `addAsset(string $path)`: +Adds a file, like an image, font, stylesheet, and so on. + +* `waitDelay(string $delay)`: +Sets the duration (i.e., "1s", "2ms", etc.) to wait when loading an HTML +document before converting it to PDF. (default None). + +* `waitForExpression(string $expression)`: +Sets the JavaScript expression to wait before converting an HTML +document to PDF until it returns true. (default None). +For instance: "window.status === 'ready'". + +* `emulatedMediaType(Sensiolabs\GotenbergBundle\Enumeration\EmulatedMediaType $mediaType)`: +Forces Chromium to emulate, either "screen" or "print". (default "print"). + +* `userAgent(string $userAgent)`: +Override the default User-Agent HTTP header. (default None). + +* `extraHttpHeaders(array $headers)`: +Sets extra HTTP headers that Chromium will send when loading the HTML +document. (default None). (overrides any previous headers). + +* `addExtraHttpHeaders(array $headers)`: +Adds extra HTTP headers that Chromium will send when loading the HTML +document. (default None). + +* `failOnHttpStatusCodes(array $statusCodes)`: +Return a 409 Conflict response if the HTTP status code from +the main page is not acceptable. (default [499,599]). (overrides any previous configuration). + +* `failOnResourceHttpStatusCodes(array $statusCodes)`: +Return a 409 Conflict response if the HTTP status code from at least one resource is not acceptable. +(default None). (overrides any previous configuration). + +* `failOnResourceLoadingFailed(bool $bool)`: +Forces GotenbergScreenshot to return a 409 Conflict response if there are +exceptions load at least one resource. (default false). + +* `failOnConsoleExceptions(bool $bool)`: +Forces GotenbergPdf to return a 409 Conflict response if there are +exceptions in the Chromium console. (default false). + +* `skipNetworkIdleEvent(bool $bool)`: + +* `pdfFormat(?Sensiolabs\GotenbergBundle\Enumeration\PdfFormat $format)`: +Sets the PDF format of the resulting PDF. (default None). + +* `pdfUniversalAccess(bool $bool)`: +Enable PDF for Universal Access for optimal accessibility. (default false). + +* `metadata(array $metadata)`: +Resets the metadata. + +* `addMetadata(string $key, string $value)`: +The metadata to write. + +* `splitMode(?Sensiolabs\GotenbergBundle\Enumeration\SplitMode $splitMode)`: +Either intervals or pages. (default None). + +* `splitSpan(string $splitSpan)`: +Either the intervals or the page ranges to extract, depending on the selected mode. (default None). + +* `splitUnify(bool $bool)`: +Specify whether to put extracted pages into a single file or as many files as there are page ranges. Only works with pages mode. (default false). + +* `downloadFrom(array $downloadFrom)`: + +* `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. + +* `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. + +* `webhookExtraHeaders(array $extraHeaders)`: +Extra headers that will be provided to the webhook endpoint. May it either be Success or Error. + +* `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 new file mode 100644 index 00000000..477c8815 --- /dev/null +++ b/docs/Pdf/builders_api/MergePdfBuilder.md @@ -0,0 +1,34 @@ +# 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. + +* `downloadFrom(array $downloadFrom)`: + +* `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. + +* `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. + +* `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/SplitPdfBuilder.md b/docs/Pdf/builders_api/SplitPdfBuilder.md new file mode 100644 index 00000000..8a5e3b4d --- /dev/null +++ b/docs/Pdf/builders_api/SplitPdfBuilder.md @@ -0,0 +1,31 @@ +# SplitPdfBuilder + +Split `n` pdf files. + +* `splitMode(?Sensiolabs\GotenbergBundle\Enumeration\SplitMode $splitMode)`: +Either intervals or pages. (default None). + +* `splitSpan(string $splitSpan)`: +Either the intervals or the page ranges to extract, depending on the selected mode. (default None). + +* `splitUnify(bool $bool)`: +Specify whether to put extracted pages into a single file or as many files as there are page ranges. Only works with pages mode. (default false). + +* `files(string $paths)`: + +* `downloadFrom(array $downloadFrom)`: + +* `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. + +* `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. + +* `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 new file mode 100644 index 00000000..38b66391 --- /dev/null +++ b/docs/Pdf/builders_api/UrlPdfBuilder.md @@ -0,0 +1,170 @@ +# UrlPdfBuilder + +* `setRequestContext(?Symfony\Component\Routing\RequestContext $requestContext)`: + +* `url(string $url)`: +URL of the page you want to convert into PDF. + +* `route(string $name, array $parameters)`: + +* `cookies(array $cookies)`: + +* `setCookie(string $key, Symfony\Component\HttpFoundation\Cookie|array $cookie)`: + +* `forwardCookie(string $name)`: + +* `singlePage(bool $bool)`: +Define whether to print the entire content in one single page. +If the singlePage form field is set to true, it automatically overrides the values from the paperHeight and nativePageRanges form fields. + +* `paperSize(float $width, float $height, Sensiolabs\GotenbergBundle\Enumeration\Unit $unit)`: +Overrides the default paper size, in inches. +Examples of paper size (width x height): +Letter - 8.5 x 11 (default) +Legal - 8.5 x 14 +Tabloid - 11 x 17 +Ledger - 17 x 11 +A0 - 33.1 x 46.8 +A1 - 23.4 x 33.1 +A2 - 16.54 x 23.4 +A3 - 11.7 x 16.54 +A4 - 8.27 x 11.7 +A5 - 5.83 x 8.27 +A6 - 4.13 x 5.83 + +* `paperStandardSize(Sensiolabs\GotenbergBundle\Enumeration\PaperSizeInterface $paperSize)`: + +* `paperWidth(float $width, Sensiolabs\GotenbergBundle\Enumeration\Unit $unit)`: + +* `paperHeight(float $height, Sensiolabs\GotenbergBundle\Enumeration\Unit $unit)`: + +* `margins(float $top, float $bottom, float $left, float $right, Sensiolabs\GotenbergBundle\Enumeration\Unit $unit)`: +Overrides the default margins (e.g., 0.39), in inches. + +* `marginTop(float $top, Sensiolabs\GotenbergBundle\Enumeration\Unit $unit)`: + +* `marginBottom(float $bottom, Sensiolabs\GotenbergBundle\Enumeration\Unit $unit)`: + +* `marginLeft(float $left, Sensiolabs\GotenbergBundle\Enumeration\Unit $unit)`: + +* `marginRight(float $right, Sensiolabs\GotenbergBundle\Enumeration\Unit $unit)`: + +* `preferCssPageSize(bool $bool)`: +Define whether to prefer page size as defined by CSS. (Default false). + +* `generateDocumentOutline(bool $bool)`: +Define whether the document outline should be embedded into the PDF. (Default false). + +* `printBackground(bool $bool)`: +Prints the background graphics. (Default false). + +* `omitBackground(bool $bool)`: +Hides default white background and allows generating PDFs with +transparency. (Default false). + +* `landscape(bool $bool)`: +Sets the paper orientation to landscape. (Default false). + +* `scale(float $scale)`: +The scale of the page rendering (e.g., 1.0). (Default 1.0). + +* `nativePageRanges(string $range)`: +Page ranges to print, e.g., '1-5, 8, 11-13'. (default All pages). + +* `header(string $template, array $context)`: + +* `footer(string $template, array $context)`: + +* `headerFile(string $path)`: +HTML file containing the header. (default None). + +* `footerFile(string $path)`: +HTML file containing the footer. (default None). + +* `assets(string $paths)`: +Adds additional files, like images, fonts, stylesheets, and so on (overrides any previous files). + +* `addAsset(string $path)`: +Adds a file, like an image, font, stylesheet, and so on. + +* `waitDelay(string $delay)`: +Sets the duration (i.e., "1s", "2ms", etc.) to wait when loading an HTML +document before converting it to PDF. (default None). + +* `waitForExpression(string $expression)`: +Sets the JavaScript expression to wait before converting an HTML +document to PDF until it returns true. (default None). +For instance: "window.status === 'ready'". + +* `emulatedMediaType(Sensiolabs\GotenbergBundle\Enumeration\EmulatedMediaType $mediaType)`: +Forces Chromium to emulate, either "screen" or "print". (default "print"). + +* `userAgent(string $userAgent)`: +Override the default User-Agent HTTP header. (default None). + +* `extraHttpHeaders(array $headers)`: +Sets extra HTTP headers that Chromium will send when loading the HTML +document. (default None). (overrides any previous headers). + +* `addExtraHttpHeaders(array $headers)`: +Adds extra HTTP headers that Chromium will send when loading the HTML +document. (default None). + +* `failOnHttpStatusCodes(array $statusCodes)`: +Return a 409 Conflict response if the HTTP status code from +the main page is not acceptable. (default [499,599]). (overrides any previous configuration). + +* `failOnResourceHttpStatusCodes(array $statusCodes)`: +Return a 409 Conflict response if the HTTP status code from at least one resource is not acceptable. +(default None). (overrides any previous configuration). + +* `failOnResourceLoadingFailed(bool $bool)`: +Forces GotenbergScreenshot to return a 409 Conflict response if there are +exceptions load at least one resource. (default false). + +* `failOnConsoleExceptions(bool $bool)`: +Forces GotenbergPdf to return a 409 Conflict response if there are +exceptions in the Chromium console. (default false). + +* `skipNetworkIdleEvent(bool $bool)`: + +* `pdfFormat(?Sensiolabs\GotenbergBundle\Enumeration\PdfFormat $format)`: +Sets the PDF format of the resulting PDF. (default None). + +* `pdfUniversalAccess(bool $bool)`: +Enable PDF for Universal Access for optimal accessibility. (default false). + +* `metadata(array $metadata)`: +Resets the metadata. + +* `addMetadata(string $key, string $value)`: +The metadata to write. + +* `splitMode(?Sensiolabs\GotenbergBundle\Enumeration\SplitMode $splitMode)`: +Either intervals or pages. (default None). + +* `splitSpan(string $splitSpan)`: +Either the intervals or the page ranges to extract, depending on the selected mode. (default None). + +* `splitUnify(bool $bool)`: +Specify whether to put extracted pages into a single file or as many files as there are page ranges. Only works with pages mode. (default false). + +* `downloadFrom(array $downloadFrom)`: + +* `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. + +* `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. + +* `webhookExtraHeaders(array $extraHeaders)`: +Extra headers that will be provided to the webhook endpoint. May it either be Success or Error. + +* `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 new file mode 100644 index 00000000..c28cb55a --- /dev/null +++ b/docs/Screenshot/builders_api/HtmlScreenshotBuilder.md @@ -0,0 +1,101 @@ +# HtmlScreenshotBuilder + +* `content(string $template, array $context)`: + +* `contentFile(string $path)`: +The HTML file to convert into Screenshot. + +* `cookies(array $cookies)`: + +* `setCookie(string $key, Symfony\Component\HttpFoundation\Cookie|array $cookie)`: + +* `forwardCookie(string $name)`: + +* `width(int $width)`: +The device screen width in pixels. (Default 800). + +* `height(int $height)`: +The device screen width in pixels. (Default 600). + +* `clip(bool $bool)`: +Define whether to clip the screenshot according to the device dimensions. (Default false). + +* `format(Sensiolabs\GotenbergBundle\Enumeration\ScreenshotFormat $format)`: +The image compression format, either "png", "jpeg" or "webp". (default png). + +* `quality(int $quality)`: +The compression quality from range 0 to 100 (jpeg only). (default 100). + +* `omitBackground(bool $bool)`: +Hides default white background and allows generating screenshot with +transparency. (Default false). + +* `optimizeForSpeed(bool $bool)`: +Define whether to optimize image encoding for speed, not for resulting size. (Default false). + +* `waitDelay(string $delay)`: +Sets the duration (i.e., "1s", "2ms", etc.) to wait when loading an HTML +document before converting it to screenshot. (default None). + +* `waitForExpression(string $expression)`: +Sets the JavaScript expression to wait before converting an HTML +document to screenshot until it returns true. (default None). +For instance: "window.status === 'ready'". + +* `emulatedMediaType(Sensiolabs\GotenbergBundle\Enumeration\EmulatedMediaType $mediaType)`: +Forces Chromium to emulate, either "screen" or "print". (default "print"). + +* `userAgent(string $userAgent)`: +Override the default User-Agent HTTP header. (default None). + +* `extraHttpHeaders(array $headers)`: +Sets extra HTTP headers that Chromium will send when loading the HTML +document. (default None). (overrides any previous headers). + +* `addExtraHttpHeaders(array $headers)`: +Adds extra HTTP headers that Chromium will send when loading the HTML +document. (default None). + +* `failOnHttpStatusCodes(array $statusCodes)`: +Return a 409 Conflict response if the HTTP status code from +the main page is not acceptable. (default [499,599]). (overrides any previous configuration). + +* `failOnResourceHttpStatusCodes(array $statusCodes)`: +Return a 409 Conflict response if the HTTP status code from at least one resource is not acceptable. +(default None). (overrides any previous configuration). + +* `failOnResourceLoadingFailed(bool $bool)`: +Forces GotenbergScreenshot to return a 409 Conflict response if there are +exceptions load at least one resource. (default false). + +* `failOnConsoleExceptions(bool $bool)`: +Forces GotenbergScreenshot to return a 409 Conflict response if there are +exceptions in the Chromium console. (default false). + +* `skipNetworkIdleEvent(bool $bool)`: + +* `assets(string $paths)`: +Adds additional files, like images, fonts, stylesheets, and so on (overrides any previous files). + +* `addAsset(string $path)`: +Adds a file, like an image, font, stylesheet, and so on. + +* `downloadFrom(array $downloadFrom)`: + +* `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. + +* `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. + +* `webhookExtraHeaders(array $extraHeaders)`: +Extra headers that will be provided to the webhook endpoint. May it either be Success or Error. + +* `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 new file mode 100644 index 00000000..2c961101 --- /dev/null +++ b/docs/Screenshot/builders_api/MarkdownScreenshotBuilder.md @@ -0,0 +1,104 @@ +# MarkdownScreenshotBuilder + +* `wrapper(string $template, array $context)`: +The HTML file that wraps the markdown content, rendered from a Twig template. + +* `wrapperFile(string $path)`: +The HTML file that wraps the markdown content. + +* `files(string $paths)`: + +* `cookies(array $cookies)`: + +* `setCookie(string $key, Symfony\Component\HttpFoundation\Cookie|array $cookie)`: + +* `forwardCookie(string $name)`: + +* `width(int $width)`: +The device screen width in pixels. (Default 800). + +* `height(int $height)`: +The device screen width in pixels. (Default 600). + +* `clip(bool $bool)`: +Define whether to clip the screenshot according to the device dimensions. (Default false). + +* `format(Sensiolabs\GotenbergBundle\Enumeration\ScreenshotFormat $format)`: +The image compression format, either "png", "jpeg" or "webp". (default png). + +* `quality(int $quality)`: +The compression quality from range 0 to 100 (jpeg only). (default 100). + +* `omitBackground(bool $bool)`: +Hides default white background and allows generating screenshot with +transparency. (Default false). + +* `optimizeForSpeed(bool $bool)`: +Define whether to optimize image encoding for speed, not for resulting size. (Default false). + +* `waitDelay(string $delay)`: +Sets the duration (i.e., "1s", "2ms", etc.) to wait when loading an HTML +document before converting it to screenshot. (default None). + +* `waitForExpression(string $expression)`: +Sets the JavaScript expression to wait before converting an HTML +document to screenshot until it returns true. (default None). +For instance: "window.status === 'ready'". + +* `emulatedMediaType(Sensiolabs\GotenbergBundle\Enumeration\EmulatedMediaType $mediaType)`: +Forces Chromium to emulate, either "screen" or "print". (default "print"). + +* `userAgent(string $userAgent)`: +Override the default User-Agent HTTP header. (default None). + +* `extraHttpHeaders(array $headers)`: +Sets extra HTTP headers that Chromium will send when loading the HTML +document. (default None). (overrides any previous headers). + +* `addExtraHttpHeaders(array $headers)`: +Adds extra HTTP headers that Chromium will send when loading the HTML +document. (default None). + +* `failOnHttpStatusCodes(array $statusCodes)`: +Return a 409 Conflict response if the HTTP status code from +the main page is not acceptable. (default [499,599]). (overrides any previous configuration). + +* `failOnResourceHttpStatusCodes(array $statusCodes)`: +Return a 409 Conflict response if the HTTP status code from at least one resource is not acceptable. +(default None). (overrides any previous configuration). + +* `failOnResourceLoadingFailed(bool $bool)`: +Forces GotenbergScreenshot to return a 409 Conflict response if there are +exceptions load at least one resource. (default false). + +* `failOnConsoleExceptions(bool $bool)`: +Forces GotenbergScreenshot to return a 409 Conflict response if there are +exceptions in the Chromium console. (default false). + +* `skipNetworkIdleEvent(bool $bool)`: + +* `assets(string $paths)`: +Adds additional files, like images, fonts, stylesheets, and so on (overrides any previous files). + +* `addAsset(string $path)`: +Adds a file, like an image, font, stylesheet, and so on. + +* `downloadFrom(array $downloadFrom)`: + +* `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. + +* `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. + +* `webhookExtraHeaders(array $extraHeaders)`: +Extra headers that will be provided to the webhook endpoint. May it either be Success or Error. + +* `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 new file mode 100644 index 00000000..868d5e8a --- /dev/null +++ b/docs/Screenshot/builders_api/UrlScreenshotBuilder.md @@ -0,0 +1,103 @@ +# UrlScreenshotBuilder + +* `setRequestContext(?Symfony\Component\Routing\RequestContext $requestContext)`: + +* `url(string $url)`: +URL of the page you want to screenshot. + +* `route(string $name, array $parameters)`: + +* `cookies(array $cookies)`: + +* `setCookie(string $key, Symfony\Component\HttpFoundation\Cookie|array $cookie)`: + +* `forwardCookie(string $name)`: + +* `width(int $width)`: +The device screen width in pixels. (Default 800). + +* `height(int $height)`: +The device screen width in pixels. (Default 600). + +* `clip(bool $bool)`: +Define whether to clip the screenshot according to the device dimensions. (Default false). + +* `format(Sensiolabs\GotenbergBundle\Enumeration\ScreenshotFormat $format)`: +The image compression format, either "png", "jpeg" or "webp". (default png). + +* `quality(int $quality)`: +The compression quality from range 0 to 100 (jpeg only). (default 100). + +* `omitBackground(bool $bool)`: +Hides default white background and allows generating screenshot with +transparency. (Default false). + +* `optimizeForSpeed(bool $bool)`: +Define whether to optimize image encoding for speed, not for resulting size. (Default false). + +* `waitDelay(string $delay)`: +Sets the duration (i.e., "1s", "2ms", etc.) to wait when loading an HTML +document before converting it to screenshot. (default None). + +* `waitForExpression(string $expression)`: +Sets the JavaScript expression to wait before converting an HTML +document to screenshot until it returns true. (default None). +For instance: "window.status === 'ready'". + +* `emulatedMediaType(Sensiolabs\GotenbergBundle\Enumeration\EmulatedMediaType $mediaType)`: +Forces Chromium to emulate, either "screen" or "print". (default "print"). + +* `userAgent(string $userAgent)`: +Override the default User-Agent HTTP header. (default None). + +* `extraHttpHeaders(array $headers)`: +Sets extra HTTP headers that Chromium will send when loading the HTML +document. (default None). (overrides any previous headers). + +* `addExtraHttpHeaders(array $headers)`: +Adds extra HTTP headers that Chromium will send when loading the HTML +document. (default None). + +* `failOnHttpStatusCodes(array $statusCodes)`: +Return a 409 Conflict response if the HTTP status code from +the main page is not acceptable. (default [499,599]). (overrides any previous configuration). + +* `failOnResourceHttpStatusCodes(array $statusCodes)`: +Return a 409 Conflict response if the HTTP status code from at least one resource is not acceptable. +(default None). (overrides any previous configuration). + +* `failOnResourceLoadingFailed(bool $bool)`: +Forces GotenbergScreenshot to return a 409 Conflict response if there are +exceptions load at least one resource. (default false). + +* `failOnConsoleExceptions(bool $bool)`: +Forces GotenbergScreenshot to return a 409 Conflict response if there are +exceptions in the Chromium console. (default false). + +* `skipNetworkIdleEvent(bool $bool)`: + +* `assets(string $paths)`: +Adds additional files, like images, fonts, stylesheets, and so on (overrides any previous files). + +* `addAsset(string $path)`: +Adds a file, like an image, font, stylesheet, and so on. + +* `downloadFrom(array $downloadFrom)`: + +* `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. + +* `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. + +* `webhookExtraHeaders(array $extraHeaders)`: +Extra headers that will be provided to the webhook endpoint. May it either be Success or Error. + +* `addCookies(array $cookies)`: +Add cookies to store in the Chromium cookie jar. + diff --git a/docs/builders_api.md b/docs/builders_api.md index 5842431b..a739dbc1 100644 --- a/docs/builders_api.md +++ b/docs/builders_api.md @@ -8,6 +8,7 @@ * [LibreOfficePdfBuilder](./Pdf/builders_api/LibreOfficePdfBuilder.md) * [MergePdfBuilder](./Pdf/builders_api/MergePdfBuilder.md) * [ConvertPdfBuilder](./Pdf/builders_api/ConvertPdfBuilder.md) +* [SplitPdfBuilder](./Pdf/builders_api/SplitPdfBuilder.md) ## Screenshot diff --git a/docs/configuration.md b/docs/configuration.md index 5fc78fda..4bd34c02 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -231,6 +231,15 @@ sensiolabs_gotenberg: # Enable PDF for Universal Access for optimal accessibility - default false. pdf_universal_access: null + # Either intervals or pages. - default None. https://gotenberg.dev/docs/routes#split-chromium + split_mode: null + + # Either the intervals or the page ranges to extract, depending on the selected mode. - default None. https://gotenberg.dev/docs/routes#split-chromium + split_span: null + + # Specify whether to put extracted pages into a single file or as many files as there are page ranges. Only works with pages mode. - default false. https://gotenberg.dev/docs/routes#split-chromium + split_unify: null + # Webhook configuration name or definition. webhook: @@ -419,6 +428,15 @@ sensiolabs_gotenberg: # Enable PDF for Universal Access for optimal accessibility - default false. pdf_universal_access: null + # Either intervals or pages. - default None. https://gotenberg.dev/docs/routes#split-chromium + split_mode: null + + # Either the intervals or the page ranges to extract, depending on the selected mode. - default None. https://gotenberg.dev/docs/routes#split-chromium + split_span: null + + # Specify whether to put extracted pages into a single file or as many files as there are page ranges. Only works with pages mode. - default false. https://gotenberg.dev/docs/routes#split-chromium + split_unify: null + # Webhook configuration name or definition. webhook: @@ -607,6 +625,15 @@ sensiolabs_gotenberg: # Enable PDF for Universal Access for optimal accessibility - default false. pdf_universal_access: null + # Either intervals or pages. - default None. https://gotenberg.dev/docs/routes#split-chromium + split_mode: null + + # Either the intervals or the page ranges to extract, depending on the selected mode. - default None. https://gotenberg.dev/docs/routes#split-chromium + split_span: null + + # Specify whether to put extracted pages into a single file or as many files as there are page ranges. Only works with pages mode. - default false. https://gotenberg.dev/docs/routes#split-chromium + split_unify: null + # Webhook configuration name or definition. webhook: @@ -755,6 +782,15 @@ sensiolabs_gotenberg: # Enable PDF for Universal Access for optimal accessibility - default false. pdf_universal_access: null + + # Either intervals or pages. - default None. https://gotenberg.dev/docs/routes#split-libreoffice + split_mode: null + + # Either the intervals or the page ranges to extract, depending on the selected mode. - default None. https://gotenberg.dev/docs/routes#split-libreoffice + split_span: null + + # Specify whether to put extracted pages into a single file or as many files as there are page ranges. Only works with pages mode. - default false. https://gotenberg.dev/docs/routes#split-libreoffice + split_unify: null merge: # Convert PDF into the given PDF/A format - default None. @@ -810,6 +846,15 @@ sensiolabs_gotenberg: name: name: ~ value: ~ + split: + # Either intervals or pages. - default None. https://gotenberg.dev/docs/routes#split-libreoffice + split_mode: null + + # Either the intervals or the page ranges to extract, depending on the selected mode. - default None. https://gotenberg.dev/docs/routes#split-libreoffice + split_span: null + + # Specify whether to put extracted pages into a single file or as many files as there are page ranges. Only works with pages mode. - default false. https://gotenberg.dev/docs/routes#split-libreoffice + split_unify: null screenshot: html: diff --git a/docs/generate.php b/docs/generate.php index 0b826131..1936bb68 100755 --- a/docs/generate.php +++ b/docs/generate.php @@ -6,6 +6,7 @@ use Sensiolabs\GotenbergBundle\Builder\Pdf\LibreOfficePdfBuilder; use Sensiolabs\GotenbergBundle\Builder\Pdf\MarkdownPdfBuilder; use Sensiolabs\GotenbergBundle\Builder\Pdf\MergePdfBuilder; +use Sensiolabs\GotenbergBundle\Builder\Pdf\SplitPdfBuilder; use Sensiolabs\GotenbergBundle\Builder\Pdf\UrlPdfBuilder; use Sensiolabs\GotenbergBundle\Builder\Screenshot\HtmlScreenshotBuilder; use Sensiolabs\GotenbergBundle\Builder\Screenshot\MarkdownScreenshotBuilder; @@ -27,6 +28,7 @@ LibreOfficePdfBuilder::class, MergePdfBuilder::class, ConvertPdfBuilder::class, + SplitPdfBuilder::class, ], 'Screenshot' => [ HtmlScreenshotBuilder::class, diff --git a/docs/pdf/customization.md b/docs/pdf/customization.md index d0341b58..6126a2b2 100644 --- a/docs/pdf/customization.md +++ b/docs/pdf/customization.md @@ -23,6 +23,9 @@ [landscape](#landscape) [scale](#scale) [nativePageRanges](#nativePageRanges) +[splitMode](#splitMode) +[splitSpan](#splitSpan) +[splitUnify](#splitUnify) ### Additional content [header and footer](#header-and-footer) @@ -424,6 +427,96 @@ class YourController } } ``` + +## splitMode + +default: `None` + +Either `intervals` or `pages`. + +```php +namespace App\Controller; + +use Sensiolabs\GotenbergBundle\Enum\SplitMode; +use Sensiolabs\GotenbergBundle\GotenbergPdfInterface; + +class YourController +{ + public function yourControllerMethod(GotenbergPdfInterface $gotenberg): Response + { + return $gotenberg->html() + ->content('content.html.twig', [ + 'my_var' => 'value' + ]) + ->splitMode(SplitMode::Intervals) + ->splitSpan('1') + ->generate() + ->stream() + ; + } +} +``` + +## splitSpan + +default: `None` + +Either the intervals or the page ranges to extract, depending on the selected `splitMode`. + +```php +namespace App\Controller; + +use Sensiolabs\GotenbergBundle\Enumeration\SplitMode; +use Sensiolabs\GotenbergBundle\GotenbergPdfInterface; + +class YourController +{ + public function yourControllerMethod(GotenbergPdfInterface $gotenberg): Response + { + return $gotenberg->html() + ->content('content.html.twig', [ + 'my_var' => 'value' + ])) + ->splitMode(SplitMode::Intervals) + ->splitSpan('1') + ->generate() + ->stream() + ; + } +} +``` + +## splitUnify + +Default: `false` + +Specify whether to put extracted pages into a single file or as many files as +there are page ranges. Only works with `pages` mode. + +```php +namespace App\Controller; + +use Sensiolabs\GotenbergBundle\Enum\SplitMode; +use Sensiolabs\GotenbergBundle\GotenbergPdfInterface; + +class YourController +{ + public function yourControllerMethod(GotenbergPdfInterface $gotenberg): Response + { + return $gotenberg->html() + ->content('content.html.twig', [ + 'my_var' => 'value' + ]) + ->splitMode(SplitMode::Pages) + ->splitSpan('1-2') + ->splitUnify() // is same as ->splitUnify(true) + ->generate() + ->stream() + ; + } +} +``` + ## Additional content > [!WARNING] diff --git a/docs/pdf/office-builder.md b/docs/pdf/office-builder.md index 0b8fe11c..b7a05070 100644 --- a/docs/pdf/office-builder.md +++ b/docs/pdf/office-builder.md @@ -61,7 +61,50 @@ class YourController } ``` -## merge +## Available functions + +### Render +[merge](#merge) +[landscape](#landscape) +[nativePageRanges](#nativePageRanges) +[singlePageSheets](#singlePageSheets) +[skipEmptyPages](#skipEmptyPages) +[losslessImageCompression](#losslessImageCompression) +[quality](#quality) +[reduceImageResolution](#reduceImageResolution) +[maxImageResolution](#maxImageResolution) +[splitMode](#splitMode) +[splitSpan](#splitSpan) +[splitUnify](#splitUnify) + +### Additional content +[doNotExportFormFields](#doNotExportFormFields) +[allowDuplicateFieldNames](#allowDuplicateFieldNames) +[doNotExportBookmarks](#doNotExportBookmarks) +[exportBookmarksToPdfDestination](#exportBookmarksToPdfDestination) +[exportPlaceholders](#exportPlaceholders) +[exportNotes](#exportNotes) +[exportNotesPages](#exportNotesPages) +[exportOnlyNotesPages](#exportOnlyNotesPages) +[exportNotesInMargin](#exportNotesInMargin) +[exportLinksRelativeFsys](#exportLinksRelativeFsys) +[exportHiddenSlides](#exportHiddenSlides) +[addOriginalDocumentAsStream](#addOriginalDocumentAsStream) +[download from](#download-from) + +### Formatting +[metadata](#metadata) +[addMetadata](#addMetadata) +[pdfFormat](#pdfFormat) +[pdfUniversalAccess](#pdfUniversalAccess) +[convertOooTargetToPdfTarget](#convertOooTargetToPdfTarget) + +### Security +[password](#password) + +## Render + +### merge Default: `false` @@ -89,7 +132,7 @@ class YourController > [!TIP] > For more information go to [Gotenberg documentations](https://gotenberg.dev/docs/routes#merge-libreoffice). -## landscape +### landscape Default: `false` @@ -117,7 +160,7 @@ class YourController > [!TIP] > For more information go to [Gotenberg documentations](https://gotenberg.dev/docs/routes#page-properties-libreoffice). -## nativePageRanges +### nativePageRanges Default: `All pages generated` @@ -145,12 +188,11 @@ class YourController > [!TIP] > For more information go to [Gotenberg documentations](https://gotenberg.dev/docs/routes#page-properties-libreoffice). -## doNotExportFormFields +### singlePageSheets -Default: `true` +Default: `false` -Set whether to export the form fields or to use the inputted/selected content -of the fields. +Set whether to render the entire spreadsheet as a single page. ```php namespace App\Controller; @@ -163,7 +205,7 @@ class YourController { return $gotenberg->office() ->files('document.txt') - ->doNotExportFormFields() // is same as `->doNotExportFormFields(false)` + ->singlePageSheets() // is same as `->singlePageSheets(true)` ->generate() ->stream() ; @@ -174,11 +216,11 @@ class YourController > [!TIP] > For more information go to [Gotenberg documentations](https://gotenberg.dev/docs/routes#page-properties-libreoffice). -## singlePageSheets +### skipEmptyPages Default: `false` -Set whether to render the entire spreadsheet as a single page. +Specify that automatically inserted empty pages are suppressed. This option is active only if storing Writer documents. ```php namespace App\Controller; @@ -191,9 +233,8 @@ class YourController { return $gotenberg->office() ->files('document.txt') - ->singlePageSheets() // is same as `->singlePageSheets(true)` + ->skipEmptyPages() // is same as `->skipEmptyPages(true)` ->generate() - ->stream() ; } } @@ -202,16 +243,16 @@ class YourController > [!TIP] > For more information go to [Gotenberg documentations](https://gotenberg.dev/docs/routes#page-properties-libreoffice). -## pdfFormat +### losslessImageCompression -Default: `None` +Default: `false` -Convert the resulting PDF into the given PDF/A format. +Specify if images are exported to PDF using a lossless compression format like PNG or compressed using the JPEG format. ```php namespace App\Controller; -use Sensiolabs\GotenbergBundle\Enum\PdfFormat;use Sensiolabs\GotenbergBundle\GotenbergPdfInterface; +use Sensiolabs\GotenbergBundle\GotenbergPdfInterface; class YourController { @@ -219,27 +260,53 @@ class YourController { return $gotenberg->office() ->files('document.txt') - ->pdfFormat(PdfFormat::Pdf1b) + ->losslessImageCompression() // is same as `->losslessImageCompression(true)` ->generate() - ->stream() ; } } ``` > [!TIP] -> For more information go to [Gotenberg documentations](https://gotenberg.dev/docs/routes#pdfa-libreoffice). +> For more information go to [Gotenberg documentations](https://gotenberg.dev/docs/routes#images-libreoffice). -## pdfUniversalAccess +### quality + +Default: `90` + +Specify the quality of the JPG export. A higher value produces a higher-quality image and a larger file. Between 1 and 100. + +```php +namespace App\Controller; + +use Sensiolabs\GotenbergBundle\GotenbergPdfInterface; + +class YourController +{ + public function yourControllerMethod(GotenbergPdfInterface $gotenberg): Response + { + return $gotenberg->office() + ->files('document.txt') + ->quality(75) + ->generate() + ; + } +} +``` + +> [!TIP] +> For more information go to [Gotenberg documentations](https://gotenberg.dev/docs/routes#images-libreoffice). + +### reduceImageResolution Default: `false` -Enable PDF for Universal Access for optimal accessibility. +Specify if the resolution of each image is reduced to the resolution specified by the form field maxImageResolution. ```php namespace App\Controller; -use Sensiolabs\GotenbergBundle\Enum\PdfFormat;use Sensiolabs\GotenbergBundle\GotenbergPdfInterface; +use Sensiolabs\GotenbergBundle\GotenbergPdfInterface; class YourController { @@ -247,27 +314,27 @@ class YourController { return $gotenberg->office() ->files('document.txt') - ->pdfUniversalAccess() // is same as `->pdfUniversalAccess(true)` + ->reduceImageResolution() // is same as `->reduceImageResolution(true)` ->generate() - ->stream() ; } } ``` > [!TIP] -> For more information go to [Gotenberg documentations](https://gotenberg.dev/docs/routes#pdfa-libreoffice). +> For more information go to [Gotenberg documentations](https://gotenberg.dev/docs/routes#images-libreoffice). -## metatada +### maxImageResolution -Default: `None` +Default: `300` -Resets the configuration metadata and add new ones to write. +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. ```php namespace App\Controller; -use Sensiolabs\GotenbergBundle\Enum\PdfFormat;use Sensiolabs\GotenbergBundle\GotenbergPdfInterface; +use Sensiolabs\GotenbergBundle\Enumeration\ImageResolutionDPI; +use Sensiolabs\GotenbergBundle\GotenbergPdfInterface; class YourController { @@ -275,24 +342,27 @@ class YourController { return $gotenberg->office() ->files('document.txt') - ->metadata(['Author' => 'SensioLabs', 'Subject' => 'Gotenberg']) + ->maxImageResolution(ImageResolutionDPI::DPI300) ->generate() - ->stream() ; } } ``` -## addMetadata +> [!TIP] +> For more information go to [Gotenberg documentations](https://gotenberg.dev/docs/routes#images-libreoffice). -Default: `None` +### splitMode -If you want to add metadata from the ones already loaded in the configuration. +default: `None` + +Either `intervals` or `pages`. ```php namespace App\Controller; -use Sensiolabs\GotenbergBundle\Enum\PdfFormat;use Sensiolabs\GotenbergBundle\GotenbergPdfInterface; +use Sensiolabs\GotenbergBundle\Enum\SplitMode; +use Sensiolabs\GotenbergBundle\GotenbergPdfInterface; class YourController { @@ -300,7 +370,8 @@ class YourController { return $gotenberg->office() ->files('document.txt') - ->addMetadata('key', 'value') + ->splitMode(SplitMode::Intervals) + ->splitSpan('1') ->generate() ->stream() ; @@ -309,17 +380,46 @@ class YourController ``` > [!TIP] -> For more information go to [Gotenberg documentations](https://gotenberg.dev/docs/routes#metadata-libreoffice). +> For more information go to [Gotenberg documentations](https://gotenberg.dev/docs/routes#split-libreoffice). + +### splitSpan + +default: `None` + +Either the intervals or the page ranges to extract, depending on the selected `splitMode`. + +```php +namespace App\Controller; + +use Sensiolabs\GotenbergBundle\Enumeration\SplitMode; +use Sensiolabs\GotenbergBundle\GotenbergPdfInterface; + +class YourController +{ + public function yourControllerMethod(GotenbergPdfInterface $gotenberg): Response + { + return $gotenberg->office() + ->files('document.txt') + ->splitMode(SplitMode::Intervals) + ->splitSpan('1') + ->generate() + ->stream() + ; + } +} +``` -## allowDuplicateFieldNames +### splitUnify Default: `false` -Specify whether multiple form fields exported are allowed to have the same field name. +Specify whether to put extracted pages into a single file or as many files as +there are page ranges. Only works with `pages` mode. ```php namespace App\Controller; +use Sensiolabs\GotenbergBundle\Enum\SplitMode; use Sensiolabs\GotenbergBundle\GotenbergPdfInterface; class YourController @@ -328,21 +428,24 @@ class YourController { return $gotenberg->office() ->files('document.txt') - ->allowDuplicateFieldNames() // is same as `->allowDuplicateFieldNames(true)` + ->splitMode(SplitMode::Pages) + ->splitSpan('1-2') + ->splitUnify() // is same as ->splitUnify(true) ->generate() + ->stream() ; } } ``` -> [!TIP] -> For more information go to [Gotenberg documentations](https://gotenberg.dev/docs/routes#page-properties-libreoffice). +## Additional content -## doNotExportBookmarks +### doNotExportFormFields Default: `true` -Specify if bookmarks are exported to PDF. +Set whether to export the form fields or to use the inputted/selected content +of the fields. ```php namespace App\Controller; @@ -355,8 +458,9 @@ class YourController { return $gotenberg->office() ->files('document.txt') - ->doNotExportBookmarks() // is same as `->doNotExportBookmarks(false)` + ->doNotExportFormFields() // is same as `->doNotExportFormFields(false)` ->generate() + ->stream() ; } } @@ -365,11 +469,11 @@ class YourController > [!TIP] > For more information go to [Gotenberg documentations](https://gotenberg.dev/docs/routes#page-properties-libreoffice). -## exportBookmarksToPdfDestination +### allowDuplicateFieldNames Default: `false` -Specify that the bookmarks contained in the source LibreOffice file should be exported to the PDF file as Named Destination. +Specify whether multiple form fields exported are allowed to have the same field name. ```php namespace App\Controller; @@ -382,7 +486,7 @@ class YourController { return $gotenberg->office() ->files('document.txt') - ->exportBookmarksToPdfDestination() // is same as `->exportBookmarksToPdfDestination(true)` + ->allowDuplicateFieldNames() // is same as `->allowDuplicateFieldNames(true)` ->generate() ; } @@ -392,11 +496,11 @@ class YourController > [!TIP] > For more information go to [Gotenberg documentations](https://gotenberg.dev/docs/routes#page-properties-libreoffice). -## exportPlaceholders +### doNotExportBookmarks -Default: `false` +Default: `true` -Export the placeholders fields visual markings only. The exported placeholder is ineffective. +Specify if bookmarks are exported to PDF. ```php namespace App\Controller; @@ -409,7 +513,7 @@ class YourController { return $gotenberg->office() ->files('document.txt') - ->exportPlaceholders() // is same as `->exportPlaceholders(true)` + ->doNotExportBookmarks() // is same as `->doNotExportBookmarks(false)` ->generate() ; } @@ -419,11 +523,11 @@ class YourController > [!TIP] > For more information go to [Gotenberg documentations](https://gotenberg.dev/docs/routes#page-properties-libreoffice). -## exportNotes +### exportBookmarksToPdfDestination Default: `false` -Specify if notes are exported to PDF. +Specify that the bookmarks contained in the source LibreOffice file should be exported to the PDF file as Named Destination. ```php namespace App\Controller; @@ -436,7 +540,7 @@ class YourController { return $gotenberg->office() ->files('document.txt') - ->exportNotes() // is same as `->exportNotes(true)` + ->exportBookmarksToPdfDestination() // is same as `->exportBookmarksToPdfDestination(true)` ->generate() ; } @@ -446,11 +550,11 @@ class YourController > [!TIP] > For more information go to [Gotenberg documentations](https://gotenberg.dev/docs/routes#page-properties-libreoffice). -## exportNotesPages +### exportPlaceholders Default: `false` -Specify if notes pages are exported to PDF. Notes pages are available in Impress documents only. +Export the placeholders fields visual markings only. The exported placeholder is ineffective. ```php namespace App\Controller; @@ -463,7 +567,7 @@ class YourController { return $gotenberg->office() ->files('document.txt') - ->exportNotesPages() // is same as `->exportNotesPages(true)` + ->exportPlaceholders() // is same as `->exportPlaceholders(true)` ->generate() ; } @@ -473,11 +577,11 @@ class YourController > [!TIP] > For more information go to [Gotenberg documentations](https://gotenberg.dev/docs/routes#page-properties-libreoffice). -## exportOnlyNotesPages +### exportNotes Default: `false` -Specify, if the form field exportNotesPages is set to true, if only notes pages are exported to PDF. +Specify if notes are exported to PDF. ```php namespace App\Controller; @@ -490,7 +594,7 @@ class YourController { return $gotenberg->office() ->files('document.txt') - ->exportOnlyNotesPages() // is same as `->exportOnlyNotesPages(true)` + ->exportNotes() // is same as `->exportNotes(true)` ->generate() ; } @@ -500,11 +604,11 @@ class YourController > [!TIP] > For more information go to [Gotenberg documentations](https://gotenberg.dev/docs/routes#page-properties-libreoffice). -## exportNotesInMargin +### exportNotesPages Default: `false` -Specify if notes in margin are exported to PDF. +Specify if notes pages are exported to PDF. Notes pages are available in Impress documents only. ```php namespace App\Controller; @@ -517,7 +621,7 @@ class YourController { return $gotenberg->office() ->files('document.txt') - ->exportNotesInMargin() // is same as `->exportNotesInMargin(true)` + ->exportNotesPages() // is same as `->exportNotesPages(true)` ->generate() ; } @@ -527,11 +631,11 @@ class YourController > [!TIP] > For more information go to [Gotenberg documentations](https://gotenberg.dev/docs/routes#page-properties-libreoffice). -## convertOooTargetToPdfTarget +### exportOnlyNotesPages Default: `false` -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. +Specify, if the form field exportNotesPages is set to true, if only notes pages are exported to PDF. ```php namespace App\Controller; @@ -544,7 +648,7 @@ class YourController { return $gotenberg->office() ->files('document.txt') - ->convertOooTargetToPdfTarget() // is same as `->convertOooTargetToPdfTarget(true)` + ->exportOnlyNotesPages() // is same as `->exportOnlyNotesPages(true)` ->generate() ; } @@ -554,11 +658,11 @@ class YourController > [!TIP] > For more information go to [Gotenberg documentations](https://gotenberg.dev/docs/routes#page-properties-libreoffice). -## exportLinksRelativeFsys +### exportNotesInMargin Default: `false` -Specify that the file system related hyperlinks (file:// protocol) present in the document will be exported as relative to the source document location. +Specify if notes in margin are exported to PDF. ```php namespace App\Controller; @@ -571,7 +675,7 @@ class YourController { return $gotenberg->office() ->files('document.txt') - ->exportLinksRelativeFsys() // is same as `->exportLinksRelativeFsys(true)` + ->exportNotesInMargin() // is same as `->exportNotesInMargin(true)` ->generate() ; } @@ -581,11 +685,11 @@ class YourController > [!TIP] > For more information go to [Gotenberg documentations](https://gotenberg.dev/docs/routes#page-properties-libreoffice). -## exportHiddenSlides +### exportLinksRelativeFsys Default: `false` -Export, for LibreOffice Impress, slides that are not included in slide shows. +Specify that the file system related hyperlinks (file:// protocol) present in the document will be exported as relative to the source document location. ```php namespace App\Controller; @@ -598,7 +702,7 @@ class YourController { return $gotenberg->office() ->files('document.txt') - ->exportHiddenSlides() // is same as `->exportHiddenSlides(true)` + ->exportLinksRelativeFsys() // is same as `->exportLinksRelativeFsys(true)` ->generate() ; } @@ -608,11 +712,11 @@ class YourController > [!TIP] > For more information go to [Gotenberg documentations](https://gotenberg.dev/docs/routes#page-properties-libreoffice). -## skipEmptyPages +### exportHiddenSlides Default: `false` -Specify that automatically inserted empty pages are suppressed. This option is active only if storing Writer documents. +Export, for LibreOffice Impress, slides that are not included in slide shows. ```php namespace App\Controller; @@ -625,7 +729,7 @@ class YourController { return $gotenberg->office() ->files('document.txt') - ->skipEmptyPages() // is same as `->skipEmptyPages(true)` + ->exportHiddenSlides() // is same as `->exportHiddenSlides(true)` ->generate() ; } @@ -635,7 +739,7 @@ class YourController > [!TIP] > For more information go to [Gotenberg documentations](https://gotenberg.dev/docs/routes#page-properties-libreoffice). -## addOriginalDocumentAsStream +### addOriginalDocumentAsStream Default: `false` @@ -662,43 +766,88 @@ class YourController > [!TIP] > For more information go to [Gotenberg documentations](https://gotenberg.dev/docs/routes#page-properties-libreoffice). -## losslessImageCompression +### download from -Default: `false` +> [!WARNING] +> URL of the file. It MUST return a `Content-Disposition` header with a filename parameter. -Specify if images are exported to PDF using a lossless compression format like PNG or compressed using the JPEG format. +To download files resource from URLs. ```php namespace App\Controller; use Sensiolabs\GotenbergBundle\GotenbergPdfInterface; +class YourController +{ + public function yourControllerMethod(GotenbergPdfInterface $gotenberg): Response + { + return $gotenberg + ->office() + ->downloadFrom([ + [ + 'url' => 'http://url/to/file.com', + 'extraHttpHeaders' => + [ + 'MyHeader' => 'MyValue', + ], + ], + [ + 'url' => 'http://url/to/file.com', + 'extraHttpHeaders' => + [ + 'MyHeaderOne' => 'MyValue', + 'MyHeaderTwo' => 'MyValue', + ], + ], + ]) + ->generate() + ->stream() + ; + } +} +``` + +> [!TIP] +> For more information go to [Gotenberg documentations](https://gotenberg.dev/docs/routes#download-from). + +## Formatting + +### metadata + +Default: `None` + +Resets the configuration metadata and add new ones to write. + +```php +namespace App\Controller; + +use Sensiolabs\GotenbergBundle\Enum\PdfFormat;use Sensiolabs\GotenbergBundle\GotenbergPdfInterface; + class YourController { public function yourControllerMethod(GotenbergPdfInterface $gotenberg): Response { return $gotenberg->office() ->files('document.txt') - ->losslessImageCompression() // is same as `->losslessImageCompression(true)` + ->metadata(['Author' => 'SensioLabs', 'Subject' => 'Gotenberg']) ->generate() + ->stream() ; } } ``` -> [!TIP] -> For more information go to [Gotenberg documentations](https://gotenberg.dev/docs/routes#images-libreoffice). - -## quality +### addMetadata -Default: `90` +Default: `None` -Specify the quality of the JPG export. A higher value produces a higher-quality image and a larger file. Between 1 and 100. +If you want to add metadata from the ones already loaded in the configuration. ```php namespace App\Controller; -use Sensiolabs\GotenbergBundle\GotenbergPdfInterface; +use Sensiolabs\GotenbergBundle\Enum\PdfFormat;use Sensiolabs\GotenbergBundle\GotenbergPdfInterface; class YourController { @@ -706,26 +855,27 @@ class YourController { return $gotenberg->office() ->files('document.txt') - ->quality(75) + ->addMetadata('key', 'value') ->generate() + ->stream() ; } } ``` > [!TIP] -> For more information go to [Gotenberg documentations](https://gotenberg.dev/docs/routes#images-libreoffice). +> For more information go to [Gotenberg documentations](https://gotenberg.dev/docs/routes#metadata-libreoffice). -## reduceImageResolution +### pdfFormat -Default: `false` +Default: `None` -Specify if the resolution of each image is reduced to the resolution specified by the form field maxImageResolution. +Convert the resulting PDF into the given PDF/A format. ```php namespace App\Controller; -use Sensiolabs\GotenbergBundle\GotenbergPdfInterface; +use Sensiolabs\GotenbergBundle\Enum\PdfFormat;use Sensiolabs\GotenbergBundle\GotenbergPdfInterface; class YourController { @@ -733,27 +883,27 @@ class YourController { return $gotenberg->office() ->files('document.txt') - ->reduceImageResolution() // is same as `->reduceImageResolution(true)` + ->pdfFormat(PdfFormat::Pdf1b) ->generate() + ->stream() ; } } ``` > [!TIP] -> For more information go to [Gotenberg documentations](https://gotenberg.dev/docs/routes#images-libreoffice). +> For more information go to [Gotenberg documentations](https://gotenberg.dev/docs/routes#pdfa-libreoffice). -## maxImageResolution +### pdfUniversalAccess -Default: `300` +Default: `false` -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. +Enable PDF for Universal Access for optimal accessibility. ```php namespace App\Controller; -use Sensiolabs\GotenbergBundle\Enumeration\ImageResolutionDPI; -use Sensiolabs\GotenbergBundle\GotenbergPdfInterface; +use Sensiolabs\GotenbergBundle\Enum\PdfFormat;use Sensiolabs\GotenbergBundle\GotenbergPdfInterface; class YourController { @@ -761,22 +911,22 @@ class YourController { return $gotenberg->office() ->files('document.txt') - ->maxImageResolution(ImageResolutionDPI::DPI300) + ->pdfUniversalAccess() // is same as `->pdfUniversalAccess(true)` ->generate() + ->stream() ; } } ``` > [!TIP] -> For more information go to [Gotenberg documentations](https://gotenberg.dev/docs/routes#images-libreoffice). +> For more information go to [Gotenberg documentations](https://gotenberg.dev/docs/routes#pdfa-libreoffice). -### download from +### convertOooTargetToPdfTarget -> [!WARNING] -> URL of the file. It MUST return a `Content-Disposition` header with a filename parameter. +Default: `false` -To download files resource from URLs. +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. ```php namespace App\Controller; @@ -787,36 +937,21 @@ class YourController { public function yourControllerMethod(GotenbergPdfInterface $gotenberg): Response { - return $gotenberg - ->office() - ->downloadFrom([ - [ - 'url' => 'http://url/to/file.com', - 'extraHttpHeaders' => - [ - 'MyHeader' => 'MyValue', - ], - ], - [ - 'url' => 'http://url/to/file.com', - 'extraHttpHeaders' => - [ - 'MyHeaderOne' => 'MyValue', - 'MyHeaderTwo' => 'MyValue', - ], - ], - ]) + return $gotenberg->office() + ->files('document.txt') + ->convertOooTargetToPdfTarget() // is same as `->convertOooTargetToPdfTarget(true)` ->generate() - ->stream() - ; + ; } } ``` > [!TIP] -> For more information go to [Gotenberg documentations](https://gotenberg.dev/docs/routes#download-from). +> For more information go to [Gotenberg documentations](https://gotenberg.dev/docs/routes#page-properties-libreoffice). + +## Security -## password +### password Default: `None` diff --git a/docs/pdf/split-builder.md b/docs/pdf/split-builder.md new file mode 100644 index 00000000..aba8b31d --- /dev/null +++ b/docs/pdf/split-builder.md @@ -0,0 +1,125 @@ +# Split Builder + +You may have the possibility to split several PDF pages or documents. + +## 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). + +```php +namespace App\Controller; + +use Sensiolabs\GotenbergBundle\GotenbergPdfInterface; + +class YourController +{ + public function yourControllerMethod(GotenbergPdfInterface $gotenberg): Response + { + return $gotenberg->split() + ->files( + 'document_1.pdf', + 'document_2.pdf', + ) + ->splitMode(SplitMode::Pages) + ->splitSpan('1-2') + ->splitUnify() + ->generate() + ->stream() + ; + } +} +``` + +> [!TIP] +> For more information go to [Gotenberg documentations](https://gotenberg.dev/docs/routes#split-pdfs-route). + +## splitMode + +> [!WARNING] +> Required + +Either `intervals` or `pages`. + +```php +namespace App\Controller; + +use Sensiolabs\GotenbergBundle\Enum\SplitMode; +use Sensiolabs\GotenbergBundle\GotenbergPdfInterface; + +class YourController +{ + public function yourControllerMethod(GotenbergPdfInterface $gotenberg): Response + { + return $gotenberg->split() + ->files( + 'document_1.pdf', + 'document_2.pdf', + ) + ->splitMode(SplitMode::Intervals) + ->splitSpan('1') + ->generate() + ->stream() + ; + } +} +``` + +## splitSpan + +> [!WARNING] +> Required + +Either the intervals or the page ranges to extract, depending on the selected `splitMode`. + +```php +namespace App\Controller; + +use Sensiolabs\GotenbergBundle\Enumeration\SplitMode; +use Sensiolabs\GotenbergBundle\GotenbergPdfInterface; + +class YourController +{ + public function yourControllerMethod(GotenbergPdfInterface $gotenberg): Response + { + return $gotenberg->split() + ->files('document_1.pdf') + ->splitMode(SplitMode::Intervals) + ->splitSpan('1') + ->generate() + ->stream() + ; + } +} +``` + +## splitUnify + +Default: `false` + +Specify whether to put extracted pages into a single file or as many files as +there are page ranges. Only works with `pages` mode. + +```php +namespace App\Controller; + +use Sensiolabs\GotenbergBundle\Enum\SplitMode; +use Sensiolabs\GotenbergBundle\GotenbergPdfInterface; + +class YourController +{ + public function yourControllerMethod(GotenbergPdfInterface $gotenberg): Response + { + return $gotenberg->split() + ->files('document_1.pdf') + ->splitMode(SplitMode::Pages) + ->splitSpan('1-2') + ->splitUnify() // is same as ->splitUnify(true) + ->generate() + ->stream() + ; + } +} +``` diff --git a/src/Builder/Pdf/AbstractChromiumPdfBuilder.php b/src/Builder/Pdf/AbstractChromiumPdfBuilder.php index c734cccf..deecefe0 100644 --- a/src/Builder/Pdf/AbstractChromiumPdfBuilder.php +++ b/src/Builder/Pdf/AbstractChromiumPdfBuilder.php @@ -9,6 +9,7 @@ use Sensiolabs\GotenbergBundle\Enumeration\PaperSizeInterface; use Sensiolabs\GotenbergBundle\Enumeration\Part; use Sensiolabs\GotenbergBundle\Enumeration\PdfFormat; +use Sensiolabs\GotenbergBundle\Enumeration\SplitMode; use Sensiolabs\GotenbergBundle\Enumeration\Unit; use Sensiolabs\GotenbergBundle\Enumeration\UserAgent; use Sensiolabs\GotenbergBundle\Exception\InvalidBuilderConfiguration; @@ -567,6 +568,48 @@ public function addMetadata(string $key, string $value): static return $this; } + /** + * Either intervals or pages. (default None). + * + * @see https://gotenberg.dev/docs/routes#split-chromium + */ + public function splitMode(SplitMode|null $splitMode = null): static + { + if (null === $splitMode) { + unset($this->formFields['splitMode']); + + return $this; + } + + $this->formFields['splitMode'] = $splitMode; + + return $this; + } + + /** + * Either the intervals or the page ranges to extract, depending on the selected mode. (default None). + * + * @see https://gotenberg.dev/docs/routes#split-chromium + */ + public function splitSpan(string $splitSpan): static + { + $this->formFields['splitSpan'] = $splitSpan; + + return $this; + } + + /** + * Specify whether to put extracted pages into a single file or as many files as there are page ranges. Only works with pages mode. (default false). + * + * @see https://gotenberg.dev/docs/routes#split-chromium + */ + public function splitUnify(bool $bool = true): static + { + $this->formFields['splitUnify'] = $bool; + + return $this; + } + protected function withPdfPartFile(Part $pdfPart, string $path): static { $dataPart = new DataPart( @@ -637,6 +680,9 @@ protected function addConfiguration(string $configurationName, mixed $value): vo 'skip_network_idle_event' => $this->skipNetworkIdleEvent($value), 'metadata' => $this->metadata($value), 'download_from' => $this->downloadFrom($value), + 'split_mode' => $this->splitMode(SplitMode::from($value)), + 'split_span' => $this->splitSpan($value), + 'split_unify' => $this->splitUnify($value), 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/LibreOfficePdfBuilder.php b/src/Builder/Pdf/LibreOfficePdfBuilder.php index 38272193..8a09a08e 100644 --- a/src/Builder/Pdf/LibreOfficePdfBuilder.php +++ b/src/Builder/Pdf/LibreOfficePdfBuilder.php @@ -4,6 +4,7 @@ use Sensiolabs\GotenbergBundle\Enumeration\ImageResolutionDPI; use Sensiolabs\GotenbergBundle\Enumeration\PdfFormat; +use Sensiolabs\GotenbergBundle\Enumeration\SplitMode; use Sensiolabs\GotenbergBundle\Exception\InvalidBuilderConfiguration; use Sensiolabs\GotenbergBundle\Exception\MissingRequiredFieldException; use Symfony\Component\Mime\Part\DataPart; @@ -338,6 +339,48 @@ public function maxImageResolution(ImageResolutionDPI $resolution): self return $this; } + /** + * Either intervals or pages. (default None). + * + * @see https://gotenberg.dev/docs/routes#split-libreoffice + */ + public function splitMode(SplitMode|null $splitMode = null): static + { + if (null === $splitMode) { + unset($this->formFields['splitMode']); + + return $this; + } + + $this->formFields['splitMode'] = $splitMode; + + return $this; + } + + /** + * Either the intervals or the page ranges to extract, depending on the selected mode. (default None). + * + * @see https://gotenberg.dev/docs/routes#split-libreoffice + */ + public function splitSpan(string $splitSpan): static + { + $this->formFields['splitSpan'] = $splitSpan; + + return $this; + } + + /** + * Specify whether to put extracted pages into a single file or as many files as there are page ranges. Only works with pages mode. (default false). + * + * @see https://gotenberg.dev/docs/routes#split-libreoffice + */ + public function splitUnify(bool $bool = true): static + { + $this->formFields['splitUnify'] = $bool; + + return $this; + } + public function getMultipartFormData(): array { if ([] === ($this->formFields['files'] ?? []) && [] === ($this->formFields['downloadFrom'] ?? [])) { @@ -382,6 +425,9 @@ private function addConfiguration(string $configurationName, mixed $value): void 'reduce_image_resolution' => $this->reduceImageResolution($value), 'max_image_resolution' => $this->maxImageResolution(ImageResolutionDPI::from($value)), 'download_from' => $this->downloadFrom($value), + 'split_mode' => $this->splitMode(SplitMode::from($value)), + 'split_span' => $this->splitSpan($value), + 'split_unify' => $this->splitUnify($value), 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/SplitPdfBuilder.php b/src/Builder/Pdf/SplitPdfBuilder.php new file mode 100644 index 00000000..f101d122 --- /dev/null +++ b/src/Builder/Pdf/SplitPdfBuilder.php @@ -0,0 +1,116 @@ + $configurations + */ + public function setConfigurations(array $configurations): static + { + foreach ($configurations as $property => $value) { + $this->addConfiguration($property, $value); + } + + return $this; + } + + /** + * Either intervals or pages. (default None). + * + * @see https://gotenberg.dev/docs/routes#split-pdfs-route + */ + public function splitMode(SplitMode|null $splitMode = null): self + { + if (null === $splitMode) { + unset($this->formFields['splitMode']); + + return $this; + } + + $this->formFields['splitMode'] = $splitMode; + + return $this; + } + + /** + * Either the intervals or the page ranges to extract, depending on the selected mode. (default None). + * + * @see https://gotenberg.dev/docs/routes#split-pdfs-route + */ + public function splitSpan(string $splitSpan): self + { + $this->formFields['splitSpan'] = $splitSpan; + + return $this; + } + + /** + * Specify whether to put extracted pages into a single file or as many files as there are page ranges. Only works with pages mode. (default false). + * + * @see https://gotenberg.dev/docs/routes#split-pdfs-route + */ + public function splitUnify(bool $bool = true): self + { + $this->formFields['splitUnify'] = $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('splitMode', $this->formFields) || !\array_key_exists('splitSpan', $this->formFields)) { + throw new MissingRequiredFieldException('"splitMode" and "splitSpan" 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) { + 'split_mode' => $this->splitMode(SplitMode::from($value)), + 'split_span' => $this->splitSpan($value), + 'split_unify' => $this->splitUnify($value), + 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/Debug/TraceableGotenbergPdf.php b/src/Debug/TraceableGotenbergPdf.php index d70dd42b..09cfc7f7 100644 --- a/src/Debug/TraceableGotenbergPdf.php +++ b/src/Debug/TraceableGotenbergPdf.php @@ -8,6 +8,7 @@ use Sensiolabs\GotenbergBundle\Builder\Pdf\MarkdownPdfBuilder; use Sensiolabs\GotenbergBundle\Builder\Pdf\MergePdfBuilder; use Sensiolabs\GotenbergBundle\Builder\Pdf\PdfBuilderInterface; +use Sensiolabs\GotenbergBundle\Builder\Pdf\SplitPdfBuilder; use Sensiolabs\GotenbergBundle\Builder\Pdf\UrlPdfBuilder; use Sensiolabs\GotenbergBundle\Debug\Builder\TraceablePdfBuilder; use Sensiolabs\GotenbergBundle\GotenbergPdfInterface; @@ -139,6 +140,23 @@ public function convert(): PdfBuilderInterface return $traceableBuilder; } + /** + * @return SplitPdfBuilder|TraceablePdfBuilder + */ + public function split(): PdfBuilderInterface + { + /** @var SplitPdfBuilder|TraceablePdfBuilder $traceableBuilder */ + $traceableBuilder = $this->inner->split(); + + if (!$traceableBuilder instanceof TraceablePdfBuilder) { + return $traceableBuilder; + } + + $this->builders[] = ['split', $traceableBuilder]; + + return $traceableBuilder; + } + /** * @return list */ diff --git a/src/DependencyInjection/Configuration.php b/src/DependencyInjection/Configuration.php index 47e65493..c8d5b30d 100644 --- a/src/DependencyInjection/Configuration.php +++ b/src/DependencyInjection/Configuration.php @@ -7,6 +7,7 @@ use Sensiolabs\GotenbergBundle\Enumeration\PaperSize; use Sensiolabs\GotenbergBundle\Enumeration\PdfFormat; use Sensiolabs\GotenbergBundle\Enumeration\ScreenshotFormat; +use Sensiolabs\GotenbergBundle\Enumeration\SplitMode; use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; use Symfony\Component\Config\Definition\Builder\NodeDefinition; use Symfony\Component\Config\Definition\Builder\TreeBuilder; @@ -57,6 +58,7 @@ public function getConfigTreeBuilder(): TreeBuilder ->append($this->addPdfOfficeNode()) ->append($this->addPdfMergeNode()) ->append($this->addPdfConvertNode()) + ->append($this->addPdfSplitNode()) ->end() ->arrayNode('screenshot') ->addDefaultsIfNotSet() @@ -356,6 +358,7 @@ private function addChromiumPdfOptionsNode(ArrayNodeDefinition $parent): void ; $this->addPdfFormat($parent); + $this->addSplitConfigurationNode($parent); } private function addChromiumScreenshotOptionsNode(ArrayNodeDefinition $parent): void @@ -597,6 +600,7 @@ private function addPdfOfficeNode(): NodeDefinition ; $this->addPdfFormat($treeBuilder->getRootNode()); + $this->addSplitConfigurationNode($treeBuilder->getRootNode()); return $treeBuilder->getRootNode(); } @@ -624,6 +628,14 @@ private function addPdfMergeNode(): NodeDefinition return $treeBuilder->getRootNode(); } + private function addPdfSplitNode(): NodeDefinition + { + $treeBuilder = new TreeBuilder('split'); + $this->addSplitConfigurationNode($treeBuilder->getRootNode()); + + return $treeBuilder->getRootNode(); + } + private function addPdfFormat(ArrayNodeDefinition $parent): void { $parent @@ -882,4 +894,38 @@ private function addExtraHttpHeaders(): NodeDefinition ->end() ; } + + private function addSplitConfigurationNode(ArrayNodeDefinition $parent): void + { + $parent + ->addDefaultsIfNotSet() + ->children() + ->enumNode('split_mode') + ->info('Either intervals or pages. - default None. https://gotenberg.dev/docs/routes#split-chromium') + ->values(array_map(static fn (SplitMode $case): string => $case->value, SplitMode::cases())) + ->defaultNull() + ->end() + ->scalarNode('split_span') + ->info('Either the intervals or the page ranges to extract, depending on the selected mode. - default None. https://gotenberg.dev/docs/routes#split-chromium') + ->defaultNull() + ->validate() + ->ifTrue(static function ($option): bool { + return preg_match('/([\d]+[-][\d]+)/', $option) !== 1 && preg_match('/(\d+)/', $option) !== 1; + }) + ->thenInvalid('Invalid value, the range value format need to look like e.g 1-20 or as a single int value e.g 2.') + ->end() + ->end() + ->booleanNode('split_unify') + ->info('Specify whether to put extracted pages into a single file or as many files as there are page ranges. Only works with pages mode. - default false. https://gotenberg.dev/docs/routes#split-chromium') + ->defaultNull() + ->end() + ->end() + ->validate() + ->ifTrue(static function ($option): bool { + return isset($option['split_mode']) && !isset($option['split_span']); + }) + ->thenInvalid('"splitMode" and "splitSpan" must be provided.') + ->end() + ; + } } diff --git a/src/DependencyInjection/SensiolabsGotenbergExtension.php b/src/DependencyInjection/SensiolabsGotenbergExtension.php index b9c490fa..8214c6f3 100644 --- a/src/DependencyInjection/SensiolabsGotenbergExtension.php +++ b/src/DependencyInjection/SensiolabsGotenbergExtension.php @@ -31,7 +31,8 @@ * markdown: array, * office: array, * merge: array, - * convert: array + * convert: array, + * split: array * }, * screenshot: array{ * html: array, @@ -71,6 +72,7 @@ public function load(array $configs, ContainerBuilder $container): void 'office' => $this->cleanUserOptions($config['default_options']['pdf']['office']), 'merge' => $this->cleanUserOptions($config['default_options']['pdf']['merge']), 'convert' => $this->cleanUserOptions($config['default_options']['pdf']['convert']), + 'split' => $this->cleanUserOptions($config['default_options']['pdf']['split']), ]) ; } @@ -112,6 +114,8 @@ public function load(array $configs, ContainerBuilder $container): void $this->processDefaultOptions($container, $config, '.sensiolabs_gotenberg.pdf_builder.convert', $config['default_options']['pdf']['convert']); + $this->processDefaultOptions($container, $config, '.sensiolabs_gotenberg.pdf_builder.split', $config['default_options']['pdf']['split']); + $this->processDefaultOptions($container, $config, '.sensiolabs_gotenberg.screenshot_builder.html', $config['default_options']['screenshot']['html']); $this->processDefaultOptions($container, $config, '.sensiolabs_gotenberg.screenshot_builder.url', $config['default_options']['screenshot']['url']); diff --git a/src/Enumeration/SplitMode.php b/src/Enumeration/SplitMode.php new file mode 100644 index 00000000..6370a3d0 --- /dev/null +++ b/src/Enumeration/SplitMode.php @@ -0,0 +1,9 @@ +getInternal('convert'); } + + public function split(): PdfBuilderInterface + { + return $this->getInternal('split'); + } } diff --git a/src/GotenbergPdfInterface.php b/src/GotenbergPdfInterface.php index e695c17d..8a952884 100644 --- a/src/GotenbergPdfInterface.php +++ b/src/GotenbergPdfInterface.php @@ -8,6 +8,7 @@ use Sensiolabs\GotenbergBundle\Builder\Pdf\MarkdownPdfBuilder; use Sensiolabs\GotenbergBundle\Builder\Pdf\MergePdfBuilder; use Sensiolabs\GotenbergBundle\Builder\Pdf\PdfBuilderInterface; +use Sensiolabs\GotenbergBundle\Builder\Pdf\SplitPdfBuilder; use Sensiolabs\GotenbergBundle\Builder\Pdf\UrlPdfBuilder; interface GotenbergPdfInterface @@ -50,4 +51,9 @@ public function merge(): PdfBuilderInterface; * @return ConvertPdfBuilder */ public function convert(): PdfBuilderInterface; + + /** + * @return SplitPdfBuilder + */ + public function split(): PdfBuilderInterface; } diff --git a/tests/Builder/Pdf/SplitPdfBuilderTest.php b/tests/Builder/Pdf/SplitPdfBuilderTest.php new file mode 100644 index 00000000..100218df --- /dev/null +++ b/tests/Builder/Pdf/SplitPdfBuilderTest.php @@ -0,0 +1,120 @@ +gotenbergClient + ->expects($this->once()) + ->method('call') + ->with( + $this->equalTo('/forms/pdfengines/split'), + $this->anything(), + $this->anything(), + ) + ; + + $this->getSplitPdfBuilder() + ->files(self::PDF_DOCUMENTS_DIR.'/multi_page.pdf') + ->splitMode(SplitMode::Pages) + ->splitSpan('1') + ->generate() + ; + } + + public static function configurationIsCorrectlySetProvider(): \Generator + { + yield 'split_mode' => [ + [ + 'split_mode' => 'pages', + 'split_span' => '1', + ], + [ + 'splitMode' => 'pages', + ], + ]; + yield 'split_span' => [ + [ + 'split_span' => '1', + 'split_mode' => 'pages', + ], + [ + 'splitSpan' => '1', + ], + ]; + yield 'split_unify' => [ + [ + 'split_unify' => true, + 'split_span' => '1', + 'split_mode' => 'pages', + ], + [ + 'splitUnify' => true, + ], + ]; + } + + /** + * @param array $configurations + * @param array $expected + */ + #[DataProvider('configurationIsCorrectlySetProvider')] + public function testConfigurationIsCorrectlySet(array $configurations, array $expected): void + { + $builder = $this->getSplitPdfBuilder(); + $builder->setConfigurations($configurations); + $builder->files(self::PDF_DOCUMENTS_DIR.'/multi_page.pdf'); + + self::assertEquals($expected, $builder->getMultipartFormData()[0]); + } + + public function testRequiredFormData(): void + { + $builder = $this->getSplitPdfBuilder(); + + $this->expectException(MissingRequiredFieldException::class); + $this->expectExceptionMessage('"splitMode" and "splitSpan" must be provided.'); + + $builder->getMultipartFormData(); + } + + public function testRequiredFile(): void + { + $builder = $this->getSplitPdfBuilder() + ->splitMode(SplitMode::Pages) + ->splitSpan('1') + ; + + $this->expectException(MissingRequiredFieldException::class); + $this->expectExceptionMessage('At least one PDF file is required'); + + $builder->getMultipartFormData(); + } + + private function getSplitPdfBuilder(): SplitPdfBuilder + { + return (new SplitPdfBuilder($this->gotenbergClient, self::$assetBaseDirFormatter, $this->webhookConfigurationRegistry)) + ->processor(new NullProcessor()) + ; + } +} diff --git a/tests/DependencyInjection/ConfigurationTest.php b/tests/DependencyInjection/ConfigurationTest.php index f24e583b..4fdefb97 100644 --- a/tests/DependencyInjection/ConfigurationTest.php +++ b/tests/DependencyInjection/ConfigurationTest.php @@ -263,6 +263,9 @@ private static function getBundleDefaultConfig(): array 'pdf_format' => null, 'pdf_universal_access' => null, 'download_from' => [], + 'split_mode' => null, + 'split_span' => null, + 'split_unify' => null, ], 'url' => [ 'single_page' => null, @@ -294,6 +297,9 @@ private static function getBundleDefaultConfig(): array 'pdf_format' => null, 'pdf_universal_access' => null, 'download_from' => [], + 'split_mode' => null, + 'split_span' => null, + 'split_unify' => null, ], 'markdown' => [ 'single_page' => null, @@ -325,6 +331,9 @@ private static function getBundleDefaultConfig(): array 'pdf_format' => null, 'pdf_universal_access' => null, 'download_from' => [], + 'split_mode' => null, + 'split_span' => null, + 'split_unify' => null, ], 'office' => [ 'password' => null, @@ -353,6 +362,9 @@ private static function getBundleDefaultConfig(): array 'reduce_image_resolution' => null, 'max_image_resolution' => null, 'download_from' => [], + 'split_mode' => null, + 'split_span' => null, + 'split_unify' => null, ], 'merge' => [ 'pdf_format' => null, @@ -364,6 +376,11 @@ private static function getBundleDefaultConfig(): array 'pdf_universal_access' => null, 'download_from' => [], ], + 'split' => [ + 'split_mode' => null, + 'split_span' => null, + 'split_unify' => null, + ], ], 'screenshot' => [ 'html' => [ diff --git a/tests/DependencyInjection/SensiolabsGotenbergExtensionTest.php b/tests/DependencyInjection/SensiolabsGotenbergExtensionTest.php index a69c7dd4..d984c616 100644 --- a/tests/DependencyInjection/SensiolabsGotenbergExtensionTest.php +++ b/tests/DependencyInjection/SensiolabsGotenbergExtensionTest.php @@ -426,6 +426,7 @@ public function testDataCollectorIsProperlyConfiguredIfEnabled(): void 'pdf_format' => 'PDF/A-2b', 'download_from' => [], ], + 'split' => [], ], $dataCollectorOptions); } diff --git a/tests/Fixtures/pdf/multi_page.pdf b/tests/Fixtures/pdf/multi_page.pdf new file mode 100644 index 0000000000000000000000000000000000000000..bb43e8f10d2caaa0a3a497d713f5a6f7a2329944 GIT binary patch literal 139349 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

dl}znD6+>i|(SWcdqfNV^ zhT>qHF9c|*3oBlKgM52s&=K}DCexqbQc3)RBpobE&34S1<#hWUAfh~#`G}!x4{gv# zo_|o~I*UV#dv5{@o$amsMptO__a@7wuW`5sRk1y66%hp=q=I2PUflHqHn$!0|JE*? z7U>XC)&;n-x|dR0O@@3(W|llt;}Y_jBYp*8LFri3%4*n%#pfnI{S8k*SKHXg70-8e z<*|=-n29p&V09LD%Cd%s_g%Utxw{hMrC>4QpK;Eauccz3!fNA8hsh>&wl;G7oi0W% zGKh_;CHbNPj_{+6lfl}F{E9O|S5CI=^GBACdwisWV=GN9+3}2YsOonqsmICcXtC-2 zhO+zNQKy#yCPGg3==-Dy;iKVk))UbDB9)=onslwoe^zBEG-Rr)whQs(H{9;(y+VPe zrJlf6&xhAYpFP{n5k3?P<|rg0;s=3Z1R#GsiLx$?eP(D(Ld-GOvj0rppphycgH5;@ z*E7fk;uoKnFTp?+pnn2_6~a#2BOXOwr!w}M7!B8JO!#9)tJbP5`|$}K@>YVcBIznp zRcB~aa$Xo7@)xDa_9ZKlb36yuj}@7WmLlW&$~ZDOpgJHksWDMx>~kGW_Y|Ln7YqtS zXG7;Xw2+?sNz7tige?5T^ZB-?=w~a_!^p_8Ldr%RR9R2)gS=k`1La+ zEgrMUyTQT4D#L@+InY&_H%5yTsBWbqB?SX@5w4l&+zR&pr3-cD zm-V&4%*~Qq7_Te9Lu8>U*a}iDC)7IUenI{Bub=vAjS7M!3!NF2(E!63cs58{7Q#rG7}51h$k^}b zy2EP*o3alYkaZDl=*&!n_c~EfWl?1ZUs7`0(4K`cwv3U#vff_#dqG#rt082@r4{@M zOr%Sg_bzathNSs)aG*t^maaaZH!8>rcQGWPnJW;Oj5rZKdIRq1?U9j~+UCqTU};-T z9{IXO`Z*w#)<*Er3&7{K%2uu$FMr2q^rULGrmZL@v$Y<@T&UBr;v5sF`~FQG5QV$a zxF&LMFOXHT7|2VrzeWO)I4C!1bLVmDlEr;NL6SI~Pwaf(FW}>#PWDmrpnMWmGAr*q zHP1w;ftO-n&6G^@>NU;^+%4aDcKWspJcBGOz`(we^zJ-SikAd59sB_PJeGkS5JF4! zNxzlpj<%3%a$0z0{RWq25i{N{!M^Bny=C||f+kyS(xkopr(rWQyNshvC_k`+-o)$G zx#9cKc0ENYfzlFv+Tg03Ww0w7Se|oz{kDLQNE$TEJ;S)*d(~_zP$^2)ZZBW9UG|HO z?ugSulRDrHiSq-5+z<6r;Ye)A)fmpvYht53uEh&w26k<=Wpz0h)MhYsyO2A20d`+2 zz$|YEXqT$Htgg10)eNR;#VOffOOjyWgOxj#EV#bK`z()JPM?wPngT1&*OK)aW2CVS z0{`L>^?5E{%AAPAQ6?^2WTDonZbjG4q!R8$!&;2oyOZ}Ns=EAaJ?OCW6cn976f2Dv zW6?|2O7M>AHJ}SKZ;Ji)a6Vu90 zXQLC+tQ}v=+v|^Vhpqq^D%jkQb~bn~JLDh4$EXfdN@XyGwp-}X^lQ*@iv|}bDe|qB z_6|eY{J&&M5+&Eq?f{XlU--M=16|(A+e0ly%`?6eI$9a20Ua@pgkHYmJ6|E=o$H3D zP)mc8Y^&!R))O2M{P^H#ZsbKGi$_PE>V!D|vT#h%2$EN(a@(*Vc5pnPEJsj$bFv|_g-th83m-sxZ(SnQ7nU1B zZVe5ZL6fW>i?n4L=pfPu2a@mVQ|< znd~Aek;uz?5ufDyxfC*sOrn_+ll`e@pG8}4I$3QT%)cxGz<`~OFttWp3J{>UM3HF0 zm0ebBS9jMRWuJ1|=UJsAF%zs-mZ2+v+pbp?MDzighek`y|6R477bOQ7>DBX!Tm&ts z#$!#nr-Fr_l_fkp&-CqvX8}!x={{E)Vdz2*I(Hdkyg5BpJ=rS0&Z1fEs9^iv42ifa zz`r9&|L(?pIN{1)%8HkX5cOJSHnQEoMqM9}$2^{|RQ7aNNJpcs6EfVQob)UDw)FIq zW;BF}T!lbp`xzA$_fvk58PY6cT)}=G@P$7~8(_1b)wP%|VBBBrw$iMddeAsmMRj$) z_1fkNBq3ee_!CE?c)RTYjKPhKBV_uazo&JPKQ_@zqYfO5U_Lk|i&E^H86uiII1X

<+WUW;I18icTki18Eyo?U-PO?pR3*CVGLH*oAouU zkT*PxHws1u1$)7$qu}4bQNqf38@;CBaQGaZeOBH5Vd{KS+0g!9<+|ZTDL4F%L_-sD zGFJV(??AnXBi~iF$^zeKF-b39;ityc#zZeGs?Am&Nhm~_qqefrdo6PEqTzXtY;L6) z=)XR;?gvi9e&IK%S9;b1#nfdB)IWuER%_faJ@*?dmOkLoA*|ScsD|;y1_eeT%s~c5 zNSu}~DzQ+keb&=z@)auIga(wnDXl|i%wO;X<9kU!zSIO%=K*kj!#PLBak!Q9d(Qla zOV+B)vtvxOUg=wx$L(8#anb+uLG=ak%g^Wd?vRycB<%(en~uFi^ZCqKdFH(TT>HhT zI;V%ObtWZ@H_0(FhNEXttMq~RdA+l-^7Qz@^Ld~e#dzG{@{GXF{d*w6+bi~D7f8nd zlbAniVnR@6u+5Dct~G+DE0ISPEPQ7lndy`Iai0@bRzMWq^)~!Y1y-s{q=!CbdW+qk zAQnLDNULADjo`|Tq8m<@k5(3n6-MUadm4TDv(|2P@5y(fORs(VBd)IRcn9Z)m7t?~ z+d?f;9)yWOaY~YR&bGi{eCWdaf?!x>5}ApPu}-Jd|EnRve6J;wx28_+3|pgObFFB} zy4v41MARXC2v@IC{Do3*w$&eoYYe9l;l=$1$(2ev*8mH~-;_(67#%*OhWv&zi2e;1 zP0JFPhB@Jz$fn!u=#@Y35SY*@{N4O}^B9aZBJ)$L*T5qK3=yB|?K0YJH0PIEvK=DV z6-cgqhN1jiM1O*@jP$5_j~F6XeKB8;N1y4Vh>(nOn=@6U6@`TOCCm4wB2@!Hq{NrW>IRw5Z*_tx zvp1#f_1^6FmV&~|z0@Akqm5T|h2j6tU3FRtSjY$njM2)6vu?VVYPVD`mIO|QF+ z&F?2q`_j9ItQkVMCyaBYH|?5nf!Oz=E?%8N$)||7pa}8zMYObc&Z}MU znQrLh1&sW9)go_n@zz-zY0SrDSHYx7gQi9LDPGMKiX2&-kxZL)81;Rn7!CbXEXR=>^+k-f9j8>5+Ar-<`&XK zDQR19mw2JsmyrEWr#e|=00D!>0t^@V6A3fjWN0Y<ggK%nh6Cu%;>}^_->P*xM(Le2tnB7k6qrLT@6U9!Jxh z7bGn0Id}Ho5eDKZ&@}RyU+()Vq|7TB39~+#ZKbewzz;SbOEawYJ{T-XbQi#Ypw5px z-ms$o2YmB^dR_Fz3+Xyfv#F)MI=zh4k_F0DT%QZrj`&UF`tNw@KmW5@J^~TcE2eg( zs$47Q7_^9GZ=YssW+cIzQ-xPNWN#bFE30^=SdYIQF%8cS|v)%{Ro&5@C z%&UIGL2h5Y##LyiV_FUmQakt=u6pGtThAww^k9sc`3sd-g!m=BRt?yI)Q}Mi&qgGxRua2d6K%b&EKWkiyMDP^!BXxtwM2?8WDp z;9H%BHVk3zu}(BLMu6XS(asYA9$Rwgr&zSnym1e|KnY`Gr%g%tUcPvj^*P`|(Uxp~ zt_pdghg83d0;24f`05s2pVa!k%RA z5vSZ6qA`>lj{F<0*x3Gty3ZA^t}fY^?M!G9CNO^pync95 zty$kit^MHfoefb!x|lJ~C2-c%t+NnYVDR4Y6LtlzkZvJSXi%Gn!JYC1;>kM8^DJUa zS*hDU!t&8%lu-js%BFGk8EH?BF-=fs+!;-;x0$~`F=})yA&(@Hymdd zB4RIFIipv5^G9S}fBWKGgq!PDbc(~VL-+zviyab9&{zJaGIgh^^j2WPw+W$d?xlQn zPcP2$yGQ-Wy}3G>B*)`v4SJ<-k*l9=y!JoH4sO{uNN4*P=VpI9GgQH8=mf{cK^r=; z>vV*^Ky|Ud-WL?~nn#upON_n+m$;x$AXXPCd~fn%r2s(sWk!1Om%MOC9xd(~!cmG- zk-Ha?ka&WrY`soaZUs9HLaG#)g>+m#5_35kc-z5dPk~}2S5z&*{_s2lu?blF!NzpL zA+PNB zzt4Wo-5<{VbT3`cqMx4XUsYFk&s5J$*I0QcpiWK|3kKzA>l<(uw2k0J9U1Cxb}}8+ zXW_ey;t)$?_I?P29DV6`NWb)=SG}U?6;OM8H}V23b3VhplYzWs#NjiuuKNMzrt?6= zR7Deaau$*f~qj)>XX;R`6ve#)di zzF6gWN*XvgtJ0F6+Sszm$V=`VW43p3V|P{k)@Eh4!f*7P7{;JqMi|Vctuaw}hPGuME!@y|vmP$AH zG)uacIB9{NNGSOnwxq=*FQ)OJQ%3pg68EJ($4=v)Ck%QbhMosuiQt&xs)EOpb>;{2 z7vKc!X?vp;bptAkhXF?(mGWnu_RhSMwmV@jLdm{y&B$QN-qAf^_PNqF#dk>JI2@Fk zCAX~-FH!2sesam21w)&FYPD4&c*q4LK0tIApDnR8K_@Q0KPFl!MjS%!AvgWPbXpXRR!i8>o5oRcMj~X~ z36I%>Z)nSR1Cp8fX1+wddmzwQzSM-NlzX8dW0h0Xxc&zF7bv6IBsSYo-U_qq2*&5R z18MiG53i`PBRleqT;38Wbf)U%FJg92L!^J-}b`d4CfSIR3}hvna-PJ%vN6w=ULu3+b!0q zGl=XV>ePdn9%1c1#+xzx`1n2d1Z}`usEo?jsj;)MkeZ7G91Wv)4Ox84yiUb|!^986 zPv*M@cbRh`S-|>oL4L?rPT`>FkyEgs@cWF)l;|00=rd9#ZZgIud;;g_(68Ei29CPkSV|$-i6w1X}>= z%{A}gT!)EWnoB-C%-;~yX+Um(i2_ypyuqm9yNdrvNfq@l(4jT5uqyr>#$b(8y<*RI zx|5{DIN@1E#pqilm)Z$+)_Oc23%y)9h5Z;)@yVWyD`=7DjdZY>rMUBp2`^6`tGr1+ zY$Ns5H;BpG=h*V5ln^&)N^l8%n`x!tNO8@FR+bf?7t!X+4Ou7S5q{6mh$!8!KK811 ziTgz6IP!Yac8IFsP;15NAK8?TgPE&QEu zGc0}aNoiOJV(?z~@>){q>fK1oiAd{Cu_|qT}FE*Z=gWX%| zN2Lz(jDnOj@M@-?Ei>UVHqb^G5QW`+iFmbU$feMC0)2dwmu3b=!^XCzzLgQi(J9Y+ z?kFWku5(>-)JQ;$S86<%lL=FTDEAeSabzGV6;u(WMkIt7%SE9*lB zIm2de=y39Z+V9>Y%!s394XM}j__MVRf&!b}RvWrMR^ao`DKq~eO+?qS@ZOx*)vWjr zU-7S?CK<68zt~z5Ce_6duCXpZ3Lw>aC`o7f8p?{qqt4m_^D_I^sX}1qWy0v;&?pH#*1qFS)1a758kP;5WpL?M? zW{vCZAHM5Pe9ZhpJ5GJ4HKj2DX=ZL#T)TxH?VC5GhI2fK!KI1LRcT*GmCHQi?U_AT zwP?3tieF@DA?8r7s@!bAl0PG8H7_k3hnXpSrAyO!t~gwQ-UOx#Iwv*X>f8}6d8^|S z@rDY#ljwa`8NJF_045TzEw$2~tIZpMiCvL(;oeJT#D9EsMvV*`I%pvQSBeigHOn$- z--uv)WZ4Xd(yhp_#F2?k%lAaMcHhkZ1OZ)4n1A%+UE|rmjgbL0pHYuM=zCXWh_w49 zCS2FLgqvnhSAobe0v;w*Q|3CiUPe~6x^q2Y~U zf)S_BMfB?jH}#Qd2@`>eAA;%JeQ>b^mAouXcV}F)Mx`c36$@=Dq*1qJ7fE?qVU%qU zF-ke{{1Q=s>RA zuTZ?^@lj%GEIR0c50}8xtZO6WlFtF*E903228(&bFy)wU6uGd&UOGI#w64>v)$r*t zi?|rHvDq#hZmVjS6gWh>UaUWH@@Z$Lc5kS$di{!BG)9Z%Ta{u*Y8B#;^=HR~w65A= zuXw#izh<{(e~j7aCgzP*^UAj19~IT@r|;s-Qe)~v@r5HzLUJOZuRS6L;qryU@@~#0 zfi1o9t5c=q@iopN{XX%RJ&W6fcL+$cf?*cmV(4oY$PV2?)VaV76u2Daht~CDrg!}o zAzTL!wJB1hL)=7TxuLY;r=Q53I1|FdjNOEZC$0B>rQXI> z8o~WG0K>saM#i*Em2Z!Y&qt__16s6LYJ5$@R%413Osf&rp@oOzfvCOb3~c@z-7<<+ z%ko{^TU8LnxEWjsi zgTM#`^kRYbOBS(OeL>X?3@UH_PQnY(6v;HvR25Qa4U~?%SQ5; zqSp%Df6RwJCPjK@Pu<(@6M}54V)9lym0eqo)iFsqh-KY5=fCcBmcXdvRYF|rSHr5+@*sz2*$-zfeJV09;bJ@|pPz>YiqHNl)&?NWbuA1myRrXc6ndj&5ywarzhT`*nV5%4Uvqvbg% zBb~9lq*wirWao}0^QIKCh)EW5Tbu9}*PpX}Q(J#ExkwgYALdi|J`#~6Wn@^fTT5xp z*;u;9WM!FX?TZ5^jf8G-=;IxDkRH=r?g_y=UaZPH$U$hx8KP8C(2peL;!kM=F1%P# z6*^sI{O_s^(6VoJ;bfJz;M$Dq3ASYIGp*#lKO=+A0hcv$Z`*}-)MM=kZdw1?67!OX z5rvoMQ=wIL6Ygl$V`a`d-R$fte)|jLMd_FV2Elp8aKP;r2-$@cL(lW<$Ft=xdy)D- z(zcpKqX0W-_b*30-jaYizMvOYzORW4z#Nuj*C;CAP~ zo(E*&tV3UwN}CcvMD4zOhUGx$u*jisf2@E6Byd3i9w9fLl*MFq80XWUU|6NZ*YWnF z%gH0MN_g&uttcLBD$VTrfB}@GyW8+RQ0%K|@2(xT#uBW{W z8eu=$TkgGHO1a9V`LcRc8b5z({d@ItX;Y-+SdXlhsI;r%t9R$SG!OQJjB=5jkik@q zR`2=J|3Nd&IDyumx5;lju{}!ee}=xsQx2a}YI`4a{zV^~K$uai(6DWLB^vJe#j4ye zN!jxum4aI#Qei^AiHlTLVJ0jR>@AV-zLx#!w6+FVpB>SO1JoL_#XlEC!~xyJ=XUb% zs{K{sH{hGbXG#t9<%C#U7BfX-%ev!T5n)WC%o4`F2ddssc*@F}!t1+a? zDAQUpx$QMxyWH5ILk&lacn)^;{@N>fXch-IB}a~`&tdTwZN#$X;FUxhtbl;rA6l>2 zHEZ~41!9hh{eaK9Fg4sa9Z5YaM3J#o=Du24?i@9b1@8wh@XoOmVg+!YXjJrv&nCR~ zPk%oCV%**S-jii=&lC#&ZRqdLKfIh?S?Pwou`AV)N>ieklDON@c0L=(qI8D5XN3A{ z)*lp|Q1`MMXI>r#M8ozzaxlbglD9YkX4@-ZXL`;W6xcPMo6 zyxxs|m)@Alk52xPJNR48;4pzDU}*z!&+q&)$!uH(-DSCIR&v-*BT|?0!a?!%v|v7> zRtmM}C>iigFqO|ETCWdujxLw1>e9CsHpp4bPf0zGx|V5-wKQHX9~{=lo|SUpYp5^G z_*_5=^`*(Od}}B#g;G|quTr5EMhMVEN3k6{JdhPT&bwzQM)mfgE{}10$&hcgwzp} z`ndUA`Be~!*FTm$97c@i8y$8@4Di^Wiz-GfysWe#F|lipi4Ah1ciedX8f#;o?{ywB zS6Gvzh!RNcOHFXoRzyPThO!3BkR1f~&2zsmP5yVG-^~dDBcD?S=l^*8`g7LTvc2~0 zQu(pQRq?&re<&aZ>A$CjqH%k)i#%%`f}#R;P!DgItEC}T3=I3`O+}8tt)M5pEDt7u zP-b-qpux^Z=bWzfL2n7Xd(5w{8Ox>I3s7HvkxF<`i?z6ApodNOyv4!;nWy)gVaohP zdA=eOj#cW~ch(i5lnI+QkF^~>`!^zoCz1yeFU;=9E;qpwb_sOr`F#yDH;S&?f_>=v za6zixE>6Y#4N7*1*dSdW>c32=7*8wkqLoa!tOXB+`X{>$BR+CSr0xh3Cwfn|Lpm() z8oi~Zxw2Pxj;Dr;Vx+^x%kopdh5=R%?pv$m(NnUde4!$jAp6OSZibm^7S63QFMM2e z&z2)k#qJR3+n!81m{f<|5M94ETK_lE3c-9)Y}v;|FB%TGu1-Jk9RPPWeB|0Z&t{gW z(aRywtl$yTmQHR^YjHiU2I(nO#Kl9<4M79o9IP);q&6OiM~vSq#+s=frP{B5GEKFX zrvd3j71?j=a9GWJHY8`1d+<5k5{Gr{fv7X)UP?_3R}o&(*)VH*ABTulIHCrq-eOxZn?3a#V(qk3HIwH5i+*fzDAi02GOI^vDI#`Hf*9~^~NG`LCnVC;naw`3pZ`43rp-06<#wq zG&6$Eh`j!vj!mTlSFVdbX*J*O%M9dT_>pnHf)nXzL*?_0I$d|k>SqsNL@8uR8wyzP z?_fpUi>ox%2vdoebZ_rnEnoi_GY|nPrnq-AOWFO&_1EyI%+#e*`!Hvsap)~U;u~gh z$QkBQMzp_2y8!1$r0SKE^_;dv+Ugewem*W!1I5V~iBUqgefP#V?t*oS*(#zL=wOA| z2Wut4;F~_SK<)Q8PoAFC(Fcz4Gs>51YaU7;gfMJHzKSRVp|$LKxTIO(UJTZ}Be2ub zpGBaTeH87?v*Ys-W)_!Rz42-*Oeqd2<$E4X#dn=1;KoAo+;5GFeLH1!jmAagJx8E_ z&>+wCS`y3zsy5OjWrcB~m1jOA`p*mPvB*IZs!qyorKgUM`;^4`BGK4WR%>!jmO-pv zVz7e)@VQ_vl2~gsot%e0Um4I)y6p?)`x&eA`L>ijlo!KStgl@!w$lvyaDkMGYfA)A z@X}4jdx`Xl+&lW|9kx$B_mfn`2#sHy~>VC!}vw< z+wkDJy;ed!eb^VAUUVs1gb%lud*kVz6q1HaybY$CvUHezz+*`PuiMK=+o0{21E`Pe z68G}eGA8@|ftzt+_JUYy!&-i)^hN}8x3)qggFms;Ezg_tX)BuZK4;Q>T>j1+AI-xs zV(W~AxTbLaK{BA%4iJzfV6J0=#SA=Ug-fS_*%t>Ft$@(0LU-fcDDzK>8s?>4k!JaV zYtrOlYq&I=NLy5!nSoHPFB}=OJPt$&I@*P&c!aHetMcQN2a8N*sw}lQ8B-JGWT^k2 z3nH8%&Kqvlj1xHO{fc4-FwS6L%_|NSG7ym9$u!{!35&8*SP%b!nhecW9FKC`fuj2l zF=g&QQLER6y}@M){@;OjZA|cW;-R1rQ0>HrN-4}*eGaj~*;uN-7Y&;7Czkrt@e?c1Y0vn7QQ@e-teJZvs`db*( z$AG+_&T1=8*yWxOH5;y<3(B#(N#9z;pDW!~igqla(y=tQe?3>bGneG2pyw%(q|!=k zjr;b0g(7iQpt!@MymU0?T=SOjQ!*jPEN0n#0UH{G*(@^?kg0pR=RhEe47_&yu%poF6=wSS|b%REQ=1*{kg%(4)#$yQXK%~H$LTc{h0Pf-R6X>>6_ ztRKICb+WBA1oPD9FG#oHewAO6Ht9SO7%F7Kc#GU&>o;2vAXDl2VlqbeKFry;IKH=K zqt6oHZ9MI?YI^8ODaj-C;A5+A`U-!68oT2AlSbE)2Y7%D#TL#mh8sIO(s*e{8C{6T zv3;Kxyo8R~J6C^$QPUfb#<&3l(0{a0=c5u=2XQi}rk|Ff!|8>FOX@&A+Nkvt<56&aF(rL#MqBs zFn)&IoA()?Y$bkyWGiIeb0V9}pk#dpwt>u8+1eKoz-9E6cpBb3FDmy&d|%YzHnqFp zHJiT`bEf!ho~ad6#cH*csH=0>a*f*R$kxm(i&Xv_Lh8lw{g(?G_{Rx0&Y`%U%&$J# zJ9T`U#1LH&@jzI`T80z1?dZ^>_$d`C#Y0fDp+8)G+LbqWY4AAvRYV~%v3D(qA&FIy zcI#ogn24de4L#h)EA#dzVqvfdh{bX(!IFZ=>~5KLUUbuJbH6{~7w87uZ=@dVDL4y| z<(D;vw<8j5M4achjt|h3v~`S-{iz-SFppvQ?xp#lSk2~)&g@bi=BszAV%18-bcH(irR z67~~)-GG#8_*?6AW=A4Y+mFDqfj0gx6lY9W?I9Zj{<0%tr$A z=T7yAh+Rg?5gthpx5oYR9IJGyRpcdg;}$G$M)(ftM#aUBQCSFyZ@69XrSH}*vBy<# z^;M$7U{|Mm62S^zgQAqAJzS@ZwF7P<`$ST~^vnJYu|ah&dZf7^1^U3~q)}wD)w%BF z=}o0?>#bGj!c64hX>P217}ih)1ZwXyqi?=_o4y@9t3$#`W)v%0D2B_rc%BVB%}uds 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 literal 0 HcmV?d00001