DateTimeFilter.php 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. <?php
  2. declare(strict_types=1);
  3. namespace App\Filter\DoctrineFilter;
  4. use App\Annotation\DateTimeConstraintAware;
  5. use App\Service\Utils\DateTimeConstraint;
  6. use App\Service\Utils\StringsUtils;
  7. use App\Tests\Filter\DoctrineFilter\DateTimeFilterTest;
  8. use Doctrine\ORM\Mapping\ClassMetadata;
  9. use Doctrine\ORM\Query\Filter\SQLFilter;
  10. /**
  11. * Classe DateTimeFilter qui définie la requête SQL devant être ajoutée aux Entités possédant l'annotation DateTimeConstraintAware
  12. */
  13. final class DateTimeFilter extends SQLFilter
  14. {
  15. private DateTimeConstraint $dateTimeConstraint;
  16. /**
  17. * Méthode surchargée de SQLFilter
  18. * @param ClassMetadata $targetEntity
  19. * @param string $targetTableAlias
  20. * @return string
  21. * @throws \Exception
  22. */
  23. public function addFilterConstraint(ClassMetadata $targetEntity, $targetTableAlias): string
  24. {
  25. if(!$this->hasParameter('_time_constraint')
  26. || !boolval(StringsUtils::unquote($this->getParameter('_time_constraint')))
  27. || !$this->hasParameter('accessId')
  28. )
  29. return '';
  30. $dateTimeConstraintAware = $targetEntity->getReflectionClass()->getAttributes(DateTimeConstraintAware::class)[0] ?? null;
  31. $startFieldName = $dateTimeConstraintAware?->getArguments()['startDateFieldName'] ?? null;
  32. $endFieldName = $dateTimeConstraintAware?->getArguments()['endDateFieldName'] ?? null;
  33. if ($startFieldName === '' || is_null($startFieldName) || $endFieldName === '' || is_null($endFieldName)) {
  34. return '';
  35. }
  36. $accessId = intval(StringsUtils::unquote($this->getParameter('accessId')));
  37. $constraints = $this->dateTimeConstraint->invoke($accessId);
  38. $fields = [
  39. DateTimeConstraint::START_KEY => $startFieldName,
  40. DateTimeConstraint::END_KEY => $endFieldName
  41. ];
  42. return $this->constructQuery($constraints, $targetTableAlias, $fields);
  43. }
  44. /**
  45. * Fonction permettant de construire la requête SQL correspondante aux contraintes
  46. * @param array $constraints
  47. * @param string $targetTableAlias
  48. * @param array $fields
  49. * @return string
  50. */
  51. private function constructQuery(array $constraints, string $targetTableAlias, array $fields): string{
  52. $queryConditionsAND = [];
  53. foreach ($constraints as $key => $constraint) {
  54. $queryConditionsOR = [];
  55. foreach ($constraint as $date => $conditions){
  56. foreach ($conditions as $condition){
  57. $arithmetic = $this->getArithmeticValue($condition);
  58. if(!is_null($arithmetic))
  59. $queryConditionsOR[] = sprintf("%s.%s %s '%s'", $targetTableAlias, $fields[$key], $arithmetic, $date);
  60. else
  61. $queryConditionsOR[] = sprintf("%s.%s IS NULL", $targetTableAlias, $fields[$key]);
  62. }
  63. }
  64. if(!empty($queryConditionsOR))
  65. $queryConditionsAND[] = sprintf("(%s)", join(' OR ', $queryConditionsOR));
  66. }
  67. return join(" AND ", $queryConditionsAND);
  68. }
  69. /**
  70. * Fonction retournant la valeur arithmétique correspondant à la condition de la contrainte
  71. * @param $condition
  72. * @return string|null
  73. * @see DateTimeFilterTest::testGetArithmeticValue()
  74. */
  75. private function getArithmeticValue($condition): string|null{
  76. switch ($condition){
  77. case DateTimeConstraint::INF : return '<';
  78. case DateTimeConstraint::EQUAL : return '=';
  79. case DateTimeConstraint::SUP : return '>';
  80. case DateTimeConstraint::INF + DateTimeConstraint::EQUAL : return '<=';
  81. case DateTimeConstraint::SUP + DateTimeConstraint::EQUAL : return '>=';
  82. }
  83. return null;
  84. }
  85. /**
  86. * Permets d'assurer l'injection de dépendance du service DateTimeConstraint
  87. * @param DateTimeConstraint $dateTimeConstraint
  88. */
  89. public function setDateTimeConstraint(DateTimeConstraint $dateTimeConstraint){
  90. $this->dateTimeConstraint = $dateTimeConstraint;
  91. }
  92. }