Plugin skeleton, drop-in step registry, option-backed session, single-page checklist UI, downloadable Markdown report. Steps live as one file each under includes/steps/ — adding/removing one is a single file change. Step IDs are stable strings so renaming files preserves session data. Architecture (hc-5ix.3): WPH_Steps singleton globs includes/steps/*.php, natsort-orders by filename, requires each file (which returns a WPH_Step instance), then applies a 'wph_steps' filter so installs can drop steps. Session (hc-5ix.4): option-backed (per decision — plugin is installed per-engagement, so DB-resident history would be lost on uninstall). Single in-progress session per site; finished sessions render a report that the user downloads/copies. Recovery bootstrap (hc-5ix.1): detects whether wp-site-recovery is installed + active, surfaces state on the start panel and in every active session. Manual install for now; private update channel deferred to hc-5ix.27. Smoke-tested on testsite: registry discovery (13 steps in correct order), start → update_step → progress count → finish → 8KB Markdown report → discard cycle.
92 lines
3.3 KiB
PHP
92 lines
3.3 KiB
PHP
<?php
|
|
if (!defined('ABSPATH')) exit;
|
|
|
|
/**
|
|
* Build a Markdown report for a healthcheck session.
|
|
* Per bead hc-5ix.7: pure Markdown, downloadable. No DB-side report storage
|
|
* (plugin may be uninstalled at the end of the engagement).
|
|
*/
|
|
function wph_build_markdown_report(WPH_Session $session): string {
|
|
$tech = get_userdata($session->technician_id());
|
|
$tech_name = $tech ? $tech->display_name : '#' . $session->technician_id();
|
|
|
|
$lines = [];
|
|
$lines[] = '# Site Healthcheck — ' . $session->site_url();
|
|
$lines[] = '';
|
|
$lines[] = '- **Started:** ' . date('Y-m-d H:i', $session->started_at());
|
|
if ($session->is_finished()) {
|
|
$lines[] = '- **Finished:** ' . date('Y-m-d H:i', (int) $session->finished_at());
|
|
$minutes = max(1, (int) round(((int) $session->finished_at() - $session->started_at()) / 60));
|
|
$lines[] = '- **Duration:** ~' . $minutes . ' minute(s)';
|
|
}
|
|
$lines[] = '- **Technician:** ' . $tech_name;
|
|
$lines[] = '- **Site:** ' . $session->site_url();
|
|
$lines[] = '- **WordPress:** ' . $session->wp_version();
|
|
$lines[] = '- **PHP:** ' . $session->php_version();
|
|
$lines[] = '- **Session ID:** ' . $session->id();
|
|
$lines[] = '';
|
|
|
|
// Summary table
|
|
$lines[] = '## Summary';
|
|
$lines[] = '';
|
|
$lines[] = '| Step | Status |';
|
|
$lines[] = '|---|---|';
|
|
foreach (WPH_Steps::instance()->all() as $step) {
|
|
$state = $session->step_state($step->id());
|
|
$lines[] = '| ' . $step->title() . ' | ' . wph_status_label($state['status']) . ' |';
|
|
}
|
|
$lines[] = '';
|
|
|
|
// Per-step detail
|
|
$lines[] = '## Detail';
|
|
$lines[] = '';
|
|
foreach (WPH_Steps::instance()->all() as $step) {
|
|
$state = $session->step_state($step->id());
|
|
$lines[] = '### ' . $step->title();
|
|
$lines[] = '';
|
|
$lines[] = '_Status: ' . wph_status_label($state['status']) . '_';
|
|
if ($state['updated_at']) {
|
|
$lines[] = '_Saved: ' . date('Y-m-d H:i', $state['updated_at']) . '_';
|
|
}
|
|
if ($blurb = $step->blurb()) {
|
|
$lines[] = '';
|
|
$lines[] = $blurb;
|
|
}
|
|
if ($items = $step->sub_items()) {
|
|
$lines[] = '';
|
|
foreach ($items as $item) {
|
|
$lines[] = '- [ ] ' . $item;
|
|
}
|
|
}
|
|
if (!empty($state['notes'])) {
|
|
$lines[] = '';
|
|
$lines[] = '**Notes:**';
|
|
$lines[] = '';
|
|
foreach (preg_split('/\R/', (string) $state['notes']) as $nl) {
|
|
$lines[] = '> ' . $nl;
|
|
}
|
|
}
|
|
if ($state['status'] === WPH_Session::STATUS_BLOCKED && ($esc = $step->escalation())) {
|
|
$lines[] = '';
|
|
$lines[] = '> ⚠ **Escalation:** ' . $esc;
|
|
}
|
|
$lines[] = '';
|
|
}
|
|
|
|
$lines[] = '---';
|
|
$lines[] = '_Generated by Site Healthcheck plugin v' . WPH_VERSION . '_';
|
|
|
|
return implode("\n", $lines) . "\n";
|
|
}
|
|
|
|
function wph_status_label(string $status): string {
|
|
switch ($status) {
|
|
case WPH_Session::STATUS_DONE: return '✅ Done';
|
|
case WPH_Session::STATUS_SKIPPED: return '⏭ Skipped';
|
|
case WPH_Session::STATUS_BLOCKED: return '🛑 Blocked';
|
|
case WPH_Session::STATUS_NA: return '— N/A';
|
|
case WPH_Session::STATUS_NOT_STARTED:
|
|
default: return '◻ Not started';
|
|
}
|
|
}
|