src/Domain/Common/Lock/EditionConsultationLockHandler.php line 48

Open in your IDE?
  1. <?php
  2. declare(strict_types=1);
  3. namespace App\Domain\Common\Lock;
  4. use App\Domain\Common\Entity\Utilisateur;
  5. use App\Domain\Common\Repository\UtilisateurRepository;
  6. use App\Domain\Common\Traits\UserAwareTrait;
  7. use App\Domain\Machine\Cache\MachineCacheManager;
  8. use App\Infrastructure\Controller\Common\BaseController;
  9. use Psr\Log\LoggerInterface;
  10. use Symfony\Component\Cache\Adapter\PdoAdapter;
  11. use Symfony\Component\Cache\CacheItem;
  12. use Symfony\Component\HttpFoundation\Session\Flash\FlashBagInterface;
  13. use Symfony\Component\HttpFoundation\Session\SessionInterface;
  14. use Symfony\Contracts\Translation\TranslatorInterface;
  15. class EditionConsultationLockHandler
  16. {
  17.     protected const KEY_PREFIX_BY_RESOURCE 'edition_consultation_resource';
  18.     protected const KEY_PREFIX_BY_USER 'edition_consultation_user';
  19.     protected const KEY_PREFIX_BY_MACHINE 'edition_consultation_machine';
  20.     protected const SESSION_KEY_FORCE_UNLOCK 'forceUnlock';
  21.     use UserAwareTrait;
  22.     private PdoAdapter $cache;
  23.     private FlashBagInterface $bag;
  24.     private UtilisateurRepository $utilisateurRepository;
  25.     private MachineCacheManager $machineCacheManager;
  26.     private TranslatorInterface $translator;
  27.     private SessionInterface $session;
  28.     private LoggerInterface $logger;
  29.     public function __construct(
  30.         PdoAdapter $cache,
  31.         UtilisateurRepository $utilisateurRepository,
  32.         SessionInterface $session,
  33.         MachineCacheManager $machineCacheManager,
  34.         TranslatorInterface $translator,
  35.         LoggerInterface $logger
  36.     )
  37.     {
  38.         $this->cache $cache;
  39.         $this->utilisateurRepository $utilisateurRepository;
  40.         $this->session $session;
  41.         $this->bag $session->getFlashBag();
  42.         $this->machineCacheManager $machineCacheManager;
  43.         $this->translator $translator;
  44.         $this->logger $logger;
  45.     }
  46.     public function acquireOrRefresh(int $consultationId): bool
  47.     {
  48.         $userId $this->cache->get($this->getLockKeyByRessource($consultationId), [$this->getUser(), 'getId']);
  49.         if ($userId === $this->getUser()->getId()) {
  50.             // l'user en question possede le lock
  51.             $this->removeLock($consultationId);
  52.             // on le refresh
  53.             $this->cache->get($this->getLockKeyByRessource($consultationId),  fn() => $userId);
  54.             $this->cache->get($this->getLockKeyByUser(), fn() => $consultationId);
  55.             if ($machine $this->machineCacheManager->get()) {
  56.                 $this->logger->info('Save lock engine', [
  57.                     'consultation_id' => $consultationId,
  58.                     'lock_engine_id' => $this->getLockKeyByMachine($consultationId),
  59.                     'engine_id' => $machine->getId(),
  60.                     'user_id' => $userId
  61.                 ]);
  62.                 $this->cache->get($this->getLockKeyByMachine($consultationId), fn() => $machine->getId());
  63.             }
  64.             return true;
  65.         }
  66.         $userWhoLockId $this->cache->get($this->getLockKeyByRessource($consultationId),  fn() => $userId);
  67.         $userWhoLockEntity $this->utilisateurRepository->find($userWhoLockId);
  68.         $this->bag->add(
  69.             BaseController::FLASH_ERROR,
  70.             $this->translator->trans('consultation.locked', ['%user%' => $userWhoLockEntity], 'flash')
  71.         );
  72.         return false;
  73.     }
  74.     public function releaseUserLock(): void
  75.     {
  76.         // TODO eventuellement stocker un test avant dans un cache plus rapide (session, redis ...)
  77.         // on relache le lock de l'user, s'il en a un
  78.         $consultationId $this->cache->get($this->getLockKeyByUser(), fn() => null);
  79.         $this->removeLock($consultationId);
  80.     }
  81.     public function consultationHasMachineLock(int $consultationId): bool
  82.     {
  83.         return $this->cache->hasItem($this->getLockKeyByMachine($consultationId));
  84.     }
  85.     public function getMachineIdLock(int $consultationId): ?int
  86.     {
  87.         if ($this->consultationHasMachineLock($consultationId)) {
  88.             /** @var CacheItem $cacheItem */
  89.             $cacheItem $this->cache->getItem($this->getLockKeyByMachine($consultationId));
  90.             return $cacheItem->get();
  91.         }
  92.         return null;
  93.     }
  94.     protected function removeLock(?int $consultationId null)
  95.     {
  96.         if ($consultationId) {
  97.             $this->logger->info('Delete lock engine', [
  98.                 'consultation_id' => $consultationId,
  99.                 'lock_engine_id' => $this->getLockKeyByMachine($consultationId)
  100.             ]);
  101.             $this->cache->delete($this->getLockKeyByRessource($consultationId));
  102.             $this->cache->delete($this->getLockKeyByMachine($consultationId));
  103.         }
  104.         $cacheConsultationId $this->cache->get($this->getLockKeyByUser(), fn() => $consultationId);
  105.         if ($cacheConsultationId && $cacheConsultationId !== $consultationId) {
  106.             $this->cache->delete($this->getLockKeyByRessource($cacheConsultationId));
  107.         }
  108.         $this->cache->delete($this->getLockKeyByUser());
  109.     }
  110.     protected function getLockKeyByRessource(int $id): string
  111.     {
  112.         return self::KEY_PREFIX_BY_RESOURCE '-' $id;
  113.     }
  114.     protected function getLockKeyByUser(): string
  115.     {
  116.         return self::KEY_PREFIX_BY_USER '-' $this->getUser()->getId();
  117.     }
  118.     protected function getLockKeyByMachine($consultationId): string
  119.     {
  120.         return self::KEY_PREFIX_BY_MACHINE '-' $consultationId;
  121.     }
  122.     public function getUserLock(int $consultationId): ?Utilisateur
  123.     {
  124.         $userId $this->cache->get($this->getLockKeyByRessource($consultationId), [$this->getUser(), 'getId']);
  125.         /** @var Utilisateur|null $user */
  126.         $user $this->utilisateurRepository->find($userId);
  127.         return $user;
  128.     }
  129.     public function forceSessionUnlockMode(): void
  130.     {
  131.         $this->session->set(self::SESSION_KEY_FORCE_UNLOCKtrue);
  132.     }
  133.     public function acquireSessionUnlockMode(): bool
  134.     {
  135.         if ($this->session->get(self::SESSION_KEY_FORCE_UNLOCKfalse) === true) {
  136.             $this->session->set(self::SESSION_KEY_FORCE_UNLOCKfalse);
  137.             return true;
  138.         }
  139.         return false;
  140.     }
  141. }