diff --git a/Controller/ManageController.php b/Controller/ManageController.php index ab4e250..8ed811c 100644 --- a/Controller/ManageController.php +++ b/Controller/ManageController.php @@ -92,7 +92,9 @@ public function create(Request $request): Response if ($form->isSubmitted() && $form->isValid()) { try { - $this->manageService->create($sharedProject, $form->get('password')->getData()); + /** @var string $password */ + $password = $form->get('password')->getData(); + $this->manageService->create($sharedProject, $password); $this->flashSuccess('action.update.success'); return $this->redirectToRoute('manage_shared_project_timesheets'); @@ -127,7 +129,9 @@ public function update(SharedProjectTimesheet $sharedProject, string $shareKey, if ($form->isSubmitted() && $form->isValid()) { try { - $this->manageService->update($sharedProject, $form->get('password')->getData()); + /** @var string $password */ + $password = $form->get('password')->getData(); + $this->manageService->update($sharedProject, $password); $this->flashSuccess('action.update.success'); return $this->redirectToRoute('manage_shared_project_timesheets'); diff --git a/Controller/ViewController.php b/Controller/ViewController.php index d12a6b2..8173f51 100644 --- a/Controller/ViewController.php +++ b/Controller/ViewController.php @@ -49,7 +49,11 @@ public function indexAction(#[MapEntity(mapping: ['shareKey' => 'shareKey'])] Sh return $this->renderCustomerView($sharedPortal, $request); } - return $this->renderProjectView($sharedPortal, $sharedPortal->getProject(), $request); + if ($sharedPortal->getProject() !== null) { + return $this->renderProjectView($sharedPortal, $sharedPortal->getProject(), $request); + } + + throw $this->createNotFoundException('Invalid shared portal: neither customer nor project is set'); } #[Route(path: '/auth/shared-project-timesheets/customer/{customer}/{shareKey}/project/{project}', methods: ['GET', 'POST'])] @@ -161,7 +165,7 @@ private function renderProjectView(SharedProjectTimesheet $sharedProject, Projec ? $this->viewService->getMonthlyStats($sharedProject, $year, $month, $project) : null; // we cannot call $this->getDateTimeFactory() as it throws a AccessDeniedException for anonymous users - $timezone = $project->getCustomer()->getTimezone() ?? date_default_timezone_get(); + $timezone = $project->getCustomer()?->getTimezone() ?? date_default_timezone_get(); $date = new \DateTimeImmutable('now', new \DateTimeZone($timezone)); $stats = $this->projectStatisticService->getBudgetStatisticModel($project, $date); diff --git a/Model/TimeRecord.php b/Model/TimeRecord.php index 3c2aed4..bae56c1 100644 --- a/Model/TimeRecord.php +++ b/Model/TimeRecord.php @@ -48,6 +48,14 @@ public static function fromTimesheet(Timesheet $timesheet, string $mergeMode = R throw new \InvalidArgumentException("Invalid merge mode given: $mergeMode"); } + if ($timesheet->getBegin() === null) { + throw new \InvalidArgumentException('Timesheet without begin date is not supported'); + } + + if ($timesheet->getUser() === null) { + throw new \InvalidArgumentException('Timesheet without user is not supported'); + } + $record = new TimeRecord($timesheet->getBegin(), $timesheet->getUser(), $mergeMode); $record->addTimesheet($timesheet); diff --git a/Repository/SharedProjectTimesheetRepository.php b/Repository/SharedProjectTimesheetRepository.php index fbc98a0..117768f 100644 --- a/Repository/SharedProjectTimesheetRepository.php +++ b/Repository/SharedProjectTimesheetRepository.php @@ -72,6 +72,10 @@ public function getProjects(SharedProjectTimesheet $sharedProject): array return [$sharedProject->getProject()]; } + if ($sharedProject->getCustomer() === null) { + throw new \InvalidArgumentException('Unsupported, needs a customer'); + } + /** @var ProjectRepository $projectRepository */ $projectRepository = $this->_em->getRepository(Project::class); // @phpstan-ignore varTag.type diff --git a/Service/ManageService.php b/Service/ManageService.php index 52b0603..e7d6a4d 100644 --- a/Service/ManageService.php +++ b/Service/ManageService.php @@ -29,7 +29,7 @@ public function create(SharedProjectTimesheet $sharedPortal, ?string $password = if ($sharedPortal->getShareKey() === null) { $i = 0; do { - $newKey = substr(preg_replace('/[^A-Za-z0-9]+/', '', $this->getUuidV4()), 0, 20); + $newKey = substr(preg_replace('/[^A-Za-z0-9]+/', '', $this->getUuidV4()), 0, 20); // @phpstan-ignore argument.type $existingEntry = $this->repository->findByShareKey($newKey); // make sure we exit in case we cannot generate a new key diff --git a/Service/ViewService.php b/Service/ViewService.php index edb9cbd..2a30344 100644 --- a/Service/ViewService.php +++ b/Service/ViewService.php @@ -95,12 +95,18 @@ public function getTimeRecords(SharedProjectTimesheet $sharedProject, int $year, $timeRecords = []; $mergeMode = $sharedProject->getRecordMergeMode(); foreach ($timesheets as $timesheet) { + if ($timesheet->getBegin() === null || $timesheet->getUser() === null) { + continue; + } $dateKey = $timesheet->getBegin()->format('Y-m-d'); if (!\array_key_exists($dateKey, $timeRecords)) { $timeRecords[$dateKey] = []; } $userKey = preg_replace('/[^a-z0-9]/', '', strtolower($timesheet->getUser()->getDisplayName())); + if ($userKey === null) { + continue; + } if ($mergeMode !== RecordMergeMode::MODE_NONE) { // Assume that records from one user will be merged into one if (!\array_key_exists($userKey, $timeRecords[$dateKey])) { diff --git a/phpstan.neon b/phpstan.neon index bce88ac..63fba89 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -8,7 +8,7 @@ includes: - %rootDir%/../phpstan/conf/bleedingEdge.neon parameters: - level: 7 + level: 8 excludePaths: - vendor/(?) - tests/(?)