db = $db; $this->table = Schema::tables()['backups']; } public function create(array $fields): array { $now = gmdate('Y-m-d H:i:s'); $row = array_merge([ 'id' => wp_generate_uuid4(), 'label' => '', 'origin' => 'local', 'source_url' => '', 'file' => '', 'status' => self::BUILDING, 'size' => 0, 'summary' => [], 'created_at' => $now, 'added_at' => $now, 'job_id' => null, ], $fields); $this->write($this->db->quietly(fn () => $this->db->wpdb()->insert($this->table, self::encode($row)))); return $row; } public function find(string $id): ?array { $rows = $this->db->results($this->db->wpdb()->prepare('SELECT * FROM ' . Db::ident($this->table) . ' WHERE id = %s', $id), ARRAY_A); return $rows ? self::decode($rows[0]) : null; } public function update(string $id, array $fields): void { $this->write($this->db->quietly(fn () => $this->db->wpdb()->update($this->table, self::encode($fields), ['id' => $id]))); } public function delete(string $id): void { $this->db->quietly(fn () => $this->db->wpdb()->delete($this->table, ['id' => $id])); } /** @return array[] ready backups, newest first */ public function ready(): array { return $this->with_status(self::READY); } /** @return array[] rows with $status (added before $added_before when given), newest first */ public function with_status(string $status, ?string $added_before = null): array { $wpdb = $this->db->wpdb(); $where = $wpdb->prepare('status = %s', $status) . ($added_before !== null ? $wpdb->prepare(' AND added_at < %s', $added_before) : ''); $rows = $this->db->results('SELECT * FROM ' . Db::ident($this->table) . " WHERE {$where} ORDER BY created_at DESC, added_at DESC", ARRAY_A); return array_map([self::class, 'decode'], $rows); } /** The shape the REST API and the UI use. */ public static function to_api(array $row): array { return [ 'id' => $row['id'], 'label' => $row['label'], 'origin' => $row['origin'], 'source_url' => $row['source_url'], 'size' => (int) $row['size'], 'created_at' => $row['created_at'], 'added_at' => $row['added_at'], 'summary' => $row['summary'], ]; } private static function encode(array $row): array { if (array_key_exists('summary', $row)) { $row['summary'] = wp_json_encode($row['summary']); } return $row; } private static function decode(array $row): array { $row['size'] = (int) $row['size']; $row['summary'] = json_decode((string) $row['summary'], true) ?: []; return $row; } /** @param int|false $result */ private function write($result): void { if ($result === false) { throw new RelayError( 'db.query_failed', /* translators: %s: database error message */ esc_html(sprintf(__('Database error: %s', 'siterelay'), $this->db->wpdb()->last_error)), esc_html__('SiteRelay could not save the backup record.', 'siterelay') ); } } }