Commit 3616eff5 authored by Thibaut Vallee's avatar Thibaut Vallee
Browse files

création du HistoriqueListener

parent 52556c6b
Loading
Loading
Loading
Loading
+6 −0
Changes for CHANGELOG.md: 6 added lines, 0 removed lines.
Original line number Diff line number Diff line
CHANGELOG
=========
0.2.6 (11/12/2025)
------------------
- Mise en place de l'HistoriqueListener pour gerer automatiquement les HistoCreation/HistoModification
- Suppression du HistoriqueStateProcessor devenue inutile
- Remplacement du trait HistoUserTrait par HistoUserRepository

0.2.5 (28/11/2025)
------------------
- Config : nouveau Paramétre unicaen.user_class et unicaen.role_class
+56 −0
Changes for api/src/Event/HistoriqueListener.php: 56 added lines, 0 removed lines.
Original line number Diff line number Diff line
<?php

namespace Unicaen\Utilisateur\Event;

use DateTime;
use Doctrine\Bundle\DoctrineBundle\Attribute\AsDoctrineListener;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\Events;
use Doctrine\Persistence\Event\LifecycleEventArgs;
use Symfony\Bundle\SecurityBundle\Security;
use Symfony\Component\DependencyInjection\ParameterBag\ContainerBagInterface;
use Unicaen\Utilisateur\Model\HistoriqueAwareInterface;
use Unicaen\Utilisateur\Repository\HistoUserRepository;

#[AsDoctrineListener(event: Events::prePersist, connection: 'default')]
#[AsDoctrineListener(event: Events::preUpdate, connection: 'default')]
class HistoriqueListener
{
    protected HistoUserRepository $histoUserRepository;
    public function __construct
    (
        HistoUserRepository $histoUserRepository
    ) {
        $this->histoUserRepository = $histoUserRepository;
    }

    /**
     * @throws \Exception
     */
    public function prePersist(LifecycleEventArgs $args)
    {
        $entity = $args->getObject();
        if (! $entity instanceof HistoriqueAwareInterface) {
            return;
        }
        $now = new DateTime();
        $user = $this->histoUserRepository->getHistoUser();
        $entity->setHistoCreation($now);
        $entity->setHistoCreateur($user);
    }

    /**
     * @throws \Exception
     */
    public function preUpdate(LifecycleEventArgs $args)
    {
        $entity = $args->getObject();
        if (! $entity instanceof HistoriqueAwareInterface) {
            return;
        }
        $now = new DateTime();
        $user = $this->histoUserRepository->getHistoUser();
        $entity->setHistoModification($now);
        $entity->setHistoModificateur($user);
    }
}
 No newline at end of file
+18 −14
Changes for api/src/Repository/HistoUserRepository.php: 18 added lines, 14 removed lines.
Original line number Diff line number Diff line
<?php

namespace Unicaen\Utilisateur\State;
namespace Unicaen\Utilisateur\Repository;

use Doctrine\ORM\EntityManagerInterface;
use Error;
use Exception;
use Doctrine\Persistence\ManagerRegistry;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Symfony\Bundle\SecurityBundle\Security;
use Symfony\Component\DependencyInjection\ParameterBag\ContainerBagInterface;
use Symfony\Component\Security\Core\User\UserInterface;
use Unicaen\Utilisateur\Entity\User;
use Error;
use Exception;


/**
 * Trait qui retourne si possible l'utilisateur pour le process
 * Soit l'utilisateur connecté, soit celui dont le code est fournis par le parametre histo.histo_default_username
 * Repository de UnicaenUtilisateur mais qui permet de déterminer l'utiliser à utiliser dans les champs d'historisation
 * Choix fait de ne pas l'intégrer directement dans UtilisateurRepository pour ne pas obliger des application n'utilisant pas de champs d'historisation d'avoir cette méthode spécigique
 */

/**
 * @var ?Security $security,
 * @var ?EntityManagerInterface $em,
 * @var ?ContainerBagInterface $params,
 */
Trait HistoUserTrait
class HistoUserRepository extends UtilisateurRepository
{
    public function __construct(
        private ManagerRegistry $registry,
        private Security $security,
        private ContainerBagInterface $param)
    {
        parent::__construct($registry, User::class);
    }

    const HISTO_DEFAULT_USERNAME = 'histo.histo_default_username';
    protected function getHistoUser() : ?UserInterface
    public function getHistoUser() : ?UserInterface
    {
        try {
            if (isset($this->security)) {
@@ -41,7 +45,7 @@ Trait HistoUserTrait
                catch (Exception|Error $e){
                    throw new Exception("Le paramétre config d'histo_user n'est pas définie");
                }
                $user = $this->em->getRepository(User::class)->findOneBy(['username' => $defaultUsername]);
                $user = $this->findOneBy(['username' => $defaultUsername]);
                if(!isset($user)){
                    throw new Exception("Utilisateur par défaut non trouvée");
                }
+0 −55
Changes for api/src/State/HistoriqueStateProcessor.php: 0 added lines, 55 removed lines.
Original line number Diff line number Diff line
<?php

namespace Unicaen\Utilisateur\State;
use ApiPlatform\Metadata\Operation;
use ApiPlatform\Metadata\Patch;
use ApiPlatform\Metadata\Post;
use ApiPlatform\State\ProcessorInterface;
use Unicaen\Utilisateur\Model\HistoriqueAwareInterface;
use Doctrine\ORM\EntityManagerInterface;
use Exception;
use Symfony\Bundle\SecurityBundle\Security;
use Symfony\Component\Clock\ClockInterface;
use Symfony\Component\DependencyInjection\Attribute\AsDecorator;
use Symfony\Component\DependencyInjection\ParameterBag\ContainerBagInterface;
use Unicaen\Utilisateur\Entity\User;

/**
 * @desc Lors d'une maj via doctrine d'une entité, on met a jour l'histoCreation/l'histoModification si elle exist
 */
#[AsDecorator('api_platform.doctrine.orm.state.persist_processor')]
class HistoriqueStateProcessor implements ProcessorInterface
{

    use HistoUserTrait;

    public function __construct
    (
        private ProcessorInterface $persistProcessor,
        private Security $security,
        private EntityManagerInterface $em,
        private ClockInterface $clock,
        private ContainerBagInterface $param
    ) {
    }

    public function process(mixed $data, Operation $operation, array $uriVariables = [], array $context = []): mixed
    {
        if($data instanceof HistoriqueAwareInterface){
            $user = $this->getHistoUser();
            $now = $this->clock->now();
            switch (true){
                case ($operation instanceof Post):
                    $data->setHistoCreation($now);
                    $data->setHistoCreateur($user);
                break;
                case ($operation instanceof Patch) :
                    $data->setHistoModification($now);
                    $data->setHistoModificateur($user);
                break;
            }
        }
        $data = $this->persistProcessor->process($data, $operation, $uriVariables, $context);
        return $data;
    }
}
+8 −12
Changes for api/src/State/HistoriserProcessor.php: 8 added lines, 12 removed lines.
Original line number Diff line number Diff line
@@ -4,22 +4,18 @@ namespace Unicaen\Utilisateur\State;

use ApiPlatform\Metadata\Operation;
use ApiPlatform\State\ProcessorInterface;
use Unicaen\Utilisateur\Model\HistoriqueAwareInterface;
use Doctrine\ORM\EntityManagerInterface;
use Unicaen\Utilisateur\Model\HistoriqueAwareInterface;
use Exception;
use Symfony\Bundle\SecurityBundle\Security;
use Symfony\Component\Clock\ClockInterface;
use Symfony\Component\DependencyInjection\ParameterBag\ContainerBagInterface;
use DateTime;
use Unicaen\Utilisateur\Repository\HistoUserRepository;

class HistoriserProcessor implements ProcessorInterface
{
    use HistoUserTrait;

    public function __construct(
        private Security $security,
        private EntityManagerInterface $em,
        private ClockInterface $clock,
        private ContainerBagInterface $param
        private HistoUserRepository $histoUserRepository
    ) {
    }

@@ -31,10 +27,10 @@ class HistoriserProcessor implements ProcessorInterface
        if(!$data instanceof HistoriqueAwareInterface){
            throw new Exception("L'entité doit implémenter HistoriqueAwareInterface pour permettre l'historisation");
        }
        $histoUser = $this->getHistoUser();
        $data->setHistoModificateur($histoUser);
        $data->setHistoDestructeur($histoUser);
        $now = $this->clock->now();
        $user = $this->histoUserRepository->getHistoUser();
        $data->setHistoModificateur($user);
        $data->setHistoDestructeur($user);
        $now = new DateTime();
        $data->setHistoModification($now);
        $data->setHistoDestruction($now);
        $this->em->persist($data);
Loading