diff --git a/api/src/Controller/AbstractController.php b/api/src/Controller/AbstractController.php index c0cf8a9..b9af4ce 100644 --- a/api/src/Controller/AbstractController.php +++ b/api/src/Controller/AbstractController.php @@ -4,7 +4,9 @@ namespace TorstenHettstedt\TimekeepingApi\Controller; use JsonSerializable; use PDO; +use Psr\Container\ContainerExceptionInterface; use Psr\Container\ContainerInterface; +use Psr\Container\NotFoundExceptionInterface; use Slim\Psr7\Response; abstract class AbstractController @@ -18,6 +20,8 @@ abstract class AbstractController * @param ContainerInterface $container * * @throws NotDatabasesException + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface */ public function __construct(ContainerInterface $container) { @@ -34,7 +38,8 @@ abstract class AbstractController * * @return Response */ - protected function printResponse(Response $response, mixed $data, int $status_code): Response { + protected function printResponse(Response $response, mixed $data, int $status_code): Response + { $payload = json_encode($data); $response->getBody()->write($payload); diff --git a/api/src/Controller/PreflightController.php b/api/src/Controller/PreflightController.php index 1ac6bf9..d017f7a 100644 --- a/api/src/Controller/PreflightController.php +++ b/api/src/Controller/PreflightController.php @@ -11,6 +11,7 @@ use TorstenHettstedt\TimekeepingApi\Middleware\OriginAccessControlHandler; class PreflightController { + /** @noinspection PhpUnused */ public function preflight(Request $request, Response $response): ResponseInterface { return (new OriginAccessControlHandler())->originAccessControl($request, $response); diff --git a/api/src/Controller/WorkingHoursController.php b/api/src/Controller/WorkingHoursController.php index be291db..7b14b97 100644 --- a/api/src/Controller/WorkingHoursController.php +++ b/api/src/Controller/WorkingHoursController.php @@ -21,9 +21,9 @@ class WorkingHoursController extends AbstractController { /** - * @param Request $request - * @param Response $response - * @param mixed[] $args + * @param Request $request + * @param Response $response + * @param array $args * * @return Response * @@ -44,9 +44,9 @@ class WorkingHoursController extends AbstractController } /** - * @param Request $request - * @param Response $response - * @param mixed[] $args + * @param Request $request + * @param Response $response + * @param array $args * * @return Response * @@ -59,21 +59,29 @@ class WorkingHoursController extends AbstractController $repository = new WorkingHoursRepository($this->databases); $queryParams = $request->getQueryParams(); try { - return $this->printResponse($response, $repository->findFiltered( - $queryParams['start-date'] ?? null, - $queryParams['end-date'] ?? null - ), StatusCodeInterface::STATUS_OK); + return $this->printResponse( + $response, + $repository->findFiltered( + $queryParams['start-date'] ?? null, + $queryParams['end-date'] ?? null + ), + StatusCodeInterface::STATUS_OK + ); } catch (RepositoryBadWhereDataException $exception) { throw new HttpBadRequestException($request, 'Ein Wert für das Datum im Query ist ungültig', $exception); } catch (Exception $exception) { - throw new HttpInternalServerErrorException($request, 'Der Wert für das Datum oder die Zeit ist falsch in der Datenbank', $exception); + throw new HttpInternalServerErrorException( + $request, + 'Der Wert für das Datum oder die Zeit ist falsch in der Datenbank', + $exception + ); } } /** - * @param Request $request - * @param Response $response - * @param mixed[] $args + * @param Request $request + * @param Response $response + * @param array $args * * @return Response * @@ -88,14 +96,18 @@ class WorkingHoursController extends AbstractController } catch (RepositoryRecordNotFoundException $exception) { throw new HttpNotFoundException($request, 'Der Eintrag ist nicht vorhanden.', $exception); } catch (Exception $exception) { - throw new HttpInternalServerErrorException($request, 'Der Wert für das Datum oder die Zeit ist falsch in der Datenbank', $exception); + throw new HttpInternalServerErrorException( + $request, + 'Der Wert für das Datum oder die Zeit ist falsch in der Datenbank', + $exception + ); } } /** - * @param Request $request - * @param Response $response - * @param mixed[] $args + * @param Request $request + * @param Response $response + * @param array $args * * @return Response * @@ -114,7 +126,11 @@ class WorkingHoursController extends AbstractController } catch (RepositoryRecordAlreadyExistException $exception) { throw new HttpConflictRequestException($request, 'Der Eintrag ist schon vorhanden.', $exception); } catch (Exception $exception) { - throw new HttpInternalServerErrorException($request, 'Der Wert für das Datum oder die Zeit ist falsch in der Datenbank', $exception); + throw new HttpInternalServerErrorException( + $request, + 'Der Wert für das Datum oder die Zeit ist falsch in der Datenbank', + $exception + ); } return $this->printResponse($response, $model, StatusCodeInterface::STATUS_CREATED); } diff --git a/api/src/Controller/WorkingHoursViewController.php b/api/src/Controller/WorkingHoursViewController.php index 917b163..ff26ca0 100644 --- a/api/src/Controller/WorkingHoursViewController.php +++ b/api/src/Controller/WorkingHoursViewController.php @@ -15,9 +15,9 @@ use TorstenHettstedt\TimekeepingApi\Repositories\WorkingHoursYearlyViewRepositor class WorkingHoursViewController extends AbstractController { /** - * @param Request $request - * @param Response $response - * @param mixed[] $args + * @param Request $request + * @param Response $response + * @param array $args * * @return Response * @@ -30,15 +30,17 @@ class WorkingHoursViewController extends AbstractController try { return $this->printResponse($response, $repository->findAll(), StatusCodeInterface::STATUS_OK); } catch (Exception $exception) { - throw new HttpInternalServerErrorException($request, - 'Der Wert für das Datum oder die Zeit ist falsch in der Datenbank', $exception); + throw new HttpInternalServerErrorException( + $request, + 'Der Wert für das Datum oder die Zeit ist falsch in der Datenbank', $exception + ); } } /** - * @param Request $request - * @param Response $response - * @param mixed[] $args + * @param Request $request + * @param Response $response + * @param array $args * * @return Response * @@ -51,15 +53,17 @@ class WorkingHoursViewController extends AbstractController try { return $this->printResponse($response, $repository->findAll(), StatusCodeInterface::STATUS_OK); } catch (Exception $exception) { - throw new HttpInternalServerErrorException($request, - 'Der Wert für das Datum oder die Zeit ist falsch in der Datenbank', $exception); + throw new HttpInternalServerErrorException( + $request, + 'Der Wert für das Datum oder die Zeit ist falsch in der Datenbank', $exception + ); } } /** - * @param Request $request - * @param Response $response - * @param mixed[] $args + * @param Request $request + * @param Response $response + * @param array $args * * @return Response * @@ -72,8 +76,10 @@ class WorkingHoursViewController extends AbstractController try { return $this->printResponse($response, $repository->findAll(), StatusCodeInterface::STATUS_OK); } catch (Exception $exception) { - throw new HttpInternalServerErrorException($request, - 'Der Wert für das Datum oder die Zeit ist falsch in der Datenbank', $exception); + throw new HttpInternalServerErrorException( + $request, + 'Der Wert für das Datum oder die Zeit ist falsch in der Datenbank', $exception + ); } } diff --git a/api/src/Middleware/ErrorHandler.php b/api/src/Middleware/ErrorHandler.php index 80d5f15..38985df 100644 --- a/api/src/Middleware/ErrorHandler.php +++ b/api/src/Middleware/ErrorHandler.php @@ -1,10 +1,12 @@ - + */ protected App $app; /** * ErrorHandler constructor. * - * @param App $app + * @param App $app */ public function __construct(App $app) { @@ -29,7 +34,7 @@ class ErrorHandler /** * @param Throwable $exception * - * @return mixed[] + * @return array */ #[ArrayShape([ 'timestamp' => "false|string", @@ -71,8 +76,7 @@ class ErrorHandler bool $logErrors, bool $logErrorDetails, ?LoggerInterface $logger = null - ): ResponseInterface - { + ): ResponseInterface { if ($logger !== null && $logErrors === true) { $logger->error($exception->getMessage()); } diff --git a/api/src/Middleware/JsonBodyParserMiddleware.php b/api/src/Middleware/JsonBodyParserMiddleware.php index 1c020e6..e09d5ec 100644 --- a/api/src/Middleware/JsonBodyParserMiddleware.php +++ b/api/src/Middleware/JsonBodyParserMiddleware.php @@ -13,7 +13,7 @@ class JsonBodyParserMiddleware implements MiddlewareInterface { $contentType = $request->getHeaderLine('Content-Type'); - if (strstr($contentType, 'application/json')) { + if (str_contains($contentType, 'application/json')) { $contents = json_decode(file_get_contents('php://input'), true); if (json_last_error() === JSON_ERROR_NONE) { $request = $request->withParsedBody($contents); diff --git a/api/src/Middleware/OriginAccessControlHandler.php b/api/src/Middleware/OriginAccessControlHandler.php index a62de79..6eb301c 100644 --- a/api/src/Middleware/OriginAccessControlHandler.php +++ b/api/src/Middleware/OriginAccessControlHandler.php @@ -28,15 +28,14 @@ class OriginAccessControlHandler implements MiddlewareInterface public function originAccessControl(Request $request, Response $response): Response { - $routeContext = RouteContext::fromRequest($request); $routingResults = $routeContext->getRoutingResults(); $methods = $routingResults->getAllowedMethods(); $requestHeaders = $request->getHeaderLine('Access-Control-Request-Headers'); if ($this->testRoute($request)) { - // Stunden Minuten Sekunden - $accessControlMaxAge = 24 * 60 * 60; + // Stunden Minuten Sekunden + $accessControlMaxAge = 24 * 60 * 60; $response = $response->withHeader('Access-Control-Allow-Origin', $this->buildOrigin($request)); $response = $response->withHeader('Access-Control-Allow-Methods', implode(',', $methods)); $response = $response->withHeader('Access-Control-Allow-Headers', $requestHeaders); @@ -53,6 +52,6 @@ class OriginAccessControlHandler implements MiddlewareInterface protected function buildOrigin(Request $request): string { - return $request->getHeaderLine('Origin') ?? ''; + return $request->getHeaderLine('Origin'); } } \ No newline at end of file diff --git a/api/src/Models/PeriodDesignationEnum.php b/api/src/Models/PeriodDesignationEnum.php index 8efffb6..b0d93a7 100644 --- a/api/src/Models/PeriodDesignationEnum.php +++ b/api/src/Models/PeriodDesignationEnum.php @@ -1,23 +1,16 @@ - - * - * @method static PeriodDesignationEnum WEEKLY() - * @method static PeriodDesignationEnum MONTHLY() - * @method static PeriodDesignationEnum YEARLY() */ -class PeriodDesignationEnum extends Enum +enum PeriodDesignationEnum: string { - private const WEEKLY = 'Y#W'; - private const MONTHLY = 'Y-m'; - private const YEARLY = 'Y'; + case WEEKLY = 'Y#W'; + case MONTHLY = 'Y-m'; + case YEARLY = 'Y'; } \ No newline at end of file diff --git a/api/src/Models/WorkingHours.php b/api/src/Models/WorkingHours.php index e485f31..e55e5b4 100644 --- a/api/src/Models/WorkingHours.php +++ b/api/src/Models/WorkingHours.php @@ -10,42 +10,26 @@ use JetBrains\PhpStorm\ArrayShape; class WorkingHours implements ModelInterface { - protected ?DateTime $workingDay = null; + protected ?DateTime $workingDay = null; protected ?DateInterval $workingTime = null; - /** - * @return DateTime|null - */ public function getWorkingDay(): ?DateTime { return $this->workingDay; } - /** - * @param DateTime $workingDay - * - * @return WorkingHours - */ - public function setWorkingDay(DateTime $workingDay): WorkingHours + public function setWorkingDay(DateTime $workingDay): static { $this->workingDay = $workingDay; return $this; } - /** - * @return DateInterval|null - */ public function getWorkingTime(): ?DateInterval { return $this->workingTime; } - /** - * @param DateInterval $workingTime - * - * @return WorkingHours - */ - public function setWorkingTime(DateInterval $workingTime): WorkingHours + public function setWorkingTime(DateInterval $workingTime): static { $this->workingTime = $workingTime; return $this; @@ -58,7 +42,7 @@ class WorkingHours implements ModelInterface public function jsonSerialize(): array { return [ - 'workingDay' => $this->getWorkingDay()->format('Y-m-d'), + 'workingDay' => $this->getWorkingDay()->format('Y-m-d'), 'workingTime' => $this->getWorkingTime()->format('%H:%I:%S') ]; } diff --git a/api/src/Models/WorkingHoursView.php b/api/src/Models/WorkingHoursView.php index b229ec8..bdeef5c 100644 --- a/api/src/Models/WorkingHoursView.php +++ b/api/src/Models/WorkingHoursView.php @@ -10,21 +10,12 @@ use JetBrains\PhpStorm\ArrayShape; class WorkingHoursView implements ModelInterface { - protected DateTimeInterface $period; + protected DateTimeInterface $period; protected PeriodDesignationEnum $periodDesignation; - protected int $workingDays; - protected DateInterval $totalHours; - protected DateInterval $overtime; + protected int $workingDays; + protected DateInterval $totalHours; + protected DateInterval $overtime; - /** - * WorkingHoursView constructor. - * - * @param DateTimeInterface $period - * @param PeriodDesignationEnum $periodDesignation - * @param int $workingDays - * @param DateInterval $totalHours - * @param DateInterval $overtime - */ public function __construct( DateTimeInterface $period, PeriodDesignationEnum $periodDesignation, @@ -39,41 +30,26 @@ class WorkingHoursView implements ModelInterface $this->overtime = $overtime; } - /** - * @return DateTimeInterface - */ public function getPeriod(): DateTimeInterface { return $this->period; } - /** - * @return PeriodDesignationEnum - */ public function getPeriodDesignation(): PeriodDesignationEnum { return $this->periodDesignation; } - /** - * @return int - */ public function getWorkingDays(): int { return $this->workingDays; } - /** - * @return DateInterval - */ public function getTotalHours(): DateInterval { return $this->totalHours; } - /** - * @return DateInterval - */ public function getOvertime(): DateInterval { return $this->overtime; @@ -84,17 +60,18 @@ class WorkingHoursView implements ModelInterface * * @return array */ - #[ArrayShape(['period' => "string", - 'periodDesignation' => "string", - 'totalHours' => "string", - 'workingDays' => "int", - 'overtime' => "string" + #[ArrayShape([ + 'period' => "string", + 'periodDesignation' => "string", + 'totalHours' => "string", + 'workingDays' => "int", + 'overtime' => "string" ])] public function jsonSerialize(): array { $formatOvertime = (($this->getOvertime()->invert === 1) ? '-' : '') . '%H:%I:%S'; return [ - 'period' => $this->getPeriod()->format($this->getPeriodDesignation()->getValue()), - 'periodDesignation' => strtolower($this->getPeriodDesignation()->getKey()), + 'period' => $this->getPeriod()->format($this->getPeriodDesignation()->value), + 'periodDesignation' => strtolower($this->getPeriodDesignation()->name), 'workingDays' => $this->getWorkingDays(), 'totalHours' => $this->getTotalHours()->format('%H:%I:%S'), 'overtime' => $this->getOvertime()->format($formatOvertime) diff --git a/api/src/Repositories/AbstractWorkingHoursViewRepository.php b/api/src/Repositories/AbstractWorkingHoursViewRepository.php index d8a757b..fbeb182 100644 --- a/api/src/Repositories/AbstractWorkingHoursViewRepository.php +++ b/api/src/Repositories/AbstractWorkingHoursViewRepository.php @@ -18,9 +18,8 @@ abstract class AbstractWorkingHoursViewRepository implements RepositoryReaderInt { protected const SQL_SELECT = ''; - protected const SQL_WHERE = ''; + protected const SQL_WHERE = ''; - protected PDO $database; protected PeriodDesignationEnum $periodDesignation; /** @@ -28,9 +27,8 @@ abstract class AbstractWorkingHoursViewRepository implements RepositoryReaderInt * * @param PDO $database */ - public function __construct(PDO $database) + public function __construct(protected PDO $database) { - $this->database = $database; $this->database->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); } @@ -51,7 +49,7 @@ abstract class AbstractWorkingHoursViewRepository implements RepositoryReaderInt $model = new WorkingHoursView( $this->buildDateFromPeriod($row['period']), $this->periodDesignation, - (int) $row['workingDays'], + (int)$row['workingDays'], $this->buildDateInterval($row['totalHours']), $this->buildDateInterval($row['overtime']) ); @@ -82,7 +80,7 @@ abstract class AbstractWorkingHoursViewRepository implements RepositoryReaderInt return new WorkingHoursView( $this->buildDateFromPeriod($row['period']), $this->periodDesignation, - (int) $row['workingDays'], + (int)$row['workingDays'], $this->buildDateInterval($row['totalHours']), $this->buildDateInterval($row['overtime']) ); diff --git a/api/src/Repositories/RepositoryReaderInterface.php b/api/src/Repositories/RepositoryReaderInterface.php index 00aa1dc..97eb4df 100644 --- a/api/src/Repositories/RepositoryReaderInterface.php +++ b/api/src/Repositories/RepositoryReaderInterface.php @@ -3,8 +3,10 @@ namespace TorstenHettstedt\TimekeepingApi\Repositories; +use TorstenHettstedt\TimekeepingApi\Models\ModelInterface; + /** - * @template T of \TorstenHettstedt\TimekeepingApi\Models\ModelInterface + * @template T of ModelInterface */ interface RepositoryReaderInterface { diff --git a/api/src/Repositories/RepositoryWriterInterface.php b/api/src/Repositories/RepositoryWriterInterface.php index bc5f8fc..8c7241d 100644 --- a/api/src/Repositories/RepositoryWriterInterface.php +++ b/api/src/Repositories/RepositoryWriterInterface.php @@ -3,8 +3,10 @@ namespace TorstenHettstedt\TimekeepingApi\Repositories; +use TorstenHettstedt\TimekeepingApi\Models\ModelInterface; + /** - * @template T of \TorstenHettstedt\TimekeepingApi\Models\ModelInterface + * @template T of ModelInterface */ interface RepositoryWriterInterface { diff --git a/api/src/Repositories/WorkingHoursMonthlyViewRepository.php b/api/src/Repositories/WorkingHoursMonthlyViewRepository.php index eb73c7e..a307076 100644 --- a/api/src/Repositories/WorkingHoursMonthlyViewRepository.php +++ b/api/src/Repositories/WorkingHoursMonthlyViewRepository.php @@ -13,22 +13,19 @@ class WorkingHoursMonthlyViewRepository extends AbstractWorkingHoursViewReposito { protected const SQL_SELECT = <<periodDesignation = PeriodDesignationEnum::MONTHLY(); + $this->periodDesignation = PeriodDesignationEnum::MONTHLY; } protected function buildDateFromPeriod(string $period): DateTimeInterface diff --git a/api/src/Repositories/WorkingHoursRepository.php b/api/src/Repositories/WorkingHoursRepository.php index 82c81d1..3434753 100644 --- a/api/src/Repositories/WorkingHoursRepository.php +++ b/api/src/Repositories/WorkingHoursRepository.php @@ -21,16 +21,8 @@ use TorstenHettstedt\TimekeepingApi\Models\WorkingHours; class WorkingHoursRepository implements RepositoryReaderInterface, RepositoryWriterInterface { - protected PDO $database; - - /** - * WorkingHoursRepository constructor. - * - * @param PDO $database - */ - public function __construct(PDO $database) + public function __construct(protected PDO $database) { - $this->database = $database; $this->database->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); } @@ -106,7 +98,7 @@ class WorkingHoursRepository implements RepositoryReaderInterface, RepositoryWri if (is_string($end)) { $stmt->bindParam(':end', $end); } - return $stmt ?? null; + return $stmt ?: null; } /** @@ -121,7 +113,9 @@ class WorkingHoursRepository implements RepositoryReaderInterface, RepositoryWri */ public function findByKey(mixed $primary_key): WorkingHours { - $stmt = $this->database->prepare('select "Datum" as "workingDay", "Arbeitszeit" as "workingTime" from public."Arbeitszeiten" where "Datum" = ?'); + $stmt = $this->database->prepare( + 'select "Datum" as "workingDay", "Arbeitszeit" as "workingTime" from public."Arbeitszeiten" where "Datum" = ?' + ); $stmt->bindParam(1, $primary_key); $stmt->execute(); $row = $stmt->fetch(); @@ -155,7 +149,9 @@ class WorkingHoursRepository implements RepositoryReaderInterface, RepositoryWri throw new RepositoryRecordAlreadyExistException(); } /** @noinspection PhpUnusedLocalVariableInspection */ catch (RepositoryRecordNotFoundException $exception) { - $stmt = $this->database->prepare('insert into public."Arbeitszeiten" ("Datum", "Arbeitszeit") values (?, ?) on conflict do nothing'); + $stmt = $this->database->prepare( + 'insert into public."Arbeitszeiten" ("Datum", "Arbeitszeit") values (?, ?) on conflict do nothing' + ); $stmt->bindParam(1, $workingDay); $stmt->bindParam(2, $workingTime); $stmt->execute(); diff --git a/api/src/Repositories/WorkingHoursWeeklyViewRepository.php b/api/src/Repositories/WorkingHoursWeeklyViewRepository.php index d1043e1..e0f383b 100644 --- a/api/src/Repositories/WorkingHoursWeeklyViewRepository.php +++ b/api/src/Repositories/WorkingHoursWeeklyViewRepository.php @@ -12,22 +12,19 @@ class WorkingHoursWeeklyViewRepository extends AbstractWorkingHoursViewRepositor { protected const SQL_SELECT = <<periodDesignation = PeriodDesignationEnum::WEEKLY(); + $this->periodDesignation = PeriodDesignationEnum::WEEKLY; } protected function buildDateFromPeriod(string $period): DateTimeInterface diff --git a/api/src/Repositories/WorkingHoursYearlyViewRepository.php b/api/src/Repositories/WorkingHoursYearlyViewRepository.php index 1efb106..522e37b 100644 --- a/api/src/Repositories/WorkingHoursYearlyViewRepository.php +++ b/api/src/Repositories/WorkingHoursYearlyViewRepository.php @@ -12,22 +12,19 @@ class WorkingHoursYearlyViewRepository extends AbstractWorkingHoursViewRepositor { protected const SQL_SELECT = <<periodDesignation = PeriodDesignationEnum::YEARLY(); + $this->periodDesignation = PeriodDesignationEnum::YEARLY; } /**