Commit b6d3f63b authored by Bertrand Gauthier's avatar Bertrand Gauthier
Browse files

Ajout de spécificateurs de sélection d'alerte

parent 9954d1c4
Loading
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -106,6 +106,9 @@ return [
        'aliases' => [
            'alertes' => AlerteViewHelper::class,
        ],
        'shared' => [
            AlerteViewHelper::class => false,
        ]
    ],
    'view_manager' => [
        'template_path_stack' => [
+87 −38
Original line number Diff line number Diff line
@@ -3,7 +3,6 @@
namespace UnicaenAlerte\View\Helper;

use Doctrine\ORM\Query\Expr\Join;
use InvalidArgumentException;
use Laminas\View\Helper\AbstractHelper;
use UnicaenAlerte\Entity\Db\Alerte;
use UnicaenAlerte\Entity\Db\Repository\AlerteRepositoryAwareTrait;
@@ -15,10 +14,26 @@ class AlerteViewHelper extends AbstractHelper
{
    use AlerteRepositoryAwareTrait;

    private array $alerteCodes = [];
    /**
     * Sélection précise des alertes par leur code,
     * en précisant pour chacune si elle doit avoir un planning qui inclue la date du jour pour être retenue.
     *
     * @var bool[] $code => $withMatchingPlanning
     */
    private array $withCodesAndMatchingPlanning = [];

    /**
     * Spécifie *globalement* si les alertes doivent avoir un planning qui inclue la date du jour pour être retenues.
     *
     * @var bool
     */
    private bool $withMatchingPlanning = false;

    /** @var null|Alerte[] */
    /**
     * Alertes répondant aux critères de sélection.
     *
     * @var null|Alerte[]
     */
    private ?array $alertes = null;

    /**
@@ -42,38 +57,70 @@ class AlerteViewHelper extends AbstractHelper
    }

    /**
     * Sélection d'une alerte précise par son code.
     * Sélection précise des alertes par leur code.
     *
     * @param string[] $codes
     */
    public function withCodes(array $codes): self
    {
        return $this->withCodesAndMatchingPlanning($codes, false);
    }

    /**
     * Sélection précise des alertes par leur code,
     * en précisant si les alertes doivent avoir un planning qui inclue la date du jour.
     *
     * @param string[] $codes
     * @param bool $matchingPlanning L'alerte doit-elle avoir un planning qui inclue la date du jour pour être retenue ?
     * @return \UnicaenAlerte\View\Helper\AlerteViewHelper
     */
    public function withCodesAndMatchingPlanning(array $codes, bool $matchingPlanning = true): self
    {
        foreach ($codes as $code) {
            $this->withCodeAndMatchingPlanning($code, $matchingPlanning);
        }

        return $this;
    }

    /**
     * Sélection précise d'une alerte par son code.
     *
     * @param string $code
     * @return self
     */
    public function withCode(string $code): self
    {
        return $this->withCodes([$code]);
        return $this->withCodeAndMatchingPlanning($code, false);
    }

    /**
     * Sélection précises des alertes par leur code.
     * Sélection précise d'une alerte par son code,
     * en précisant si l'alerte doit avoir un planning qui inclue la date du jour.
     *
     * @param string[] $codes
     * @param string $code
     * @param bool $matchingPlanning L'alerte doit-elle avoir un planning qui inclue la date du jour pour être retenue ?
     * @return self
     */
    public function withCodes(array $codes): self
    public function withCodeAndMatchingPlanning(string $code, bool $matchingPlanning = true): self
    {
        $this->alerteCodes = $codes;
        $this->withCodesAndMatchingPlanning[$code] = $matchingPlanning;
        $this->alertes = null;

        $this->withMatchingPlanning = false;

        return $this;
    }

    /**
     * Permet de ne sélectionner que les alertes ayant un planning qui inclue la date du jour.
     *
     * @param bool $withMatchingPlanning
     * @param bool $matchingPlanning L'alerte doit-elle avoir un planning qui inclue la date du jour pour être retenue ?
     * @return self
     */
    public function withMatchingPlanning(bool $withMatchingPlanning = true): self
    public function withMatchingPlanning(bool $matchingPlanning = true): self
    {
        $this->withMatchingPlanning = $withMatchingPlanning;
        $this->withMatchingPlanning = $matchingPlanning;
        $this->alertes = null;

        return $this;
@@ -146,41 +193,43 @@ class AlerteViewHelper extends AbstractHelper

    private function fetchAlertes(): array
    {
        $qb = $this->alerteRepository->createQueryBuilder('a');
        $qb = $this->alerteRepository->createQueryBuilder('a')
            ->addSelect('p') // seuls les plannings (éventuels) incluant la date du jour nous intéressent
            ->leftJoin('a.plannings', 'p', Join::WITH, 'current_timestamp() between p.startDate and p.endDate');

        if (!empty($this->alerteCodes)) {
            $qb->andWhere($qb->expr()->in('a.code', $this->alerteCodes));
        $ors = [];
        foreach ($this->withCodesAndMatchingPlanning as $code => $matchingPlanning) {
            // le code de l'alerte doit matcher
            $param = uniqid(':code_');
            $expr = "a.code = $param";
            $qb->setParameter($param, $code);
            if ($matchingPlanning) {
                // et en plus, un planning doit exister
                $expr = $qb->expr()->andX($expr, 'p.id is not null');
            }
            $ors[] = $expr;
        }
        if ($ors) {
            $qb->andWhere($qb->expr()->orX(...$ors));
        }

        // filtre global portant sur toutes les alertes.
        if ($this->withMatchingPlanning) {
            $qb
                ->addSelect('p')
                ->join('a.plannings', 'p', Join::WITH, 'current_timestamp() between p.startDate and p.endDate');
            $qb->andWhere('p.id is not null');
        }

        /** @var Alerte[] $alertes */
        $alertes = $qb->getQuery()->getResult();

        if (!$this->withMatchingPlanning) {
            // si on ne trouve pas tous les codes d'alertes spécifiés, on couine !
            if (!empty($this->alerteCodes) && count($this->alerteCodes) !== count($alertes)) {
                $codesDiff = array_diff($this->alerteCodes, array_map(fn(Alerte $a) => $a->getCode(), $alertes));
                throw new InvalidArgumentException(
                    "Aucune alerte trouvée pour les codes spécifiés suivants : " . implode(', ', $codesDiff)
                );
            }
        }

        if ($this->withMatchingPlanning) {
            // la sévérité éventuellement spécifiée dans le planning écrase la sévérité par défaut :
        // la sévérité spécifiée dans l'eventuel planning écrase la sévérité par défaut :
        foreach ($alertes as $alerte) {
            /** @var \UnicaenAlerte\Entity\Db\AlertePlanning $planning */
                $planning = $alerte->getPlannings()->first(); // un seul planning en cours théoriquement
                if ($severity = $planning->getSeverity()) {
            $planning = $alerte->getPlannings()->first(); // un seul planning en cours pris en compte
            if ($planning && $severity = $planning->getSeverity()) {
                $alerte->setSeverity($severity);
                break;
            }
        }
        }

        return $alertes;
    }