mirror of
https://gitlab.com/Chill-Projet/chill-bundles.git
synced 2025-09-30 02:25:00 +00:00
Add support for motive descendants in filters and improve Motive entity
- Added `getDescendants` method to `Motive` entity to retrieve all descendants recursively. - Updated `TicketACLAwareRepository` to include descendants when filtering by motives. - Updated API specification to clarify that motive descendants are included in query filters. - Added unit tests for `Motive` entity to validate descendant logic.
This commit is contained in:
@@ -112,7 +112,7 @@ paths:
|
||||
- no
|
||||
- name: byMotives
|
||||
in: query
|
||||
description: the motives of the ticket
|
||||
description: the motives of the ticket. All the descendants of the motive are taken into account.
|
||||
required: false
|
||||
style: form
|
||||
explode: false
|
||||
|
@@ -195,4 +195,25 @@ class Motive
|
||||
{
|
||||
return $this->parent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the descendants of the current entity.
|
||||
*
|
||||
* This method collects all descendant entities recursively, starting from the current entity
|
||||
* and including all of its children and their descendants.
|
||||
*
|
||||
* @return ReadableCollection&Selectable A collection containing the current entity and all its descendants
|
||||
*/
|
||||
public function getDescendants(): ReadableCollection&Selectable
|
||||
{
|
||||
$collection = new ArrayCollection([$this]);
|
||||
|
||||
foreach ($this->getChildren() as $child) {
|
||||
foreach ($child->getDescendants() as $descendant) {
|
||||
$collection->add($descendant);
|
||||
}
|
||||
}
|
||||
|
||||
return $collection;
|
||||
}
|
||||
}
|
||||
|
@@ -113,10 +113,11 @@ final readonly class TicketACLAwareRepository implements TicketACLAwareRepositor
|
||||
if (array_key_exists('byMotives', $params)) {
|
||||
$byMotives = $qb->expr()->orX();
|
||||
foreach ($params['byMotives'] as $motive) {
|
||||
$motivesWithDescendants = $motive->getDescendants()->toArray();
|
||||
$byMotives->add(
|
||||
$qb->expr()->exists(sprintf(
|
||||
'SELECT 1 FROM %s tp_motive_%d WHERE tp_motive_%d.ticket = t
|
||||
AND tp_motive_%d.motive = :motive_%d AND tp_motive_%d.endDate IS NULL
|
||||
AND tp_motive_%d.motive IN (:motives_%d) AND tp_motive_%d.endDate IS NULL
|
||||
',
|
||||
MotiveHistory::class,
|
||||
++$i,
|
||||
@@ -126,7 +127,7 @@ final readonly class TicketACLAwareRepository implements TicketACLAwareRepositor
|
||||
$i,
|
||||
))
|
||||
);
|
||||
$qb->setParameter(sprintf('motive_%d', $i), $motive);
|
||||
$qb->setParameter(sprintf('motives_%d', $i), $motivesWithDescendants);
|
||||
}
|
||||
$qb->andWhere($byMotives);
|
||||
}
|
||||
|
63
src/Bundle/ChillTicketBundle/tests/Entity/MotiveTest.php
Normal file
63
src/Bundle/ChillTicketBundle/tests/Entity/MotiveTest.php
Normal file
@@ -0,0 +1,63 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* Chill is a software for social workers
|
||||
*
|
||||
* For the full copyright and license information, please view
|
||||
* the LICENSE file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Chill\TicketBundle\Tests\Entity;
|
||||
|
||||
use Chill\TicketBundle\Entity\Motive;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*
|
||||
* @covers \Chill\TicketBundle\Entity\Motive::getWithDescendants
|
||||
*/
|
||||
final class MotiveTest extends TestCase
|
||||
{
|
||||
public function testGetDescendantsOnLeafReturnsSelfOnly(): void
|
||||
{
|
||||
$leaf = new Motive();
|
||||
$leaf->setLabel(['fr' => 'Feuille']);
|
||||
|
||||
$collection = $leaf->getDescendants();
|
||||
|
||||
self::assertCount(1, $collection);
|
||||
self::assertSame($leaf, $collection->first());
|
||||
self::assertContains($leaf, $collection->toArray());
|
||||
}
|
||||
|
||||
public function testGetWithDescendantsReturnsSelfAndAllDescendants(): void
|
||||
{
|
||||
$parent = new Motive();
|
||||
$parent->setLabel(['fr' => 'Parent']);
|
||||
|
||||
$childA = new Motive();
|
||||
$childA->setLabel(['fr' => 'Enfant A']);
|
||||
$childA->setParent($parent);
|
||||
|
||||
$childB = new Motive();
|
||||
$childB->setLabel(['fr' => 'Enfant B']);
|
||||
$childB->setParent($parent);
|
||||
|
||||
$grandChildA1 = new Motive();
|
||||
$grandChildA1->setLabel(['fr' => 'Petit-enfant A1']);
|
||||
$grandChildA1->setParent($childA);
|
||||
|
||||
$descendants = $parent->getDescendants();
|
||||
$asArray = $descendants->toArray();
|
||||
|
||||
// It should contain the parent itself, both children and the grand child
|
||||
self::assertCount(4, $descendants, 'Expected parent + 2 children + 1 grandchild');
|
||||
self::assertContains($parent, $asArray);
|
||||
self::assertContains($childA, $asArray);
|
||||
self::assertContains($childB, $asArray);
|
||||
self::assertContains($grandChildA1, $asArray);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user