From dbbb6c09f19c2d522930d77c0924a50e7ecd9675 Mon Sep 17 00:00:00 2001 From: Julien Neuhart Date: Sun, 22 Dec 2024 16:08:47 +0100 Subject: [PATCH] feat(split): add the split feature --- src/Modules/ChromiumPdf.php | 13 +++++++++++ src/Modules/LibreOffice.php | 13 +++++++++++ src/Modules/PdfEngines.php | 21 ++++++++++++++++++ src/SplitMode.php | 33 +++++++++++++++++++++++++++ tests/Modules/ChromiumPdfTest.php | 26 ++++++++++++++++++++++ tests/Modules/LibreOfficeTest.php | 14 ++++++++++++ tests/Modules/PdfEnginesTest.php | 37 +++++++++++++++++++++++++++++++ tests/SplitModeTest.php | 25 +++++++++++++++++++++ 8 files changed, 182 insertions(+) create mode 100644 src/SplitMode.php create mode 100644 tests/SplitModeTest.php diff --git a/src/Modules/ChromiumPdf.php b/src/Modules/ChromiumPdf.php index fed95ad..f48e4ee 100644 --- a/src/Modules/ChromiumPdf.php +++ b/src/Modules/ChromiumPdf.php @@ -5,6 +5,7 @@ namespace Gotenberg\Modules; use Gotenberg\Exceptions\NativeFunctionErrored; +use Gotenberg\SplitMode; use Gotenberg\Stream; use Psr\Http\Message\RequestInterface; @@ -153,6 +154,18 @@ public function footer(Stream $footer): self return $this; } + /** + * Splits the resulting PDF. + */ + public function split(SplitMode $mode): self + { + $this->formValue('splitMode', $mode->mode); + $this->formValue('splitSpan', $mode->span); + $this->formValue('splitUnify', $mode->unify ?: '0'); + + return $this; + } + /** * Sets the PDF/A format of the resulting PDF. */ diff --git a/src/Modules/LibreOffice.php b/src/Modules/LibreOffice.php index 58700df..2f808ac 100644 --- a/src/Modules/LibreOffice.php +++ b/src/Modules/LibreOffice.php @@ -8,6 +8,7 @@ use Gotenberg\HrtimeIndex; use Gotenberg\Index; use Gotenberg\MultipartFormDataModule; +use Gotenberg\SplitMode; use Gotenberg\Stream; use Psr\Http\Message\RequestInterface; @@ -324,6 +325,18 @@ public function merge(): self return $this; } + /** + * Splits the resulting PDFs. + */ + public function split(SplitMode $mode): self + { + $this->formValue('splitMode', $mode->mode); + $this->formValue('splitSpan', $mode->span); + $this->formValue('splitUnify', $mode->unify ?: '0'); + + return $this; + } + /** * Converts the given document(s) to PDF(s). Gotenberg will return either * a unique PDF if you request a merge or a ZIP archive with the PDFs. diff --git a/src/Modules/PdfEngines.php b/src/Modules/PdfEngines.php index 8b79814..c8e07b9 100644 --- a/src/Modules/PdfEngines.php +++ b/src/Modules/PdfEngines.php @@ -8,6 +8,7 @@ use Gotenberg\HrtimeIndex; use Gotenberg\Index; use Gotenberg\MultipartFormDataModule; +use Gotenberg\SplitMode; use Gotenberg\Stream; use Psr\Http\Message\RequestInterface; @@ -87,6 +88,26 @@ public function merge(Stream ...$pdfs): RequestInterface return $this->request(); } + /** + * Splits PDFs. + */ + public function split(SplitMode $mode, Stream ...$pdfs): RequestInterface + { + $this->formValue('splitMode', $mode->mode); + $this->formValue('splitSpan', $mode->span); + $this->formValue('splitUnify', $mode->unify ?: '0'); + + $index = $this->index ?? new HrtimeIndex(); + + foreach ($pdfs as $pdf) { + $this->formFile($index->create() . '_' . $pdf->getFilename(), $pdf->getStream()); + } + + $this->endpoint = '/forms/pdfengines/split'; + + return $this->request(); + } + /** * Converts PDF(s) to a specific PDF/A format. * Gotenberg will return the PDF or a ZIP archive with the PDFs. diff --git a/src/SplitMode.php b/src/SplitMode.php new file mode 100644 index 0000000..1b86637 --- /dev/null +++ b/src/SplitMode.php @@ -0,0 +1,33 @@ + 'Gotenberg' ], @@ -215,6 +220,7 @@ function ( bool $failOnResourceLoadingFailed = false, bool $failOnConsoleExceptions = false, bool|null $skipNetworkIdleEvent = null, + SplitMode|null $splitMode = null, string|null $pdfa = null, bool $pdfua = false, array $metadata = [], @@ -250,6 +256,7 @@ function ( $failOnResourceLoadingFailed, $failOnConsoleExceptions, $skipNetworkIdleEvent, + $splitMode, $pdfa, $pdfua, $metadata, @@ -293,6 +300,7 @@ function ( $failOnResourceLoadingFailed, $failOnConsoleExceptions, $skipNetworkIdleEvent, + $splitMode, $pdfa, $pdfua, $metadata, @@ -336,6 +344,7 @@ function ( true, true, true, + SplitMode::intervals(1), 'PDF/A-1a', true, [ 'Producer' => 'Gotenberg' ], @@ -386,6 +395,7 @@ function ( bool $failOnResourceLoadingFailed = false, bool $failOnConsoleExceptions = false, bool|null $skipNetworkIdleEvent = null, + SplitMode|null $splitMode = null, string|null $pdfa = null, bool $pdfua = false, array $metadata = [], @@ -421,6 +431,7 @@ function ( $failOnResourceLoadingFailed, $failOnConsoleExceptions, $skipNetworkIdleEvent, + $splitMode, $pdfa, $pdfua, $metadata, @@ -469,6 +480,7 @@ function ( $failOnResourceLoadingFailed, $failOnConsoleExceptions, $skipNetworkIdleEvent, + $splitMode, $pdfa, $pdfua, $metadata, @@ -521,6 +533,7 @@ function ( true, true, true, + SplitMode::intervals(1), 'PDF/A-1a', true, [ 'Producer' => 'Gotenberg' ], @@ -567,6 +580,7 @@ function hydrateChromiumPdfFormData( bool $failOnResourceLoadingFailed = false, bool $failOnConsoleExceptions = false, bool|null $skipNetworkIdleEvent = null, + SplitMode|null $splitMode = null, string|null $pdfa = null, bool $pdfua = false, array $metadata = [], @@ -668,6 +682,10 @@ function hydrateChromiumPdfFormData( $chromium->skipNetworkIdleEvent($skipNetworkIdleEvent); } + if ($splitMode !== null) { + $chromium->split($splitMode); + } + if ($pdfa !== null) { $chromium->pdfa($pdfa); } @@ -724,6 +742,7 @@ function expectChromiumPdfOptions( bool $failOnResourceLoadingFailed, bool $failOnConsoleExceptions, bool|null $skipNetworkIdleEvent, + SplitMode|null $splitMode, string|null $pdfa, bool $pdfua, array $metadata, @@ -808,6 +827,13 @@ function expectChromiumPdfOptions( expect($body)->unless($failOnResourceLoadingFailed === false, fn ($body) => $body->toContainFormValue('failOnResourceLoadingFailed', '1')); expect($body)->unless($failOnConsoleExceptions === false, fn ($body) => $body->toContainFormValue('failOnConsoleExceptions', '1')); expect($body)->unless($skipNetworkIdleEvent === null, fn ($body) => $body->toContainFormValue('skipNetworkIdleEvent', $skipNetworkIdleEvent === true ? '1' : '0')); + + if ($splitMode !== null) { + expect($body)->toContainFormValue('splitMode', $splitMode->mode); + expect($body)->toContainFormValue('splitSpan', $splitMode->span); + expect($body)->toContainFormValue('splitUnify', $splitMode->unify ? '1' : '0'); + } + expect($body)->unless($pdfa === null, fn ($body) => $body->toContainFormValue('pdfa', $pdfa)); expect($body)->unless($pdfua === false, fn ($body) => $body->toContainFormValue('pdfua', '1')); diff --git a/tests/Modules/LibreOfficeTest.php b/tests/Modules/LibreOfficeTest.php index 471612b..f24a767 100644 --- a/tests/Modules/LibreOfficeTest.php +++ b/tests/Modules/LibreOfficeTest.php @@ -4,6 +4,7 @@ use Gotenberg\Exceptions\NativeFunctionErrored; use Gotenberg\Gotenberg; +use Gotenberg\SplitMode; use Gotenberg\Stream; use Gotenberg\Test\DummyIndex; @@ -37,6 +38,7 @@ function ( int|null $quality = null, bool $reduceImageResolution = false, int|null $maxImageResolution = null, + SplitMode|null $splitMode = null, string|null $pdfa = null, bool $pdfua = false, array $metadata = [], @@ -136,6 +138,10 @@ function ( $libreOffice->pdfa($pdfa); } + if ($splitMode !== null) { + $libreOffice->split($splitMode); + } + if ($pdfua) { $libreOffice->pdfua(); } @@ -176,6 +182,13 @@ function ( expect($body)->unless($quality === null, fn ($body) => $body->toContainFormValue('quality', $quality)); expect($body)->unless($reduceImageResolution === false, fn ($body) => $body->toContainFormValue('reduceImageResolution', '1')); expect($body)->unless($maxImageResolution === null, fn ($body) => $body->toContainFormValue('maxImageResolution', $maxImageResolution)); + + if ($splitMode !== null) { + expect($body)->toContainFormValue('splitMode', $splitMode->mode); + expect($body)->toContainFormValue('splitSpan', $splitMode->span); + expect($body)->toContainFormValue('splitUnify', $splitMode->unify ? '1' : '0'); + } + expect($body)->unless($pdfa === null, fn ($body) => $body->toContainFormValue('pdfa', $pdfa)); expect($body)->unless($pdfua === false, fn ($body) => $body->toContainFormValue('pdfua', '1')); expect($body)->unless($merge === false, fn ($body) => $body->toContainFormValue('merge', '1')); @@ -229,6 +242,7 @@ function ( 100, true, 150, + SplitMode::intervals(1), 'PDF/A-1a', true, [ 'Producer' => 'Gotenberg' ], diff --git a/tests/Modules/PdfEnginesTest.php b/tests/Modules/PdfEnginesTest.php index 3b27079..5f137c3 100644 --- a/tests/Modules/PdfEnginesTest.php +++ b/tests/Modules/PdfEnginesTest.php @@ -4,6 +4,7 @@ use Gotenberg\Exceptions\NativeFunctionErrored; use Gotenberg\Gotenberg; +use Gotenberg\SplitMode; use Gotenberg\Stream; use Gotenberg\Test\DummyIndex; @@ -68,6 +69,42 @@ function (array $pdfs, string|null $pdfa = null, bool $pdfua = false, array $met ], ]); +it( + 'creates a valid request for the "/forms/pdfengines/split" endpoint', + /** @param Stream[] $pdfs */ + function (array $pdfs, SplitMode $mode): void { + $pdfEngines = Gotenberg::pdfEngines('')->index(new DummyIndex()); + + $request = $pdfEngines->split($mode, ...$pdfs); + $body = sanitize($request->getBody()->getContents()); + + expect($request->getUri()->getPath())->toBe('/forms/pdfengines/split'); + expect($body)->toContainFormValue('splitMode', $mode->mode); + expect($body)->toContainFormValue('splitSpan', $mode->span); + expect($body)->toContainFormValue('splitUnify', $mode->unify ? '1' : '0'); + + foreach ($pdfs as $pdf) { + $pdf->getStream()->rewind(); + expect($body)->toContainFormFile('foo_' . $pdf->getFilename(), $pdf->getStream()->getContents(), 'application/pdf'); + } + }, +)->with([ + [ + [ + Stream::string('my.pdf', 'PDF content'), + ], + SplitMode::intervals(1), + ], + [ + [ + Stream::string('my.pdf', 'PDF content'), + Stream::string('my_second.pdf', 'Second PDF content'), + Stream::string('my_third.pdf', 'Third PDF content'), + ], + SplitMode::pages('1-2', true), + ], +]); + it( 'creates a valid request for the "/forms/pdfengines/convert" endpoint', function (string $pdfa, Stream ...$pdfs): void { diff --git a/tests/SplitModeTest.php b/tests/SplitModeTest.php new file mode 100644 index 0000000..e13b687 --- /dev/null +++ b/tests/SplitModeTest.php @@ -0,0 +1,25 @@ +mode)->toBe('intervals'); + expect($mode->span)->toBe('1'); + expect($mode->unify)->toBeFalse(); + }, +); + +it( + 'creates a pages split mode', + function (): void { + $mode = SplitMode::pages('1-2', true); + expect($mode->mode)->toBe('pages'); + expect($mode->span)->toBe('1-2'); + expect($mode->unify)->toBeTrue(); + }, +);