Vincent GUFFON 4 år sedan
förälder
incheckning
fb3e2ccb26

+ 30 - 2
src/Entity/Core/ContactPoint.php

@@ -13,6 +13,7 @@ use Doctrine\Common\Collections\ArrayCollection;
 use Doctrine\Common\Collections\Collection;
 use Doctrine\Common\Collections\Collection;
 use Doctrine\ORM\Mapping as ORM;
 use Doctrine\ORM\Mapping as ORM;
 use Symfony\Component\Validator\Constraints as Assert;
 use Symfony\Component\Validator\Constraints as Assert;
+use App\Validator\Core as OpentalentAssert;
 
 
 /**
 /**
  * Données de contact d'une Person ou d'une Organization ou d'un lieu
  * Données de contact d'une Person ou d'une Organization ou d'un lieu
@@ -31,6 +32,7 @@ use Symfony\Component\Validator\Constraints as Assert;
     ]
     ]
 )]
 )]
 #[ORM\Entity(repositoryClass: ContactPointRepository::class)]
 #[ORM\Entity(repositoryClass: ContactPointRepository::class)]
+#[OpentalentAssert\ContactPoint]
 class ContactPoint
 class ContactPoint
 {
 {
     #[ORM\Id]
     #[ORM\Id]
@@ -69,10 +71,14 @@ class ContactPoint
 
 
     #[ORM\ManyToMany(targetEntity: Organization::class, inversedBy: 'contactPoints')]
     #[ORM\ManyToMany(targetEntity: Organization::class, inversedBy: 'contactPoints')]
     #[ORM\JoinTable(name: 'organization_contactpoint')]
     #[ORM\JoinTable(name: 'organization_contactpoint')]
+    #[ORM\JoinColumn(name: 'contactPoint_id', referencedColumnName: 'id', unique: true)]
+    #[ORM\InverseJoinColumn(name: 'organization_id', referencedColumnName: 'id')]
     private Collection $organization;
     private Collection $organization;
 
 
     #[ORM\ManyToMany(targetEntity: Person::class ,inversedBy: 'contactPoints')]
     #[ORM\ManyToMany(targetEntity: Person::class ,inversedBy: 'contactPoints')]
     #[ORM\JoinTable(name: 'person_contactpoint')]
     #[ORM\JoinTable(name: 'person_contactpoint')]
+    #[ORM\JoinColumn(name: 'contactPoint_id', referencedColumnName: 'id', unique: true)]
+    #[ORM\InverseJoinColumn(name: 'person_id', referencedColumnName: 'id')]
     private Collection $person;
     private Collection $person;
 
 
     #[Pure] public function __construct()
     #[Pure] public function __construct()
@@ -215,6 +221,7 @@ class ContactPoint
     {
     {
         if (!$this->organization->contains($organization)) {
         if (!$this->organization->contains($organization)) {
             $this->organization[] = $organization;
             $this->organization[] = $organization;
+            $organization->addContactPoint($this);
         }
         }
 
 
         return $this;
         return $this;
@@ -222,8 +229,18 @@ class ContactPoint
 
 
     public function removeOrganization(Organization $organization): self
     public function removeOrganization(Organization $organization): self
     {
     {
-        $this->organization->removeElement($organization);
+        if ($this->organization->removeElement($organization)) {
+            $organization->removeContactPoint($this);
+        }
+
+        return $this;
+    }
 
 
+    public function removeOrganizations(): self
+    {
+        foreach ($this->getOrganization() as $organization){
+            $this->removeOrganization($organization);
+        }
         return $this;
         return $this;
     }
     }
 
 
@@ -236,6 +253,7 @@ class ContactPoint
     {
     {
         if (!$this->person->contains($person)) {
         if (!$this->person->contains($person)) {
             $this->person[] = $person;
             $this->person[] = $person;
+            $person->addContactPoint($this);
         }
         }
 
 
         return $this;
         return $this;
@@ -243,8 +261,18 @@ class ContactPoint
 
 
     public function removePerson(Person $person): self
     public function removePerson(Person $person): self
     {
     {
-        $this->person->removeElement($person);
+        if ($this->person->removeElement($person)) {
+            $person->removeContactPoint($this);
+        }
+
+        return $this;
+    }
 
 
+    public function removePeople(): self
+    {
+        foreach ($this->getPerson() as $person){
+            $this->removePerson($person);
+        }
         return $this;
         return $this;
     }
     }
 }
 }

+ 38 - 0
src/Repository/Core/ContactPointRepository.php

@@ -4,6 +4,8 @@ declare(strict_types=1);
 namespace App\Repository\Core;
 namespace App\Repository\Core;
 
 
 use App\Entity\Core\ContactPoint;
 use App\Entity\Core\ContactPoint;
+use App\Entity\Organization\Organization;
+use App\Entity\Person\Person;
 use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
 use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
 use Doctrine\Persistence\ManagerRegistry;
 use Doctrine\Persistence\ManagerRegistry;
 
 
@@ -20,4 +22,40 @@ class ContactPointRepository extends ServiceEntityRepository
         parent::__construct($registry, ContactPoint::class);
         parent::__construct($registry, ContactPoint::class);
     }
     }
 
 
+    /**
+     * Récupération des points de contacts d'une organization et d'un type précis
+     * @param String $type
+     * @param Organization $organization
+     * @return array|null
+     */
+    public function getByTypeAndOrganization(String $type, Organization $organization): array | null{
+        return $this->createQueryBuilder('contact_point')
+            ->innerJoin('contact_point.organization', 'organization')
+            ->where('contact_point.contactType = :type')
+            ->andWhere('organization.id = :organizationId')
+            ->setParameter('type', $type)
+            ->setParameter('organizationId', $organization->getId())
+            ->getQuery()
+            ->getResult()
+            ;
+    }
+
+    /**
+     * Récupération des points de contacts d'une person et d'un type précis
+     * @param String $type
+     * @param Person $person
+     * @return array|null
+     */
+    public function getByTypeAndPerson(String $type, Person $person): array | null{
+        return $this->createQueryBuilder('contact_point')
+            ->innerJoin('contact_point.person', 'person')
+            ->where('contact_point.contactType = :type')
+            ->andWhere('person.id = :personId')
+            ->setParameter('type', $type)
+            ->setParameter('personId', $person->getId())
+            ->getQuery()
+            ->getResult()
+            ;
+    }
+
 }
 }

+ 2 - 2
src/Security/Voter/ContactPointVoter.php

@@ -17,7 +17,7 @@ class ContactPointVoter extends Voter
 
 
     protected function supports($attribute, $subject): bool
     protected function supports($attribute, $subject): bool
     {
     {
-        return in_array($attribute, ['CONTACT_POINT_READ', 'CONTACT_POINT_EDIT'])
+        return in_array($attribute, ['CONTACT_POINT_READ', 'CONTACT_POINT_EDIT', 'CONTACT_POINT_DELETE'])
             && $subject instanceof ContactPoint;
             && $subject instanceof ContactPoint;
     }
     }
 
 
@@ -35,7 +35,6 @@ class ContactPointVoter extends Voter
         if (!$user instanceof UserInterface) {
         if (!$user instanceof UserInterface) {
             return false;
             return false;
         }
         }
-
         switch ($attribute) {
         switch ($attribute) {
             case 'CONTACT_POINT_READ':
             case 'CONTACT_POINT_READ':
                 if($subject->getOrganization()->count() === 1){
                 if($subject->getOrganization()->count() === 1){
@@ -44,6 +43,7 @@ class ContactPointVoter extends Voter
                 }
                 }
                 break;
                 break;
             case 'CONTACT_POINT_EDIT':
             case 'CONTACT_POINT_EDIT':
+            case 'CONTACT_POINT_DELETE':
                 if($subject->getOrganization()->count() === 1){
                 if($subject->getOrganization()->count() === 1){
                     return $this->security->isGranted('ROLE_ORGANIZATION')
                     return $this->security->isGranted('ROLE_ORGANIZATION')
                         && $subject->getOrganization()->current()->getId() === $user->getOrganization()->getId();
                         && $subject->getOrganization()->current()->getId() === $user->getOrganization()->getId();

+ 17 - 0
src/Validator/Core/ContactPoint.php

@@ -0,0 +1,17 @@
+<?php
+declare(strict_types=1);
+
+namespace App\Validator\Core;
+
+use Symfony\Component\Validator\Constraint;
+
+#[\Attribute]
+class ContactPoint extends Constraint
+{
+    public $message = '{{ type }}_non_unique';
+
+    public function getTargets()
+    {
+        return self::CLASS_CONSTRAINT;
+    }
+}

+ 42 - 0
src/Validator/Core/ContactPointValidator.php

@@ -0,0 +1,42 @@
+<?php
+declare(strict_types=1);
+
+namespace App\Validator\Core;
+
+use App\Enum\Core\ContactPointTypeEnum;
+use App\Repository\Core\ContactPointRepository;
+use Symfony\Component\Validator\Constraint;
+use Symfony\Component\Validator\ConstraintValidator;
+use App\Entity\Core\ContactPoint;
+
+/**
+ * Classe control qu'une seul et même type de point de contact est autorisé pour chaque owner (organization, person, place)
+ */
+class ContactPointValidator extends ConstraintValidator
+{
+    public function __construct(private ContactPointRepository $contactPointRepository){}
+
+    public function validate($value, Constraint $constraint)
+    {
+        /** @var ContactPoint $contactPoint */
+        $contactPoint = $value;
+
+        // si le type est autre, on valide
+        if($contactPoint->getContactType() === ContactPointTypeEnum::OTHER()->getValue())
+            return;
+
+        $contactPointByType = [];
+        if($contactPoint->getOrganization())
+            $contactPointByType = $this->contactPointRepository->getByTypeAndOrganization($contactPoint->getContactType(), $contactPoint->getOrganization()->first());
+        else if($contactPoint->getPerson())
+            $contactPointByType = $this->contactPointRepository->getByTypeAndPerson($contactPoint->getContactType(), $contactPoint->getPerson()->first());
+
+        //Si le nombre de point de contact du type est supérieur à 1, OU si le nombre est égale a 1 ET que l'id du point de contact n'est pas celui en cours : invalide.
+        if(count($contactPointByType) > 1 || (count($contactPointByType) === 1 && $contactPointByType[0]->getId() !== $contactPoint->getId())){
+            $this->context->buildViolation($constraint->message)
+                ->setParameter('{{ type }}', $contactPoint->getContactType())
+                ->atPath('contactType')
+                ->addViolation();
+        }
+    }
+}