diff --git a/docs/configuration.md b/docs/configuration.md index 3f7cbf2a..69fd87fc 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -312,6 +312,9 @@ Enabled byd efault but can be disabled via the `sensiolabs_gotenberg.controller_ ## download from +> [!WARNING] +> URL of the file. It MUST return a `Content-Disposition` header with a filename parameter. + To download files resource from URLs. ``` yaml diff --git a/docs/pdf/builders_api/HtmlPdfBuilder.md b/docs/pdf/builders_api/HtmlPdfBuilder.md index 4dc69023..f1b399b2 100644 --- a/docs/pdf/builders_api/HtmlPdfBuilder.md +++ b/docs/pdf/builders_api/HtmlPdfBuilder.md @@ -128,13 +128,13 @@ Resets the metadata. The metadata to write. * `downloadFrom(array $downloadFrom)`: -Sets download from to download each entry (file) in parallel (default None). -(URLs MUST return a Content-Disposition header with a filename parameter.). * `fileName(string $fileName, string $headerDisposition)`: * `processor(Sensiolabs\GotenbergBundle\Processor\ProcessorInterface $processor)`: +* `withDownloadFrom(array $formFields, array $downloadFrom)`: + * `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 index adab5a3f..eeee4b63 100644 --- a/docs/pdf/builders_api/LibreOfficePdfBuilder.md +++ b/docs/pdf/builders_api/LibreOfficePdfBuilder.md @@ -86,10 +86,10 @@ Specify if the resolution of each image is reduced to the resolution specified b 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. * `downloadFrom(array $downloadFrom)`: -Sets download from to download each entry (file) in parallel (default None). -(URLs MUST return a Content-Disposition header with a filename parameter.). * `fileName(string $fileName, string $headerDisposition)`: * `processor(Sensiolabs\GotenbergBundle\Processor\ProcessorInterface $processor)`: +* `withDownloadFrom(array $formFields, array $downloadFrom)`: + diff --git a/docs/pdf/builders_api/MarkdownPdfBuilder.md b/docs/pdf/builders_api/MarkdownPdfBuilder.md index 406f5e28..9dd36ef1 100644 --- a/docs/pdf/builders_api/MarkdownPdfBuilder.md +++ b/docs/pdf/builders_api/MarkdownPdfBuilder.md @@ -131,13 +131,13 @@ Resets the metadata. The metadata to write. * `downloadFrom(array $downloadFrom)`: -Sets download from to download each entry (file) in parallel (default None). -(URLs MUST return a Content-Disposition header with a filename parameter.). * `fileName(string $fileName, string $headerDisposition)`: * `processor(Sensiolabs\GotenbergBundle\Processor\ProcessorInterface $processor)`: +* `withDownloadFrom(array $formFields, array $downloadFrom)`: + * `addCookies(array $cookies)`: Add cookies to store in the Chromium cookie jar. diff --git a/docs/pdf/builders_api/UrlPdfBuilder.md b/docs/pdf/builders_api/UrlPdfBuilder.md index 528dc172..555583c1 100644 --- a/docs/pdf/builders_api/UrlPdfBuilder.md +++ b/docs/pdf/builders_api/UrlPdfBuilder.md @@ -130,13 +130,13 @@ Resets the metadata. The metadata to write. * `downloadFrom(array $downloadFrom)`: -Sets download from to download each entry (file) in parallel (default None). -(URLs MUST return a Content-Disposition header with a filename parameter.). * `fileName(string $fileName, string $headerDisposition)`: * `processor(Sensiolabs\GotenbergBundle\Processor\ProcessorInterface $processor)`: +* `withDownloadFrom(array $formFields, array $downloadFrom)`: + * `addCookies(array $cookies)`: Add cookies to store in the Chromium cookie jar. diff --git a/docs/pdf/customization.md b/docs/pdf/customization.md index fc86dd65..94eb193a 100644 --- a/docs/pdf/customization.md +++ b/docs/pdf/customization.md @@ -529,6 +529,9 @@ class YourController ### download from +> [!WARNING] +> URL of the file. It MUST return a `Content-Disposition` header with a filename parameter. + To download files resource from URLs. ```php diff --git a/docs/pdf/office-builder.md b/docs/pdf/office-builder.md index 4e098bf3..0b8fe11c 100644 --- a/docs/pdf/office-builder.md +++ b/docs/pdf/office-builder.md @@ -773,6 +773,9 @@ class YourController ### download from +> [!WARNING] +> URL of the file. It MUST return a `Content-Disposition` header with a filename parameter. + To download files resource from URLs. ```php diff --git a/docs/screenshot/builders_api/HtmlScreenshotBuilder.md b/docs/screenshot/builders_api/HtmlScreenshotBuilder.md index 551adff1..35c73f68 100644 --- a/docs/screenshot/builders_api/HtmlScreenshotBuilder.md +++ b/docs/screenshot/builders_api/HtmlScreenshotBuilder.md @@ -73,13 +73,13 @@ Adds additional files, like images, fonts, stylesheets, and so on (overrides any Adds a file, like an image, font, stylesheet, and so on. * `downloadFrom(array $downloadFrom)`: -Sets download from to download each entry (file) in parallel (default None). -(URLs MUST return a Content-Disposition header with a filename parameter.). * `fileName(string $fileName, string $headerDisposition)`: * `processor(Sensiolabs\GotenbergBundle\Processor\ProcessorInterface $processor)`: +* `withDownloadFrom(array $formFields, array $downloadFrom)`: + * `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 index ccd2872a..1dec2ca6 100644 --- a/docs/screenshot/builders_api/MarkdownScreenshotBuilder.md +++ b/docs/screenshot/builders_api/MarkdownScreenshotBuilder.md @@ -76,13 +76,13 @@ Adds additional files, like images, fonts, stylesheets, and so on (overrides any Adds a file, like an image, font, stylesheet, and so on. * `downloadFrom(array $downloadFrom)`: -Sets download from to download each entry (file) in parallel (default None). -(URLs MUST return a Content-Disposition header with a filename parameter.). * `fileName(string $fileName, string $headerDisposition)`: * `processor(Sensiolabs\GotenbergBundle\Processor\ProcessorInterface $processor)`: +* `withDownloadFrom(array $formFields, array $downloadFrom)`: + * `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 index 8fbd868e..5ac3c857 100644 --- a/docs/screenshot/builders_api/UrlScreenshotBuilder.md +++ b/docs/screenshot/builders_api/UrlScreenshotBuilder.md @@ -75,13 +75,13 @@ Adds additional files, like images, fonts, stylesheets, and so on (overrides any Adds a file, like an image, font, stylesheet, and so on. * `downloadFrom(array $downloadFrom)`: -Sets download from to download each entry (file) in parallel (default None). -(URLs MUST return a Content-Disposition header with a filename parameter.). * `fileName(string $fileName, string $headerDisposition)`: * `processor(Sensiolabs\GotenbergBundle\Processor\ProcessorInterface $processor)`: +* `withDownloadFrom(array $formFields, array $downloadFrom)`: + * `addCookies(array $cookies)`: Add cookies to store in the Chromium cookie jar. diff --git a/docs/screenshot/customization.md b/docs/screenshot/customization.md index 775bdcc7..f4610162 100644 --- a/docs/screenshot/customization.md +++ b/docs/screenshot/customization.md @@ -189,6 +189,9 @@ class YourController ### download from +> [!WARNING] +> URL of the file. It MUST return a `Content-Disposition` header with a filename parameter. + To download files resource from URLs. ```php diff --git a/src/Builder/DownloadFromTrait.php b/src/Builder/DownloadFromTrait.php new file mode 100644 index 00000000..e1925881 --- /dev/null +++ b/src/Builder/DownloadFromTrait.php @@ -0,0 +1,53 @@ +}> $downloadFrom + */ + abstract public function downloadFrom(array $downloadFrom): static; + + /** + * @param array{downloadFrom?: array}>} $formFields + * @param list}> $downloadFrom + */ + public function withDownloadFrom(array &$formFields, array $downloadFrom): static + { + if ([] === $downloadFrom) { + unset($formFields['downloadFrom']); + + return $this; + } + + $formFields['downloadFrom'] = []; + + foreach ($downloadFrom as $file) { + if (!\array_key_exists('url', $file)) { + throw new MissingRequiredFieldException('Missing field "url"'); + } + + $formFields['downloadFrom'][$file['url']] = $file; + } + + return $this; + } + + private function downloadFromNormalizer(array $value, callable $encoder): array + { + $downloadsFrom = array_values($value); + $data = []; + + array_push($data, ...$downloadsFrom); + + return $encoder('downloadFrom', $data); + } +} diff --git a/src/Builder/Pdf/AbstractChromiumPdfBuilder.php b/src/Builder/Pdf/AbstractChromiumPdfBuilder.php index 3626253a..d5f2cd34 100644 --- a/src/Builder/Pdf/AbstractChromiumPdfBuilder.php +++ b/src/Builder/Pdf/AbstractChromiumPdfBuilder.php @@ -522,31 +522,6 @@ public function addMetadata(string $key, string $value): static return $this; } - /** - * Sets download from to download each entry (file) in parallel (default None). - * (URLs MUST return a Content-Disposition header with a filename parameter.). - * - * @see https://gotenberg.dev/docs/routes#download-from - * - * @param list}> $downloadFrom - */ - public function downloadFrom(array $downloadFrom): static - { - if ([] === $downloadFrom) { - unset($this->formFields['downloadFrom']); - - return $this; - } - - $this->formFields['downloadFrom'] = []; - - foreach ($downloadFrom as $file) { - $this->formFields['downloadFrom'][] = $file; - } - - return $this; - } - protected function withPdfPartFile(Part $pdfPart, string $path): static { $dataPart = new DataPart( diff --git a/src/Builder/Pdf/AbstractPdfBuilder.php b/src/Builder/Pdf/AbstractPdfBuilder.php index b7931801..658cab32 100644 --- a/src/Builder/Pdf/AbstractPdfBuilder.php +++ b/src/Builder/Pdf/AbstractPdfBuilder.php @@ -3,12 +3,14 @@ namespace Sensiolabs\GotenbergBundle\Builder\Pdf; use Sensiolabs\GotenbergBundle\Builder\DefaultBuilderTrait; +use Sensiolabs\GotenbergBundle\Builder\DownloadFromTrait; use Sensiolabs\GotenbergBundle\Client\GotenbergClientInterface; use Sensiolabs\GotenbergBundle\Formatter\AssetBaseDirFormatter; abstract class AbstractPdfBuilder implements PdfBuilderInterface { use DefaultBuilderTrait; + use DownloadFromTrait; public function __construct( GotenbergClientInterface $gotenbergClient, @@ -21,9 +23,15 @@ public function __construct( 'metadata' => function (mixed $value): array { return $this->encodeData('metadata', $value); }, - 'downloadFrom' => function (mixed $value): array { - return $this->encodeData('downloadFrom', $value); - }, + 'downloadFrom' => fn (array $value): array => $this->downloadFromNormalizer($value, $this->encodeData(...)), ]; } + + /** + * @param list}> $downloadFrom + */ + public function downloadFrom(array $downloadFrom): static + { + return $this->withDownloadFrom($this->formFields, $downloadFrom); + } } diff --git a/src/Builder/Pdf/ConvertPdfBuilder.php b/src/Builder/Pdf/ConvertPdfBuilder.php index 715ce4bd..33916fa1 100644 --- a/src/Builder/Pdf/ConvertPdfBuilder.php +++ b/src/Builder/Pdf/ConvertPdfBuilder.php @@ -74,31 +74,6 @@ public function getMultipartFormData(): array return parent::getMultipartFormData(); } - /** - * Sets download from to download each entry (file) in parallel (default None). - * (URLs MUST return a Content-Disposition header with a filename parameter.). - * - * @see https://gotenberg.dev/docs/routes#download-from - * - * @param list}> $downloadFrom - */ - public function downloadFrom(array $downloadFrom): static - { - if ([] === $downloadFrom) { - unset($this->formFields['downloadFrom']); - - return $this; - } - - $this->formFields['downloadFrom'] = []; - - foreach ($downloadFrom as $file) { - $this->formFields['downloadFrom'][] = $file; - } - - return $this; - } - protected function getEndpoint(): string { return self::ENDPOINT; diff --git a/src/Builder/Pdf/LibreOfficePdfBuilder.php b/src/Builder/Pdf/LibreOfficePdfBuilder.php index 0f76c4ea..38272193 100644 --- a/src/Builder/Pdf/LibreOfficePdfBuilder.php +++ b/src/Builder/Pdf/LibreOfficePdfBuilder.php @@ -43,7 +43,7 @@ public function setConfigurations(array $configurations): static /** * Set the password for opening the source file. */ - public function password(string $password): self + public function password(#[\SensitiveParameter] string $password): self { $this->formFields['password'] = $password; @@ -347,31 +347,6 @@ public function getMultipartFormData(): array return parent::getMultipartFormData(); } - /** - * Sets download from to download each entry (file) in parallel (default None). - * (URLs MUST return a Content-Disposition header with a filename parameter.). - * - * @see https://gotenberg.dev/docs/routes#download-from - * - * @param list}> $downloadFrom - */ - public function downloadFrom(array $downloadFrom): self - { - if ([] === $downloadFrom) { - unset($this->formFields['downloadFrom']); - - return $this; - } - - $this->formFields['downloadFrom'] = []; - - foreach ($downloadFrom as $file) { - $this->formFields['downloadFrom'][] = $file; - } - - return $this; - } - protected function getEndpoint(): string { return self::ENDPOINT; diff --git a/src/Builder/Pdf/MergePdfBuilder.php b/src/Builder/Pdf/MergePdfBuilder.php index fd6f5313..6ff9b8b5 100644 --- a/src/Builder/Pdf/MergePdfBuilder.php +++ b/src/Builder/Pdf/MergePdfBuilder.php @@ -96,31 +96,6 @@ public function getMultipartFormData(): array return parent::getMultipartFormData(); } - /** - * Sets download from to download each entry (file) in parallel (default None). - * (URLs MUST return a Content-Disposition header with a filename parameter.). - * - * @see https://gotenberg.dev/docs/routes#download-from - * - * @param list}> $downloadFrom - */ - public function downloadFrom(array $downloadFrom): static - { - if ([] === $downloadFrom) { - unset($this->formFields['downloadFrom']); - - return $this; - } - - $this->formFields['downloadFrom'] = []; - - foreach ($downloadFrom as $file) { - $this->formFields['downloadFrom'][] = $file; - } - - return $this; - } - protected function getEndpoint(): string { return self::ENDPOINT; diff --git a/src/Builder/Screenshot/AbstractChromiumScreenshotBuilder.php b/src/Builder/Screenshot/AbstractChromiumScreenshotBuilder.php index 3e39bcde..b41ba859 100644 --- a/src/Builder/Screenshot/AbstractChromiumScreenshotBuilder.php +++ b/src/Builder/Screenshot/AbstractChromiumScreenshotBuilder.php @@ -329,31 +329,6 @@ public function addAsset(string $path): static return $this; } - /** - * Sets download from to download each entry (file) in parallel (default None). - * (URLs MUST return a Content-Disposition header with a filename parameter.). - * - * @see https://gotenberg.dev/docs/routes#download-from - * - * @param list}> $downloadFrom - */ - public function downloadFrom(array $downloadFrom): static - { - if ([] === $downloadFrom) { - unset($this->formFields['downloadFrom']); - - return $this; - } - - $this->formFields['downloadFrom'] = []; - - foreach ($downloadFrom as $file) { - $this->formFields['downloadFrom'][] = $file; - } - - return $this; - } - protected function withScreenshotPartFile(Part $screenshotPart, string $path): static { $dataPart = new DataPart( diff --git a/src/Builder/Screenshot/AbstractScreenshotBuilder.php b/src/Builder/Screenshot/AbstractScreenshotBuilder.php index 6f8e9efe..322719f0 100644 --- a/src/Builder/Screenshot/AbstractScreenshotBuilder.php +++ b/src/Builder/Screenshot/AbstractScreenshotBuilder.php @@ -3,6 +3,7 @@ namespace Sensiolabs\GotenbergBundle\Builder\Screenshot; use Sensiolabs\GotenbergBundle\Builder\DefaultBuilderTrait; +use Sensiolabs\GotenbergBundle\Builder\DownloadFromTrait; use Sensiolabs\GotenbergBundle\Client\GotenbergClientInterface; use Sensiolabs\GotenbergBundle\Enumeration\Part; use Sensiolabs\GotenbergBundle\Formatter\AssetBaseDirFormatter; @@ -11,6 +12,7 @@ abstract class AbstractScreenshotBuilder implements ScreenshotBuilderInterface { use DefaultBuilderTrait; + use DownloadFromTrait; public function __construct( GotenbergClientInterface $gotenbergClient, @@ -20,24 +22,15 @@ public function __construct( $this->asset = $asset; $this->normalizers = [ - 'extraHttpHeaders' => function (mixed $value): array { - return $this->encodeData('extraHttpHeaders', $value); - }, - 'assets' => static function (array $value): array { - return ['files' => $value]; - }, - Part::Body->value => static function (DataPart $value): array { - return ['files' => $value]; - }, - 'failOnHttpStatusCodes' => function (mixed $value): array { - return $this->encodeData('failOnHttpStatusCodes', $value); - }, - 'cookies' => function (mixed $value): array { - return $this->encodeData('cookies', array_values($value)); - }, - 'downloadFrom' => function (mixed $value): array { - return $this->encodeData('downloadFrom', $value); - }, + 'downloadFrom' => fn (array $value): array => $this->downloadFromNormalizer($value, $this->encodeData(...)), ]; } + + /** + * @param list}> $downloadFrom + */ + public function downloadFrom(array $downloadFrom): static + { + return $this->withDownloadFrom($this->formFields, $downloadFrom); + } } diff --git a/src/DependencyInjection/Configuration.php b/src/DependencyInjection/Configuration.php index 59dce55f..32c5c3a9 100644 --- a/src/DependencyInjection/Configuration.php +++ b/src/DependencyInjection/Configuration.php @@ -259,7 +259,7 @@ private function addChromiumPdfOptionsNode(ArrayNodeDefinition $parent): void ->info('The JavaScript expression to wait before converting an HTML document into PDF until it returns true - default None. https://gotenberg.dev/docs/routes#wait-before-rendering') ->defaultNull() ->validate() - ->ifTrue(static function ($option) { + ->ifTrue(static function ($option): bool { return !\is_string($option); }) ->thenInvalid('Invalid value %s') @@ -299,7 +299,7 @@ private function addChromiumPdfOptionsNode(ArrayNodeDefinition $parent): void ->info('Override the default User-Agent HTTP header. - default None. https://gotenberg.dev/docs/routes#custom-http-headers-chromium') ->defaultNull() ->validate() - ->ifTrue(static function ($option) { + ->ifTrue(static function ($option): bool { return !\is_string($option); }) ->thenInvalid('Invalid value %s') @@ -324,7 +324,7 @@ private function addChromiumPdfOptionsNode(ArrayNodeDefinition $parent): void ->append($this->addDownloadFrom()) ->end() ->validate() - ->ifTrue(function ($v) { + ->ifTrue(function ($v): bool { return isset($v['paper_standard_size']) && (isset($v['paper_height']) || isset($v['paper_width'])); }) ->thenInvalid('You cannot use "paper_standard_size" when "paper_height", "paper_width" or both are set".') @@ -383,7 +383,7 @@ private function addChromiumScreenshotOptionsNode(ArrayNodeDefinition $parent): ->info('The JavaScript expression to wait before converting an HTML document into PDF until it returns true - default None. https://gotenberg.dev/docs/routes#wait-before-rendering') ->defaultNull() ->validate() - ->ifTrue(static function ($option) { + ->ifTrue(static function ($option): bool { return !\is_string($option); }) ->thenInvalid('Invalid value %s') @@ -423,7 +423,7 @@ private function addChromiumScreenshotOptionsNode(ArrayNodeDefinition $parent): ->info('Override the default User-Agent HTTP header. - default None. https://gotenberg.dev/docs/routes#custom-http-headers-chromium') ->defaultNull() ->validate() - ->ifTrue(static function ($option) { + ->ifTrue(static function ($option): bool { return !\is_string($option); }) ->thenInvalid('Invalid value %s') @@ -647,7 +647,7 @@ private function addDownloadFrom(): NodeDefinition ->children() ->scalarNode('name') ->validate() - ->ifTrue(static function ($option) { + ->ifTrue(static function ($option): bool { return !\is_string($option); }) ->thenInvalid('Invalid header name %s') @@ -655,7 +655,7 @@ private function addDownloadFrom(): NodeDefinition ->end() ->scalarNode('value') ->validate() - ->ifTrue(static function ($option) { + ->ifTrue(static function ($option): bool { return !\is_string($option); }) ->thenInvalid('Invalid header value %s') @@ -681,7 +681,7 @@ private function addExtraHttpHeaders(): NodeDefinition ->children() ->scalarNode('name') ->validate() - ->ifTrue(static function ($option) { + ->ifTrue(static function ($option): bool { return !\is_string($option); }) ->thenInvalid('Invalid header name %s') @@ -689,7 +689,7 @@ private function addExtraHttpHeaders(): NodeDefinition ->end() ->scalarNode('value') ->validate() - ->ifTrue(static function ($option) { + ->ifTrue(static function ($option): bool { return !\is_string($option); }) ->thenInvalid('Invalid header value %s')