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

Allow live pdf template edit #191

Merged
merged 28 commits into from
Mar 30, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
df4a8a4
Allow to customize the CSS used to render the GiftCard PDF
Roshyo Jan 19, 2022
30a17ed
Live render PDF in admin
Roshyo Jan 22, 2022
7e97330
Make tests green and integrate requested changes
Roshyo Feb 7, 2022
b757d04
Make tests green
Roshyo Feb 7, 2022
e60db84
Fix ECS
Roshyo Feb 7, 2022
ee2495c
Add phpunit tests
Roshyo Feb 7, 2022
f590df2
Fix ECS
Roshyo Feb 7, 2022
8fe7f64
Return file path after generating the PDF
Roshyo Feb 16, 2022
c03fce5
Adding more tests for better coverage
Roshyo Feb 16, 2022
64ff8b7
Fix ECS
Roshyo Feb 16, 2022
3567496
Rename controllers to explicitly define the example
Roshyo Feb 16, 2022
d5fcc76
Rename Dummy Factory to Example Factory
Roshyo Feb 23, 2022
917dba6
Load and display the HTML code on PDF page
Roshyo Mar 4, 2022
4d411ac
Fix require checker
Roshyo Mar 4, 2022
6931f7b
Fix Psalm
Roshyo Mar 4, 2022
2cc4b1b
Remove unused dependency
Roshyo Mar 4, 2022
a8a663b
Add comment about dropping Sf4.4
Roshyo Mar 4, 2022
4bc9173
Remove un-needed HTTP methods.
Roshyo Mar 4, 2022
c7cca1d
Avoid generating a PDF file and rather display it directly
Roshyo Mar 4, 2022
d45e091
Use dom crawler instead of ignoring dep
Roshyo Mar 4, 2022
4dc801c
Remove unused controller
Roshyo Mar 4, 2022
839fbd4
Remove test
Roshyo Mar 4, 2022
433a6e1
Add more tests and integrate changes requuested
Roshyo Mar 7, 2022
df31529
Remove un-needed dep
Roshyo Mar 7, 2022
e8075eb
Use css.twig file instead of txt file
Roshyo Mar 9, 2022
2c1924e
Fix services declaration and tests
Roshyo Mar 28, 2022
f4a2117
Fix composer file
Roshyo Mar 29, 2022
8acee4b
Use the rendering options provider for the PDF generation
Roshyo Mar 29, 2022
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
2 changes: 2 additions & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,14 @@
"doctrine/orm": "^2.7",
"doctrine/persistence": "^1.3 || ^2.2",
"fakerphp/faker": "^1.9.0",
"knplabs/gaufrette": "^0.8",
"knplabs/knp-menu": "^3.2",
"knplabs/knp-snappy": "^1.2",
"knplabs/knp-snappy-bundle": "^1.7",
"sylius/resource-bundle": "^1.6",
"symfony/config": "^4.4 || ^5.0",
"symfony/dependency-injection": "^4.4 || ^5.0",
"symfony/dom-crawler": "^4.4 || ^5.0",
"symfony/event-dispatcher": "^4.4 || ^5.0",
"symfony/form": "^4.4 || ^5.0",
"symfony/http-foundation": "^4.4 || ^5.0.7",
Expand Down
53 changes: 53 additions & 0 deletions src/Controller/Action/Admin/GenerateEncodedExamplePdfAction.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
<?php

declare(strict_types=1);

namespace Setono\SyliusGiftCardPlugin\Controller\Action\Admin;

use Setono\SyliusGiftCardPlugin\Factory\GiftCardFactoryInterface;
use Setono\SyliusGiftCardPlugin\Form\Type\GiftCardConfigurationType;
use Setono\SyliusGiftCardPlugin\Generator\GiftCardPdfGeneratorInterface;
use Setono\SyliusGiftCardPlugin\Model\GiftCardConfigurationInterface;
use Sylius\Component\Resource\Repository\RepositoryInterface;
use Symfony\Component\Form\FormFactoryInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Webmozart\Assert\Assert;

final class GenerateEncodedExamplePdfAction
{
private GiftCardFactoryInterface $giftCardFactory;

private RepositoryInterface $giftCardConfigurationRepository;

private GiftCardPdfGeneratorInterface $giftCardPdfGenerator;

private FormFactoryInterface $formFactory;

public function __construct(
GiftCardFactoryInterface $giftCardFactory,
RepositoryInterface $giftCardConfigurationRepository,
GiftCardPdfGeneratorInterface $giftCardPdfGenerator,
FormFactoryInterface $formFactory
) {
$this->giftCardFactory = $giftCardFactory;
$this->giftCardConfigurationRepository = $giftCardConfigurationRepository;
$this->giftCardPdfGenerator = $giftCardPdfGenerator;
$this->formFactory = $formFactory;
}

public function __invoke(Request $request, int $id): Response
{
$giftCard = $this->giftCardFactory->createExample();
/** @var GiftCardConfigurationInterface|null $giftCardConfiguration */
$giftCardConfiguration = $this->giftCardConfigurationRepository->find($id);
Assert::isInstanceOf($giftCardConfiguration, GiftCardConfigurationInterface::class);

$form = $this->formFactory->create(GiftCardConfigurationType::class, $giftCardConfiguration);
$form->handleRequest($request);

$pdfContent = $this->giftCardPdfGenerator->generateAndGetContent($giftCard, $giftCardConfiguration);

return new Response(\base64_encode($pdfContent));
}
}
54 changes: 54 additions & 0 deletions src/Controller/Action/Admin/LoadDefaultPdfCssAction.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
<?php

declare(strict_types=1);

namespace Setono\SyliusGiftCardPlugin\Controller\Action\Admin;

use Setono\SyliusGiftCardPlugin\Factory\GiftCardFactoryInterface;
use Setono\SyliusGiftCardPlugin\Generator\GiftCardPdfGeneratorInterface;
use Setono\SyliusGiftCardPlugin\Model\GiftCardConfigurationInterface;
use Setono\SyliusGiftCardPlugin\Provider\DefaultPdfCssProviderInterface;
use Sylius\Component\Resource\Repository\RepositoryInterface;
use Symfony\Component\HttpFoundation\JsonResponse;
use Webmozart\Assert\Assert;

final class LoadDefaultPdfCssAction
{
private GiftCardFactoryInterface $giftCardFactory;

private RepositoryInterface $giftCardConfigurationRepository;

private GiftCardPdfGeneratorInterface $giftCardPdfGenerator;

private DefaultPdfCssProviderInterface $defaultPdfCssProvider;

public function __construct(
GiftCardFactoryInterface $giftCardFactory,
RepositoryInterface $giftCardConfigurationRepository,
GiftCardPdfGeneratorInterface $giftCardPdfGenerator,
DefaultPdfCssProviderInterface $defaultPdfCssProvider
) {
$this->giftCardFactory = $giftCardFactory;
$this->giftCardConfigurationRepository = $giftCardConfigurationRepository;
$this->giftCardPdfGenerator = $giftCardPdfGenerator;
$this->defaultPdfCssProvider = $defaultPdfCssProvider;
}

public function __invoke(int $id): JsonResponse
{
$giftCard = $this->giftCardFactory->createExample();
/** @var GiftCardConfigurationInterface|null $giftCardConfiguration */
$giftCardConfiguration = $this->giftCardConfigurationRepository->find($id);
Assert::isInstanceOf($giftCardConfiguration, GiftCardConfigurationInterface::class);

$defaultCss = $this->defaultPdfCssProvider->getDefaultCss();
$giftCardConfiguration->setPdfRenderingCss($defaultCss);

$pdfContent = $this->giftCardPdfGenerator->generateAndGetContent($giftCard, $giftCardConfiguration);

return new JsonResponse([
'css' => $defaultCss,
'pdfContent' => \base64_encode($pdfContent),
]);
}
}
6 changes: 6 additions & 0 deletions src/DependencyInjection/SetonoSyliusGiftCardExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,12 @@ public function load(array $configs, ContainerBuilder $container): void
$config['pdf_rendering']['available_page_sizes']
);

// Load default CSS file
$container->setParameter(
'setono_sylius_gift_card.default_css_file',
'@SetonoSyliusGiftCardPlugin/Shop/GiftCard/defaultGiftCardConfiguration.css.twig'
);

$this->registerResources('setono_sylius_gift_card', $config['driver'], $config['resources'], $container);

$loader->load('services.xml');
Expand Down
16 changes: 15 additions & 1 deletion src/Factory/GiftCardFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
use Sylius\Component\Core\Model\ChannelInterface;
use Sylius\Component\Core\Model\CustomerInterface;
use Sylius\Component\Core\Model\OrderInterface;
use Sylius\Component\Currency\Context\CurrencyContextInterface;
use Sylius\Component\Resource\Factory\FactoryInterface;
use Webmozart\Assert\Assert;

Expand All @@ -27,16 +28,20 @@ final class GiftCardFactory implements GiftCardFactoryInterface

private DateTimeProvider $dateTimeProvider;

private CurrencyContextInterface $currencyContext;

public function __construct(
FactoryInterface $decoratedFactory,
GiftCardCodeGeneratorInterface $giftCardCodeGenerator,
GiftCardChannelConfigurationProviderInterface $giftCardChannelConfigurationProvider,
DateTimeProvider $dateTimeProvider
DateTimeProvider $dateTimeProvider,
CurrencyContextInterface $currencyContext
) {
$this->decoratedFactory = $decoratedFactory;
$this->giftCardCodeGenerator = $giftCardCodeGenerator;
$this->giftCardChannelConfigurationProvider = $giftCardChannelConfigurationProvider;
$this->dateTimeProvider = $dateTimeProvider;
$this->currencyContext = $currencyContext;
}

public function createNew(): GiftCardInterface
Expand Down Expand Up @@ -114,4 +119,13 @@ public function createFromOrderItemUnitAndCart(

return $giftCard;
}

public function createExample(): GiftCardInterface
{
$giftCard = $this->createNew();
$giftCard->setAmount(1500);
$giftCard->setCurrencyCode($this->currencyContext->getCurrencyCode());

return $giftCard;
}
}
5 changes: 5 additions & 0 deletions src/Factory/GiftCardFactoryInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,9 @@ public function createFromOrderItemUnitAndCart(
OrderItemUnitInterface $orderItemUnit,
OrderInterface $cart
): GiftCardInterface;

Roshyo marked this conversation as resolved.
Show resolved Hide resolved
/**
* Create an example GiftCard that is used to generate the example PDF for configuration live rendering
*/
public function createExample(): GiftCardInterface;
}
4 changes: 4 additions & 0 deletions src/Form/Type/GiftCardConfigurationType.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\Extension\Core\Type\CollectionType;
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface;

Expand Down Expand Up @@ -82,6 +83,9 @@ public function buildForm(FormBuilderInterface $builder, array $options): void
return $value;
},
]);
$builder->add('pdfRenderingCss', TextareaType::class, [
'label' => 'setono_sylius_gift_card.form.gift_card_configuration.pdf_rendering_css',
]);
$builder->get('defaultValidityPeriod')->addModelTransformer(
new CallbackTransformer(
function (?string $period): array {
Expand Down
1 change: 1 addition & 0 deletions src/Generator/GiftCardCodeGenerator.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ public function generate(): string
do {
// if we didn't remove the 'hard to read' characters we would only have to
// generate codeLength / 2 bytes because hex uses two characters to represent one byte
/** @psalm-suppress ArgumentTypeCoercion */
$code = bin2hex(random_bytes($this->codeLength));
$code = preg_replace('/[01]/', '', $code); // remove hard to read characters
$code = mb_strtoupper(mb_substr($code, 0, $this->codeLength));
Expand Down
46 changes: 45 additions & 1 deletion src/Generator/GiftCardPdfGenerator.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

namespace Setono\SyliusGiftCardPlugin\Generator;

use Gaufrette\FilesystemInterface;
use Knp\Bundle\SnappyBundle\Snappy\Response\PdfResponse;
use Knp\Snappy\GeneratorInterface;
use Setono\SyliusGiftCardPlugin\Model\GiftCardConfigurationInterface;
Expand All @@ -19,14 +20,22 @@ class GiftCardPdfGenerator implements GiftCardPdfGeneratorInterface

private PdfRenderingOptionsProviderInterface $renderingOptionsProvider;

private GiftCardPdfPathGeneratorInterface $giftCardPdfPathGenerator;

private FilesystemInterface $filesystem;

public function __construct(
Environment $twig,
GeneratorInterface $snappy,
PdfRenderingOptionsProviderInterface $renderingOptionsProvider
PdfRenderingOptionsProviderInterface $renderingOptionsProvider,
GiftCardPdfPathGeneratorInterface $giftCardPdfPathGenerator,
FilesystemInterface $filesystem
) {
$this->twig = $twig;
$this->snappy = $snappy;
$this->renderingOptionsProvider = $renderingOptionsProvider;
$this->giftCardPdfPathGenerator = $giftCardPdfPathGenerator;
$this->filesystem = $filesystem;
}

public function generatePdfResponse(
Expand All @@ -42,4 +51,39 @@ public function generatePdfResponse(

return new PdfResponse($this->snappy->getOutputFromHtml($html, $renderingOptions), 'gift_card.pdf');
}

public function generateAndGetContent(
GiftCardInterface $giftCard,
GiftCardConfigurationInterface $giftCardChannelConfiguration
): string {
$html = $this->twig->render('@SetonoSyliusGiftCardPlugin/Shop/GiftCard/pdf.html.twig', [
'giftCard' => $giftCard,
'configuration' => $giftCardChannelConfiguration,
]);
$renderingOptions = $this->renderingOptionsProvider->getRenderingOptions($giftCardChannelConfiguration);

return $this->snappy->getOutputFromHtml($html, $renderingOptions);
}

public function generateAndSavePdf(
Roshyo marked this conversation as resolved.
Show resolved Hide resolved
GiftCardInterface $giftCard,
GiftCardConfigurationInterface $giftCardChannelConfiguration
): string {
$html = $this->twig->render('@SetonoSyliusGiftCardPlugin/Shop/GiftCard/pdf.html.twig', [
'giftCard' => $giftCard,
'configuration' => $giftCardChannelConfiguration,
]);
$renderingOptions = $this->renderingOptionsProvider->getRenderingOptions($giftCardChannelConfiguration);

$filePath = $this->giftCardPdfPathGenerator->generatePath($giftCardChannelConfiguration);
$pdfContent = $this->snappy->getOutputFromHtml($html, $renderingOptions);

$this->filesystem->write(
$filePath,
$pdfContent,
true
);

return $filePath;
}
}
10 changes: 10 additions & 0 deletions src/Generator/GiftCardPdfGeneratorInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,14 @@ public function generatePdfResponse(
GiftCardInterface $giftCard,
GiftCardConfigurationInterface $giftCardChannelConfiguration
): PdfResponse;

public function generateAndGetContent(
GiftCardInterface $giftCard,
GiftCardConfigurationInterface $giftCardChannelConfiguration
): string;

public function generateAndSavePdf(
GiftCardInterface $giftCard,
GiftCardConfigurationInterface $giftCardChannelConfiguration
): string;
}
23 changes: 23 additions & 0 deletions src/Generator/GiftCardPdfPathGenerator.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?php

declare(strict_types=1);

namespace Setono\SyliusGiftCardPlugin\Generator;

use Setono\SyliusGiftCardPlugin\Model\GiftCardConfigurationInterface;
use function sprintf;
use Webmozart\Assert\Assert;

final class GiftCardPdfPathGenerator implements GiftCardPdfPathGeneratorInterface
{
public function generatePath(GiftCardConfigurationInterface $giftCardChannelConfiguration): string
{
$giftCardChannelConfigurationId = $giftCardChannelConfiguration->getId();
Assert::integer($giftCardChannelConfigurationId);

return sprintf(
'gift_card_configuration_pdf_%d.pdf',
$giftCardChannelConfigurationId
);
}
}
12 changes: 12 additions & 0 deletions src/Generator/GiftCardPdfPathGeneratorInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?php

declare(strict_types=1);

namespace Setono\SyliusGiftCardPlugin\Generator;

use Setono\SyliusGiftCardPlugin\Model\GiftCardConfigurationInterface;

interface GiftCardPdfPathGeneratorInterface
{
public function generatePath(GiftCardConfigurationInterface $giftCardChannelConfiguration): string;
}
12 changes: 12 additions & 0 deletions src/Model/GiftCardConfiguration.php
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ class GiftCardConfiguration implements GiftCardConfigurationInterface

protected ?string $orientation = null;

protected ?string $pdfRenderingCss = null;

public function __construct()
{
$this->images = new ArrayCollection();
Expand Down Expand Up @@ -201,4 +203,14 @@ public function setOrientation(?string $orientation): void
{
$this->orientation = $orientation;
}

public function getPdfRenderingCss(): ?string
{
return $this->pdfRenderingCss;
}

public function setPdfRenderingCss(?string $pdfRenderingCss): void
{
$this->pdfRenderingCss = $pdfRenderingCss;
}
}
4 changes: 4 additions & 0 deletions src/Model/GiftCardConfigurationInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -50,4 +50,8 @@ public function setPageSize(?string $pageSize): void;
public function getOrientation(): ?string;

public function setOrientation(?string $orientation): void;

public function getPdfRenderingCss(): ?string;

public function setPdfRenderingCss(?string $pdfRenderingCss): void;
}
25 changes: 25 additions & 0 deletions src/Provider/DefaultPdfCssProvider.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php

declare(strict_types=1);

namespace Setono\SyliusGiftCardPlugin\Provider;

use Twig\Environment;

final class DefaultPdfCssProvider implements DefaultPdfCssProviderInterface
{
private string $defaultCssFile;

private Environment $twig;

public function __construct(string $defaultCssFile, Environment $twig)
{
$this->defaultCssFile = $defaultCssFile;
$this->twig = $twig;
}

public function getDefaultCss(): string
{
return $this->twig->render($this->defaultCssFile);
}
}
Loading