Skip to content

Commit

Permalink
Signing authority form (#1047)
Browse files Browse the repository at this point in the history
  • Loading branch information
mmarchois authored Nov 7, 2024
1 parent 4c52c6b commit f38c459
Show file tree
Hide file tree
Showing 23 changed files with 665 additions and 7 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?xml version="1.0" encoding="UTF-8"?>
<constraint-mapping xmlns="http://symfony.com/schema/dic/constraint-mapping"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://symfony.com/schema/dic/constraint-mapping https://symfony.com/schema/dic/constraint-mapping/constraint-mapping-1.0.xsd">
<class name="App\Application\Organization\SigningAuthority\Command\SaveSigningAuthorityCommand">
<property name="name">
<constraint name="NotBlank"/>
<constraint name="Length">
<option name="max">100</option>
</constraint>
</property>
<property name="placeOfSignature">
<constraint name="NotBlank"/>
<constraint name="Length">
<option name="max">100</option>
</constraint>
</property>
<property name="signatoryName">
<constraint name="NotBlank"/>
<constraint name="Length">
<option name="max">100</option>
</constraint>
</property>
<property name="address">
<constraint name="NotBlank"/>
</property>
</class>
</constraint-mapping>
Binary file added public/images/signing_authority.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?php

declare(strict_types=1);

namespace App\Application\Organization\SigningAuthority\Command;

use App\Application\CommandInterface;
use App\Domain\Organization\SigningAuthority\SigningAuthority;
use App\Domain\User\Organization;

final class SaveSigningAuthorityCommand implements CommandInterface
{
public ?string $name = null;
public ?string $address = null;
public ?string $placeOfSignature = null;
public ?string $signatoryName = null;

public function __construct(
public readonly Organization $organization,
public readonly ?SigningAuthority $signingAuthority = null,
) {
$this->name = $signingAuthority?->getName();
$this->address = $signingAuthority?->getAddress();
$this->placeOfSignature = $signingAuthority?->getPlaceOfSignature();
$this->signatoryName = $signingAuthority?->getSignatoryName();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<?php

declare(strict_types=1);

namespace App\Application\Organization\SigningAuthority\Command;

use App\Application\IdFactoryInterface;
use App\Domain\Organization\SigningAuthority\Repository\SigningAuthorityRepositoryInterface;
use App\Domain\Organization\SigningAuthority\SigningAuthority;

final class SaveSigningAuthorityCommandHandler
{
public function __construct(
private IdFactoryInterface $idFactory,
private SigningAuthorityRepositoryInterface $signingAuthorityRepository,
) {
}

public function __invoke(SaveSigningAuthorityCommand $command): SigningAuthority
{
if ($signingAuthority = $command->signingAuthority) {
$signingAuthority->update(
name: $command->name,
address: $command->address,
placeOfSignature: $command->placeOfSignature,
signatoryName: $command->signatoryName,
);

return $signingAuthority;
}

return $this->signingAuthorityRepository->add(
new SigningAuthority(
uuid: $this->idFactory->make(),
name: $command->name,
address: $command->address,
placeOfSignature: $command->placeOfSignature,
signatoryName: $command->signatoryName,
organization: $command->organization,
),
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?php

declare(strict_types=1);

namespace App\Application\Organization\SigningAuthority\Query;

use App\Application\QueryInterface;

final class GetSigningAuthorityByOrganizationQuery implements QueryInterface
{
public function __construct(
public readonly string $organizationUuid,
) {
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?php

declare(strict_types=1);

namespace App\Application\Organization\SigningAuthority\Query;

use App\Domain\Organization\SigningAuthority\Repository\SigningAuthorityRepositoryInterface;
use App\Domain\Organization\SigningAuthority\SigningAuthority;

final class GetSigningAuthorityByOrganizationQueryHandler
{
public function __construct(
private SigningAuthorityRepositoryInterface $signingAuthorityRepository,
) {
}

public function __invoke(GetSigningAuthorityByOrganizationQuery $query): ?SigningAuthority
{
return $this->signingAuthorityRepository->findOneByOrganizationUuid($query->organizationUuid);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?php

declare(strict_types=1);

namespace App\Domain\Organization\SigningAuthority\Repository;

use App\Domain\Organization\SigningAuthority\SigningAuthority;

interface SigningAuthorityRepositoryInterface
{
public function findOneByOrganizationUuid(string $organizationUuid): ?SigningAuthority;

public function add(SigningAuthority $signingAuthority): SigningAuthority;
}
12 changes: 12 additions & 0 deletions src/Domain/Organization/SigningAuthority/SigningAuthority.php
Original file line number Diff line number Diff line change
Expand Up @@ -47,4 +47,16 @@ public function getOrganization(): Organization
{
return $this->organization;
}

public function update(
string $name,
string $address,
string $placeOfSignature,
string $signatoryName,
): void {
$this->name = $name;
$this->address = $address;
$this->placeOfSignature = $placeOfSignature;
$this->signatoryName = $signatoryName;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
<?php

declare(strict_types=1);

namespace App\Infrastructure\Controller\MyArea\Organization\SigningAuthority;

use App\Application\CommandBusInterface;
use App\Application\Organization\SigningAuthority\Command\SaveSigningAuthorityCommand;
use App\Application\Organization\SigningAuthority\Query\GetSigningAuthorityByOrganizationQuery;
use App\Application\QueryBusInterface;
use App\Infrastructure\Controller\MyArea\Organization\AbstractOrganizationController;
use App\Infrastructure\Form\Organization\SigningAuthorityFormType;
use App\Infrastructure\Security\Voter\OrganizationVoter;
use Symfony\Bundle\SecurityBundle\Security;
use Symfony\Component\Form\FormFactoryInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Routing\Requirement\Requirement;
use Symfony\Component\Routing\RouterInterface;

final class EditSigningAuthorityController extends AbstractOrganizationController
{
public function __construct(
private \Twig\Environment $twig,
private FormFactoryInterface $formFactory,
private RouterInterface $router,
private CommandBusInterface $commandBus,
QueryBusInterface $queryBus,
Security $security,
) {
parent::__construct($queryBus, $security);
}

#[Route(
'/organizations/{uuid}/signing_authority/edit',
name: 'app_config_signing_authority_edit',
requirements: ['uuid' => Requirement::UUID],
methods: ['GET', 'POST'],
)]
public function __invoke(Request $request, string $uuid): Response
{
$organization = $this->getOrganization($uuid);

if (!$this->security->isGranted(OrganizationVoter::EDIT, $organization)) {
throw new AccessDeniedHttpException();
}

$signingAuthority = $this->queryBus->handle(new GetSigningAuthorityByOrganizationQuery($uuid));
$command = new SaveSigningAuthorityCommand($organization, $signingAuthority);
$form = $this->formFactory->create(SigningAuthorityFormType::class, $command);
$form->handleRequest($request);

if ($form->isSubmitted() && $form->isValid()) {
$this->commandBus->handle($command);

return new RedirectResponse(
url: $this->router->generate('app_config_signing_authority_edit', ['uuid' => $uuid]),
status: Response::HTTP_SEE_OTHER,
);
}

return new Response(
content: $this->twig->render(
name: 'my_area/organization/signing_authority/form.html.twig',
context: [
'organization' => $organization,
'form' => $form->createView(),
],
),
status: ($form->isSubmitted() && !$form->isValid())
? Response::HTTP_UNPROCESSABLE_ENTITY
: Response::HTTP_OK,
);
}
}
58 changes: 58 additions & 0 deletions src/Infrastructure/Form/Organization/SigningAuthorityFormType.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
<?php

declare(strict_types=1);

namespace App\Infrastructure\Form\Organization;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface;

final class SigningAuthorityFormType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder
->add(
'name',
TextType::class,
options: [
'label' => 'signing_authority.name',
'help' => 'signing_authority.name.help',
],
)
->add(
'address',
TextareaType::class,
options: [
'label' => 'signing_authority.address',
'help' => 'signing_authority.address.help',
],
)
->add(
'placeOfSignature',
TextType::class,
options: [
'label' => 'signing_authority.placeOfSignature',
'help' => 'signing_authority.placeOfSignature.help',
],
)
->add(
'signatoryName',
TextType::class,
options: [
'label' => 'signing_authority.signatoryName',
'help' => 'signing_authority.signatoryName.help',
],
)
->add('save', SubmitType::class,
options: [
'label' => 'common.save',
'attr' => ['class' => 'fr-btn'],
],
)
;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<?php

declare(strict_types=1);

namespace App\Infrastructure\Persistence\Doctrine\Repository\SigningAuthority;

use App\Domain\Organization\SigningAuthority\Repository\SigningAuthorityRepositoryInterface;
use App\Domain\Organization\SigningAuthority\SigningAuthority;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry;

final class SigningAuthorityRepository extends ServiceEntityRepository implements SigningAuthorityRepositoryInterface
{
public function __construct(ManagerRegistry $registry)
{
parent::__construct($registry, SigningAuthority::class);
}

public function add(SigningAuthority $signingAuthority): SigningAuthority
{
$this->getEntityManager()->persist($signingAuthority);

return $signingAuthority;
}

public function findOneByOrganizationUuid(string $organizationUuid): ?SigningAuthority
{
return $this->createQueryBuilder('s')
->where('s.organization = :uuid')
->setParameter('uuid', $organizationUuid)
->setMaxResults(1)
->getQuery()
->getOneOrNullResult()
;
}
}
6 changes: 4 additions & 2 deletions templates/my_area/organization/_menu.html.twig
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
</a>
</li>
<li class="fr-sidemenu__item">
<button class="fr-sidemenu__btn" aria-expanded="{{ 'app_config_visa' in routeName ? 'true' : 'false' }}" aria-controls="sidemenu-config">{{ 'config.menu.regulations'|trans }}</button>
<button class="fr-sidemenu__btn" aria-expanded="{{ 'app_config_visa' in routeName or 'app_config_signing_authority' in routeName ? 'true' : 'false' }}" aria-controls="sidemenu-config">{{ 'config.menu.regulations'|trans }}</button>
<div class="fr-collapse" id="sidemenu-config">
<ul class="fr-sidemenu__list">
<li class="fr-sidemenu__item">
Expand All @@ -26,7 +26,9 @@
</a>
</li>
<li class="fr-sidemenu__item">
<a class="fr-sidemenu__link href="#" target="_self">{{ 'config.menu.authority'|trans }}</a>
<a class="fr-sidemenu__link" href="{{ path('app_config_signing_authority_edit', {uuid: organization.uuid}) }}" aria-current="{{ 'app_config_signing_authority_edit' in routeName ? 'true' : 'false' }}">
{{ 'config.menu.authority'|trans }}
</a>
</li>
</ul>
</div>
Expand Down
Loading

0 comments on commit f38c459

Please sign in to comment.