Make your WordPress site irresistible. Natural SEO attraction with: - robots.txt management - sitemap.xml generation - LLMs.txt support - Google integration (Analytics, Search Console, Tag Manager) - Schema.org structured data - Open Graph / Twitter Card meta tags - AMP support - Visual elements gallery - Built-in backup/restore module Includes build.sh and .distignore for WordPress-installable release ZIPs.
695 lines
24 KiB
PHP
695 lines
24 KiB
PHP
<?php
|
|
/**
|
|
* TigerStyle SEO Backup Validator
|
|
*
|
|
* Validates backup integrity, checksums, and structure
|
|
* to ensure reliable restoration.
|
|
*
|
|
* @package TigerStyleSEO
|
|
* @subpackage BackupValidator
|
|
*/
|
|
|
|
// Prevent direct access
|
|
if (!defined('ABSPATH')) {
|
|
exit;
|
|
}
|
|
|
|
class TigerStyleSEO_Backup_Validator {
|
|
|
|
/**
|
|
* Single instance
|
|
*/
|
|
private static $instance = null;
|
|
|
|
/**
|
|
* Get instance
|
|
*/
|
|
public static function instance() {
|
|
if (is_null(self::$instance)) {
|
|
self::$instance = new self();
|
|
}
|
|
return self::$instance;
|
|
}
|
|
|
|
/**
|
|
* Logger
|
|
*/
|
|
private $logger;
|
|
|
|
/**
|
|
* Constructor
|
|
*/
|
|
private function __construct() {
|
|
$this->logger = TigerStyleSEO_Backup_Logger::instance();
|
|
}
|
|
|
|
/**
|
|
* Validate backup by ID
|
|
*/
|
|
public function validate_backup($backup_id) {
|
|
try {
|
|
$storage_manager = new TigerStyleSEO_Storage_Manager();
|
|
|
|
// Check if backup exists
|
|
if (!$storage_manager->backup_exists($backup_id)) {
|
|
throw new Exception(__('Backup does not exist', 'tigerstyle-heat'));
|
|
}
|
|
|
|
// Download backup for validation
|
|
$backup_file = $storage_manager->download_backup($backup_id);
|
|
|
|
// Extract backup temporarily
|
|
$temp_dir = $this->extract_backup_for_validation($backup_file);
|
|
|
|
try {
|
|
// Validate backup structure and integrity
|
|
$result = $this->validate_backup_directory($temp_dir);
|
|
|
|
return $result;
|
|
|
|
} finally {
|
|
// Cleanup temporary files
|
|
$this->cleanup_temp_directory($temp_dir);
|
|
}
|
|
|
|
} catch (Exception $e) {
|
|
$this->logger->error('Backup validation failed: ' . $e->getMessage(), array(
|
|
'backup_id' => $backup_id
|
|
));
|
|
|
|
throw $e;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Validate backup directory structure and integrity
|
|
*/
|
|
public function validate_backup_directory($backup_dir, $manifest = null) {
|
|
$validation_results = array(
|
|
'valid' => true,
|
|
'errors' => array(),
|
|
'warnings' => array(),
|
|
'checks' => array()
|
|
);
|
|
|
|
try {
|
|
// Load manifest if not provided
|
|
if (!$manifest) {
|
|
$manifest = $this->load_manifest($backup_dir);
|
|
}
|
|
|
|
// Check required files
|
|
$validation_results['checks']['manifest'] = $this->validate_manifest($backup_dir, $manifest);
|
|
$validation_results['checks']['structure'] = $this->validate_backup_structure($backup_dir, $manifest);
|
|
$validation_results['checks']['database'] = $this->validate_database_backup($backup_dir, $manifest);
|
|
$validation_results['checks']['files'] = $this->validate_files_backup($backup_dir, $manifest);
|
|
$validation_results['checks']['checksums'] = $this->validate_checksums($backup_dir, $manifest);
|
|
|
|
// Collect errors and warnings
|
|
foreach ($validation_results['checks'] as $check_name => $check_result) {
|
|
if (!$check_result['valid']) {
|
|
$validation_results['valid'] = false;
|
|
$validation_results['errors'] = array_merge(
|
|
$validation_results['errors'],
|
|
$check_result['errors']
|
|
);
|
|
}
|
|
$validation_results['warnings'] = array_merge(
|
|
$validation_results['warnings'],
|
|
$check_result['warnings']
|
|
);
|
|
}
|
|
|
|
$this->logger->info('Backup validation completed', array(
|
|
'backup_dir' => basename($backup_dir),
|
|
'valid' => $validation_results['valid'],
|
|
'error_count' => count($validation_results['errors']),
|
|
'warning_count' => count($validation_results['warnings'])
|
|
));
|
|
|
|
} catch (Exception $e) {
|
|
$validation_results['valid'] = false;
|
|
$validation_results['errors'][] = $e->getMessage();
|
|
|
|
$this->logger->error('Backup validation exception: ' . $e->getMessage(), array(
|
|
'backup_dir' => $backup_dir
|
|
));
|
|
}
|
|
|
|
return $validation_results;
|
|
}
|
|
|
|
/**
|
|
* Load and validate manifest file
|
|
*/
|
|
private function load_manifest($backup_dir) {
|
|
$manifest_file = $backup_dir . '/manifest.json';
|
|
|
|
if (!file_exists($manifest_file)) {
|
|
throw new Exception(__('Manifest file not found', 'tigerstyle-heat'));
|
|
}
|
|
|
|
$manifest_content = file_get_contents($manifest_file);
|
|
$manifest = json_decode($manifest_content, true);
|
|
|
|
if (json_last_error() !== JSON_ERROR_NONE) {
|
|
throw new Exception(__('Invalid manifest format: ', 'tigerstyle-heat') . json_last_error_msg());
|
|
}
|
|
|
|
return $manifest;
|
|
}
|
|
|
|
/**
|
|
* Validate manifest structure and content
|
|
*/
|
|
private function validate_manifest($backup_dir, $manifest) {
|
|
$result = array(
|
|
'valid' => true,
|
|
'errors' => array(),
|
|
'warnings' => array()
|
|
);
|
|
|
|
// Check required manifest fields
|
|
$required_fields = array(
|
|
'backup_id',
|
|
'created_at',
|
|
'wordpress_version',
|
|
'site_url',
|
|
'plugin_version',
|
|
'options'
|
|
);
|
|
|
|
foreach ($required_fields as $field) {
|
|
if (!isset($manifest[$field])) {
|
|
$result['errors'][] = sprintf(__('Missing required manifest field: %s', 'tigerstyle-heat'), $field);
|
|
$result['valid'] = false;
|
|
}
|
|
}
|
|
|
|
// Validate manifest data types
|
|
if (isset($manifest['created_at']) && !$this->is_valid_datetime($manifest['created_at'])) {
|
|
$result['errors'][] = __('Invalid created_at format in manifest', 'tigerstyle-heat');
|
|
$result['valid'] = false;
|
|
}
|
|
|
|
if (isset($manifest['site_url']) && !filter_var($manifest['site_url'], FILTER_VALIDATE_URL)) {
|
|
$result['warnings'][] = __('Invalid site_url format in manifest', 'tigerstyle-heat');
|
|
}
|
|
|
|
// Check WordPress version compatibility
|
|
if (isset($manifest['wordpress_version'])) {
|
|
$current_wp_version = get_bloginfo('version');
|
|
if (version_compare($manifest['wordpress_version'], $current_wp_version, '>')) {
|
|
$result['warnings'][] = sprintf(
|
|
__('Backup was created with newer WordPress version (%s) than current (%s)', 'tigerstyle-heat'),
|
|
$manifest['wordpress_version'],
|
|
$current_wp_version
|
|
);
|
|
}
|
|
}
|
|
|
|
// Validate options structure
|
|
if (isset($manifest['options']) && !is_array($manifest['options'])) {
|
|
$result['errors'][] = __('Invalid options structure in manifest', 'tigerstyle-heat');
|
|
$result['valid'] = false;
|
|
}
|
|
|
|
return $result;
|
|
}
|
|
|
|
/**
|
|
* Validate backup directory structure
|
|
*/
|
|
private function validate_backup_structure($backup_dir, $manifest) {
|
|
$result = array(
|
|
'valid' => true,
|
|
'errors' => array(),
|
|
'warnings' => array()
|
|
);
|
|
|
|
// Check for manifest file
|
|
if (!file_exists($backup_dir . '/manifest.json')) {
|
|
$result['errors'][] = __('Manifest file is missing', 'tigerstyle-heat');
|
|
$result['valid'] = false;
|
|
}
|
|
|
|
// Check for database backup if included
|
|
if (isset($manifest['options']['include_database']) && $manifest['options']['include_database']) {
|
|
if (!file_exists($backup_dir . '/database.sql')) {
|
|
$result['errors'][] = __('Database backup file is missing', 'tigerstyle-heat');
|
|
$result['valid'] = false;
|
|
}
|
|
}
|
|
|
|
// Check for files backup if included
|
|
if (isset($manifest['options']['include_files']) && $manifest['options']['include_files']) {
|
|
if (!is_dir($backup_dir . '/files')) {
|
|
$result['errors'][] = __('Files backup directory is missing', 'tigerstyle-heat');
|
|
$result['valid'] = false;
|
|
}
|
|
}
|
|
|
|
return $result;
|
|
}
|
|
|
|
/**
|
|
* Validate database backup
|
|
*/
|
|
private function validate_database_backup($backup_dir, $manifest) {
|
|
$result = array(
|
|
'valid' => true,
|
|
'errors' => array(),
|
|
'warnings' => array()
|
|
);
|
|
|
|
// Skip if database backup not included
|
|
if (!isset($manifest['options']['include_database']) || !$manifest['options']['include_database']) {
|
|
return $result;
|
|
}
|
|
|
|
$sql_file = $backup_dir . '/database.sql';
|
|
|
|
if (!file_exists($sql_file)) {
|
|
$result['errors'][] = __('Database backup file not found', 'tigerstyle-heat');
|
|
$result['valid'] = false;
|
|
return $result;
|
|
}
|
|
|
|
// Check file size
|
|
$file_size = filesize($sql_file);
|
|
if ($file_size === 0) {
|
|
$result['errors'][] = __('Database backup file is empty', 'tigerstyle-heat');
|
|
$result['valid'] = false;
|
|
return $result;
|
|
}
|
|
|
|
// Validate SQL content structure
|
|
$sql_validation = $this->validate_sql_file($sql_file);
|
|
if (!$sql_validation['valid']) {
|
|
$result['errors'] = array_merge($result['errors'], $sql_validation['errors']);
|
|
$result['warnings'] = array_merge($result['warnings'], $sql_validation['warnings']);
|
|
$result['valid'] = false;
|
|
}
|
|
|
|
// Validate checksum if available
|
|
if (isset($manifest['database_info']['checksum'])) {
|
|
$actual_checksum = md5_file($sql_file);
|
|
if ($actual_checksum !== $manifest['database_info']['checksum']) {
|
|
$result['errors'][] = __('Database backup checksum mismatch', 'tigerstyle-heat');
|
|
$result['valid'] = false;
|
|
}
|
|
}
|
|
|
|
// Check file size against manifest
|
|
if (isset($manifest['database_info']['file_size'])) {
|
|
if ($file_size !== $manifest['database_info']['file_size']) {
|
|
$result['warnings'][] = __('Database backup file size differs from manifest', 'tigerstyle-heat');
|
|
}
|
|
}
|
|
|
|
return $result;
|
|
}
|
|
|
|
/**
|
|
* Validate SQL file structure
|
|
*/
|
|
private function validate_sql_file($sql_file) {
|
|
$result = array(
|
|
'valid' => true,
|
|
'errors' => array(),
|
|
'warnings' => array()
|
|
);
|
|
|
|
$handle = fopen($sql_file, 'r');
|
|
if (!$handle) {
|
|
$result['errors'][] = __('Cannot read database backup file', 'tigerstyle-heat');
|
|
$result['valid'] = false;
|
|
return $result;
|
|
}
|
|
|
|
$line_count = 0;
|
|
$has_wp_tables = false;
|
|
$has_create_statements = false;
|
|
$has_insert_statements = false;
|
|
|
|
try {
|
|
while (($line = fgets($handle)) !== false && $line_count < 1000) { // Check first 1000 lines
|
|
$line = trim($line);
|
|
$line_count++;
|
|
|
|
// Skip empty lines and comments
|
|
if (empty($line) || strpos($line, '--') === 0) {
|
|
continue;
|
|
}
|
|
|
|
// Check for WordPress table patterns
|
|
if (preg_match('/CREATE TABLE.*wp_\w+/', $line) || preg_match('/INSERT INTO.*wp_\w+/', $line)) {
|
|
$has_wp_tables = true;
|
|
}
|
|
|
|
// Check for CREATE TABLE statements
|
|
if (strpos($line, 'CREATE TABLE') !== false) {
|
|
$has_create_statements = true;
|
|
}
|
|
|
|
// Check for INSERT statements
|
|
if (strpos($line, 'INSERT INTO') !== false) {
|
|
$has_insert_statements = true;
|
|
}
|
|
|
|
// Check for SQL syntax errors (basic validation)
|
|
if (!$this->is_valid_sql_line($line)) {
|
|
$result['warnings'][] = sprintf(__('Potential SQL syntax issue at line %d', 'tigerstyle-heat'), $line_count);
|
|
}
|
|
}
|
|
|
|
} finally {
|
|
fclose($handle);
|
|
}
|
|
|
|
// Validate SQL content
|
|
if (!$has_wp_tables) {
|
|
$result['warnings'][] = __('No WordPress tables found in database backup', 'tigerstyle-heat');
|
|
}
|
|
|
|
if (!$has_create_statements) {
|
|
$result['errors'][] = __('No CREATE TABLE statements found in database backup', 'tigerstyle-heat');
|
|
$result['valid'] = false;
|
|
}
|
|
|
|
if (!$has_insert_statements) {
|
|
$result['warnings'][] = __('No INSERT statements found in database backup', 'tigerstyle-heat');
|
|
}
|
|
|
|
if ($line_count === 0) {
|
|
$result['errors'][] = __('Database backup file appears to be empty', 'tigerstyle-heat');
|
|
$result['valid'] = false;
|
|
}
|
|
|
|
return $result;
|
|
}
|
|
|
|
/**
|
|
* Validate files backup
|
|
*/
|
|
private function validate_files_backup($backup_dir, $manifest) {
|
|
$result = array(
|
|
'valid' => true,
|
|
'errors' => array(),
|
|
'warnings' => array()
|
|
);
|
|
|
|
// Skip if files backup not included
|
|
if (!isset($manifest['options']['include_files']) || !$manifest['options']['include_files']) {
|
|
return $result;
|
|
}
|
|
|
|
$files_dir = $backup_dir . '/files';
|
|
|
|
if (!is_dir($files_dir)) {
|
|
$result['errors'][] = __('Files backup directory not found', 'tigerstyle-heat');
|
|
$result['valid'] = false;
|
|
return $result;
|
|
}
|
|
|
|
// Check for essential WordPress files
|
|
$essential_files = array(
|
|
'wp-config.php',
|
|
'wp-content'
|
|
);
|
|
|
|
foreach ($essential_files as $file) {
|
|
$file_path = $files_dir . '/' . $file;
|
|
if (!file_exists($file_path)) {
|
|
$result['warnings'][] = sprintf(__('Essential file/directory missing: %s', 'tigerstyle-heat'), $file);
|
|
}
|
|
}
|
|
|
|
// Validate file manifest if available
|
|
if (isset($manifest['files']) && is_array($manifest['files'])) {
|
|
$file_validation = $this->validate_file_manifest($files_dir, $manifest['files']);
|
|
$result['errors'] = array_merge($result['errors'], $file_validation['errors']);
|
|
$result['warnings'] = array_merge($result['warnings'], $file_validation['warnings']);
|
|
|
|
if (!$file_validation['valid']) {
|
|
$result['valid'] = false;
|
|
}
|
|
}
|
|
|
|
return $result;
|
|
}
|
|
|
|
/**
|
|
* Validate file manifest against actual files
|
|
*/
|
|
private function validate_file_manifest($files_dir, $file_manifest) {
|
|
$result = array(
|
|
'valid' => true,
|
|
'errors' => array(),
|
|
'warnings' => array()
|
|
);
|
|
|
|
$checked_files = 0;
|
|
$missing_files = 0;
|
|
$checksum_mismatches = 0;
|
|
|
|
foreach ($file_manifest as $relative_path => $file_info) {
|
|
$full_path = $files_dir . '/' . $relative_path;
|
|
$checked_files++;
|
|
|
|
if (!file_exists($full_path)) {
|
|
$missing_files++;
|
|
if ($missing_files <= 10) { // Limit error messages
|
|
$result['errors'][] = sprintf(__('Missing file: %s', 'tigerstyle-heat'), $relative_path);
|
|
}
|
|
$result['valid'] = false;
|
|
continue;
|
|
}
|
|
|
|
// Validate file size
|
|
if (isset($file_info['size'])) {
|
|
$actual_size = filesize($full_path);
|
|
if ($actual_size !== $file_info['size']) {
|
|
$result['warnings'][] = sprintf(__('File size mismatch: %s', 'tigerstyle-heat'), $relative_path);
|
|
}
|
|
}
|
|
|
|
// Validate checksum (sample validation for performance)
|
|
if (isset($file_info['checksum']) && $checked_files % 10 === 0) { // Check every 10th file
|
|
$actual_checksum = md5_file($full_path);
|
|
if ($actual_checksum !== $file_info['checksum']) {
|
|
$checksum_mismatches++;
|
|
if ($checksum_mismatches <= 5) { // Limit error messages
|
|
$result['warnings'][] = sprintf(__('Checksum mismatch: %s', 'tigerstyle-heat'), $relative_path);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if ($missing_files > 10) {
|
|
$result['errors'][] = sprintf(__('... and %d more missing files', 'tigerstyle-heat'), $missing_files - 10);
|
|
}
|
|
|
|
if ($checksum_mismatches > 5) {
|
|
$result['warnings'][] = sprintf(__('... and %d more checksum mismatches', 'tigerstyle-heat'), $checksum_mismatches - 5);
|
|
}
|
|
|
|
return $result;
|
|
}
|
|
|
|
/**
|
|
* Validate backup checksums
|
|
*/
|
|
private function validate_checksums($backup_dir, $manifest) {
|
|
$result = array(
|
|
'valid' => true,
|
|
'errors' => array(),
|
|
'warnings' => array()
|
|
);
|
|
|
|
if (!isset($manifest['checksums']) || !is_array($manifest['checksums'])) {
|
|
$result['warnings'][] = __('No checksums found in manifest', 'tigerstyle-heat');
|
|
return $result;
|
|
}
|
|
|
|
foreach ($manifest['checksums'] as $file => $expected_checksum) {
|
|
$file_path = $backup_dir . '/' . $file;
|
|
|
|
if (!file_exists($file_path)) {
|
|
continue; // File validation handled elsewhere
|
|
}
|
|
|
|
$actual_checksum = md5_file($file_path);
|
|
if ($actual_checksum !== $expected_checksum) {
|
|
$result['errors'][] = sprintf(__('Checksum mismatch for file: %s', 'tigerstyle-heat'), $file);
|
|
$result['valid'] = false;
|
|
}
|
|
}
|
|
|
|
return $result;
|
|
}
|
|
|
|
/**
|
|
* Extract backup for validation
|
|
*/
|
|
private function extract_backup_for_validation($backup_file) {
|
|
$upload_dir = wp_upload_dir();
|
|
$temp_dir = $upload_dir['basedir'] . '/tigerstyle-validation/' . uniqid('validation_');
|
|
|
|
if (!wp_mkdir_p($temp_dir)) {
|
|
throw new Exception(__('Failed to create validation directory', 'tigerstyle-heat'));
|
|
}
|
|
|
|
$compression_manager = new TigerStyleSEO_Compression_Manager();
|
|
$compression_method = $this->detect_compression_method($backup_file);
|
|
|
|
$compression_manager->extract_archive($backup_file, $temp_dir, $compression_method);
|
|
|
|
return $temp_dir;
|
|
}
|
|
|
|
/**
|
|
* Detect compression method from filename
|
|
*/
|
|
private function detect_compression_method($filename) {
|
|
$extension = strtolower(pathinfo($filename, PATHINFO_EXTENSION));
|
|
|
|
switch ($extension) {
|
|
case 'zip':
|
|
return 'zip';
|
|
case 'gz':
|
|
return 'tar.gz';
|
|
case 'bz2':
|
|
return 'tar.bz2';
|
|
default:
|
|
return 'none';
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Cleanup temporary directory
|
|
*/
|
|
private function cleanup_temp_directory($temp_dir) {
|
|
if (!is_dir($temp_dir)) {
|
|
return;
|
|
}
|
|
|
|
$iterator = new RecursiveIteratorIterator(
|
|
new RecursiveDirectoryIterator($temp_dir, RecursiveDirectoryIterator::SKIP_DOTS),
|
|
RecursiveIteratorIterator::CHILD_FIRST
|
|
);
|
|
|
|
foreach ($iterator as $file) {
|
|
if ($file->isDir()) {
|
|
rmdir($file->getPathname());
|
|
} else {
|
|
unlink($file->getPathname());
|
|
}
|
|
}
|
|
|
|
rmdir($temp_dir);
|
|
}
|
|
|
|
/**
|
|
* Validate datetime format
|
|
*/
|
|
private function is_valid_datetime($datetime) {
|
|
$d = DateTime::createFromFormat('Y-m-d H:i:s', $datetime);
|
|
return $d && $d->format('Y-m-d H:i:s') === $datetime;
|
|
}
|
|
|
|
/**
|
|
* Basic SQL line validation
|
|
*/
|
|
private function is_valid_sql_line($line) {
|
|
// Skip empty lines and comments
|
|
if (empty($line) || strpos($line, '--') === 0) {
|
|
return true;
|
|
}
|
|
|
|
// Check for common SQL syntax patterns
|
|
$sql_keywords = array(
|
|
'CREATE', 'DROP', 'INSERT', 'UPDATE', 'DELETE', 'SELECT',
|
|
'ALTER', 'SET', 'START', 'COMMIT', 'ROLLBACK'
|
|
);
|
|
|
|
$line_upper = strtoupper($line);
|
|
|
|
// Check if line starts with SQL keyword or is part of a multi-line statement
|
|
foreach ($sql_keywords as $keyword) {
|
|
if (strpos($line_upper, $keyword) === 0) {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
// Check for VALUES clause (part of INSERT statements)
|
|
if (strpos($line_upper, 'VALUES') !== false || strpos($line_upper, '(') === 0) {
|
|
return true;
|
|
}
|
|
|
|
// Check for properly quoted strings and escaped characters
|
|
if (preg_match('/^[^\']*(?:\'[^\'\\\\]*(?:\\\\.[^\'\\\\]*)*\'[^\']*)*$/', $line)) {
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Quick backup validation (without full extraction)
|
|
*/
|
|
public function quick_validate_backup($backup_id) {
|
|
try {
|
|
$storage_manager = new TigerStyleSEO_Storage_Manager();
|
|
|
|
// Check if backup exists
|
|
if (!$storage_manager->backup_exists($backup_id)) {
|
|
return array('valid' => false, 'error' => __('Backup does not exist', 'tigerstyle-heat'));
|
|
}
|
|
|
|
// Get backup info
|
|
$backup_info = $storage_manager->get_backup_info($backup_id);
|
|
|
|
// Basic checks
|
|
if (empty($backup_info['file_size']) || $backup_info['file_size'] < 1000) {
|
|
return array('valid' => false, 'error' => __('Backup file is too small', 'tigerstyle-heat'));
|
|
}
|
|
|
|
// For local backups, check if file exists and is readable
|
|
if ($backup_info['storage_type'] === 'local') {
|
|
if (!file_exists($backup_info['file_path']) || !is_readable($backup_info['file_path'])) {
|
|
return array('valid' => false, 'error' => __('Backup file is not accessible', 'tigerstyle-heat'));
|
|
}
|
|
}
|
|
|
|
return array('valid' => true, 'message' => __('Backup appears to be valid', 'tigerstyle-heat'));
|
|
|
|
} catch (Exception $e) {
|
|
return array('valid' => false, 'error' => $e->getMessage());
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Validate backup before restore (comprehensive)
|
|
*/
|
|
public function validate_for_restore($backup_id) {
|
|
// Perform quick validation first
|
|
$quick_result = $this->quick_validate_backup($backup_id);
|
|
if (!$quick_result['valid']) {
|
|
return $quick_result;
|
|
}
|
|
|
|
// Perform full validation
|
|
$full_result = $this->validate_backup($backup_id);
|
|
|
|
// Add restore-specific validations
|
|
if ($full_result['valid']) {
|
|
// Check compatibility with current WordPress version
|
|
// Check available disk space
|
|
// Check database permissions
|
|
// etc.
|
|
}
|
|
|
|
return $full_result;
|
|
}
|
|
} |