-
Notifications
You must be signed in to change notification settings - Fork 11
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Doc/processor #141
base: main
Are you sure you want to change the base?
Doc/processor #141
Changes from 9 commits
29ed939
610aa18
9ff44e1
ac079d2
e4e7845
63c2ce5
5e74cfe
03d6372
d225842
caf2681
91bcfec
b45d810
ce37c5c
8221a36
19ca331
e410a17
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -33,12 +33,16 @@ | |
"symfony/mime": "^6.4 || ^7.0" | ||
}, | ||
"require-dev": { | ||
"ext-mbstring": "*", | ||
"async-aws/s3": "^2.6", | ||
"friendsofphp/php-cs-fixer": "^3.41", | ||
"league/flysystem": "^3.29", | ||
"league/flysystem-bundle": "^3.3", | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. might be worth to lower the requirement |
||
"phpstan/extension-installer": "^1.3", | ||
"phpstan/phpstan": "^1.10", | ||
"phpstan/phpstan-symfony": "^1.3", | ||
"phpunit/phpunit": "^10.4", | ||
"shipmonk/composer-dependency-analyser": "^1.7", | ||
"shipmonk/composer-dependency-analyser": "^1.8", | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. needed to ignore |
||
"symfony/framework-bundle": "^6.4 || ^7.0", | ||
"symfony/http-client": "^6.4 || ^7.0", | ||
"symfony/monolog-bundle": "^3.10", | ||
|
@@ -56,7 +60,9 @@ | |
}, | ||
"suggest": { | ||
"symfony/monolog-bundle": "Enables logging througout the generating process.", | ||
"symfony/twig-bundle": "Allows you to use Twig to render templates into PDF", | ||
"monolog/monolog": "Enables logging througout the generating process." | ||
"symfony/twig-bundle": "Allows you to use Twig to render templates into PDF.", | ||
"monolog/monolog": "Enables logging througout the generating process.", | ||
"async-aws/s3": "Upload any file to aws s3 compatible endpoints supporting multi part upload without memory overhead.", | ||
"league/flysystem-bundle": "Upload any file using this filesystem abstraction package." | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,155 @@ | ||
# Processing | ||
|
||
Let's say you want to save the PDF or Screenshot as a file, you will need to use a `Sensiolabs\GotenbergBundle\Processor\ProcessorInterface`. | ||
To avoid loading the whole file content in memory you can stream it to the browser. | ||
|
||
You can also hook on the stream and save the file chunk by chunk. To do so we leverage the [`->stream`](https://symfony.com/doc/current/http_client.html#streaming-responses) method from the HttpClientInterface and use a powerful feature from PHP Generators : [`->send`](https://www.php.net/manual/en/generator.send.php). | ||
|
||
## Native Processors | ||
|
||
Given an exemple for a PDF (works the same for Screenshots): | ||
|
||
```php | ||
/** @var GotenbergPdfInterface $gotenbergPdf */ | ||
use Sensiolabs\GotenbergBundle\Builder\GotenbergFileResult;$gotenbergPdf = /* ... */; | ||
|
||
/** @var GotenbergFileResult $gotenbergFileResult */ | ||
$gotenbergFileResult = $gotenbergPdf->html() | ||
// ... | ||
->fileName('my_pdf') | ||
->processor(/* ... */) | ||
->generate() | ||
; | ||
|
||
// Either process it with | ||
$result = $gotenbergFileResult->process(); // `$result` depends on the Processor used. See below. | ||
// or to send a response to the browser : | ||
$result = $gotenbergFileResult->stream(); // `$result` is a `Symfony\Component\HttpFoundation\StreamedResponse` | ||
``` | ||
|
||
Here is the list of existing Processors : | ||
|
||
### `Sensiolabs\GotenbergBundle\Processor\FileProcessor` | ||
|
||
Useful if you want to store the file in the local filesystem. | ||
<details> | ||
<summary>Example in a controller</summary> | ||
|
||
```php | ||
use Sensiolabs\GotenbergBundle\GotenbergPdfInterface; | ||
use Sensiolabs\GotenbergBundle\Processor\FileProcessor; | ||
use Symfony\Component\DependencyInjection\Attribute\Autowire; | ||
use Symfony\Component\Filesystem\Filesystem; | ||
use Symfony\Component\HttpFoundation\Response; | ||
|
||
#[Route(path: '/my-pdf', name: 'my_pdf')] | ||
public function pdf( | ||
GotenbergPdfInterface $gotenbergPdf, | ||
Filesystem $filesystem, | ||
|
||
#[Autowire('%kernel.project_dir%/var/pdf')] | ||
string $pdfStorage, | ||
): Response { | ||
return $gotenbergPdf->html() | ||
// ... | ||
->fileName('my_pdf') | ||
->processor(new FileProcessor( | ||
$filesystem, | ||
$pdfStorage, | ||
)) | ||
->generate() | ||
->stream() | ||
; | ||
} | ||
``` | ||
|
||
This will save the file under `%kernel.project_dir%/var/pdf/my_pdf.pdf` once the file has been fully streamed to the browser. | ||
|
||
</details> | ||
|
||
|
||
|
||
<details> | ||
<summary>If you are not streaming to a browser, you can still process the file using the `process` method instead of `stream`</summary> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Back quotes seem to be broken in the preview. |
||
|
||
```php | ||
use Sensiolabs\GotenbergBundle\GotenbergPdfInterface; | ||
use Sensiolabs\GotenbergBundle\Processor\FileProcessor; | ||
use Symfony\Component\Filesystem\Filesystem; | ||
|
||
class SomeService | ||
{ | ||
public function __construct( | ||
private readonly GotenbergPdfInterface $gotenbergPdf, | ||
|
||
#[Autowire('%kernel.project_dir%/var/pdf')] | ||
private readonly string $kernelProjectDir, | ||
Neirda24 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
) {} | ||
|
||
public function pdf(): \SplFileInfo | ||
{ | ||
return $this->gotenbergPdf->html() | ||
// | ||
->fileName('my_pdf') | ||
->processor(new FileProcessor( | ||
new Filesystem(), | ||
"{$this->kernelProjectDir}/var/pdf", | ||
Neirda24 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
)) | ||
->generate() | ||
->process() | ||
; | ||
} | ||
} | ||
``` | ||
|
||
This will return a `SplFileInfo` of the generated file stored at `%kernel.project_dir%/var/pdf/my_pdf.pdf`. | ||
|
||
</details> | ||
|
||
## `Sensiolabs\GotenbergBundle\Processor\NullProcessor` | ||
Neirda24 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
Empty processor. Does nothing. Returns `null`. | ||
|
||
## `Sensiolabs\GotenbergBundle\Processor\TempfileProcessor` | ||
Neirda24 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
Creates a temporary file and dump all chunks into it. Return a `ressource` of said `tmpfile()`. | ||
TODO : warning about tmpfile | ||
|
||
## `Sensiolabs\GotenbergBundle\Processor\ChainProcessor` | ||
|
||
Apply multiple processors. Each chunk will be sent to each processor sequentially. Return an array of vaues returned by chained processors. | ||
|
||
TODO | ||
|
||
## `Sensiolabs\GotenbergBundle\Bridge\LeagueFlysystem\Processor\FlysystemProcessor` | ||
|
||
Upload using the `league/flysystem-bundle` package. Returns a `callable`. This callable will return the uploaded content. | ||
|
||
## `Sensiolabs\GotenbergBundle\Bridge\AsyncAws\Processor\AsyncAwsS3MultiPartProcessor` | ||
|
||
Upload using the `async-aws/s3` package. Uploads using the (multipart upload)[https://docs.aws.amazon.com/AmazonS3/latest/userguide/mpuoverview.html] feature of S3. Returns a `AsyncAws\S3\Result\CompleteMultipartUploadOutput` object. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Wrong format |
||
|
||
### Custom processor | ||
Neirda24 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
A custom processor must implement `Sensiolabs\GotenbergBundle\Processor\ProcessorInterface` which require that your `__invoke` method is a `\Generator`. To receive a chunk you must assign `yield` to a variable like so : `$chunk = yield`. | ||
|
||
The basic needed code is the following : | ||
|
||
```php | ||
use Sensiolabs\GotenbergBundle\Processor\ProcessorInterface; | ||
|
||
/** | ||
* @implements ProcessorInterface<YOUR_GENERATOR_RETURN_TYPE> | ||
*/ | ||
class CustomProcessor implements ProcessorInterface | ||
{ | ||
public function __invoke(string|null $fileName): \Generator | ||
{ | ||
do { | ||
$chunk = yield; | ||
// do something with it | ||
} while (!$chunk->isLast()); | ||
// rest of your code | ||
} | ||
} | ||
``` | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We should also explain that the returned value of the processor will be returned by the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
might be worth to lower the requirement