Email delivery test step + step-form extension point

Demonstrates the drop-in pattern: adding a step with a form is a single
new file under includes/steps/, plus one small extension to the base
abstraction.

WPH_Step gains:
- render_extra($session_state) — emit extra HTML inside the step card
- handle_action($name, $input) — handle a step-specific POST and
  return a finding to record

New generic admin-post handler wph_step_action routes form submissions
to the matching step's handle_action() with nonce verification.

The email step (includes/steps/115-email.php):
- Detects 7 known SMTP plugins, surfaces default From address
- Renders a To: input prefilled with the current admin's email
- Sends via wp_mail() with wp_mail_failed capture so failures show the
  underlying error
- Records the outcome as a 'last_send' finding so it appears on the
  step card, in the summary, and in the downloadable report
This commit is contained in:
2026-06-11 18:45:47 +01:00
parent cf3007ec37
commit 0052005de1
4 changed files with 182 additions and 0 deletions

View File

@@ -10,6 +10,7 @@ add_action('admin_post_wph_download_report', 'wph_handle_download_report');
add_action('admin_post_wph_refresh_checks', 'wph_handle_refresh_checks');
add_action('admin_post_wph_download_html', 'wph_handle_download_html');
add_action('admin_post_wph_email_report', 'wph_handle_email_report');
add_action('admin_post_wph_step_action', 'wph_handle_step_action');
add_action('admin_enqueue_scripts', 'wph_enqueue_assets');
function wph_register_menu(): void {
@@ -287,6 +288,7 @@ function wph_render_step_card(WPH_Session $session, WPH_Step $step): void {
<div class="wph-escalation"><?php echo esc_html($esc); ?></div>
<?php endif; ?>
<?php wph_render_autocheck($session, $step); ?>
<?php $step->render_extra($session->data()); ?>
<p>
<label>
<strong>Status:</strong>
@@ -427,6 +429,41 @@ function wph_render_autocheck(WPH_Session $session, WPH_Step $step): void {
<?php
}
function wph_handle_step_action(): void {
if (!current_user_can('manage_options')) wp_die('Forbidden');
$step_id = isset($_POST['step']) ? sanitize_key((string) $_POST['step']) : '';
$action_name = isset($_POST['step_action']) ? sanitize_key((string) $_POST['step_action']) : '';
check_admin_referer('wph_step_action_' . $step_id . '_' . $action_name);
$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.');
// 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']) : '';