<?php
namespace App\Entity\Adherent\Annuaire;
use App\Entity\Adherent\Magasin;
use App\Entity\ContactThemeCanal;
use App\Repository\Adherent\Annuaire\MagasinContactRepository;
use App\Service\PhoneNumberService;
use DateTimeImmutable;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use JetBrains\PhpStorm\NoReturn;
use phpDocumentor\Reflection\Types\Integer;
use Symfony\Component\Serializer\Annotation\Groups;
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Component\Validator\Context\ExecutionContextInterface;
#[ORM\Entity(repositoryClass: MagasinContactRepository::class)]
#[ORM\UniqueConstraint(name: 'unique_contact_qualif_value', fields: ['magasin', 'value', 'qualifier'])]
#[ORM\HasLifecycleCallbacks]
class MagasinContact
{
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column(type: 'integer')]
#[Groups(groups: ['contact_history'])]
private int $id;
#[ORM\ManyToOne(targetEntity: Magasin::class, inversedBy: 'magasinContacts')]
#[ORM\JoinColumn(name: 'magasin', referencedColumnName: 'k_adherent', nullable: false)]
#[Groups(groups: ['contact_history'])]
private ?Magasin $magasin;
#[ORM\Column(type: 'datetime_immutable')]
#[Groups(groups: ['contact_history'])]
private DateTimeImmutable $createdAt;
#[ORM\Column(type: 'datetime_immutable', nullable: true)]
#[Groups(groups: ['contact_history'])]
private ?DateTimeImmutable $updatedAt = null;
#[ORM\Column(length: 255)]
#[Groups(groups: ['contact_history'])]
private ?string $value = null;
#[ORM\Column(length: 255, nullable: true)]
#[Groups(groups: ['contact_history'])]
private ?string $name = null;
#[ORM\ManyToOne(cascade: ['persist'], inversedBy: 'magasinContacts')]
#[ORM\JoinColumn(nullable: false)]
#[Groups(groups: ['contact_history'])]
private ?MagasinContactQualifier $qualifier = null;
#[ORM\ManyToMany(targetEntity: ContactThemeCanal::class, inversedBy: 'magasinContacts')]
#[Groups(groups: ['contact_history'])]
private Collection $canaux;
#[ORM\Column(type: 'integer', length: 255, nullable: true)]
#[Groups(groups: ['contact_history'])]
private ?int $kProgress = null;
#[ORM\Column(type: 'integer', length: 255, nullable: true)]
#[Groups(groups: ['contact_history'])]
private ?int $idAnnuaireProgress;
#[ORM\Column(type: 'boolean')]
#[Groups(groups: ['contact_history'])]
private bool $principal = false;
private bool $existInProgress = false;
public function __construct()
{
$this->createdAt = new DateTimeImmutable("now");
$this->canaux = new ArrayCollection();
$this->idAnnuaireProgress = -1;
}
#[Assert\Callback]
public function validate(ExecutionContextInterface $context, $payload): void
{
$phoneNumberService = new PhoneNumberService();
if ($this->magasin->allowExistMagasinContact($this)) {
$context->buildViolation("Cette valeur existe déjà")->atPath('value')->addViolation();
}
// Il y a des canaux qui ne peuvent avoir qu'un seul contact rattaché. Ex : Un seul téléphone peut-être affiché sur la fiche OPC.
foreach ($this->canaux as $canal) {
if (!$canal->isMultiple()) {
$contactsMag = $this->magasin->getMagasinContacts();
foreach ($contactsMag as $contact) {
if ($contact !== $this && $contact->hasCanal($canal->getIdentifier())) {
$context->buildViolation("Le canal est déjà utilisé par un autre contact et ne peux contenir plusieurs contacts.")->atPath('canaux')->addViolation();
}
}
}
}
if (!$this->qualifier->isMultiple() && $this->magasin->hasMagasinContact($this, $this->qualifier)) {
$context->buildViolation("Ce qualifiant est déjà utilisé pour ce magasin et ne peux pas contenir plusieurs valeurs.")->atPath('qualifier')->addViolation();
}
if ($this->qualifier->getType() === "TEL") {
$cleanedNumber = $phoneNumberService->validateAndFormatPhoneNumber($this->value, strtoupper($this->magasin->getKPays()));
if (is_null($cleanedNumber)) {
$context->buildViolation("Le numéro de téléphone renseigné n'est pas valide.")->atPath('value')->addViolation();
} else {
$cleanedNumber = preg_replace('/\s+/', '', strtolower($cleanedNumber));
$this->value = strtolower($cleanedNumber);
}
} else {
$cleanedMail = preg_replace('/\s+/', '', strtolower($this->value));
$this->value = strtolower($cleanedMail);
if (!filter_var($cleanedMail, FILTER_VALIDATE_EMAIL)) {
$context->buildViolation("Le mail renseigné n'est pas valide.")->atPath('value')->addViolation();
}
}
}
#[ORM\PreUpdate]
public function onPreUpdateEntity(): void
{
$this->updatedAt = new DateTimeImmutable("now");
}
public function getId(): ?int
{
return $this->id;
}
public function getMagasin(): ?Magasin
{
return $this->magasin;
}
public function setMagasin(?Magasin $magasin): static
{
$this->magasin = $magasin;
return $this;
}
public function getValue(): ?string
{
return $this->value;
}
public function setValue(?string $value): static
{
$this->value = $value;
return $this;
}
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 getQualifier(): ?MagasinContactQualifier
{
return $this->qualifier;
}
public function setQualifier(?MagasinContactQualifier $qualifier): static
{
$this->qualifier = $qualifier;
return $this;
}
/**
* @return Collection<int, ContactThemeCanal>
*/
public function getCanaux(): Collection
{
return $this->canaux;
}
public function getCanauxByTheme()
{
$data = [];
foreach ($this->canaux as $canal) {
$data[strtoupper($canal->getContactTheme()->getType())][] = $canal;
}
return $data;
}
public function addCanaux(ContactThemeCanal $canaux): static
{
if (!$this->canaux->contains($canaux)) {
$this->canaux->add($canaux);
}
return $this;
}
public function removeCanaux(ContactThemeCanal $canaux): static
{
$this->canaux->removeElement($canaux);
return $this;
}
public function hasCanal($canalIdentifier): bool
{
return array_reduce($this->canaux->toArray(), fn($carry, $contactCanal) => $carry || ($contactCanal->getIdentifier() === $canalIdentifier), false);
}
public function getName(): ?string
{
return $this->name;
}
public function setName(string $name): MagasinContact
{
$this->name = $name;
return $this;
}
public function getKProgress(): ?int
{
return $this->kProgress;
}
public function setKProgress(int|bool $kProgress): void
{
$this->kProgress = $kProgress;
}
public function getExistInProgress()
{
return $this->existInProgress;
}
public function setExistInProgress(bool $exist): void
{
$this->existInProgress = $exist;
}
public function isPrincipal(): bool
{
return $this->principal;
}
public function setPrincipal(bool $principal): void
{
$this->principal = $principal;
}
public function getIdAnnuaireProgress(): ?int
{
return $this->idAnnuaireProgress;
}
public function setIdAnnuaireProgress(int|null $idAnnuaireProgress): void
{
$this->idAnnuaireProgress = $idAnnuaireProgress;
}
public function toArray(): array
{
return [
'id' => $this->id,
'value' => $this->value,
'qualifier' => [
'category' => $this->qualifier->getCategory(),
'type' => $this->qualifier->getType(),
'label' => $this->qualifier->getLabel()
],
'principal' => $this->isPrincipal(),
'name' => $this->name
];
}
}