feat(shared) : add timestampable/blamable trait and doctrine subscriber
This commit is contained in:
+2
-1
@@ -13,6 +13,7 @@ use ApiPlatform\Metadata\Patch;
|
||||
use ApiPlatform\Metadata\Post;
|
||||
use App\Enum\ContractType;
|
||||
use App\Repository\UserRepository;
|
||||
use App\Shared\Domain\Contract\UserInterface as SharedUserInterface;
|
||||
use App\State\MeProvider;
|
||||
use App\State\UserPasswordHasherProcessor;
|
||||
use DateTimeImmutable;
|
||||
@@ -44,7 +45,7 @@ use Symfony\Component\Serializer\Attribute\Groups;
|
||||
)]
|
||||
#[ORM\Entity(repositoryClass: UserRepository::class)]
|
||||
#[ORM\Table(name: '`user`')]
|
||||
class User implements UserInterface, PasswordAuthenticatedUserInterface
|
||||
class User implements UserInterface, PasswordAuthenticatedUserInterface, SharedUserInterface
|
||||
{
|
||||
#[ORM\Id]
|
||||
#[ORM\GeneratedValue]
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Shared\Application;
|
||||
|
||||
use App\Shared\Domain\Contract\UserInterface;
|
||||
|
||||
interface CurrentUserProviderInterface
|
||||
{
|
||||
public function getCurrentUser(): ?UserInterface;
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Shared\Domain\Contract;
|
||||
|
||||
interface BlamableInterface
|
||||
{
|
||||
public function getCreatedBy(): ?UserInterface;
|
||||
|
||||
public function setCreatedBy(?UserInterface $user): void;
|
||||
|
||||
public function getUpdatedBy(): ?UserInterface;
|
||||
|
||||
public function setUpdatedBy(?UserInterface $user): void;
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Shared\Domain\Contract;
|
||||
|
||||
use DateTimeImmutable;
|
||||
|
||||
interface TimestampableInterface
|
||||
{
|
||||
public function getCreatedAt(): ?DateTimeImmutable;
|
||||
|
||||
public function setCreatedAt(DateTimeImmutable $createdAt): void;
|
||||
|
||||
public function getUpdatedAt(): ?DateTimeImmutable;
|
||||
|
||||
public function setUpdatedAt(DateTimeImmutable $updatedAt): void;
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Shared\Domain\Contract;
|
||||
|
||||
interface UserInterface
|
||||
{
|
||||
public function getId(): ?int;
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Shared\Domain\Trait;
|
||||
|
||||
use App\Shared\Domain\Contract\UserInterface;
|
||||
use DateTimeImmutable;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Symfony\Component\Serializer\Attribute\Groups;
|
||||
|
||||
trait TimestampableBlamableTrait
|
||||
{
|
||||
#[ORM\Column(name: 'created_at', type: 'datetime_immutable', nullable: true)]
|
||||
#[Groups(['timestampable:read'])]
|
||||
private ?DateTimeImmutable $createdAt = null;
|
||||
|
||||
#[ORM\Column(name: 'updated_at', type: 'datetime_immutable', nullable: true)]
|
||||
#[Groups(['timestampable:read'])]
|
||||
private ?DateTimeImmutable $updatedAt = null;
|
||||
|
||||
#[ORM\ManyToOne(targetEntity: UserInterface::class)]
|
||||
#[ORM\JoinColumn(name: 'created_by', referencedColumnName: 'id', nullable: true, onDelete: 'SET NULL')]
|
||||
#[Groups(['blamable:read'])]
|
||||
private ?UserInterface $createdBy = null;
|
||||
|
||||
#[ORM\ManyToOne(targetEntity: UserInterface::class)]
|
||||
#[ORM\JoinColumn(name: 'updated_by', referencedColumnName: 'id', nullable: true, onDelete: 'SET NULL')]
|
||||
#[Groups(['blamable:read'])]
|
||||
private ?UserInterface $updatedBy = null;
|
||||
|
||||
public function getCreatedAt(): ?DateTimeImmutable
|
||||
{
|
||||
return $this->createdAt;
|
||||
}
|
||||
|
||||
public function setCreatedAt(DateTimeImmutable $createdAt): void
|
||||
{
|
||||
$this->createdAt = $createdAt;
|
||||
}
|
||||
|
||||
public function getUpdatedAt(): ?DateTimeImmutable
|
||||
{
|
||||
return $this->updatedAt;
|
||||
}
|
||||
|
||||
public function setUpdatedAt(DateTimeImmutable $updatedAt): void
|
||||
{
|
||||
$this->updatedAt = $updatedAt;
|
||||
}
|
||||
|
||||
public function getCreatedBy(): ?UserInterface
|
||||
{
|
||||
return $this->createdBy;
|
||||
}
|
||||
|
||||
public function setCreatedBy(?UserInterface $user): void
|
||||
{
|
||||
$this->createdBy = $user;
|
||||
}
|
||||
|
||||
public function getUpdatedBy(): ?UserInterface
|
||||
{
|
||||
return $this->updatedBy;
|
||||
}
|
||||
|
||||
public function setUpdatedBy(?UserInterface $user): void
|
||||
{
|
||||
$this->updatedBy = $user;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Shared\Infrastructure\Doctrine;
|
||||
|
||||
use App\Shared\Application\CurrentUserProviderInterface;
|
||||
use App\Shared\Domain\Contract\BlamableInterface;
|
||||
use App\Shared\Domain\Contract\TimestampableInterface;
|
||||
use DateTimeImmutable;
|
||||
use Doctrine\Bundle\DoctrineBundle\Attribute\AsDoctrineListener;
|
||||
use Doctrine\ORM\Event\PrePersistEventArgs;
|
||||
use Doctrine\ORM\Event\PreUpdateEventArgs;
|
||||
use Doctrine\ORM\Events;
|
||||
|
||||
#[AsDoctrineListener(event: Events::prePersist)]
|
||||
#[AsDoctrineListener(event: Events::preUpdate)]
|
||||
final readonly class TimestampableBlamableSubscriber
|
||||
{
|
||||
public function __construct(
|
||||
private CurrentUserProviderInterface $currentUserProvider,
|
||||
) {}
|
||||
|
||||
public function prePersist(PrePersistEventArgs $args): void
|
||||
{
|
||||
$this->applyOnCreate($args->getObject());
|
||||
}
|
||||
|
||||
public function preUpdate(PreUpdateEventArgs $args): void
|
||||
{
|
||||
$this->applyOnUpdate($args->getObject());
|
||||
}
|
||||
|
||||
public function applyOnCreate(object $entity): void
|
||||
{
|
||||
$now = new DateTimeImmutable();
|
||||
|
||||
if ($entity instanceof TimestampableInterface) {
|
||||
if (null === $entity->getCreatedAt()) {
|
||||
$entity->setCreatedAt($now);
|
||||
}
|
||||
$entity->setUpdatedAt($now);
|
||||
}
|
||||
|
||||
if ($entity instanceof BlamableInterface) {
|
||||
$user = $this->currentUserProvider->getCurrentUser();
|
||||
if (null === $entity->getCreatedBy()) {
|
||||
$entity->setCreatedBy($user);
|
||||
}
|
||||
$entity->setUpdatedBy($user);
|
||||
}
|
||||
}
|
||||
|
||||
public function applyOnUpdate(object $entity): void
|
||||
{
|
||||
if ($entity instanceof TimestampableInterface) {
|
||||
$entity->setUpdatedAt(new DateTimeImmutable());
|
||||
}
|
||||
|
||||
if ($entity instanceof BlamableInterface) {
|
||||
$entity->setUpdatedBy($this->currentUserProvider->getCurrentUser());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Shared\Infrastructure\Security;
|
||||
|
||||
use App\Shared\Application\CurrentUserProviderInterface;
|
||||
use App\Shared\Domain\Contract\UserInterface;
|
||||
use Symfony\Bundle\SecurityBundle\Security;
|
||||
|
||||
final readonly class SecurityCurrentUserProvider implements CurrentUserProviderInterface
|
||||
{
|
||||
public function __construct(
|
||||
private Security $security,
|
||||
) {}
|
||||
|
||||
public function getCurrentUser(): ?UserInterface
|
||||
{
|
||||
$user = $this->security->getUser();
|
||||
|
||||
return $user instanceof UserInterface ? $user : null;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user