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

Rework services to allow future changes towards profiler #25

Merged
merged 3 commits into from
Mar 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions .phpstorm.meta.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php

namespace PHPSTORM_META {
expectedArguments(
\Sensiolabs\GotenbergBundle\Builder\AbstractPdfBuilder::fileName(),
1,
\Symfony\Component\HttpFoundation\HeaderUtils::DISPOSITION_INLINE,
\Symfony\Component\HttpFoundation\HeaderUtils::DISPOSITION_ATTACHMENT,
);
}
65 changes: 51 additions & 14 deletions config/services.php
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
<?php

use Sensiolabs\GotenbergBundle\Builder\HtmlPdfBuilder;
use Sensiolabs\GotenbergBundle\Builder\LibreOfficePdfBuilder;
use Sensiolabs\GotenbergBundle\Builder\MarkdownPdfBuilder;
use Sensiolabs\GotenbergBundle\Builder\UrlPdfBuilder;
use Sensiolabs\GotenbergBundle\Client\GotenbergClient;
use Sensiolabs\GotenbergBundle\Client\GotenbergClientInterface;
use Sensiolabs\GotenbergBundle\Formatter\AssetBaseDirFormatter;
Expand All @@ -12,29 +16,16 @@
use function Symfony\Component\DependencyInjection\Loader\Configurator\abstract_arg;
use function Symfony\Component\DependencyInjection\Loader\Configurator\param;
use function Symfony\Component\DependencyInjection\Loader\Configurator\service;
use function Symfony\Component\DependencyInjection\Loader\Configurator\tagged_locator;

return function (ContainerConfigurator $container): void {
$services = $container->services();

$services->set('sensiolabs_gotenberg', Gotenberg::class)
->args([
service('sensiolabs_gotenberg.client'),
abstract_arg('html configuration options'),
abstract_arg('url configuration options'),
abstract_arg('markdown configuration options'),
abstract_arg('office configuration options'),
service('sensiolabs_gotenberg.asset.base_dir_formatter'),
service('twig')->nullOnInvalid(),
])
->public()
->alias(GotenbergInterface::class, 'sensiolabs_gotenberg');

$services->set('sensiolabs_gotenberg.client', GotenbergClient::class)
->args([
abstract_arg('base_uri to gotenberg API'),
service(HttpClientInterface::class),
])
->public()
->alias(GotenbergClientInterface::class, 'sensiolabs_gotenberg.client');

$services->set('sensiolabs_gotenberg.asset.base_dir_formatter', AssetBaseDirFormatter::class)
Expand All @@ -49,4 +40,50 @@
$services->set('sensiolabs_gotenberg.twig.asset_extension', GotenbergAssetExtension::class)
->tag('twig.extension')
;

$services->set('.sensiolabs_gotenberg.builder.html', HtmlPdfBuilder::class)
->share(false)
->args([
service('sensiolabs_gotenberg.client'),
service('sensiolabs_gotenberg.asset.base_dir_formatter'),
service('twig')->nullOnInvalid(),
])
->tag('sensiolabs_gotenberg.builder')
;

$services->set('.sensiolabs_gotenberg.builder.url', UrlPdfBuilder::class)
->share(false)
->args([
service('sensiolabs_gotenberg.client'),
service('sensiolabs_gotenberg.asset.base_dir_formatter'),
service('twig')->nullOnInvalid(),
])
->tag('sensiolabs_gotenberg.builder')
;

$services->set('.sensiolabs_gotenberg.builder.markdown', MarkdownPdfBuilder::class)
->share(false)
->args([
service('sensiolabs_gotenberg.client'),
service('sensiolabs_gotenberg.asset.base_dir_formatter'),
service('twig')->nullOnInvalid(),
])
->tag('sensiolabs_gotenberg.builder')
;

$services->set('.sensiolabs_gotenberg.builder.office', LibreOfficePdfBuilder::class)
->share(false)
->args([
service('sensiolabs_gotenberg.client'),
service('sensiolabs_gotenberg.asset.base_dir_formatter'),
])
->tag('sensiolabs_gotenberg.builder')
;

Neirda24 marked this conversation as resolved.
Show resolved Hide resolved
$services->set('sensiolabs_gotenberg', Gotenberg::class)
->args([
tagged_locator('sensiolabs_gotenberg.builder'),
])
->alias(GotenbergInterface::class, 'sensiolabs_gotenberg')
;
};
6 changes: 6 additions & 0 deletions phpstan.neon
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
parameters:
level: 8
paths:
- 'config'
- 'src'
- 'tests'
ignoreErrors:
-
message: "#^Method Sensiolabs\\\\GotenbergBundle\\\\Tests\\\\Kernel\\:\\:configureContainer\\(\\) is unused\\.$#"
count: 1
path: tests/Kernel.php
4 changes: 4 additions & 0 deletions phpunit.xml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@
beStrictAboutOutputDuringTests="true"
failOnRisky="true"
failOnWarning="true">
<php>
<env name="KERNEL_CLASS" value="Sensiolabs\GotenbergBundle\Tests\Kernel"/>
</php>

<testsuites>
<testsuite name="default">
<directory>tests</directory>
Expand Down
3 changes: 3 additions & 0 deletions src/Builder/AbstractChromiumPdfBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,7 @@ public function nativePageRanges(string $range): static
}

/**
* @param string $template #Template
* @param array<string, mixed> $context
*
* @throws PdfPartRenderingException if the template could not be rendered
Expand All @@ -204,6 +205,7 @@ public function header(string $template, array $context = []): static
}

/**
* @param string $template #Template
* @param array<string, mixed> $context
*
* @throws PdfPartRenderingException if the template could not be rendered
Expand Down Expand Up @@ -439,6 +441,7 @@ protected function withPdfPartFile(PdfPart $pdfPart, string $path): static
}

/**
* @param string $template #Template
* @param array<string, mixed> $context
*
* @throws PdfPartRenderingException if the template could not be rendered
Expand Down
38 changes: 32 additions & 6 deletions src/Builder/AbstractPdfBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@

use Sensiolabs\GotenbergBundle\Client\GotenbergClientInterface;
use Sensiolabs\GotenbergBundle\Client\PdfResponse;
use Sensiolabs\GotenbergBundle\Exception\MissingRequiredFieldException;
use Sensiolabs\GotenbergBundle\Formatter\AssetBaseDirFormatter;
use Symfony\Component\HttpFoundation\File\File;
use Symfony\Component\HttpFoundation\HeaderUtils;

abstract class AbstractPdfBuilder implements PdfBuilderInterface
{
Expand All @@ -15,6 +15,10 @@ abstract class AbstractPdfBuilder implements PdfBuilderInterface
*/
protected array $formFields = [];

private string|null $fileName = null;

private string $headerDisposition = HeaderUtils::DISPOSITION_INLINE;

public function __construct(
protected readonly GotenbergClientInterface $gotenbergClient,
protected readonly AssetBaseDirFormatter $asset,
Expand All @@ -24,9 +28,7 @@ public function __construct(
/**
* Compiles the form values into a multipart form data array to send to the HTTP client.
*
* @return array<int, array<string, string>>
*
* @throws MissingRequiredFieldException
* @return list<array<string, string>>
*/
abstract public function getMultipartFormData(): array;

Expand All @@ -40,13 +42,37 @@ abstract protected function getEndpoint(): string;
*/
abstract public function setConfigurations(array $configurations): self;

/**
* @param HeaderUtils::DISPOSITION_* $headerDisposition
*/
public function fileName(string $fileName, string $headerDisposition = HeaderUtils::DISPOSITION_INLINE): static
{
$this->fileName = $fileName;
$this->headerDisposition = $headerDisposition;

return $this;
}

public function generate(): PdfResponse
{
return $this->gotenbergClient->call($this->getEndpoint(), $this->getMultipartFormData());
$pdfResponse = $this->gotenbergClient->call($this->getEndpoint(), $this->getMultipartFormData());

if (null !== $this->fileName) {
Neirda24 marked this conversation as resolved.
Show resolved Hide resolved
$disposition = HeaderUtils::makeDisposition(
$this->headerDisposition,
$this->fileName
);

$pdfResponse
->headers->set('Content-Disposition', $disposition)
;
}

return $pdfResponse;
}

/**
* @param string[] $validExtensions
* @param non-empty-list<string> $validExtensions
*/
protected function assertFileExtension(string $path, array $validExtensions): void
{
Expand Down
1 change: 1 addition & 0 deletions src/Builder/HtmlPdfBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ final class HtmlPdfBuilder extends AbstractChromiumPdfBuilder
private const ENDPOINT = '/forms/chromium/convert/html';

/**
* @param string $template #Template
* @param array<string, mixed> $context
*
* @throws PdfPartRenderingException if the template could not be rendered
Expand Down
1 change: 1 addition & 0 deletions src/Builder/MarkdownPdfBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ final class MarkdownPdfBuilder extends AbstractChromiumPdfBuilder
/**
* The HTML file that wraps the markdown content, rendered from a Twig template.
*
* @param string $template #Template
* @param array<string, mixed> $context
*
* @throws PdfPartRenderingException if the template could not be rendered
Expand Down
15 changes: 0 additions & 15 deletions src/Client/PdfResponse.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,7 @@

namespace Sensiolabs\GotenbergBundle\Client;

use Symfony\Component\Filesystem\Filesystem;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\HttpException;
use Symfony\Contracts\HttpClient\ResponseInterface;

class PdfResponse extends Response
Expand All @@ -13,17 +11,4 @@ public function __construct(public ResponseInterface $response)
{
parent::__construct($response->getContent(), $response->getStatusCode(), $response->getHeaders());
}

public function saveTo(string $filename): string
Neirda24 marked this conversation as resolved.
Show resolved Hide resolved
{
$file = new Filesystem();

try {
$file->dumpFile($filename, $this->response->getContent());
} catch (\Exception $exception) {
throw new HttpException(500, $exception->getMessage());
}

return $filename;
}
}
8 changes: 0 additions & 8 deletions src/DependencyInjection/Configuration.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,18 +21,10 @@ public function getConfigTreeBuilder(): TreeBuilder
->scalarNode('base_uri')
->info('Host of your local Gotenberg API')
->defaultValue('http://localhost:3000')
->cannotBeEmpty()
->validate()
->ifTrue(static function ($option): bool {
return preg_match('/^(http|https):\/\//', $option) !== 1;
})
->thenInvalid('Invalid API Gotenberg host.')
->end()
->end()
->scalarNode('base_directory')
->info('Base directory will be used for assets, files, markdown')
->defaultValue('%kernel.project_dir%')
->cannotBeEmpty()
->end()
->arrayNode('default_options')
->addDefaultsIfNotSet()
Expand Down
27 changes: 20 additions & 7 deletions src/DependencyInjection/SensiolabsGotenbergExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace Sensiolabs\GotenbergBundle\DependencyInjection;

use Sensiolabs\GotenbergBundle\Builder\PdfBuilderInterface;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Loader\PhpFileLoader;
Expand All @@ -19,23 +20,35 @@ public function load(array $configs, ContainerBuilder $container): void
/** @var array{base_uri: string, base_directory: string, default_options: array{html: array<string, mixed>, url: array<string, mixed>, markdown: array<string, mixed>, office: array<string, mixed>}} $config */
$config = $this->processConfiguration($configuration, $configs);

$container->registerForAutoconfiguration(PdfBuilderInterface::class)
->addTag('sensiolabs_gotenberg.builder')
;

$definition = $container->getDefinition('sensiolabs_gotenberg.client');
$definition->replaceArgument(0, $config['base_uri']);

$definition = $container->getDefinition('sensiolabs_gotenberg');
$definition->replaceArgument(1, $this->cleanUserOptions($config['default_options']['html']));
$definition->replaceArgument(2, $this->cleanUserOptions($config['default_options']['url']));
$definition->replaceArgument(3, $this->cleanUserOptions($config['default_options']['markdown']));
$definition->replaceArgument(4, $this->cleanUserOptions($config['default_options']['office']));
$definition = $container->getDefinition('.sensiolabs_gotenberg.builder.html');
$definition->addMethodCall('setConfigurations', [$this->cleanUserOptions($config['default_options']['html'])]);

$definition = $container->getDefinition('.sensiolabs_gotenberg.builder.url');
$definition->addMethodCall('setConfigurations', [$this->cleanUserOptions($config['default_options']['url'])]);

$definition = $container->getDefinition('.sensiolabs_gotenberg.builder.markdown');
$definition->addMethodCall('setConfigurations', [$this->cleanUserOptions($config['default_options']['markdown'])]);

$definition = $container->getDefinition('.sensiolabs_gotenberg.builder.office');
$definition->addMethodCall('setConfigurations', [$this->cleanUserOptions($config['default_options']['office'])]);

$definition = $container->getDefinition('sensiolabs_gotenberg.asset.base_dir_formatter');
$definition->replaceArgument(2, $config['base_directory']);
}

/**
* @param array<string, mixed> $userConfigurations
* @template T of array<string, mixed>
*
* @param T $userConfigurations
*
* @return array<string, mixed>
* @return array<key-of<T>, value-of<T>>
*/
private function cleanUserOptions(array $userConfigurations): array
{
Expand Down
Loading