mirror of
				https://gitlab.com/Chill-Projet/chill-bundles.git
				synced 2025-11-03 18:58:24 +00:00 
			
		
		
		
	create api for social issue consistency
This commit is contained in:
		@@ -0,0 +1,28 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace Chill\PersonBundle\AccompanyingPeriod\SocialIssueConsistency;
 | 
			
		||||
 | 
			
		||||
use Doctrine\Common\Collections\Collection;
 | 
			
		||||
use Chill\PersonBundle\Entity\AccompanyingPeriod;
 | 
			
		||||
use Chill\PersonBundle\Entity\SocialWork\SocialIssue;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * This interface must be implemented on entities which:
 | 
			
		||||
 *
 | 
			
		||||
 * * have both social issue and is linked to an AccompanyingPeriod
 | 
			
		||||
 * * when the social issues in the entity should be added to the accompanying period
 | 
			
		||||
 *
 | 
			
		||||
 * A doctrine listener will list social issues which are associated to the entity, but
 | 
			
		||||
 * not on the AccompanyingPeriod, and push them back to the accompanying period.
 | 
			
		||||
 */
 | 
			
		||||
interface AccompanyingPeriodLinkedWithSocialIssuesEntityInterface
 | 
			
		||||
{
 | 
			
		||||
    public function getAccompanyingPeriod(): AccompanyingPeriod;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @return Collection|SocialIssue[]
 | 
			
		||||
     */
 | 
			
		||||
    public function getSocialIssues(): Collection;
 | 
			
		||||
 | 
			
		||||
    public function removeSocialIssue(SocialIssue $issue): self;
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,66 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace Chill\PersonBundle\AccompanyingPeriod\SocialIssueConsistency;
 | 
			
		||||
 | 
			
		||||
use Chill\PersonBundle\Entity\AccompanyingPeriod;
 | 
			
		||||
use Chill\PersonBundle\Entity\SocialWork\SocialIssue;
 | 
			
		||||
use Doctrine\ORM\Event\LifecycleEventArgs;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * This service listens for preUpdate and prePersist events on some entities
 | 
			
		||||
 * and ensure consistency of SocialIssue with an associated AccompanyingPeriod.
 | 
			
		||||
 *
 | 
			
		||||
 * The entity must implements interface Chill\PersonBundle\AccompanyingPeriod\SocialIssueConsistency\AccompanyingPeriodLinkedWithSocialIssuesEntityInterface.
 | 
			
		||||
 *
 | 
			
		||||
 * This subscriber is not called automatically: for performance reasons, this
 | 
			
		||||
 * apply only on entities which are configured. See https://symfony.com/doc/4.4/doctrine/events.html#doctrine-entity-listeners
 | 
			
		||||
 */
 | 
			
		||||
final class AccompanyingPeriodSocialIssueConsistencyEntityListener
 | 
			
		||||
{
 | 
			
		||||
    public function prePersist(AccompanyingPeriodLinkedWithSocialIssuesEntityInterface $entity, LifecycleEventArgs $eventArgs)
 | 
			
		||||
    {
 | 
			
		||||
        $this->ensureConsistencyEntity($entity);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function preUpdate(AccompanyingPeriodLinkedWithSocialIssuesEntityInterface $entity, LifecycleEventArgs $eventArgs)
 | 
			
		||||
    {
 | 
			
		||||
        $this->ensureConsistencyEntity($entity);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function prePersistAccompanyingPeriod(AccompanyingPeriod $period, LifecycleEventArgs $eventArgs)
 | 
			
		||||
    {
 | 
			
		||||
        $this->ensureConsistencyAccompanyingPeriod($period);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function preUpdateAccompanyingPeriod(AccompanyingPeriod $period, LifecycleEventArgs $eventArgs)
 | 
			
		||||
    {
 | 
			
		||||
        $this->ensureConsistencyAccompanyingPeriod($period);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private function ensureConsistencyEntity(AccompanyingPeriodLinkedWithSocialIssuesEntityInterface $entity): void
 | 
			
		||||
    {
 | 
			
		||||
        // remove issues parents on the entity itself
 | 
			
		||||
        $ancestors = SocialIssue::findAncestorSocialIssues($entity->getSocialIssues());
 | 
			
		||||
        foreach ($ancestors as $ancestor) {
 | 
			
		||||
            $entity->removeSocialIssue($ancestor);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $period = $entity->getAccompanyingPeriod();
 | 
			
		||||
 | 
			
		||||
        foreach ($entity->getSocialIssues() as $issue) {
 | 
			
		||||
            // the entity itself test if the social issue is already associated, or not
 | 
			
		||||
            $period->addSocialIssue($issue);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $this->ensureConsistencyAccompanyingPeriod($period);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private function ensureConsistencyAccompanyingPeriod(AccompanyingPeriod $period): void
 | 
			
		||||
    {
 | 
			
		||||
        $ancestors = SocialIssue::findAncestorSocialIssues($period->getSocialIssues());
 | 
			
		||||
 | 
			
		||||
        foreach ($ancestors as $ancestor) {
 | 
			
		||||
            $period->removeSocialIssue($ancestor);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -2,11 +2,13 @@
 | 
			
		||||
 | 
			
		||||
namespace Chill\PersonBundle\Entity\AccompanyingPeriod;
 | 
			
		||||
 | 
			
		||||
use Chill\PersonBundle\AccompanyingPeriod\SocialIssueConsistency\AccompanyingPeriodLinkedWithSocialIssuesEntityInterface;
 | 
			
		||||
use Chill\PersonBundle\Entity\SocialWork\Result;
 | 
			
		||||
use Chill\PersonBundle\Entity\SocialWork\SocialAction;
 | 
			
		||||
use Chill\PersonBundle\Entity\Person;
 | 
			
		||||
use Chill\MainBundle\Entity\User;
 | 
			
		||||
use Chill\PersonBundle\Entity\AccompanyingPeriod;
 | 
			
		||||
use Chill\PersonBundle\Entity\SocialWork\SocialIssue;
 | 
			
		||||
use Chill\ThirdPartyBundle\Entity\ThirdParty;
 | 
			
		||||
use DateTimeInterface;
 | 
			
		||||
use Doctrine\Common\Collections\ArrayCollection;
 | 
			
		||||
@@ -470,4 +472,4 @@ use Symfony\Component\Validator\Constraints as Assert;
 | 
			
		||||
 | 
			
		||||
         return $this;
 | 
			
		||||
     }
 | 
			
		||||
}
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
@@ -233,4 +233,57 @@ class SocialIssue
 | 
			
		||||
 | 
			
		||||
        return $recursiveSocialActions;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Recursive method which return true if the current $issue is a descendant
 | 
			
		||||
     * of the $issue given in parameter.
 | 
			
		||||
     *
 | 
			
		||||
     * @param SocialIssue $issue
 | 
			
		||||
     * @return bool
 | 
			
		||||
     */
 | 
			
		||||
    public function isDescendantOf(SocialIssue $issue): bool
 | 
			
		||||
    {
 | 
			
		||||
        if (!$this->hasParent()) {
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if ($this->getParent() === $issue) {
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return $this->getParent()->isDescendantOf($issue);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * In a SocialIssues's collection, find the elements which are an ancestor of
 | 
			
		||||
     * other elements.
 | 
			
		||||
     *
 | 
			
		||||
     * Removing those elements of the Collection (which is not done by this method)
 | 
			
		||||
     * will ensure that only the most descendent elements are present in the collection,
 | 
			
		||||
     * (any ancestor of another element are present).
 | 
			
		||||
     *
 | 
			
		||||
     * @param Collection|SocialIssue[] $socialIssues
 | 
			
		||||
     * @return Collection|SocialIssue[]
 | 
			
		||||
     */
 | 
			
		||||
    public static function findAncestorSocialIssues(Collection $socialIssues): Collection
 | 
			
		||||
    {
 | 
			
		||||
        $ancestors = new ArrayCollection();
 | 
			
		||||
 | 
			
		||||
        foreach ($socialIssues as $candidateChild) {
 | 
			
		||||
            if ($ancestors->contains($candidateChild)) {
 | 
			
		||||
                continue;
 | 
			
		||||
            }
 | 
			
		||||
            foreach ($socialIssues as $candidateParent) {
 | 
			
		||||
                if ($ancestors->contains($candidateParent)) {
 | 
			
		||||
                    continue;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                if ($candidateChild->isDescendantOf($candidateParent)) {
 | 
			
		||||
                    $ancestors->add($candidateParent);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return $ancestors;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,140 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace Chill\PersonBundle\Tests\AccompanyingPeriod\SocialIssueConsistency;
 | 
			
		||||
 | 
			
		||||
use Chill\PersonBundle\AccompanyingPeriod\SocialIssueConsistency\AccompanyingPeriodLinkedWithSocialIssuesEntityInterface;
 | 
			
		||||
use Chill\PersonBundle\AccompanyingPeriod\SocialIssueConsistency\AccompanyingPeriodSocialIssueConsistencyEntityListener;
 | 
			
		||||
use Chill\PersonBundle\Entity\AccompanyingPeriod;
 | 
			
		||||
use Chill\PersonBundle\Entity\SocialWork\SocialIssue;
 | 
			
		||||
use Doctrine\Common\Collections\ArrayCollection;
 | 
			
		||||
use Doctrine\Common\Collections\Collection;
 | 
			
		||||
use Doctrine\ORM\Event\LifecycleEventArgs;
 | 
			
		||||
use PHPUnit\Framework\TestCase;
 | 
			
		||||
 | 
			
		||||
class AccompanyingPeriodSocialIssueConsistencyEntityListenerTest extends TestCase
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
    public function testPrePersistAccompanyingPeriod()
 | 
			
		||||
    {
 | 
			
		||||
        $arraySocialIssues = [
 | 
			
		||||
            $parent = new SocialIssue(),
 | 
			
		||||
            $child = (new SocialIssue())->setParent($parent),
 | 
			
		||||
            $grandChild = (new SocialIssue())->setParent($child),
 | 
			
		||||
            $grandGrandChild = (new SocialIssue())->setParent($grandChild),
 | 
			
		||||
        ];
 | 
			
		||||
        $period = new AccompanyingPeriod();
 | 
			
		||||
        $consistency = new AccompanyingPeriodSocialIssueConsistencyEntityListener();
 | 
			
		||||
 | 
			
		||||
        foreach ($arraySocialIssues as $issue) {
 | 
			
		||||
            $period->addSocialIssue($issue);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $consistency->prePersistAccompanyingPeriod($period, $this->generateLifecycleArgs());
 | 
			
		||||
 | 
			
		||||
        $this->assertCount(1, $period->getSocialIssues());
 | 
			
		||||
        $this->assertSame($grandGrandChild, $period->getSocialIssues()->first());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function testPreUpdate()
 | 
			
		||||
    {
 | 
			
		||||
        $socialIssues = new ArrayCollection([
 | 
			
		||||
            $parent = new SocialIssue(),
 | 
			
		||||
            $child = (new SocialIssue())->setParent($parent),
 | 
			
		||||
            $grandChild = (new SocialIssue())->setParent($child),
 | 
			
		||||
            $grandGrandChild = (new SocialIssue())->setParent($grandChild),
 | 
			
		||||
        ]);
 | 
			
		||||
        $period = (new AccompanyingPeriod())->addSocialIssue($unrelated = new SocialIssue());
 | 
			
		||||
        $entity = $this->generateClass($period, $socialIssues);
 | 
			
		||||
        $consistency = new AccompanyingPeriodSocialIssueConsistencyEntityListener();
 | 
			
		||||
 | 
			
		||||
        $consistency->preUpdate($entity, $this->generateLifecycleArgs());
 | 
			
		||||
 | 
			
		||||
        $this->assertCount(2, $period->getSocialIssues());
 | 
			
		||||
        $this->assertContains($grandGrandChild, $period->getSocialIssues());
 | 
			
		||||
        $this->assertContains($unrelated, $period->getSocialIssues());
 | 
			
		||||
 | 
			
		||||
        $this->assertCount(1, $entity->getSocialIssues());
 | 
			
		||||
        $this->assertContains($grandGrandChild, $entity->getSocialIssues());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function testPrePersist()
 | 
			
		||||
    {
 | 
			
		||||
        $socialIssues = new ArrayCollection([
 | 
			
		||||
            $parent = new SocialIssue(),
 | 
			
		||||
            $child = (new SocialIssue())->setParent($parent),
 | 
			
		||||
            $grandChild = (new SocialIssue())->setParent($child),
 | 
			
		||||
            $grandGrandChild = (new SocialIssue())->setParent($grandChild),
 | 
			
		||||
        ]);
 | 
			
		||||
        $period = (new AccompanyingPeriod())->addSocialIssue($unrelated = new SocialIssue());
 | 
			
		||||
        $entity = $this->generateClass($period, $socialIssues);
 | 
			
		||||
        $consistency = new AccompanyingPeriodSocialIssueConsistencyEntityListener();
 | 
			
		||||
 | 
			
		||||
        $consistency->prePersist($entity, $this->generateLifecycleArgs());
 | 
			
		||||
 | 
			
		||||
        $this->assertCount(2, $period->getSocialIssues());
 | 
			
		||||
        $this->assertContains($grandGrandChild, $period->getSocialIssues());
 | 
			
		||||
        $this->assertContains($unrelated, $period->getSocialIssues());
 | 
			
		||||
 | 
			
		||||
        $this->assertCount(1, $entity->getSocialIssues());
 | 
			
		||||
        $this->assertContains($grandGrandChild, $entity->getSocialIssues());
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function testPreUpdateAccompanyingPeriod()
 | 
			
		||||
    {
 | 
			
		||||
        $arraySocialIssues = [
 | 
			
		||||
            $parent = new SocialIssue(),
 | 
			
		||||
            $child = (new SocialIssue())->setParent($parent),
 | 
			
		||||
            $grandChild = (new SocialIssue())->setParent($child),
 | 
			
		||||
            $grandGrandChild = (new SocialIssue())->setParent($grandChild),
 | 
			
		||||
        ];
 | 
			
		||||
        $period = new AccompanyingPeriod();
 | 
			
		||||
        $consistency = new AccompanyingPeriodSocialIssueConsistencyEntityListener();
 | 
			
		||||
 | 
			
		||||
        foreach ($arraySocialIssues as $issue) {
 | 
			
		||||
            $period->addSocialIssue($issue);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $consistency->prePersistAccompanyingPeriod($period, $this->generateLifecycleArgs());
 | 
			
		||||
 | 
			
		||||
        $this->assertCount(1, $period->getSocialIssues());
 | 
			
		||||
        $this->assertSame($grandGrandChild, $period->getSocialIssues()->first());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    protected function generateLifecycleArgs(): LifecycleEventArgs
 | 
			
		||||
    {
 | 
			
		||||
        return $this->createMock(LifecycleEventArgs::class);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    protected function generateClass(AccompanyingPeriod $period, Collection $socialIssues): AccompanyingPeriodLinkedWithSocialIssuesEntityInterface
 | 
			
		||||
    {
 | 
			
		||||
       return new class($period, $socialIssues) implements AccompanyingPeriodLinkedWithSocialIssuesEntityInterface
 | 
			
		||||
       {
 | 
			
		||||
           public Collection $socialIssues;
 | 
			
		||||
           public AccompanyingPeriod $period;
 | 
			
		||||
 | 
			
		||||
           public function __construct($period, $socialIssues)
 | 
			
		||||
           {
 | 
			
		||||
               $this->period = $period;
 | 
			
		||||
               $this->socialIssues = $socialIssues;
 | 
			
		||||
           }
 | 
			
		||||
 | 
			
		||||
           public function getAccompanyingPeriod(): AccompanyingPeriod
 | 
			
		||||
           {
 | 
			
		||||
               return $this->period;
 | 
			
		||||
           }
 | 
			
		||||
 | 
			
		||||
           public function getSocialIssues(): Collection
 | 
			
		||||
           {
 | 
			
		||||
               return $this->socialIssues;
 | 
			
		||||
           }
 | 
			
		||||
 | 
			
		||||
           public function removeSocialIssue(SocialIssue $issue): AccompanyingPeriodLinkedWithSocialIssuesEntityInterface
 | 
			
		||||
           {
 | 
			
		||||
               $this->socialIssues->removeElement($issue);
 | 
			
		||||
 | 
			
		||||
               return $this;
 | 
			
		||||
           }
 | 
			
		||||
       };
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,51 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace Chill\PersonBundle\Tests\Entity\SocialWork;
 | 
			
		||||
 | 
			
		||||
use Chill\PersonBundle\Entity\SocialWork\SocialIssue;
 | 
			
		||||
use Doctrine\Common\Collections\ArrayCollection;
 | 
			
		||||
use PHPUnit\Framework\TestCase;
 | 
			
		||||
 | 
			
		||||
class SocialIssueTest extends TestCase
 | 
			
		||||
{
 | 
			
		||||
    public function testIsDescendantOf()
 | 
			
		||||
    {
 | 
			
		||||
        $parent = new SocialIssue();
 | 
			
		||||
        $child = (new SocialIssue())->setParent($parent);
 | 
			
		||||
        $grandChild = (new SocialIssue())->setParent($child);
 | 
			
		||||
        $grandGrandChild = (new SocialIssue())->setParent($grandChild);
 | 
			
		||||
        $unrelated = new SocialIssue();
 | 
			
		||||
 | 
			
		||||
        $this->assertTrue($grandGrandChild->isDescendantOf($parent));
 | 
			
		||||
        $this->assertTrue($grandGrandChild->isDescendantOf($grandChild));
 | 
			
		||||
        $this->assertTrue($grandGrandChild->isDescendantOf($child));
 | 
			
		||||
        $this->assertFalse($grandGrandChild->isDescendantOf($unrelated));
 | 
			
		||||
 | 
			
		||||
        $this->assertTrue($grandChild->isDescendantOf($parent));
 | 
			
		||||
        $this->assertTrue($grandChild->isDescendantOf($child));
 | 
			
		||||
        $this->assertFalse($grandChild->isDescendantOf($unrelated));
 | 
			
		||||
        $this->assertFalse($grandChild->isDescendantOf($grandChild));
 | 
			
		||||
 | 
			
		||||
        $this->assertFalse($unrelated->isDescendantOf($parent));
 | 
			
		||||
 | 
			
		||||
        $this->assertFalse($child->isDescendantOf($grandChild));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function testFindSocialIssuesAncestors()
 | 
			
		||||
    {
 | 
			
		||||
        $socialIssues = new ArrayCollection([
 | 
			
		||||
            $parent = new SocialIssue(),
 | 
			
		||||
            $child = (new SocialIssue())->setParent($parent),
 | 
			
		||||
            $grandChild = (new SocialIssue())->setParent($child),
 | 
			
		||||
            $grandGrandChild = (new SocialIssue())->setParent($grandChild),
 | 
			
		||||
            $unrelated = new SocialIssue(),
 | 
			
		||||
        ]);
 | 
			
		||||
 | 
			
		||||
        $ancestors = SocialIssue::findAncestorSocialIssues($socialIssues);
 | 
			
		||||
 | 
			
		||||
        $this->assertCount(3, $ancestors);
 | 
			
		||||
        $this->assertContains($parent, $ancestors);
 | 
			
		||||
        $this->assertContains($child, $ancestors);
 | 
			
		||||
        $this->assertContains($grandChild, $ancestors);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user