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 1 commit
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
64 changes: 50 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 @@ -16,25 +20,11 @@
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 +39,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([
abstract_arg('All builders indexed by class FQCN')
Neirda24 marked this conversation as resolved.
Show resolved Hide resolved
])
->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
28 changes: 24 additions & 4 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,8 @@ abstract class AbstractPdfBuilder implements PdfBuilderInterface
*/
protected array $formFields = [];

private string|null $fileName;

public function __construct(
protected readonly GotenbergClientInterface $gotenbergClient,
protected readonly AssetBaseDirFormatter $asset,
Expand All @@ -25,8 +27,6 @@ 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
*/
abstract public function getMultipartFormData(): array;

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

public function withFileName(string $fileName): static
{
$this->fileName = $fileName;

return $this;
}
Neirda24 marked this conversation as resolved.
Show resolved Hide resolved

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(
HeaderUtils::DISPOSITION_INLINE, # TODO : make dynamic
$this->fileName
);

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

return $pdfResponse;
}

/**
Expand Down
29 changes: 29 additions & 0 deletions src/DependencyInjection/CompilerPass/ProcessBuildersPass.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?php

declare(strict_types=1);

namespace Sensiolabs\GotenbergBundle\DependencyInjection\CompilerPass;

use Sensiolabs\GotenbergBundle\Builder\PdfBuilderInterface;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\Compiler\ServiceLocatorTagPass;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Reference;

final class ProcessBuildersPass implements CompilerPassInterface
{
public function process(ContainerBuilder $container): void
{
/** @var array<class-string<PdfBuilderInterface>, Reference> $builders */
$builders = [];
foreach ($container->findTaggedServiceIds('sensiolabs_gotenberg.builder') as $serviceId => $tags) {
$definition = $container->getDefinition($serviceId);

$builders[$definition->getClass()] = new Reference($serviceId);
}

$gotenberg = $container->findDefinition('sensiolabs_gotenberg');

$gotenberg->setArgument('$container', ServiceLocatorTagPass::register($container, $builders));
}
}
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
21 changes: 16 additions & 5 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,14 +20,24 @@ 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']);
Expand Down
44 changes: 14 additions & 30 deletions src/Pdf/Gotenberg.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,58 +2,42 @@

namespace Sensiolabs\GotenbergBundle\Pdf;

use Psr\Container\ContainerInterface;
use Sensiolabs\GotenbergBundle\Builder\HtmlPdfBuilder;
use Sensiolabs\GotenbergBundle\Builder\LibreOfficePdfBuilder;
use Sensiolabs\GotenbergBundle\Builder\MarkdownPdfBuilder;
use Sensiolabs\GotenbergBundle\Builder\PdfBuilderInterface;
use Sensiolabs\GotenbergBundle\Builder\UrlPdfBuilder;
use Sensiolabs\GotenbergBundle\Client\GotenbergClientInterface;
use Sensiolabs\GotenbergBundle\Formatter\AssetBaseDirFormatter;
use Twig\Environment;

final readonly class Gotenberg implements GotenbergInterface
{
/**
* @param array<string, mixed> $htmlConfiguration
* @param array<string, mixed> $urlConfiguration
* @param array<string, mixed> $markdownConfiguration
* @param array<string, mixed> $officeConfiguration
*/
public function __construct(
private GotenbergClientInterface $gotenbergClient,
private array $htmlConfiguration,
private array $urlConfiguration,
private array $markdownConfiguration,
private array $officeConfiguration,
private AssetBaseDirFormatter $asset,
private ?Environment $twig = null,
private ContainerInterface $container,
) {
}

public function get(string $builder): PdfBuilderInterface
{
return $this->container->get($builder);
}

public function html(): HtmlPdfBuilder
{
return (new HtmlPdfBuilder($this->gotenbergClient, $this->asset, $this->twig))
->setConfigurations($this->htmlConfiguration)
;
return $this->get(HtmlPdfBuilder::class);
}

public function url(): UrlPdfBuilder
{
return (new UrlPdfBuilder($this->gotenbergClient, $this->asset, $this->twig))
->setConfigurations($this->urlConfiguration)
;
return $this->get(UrlPdfBuilder::class);
}

public function markdown(): MarkdownPdfBuilder
public function office(): LibreOfficePdfBuilder
{
return (new MarkdownPdfBuilder($this->gotenbergClient, $this->asset, $this->twig))
->setConfigurations($this->markdownConfiguration)
;
return $this->get(LibreOfficePdfBuilder::class);
}

public function office(): LibreOfficePdfBuilder
public function markdown(): MarkdownPdfBuilder
{
return (new LibreOfficePdfBuilder($this->gotenbergClient, $this->asset))
->setConfigurations($this->officeConfiguration)
;
return $this->get(MarkdownPdfBuilder::class);
}
}
22 changes: 16 additions & 6 deletions src/Pdf/GotenbergInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,25 @@

namespace Sensiolabs\GotenbergBundle\Pdf;

use Sensiolabs\GotenbergBundle\Builder\HtmlPdfBuilder;
use Sensiolabs\GotenbergBundle\Builder\LibreOfficePdfBuilder;
use Sensiolabs\GotenbergBundle\Builder\MarkdownPdfBuilder;
use Sensiolabs\GotenbergBundle\Builder\PdfBuilderInterface;
use Sensiolabs\GotenbergBundle\Builder\UrlPdfBuilder;

interface GotenbergInterface
{
public function html(): PdfBuilderInterface;
/**
* @template T of PdfBuilderInterface
*
* @param class-string<T> $builder
*
* @return T
*/
public function get(string $builder): PdfBuilderInterface;

public function url(): PdfBuilderInterface;

public function markdown(): PdfBuilderInterface;

public function office(): PdfBuilderInterface;
public function html(): HtmlPdfBuilder;
public function url(): UrlPdfBuilder;
public function office(): LibreOfficePdfBuilder;
public function markdown(): MarkdownPdfBuilder;
}
6 changes: 6 additions & 0 deletions src/SensiolabsGotenbergBundle.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,14 @@

namespace Sensiolabs\GotenbergBundle;

use Sensiolabs\GotenbergBundle\DependencyInjection\CompilerPass\ProcessBuildersPass;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\HttpKernel\Bundle\Bundle;

class SensiolabsGotenbergBundle extends Bundle
{
public function build(ContainerBuilder $container)
{
$container->addCompilerPass(new ProcessBuildersPass());
}
}
10 changes: 0 additions & 10 deletions tests/DependencyInjection/ConfigurationTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -53,16 +53,6 @@ public function testDefaultConfig(): void
self::assertEquals(self::getBundleDefaultConfig(), $config);
}

public function testInvalidHost(): void
{
$this->expectException(InvalidConfigurationException::class);
$processor = new Processor();
$processor->processConfiguration(
new Configuration(),
[['base_uri' => 'localhost:3000']],
);
}

#[DataProvider('provideInvalidRange')]
public function testInvalidRange(mixed $range): void
{
Expand Down
Loading