Because cats have 9 lives, but servers don't - so they need backup-restore! Complete backup solution with S3/MinIO support. - Full WordPress backup (files + database) - S3 / MinIO / S3-compatible storage backends - Scheduled automatic backups - Disaster recovery / one-click restore - Backup integrity validation - Cat-themed admin interface Includes build.sh and .distignore for WordPress-installable release ZIPs.
596 lines
17 KiB
Plaintext
596 lines
17 KiB
Plaintext
<?php
|
|
/**
|
|
* Plugin Name: TigerStyle Life9
|
|
* Plugin URI: https://tigerstyle.com/plugins/life9
|
|
* Description: Because cats have 9 lives, but servers don't - so they need backup-restore!
|
|
* Version: 1.0.0
|
|
* Author: TigerStyle Development
|
|
* Author URI: https://tigerstyle.com
|
|
* License: GPL v2 or later
|
|
* License URI: https://www.gnu.org/licenses/gpl-2.0.html
|
|
* Text Domain: tigerstyle-life9
|
|
* Domain Path: /languages
|
|
* Requires at least: 5.0
|
|
* Tested up to: 6.3
|
|
* Requires PHP: 7.4
|
|
* Network: false
|
|
*
|
|
* @package TigerStyleLife9
|
|
* @version 1.0.0
|
|
*/
|
|
|
|
// Exit if accessed directly
|
|
if (!defined('ABSPATH')) {
|
|
exit;
|
|
}
|
|
|
|
// Define plugin constants
|
|
define('TIGERSTYLE_LIFE9_VERSION', '1.0.0');
|
|
define('TIGERSTYLE_LIFE9_PATH', plugin_dir_path(__FILE__));
|
|
define('TIGERSTYLE_LIFE9_URL', plugin_dir_url(__FILE__));
|
|
define('TIGERSTYLE_LIFE9_BASENAME', plugin_basename(__FILE__));
|
|
define('TIGERSTYLE_LIFE9_FILE', __FILE__);
|
|
|
|
/**
|
|
* Main TigerStyle Life9 Plugin Class
|
|
*
|
|
* Singleton pattern implementation for the backup plugin
|
|
*
|
|
* @since 1.0.0
|
|
*/
|
|
final class TigerStyle_Life9 {
|
|
|
|
/**
|
|
* Plugin instance
|
|
*
|
|
* @var TigerStyle_Life9
|
|
*/
|
|
private static $instance = null;
|
|
|
|
/**
|
|
* Security manager
|
|
*
|
|
* @var TigerStyle_Life9_Security
|
|
*/
|
|
private $security;
|
|
|
|
/**
|
|
* Admin interface
|
|
*
|
|
* @var TigerStyle_Life9_Admin
|
|
*/
|
|
private $admin;
|
|
|
|
/**
|
|
* REST API endpoints
|
|
*
|
|
* @var TigerStyle_Life9_REST_Endpoints
|
|
*/
|
|
private $rest_endpoints;
|
|
|
|
/**
|
|
* Backup engine
|
|
*
|
|
* @var TigerStyle_Life9_Backup_Engine
|
|
*/
|
|
private $backup_engine;
|
|
|
|
/**
|
|
* Storage manager
|
|
*
|
|
* @var TigerStyle_Life9_Storage_Manager
|
|
*/
|
|
private $storage_manager;
|
|
|
|
/**
|
|
* Get plugin instance (Singleton pattern)
|
|
*
|
|
* @return TigerStyle_Life9
|
|
*/
|
|
public static function instance() {
|
|
if (null === self::$instance) {
|
|
self::$instance = new self();
|
|
}
|
|
return self::$instance;
|
|
}
|
|
|
|
/**
|
|
* Constructor - Initialize the plugin
|
|
*/
|
|
private function __construct() {
|
|
$this->init_hooks();
|
|
$this->load_dependencies();
|
|
$this->init_components();
|
|
}
|
|
|
|
/**
|
|
* Prevent cloning
|
|
*/
|
|
private function __clone() {}
|
|
|
|
/**
|
|
* Prevent unserialization
|
|
*/
|
|
public function __wakeup() {}
|
|
|
|
/**
|
|
* Initialize WordPress hooks
|
|
*/
|
|
private function init_hooks() {
|
|
// Activation and deactivation hooks
|
|
register_activation_hook(__FILE__, [$this, 'activate']);
|
|
register_deactivation_hook(__FILE__, [$this, 'deactivate']);
|
|
|
|
// Plugin lifecycle hooks
|
|
add_action('plugins_loaded', [$this, 'loaded'], 10);
|
|
add_action('init', [$this, 'init'], 10);
|
|
add_action('wp_loaded', [$this, 'wp_loaded'], 10);
|
|
|
|
// Load text domain for translations
|
|
add_action('plugins_loaded', [$this, 'load_textdomain']);
|
|
|
|
// Security hooks
|
|
add_action('init', [$this, 'init_security'], 1);
|
|
|
|
// Admin hooks
|
|
if (is_admin()) {
|
|
add_action('admin_init', [$this, 'init_admin']);
|
|
}
|
|
|
|
// AJAX hooks
|
|
add_action('wp_ajax_tigerstyle_life9_heartbeat', [$this, 'ajax_heartbeat']);
|
|
add_action('wp_ajax_nopriv_tigerstyle_life9_heartbeat', [$this, 'ajax_heartbeat_nopriv']);
|
|
}
|
|
|
|
/**
|
|
* Load plugin dependencies
|
|
*/
|
|
private function load_dependencies() {
|
|
// Core security classes
|
|
require_once TIGERSTYLE_LIFE9_PATH . 'includes/class-security.php';
|
|
require_once TIGERSTYLE_LIFE9_PATH . 'includes/class-sanitizer.php';
|
|
require_once TIGERSTYLE_LIFE9_PATH . 'includes/class-validator.php';
|
|
require_once TIGERSTYLE_LIFE9_PATH . 'includes/class-encryption.php';
|
|
|
|
// Core functionality classes
|
|
require_once TIGERSTYLE_LIFE9_PATH . 'includes/class-file-scanner.php';
|
|
require_once TIGERSTYLE_LIFE9_PATH . 'includes/class-database-backup.php';
|
|
require_once TIGERSTYLE_LIFE9_PATH . 'includes/class-backup-engine.php';
|
|
|
|
// Storage classes (storage-backend is included in storage-manager)
|
|
require_once TIGERSTYLE_LIFE9_PATH . 'includes/class-storage-manager.php';
|
|
require_once TIGERSTYLE_LIFE9_PATH . 'includes/storage/class-storage-local.php';
|
|
|
|
// API classes
|
|
require_once TIGERSTYLE_LIFE9_PATH . 'includes/class-api.php';
|
|
require_once TIGERSTYLE_LIFE9_PATH . 'includes/class-rest-endpoints.php';
|
|
|
|
// Admin classes (only in admin)
|
|
if (is_admin()) {
|
|
require_once TIGERSTYLE_LIFE9_PATH . 'includes/class-admin.php';
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Initialize plugin components
|
|
*/
|
|
private function init_components() {
|
|
// Initialize security first
|
|
$this->security = new TigerStyle_Life9_Security();
|
|
|
|
// Initialize storage manager
|
|
$this->storage_manager = new TigerStyle_Life9_Storage_Manager();
|
|
|
|
// Initialize backup engine
|
|
$this->backup_engine = new TigerStyle_Life9_Backup_Engine($this);
|
|
|
|
// Initialize REST endpoints
|
|
$this->rest_endpoints = new TigerStyle_Life9_REST_Endpoints($this);
|
|
|
|
// Initialize admin interface (admin only)
|
|
if (is_admin()) {
|
|
$this->admin = new TigerStyle_Life9_Admin($this);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Plugin activation hook
|
|
*/
|
|
public function activate() {
|
|
// Check system requirements
|
|
$this->check_requirements();
|
|
|
|
// Create database tables if needed
|
|
$this->create_tables();
|
|
|
|
// Create backup directory
|
|
$this->create_backup_directory();
|
|
|
|
// Set default options
|
|
$this->set_default_options();
|
|
|
|
// Schedule cleanup cron job
|
|
if (!wp_next_scheduled('tigerstyle_life9_cleanup')) {
|
|
wp_schedule_event(time(), 'daily', 'tigerstyle_life9_cleanup');
|
|
}
|
|
|
|
// Flush rewrite rules for REST endpoints
|
|
flush_rewrite_rules();
|
|
|
|
// Set activation flag
|
|
update_option('tigerstyle_life9_activated', time());
|
|
}
|
|
|
|
/**
|
|
* Plugin deactivation hook
|
|
*/
|
|
public function deactivate() {
|
|
// Clear scheduled events
|
|
wp_clear_scheduled_hook('tigerstyle_life9_cleanup');
|
|
wp_clear_scheduled_hook('tigerstyle_life9_backup');
|
|
|
|
// Clear transients
|
|
delete_transient('tigerstyle_life9_system_check');
|
|
delete_transient('tigerstyle_life9_backup_list');
|
|
|
|
// Flush rewrite rules
|
|
flush_rewrite_rules();
|
|
}
|
|
|
|
/**
|
|
* Check system requirements
|
|
*/
|
|
private function check_requirements() {
|
|
// Check PHP version
|
|
if (version_compare(PHP_VERSION, '7.4', '<')) {
|
|
deactivate_plugins(plugin_basename(__FILE__));
|
|
wp_die(__('TigerStyle Life9 requires PHP 7.4 or higher.', 'tigerstyle-life9'));
|
|
}
|
|
|
|
// Check WordPress version
|
|
if (version_compare(get_bloginfo('version'), '5.0', '<')) {
|
|
deactivate_plugins(plugin_basename(__FILE__));
|
|
wp_die(__('TigerStyle Life9 requires WordPress 5.0 or higher.', 'tigerstyle-life9'));
|
|
}
|
|
|
|
// Check required PHP extensions
|
|
$required_extensions = ['openssl', 'zip', 'json', 'mysqli'];
|
|
foreach ($required_extensions as $extension) {
|
|
if (!extension_loaded($extension)) {
|
|
deactivate_plugins(plugin_basename(__FILE__));
|
|
wp_die(sprintf(__('TigerStyle Life9 requires the %s PHP extension.', 'tigerstyle-life9'), $extension));
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Create database tables
|
|
*/
|
|
private function create_tables() {
|
|
global $wpdb;
|
|
|
|
$charset_collate = $wpdb->get_charset_collate();
|
|
|
|
// Backups table
|
|
$table_name = $wpdb->prefix . 'tigerstyle_life9_backups';
|
|
$sql = "CREATE TABLE $table_name (
|
|
id mediumint(9) NOT NULL AUTO_INCREMENT,
|
|
backup_id varchar(255) NOT NULL,
|
|
name varchar(255) NOT NULL,
|
|
type varchar(50) NOT NULL,
|
|
status varchar(50) NOT NULL,
|
|
file_path text,
|
|
file_size bigint(20) DEFAULT 0,
|
|
created_at datetime DEFAULT CURRENT_TIMESTAMP,
|
|
completed_at datetime NULL,
|
|
config text,
|
|
metadata text,
|
|
checksum varchar(255),
|
|
PRIMARY KEY (id),
|
|
UNIQUE KEY backup_id (backup_id),
|
|
KEY status (status),
|
|
KEY created_at (created_at)
|
|
) $charset_collate;";
|
|
|
|
require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
|
|
dbDelta($sql);
|
|
|
|
// Settings table
|
|
$table_name = $wpdb->prefix . 'tigerstyle_life9_settings';
|
|
$sql = "CREATE TABLE $table_name (
|
|
id mediumint(9) NOT NULL AUTO_INCREMENT,
|
|
setting_key varchar(255) NOT NULL,
|
|
setting_value longtext,
|
|
setting_type varchar(50) DEFAULT 'string',
|
|
created_at datetime DEFAULT CURRENT_TIMESTAMP,
|
|
updated_at datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
|
PRIMARY KEY (id),
|
|
UNIQUE KEY setting_key (setting_key)
|
|
) $charset_collate;";
|
|
|
|
dbDelta($sql);
|
|
}
|
|
|
|
/**
|
|
* Create backup directory
|
|
*/
|
|
private function create_backup_directory() {
|
|
$upload_dir = wp_upload_dir();
|
|
$backup_dir = $upload_dir['basedir'] . '/tigerstyle-life9';
|
|
|
|
if (!file_exists($backup_dir)) {
|
|
wp_mkdir_p($backup_dir);
|
|
|
|
// Create .htaccess for security
|
|
$htaccess_content = "# TigerStyle Life9 Security\n";
|
|
$htaccess_content .= "Order Deny,Allow\n";
|
|
$htaccess_content .= "Deny from all\n";
|
|
$htaccess_content .= "<Files ~ \"\\.(php|phtml|php3|php4|php5|pl|py|jsp|asp|sh|cgi)$\">\n";
|
|
$htaccess_content .= " deny from all\n";
|
|
$htaccess_content .= "</Files>\n";
|
|
|
|
file_put_contents($backup_dir . '/.htaccess', $htaccess_content);
|
|
|
|
// Create index.php for additional security
|
|
file_put_contents($backup_dir . '/index.php', '<?php // Silence is golden');
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Set default plugin options
|
|
*/
|
|
private function set_default_options() {
|
|
$default_options = [
|
|
'tigerstyle_life9_version' => TIGERSTYLE_LIFE9_VERSION,
|
|
'tigerstyle_life9_encryption_enabled' => true,
|
|
'tigerstyle_life9_default_storage' => 'local',
|
|
'tigerstyle_life9_backup_retention' => 30,
|
|
'tigerstyle_life9_max_backups' => 10
|
|
];
|
|
|
|
foreach ($default_options as $option_name => $option_value) {
|
|
if (get_option($option_name) === false) {
|
|
add_option($option_name, $option_value);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Initialize plugin after all plugins loaded
|
|
*/
|
|
public function loaded() {
|
|
// Check if we need to run upgrades
|
|
$installed_version = get_option('tigerstyle_life9_version');
|
|
if (version_compare($installed_version, TIGERSTYLE_LIFE9_VERSION, '<')) {
|
|
$this->upgrade($installed_version);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Initialize plugin on WordPress init
|
|
*/
|
|
public function init() {
|
|
// Register custom post types or taxonomies if needed
|
|
// Initialize any global functionality
|
|
}
|
|
|
|
/**
|
|
* Initialize when WordPress is fully loaded
|
|
*/
|
|
public function wp_loaded() {
|
|
// Initialize components that need WordPress to be fully loaded
|
|
}
|
|
|
|
/**
|
|
* Load plugin text domain for translations
|
|
*/
|
|
public function load_textdomain() {
|
|
load_plugin_textdomain(
|
|
'tigerstyle-life9',
|
|
false,
|
|
dirname(plugin_basename(__FILE__)) . '/languages'
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Initialize security component
|
|
*/
|
|
public function init_security() {
|
|
if (!$this->security) {
|
|
$this->security = new TigerStyle_Life9_Security();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Initialize admin component
|
|
*/
|
|
public function init_admin() {
|
|
if (!$this->admin && current_user_can('manage_options')) {
|
|
$this->admin = new TigerStyle_Life9_Admin($this);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Handle plugin upgrades
|
|
*
|
|
* @param string $installed_version Currently installed version
|
|
*/
|
|
private function upgrade($installed_version) {
|
|
// Run upgrade routines based on version
|
|
if (version_compare($installed_version, '1.0.0', '<')) {
|
|
// Upgrade to 1.0.0
|
|
$this->create_tables();
|
|
$this->create_backup_directory();
|
|
}
|
|
|
|
// Update version
|
|
update_option('tigerstyle_life9_version', TIGERSTYLE_LIFE9_VERSION);
|
|
}
|
|
|
|
/**
|
|
* AJAX heartbeat for authenticated users
|
|
*/
|
|
public function ajax_heartbeat() {
|
|
check_ajax_referer('tigerstyle_life9_ajax', '_wpnonce');
|
|
|
|
if (!current_user_can('manage_options')) {
|
|
wp_send_json_error('Insufficient permissions');
|
|
}
|
|
|
|
wp_send_json_success([
|
|
'timestamp' => time(),
|
|
'status' => 'active'
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* AJAX heartbeat for non-authenticated users (restricted)
|
|
*/
|
|
public function ajax_heartbeat_nopriv() {
|
|
wp_send_json_error('Authentication required');
|
|
}
|
|
|
|
/**
|
|
* Get security component
|
|
*
|
|
* @return TigerStyle_Life9_Security
|
|
*/
|
|
public function get_security() {
|
|
return $this->security;
|
|
}
|
|
|
|
/**
|
|
* Get admin component
|
|
*
|
|
* @return TigerStyle_Life9_Admin|null
|
|
*/
|
|
public function get_admin() {
|
|
return $this->admin;
|
|
}
|
|
|
|
/**
|
|
* Get backup engine
|
|
*
|
|
* @return TigerStyle_Life9_Backup_Engine
|
|
*/
|
|
public function get_backup_engine() {
|
|
return $this->backup_engine;
|
|
}
|
|
|
|
/**
|
|
* Get storage manager
|
|
*
|
|
* @return TigerStyle_Life9_Storage_Manager
|
|
*/
|
|
public function get_storage_manager() {
|
|
return $this->storage_manager;
|
|
}
|
|
|
|
/**
|
|
* Get REST endpoints
|
|
*
|
|
* @return TigerStyle_Life9_REST_Endpoints
|
|
*/
|
|
public function get_rest_endpoints() {
|
|
return $this->rest_endpoints;
|
|
}
|
|
|
|
/**
|
|
* Get plugin version
|
|
*
|
|
* @return string
|
|
*/
|
|
public function get_version() {
|
|
return TIGERSTYLE_LIFE9_VERSION;
|
|
}
|
|
|
|
/**
|
|
* Check if plugin is network activated
|
|
*
|
|
* @return bool
|
|
*/
|
|
public function is_network_activated() {
|
|
return is_plugin_active_for_network(plugin_basename(__FILE__));
|
|
}
|
|
|
|
/**
|
|
* Get plugin data
|
|
*
|
|
* @return array
|
|
*/
|
|
public function get_plugin_data() {
|
|
if (!function_exists('get_plugin_data')) {
|
|
require_once(ABSPATH . 'wp-admin/includes/plugin.php');
|
|
}
|
|
|
|
return get_plugin_data(__FILE__);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Initialize the plugin
|
|
*
|
|
* @return TigerStyle_Life9
|
|
*/
|
|
function tigerstyle_life9() {
|
|
return TigerStyle_Life9::instance();
|
|
}
|
|
|
|
// Start the plugin
|
|
tigerstyle_life9();
|
|
|
|
/**
|
|
* Plugin cleanup on uninstall
|
|
*/
|
|
function tigerstyle_life9_uninstall() {
|
|
// Only run if explicitly uninstalling
|
|
if (!defined('WP_UNINSTALL_PLUGIN')) {
|
|
return;
|
|
}
|
|
|
|
// Remove all plugin data if user chooses to
|
|
$remove_data = get_option('tigerstyle_life9_remove_data_on_uninstall', false);
|
|
|
|
if ($remove_data) {
|
|
global $wpdb;
|
|
|
|
// Drop custom tables
|
|
$wpdb->query("DROP TABLE IF EXISTS {$wpdb->prefix}tigerstyle_life9_backups");
|
|
$wpdb->query("DROP TABLE IF EXISTS {$wpdb->prefix}tigerstyle_life9_settings");
|
|
|
|
// Remove options
|
|
$wpdb->query("DELETE FROM {$wpdb->options} WHERE option_name LIKE 'tigerstyle_life9_%'");
|
|
|
|
// Remove backup directory
|
|
$upload_dir = wp_upload_dir();
|
|
$backup_dir = $upload_dir['basedir'] . '/tigerstyle-life9';
|
|
|
|
if (file_exists($backup_dir)) {
|
|
// Recursively delete directory
|
|
$files = new RecursiveIteratorIterator(
|
|
new RecursiveDirectoryIterator($backup_dir, RecursiveDirectoryIterator::SKIP_DOTS),
|
|
RecursiveIteratorIterator::CHILD_FIRST
|
|
);
|
|
|
|
foreach ($files as $file) {
|
|
if ($file->isDir()) {
|
|
rmdir($file->getRealPath());
|
|
} else {
|
|
unlink($file->getRealPath());
|
|
}
|
|
}
|
|
|
|
rmdir($backup_dir);
|
|
}
|
|
|
|
// Clear scheduled events
|
|
wp_clear_scheduled_hook('tigerstyle_life9_cleanup');
|
|
wp_clear_scheduled_hook('tigerstyle_life9_backup');
|
|
|
|
// Clear transients
|
|
delete_transient('tigerstyle_life9_system_check');
|
|
delete_transient('tigerstyle_life9_backup_list');
|
|
}
|
|
}
|
|
|
|
register_uninstall_hook(__FILE__, 'tigerstyle_life9_uninstall'); |