Render for generic doc

This commit is contained in:
Julien Fastré 2023-05-24 21:57:20 +02:00
parent 8dbe2d6ec2
commit e550817ded
Signed by: julienfastre
GPG Key ID: BDE2190974723FCB
14 changed files with 299 additions and 66 deletions

View File

@ -11,7 +11,8 @@ declare(strict_types=1);
namespace Chill\DocStoreBundle; namespace Chill\DocStoreBundle;
use Chill\DocStoreBundle\GenericDoc\ProviderForAccompanyingPeriodInterface; use Chill\DocStoreBundle\GenericDoc\GenericDocForAccompanyingPeriodProviderInterface;
use Chill\DocStoreBundle\GenericDoc\Twig\GenericDocRendererInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\HttpKernel\Bundle\Bundle; use Symfony\Component\HttpKernel\Bundle\Bundle;
@ -19,7 +20,9 @@ class ChillDocStoreBundle extends Bundle
{ {
public function build(ContainerBuilder $container) public function build(ContainerBuilder $container)
{ {
$container->registerForAutoconfiguration(ProviderForAccompanyingPeriodInterface::class) $container->registerForAutoconfiguration(GenericDocForAccompanyingPeriodProviderInterface::class)
->addTag('chill_doc_store.generic_doc_accompanying_period_provider'); ->addTag('chill_doc_store.generic_doc_accompanying_period_provider');
$container->registerForAutoconfiguration(GenericDocRendererInterface::class)
->addTag('chill_doc_store.generic_doc_renderer');
} }
} }

View File

@ -13,17 +13,22 @@ namespace Chill\DocStoreBundle\Controller;
use Chill\DocStoreBundle\GenericDoc\Manager; use Chill\DocStoreBundle\GenericDoc\Manager;
use Chill\DocStoreBundle\Security\Authorization\AccompanyingCourseDocumentVoter; use Chill\DocStoreBundle\Security\Authorization\AccompanyingCourseDocumentVoter;
use Chill\MainBundle\Pagination\PaginatorFactory;
use Chill\PersonBundle\Entity\AccompanyingPeriod; use Chill\PersonBundle\Entity\AccompanyingPeriod;
use Symfony\Bundle\TwigBundle\TwigEngine;
use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException; use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
use Symfony\Component\Routing\Annotation\Route; use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Security\Core\Security; use Symfony\Component\Security\Core\Security;
use Symfony\Component\Templating\EngineInterface;
final readonly class GenericDocForAccompanyingPeriodController final readonly class GenericDocForAccompanyingPeriodController
{ {
public function __construct( public function __construct(
private Security $security, private Security $security,
private Manager $manager private Manager $manager,
private PaginatorFactory $paginator,
private EngineInterface $twig,
) { ) {
} }
@ -41,12 +46,21 @@ final readonly class GenericDocForAccompanyingPeriodController
} }
$nb = $this->manager->countDocForAccompanyingPeriod($accompanyingPeriod); $nb = $this->manager->countDocForAccompanyingPeriod($accompanyingPeriod);
$paginator = $this->paginator->create($nb);
$documents = $this->manager->findDocForAccompanyingPeriod(
$accompanyingPeriod,
$paginator->getCurrentPageFirstItemNumber(),
$paginator->getItemsPerPage()
);
foreach ($this->manager->findDocForAccompanyingPeriod($accompanyingPeriod) as $dto) { return new Response($this->twig->render(
dump($dto); '@ChillDocStore/GenericDoc/accompanying_period_list.html.twig',
} [
'accompanyingCourse' => $accompanyingPeriod,
return new Response($nb); 'pagination' => $paginator,
'documents' => iterator_to_array($documents),
]
));
} }
} }

View File

@ -11,12 +11,16 @@ declare(strict_types=1);
namespace Chill\DocStoreBundle\GenericDoc; namespace Chill\DocStoreBundle\GenericDoc;
use Chill\PersonBundle\Entity\AccompanyingPeriod;
use Chill\PersonBundle\Entity\Person;
class GenericDocDTO class GenericDocDTO
{ {
public function __construct( public function __construct(
public readonly string $key, public readonly string $key,
public readonly array $identifiers, public readonly array $identifiers,
public readonly \DateTimeImmutable $docDate public readonly \DateTimeImmutable $docDate,
public AccompanyingPeriod|Person $linked,
) { ) {
} }
} }

View File

@ -13,7 +13,7 @@ namespace Chill\DocStoreBundle\GenericDoc;
use Chill\PersonBundle\Entity\AccompanyingPeriod; use Chill\PersonBundle\Entity\AccompanyingPeriod;
interface ProviderForAccompanyingPeriodInterface interface GenericDocForAccompanyingPeriodProviderInterface
{ {
public function buildFetchQueryForAccompanyingPeriod( public function buildFetchQueryForAccompanyingPeriod(
AccompanyingPeriod $accompanyingPeriod, AccompanyingPeriod $accompanyingPeriod,

View File

@ -23,7 +23,7 @@ class Manager
public function __construct( public function __construct(
/** /**
* @var iterable<ProviderForAccompanyingPeriodInterface> * @var iterable<GenericDocForAccompanyingPeriodProviderInterface>
*/ */
private readonly iterable $providersForAccompanyingPeriod, private readonly iterable $providersForAccompanyingPeriod,
private readonly Connection $connection, private readonly Connection $connection,
@ -81,7 +81,8 @@ class Manager
yield new GenericDocDTO( yield new GenericDocDTO(
$row['key'], $row['key'],
json_decode($row['identifiers'], true, JSON_THROW_ON_ERROR), json_decode($row['identifiers'], true, JSON_THROW_ON_ERROR),
new \DateTimeImmutable($row['doc_date']) new \DateTimeImmutable($row['doc_date']),
$accompanyingPeriod,
); );
} }
} }

View File

@ -14,15 +14,17 @@ namespace Chill\DocStoreBundle\GenericDoc\Providers;
use Chill\DocStoreBundle\Entity\AccompanyingCourseDocument; use Chill\DocStoreBundle\Entity\AccompanyingCourseDocument;
use Chill\DocStoreBundle\GenericDoc\FetchQuery; use Chill\DocStoreBundle\GenericDoc\FetchQuery;
use Chill\DocStoreBundle\GenericDoc\FetchQueryInterface; use Chill\DocStoreBundle\GenericDoc\FetchQueryInterface;
use Chill\DocStoreBundle\GenericDoc\ProviderForAccompanyingPeriodInterface; use Chill\DocStoreBundle\GenericDoc\GenericDocForAccompanyingPeriodProviderInterface;
use Chill\DocStoreBundle\Security\Authorization\AccompanyingCourseDocumentVoter; use Chill\DocStoreBundle\Security\Authorization\AccompanyingCourseDocumentVoter;
use Chill\PersonBundle\Entity\AccompanyingPeriod; use Chill\PersonBundle\Entity\AccompanyingPeriod;
use Doctrine\DBAL\Types\Types; use Doctrine\DBAL\Types\Types;
use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\Security\Core\Security; use Symfony\Component\Security\Core\Security;
final readonly class AccompanyingCourseDocumentProvider implements ProviderForAccompanyingPeriodInterface final readonly class AccompanyingProviderCourseDocumentGenericDoc implements GenericDocForAccompanyingPeriodProviderInterface
{ {
public const KEY = 'accompanying_course_document';
public function __construct( public function __construct(
private Security $security, private Security $security,
private EntityManagerInterface $entityManager, private EntityManagerInterface $entityManager,
@ -34,7 +36,7 @@ final readonly class AccompanyingCourseDocumentProvider implements ProviderForAc
$classMetadata = $this->entityManager->getClassMetadata(AccompanyingCourseDocument::class); $classMetadata = $this->entityManager->getClassMetadata(AccompanyingCourseDocument::class);
$query = new FetchQuery( $query = new FetchQuery(
'accompanying_course_document', self::KEY,
sprintf('jsonb_build_object(\'id\', %s)', $classMetadata->getIdentifierColumnNames()[0]), sprintf('jsonb_build_object(\'id\', %s)', $classMetadata->getIdentifierColumnNames()[0]),
sprintf($classMetadata->getColumnName('date')), sprintf($classMetadata->getColumnName('date')),
$classMetadata->getSchemaName() . '.' . $classMetadata->getTableName() $classMetadata->getSchemaName() . '.' . $classMetadata->getTableName()

View File

@ -0,0 +1,44 @@
<?php
declare(strict_types=1);
/*
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\DocStoreBundle\GenericDoc\Renderer;
use Chill\DocStoreBundle\GenericDoc\GenericDocDTO;
use Chill\DocStoreBundle\GenericDoc\Twig\GenericDocRendererInterface;
use Chill\DocStoreBundle\GenericDoc\Providers\AccompanyingProviderCourseDocumentGenericDoc;
use Chill\DocStoreBundle\Repository\AccompanyingCourseDocumentRepository;
final readonly class AccompanyingCourseDocumentGenericDocRenderer implements GenericDocRendererInterface
{
public function __construct(
private AccompanyingCourseDocumentRepository $accompanyingCourseDocumentRepository,
) {
}
public function supports(GenericDocDTO $genericDocDTO, $options = []): bool
{
return $genericDocDTO->key === AccompanyingProviderCourseDocumentGenericDoc::KEY;
}
public function getTemplate(GenericDocDTO $genericDocDTO, $options = []): string
{
return '@ChillDocStore/List/list_item.html.twig';
}
public function getTemplateData(GenericDocDTO $genericDocDTO, $options = []): array
{
return [
'document' => $this->accompanyingCourseDocumentRepository->find($genericDocDTO->identifiers['id']),
'accompanyingCourse' => $genericDocDTO->linked,
'options' => $options,
];
}
}

View File

@ -0,0 +1,28 @@
<?php
declare(strict_types=1);
/*
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\DocStoreBundle\GenericDoc\Twig;
use Twig\Extension\AbstractExtension;
use Twig\TwigFilter;
final class GenericDocExtension extends AbstractExtension
{
public function getFilters()
{
return [
new TwigFilter('chill_generic_doc_render', [GenericDocExtensionRuntime::class, 'renderGenericDoc'], [
'needs_environment' => true,
'is_safe' => ['html'],
])
];
}
}

View File

@ -0,0 +1,50 @@
<?php
declare(strict_types=1);
/*
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\DocStoreBundle\GenericDoc\Twig;
use Chill\DocStoreBundle\GenericDoc\GenericDocDTO;
use Twig\Environment;
use Twig\Error\LoaderError;
use Twig\Error\RuntimeError;
use Twig\Error\SyntaxError;
use Twig\Extension\RuntimeExtensionInterface;
final readonly class GenericDocExtensionRuntime implements RuntimeExtensionInterface
{
public function __construct(
/**
* @var list<GenericDocRendererInterface>
*/
private iterable $renderers,
) {
}
/**
* @throws RuntimeError
* @throws SyntaxError
* @throws LoaderError
*/
public function renderGenericDoc(Environment $twig, GenericDocDTO $genericDocDTO, array $options = []): string
{
foreach ($this->renderers as $renderer) {
if ($renderer->supports($genericDocDTO)) {
return $twig->render(
$renderer->getTemplate($genericDocDTO, $options),
$renderer->getTemplateData($genericDocDTO, $options),
);
}
}
throw new \LogicException("no renderer found");
}
}

View File

@ -0,0 +1,24 @@
<?php
declare(strict_types=1);
/*
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\DocStoreBundle\GenericDoc\Twig;
use Chill\DocStoreBundle\GenericDoc\GenericDocDTO;
interface GenericDocRendererInterface
{
public function supports(GenericDocDTO $genericDocDTO, $options = []): bool;
public function getTemplate(GenericDocDTO $genericDocDTO, $options = []): string;
public function getTemplateData(GenericDocDTO $genericDocDTO, $options = []): array;
}

View File

@ -0,0 +1,48 @@
{% extends "@ChillPerson/AccompanyingCourse/layout.html.twig" %}
{% set activeRouteKey = '' %}
{% block title %}
{{ 'Documents' }}
{% endblock %}
{% block js %}
{{ parent() }}
{{ encore_entry_script_tags('mod_entity_workflow_pick') }}
{{ encore_entry_script_tags('mod_document_action_buttons_group') }}
{% endblock %}
{% block css %}
{{ parent() }}
{{ encore_entry_link_tags('mod_entity_workflow_pick') }}
{{ encore_entry_link_tags('mod_document_action_buttons_group') }}
{% endblock %}
{% block content %}
<div class="document-list">
<h1>{{ 'Documents' }}</h1>
{% if documents|length == 0 %}
<p class="chill-no-data-statement">{{ 'No documents'|trans }}</p>
{% else %}
<div class="flex-table chill-task-list">
{% for document in documents %}
{{ document|chill_generic_doc_render }}
{% endfor %}
</div>
{% endif %}
{{ chill_pagination(pagination) }}
{% if is_granted('CHILL_ACCOMPANYING_COURSE_DOCUMENT_CREATE', accompanyingCourse) %}
<ul class="record_actions sticky-form-buttons">
<li class="create">
<a href="{{ path('accompanying_course_document_new', {'course': accompanyingCourse.id}) }}" class="btn btn-create">
{{ 'Create'|trans }}
</a>
</li>
</ul>
{% endif %}
</div>
{% endblock %}

View File

@ -15,7 +15,7 @@ use Chill\DocStoreBundle\GenericDoc\FetchQuery;
use Chill\DocStoreBundle\GenericDoc\FetchQueryInterface; use Chill\DocStoreBundle\GenericDoc\FetchQueryInterface;
use Chill\DocStoreBundle\GenericDoc\GenericDocDTO; use Chill\DocStoreBundle\GenericDoc\GenericDocDTO;
use Chill\DocStoreBundle\GenericDoc\Manager; use Chill\DocStoreBundle\GenericDoc\Manager;
use Chill\DocStoreBundle\GenericDoc\ProviderForAccompanyingPeriodInterface; use Chill\DocStoreBundle\GenericDoc\GenericDocForAccompanyingPeriodProviderInterface;
use Chill\PersonBundle\Entity\AccompanyingPeriod; use Chill\PersonBundle\Entity\AccompanyingPeriod;
use Doctrine\DBAL\Connection; use Doctrine\DBAL\Connection;
use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityManagerInterface;
@ -52,7 +52,7 @@ class ManagerTest extends KernelTestCase
} }
$manager = new Manager( $manager = new Manager(
[new SimpleProvider()], [new SimpleGenericDocProvider()],
$this->connection, $this->connection,
); );
@ -72,7 +72,7 @@ class ManagerTest extends KernelTestCase
} }
$manager = new Manager( $manager = new Manager(
[new SimpleProvider()], [new SimpleGenericDocProvider()],
$this->connection, $this->connection,
); );
@ -82,7 +82,7 @@ class ManagerTest extends KernelTestCase
} }
} }
final readonly class SimpleProvider implements ProviderForAccompanyingPeriodInterface final readonly class SimpleGenericDocProvider implements GenericDocForAccompanyingPeriodProviderInterface
{ {
public function buildFetchQueryForAccompanyingPeriod(AccompanyingPeriod $accompanyingPeriod, ?\DateTimeImmutable $startDate = null, ?\DateTimeImmutable $endDate = null, ?string $content = null, ?string $origin = null): FetchQueryInterface public function buildFetchQueryForAccompanyingPeriod(AccompanyingPeriod $accompanyingPeriod, ?\DateTimeImmutable $startDate = null, ?\DateTimeImmutable $endDate = null, ?string $content = null, ?string $origin = null): FetchQueryInterface
{ {

View File

@ -12,7 +12,7 @@ declare(strict_types=1);
namespace Chill\DocStoreBundle\Tests\GenericDoc\Providers; namespace Chill\DocStoreBundle\Tests\GenericDoc\Providers;
use Chill\DocStoreBundle\GenericDoc\FetchQueryToSqlBuilder; use Chill\DocStoreBundle\GenericDoc\FetchQueryToSqlBuilder;
use Chill\DocStoreBundle\GenericDoc\Providers\AccompanyingCourseDocumentProvider; use Chill\DocStoreBundle\GenericDoc\Providers\AccompanyingProviderCourseDocumentGenericDoc;
use Chill\DocStoreBundle\Security\Authorization\AccompanyingCourseDocumentVoter; use Chill\DocStoreBundle\Security\Authorization\AccompanyingCourseDocumentVoter;
use Chill\PersonBundle\Entity\AccompanyingPeriod; use Chill\PersonBundle\Entity\AccompanyingPeriod;
use Doctrine\DBAL\Types\Types; use Doctrine\DBAL\Types\Types;
@ -54,7 +54,7 @@ class AccompanyingCourseDocumentProviderTest extends KernelTestCase
$security->isGranted(AccompanyingCourseDocumentVoter::SEE, $period) $security->isGranted(AccompanyingCourseDocumentVoter::SEE, $period)
->willReturn(true); ->willReturn(true);
$provider = new AccompanyingCourseDocumentProvider( $provider = new AccompanyingProviderCourseDocumentGenericDoc(
$security->reveal(), $security->reveal(),
$this->entityManager $this->entityManager
); );

View File

@ -9,7 +9,7 @@ services:
Chill\DocStoreBundle\Form\DocumentCategoryType: Chill\DocStoreBundle\Form\DocumentCategoryType:
class: Chill\DocStoreBundle\Form\DocumentCategoryType class: Chill\DocStoreBundle\Form\DocumentCategoryType
arguments: ["%kernel.bundles%"] arguments: [ "%kernel.bundles%" ]
tags: tags:
- { name: form.type } - { name: form.type }
@ -51,7 +51,22 @@ services:
arguments: arguments:
$providersForAccompanyingPeriod: !tagged_iterator chill_doc_store.generic_doc_accompanying_period_provider $providersForAccompanyingPeriod: !tagged_iterator chill_doc_store.generic_doc_accompanying_period_provider
Chill\DocStoreBundle\GenericDoc\Twig\GenericDocExtension:
autoconfigure: true
autowire: true
Chill\DocStoreBundle\GenericDoc\Twig\GenericDocExtensionRuntime:
autoconfigure: true
autowire: true
arguments:
$renderers: !tagged_iterator chill_doc_store.generic_doc_renderer
Chill\DocStoreBundle\GenericDoc\Providers\: Chill\DocStoreBundle\GenericDoc\Providers\:
autowire: true autowire: true
autoconfigure: true autoconfigure: true
resource: '../GenericDoc/Providers/' resource: '../GenericDoc/Providers/'
Chill\DocStoreBundle\GenericDoc\Renderer\:
autowire: true
autoconfigure: true
resource: '../GenericDoc/Renderer/'