* @implements RepositoryWriterInterface */ class WorkingHoursRepository implements RepositoryReaderInterface, RepositoryWriterInterface { protected const string SQL_SELECT = <<<'SQL' select "Datum" as "workingDay", "Arbeitszeit" as "workingTime", "HomeOffice" as "isHomeOfficeDay" from public."Arbeitszeiten" SQL; public function __construct(protected PDO $database) { $this->database->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); } /** * * Gibt alle vorhandenen Einträge zurück * * @return WorkingHours[] * @throws Exception * @throws PDOException */ public function findAll(): array { return $this->findFiltered(null, null); } /** * * Gibt alle vorhandenen Einträge zurück * * @param string|null $start * @param string|null $end * * @return WorkingHours[] * @throws Exception */ public function findFiltered(?string $start, ?string $end): array { $models = []; $stmt = $this->buildFindFilteredStatement($start, $end); try { $stmt->execute(); } catch (PDOException $exception) { if ($exception->getCode() === '22007' || $exception->getCode() === '22008') { throw new RepositoryBadWhereDataException($exception); } throw $exception; } while ($row = $stmt->fetch()) { $model = new WorkingHours(); $model ->setWorkingDay(new DateTime($row['workingDay'])) ->setWorkingTime(new DateInterval('P0000-00-00T' . $row['workingTime'])) ->setIsHomeOffice($row['isHomeOfficeDay']); $models[] = $model; } return $models; } protected function buildFilterString(?string $start, ?string $end): string { if (is_string($start) && is_string($end)) { return 'where "Datum" >= :start AND "Datum" <= :end '; } if (is_string($start)) { return 'where "Datum" >= :start '; } if (is_string($end)) { return 'where "Datum" <= :end '; } return ''; } protected function buildFindFilteredStatement(?string $start, ?string $end): ?PDOStatement { $query = static::SQL_SELECT . ' '; $query .= $this->buildFilterString($start, $end); $query .= 'order by "Datum"'; $stmt = $this->database->prepare($query); if (is_string($start)) { $stmt->bindParam(':start', $start); } if (is_string($end)) { $stmt->bindParam(':end', $end); } return $stmt ?: null; } /** * Gibt den Eintrag zurück, der durch die ID * * @param mixed $primary_key * * @return WorkingHours * @throws RepositoryRecordNotFoundException * @throws Exception * @throws PDOException */ public function findByKey(mixed $primary_key): WorkingHours { $stmt = $this->database->prepare(static::SQL_SELECT . ' where "Datum" = ?'); $stmt->bindParam(1, $primary_key); $stmt->execute(); $row = $stmt->fetch(); if ($row === false) { throw new RepositoryRecordNotFoundException(); } $model = new WorkingHours(); $model ->setWorkingDay(new DateTime($row['workingDay'])) ->setWorkingTime(new DateInterval('P0000-00-00T' . $row['workingTime'])) ->setIsHomeOffice($row['isHomeOfficeDay']); return $model; } /** * @param WorkingHours|ModelInterface $model * * @throws RepositoryRecordAlreadyExistException * @throws Exception */ public function insert(mixed $model): void { if ($model instanceof WorkingHours) { $workingDay = $model->getWorkingDay()->format('Y-m-d'); $workingTime = $model->getWorkingTime()->format('%H:%I:%S'); $isHomeOffice = $model->isHomeOffice(); } else { throw new InvalidArgumentException('Es wird ein Modell der Klasse "' . WorkingHours::class . '" verlangt.'); } try { $this->findByKey($workingDay); throw new RepositoryRecordAlreadyExistException(); } /** @noinspection PhpUnusedLocalVariableInspection */ catch (RepositoryRecordNotFoundException $exception) { $stmt = $this->database->prepare(<<<'SQL' insert into public."Arbeitszeiten" ("Datum", "Arbeitszeit", "HomeOffice") values (?, ?, ?) on conflict do nothing SQL ); $stmt->bindParam(1, $workingDay); $stmt->bindParam(2, $workingTime); $stmt->bindParam(3, $isHomeOffice, PDO::PARAM_BOOL); $stmt->execute(); } } /** * @param WorkingHours|ModelInterface $model * * @throws RepositoryRecordNotFoundException */ public function update(mixed $model): void { if ($model instanceof WorkingHours) { $workingDay = $model->getWorkingDay()->format('Y-m-d'); $workingTime = $model->getWorkingTime()->format('%H:%I:%S'); $isHomeOffice = $model->isHomeOffice(); } else { throw new InvalidArgumentException('Es wird ein Modell der Klasse "' . WorkingHours::class . '" verlangt.'); } $stmt = $this->database->prepare(<<<'SQL' update public."Arbeitszeiten" set "Arbeitszeit" = ?, "HomeOffice" = ? where "Datum" = ? SQL ); $stmt->bindParam(1, $workingTime); $stmt->bindParam(2, $isHomeOffice, PDO::PARAM_BOOL); $stmt->bindParam(3, $workingDay); $stmt->execute(); if ($stmt->rowCount() < 1) { throw new RepositoryRecordNotFoundException(); } } /** * @param WorkingHours|ModelInterface $model * * @throws RepositoryRecordNotFoundException */ public function delete(mixed $model): void { if ($model instanceof WorkingHours) { $workingDay = $model->getWorkingDay()->format('Y-m-d'); } else { throw new InvalidArgumentException('Es wird ein Modell der Klasse "' . WorkingHours::class . '" verlangt.'); } $stmt = $this->database->prepare('delete from public."Arbeitszeiten" where "Datum" = ?'); $stmt->bindParam(1, $workingDay); $stmt->execute(); if ($stmt->rowCount() < 1) { throw new RepositoryRecordNotFoundException(); } } }