$wochentage * @param int $sortOrder Position in der Planungsliste (>= 0) * @param MahlzeitStatus $status * @param \DateTimeImmutable $erstelltAm * @param \DateTimeImmutable $aktualisiertAm * @param \DateTimeImmutable|null $gegessenAm */ public function __construct( public readonly int $id, public readonly string $name, public readonly string $notiz, public readonly array $wochentage, public readonly int $sortOrder, public readonly MahlzeitStatus $status, public readonly \DateTimeImmutable $erstelltAm, public readonly \DateTimeImmutable $aktualisiertAm, public readonly ?\DateTimeImmutable $gegessenAm, ) { foreach ($wochentage as $wochentag) { if (!$wochentag instanceof Wochentag) { throw new \TypeError('wochentage muss eine Liste von Wochentag sein.'); } } if ($status === MahlzeitStatus::Gegessen && $gegessenAm === null) { throw new BusinessRuleViolationException('Eine gegessene Mahlzeit benötigt einen gegessenAm-Zeitpunkt.'); } if ($status === MahlzeitStatus::Geplant && $gegessenAm !== null) { throw new BusinessRuleViolationException('Eine geplante Mahlzeit darf keinen gegessenAm-Zeitpunkt haben.'); } } /** * Anlegen einer neuen, geplanten Mahlzeit (noch keine ID – die bekommt die Persistenz). * * @param non-empty-string $name * @param non-empty-string $notiz * @param list $wochentage */ public static function anlegen( string $name, string $notiz, array $wochentage, int $sortOrder, \DateTimeImmutable $jetzt, ): self { return new self( id: 0, name: \trim($name), notiz: \trim($notiz), wochentage: $wochentage, sortOrder: $sortOrder, status: MahlzeitStatus::Geplant, erstelltAm: $jetzt, aktualisiertAm: $jetzt, gegessenAm: null, ); } /** * Bearbeiten der Inhalt-Felder (Name, Notiz, Wochentage, Reihenfolge). * Status/Zeitstempel bleiben dabei erhalten. * * @param non-empty-string $name * @param non-empty-string $notiz * @param list $wochentage */ public function aktualisieren( string $name, string $notiz, array $wochentage, int $sortOrder, \DateTimeImmutable $jetzt, ): self { if (\trim($name) === '') { throw new BusinessRuleViolationException('name ist ein Pflichtfeld.'); } foreach ($wochentage as $wochentag) { if (!$wochentag instanceof Wochentag) { throw new BusinessRuleViolationException('wochentage enthält einen ungültigen Wochentag.'); } } return $this->neuesModell( name: \trim($name), notiz: \trim($notiz), wochentage: $wochentage, sortOrder: $sortOrder, status: $this->status, gegessenAm: $this->gegessenAm, aktualisiertAm: $jetzt, ); } public function mitSortOrder(int $sortOrder): self { if ($sortOrder < 0) { throw new BusinessRuleViolationException('sortOrder muss >= 0 sein.'); } return $this->neuesModell( name: $this->name, notiz: $this->notiz, wochentage: $this->wochentage, sortOrder: $sortOrder, status: $this->status, gegessenAm: $this->gegessenAm, aktualisiertAm: $this->aktualisiertAm, ); } public function markAsGegessen(\DateTimeImmutable $jetzt): self { if ($this->status === MahlzeitStatus::Gegessen) { return $this; } return $this->neuesModell( name: $this->name, notiz: $this->notiz, wochentage: $this->wochentage, sortOrder: $this->sortOrder, status: MahlzeitStatus::Gegessen, gegessenAm: $jetzt, aktualisiertAm: $jetzt, ); } public function markAsGeplant(\DateTimeImmutable $jetzt): self { if ($this->status === MahlzeitStatus::Geplant) { return $this; } return $this->neuesModell( name: $this->name, notiz: $this->notiz, wochentage: $this->wochentage, sortOrder: $this->sortOrder, status: MahlzeitStatus::Geplant, gegessenAm: null, aktualisiertAm: $jetzt, ); } /** * Setzt die Persistenz-ID (id) – wird vom Processor nach dem Insert verwendet. */ public function mitId(int $id): self { return new self( id: $id, name: $this->name, notiz: $this->notiz, wochentage: $this->wochentage, sortOrder: $this->sortOrder, status: $this->status, erstelltAm: $this->erstelltAm, aktualisiertAm: $this->aktualisiertAm, gegessenAm: $this->gegessenAm, ); } public function istGegessen(): bool { return $this->status === MahlzeitStatus::Gegessen; } public function istGeplant(): bool { return $this->status === MahlzeitStatus::Geplant; } /** @return list */ public function wochentage(): array { return $this->wochentage; } /** * @param non-empty-string $name * @param non-empty-string $notiz * @param list $wochentage * @param int $sortOrder * @param MahlzeitStatus $status * @param \DateTimeImmutable|null $gegessenAm * @param \DateTimeImmutable $aktualisiertAm */ private function neuesModell( string $name, string $notiz, array $wochentage, int $sortOrder, MahlzeitStatus $status, ?\DateTimeImmutable $gegessenAm, \DateTimeImmutable $aktualisiertAm, ): self { return new self( id: $this->id, name: $name, notiz: $notiz, wochentage: $wochentage, sortOrder: $sortOrder, status: $status, erstelltAm: $this->erstelltAm, aktualisiertAm: $aktualisiertAm, gegessenAm: $gegessenAm, ); } }