Recovery plugin: folder-agnostic detection + one-click install from Gitea
Detection (recovery-bootstrap.php): - Match on plugin Name + Author instead of hard-coded folder slug, so the recovery plugin is found regardless of whether it was unpacked as site-recovery/, wp-site-recovery/, or anything else. One-click install (recovery-installer.php — new): - Pulls site-recovery from a private Gitea repo via the standard archive endpoint with token auth. - Ref resolution order: latest release → latest tag → main branch HEAD. Lets us tag pinned releases in Gitea later without changing code. - upgrader_source_selection filter forces the unpacked folder name to 'site-recovery' regardless of the gitea wrapper-folder suffix. - Config from constants in wp-config.php (WPH_GITEA_HOST/OWNER/REPO/TOKEN) beats DB option storage. Constants are visually locked in the settings UI so admins can see they're inherited. Settings page (hidden submenu, reachable at Tools → Site Healthcheck → 'Configure gitea source'): - Host / Owner / Repo / Token fields - Inline 'Install now' button when configured + plugin not installed Bootstrap status panel: - Shows the recovery plugin's actual file path when active - 'Install from gitea (latest)' button when configured + missing - 'Configure gitea source' button when not configured + missing Install handler shows a success message via transient on the main healthcheck page after a successful install + activate.
This commit is contained in:
@@ -11,21 +11,41 @@ if (!defined('ABSPATH')) exit;
|
||||
*/
|
||||
final class WPH_Recovery_Bootstrap {
|
||||
|
||||
public const RECOVERY_SLUG = 'site-recovery';
|
||||
public const RECOVERY_MAIN = 'site-recovery/site-recovery.php';
|
||||
/**
|
||||
* Detect by plugin Name + Author rather than folder slug — the recovery
|
||||
* plugin can be installed under any folder (site-recovery/, wp-site-recovery/,
|
||||
* etc.) depending on how it was unpacked. Cache the result per request.
|
||||
*/
|
||||
private const NAME = 'Site Recovery';
|
||||
private const AUTHOR = 'Steve Hanlon';
|
||||
|
||||
public static function is_installed(): bool {
|
||||
/** Return the plugin_basename (folder/file.php) if installed, or null. */
|
||||
public static function plugin_file(): ?string {
|
||||
static $cached;
|
||||
if ($cached !== null) return $cached === '' ? null : $cached;
|
||||
if (!function_exists('get_plugins')) {
|
||||
require_once ABSPATH . 'wp-admin/includes/plugin.php';
|
||||
}
|
||||
return array_key_exists(self::RECOVERY_MAIN, get_plugins());
|
||||
foreach (get_plugins() as $file => $meta) {
|
||||
if (($meta['Name'] ?? '') === self::NAME && strpos((string) ($meta['Author'] ?? ''), self::AUTHOR) !== false) {
|
||||
return $cached = $file;
|
||||
}
|
||||
}
|
||||
$cached = '';
|
||||
return null;
|
||||
}
|
||||
|
||||
public static function is_installed(): bool {
|
||||
return self::plugin_file() !== null;
|
||||
}
|
||||
|
||||
public static function is_active(): bool {
|
||||
$file = self::plugin_file();
|
||||
if (!$file) return false;
|
||||
if (!function_exists('is_plugin_active')) {
|
||||
require_once ABSPATH . 'wp-admin/includes/plugin.php';
|
||||
}
|
||||
return is_plugin_active(self::RECOVERY_MAIN);
|
||||
return is_plugin_active($file);
|
||||
}
|
||||
|
||||
public static function recovery_admin_url(): string {
|
||||
@@ -34,23 +54,37 @@ final class WPH_Recovery_Bootstrap {
|
||||
|
||||
/**
|
||||
* Render a status panel that the admin page calls from the "Before you start"
|
||||
* section. Phase-1: report state + link to manage. Phase-3 may add a
|
||||
* one-click installer from a private URL.
|
||||
* section. Shows install state, links to recovery settings when active, and
|
||||
* offers a one-click install from gitea when missing+configured.
|
||||
*/
|
||||
public static function render_status(): void {
|
||||
$installed = self::is_installed();
|
||||
$active = $installed && self::is_active();
|
||||
$file = self::plugin_file();
|
||||
$configured = WPH_Recovery_Installer::is_configured();
|
||||
?>
|
||||
<div class="wph-bootstrap-panel">
|
||||
<h3>Recovery plugin status</h3>
|
||||
<?php if ($active): ?>
|
||||
<p class="wph-ok">✓ <strong>Site Recovery</strong> is installed and active.
|
||||
<p class="wph-ok">✓ <strong>Site Recovery</strong> is installed and active <code><?php echo esc_html((string) $file); ?></code>.
|
||||
<a href="<?php echo esc_url(self::recovery_admin_url()); ?>">Open recovery settings</a> to copy the URL + password into the client record.</p>
|
||||
<?php elseif ($installed): ?>
|
||||
<p class="wph-warn">⚠ <strong>Site Recovery</strong> is installed but inactive. <a href="<?php echo esc_url(admin_url('plugins.php')); ?>">Activate it</a> before starting work.</p>
|
||||
<p class="wph-warn">⚠ <strong>Site Recovery</strong> is installed but inactive <code><?php echo esc_html((string) $file); ?></code>. <a href="<?php echo esc_url(admin_url('plugins.php')); ?>">Activate it</a> before starting work.</p>
|
||||
<?php else: ?>
|
||||
<p class="wph-bad">✗ <strong>Site Recovery</strong> is not installed. Install it before starting the healthcheck — it's the safety net while we work on the site.</p>
|
||||
<p class="description">Phase-1: install manually via <em>Plugins → Add New → Upload Plugin</em>. A private update channel for one-click install lands in hc-5ix.27.</p>
|
||||
<?php if ($configured): ?>
|
||||
<form method="post" action="<?php echo esc_url(admin_url('admin-post.php')); ?>" style="display:inline" onsubmit="return confirm('Download and install Site Recovery from gitea?');">
|
||||
<?php wp_nonce_field('wph_recovery_install'); ?>
|
||||
<input type="hidden" name="action" value="wph_recovery_install">
|
||||
<button class="button button-primary">Install from gitea (latest)</button>
|
||||
</form>
|
||||
<a href="<?php echo esc_url(admin_url('tools.php?page=site-healthcheck-settings')); ?>" class="button">Configure source</a>
|
||||
<?php else: ?>
|
||||
<p>
|
||||
<a href="<?php echo esc_url(admin_url('tools.php?page=site-healthcheck-settings')); ?>" class="button button-primary">Configure gitea source</a>
|
||||
<em>— or install manually via Plugins → Add New → Upload Plugin.</em>
|
||||
</p>
|
||||
<?php endif; ?>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<?php
|
||||
|
||||
Reference in New Issue
Block a user