diff --git a/src/API/BaseApiController.php b/src/API/BaseApiController.php index f1369c37..94bf9ba1 100644 --- a/src/API/BaseApiController.php +++ b/src/API/BaseApiController.php @@ -12,6 +12,7 @@ declare(strict_types=1); namespace App\API; use App\Entity\User; +use App\Timesheet\DateTimeFactory; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\Form\Extension\Core\Type\DateTimeType; @@ -22,4 +23,13 @@ abstract class BaseApiController extends AbstractController { public const DATE_FORMAT = DateTimeType::HTML5_FORMAT; public const DATE_FORMAT_PHP = 'Y-m-d\TH:i:s'; + + protected function getDateTimeFactory(?User $user = null): DateTimeFactory + { + if (null === $user) { + $user = $this->getUser(); + } + + return new DateTimeFactory(new \DateTimeZone($user->getTimezone())); + } } diff --git a/src/API/ProjectController.php b/src/API/ProjectController.php index a32f9ade..c392ecbe 100644 --- a/src/API/ProjectController.php +++ b/src/API/ProjectController.php @@ -11,7 +11,6 @@ declare(strict_types=1); namespace App\API; -use App\Entity\Customer; use App\Entity\Project; use App\Entity\ProjectRate; use App\Entity\User; @@ -21,7 +20,6 @@ use App\Form\API\ProjectRateApiForm; use App\Repository\ProjectRateRepository; use App\Repository\ProjectRepository; use App\Repository\Query\ProjectQuery; -use App\Timesheet\UserDateTimeFactory; use App\Utils\SearchTerm; use FOS\RestBundle\Controller\Annotations as Rest; use FOS\RestBundle\Controller\Annotations\RouteResource; @@ -62,21 +60,16 @@ class ProjectController extends BaseApiController * @var EventDispatcherInterface */ private $dispatcher; - /** - * @var UserDateTimeFactory - */ - private $dateTime; /** * @var ProjectRateRepository */ private $projectRateRepository; - public function __construct(ViewHandlerInterface $viewHandler, ProjectRepository $repository, EventDispatcherInterface $dispatcher, UserDateTimeFactory $dateTime, ProjectRateRepository $projectRateRepository) + public function __construct(ViewHandlerInterface $viewHandler, ProjectRepository $repository, EventDispatcherInterface $dispatcher, ProjectRateRepository $projectRateRepository) { $this->viewHandler = $viewHandler; $this->repository = $repository; $this->dispatcher = $dispatcher; - $this->dateTime = $dateTime; $this->projectRateRepository = $projectRateRepository; } @@ -143,16 +136,17 @@ class ProjectController extends BaseApiController } if (!$ignoreDates) { + $factory = $this->getDateTimeFactory(); if (null !== ($begin = $paramFetcher->get('start')) && !empty($begin)) { - $query->setProjectStart($this->dateTime->createDateTime($begin)); + $query->setProjectStart($factory->createDateTime($begin)); } if (null !== ($end = $paramFetcher->get('end')) && !empty($end)) { - $query->setProjectEnd($this->dateTime->createDateTime($end)); + $query->setProjectEnd($factory->createDateTime($end)); } if (empty($begin) && empty($end)) { - $now = $this->dateTime->createDateTime(); + $now = $factory->createDateTime(); $query->setProjectStart($now); $query->setProjectEnd($now); } diff --git a/src/API/TimesheetController.php b/src/API/TimesheetController.php index 57b346cd..470b2f08 100644 --- a/src/API/TimesheetController.php +++ b/src/API/TimesheetController.php @@ -12,7 +12,6 @@ declare(strict_types=1); namespace App\API; use App\Configuration\TimesheetConfiguration; -use App\Entity\Timesheet; use App\Entity\User; use App\Event\TimesheetMetaDefinitionEvent; use App\Form\API\TimesheetApiEditForm; @@ -23,7 +22,6 @@ use App\Timesheet\RoundingService; use App\Timesheet\TimesheetService; use App\Timesheet\TrackingMode\TrackingModeInterface; use App\Timesheet\TrackingModeService; -use App\Timesheet\UserDateTimeFactory; use App\Utils\SearchTerm; use Doctrine\Common\Collections\ArrayCollection; use FOS\RestBundle\Controller\Annotations as Rest; @@ -68,10 +66,6 @@ class TimesheetController extends BaseApiController * @var TimesheetConfiguration */ private $configuration; - /** - * @var UserDateTimeFactory - */ - private $dateTime; /** * @var TagRepository */ @@ -96,7 +90,6 @@ class TimesheetController extends BaseApiController public function __construct( ViewHandlerInterface $viewHandler, TimesheetRepository $repository, - UserDateTimeFactory $dateTime, TimesheetConfiguration $configuration, TagRepository $tagRepository, TrackingModeService $trackingModeService, @@ -107,7 +100,6 @@ class TimesheetController extends BaseApiController $this->viewHandler = $viewHandler; $this->repository = $repository; $this->configuration = $configuration; - $this->dateTime = $dateTime; $this->tagRepository = $tagRepository; $this->trackingModeService = $trackingModeService; $this->dispatcher = $dispatcher; @@ -231,12 +223,14 @@ class TimesheetController extends BaseApiController $query->setOrderBy($orderBy); } + $factory = $this->getDateTimeFactory(); + if (null !== ($begin = $paramFetcher->get('begin'))) { - $query->setBegin($this->dateTime->createDateTime($begin)); + $query->setBegin($factory->createDateTime($begin)); } if (null !== ($end = $paramFetcher->get('end'))) { - $query->setEnd($this->dateTime->createDateTime($end)); + $query->setEnd($factory->createDateTime($end)); } if (null !== ($active = $paramFetcher->get('active'))) { @@ -262,7 +256,7 @@ class TimesheetController extends BaseApiController } if (!empty($modifiedAfter = $paramFetcher->get('modified_after'))) { - $query->setModifiedAfter($this->dateTime->createDateTime($modifiedAfter)); + $query->setModifiedAfter($factory->createDateTime($modifiedAfter)); } /** @var Pagerfanta $data */ @@ -519,7 +513,8 @@ class TimesheetController extends BaseApiController public function recentAction(ParamFetcherInterface $paramFetcher): Response { $user = $this->getUser(); - $begin = $this->dateTime->createDateTime('-1 year'); + $factory = $this->getDateTimeFactory(); + $begin = $factory->createDateTime('-1 year'); $limit = 10; if ($this->isGranted('view_other_timesheet') && null !== ($reqUser = $paramFetcher->get('user'))) { @@ -534,7 +529,7 @@ class TimesheetController extends BaseApiController } if (null !== ($reqBegin = $paramFetcher->get('begin'))) { - $begin = $this->dateTime->createDateTime($reqBegin); + $begin = $factory->createDateTime($reqBegin); } $data = $this->repository->getRecentActivities($user, $begin, $limit); @@ -653,7 +648,7 @@ class TimesheetController extends BaseApiController $copyTimesheet = $this->service->createNewTimesheet($user); $copyTimesheet - ->setBegin($this->dateTime->createDateTime()) + ->setBegin($this->getDateTimeFactory()->createDateTime()) ->setActivity($timesheet->getActivity()) ->setProject($timesheet->getProject()) ; diff --git a/src/Controller/CalendarController.php b/src/Controller/CalendarController.php index 39c5d625..7210ad3e 100644 --- a/src/Controller/CalendarController.php +++ b/src/Controller/CalendarController.php @@ -13,7 +13,6 @@ use App\Calendar\Google; use App\Calendar\Source; use App\Configuration\CalendarConfiguration; use App\Timesheet\TrackingModeService; -use App\Timesheet\UserDateTimeFactory; use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security; use Symfony\Component\Routing\Annotation\Route; @@ -28,14 +27,14 @@ class CalendarController extends AbstractController /** * @Route(path="/", name="calendar", methods={"GET"}) */ - public function userCalendar(CalendarConfiguration $configuration, UserDateTimeFactory $dateTime, TrackingModeService $service) + public function userCalendar(CalendarConfiguration $configuration, TrackingModeService $service) { $mode = $service->getActiveMode(); return $this->render('calendar/user.html.twig', [ 'config' => $configuration, 'google' => $this->getGoogleSources($configuration), - 'now' => $dateTime->createDateTime(), + 'now' => $this->getDateTimeFactory()->createDateTime(), 'is_punch_mode' => !$mode->canEditDuration() && !$mode->canEditBegin() && !$mode->canEditEnd() ]); } diff --git a/src/Controller/InvoiceController.php b/src/Controller/InvoiceController.php index e50b0038..add07161 100644 --- a/src/Controller/InvoiceController.php +++ b/src/Controller/InvoiceController.php @@ -22,7 +22,6 @@ use App\Repository\InvoiceRepository; use App\Repository\InvoiceTemplateRepository; use App\Repository\Query\BaseQuery; use App\Repository\Query\InvoiceQuery; -use App\Timesheet\UserDateTimeFactory; use Exception; use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security; use Symfony\Component\Form\FormInterface; @@ -49,10 +48,6 @@ final class InvoiceController extends AbstractController * @var InvoiceTemplateRepository */ private $templateRepository; - /** - * @var UserDateTimeFactory - */ - private $dateTimeFactory; /** * @var InvoiceRepository */ @@ -62,12 +57,11 @@ final class InvoiceController extends AbstractController */ private $dispatcher; - public function __construct(ServiceInvoice $service, InvoiceTemplateRepository $templateRepository, InvoiceRepository $invoiceRepository, UserDateTimeFactory $dateTimeFactory, EventDispatcherInterface $dispatcher) + public function __construct(ServiceInvoice $service, InvoiceTemplateRepository $templateRepository, InvoiceRepository $invoiceRepository, EventDispatcherInterface $dispatcher) { $this->service = $service; $this->templateRepository = $templateRepository; $this->invoiceRepository = $invoiceRepository; - $this->dateTimeFactory = $dateTimeFactory; $this->dispatcher = $dispatcher; } @@ -139,8 +133,9 @@ final class InvoiceController extends AbstractController protected function getDefaultQuery(): InvoiceQuery { - $begin = $this->dateTimeFactory->createDateTime('first day of this month'); - $end = $this->dateTimeFactory->createDateTime('last day of this month'); + $factory = $this->getDateTimeFactory(); + $begin = $factory->getStartOfMonth(); + $end = $factory->getEndOfMonth(); $query = new InvoiceQuery(); $query->setOrder(InvoiceQuery::ORDER_ASC); diff --git a/src/Controller/TimesheetAbstractController.php b/src/Controller/TimesheetAbstractController.php index 1a226467..1b67db0d 100644 --- a/src/Controller/TimesheetAbstractController.php +++ b/src/Controller/TimesheetAbstractController.php @@ -29,7 +29,6 @@ use App\Repository\TimesheetRepository; use App\Timesheet\TimesheetService; use App\Timesheet\TrackingMode\TrackingModeInterface; use App\Timesheet\TrackingModeService; -use App\Timesheet\UserDateTimeFactory; use Doctrine\Common\Collections\ArrayCollection; use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Symfony\Component\Form\FormInterface; @@ -38,10 +37,6 @@ use Symfony\Component\HttpFoundation\Response; abstract class TimesheetAbstractController extends AbstractController { - /** - * @var UserDateTimeFactory - */ - protected $dateTime; /** * @var TimesheetRepository */ @@ -64,14 +59,12 @@ abstract class TimesheetAbstractController extends AbstractController protected $service; public function __construct( - UserDateTimeFactory $dateTime, TimesheetRepository $repository, TrackingModeService $trackingModeService, EventDispatcherInterface $dispatcher, ServiceExport $exportService, TimesheetService $timesheetService ) { - $this->dateTime = $dateTime; $this->repository = $repository; $this->trackingModeService = $trackingModeService; $this->dispatcher = $dispatcher; @@ -238,16 +231,18 @@ abstract class TimesheetAbstractController extends AbstractController $form->setData($query); $form->submit($request->query->all(), false); + $factory = $this->getDateTimeFactory(); + // by default the current month is exported, but it can be overwritten // this should not be removed, otherwise we would export EVERY available record in the admin section // as the default toolbar query does neither limit the user nor the date-range! if (null === $query->getBegin()) { - $query->setBegin($this->dateTime->createDateTime('first day of this month')); + $query->setBegin($factory->getStartOfMonth()); } $query->getBegin()->setTime(0, 0, 0); if (null === $query->getEnd()) { - $query->setEnd($this->dateTime->createDateTime('last day of this month')); + $query->setEnd($factory->getEndOfMonth()); } $query->getEnd()->setTime(23, 59, 59); diff --git a/src/Form/Extension/UserExtension.php b/src/Form/Extension/UserExtension.php index 570ca8ec..fb574e3a 100644 --- a/src/Form/Extension/UserExtension.php +++ b/src/Form/Extension/UserExtension.php @@ -32,13 +32,10 @@ final class UserExtension extends AbstractTypeExtension return [FormType::class]; } - /** - * @param OptionsResolver $resolver - */ public function configureOptions(OptionsResolver $resolver) { $resolver->setDefined(['user']); - // null needs to be allowed, as there is no user for anonymoud forms (like "forgot password" and "registration") + // null needs to be allowed, as there is no user for anonymous forms (like "forgot password" and "registration") $resolver->setAllowedTypes('user', [User::class, 'null']); $resolver->setDefault('user', $this->user->getUser()); } diff --git a/src/Invoice/ServiceInvoice.php b/src/Invoice/ServiceInvoice.php index af9e4134..f0d9d149 100644 --- a/src/Invoice/ServiceInvoice.php +++ b/src/Invoice/ServiceInvoice.php @@ -19,7 +19,7 @@ use App\Event\InvoicePreRenderEvent; use App\Repository\InvoiceDocumentRepository; use App\Repository\InvoiceRepository; use App\Repository\Query\InvoiceQuery; -use App\Timesheet\UserDateTimeFactory; +use App\Timesheet\DateTimeFactory; use App\Utils\FileHelper; use Symfony\Component\HttpFoundation\BinaryFileResponse; use Symfony\Component\HttpFoundation\Response; @@ -54,10 +54,6 @@ final class ServiceInvoice * @var FileHelper */ private $fileHelper; - /** - * @var UserDateTimeFactory - */ - private $dateTimeFactory; /** * @var LanguageFormattings */ @@ -67,12 +63,11 @@ final class ServiceInvoice */ private $invoiceRepository; - public function __construct(InvoiceDocumentRepository $repository, FileHelper $fileHelper, InvoiceRepository $invoiceRepository, UserDateTimeFactory $dateTimeFactory, LanguageFormattings $formatter) + public function __construct(InvoiceDocumentRepository $repository, FileHelper $fileHelper, InvoiceRepository $invoiceRepository, LanguageFormattings $formatter) { $this->documents = $repository; $this->fileHelper = $fileHelper; $this->invoiceRepository = $invoiceRepository; - $this->dateTimeFactory = $dateTimeFactory; $this->formatter = $formatter; } @@ -272,11 +267,13 @@ final class ServiceInvoice return []; } + $factory = $this->getDateTimeFactory($query); + if (null === $query->getBegin()) { - $query->setBegin($this->dateTimeFactory->createDateTime('first day of this month')); + $query->setBegin($factory->getStartOfMonth()); } if (null === $query->getEnd()) { - $query->setEnd($this->dateTimeFactory->createDateTime('last day of this month')); + $query->setEnd($factory->getEndOfMonth()); } $query->getBegin()->setTime(0, 0, 0); $query->getEnd()->setTime(23, 59, 59); @@ -307,6 +304,17 @@ final class ServiceInvoice return $entries; } + private function getDateTimeFactory(InvoiceQuery $query): DateTimeFactory + { + $timezone = date_default_timezone_get(); + + if (null !== $query->getCurrentUser()) { + $timezone = $query->getCurrentUser()->getTimezone(); + } + + return new DateTimeFactory(new \DateTimeZone($timezone)); + } + /** * @param array $entries */ @@ -433,7 +441,7 @@ final class ServiceInvoice $model = new InvoiceModel(new DefaultInvoiceFormatter($this->formatter, $template->getLanguage())); $model ->setTemplate($template) - ->setInvoiceDate($this->dateTimeFactory->createDateTime()) + ->setInvoiceDate($this->getDateTimeFactory($query)->createDateTime()) ->setQuery($query) ; diff --git a/tests/Invoice/ServiceInvoiceTest.php b/tests/Invoice/ServiceInvoiceTest.php index 320b3ff6..13fdc561 100644 --- a/tests/Invoice/ServiceInvoiceTest.php +++ b/tests/Invoice/ServiceInvoiceTest.php @@ -20,7 +20,6 @@ use App\Invoice\ServiceInvoice; use App\Repository\InvoiceDocumentRepository; use App\Repository\InvoiceRepository; use App\Repository\Query\InvoiceQuery; -use App\Tests\Mocks\Security\UserDateTimeFactoryFactory; use App\Utils\FileHelper; use PHPUnit\Framework\TestCase; use Twig\Environment; @@ -44,9 +43,8 @@ class ServiceInvoiceTest extends TestCase $repo = new InvoiceDocumentRepository($paths); $invoiceRepo = $this->createMock(InvoiceRepository::class); - $userDateTime = (new UserDateTimeFactoryFactory($this))->create(); - return new ServiceInvoice($repo, new FileHelper(realpath(__DIR__ . '/../../var/data/')), $invoiceRepo, $userDateTime, $formattings); + return new ServiceInvoice($repo, new FileHelper(realpath(__DIR__ . '/../../var/data/')), $invoiceRepo, $formattings); } public function testInvalidExceptionOnChangeState()