From 77afa207e01553935642e9221e4124274e64fdad Mon Sep 17 00:00:00 2001 From: Kevin Papst Date: Tue, 24 Feb 2026 13:27:48 +0100 Subject: [PATCH] Allow to customize statistic queries (#5827) * use TimesheetStatisticsQUery for all repository calls * send event to customize statistics query --- .../AbstractUserReportController.php | 3 +- .../Reporting/UserYearController.php | 3 +- src/Event/TimesheetStatisticsQueryEvent.php | 25 ++++++++++++ src/Timesheet/TimesheetStatisticService.php | 32 +++++++++++---- .../TimesheetStatisticsQueryEventTest.php | 31 ++++++++++++++ .../Event/WorkingTimeQueryStatsEventTest.php | 40 +++++++++++++++++++ 6 files changed, 124 insertions(+), 10 deletions(-) create mode 100644 src/Event/TimesheetStatisticsQueryEvent.php create mode 100644 tests/Event/TimesheetStatisticsQueryEventTest.php create mode 100644 tests/Event/WorkingTimeQueryStatsEventTest.php diff --git a/src/Controller/Reporting/AbstractUserReportController.php b/src/Controller/Reporting/AbstractUserReportController.php index 59f92008..d2680232 100644 --- a/src/Controller/Reporting/AbstractUserReportController.php +++ b/src/Controller/Reporting/AbstractUserReportController.php @@ -16,6 +16,7 @@ use App\Model\DateStatisticInterface; use App\Model\Statistic\StatisticDate; use App\Repository\ActivityRepository; use App\Repository\ProjectRepository; +use App\Repository\Query\TimesheetStatisticQuery; use App\Timesheet\TimesheetStatisticService; use DateTimeInterface; @@ -37,7 +38,7 @@ abstract class AbstractUserReportController extends AbstractController protected function getStatisticDataRaw(DateTimeInterface $begin, DateTimeInterface $end, User $user): array { - return $this->statisticService->getDailyStatisticsGrouped($begin, $end, [$user]); + return $this->statisticService->getDailyStatisticsGrouped(new TimesheetStatisticQuery($begin, $end, [$user])); } protected function createStatisticModel(DateTimeInterface $begin, DateTimeInterface $end, User $user): DateStatisticInterface diff --git a/src/Controller/Reporting/UserYearController.php b/src/Controller/Reporting/UserYearController.php index 6e2bbdf9..22867ba9 100644 --- a/src/Controller/Reporting/UserYearController.php +++ b/src/Controller/Reporting/UserYearController.php @@ -17,6 +17,7 @@ use App\Model\DateStatisticInterface; use App\Model\MonthlyStatistic; use App\Reporting\YearByUser\YearByUser; use App\Reporting\YearByUser\YearByUserForm; +use App\Repository\Query\TimesheetStatisticQuery; use DateTime; use DateTimeInterface; use PhpOffice\PhpSpreadsheet\Reader\Html; @@ -125,7 +126,7 @@ final class UserYearController extends AbstractUserReportController protected function getStatisticDataRaw(DateTimeInterface $begin, DateTimeInterface $end, User $user): array { - return $this->statisticService->getMonthlyStatisticsGrouped($begin, $end, [$user]); + return $this->statisticService->getMonthlyStatisticsGrouped(new TimesheetStatisticQuery($begin, $end, [$user])); } protected function createStatisticModel(DateTimeInterface $begin, DateTimeInterface $end, User $user): DateStatisticInterface diff --git a/src/Event/TimesheetStatisticsQueryEvent.php b/src/Event/TimesheetStatisticsQueryEvent.php new file mode 100644 index 00000000..c19a33f1 --- /dev/null +++ b/src/Event/TimesheetStatisticsQueryEvent.php @@ -0,0 +1,25 @@ +queryBuilder; + } +} diff --git a/src/Timesheet/TimesheetStatisticService.php b/src/Timesheet/TimesheetStatisticService.php index 82db0ff2..285bd3ef 100644 --- a/src/Timesheet/TimesheetStatisticService.php +++ b/src/Timesheet/TimesheetStatisticService.php @@ -10,15 +10,19 @@ namespace App\Timesheet; use App\Entity\User; +use App\Event\TimesheetStatisticsQueryEvent; use App\Model\DailyStatistic; use App\Model\MonthlyStatistic; use App\Repository\Query\TimesheetStatisticQuery; use App\Repository\TimesheetRepository; -use DateTimeInterface; +use Psr\EventDispatcher\EventDispatcherInterface; final class TimesheetStatisticService { - public function __construct(private readonly TimesheetRepository $repository) + public function __construct( + private readonly TimesheetRepository $repository, + private readonly EventDispatcherInterface $eventDispatcher + ) { } @@ -72,6 +76,8 @@ final class TimesheetStatisticService ; } + $this->eventDispatcher->dispatch(new TimesheetStatisticsQueryEvent($qb)); + $results = $qb->getQuery()->getResult(); foreach ($results as $row) { @@ -96,13 +102,14 @@ final class TimesheetStatisticService /** * @internal only for core development - * @param DateTimeInterface $begin - * @param DateTimeInterface $end - * @param User[] $users * @return array */ - public function getDailyStatisticsGrouped(DateTimeInterface $begin, DateTimeInterface $end, array $users): array + public function getDailyStatisticsGrouped(TimesheetStatisticQuery $query): array { + $begin = $query->getBegin(); + $end = $query->getEnd(); + $users = $query->getUsers(); + $stats = []; $usersById = []; @@ -137,6 +144,8 @@ final class TimesheetStatisticService ->addGroupBy('billable') ; + $this->eventDispatcher->dispatch(new TimesheetStatisticsQueryEvent($qb)); + $results = $qb->getQuery()->getResult(); foreach ($results as $row) { @@ -173,11 +182,14 @@ final class TimesheetStatisticService /** * @internal only for core development - * @param User[] $users * @return array */ - public function getMonthlyStatisticsGrouped(DateTimeInterface $begin, DateTimeInterface $end, array $users): array + public function getMonthlyStatisticsGrouped(TimesheetStatisticQuery $query): array { + $begin = $query->getBegin(); + $end = $query->getEnd(); + $users = $query->getUsers(); + $stats = []; $usersById = []; @@ -214,6 +226,8 @@ final class TimesheetStatisticService ->addGroupBy('billable') ; + $this->eventDispatcher->dispatch(new TimesheetStatisticsQueryEvent($qb)); + $results = $qb->getQuery()->getResult(); foreach ($results as $row) { @@ -311,6 +325,8 @@ final class TimesheetStatisticService ; } + $this->eventDispatcher->dispatch(new TimesheetStatisticsQueryEvent($qb)); + $results = $qb->getQuery()->getResult(); foreach ($results as $row) { diff --git a/tests/Event/TimesheetStatisticsQueryEventTest.php b/tests/Event/TimesheetStatisticsQueryEventTest.php new file mode 100644 index 00000000..deddc7b6 --- /dev/null +++ b/tests/Event/TimesheetStatisticsQueryEventTest.php @@ -0,0 +1,31 @@ +createMock(EntityManager::class)); + self::assertCount(0, $qb->getParameters()); + $sut = new TimesheetStatisticsQueryEvent($qb); + $qb->setParameter('foo', 'bar'); + + self::assertSame($qb, $sut->getQueryBuilder()); + self::assertCount(1, $sut->getQueryBuilder()->getParameters()); + } +} diff --git a/tests/Event/WorkingTimeQueryStatsEventTest.php b/tests/Event/WorkingTimeQueryStatsEventTest.php new file mode 100644 index 00000000..5f0cefbe --- /dev/null +++ b/tests/Event/WorkingTimeQueryStatsEventTest.php @@ -0,0 +1,40 @@ +createMock(EntityManager::class)); + self::assertCount(0, $qb->getParameters()); + + $user = new User(); + $begin = new \DateTime('2004-02-13'); + $end = new \DateTime('2099-12-31'); + + $sut = new WorkingTimeQueryStatsEvent($qb, $user, $begin, $end); + $qb->setParameter('foo', 'bar'); + + self::assertSame($qb, $sut->getQueryBuilder()); + self::assertCount(1, $sut->getQueryBuilder()->getParameters()); + self::assertSame($user, $sut->getUser()); + self::assertSame($begin, $sut->getBegin()); + self::assertSame($end, $sut->getEnd()); + } +}