- contact@e-cosplay.fr remplace par client@e-cosplay.fr dans 87 fichiers (PDFs, templates, emails, controllers, DocuSeal submitters) - monitor@e-cosplay.fr remplace par notification@e-cosplay.fr dans 4 fichiers (webhooks DocuSeal, commandes DNS/NDD, controller echeancier) - Ajout lien "En savoir plus sur notre association" vers www.e-cosplay.fr sur la page migration SITECONSEIL Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
209 lines
8.2 KiB
PHP
209 lines
8.2 KiB
PHP
<?php
|
|
|
|
namespace App\Controller\Admin;
|
|
|
|
use App\Entity\AttestationCustom;
|
|
use App\Service\DocuSealService;
|
|
use App\Service\Pdf\AttestationCustomPdf;
|
|
use Doctrine\ORM\EntityManagerInterface;
|
|
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
|
use Symfony\Component\HttpFoundation\File\UploadedFile;
|
|
use Symfony\Component\HttpFoundation\Request;
|
|
use Symfony\Component\HttpFoundation\Response;
|
|
use Symfony\Component\HttpKernel\KernelInterface;
|
|
use Symfony\Component\Routing\Attribute\Route;
|
|
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
|
|
use Symfony\Component\Security\Http\Attribute\IsGranted;
|
|
|
|
#[Route('/admin/attestations', name: 'app_admin_attestation_custom_')]
|
|
#[IsGranted('ROLE_ROOT')]
|
|
class AttestationCustomController extends AbstractController
|
|
{
|
|
public function __construct(
|
|
private EntityManagerInterface $em,
|
|
) {
|
|
}
|
|
|
|
#[Route('', name: 'index')]
|
|
public function index(): Response
|
|
{
|
|
$attestations = $this->em->getRepository(AttestationCustom::class)->findBy([], ['createdAt' => 'DESC']);
|
|
|
|
return $this->render('admin/attestation_custom/index.html.twig', [
|
|
'attestations' => $attestations,
|
|
]);
|
|
}
|
|
|
|
#[Route('/create', name: 'create', methods: ['POST'])]
|
|
public function create(Request $request, KernelInterface $kernel, UrlGeneratorInterface $urlGenerator): Response
|
|
{
|
|
$title = trim($request->request->getString('title'));
|
|
$itemsRaw = $request->request->all('items');
|
|
|
|
// Filtrer les items vides
|
|
$items = array_values(array_filter(array_map('trim', $itemsRaw), fn (string $v) => '' !== $v));
|
|
|
|
if ('' === $title || [] === $items) {
|
|
$this->addFlash('error', 'Le titre et au moins un element sont requis.');
|
|
|
|
return $this->redirectToRoute('app_admin_attestation_custom_index');
|
|
}
|
|
|
|
$attestation = new AttestationCustom($title, $items);
|
|
$this->em->persist($attestation);
|
|
$this->em->flush();
|
|
|
|
// Generer le PDF
|
|
$this->generatePdfForAttestation($attestation, $kernel, $urlGenerator);
|
|
|
|
$this->addFlash('success', 'Attestation '.$attestation->getReference().' creee.');
|
|
|
|
return $this->redirectToRoute('app_admin_attestation_custom_show', ['id' => $attestation->getId()]);
|
|
}
|
|
|
|
#[Route('/{id}', name: 'show', requirements: ['id' => '\d+'])]
|
|
public function show(int $id): Response
|
|
{
|
|
$attestation = $this->em->getRepository(AttestationCustom::class)->find($id);
|
|
if (null === $attestation) {
|
|
throw $this->createNotFoundException('Attestation introuvable');
|
|
}
|
|
|
|
return $this->render('admin/attestation_custom/show.html.twig', [
|
|
'attestation' => $attestation,
|
|
]);
|
|
}
|
|
|
|
#[Route('/{id}/regenerate-pdf', name: 'regenerate_pdf', requirements: ['id' => '\d+'], methods: ['POST'])]
|
|
public function regeneratePdf(int $id, KernelInterface $kernel, UrlGeneratorInterface $urlGenerator): Response
|
|
{
|
|
$attestation = $this->em->getRepository(AttestationCustom::class)->find($id);
|
|
if (null === $attestation) {
|
|
throw $this->createNotFoundException('Attestation introuvable');
|
|
}
|
|
|
|
$this->generatePdfForAttestation($attestation, $kernel, $urlGenerator);
|
|
$this->addFlash('success', 'PDF regenere.');
|
|
|
|
return $this->redirectToRoute('app_admin_attestation_custom_show', ['id' => $id]);
|
|
}
|
|
|
|
/**
|
|
* Envoie le PDF a DocuSeal pour signature manuelle et redirige vers DocuSeal.
|
|
*/
|
|
#[Route('/{id}/sign', name: 'sign', requirements: ['id' => '\d+'], methods: ['POST'])]
|
|
public function sign(
|
|
int $id,
|
|
DocuSealService $docuSeal,
|
|
#[\Symfony\Component\DependencyInjection\Attribute\Autowire('%kernel.project_dir%')] string $projectDir,
|
|
#[\Symfony\Component\DependencyInjection\Attribute\Autowire(env: 'DOCUSEAL_URL')] string $docuSealUrl,
|
|
\Symfony\Component\Routing\Generator\UrlGeneratorInterface $urlGenerator,
|
|
): Response {
|
|
$attestation = $this->em->getRepository(AttestationCustom::class)->find($id);
|
|
if (null === $attestation) {
|
|
throw $this->createNotFoundException('Attestation introuvable');
|
|
}
|
|
|
|
if (null === $attestation->getPdfUnsigned()) {
|
|
$this->addFlash('error', 'Le PDF doit etre genere avant la signature.');
|
|
|
|
return $this->redirectToRoute('app_admin_attestation_custom_show', ['id' => $id]);
|
|
}
|
|
|
|
$pdfPath = $projectDir.'/public/uploads/attestations/'.$attestation->getPdfUnsigned();
|
|
if (!file_exists($pdfPath)) {
|
|
$this->addFlash('error', 'Fichier PDF introuvable.');
|
|
|
|
return $this->redirectToRoute('app_admin_attestation_custom_show', ['id' => $id]);
|
|
}
|
|
|
|
/** @var \App\Entity\User $user */
|
|
$user = $this->getUser();
|
|
|
|
$redirectUrl = $urlGenerator->generate('app_admin_attestation_custom_show', [
|
|
'id' => $attestation->getId(),
|
|
], \Symfony\Component\Routing\Generator\UrlGeneratorInterface::ABSOLUTE_URL);
|
|
|
|
// @codeCoverageIgnoreStart
|
|
try {
|
|
$pdfBase64 = base64_encode(file_get_contents($pdfPath));
|
|
|
|
$result = $docuSeal->getApi()->createSubmissionFromPdf([
|
|
'name' => 'Attestation '.$attestation->getReference().' - '.$attestation->getTitle(),
|
|
'send_email' => false,
|
|
'flatten' => true,
|
|
'documents' => [[
|
|
'name' => 'attestation-'.$attestation->getReference().'.pdf',
|
|
'file' => 'data:application/pdf;base64,'.$pdfBase64,
|
|
]],
|
|
'submitters' => [[
|
|
'email' => 'client@e-cosplay.fr',
|
|
'name' => 'Association E-Cosplay',
|
|
'role' => 'First Party',
|
|
'send_email' => false,
|
|
'completed_redirect_url' => $redirectUrl,
|
|
'metadata' => [
|
|
'doc_type' => 'attestation_custom',
|
|
'attestation_custom_id' => $attestation->getId(),
|
|
],
|
|
]],
|
|
]);
|
|
|
|
// DocuSeal retourne soit {submitters: [{id}]} soit [{id}]
|
|
$submitterId = $result['submitters'][0]['id']
|
|
?? ($result[0]['id'] ?? ($result['id'] ?? null));
|
|
|
|
if (null !== $submitterId) {
|
|
$slug = $docuSeal->getSubmitterSlug((int) $submitterId);
|
|
if (null !== $slug) {
|
|
return $this->redirect(rtrim($docuSealUrl, '/').'/s/'.$slug);
|
|
}
|
|
}
|
|
|
|
$this->addFlash('error', 'Erreur DocuSeal : impossible de recuperer le lien de signature. Reponse: '.json_encode($result));
|
|
} catch (\Throwable $e) {
|
|
$this->addFlash('error', 'Erreur DocuSeal : '.$e->getMessage());
|
|
}
|
|
// @codeCoverageIgnoreEnd
|
|
|
|
return $this->redirectToRoute('app_admin_attestation_custom_show', ['id' => $id]);
|
|
}
|
|
|
|
#[Route('/{id}/delete', name: 'delete', requirements: ['id' => '\d+'], methods: ['POST'])]
|
|
public function delete(int $id): Response
|
|
{
|
|
$attestation = $this->em->getRepository(AttestationCustom::class)->find($id);
|
|
if (null === $attestation) {
|
|
throw $this->createNotFoundException('Attestation introuvable');
|
|
}
|
|
|
|
$this->em->remove($attestation);
|
|
$this->em->flush();
|
|
|
|
$this->addFlash('success', 'Attestation supprimee.');
|
|
|
|
return $this->redirectToRoute('app_admin_attestation_custom_index');
|
|
}
|
|
|
|
private function generatePdfForAttestation(AttestationCustom $attestation, KernelInterface $kernel, UrlGeneratorInterface $urlGenerator): void
|
|
{
|
|
$pdf = new AttestationCustomPdf($kernel, $attestation, $urlGenerator);
|
|
$pdf->generate();
|
|
|
|
$tmpPath = tempnam(sys_get_temp_dir(), 'att_custom_').'.pdf';
|
|
$pdf->Output('F', $tmpPath);
|
|
|
|
$attestation->setPdfUnsignedFile(new UploadedFile(
|
|
$tmpPath,
|
|
'attestation-'.$attestation->getReference().'.pdf',
|
|
'application/pdf',
|
|
null,
|
|
true,
|
|
));
|
|
$attestation->setUpdatedAt(new \DateTimeImmutable());
|
|
$this->em->flush();
|
|
|
|
@unlink($tmpPath);
|
|
}
|
|
}
|