Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Doc/processor #141

Open
wants to merge 16 commits into
base: main
Choose a base branch
from
Open
42 changes: 25 additions & 17 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,15 @@ To set up the project locally for development:

### Clone the Repository

```
git clone https://github.com/sensiolabs/GotenbergBundle.git
cd GotenbergBundle
```shell
$ git clone https://github.com/sensiolabs/GotenbergBundle.git
$ cd GotenbergBundle
```

### Install Dependencies

```
composer install
```shell
$ composer install
```

## Testing
Expand All @@ -42,14 +42,14 @@ Ensure your changes work as expected by running the test suite:

### Run Tests

```
./vendor/bin/phpunit
```shell
$ ./vendor/bin/phpunit
```

### Run Tests with Coverage (optional)

```
./vendor/bin/phpunit --coverage-text
```shell
$ ./vendor/bin/phpunit --coverage-text
```

## Quality Assurance
Expand All @@ -60,24 +60,32 @@ Maintain high code quality by following these steps before submitting a pull req

Check your code for style violations:

```
./vendor/bin/php-cs-fixer check --diff
```shell
$ PHP_CS_FIXER_IGNORE_ENV=1 ./vendor/bin/php-cs-fixer check --diff
```

Eventually, you can fix the issues automatically:

```
./vendor/bin/php-cs-fixer fix --diff
```shell
$ PHP_CS_FIXER_IGNORE_ENV=1 ./vendor/bin/php-cs-fixer fix --diff
```

### Static Analysis

```
./vendor/bin/phpstan analyse
```shell
$ php -dmemory_limit=-1 ./vendor/bin/phpstan analyse --debug
```

Detect potential issues in your code.

### Dependencies

```shell
$ ./vendor/bin/composer-dependency-analyser --show-all-usages
```

Detect potential issues in composer.json dependencies.

### Fix Issues

Address any warnings or errors reported by the tools above.
Expand All @@ -91,8 +99,8 @@ The project documentation is partially built from the source code.

### Update the documentation

```
php ./docs/generate.php
```shell
$ php ./docs/generate.php
```


Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,7 @@ class YourController
### Advanced Usage

1. [Configuration](./docs/configuration.md)
2. [Processing (saving for example)](./docs/processing.md)
2. [Working with assets](./docs/assets.md)
3. [Builders API](./docs/builders_api.md)
4. [Async & Webhooks](./docs/webhook.md)
Expand Down
7 changes: 7 additions & 0 deletions composer-dependency-analyser.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,13 @@
->addPathToScan(__DIR__.'/src/Debug', isDev: true)
->addPathToScan(__DIR__.'/tests', isDev: true)

->ignoreErrorsOnPackage('async-aws/s3', [
ErrorType::DEV_DEPENDENCY_IN_PROD,
])
->disableExtensionsAnalysis() // TODO : Bug waiting for https://github.com/shipmonk-rnd/composer-dependency-analyser/issues/217
->ignoreErrorsOnPackage('league/flysystem', [
ErrorType::DEV_DEPENDENCY_IN_PROD,
])
->ignoreErrorsOnPackage('symfony/routing', [
ErrorType::DEV_DEPENDENCY_IN_PROD,
])
Expand Down
12 changes: 9 additions & 3 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,16 @@
"symfony/mime": "^6.4 || ^7.0"
},
"require-dev": {
"ext-mbstring": "*",
"async-aws/s3": "^2.6",
Copy link
Contributor Author

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

"friendsofphp/php-cs-fixer": "^3.41",
"league/flysystem": "^3.29",
"league/flysystem-bundle": "^3.3",
Copy link
Contributor Author

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

"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",
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

needed to ignore ext-mbstring issues

"symfony/framework-bundle": "^6.4 || ^7.0",
"symfony/http-client": "^6.4 || ^7.0",
"symfony/monolog-bundle": "^3.10",
Expand All @@ -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."
}
}
11 changes: 10 additions & 1 deletion docs/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,10 @@ The default configuration for the bundle looks like :

Assuming you have the following client configured.

```yaml
<details>
<summary>app/config/framework.yaml</summary>

```yaml
# app/config/framework.yaml

framework:
Expand All @@ -19,8 +21,13 @@ framework:
base_uri: 'http://localhost:3000'
```

</details>

Then

<details>
<summary>app/config/sensiolabs_gotenberg.yaml</summary>

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

Expand Down Expand Up @@ -1237,6 +1244,8 @@ sensiolabs_gotenberg:
# - { name: 'X-Custom-Header', value: 'custom-header-value' }
```

</details>

> [!TIP]
> For more information about the [PDF properties](https://gotenberg.dev/docs/routes#page-properties-chromium)
> or [screenshot properties](https://gotenberg.dev/docs/routes#screenshots-route).
Expand Down
155 changes: 155 additions & 0 deletions docs/processing.md
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>
Copy link
Contributor

Choose a reason for hiding this comment

The 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.
Copy link
Contributor

Choose a reason for hiding this comment

The 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
}
}
```
Copy link
Contributor

Choose a reason for hiding this comment

The 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 process method

Loading
Loading