* * @method SeasonAssignmentTask|null find($id, $lockMode = null, $lockVersion = null) * @method SeasonAssignmentTask|null findOneBy(array $criteria, array $orderBy = null) * @method SeasonAssignmentTask[] findAll() * @method SeasonAssignmentTask[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null) */ class SeasonAssignmentTaskRepository extends ServiceEntityRepository { public function __construct(ManagerRegistry $registry) { parent::__construct($registry, SeasonAssignmentTask::class); } /** * Every open entry that could still be reminded about: not ticked off, on a live assignment * that has a teamer on it. * * The deadlines themselves are not part of this query. They are computed from the * assignment's first day by a relative offset, and month arithmetic is not invertible * day by day - "minus one month" from the 31st and back again lands somewhere else - so a * query built by inverting the offset would silently skip entries. The reminder resolves * every row through SeasonTaskDeadlineResolver instead; the set is small, one assignment per * all-season teamer per season. * * @return SeasonAssignmentTask[] */ public function findOpen(?\DateTimeImmutable $windowStart = null, ?\DateTimeImmutable $windowEnd = null): array { return $this ->createOpenQueryBuilder($windowStart, $windowEnd) ->getQuery() ->getResult() ; } /** * Extracted so the conditions can be pinned by a test compiling the DQL - the suite has no * fixtures, so what is asserted is what the query says, not what it returns. */ public function createOpenQueryBuilder( ?\DateTimeImmutable $windowStart = null, ?\DateTimeImmutable $windowEnd = null, ): QueryBuilder { $qb = $this->createQueryBuilder('task'); $qb ->select('task', 'season_assignment', 'teamer') ->innerJoin('task.seasonAssignment', 'season_assignment') // no teamer means nobody to remind and nobody to be late ->innerJoin('season_assignment.teamer', 'teamer') ->where($qb->expr()->andX( $qb->expr()->eq('task.done', ':done'), $qb->expr()->isNull('season_assignment.deletedAt'), $qb->expr()->isNull('teamer.deletedAt') )) ->setParameter('done', false) ->addOrderBy('teamer.lastName', \SortDirection::Ascending) ->addOrderBy('teamer.firstName', \SortDirection::Ascending) ; if (null !== $windowStart) { $qb ->andWhere($qb->expr()->gte('season_assignment.dateFrom', ':windowStart')) ->setParameter('windowStart', $windowStart) ; } if (null !== $windowEnd) { $qb ->andWhere($qb->expr()->lte('season_assignment.dateFrom', ':windowEnd')) ->setParameter('windowEnd', $windowEnd) ; } return $qb; } }