Carbon::now()->toIso8601String(), 'ok' => $ok, 'dry_run' => $dryRun, // Tail, not head: the summary line an operator is looking for // ("N object(s) would be created", or the refusal) is the last // thing printed, and a head-truncated log would cut off exactly it. 'output' => mb_strlen($output) > self::MAX_OUTPUT ? '…'.mb_substr($output, -self::MAX_OUTPUT) : $output, 'by' => $by, ]); } /** * The last run, or null if nobody has ever asked. * * @return array{at: Carbon, ok: bool, dry_run: bool, output: string, by: string}|null */ public function last(): ?array { $row = Settings::get(self::KEY); if (! is_array($row) || ! isset($row['at'])) { return null; } return [ // Parsed back into a Carbon so the view can put it on the wall // clock (R19) rather than printing an ISO string at somebody. 'at' => Carbon::parse((string) $row['at']), 'ok' => (bool) ($row['ok'] ?? false), 'dry_run' => (bool) ($row['dry_run'] ?? false), 'output' => (string) ($row['output'] ?? ''), 'by' => (string) ($row['by'] ?? ''), ]; } }