|
@@ -0,0 +1,226 @@
|
|
|
|
|
+<?php
|
|
|
|
|
+declare(strict_types=1);
|
|
|
|
|
+
|
|
|
|
|
+namespace App\Service\Utils;
|
|
|
|
|
+
|
|
|
|
|
+use App\Entity\Access\Access;
|
|
|
|
|
+use App\Service\Organization\Utils as organizationUtils;
|
|
|
|
|
+use Doctrine\ORM\EntityManagerInterface;
|
|
|
|
|
+
|
|
|
|
|
+/**
|
|
|
|
|
+ * Classe DateTimeConstraint qui définie les dates de débuts et fin de périodes
|
|
|
|
|
+ * par rapport au contraintes temporelles choisies par un utilisateur.
|
|
|
|
|
+ */
|
|
|
|
|
+class DateTimeConstraint
|
|
|
|
|
+{
|
|
|
|
|
+ const NULL = 0;
|
|
|
|
|
+ const INF = 1;
|
|
|
|
|
+ const EQUAL = 3;
|
|
|
|
|
+ const SUP = 5;
|
|
|
|
|
+ const CANCEL_OPERATION = 9;
|
|
|
|
|
+ const START_KEY = 'start';
|
|
|
|
|
+ const END_KEY = 'end';
|
|
|
|
|
+ const NULL_VALUE = 'NULL';
|
|
|
|
|
+
|
|
|
|
|
+ public function __construct(
|
|
|
|
|
+ private EntityManagerInterface $entityManager,
|
|
|
|
|
+ )
|
|
|
|
|
+ { }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * Main méthode
|
|
|
|
|
+ * @param int $accessID
|
|
|
|
|
+ * @return array
|
|
|
|
|
+ * @throws \Exception
|
|
|
|
|
+ */
|
|
|
|
|
+ public function invoke(int $accessID): array
|
|
|
|
|
+ {
|
|
|
|
|
+ $access = $this->entityManager->getRepository(Access::class)->find($accessID);
|
|
|
|
|
+ $historical = $access->getHistorical();
|
|
|
|
|
+
|
|
|
|
|
+ $contraints = [
|
|
|
|
|
+ self::START_KEY => [],
|
|
|
|
|
+ self::END_KEY => []
|
|
|
|
|
+ ];
|
|
|
|
|
+
|
|
|
|
|
+ if($this->hasCustomPeriods($historical)){
|
|
|
|
|
+ $periods = $this->getCustomPeriods($historical['dateStart'], $historical['dateEnd']);
|
|
|
|
|
+ //Une période "Custom" reviens à savoir quels sont les éléments actif durant le "présent" de la période custom, donc
|
|
|
|
|
+ //on peut utiliser le presentConstraint avec les periods custom
|
|
|
|
|
+ $contraints = $this->addConstraint($contraints, $this->presentConstraint($periods));
|
|
|
|
|
+ }else{
|
|
|
|
|
+ $periods = $this->getPeriods($access);
|
|
|
|
|
+ if($historical['present']) $contraints = $this->addConstraint($contraints, $this->presentConstraint($periods));
|
|
|
|
|
+ if($historical['past']) $contraints = $this->addConstraint($contraints, $this->pastConstraint($periods));
|
|
|
|
|
+ if($historical['future']) $contraints = $this->addConstraint($contraints, $this->futurConstraint($periods));
|
|
|
|
|
+ }
|
|
|
|
|
+ return $this->cleanConstraints($contraints);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * Retourne true si l'utilisateur veux une période précise
|
|
|
|
|
+ * @param $historical
|
|
|
|
|
+ * @return bool
|
|
|
|
|
+ */
|
|
|
|
|
+ private function hasCustomPeriods($historical): bool{
|
|
|
|
|
+ return $historical['dateStart'] && $historical['dateEnd'];
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * Retourne le tableau des périodes custom
|
|
|
|
|
+ * @param string $dateStart
|
|
|
|
|
+ * @param string $dateEnd
|
|
|
|
|
+ * @return string[]
|
|
|
|
|
+ */
|
|
|
|
|
+ private function getCustomPeriods(string $dateStart, string $dateEnd): array{
|
|
|
|
|
+ return [
|
|
|
|
|
+ organizationUtils::START_DATE_KEY => $dateStart,
|
|
|
|
|
+ organizationUtils::END_DATE_KEY => $dateEnd
|
|
|
|
|
+ ];
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * Fonction permettant de récupérer les périodes de début et de fin d'affichage
|
|
|
|
|
+ * @param Access $access
|
|
|
|
|
+ * @return array
|
|
|
|
|
+ * @throws \Exception
|
|
|
|
|
+ */
|
|
|
|
|
+ private function getPeriods(Access $access): array{
|
|
|
|
|
+ $organization = $access->getOrganization();
|
|
|
|
|
+ $activityYear = $access->getActivityYear();
|
|
|
|
|
+ $currentActivityYear = organizationUtils::getOrganizationCurrentActivityYear($organization);
|
|
|
|
|
+
|
|
|
|
|
+ $periods = organizationUtils::getActivityPeriodsSwitchYear($organization, $activityYear);
|
|
|
|
|
+ //Si l'année courante est l'année d'affichage choisie par l'utilisateur, alors la date de début est aujourd'hui
|
|
|
|
|
+ if($activityYear === $currentActivityYear){
|
|
|
|
|
+ $today = new \DateTime('now');
|
|
|
|
|
+ $periods[organizationUtils::START_DATE_KEY] = $today->format('Y-m-d');
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return $periods;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * Fonction permettant d'ajouter une nouvelle contrainte de date
|
|
|
|
|
+ * @param array $contraints
|
|
|
|
|
+ * @param array $newContraint
|
|
|
|
|
+ * @return array
|
|
|
|
|
+ */
|
|
|
|
|
+ private function addConstraint(array $contraints, array $newContraint): array{
|
|
|
|
|
+ $contraints = $this->mergeConstraint($contraints,$newContraint,self::START_KEY);
|
|
|
|
|
+ $contraints = $this->mergeConstraint($contraints,$newContraint,self::END_KEY);
|
|
|
|
|
+ return $contraints;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * Construit le tableau de contraintes pour une condition (start, end)
|
|
|
|
|
+ * @param array $contraints
|
|
|
|
|
+ * @param array $newContraint
|
|
|
|
|
+ * @param string $key
|
|
|
|
|
+ * @return array
|
|
|
|
|
+ */
|
|
|
|
|
+ private function mergeConstraint(array $contraints, array $newContraint, string $key): array{
|
|
|
|
|
+ if(array_key_exists($key, $newContraint)){
|
|
|
|
|
+ foreach ($newContraint[$key] as $dateKey => $arithmeticValue){
|
|
|
|
|
+ //Si la date à déjà des conditions
|
|
|
|
|
+ if(array_key_exists($dateKey, $contraints[$key])){
|
|
|
|
|
+ //Si la conditions (<, >, =, ...) n'est pas encore appliquée à la date
|
|
|
|
|
+ if(!in_array($arithmeticValue, $contraints[$key][$dateKey]))
|
|
|
|
|
+ $contraints[$key][$dateKey][] = $arithmeticValue;
|
|
|
|
|
+ }else{
|
|
|
|
|
+ $contraints[$key][$dateKey] = [$arithmeticValue];
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return $contraints;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * Nettoyage des contraintes (toutes celles supérieur à la condition cancel et les valeurs null isolées)
|
|
|
|
|
+ * @param array $constraints
|
|
|
|
|
+ * @return array
|
|
|
|
|
+ */
|
|
|
|
|
+ private function cleanConstraints(array $constraints): array{
|
|
|
|
|
+ $constraints[self::START_KEY] = $this->filterConstraint($constraints, self::START_KEY);
|
|
|
|
|
+ $constraints[self::START_KEY] = $this->clearNull($constraints, self::START_KEY);
|
|
|
|
|
+
|
|
|
|
|
+ $constraints[self::END_KEY] = $this->filterConstraint($constraints, self::END_KEY);
|
|
|
|
|
+ $constraints[self::END_KEY] = $this->clearNull($constraints, self::END_KEY);
|
|
|
|
|
+ return $constraints;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * Pour chaque contraintes appliquées à une date on vérifie qu'on ne dépasse pas la valeur cancel : c'est à dire
|
|
|
|
|
+ * la condition qui démontre que toutes les valeurs arithmétiques ont été choisies
|
|
|
|
|
+ * @param array $constraints
|
|
|
|
|
+ * @param $key
|
|
|
|
|
+ * @return array
|
|
|
|
|
+ */
|
|
|
|
|
+ private function filterConstraint(array $constraints, string $key): array{
|
|
|
|
|
+ return array_filter($constraints[$key], function($constraint){
|
|
|
|
|
+ return array_sum($constraint) < self::CANCEL_OPERATION ;
|
|
|
|
|
+ });
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * On ne conserve pas les contraintes sur des conditions start et end si ces dernieres ne possède qu'une valeur null :
|
|
|
|
|
+ * une valeur null doit obligatoirement s'appliquer avec un OR
|
|
|
|
|
+ * @param array $constraints
|
|
|
|
|
+ * @param $key
|
|
|
|
|
+ * @return array
|
|
|
|
|
+ */
|
|
|
|
|
+ private function clearNull(array $constraints, string $key): array{
|
|
|
|
|
+ if(count($constraints[$key]) === 1 && array_key_exists(self::NULL_VALUE, $constraints[$key]))
|
|
|
|
|
+ $constraints[$key] = [];
|
|
|
|
|
+ return $constraints[$key];
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * Une période est dans le présent si :
|
|
|
|
|
+ * - la date de début est plus petite ou égale (<=) à la date de fin de période à afficher
|
|
|
|
|
+ * ET
|
|
|
|
|
+ * - la date de fin est plus grande ou égale (>=) à la date de fin de période à afficher OU que la date de fin n'est pas remplie (NULL)
|
|
|
|
|
+ * @param $periods
|
|
|
|
|
+ * @return array
|
|
|
|
|
+ */
|
|
|
|
|
+ private function presentConstraint(array $periods): array{
|
|
|
|
|
+ return [
|
|
|
|
|
+ self::START_KEY => [
|
|
|
|
|
+ $periods[organizationUtils::END_DATE_KEY] => self::INF + self::EQUAL
|
|
|
|
|
+ ],
|
|
|
|
|
+ self::END_KEY => [
|
|
|
|
|
+ $periods[organizationUtils::START_DATE_KEY] => self::SUP + self::EQUAL,
|
|
|
|
|
+ self::NULL_VALUE => self::NULL
|
|
|
|
|
+ ]
|
|
|
|
|
+ ];
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * Une période est dans le passée si :
|
|
|
|
|
+ * - la date de fin est plus petite (<) que la date de début de période à afficher
|
|
|
|
|
+ * @param $periods
|
|
|
|
|
+ * @return \int[][]
|
|
|
|
|
+ */
|
|
|
|
|
+ private function pastConstraint($periods): array{
|
|
|
|
|
+ return [
|
|
|
|
|
+ self::END_KEY => [
|
|
|
|
|
+ $periods[organizationUtils::START_DATE_KEY] => self::INF
|
|
|
|
|
+ ]
|
|
|
|
|
+ ];
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * Une période est dans le future si :
|
|
|
|
|
+ * - la date de début est plus grande (>) que la date de fin de période à afficher
|
|
|
|
|
+ * @param $periods
|
|
|
|
|
+ * @return \int[][]
|
|
|
|
|
+ */
|
|
|
|
|
+ private function futurConstraint($periods): array{
|
|
|
|
|
+ return [
|
|
|
|
|
+ self::START_KEY => [
|
|
|
|
|
+ $periods[organizationUtils::END_DATE_KEY] => self::SUP
|
|
|
|
|
+ ]
|
|
|
|
|
+ ];
|
|
|
|
|
+ }
|
|
|
|
|
+}
|