id <=> $right->id; } ); return $jobs; } /** * Liefert einen Job anhand seiner lokalen ID. * * @param int $id Lokale ID. * @return Job|null */ public function find( int $id ): ?Job { foreach ( $this->all() as $job ) { if ( $job->id === $id ) { return $job; } } return null; } /** * Legt einen Job an oder aktualisiert ihn. * * @param Job $job Zu speichernder Job. * @return Job Der gespeicherte Job, bei Neuanlage mit vergebener ID. */ public function save( Job $job ): Job { $jobs = $this->fresh(); if ( 0 === $job->id ) { $data = $job->to_array(); $data['id'] = $this->next_id( $jobs ); $job = Job::from_array( $data ); $jobs[] = $job; } else { $found = false; foreach ( $jobs as $index => $existing ) { if ( $existing->id === $job->id ) { $jobs[ $index ] = $job; $found = true; break; } } if ( ! $found ) { $jobs[] = $job; } } $this->persist( $jobs ); return $job; } /** * Aendert einzelne Felder eines Jobs auf dem frisch gelesenen Stand. * * Der Lauf haelt seine Job-Objekte ueber Minuten; wuerde er sie am Ende * vollstaendig zurueckschreiben, ginge eine zwischenzeitliche Aenderung * im Formular verloren. Deshalb nur die genannten Felder. * * @param int $id Lokale ID. * @param array $changes Zu setzende Felder. * @return void */ public function update_fields( int $id, array $changes ): void { // Frisch gelesen: Ein inzwischen geloeschter Job bleibt geloescht, eine // Aenderung im Formular bleibt erhalten. $this->fresh(); $job = $this->find( $id ); if ( $job instanceof Job ) { $this->save( $job->with( $changes ) ); } } /** * Loescht einen Job. * * @param int $id Lokale ID. * @return bool True, wenn ein Job entfernt wurde. */ public function delete( int $id ): bool { $jobs = $this->fresh(); $remaining = array(); $removed = false; foreach ( $jobs as $job ) { if ( $job->id === $id ) { $removed = true; continue; } $remaining[] = $job; } if ( $removed ) { $this->persist( $remaining ); } return $removed; } /** * Ob mindestens ein Job eine Fehlermeldung traegt. * * @return bool */ public function has_errors(): bool { foreach ( $this->all() as $job ) { if ( '' !== $job->error ) { return true; } } return false; } /** * Die Jobs frisch aus der Datenbank, am Options-Cache vorbei. * * Die Core-Funktion get_option() cached je Prozess; ein langer Lauf kennt sonst nur den Stand * von seinem Beginn und schriebe ihn beim naechsten Speichern zurueck. * * @return Job[] */ private function fresh(): array { wp_cache_delete( self::OPTION, 'options' ); return $this->all(); } /** * Naechste freie lokale ID. * * @param Job[] $jobs Vorhandene Jobs. * @return int */ private function next_id( array $jobs ): int { $max = 0; foreach ( $jobs as $job ) { $max = max( $max, $job->id ); } return $max + 1; } /** * Schreibt die Liste zurueck. * * @param Job[] $jobs Zu speichernde Jobs. * @return void */ private function persist( array $jobs ): void { $rows = array(); foreach ( $jobs as $job ) { $rows[] = $job->to_array(); } update_option( self::OPTION, $rows, false ); } }