'; echo '

Site Healthcheck

'; if (!$session) { wph_render_start_panel(); echo ''; return; } if ($session->is_finished()) { wph_render_finished_panel($session); echo ''; return; } wph_render_active_session($session); echo ''; } function wph_render_start_panel(): void { ?>

Start a healthcheck

This will create a new in-progress session for . One session per site at a time.

progress(); $tech = get_userdata($session->technician_id()); ?>

Session: id()); ?> · Started: started_at())); ?> · Technician: display_name : '#' . $session->technician_id()); ?> · / steps

WP wp_version()); ?> · PHP php_version()); ?> · Site site_url()); ?>

'; wph_render_sidebar($session); echo '
'; foreach (WPH_Steps::instance()->all() as $step) { wph_render_step_card($session, $step); } echo '
'; } function wph_render_sidebar(WPH_Session $session): void { echo ''; } function wph_render_blocked_summary(WPH_Session $session): void { $blocked = []; foreach (WPH_Steps::instance()->all() as $step) { $state = $session->step_state($step->id()); if ($state['status'] === WPH_Session::STATUS_BLOCKED) { $blocked[] = ['step' => $step, 'state' => $state]; } } if (!$blocked) return; echo '
'; echo '

Stop & escalate

'; echo '

The following steps are blocked. Resolve or escalate before continuing:

'; echo '
'; } function wph_render_diff_summary(WPH_Session $session): void { $prev = WPH_Session::previous(); if (!$prev) return; // Aggregate findings by step+id from each session $current_idx = []; foreach (WPH_Steps::instance()->all() as $step) { $r = $session->get_autocheck($step->id()); if (!$r) continue; foreach ($r['findings'] as $f) { $current_idx[$step->id() . '|' . $f['id']] = $f; } } $prev_idx = []; foreach (WPH_Steps::instance()->all() as $step) { $r = $prev->get_autocheck($step->id()); if (!$r) continue; foreach ($r['findings'] as $f) { $prev_idx[$step->id() . '|' . $f['id']] = $f; } } $new = $resolved = $changed = []; foreach ($current_idx as $k => $f) { if (!isset($prev_idx[$k])) { if (in_array($f['level'], ['warn', 'bad'], true)) $new[] = $f; } elseif ($prev_idx[$k]['level'] !== $f['level'] || $prev_idx[$k]['value'] !== $f['value']) { $changed[] = ['was' => $prev_idx[$k], 'now' => $f]; } } foreach ($prev_idx as $k => $f) { if (!isset($current_idx[$k]) && in_array($f['level'], ['warn', 'bad'], true)) { $resolved[] = $f; } } if (!$new && !$resolved && !$changed) return; echo '
Δ vs. previous session (finished ' . esc_html(date('Y-m-d', (int) $prev->finished_at())) . ')'; if ($new) echo ' · ' . count($new) . ' new issue(s)'; if ($resolved) echo ' · ' . count($resolved) . ' resolved'; if ($changed) echo ' · ' . count($changed) . ' changed'; echo '
'; } function wph_render_step_card(WPH_Session $session, WPH_Step $step): void { $state = $session->step_state($step->id()); $status = $state['status']; $notes = $state['notes']; ?>
id()); ?>

title()); ?>

blurb()): ?>

sub_items()): ?> watch_outs()): ?>
Watch out for:
escalation())): ?>
render_extra($session->data()); ?>

Last saved ago

Healthcheck finished

Started started_at())); ?> · Finished finished_at())); ?>

Report preview

is_finished()) wp_die('No active session.'); if (!WPH_Steps::instance()->get($step_id)) wp_die('Unknown step.'); $status = isset($_POST['status']) ? sanitize_key((string) $_POST['status']) : WPH_Session::STATUS_NOT_STARTED; $notes = isset($_POST['notes']) ? wp_unslash((string) $_POST['notes']) : ''; $session->update_step($step_id, $status, $notes); wp_safe_redirect(admin_url('tools.php?page=site-healthcheck#step-' . rawurlencode($step_id))); exit; } function wph_handle_finish(): void { if (!current_user_can('manage_options')) wp_die('Forbidden'); check_admin_referer('wph_finish'); $session = WPH_Session::current(); if (!$session) wp_die('No active session.'); $session->finish(); wp_safe_redirect(admin_url('tools.php?page=site-healthcheck')); exit; } function wph_handle_discard(): void { if (!current_user_can('manage_options')) wp_die('Forbidden'); check_admin_referer('wph_discard'); WPH_Session::discard(); wp_safe_redirect(admin_url('tools.php?page=site-healthcheck')); exit; } function wph_render_autocheck(WPH_Session $session, WPH_Step $step): void { if (!$step->has_autocheck()) return; $result = $session->get_autocheck($step->id()); ?>

Automated checks

id()); ?>

No automated checks have been run for this step yet.

'✓', 'warn' => '⚠', 'bad' => '✗', 'info' => '·'][$finding['level']] ?? '·'; ?>

Checked ago ()

is_finished()) wp_die('No active session.'); $step = WPH_Steps::instance()->get($step_id); if (!$step) wp_die('Unknown step.'); // Pass POST through unslashed so handlers see the raw user input. $input = wp_unslash($_POST); @set_time_limit(60); $finding = $step->handle_action($action_name, is_array($input) ? $input : []); if (is_array($finding)) { // Append (or replace by id) onto this step's stored findings. $existing = $session->get_autocheck($step_id); $findings = $existing['findings'] ?? []; $replaced = false; foreach ($findings as $i => $f) { if (($f['id'] ?? '') === ($finding['id'] ?? '')) { $findings[$i] = $finding; $replaced = true; break; } } if (!$replaced) $findings[] = $finding; $session->set_autocheck($step_id, $findings); } wp_safe_redirect(admin_url('tools.php?page=site-healthcheck#step-' . rawurlencode($step_id))); exit; } function wph_handle_refresh_checks(): void { if (!current_user_can('manage_options')) wp_die('Forbidden'); $step_id = isset($_POST['step']) ? sanitize_key((string) $_POST['step']) : ''; check_admin_referer('wph_refresh_checks_' . $step_id); $session = WPH_Session::current(); if (!$session || $session->is_finished()) wp_die('No active session.'); $step = WPH_Steps::instance()->get($step_id); if (!$step) wp_die('Unknown step.'); @set_time_limit(60); $findings = $step->autocheck($session->data()); $session->set_autocheck($step_id, $findings); wp_safe_redirect(admin_url('tools.php?page=site-healthcheck#step-' . rawurlencode($step_id))); exit; } function wph_handle_download_report(): void { if (!current_user_can('manage_options')) wp_die('Forbidden'); check_admin_referer('wph_download_report'); $session = WPH_Session::current(); if (!$session) wp_die('No session.'); wph_stream_report($session, 'md'); } function wph_handle_download_html(): void { if (!current_user_can('manage_options')) wp_die('Forbidden'); check_admin_referer('wph_download_html'); $session = WPH_Session::current(); if (!$session) wp_die('No session.'); wph_stream_report($session, 'html'); } function wph_stream_report(WPH_Session $session, string $format): void { $host = parse_url(get_site_url(), PHP_URL_HOST) ?: 'site'; $host = preg_replace('/[^a-z0-9.-]/i', '', (string) $host); $stamp = date('Ymd', $session->started_at() ?: time()); nocache_headers(); if ($format === 'html') { header('Content-Type: text/html; charset=UTF-8'); header('Content-Disposition: attachment; filename="wph-report-' . $host . '-' . $stamp . '.html"'); echo wph_build_html_report($session); } else { header('Content-Type: text/markdown; charset=UTF-8'); header('Content-Disposition: attachment; filename="wph-report-' . $host . '-' . $stamp . '.md"'); echo wph_build_markdown_report($session); } exit; } function wph_handle_email_report(): void { if (!current_user_can('manage_options')) wp_die('Forbidden'); check_admin_referer('wph_email_report'); $session = WPH_Session::current(); if (!$session) wp_die('No session.'); $to = isset($_POST['to']) ? sanitize_email((string) wp_unslash($_POST['to'])) : ''; if (!is_email($to)) wp_die('Bad email address.'); $host = parse_url(get_site_url(), PHP_URL_HOST) ?: 'site'; $subject = 'Site Healthcheck — ' . $host . ' — ' . date('Y-m-d', $session->started_at() ?: time()); $html = wph_build_html_report($session); $ok = wp_mail($to, $subject, $html, ['Content-Type: text/html; charset=UTF-8']); wp_safe_redirect(admin_url('tools.php?page=site-healthcheck&wph_mail=' . ($ok ? '1' : '0'))); exit; }