prefix . 'wpmigpro_backups'; } /** * Get backups, newest first. */ public function get_backups($limit = 50, $offset = 0) { global $wpdb; return $wpdb->get_results($wpdb->prepare( 'SELECT * FROM %i ORDER BY created_at DESC, id DESC LIMIT %d OFFSET %d', $this->table(), $limit, $offset )); } /** * Get backup by ID */ public function get_backup($backup_id) { global $wpdb; return $wpdb->get_row($wpdb->prepare('SELECT * FROM %i WHERE id = %d', $this->table(), $backup_id)); } /** * Delete a backup file and its record. */ public function delete_backup($backup_id) { global $wpdb; $backup = $this->get_backup($backup_id); if (!$backup) { return array('success' => false, 'message' => __('Backup not found', 'enmigrate-pro')); } if ($backup->file_path && $this->is_inside_backups_dir($backup->file_path)) { WPMigPro_FS::delete($backup->file_path); } $wpdb->delete($this->table(), array('id' => $backup_id), array('%d')); $wpdb->delete($wpdb->prefix . 'wpmigpro_logs', array('backup_id' => $backup_id), array('%d')); WPMigPro_Logger::log('Backup deleted: ' . $backup->backup_name); return array('success' => true, 'message' => __('Backup deleted successfully', 'enmigrate-pro')); } /** * Only files in our backups folder may be read or deleted through backup records. */ public function is_inside_backups_dir($path) { $real = realpath($path); $base = realpath(WPMIGPRO_BACKUPS_DIR); return $real && $base && strpos(wp_normalize_path($real), trailingslashit(wp_normalize_path($base))) === 0; } /** * Total size of all backup files. */ public function get_total_backup_size() { $total_size = 0; foreach ($this->get_backups(1000) as $backup) { if ($backup->file_path && is_file($backup->file_path)) { $total_size += filesize($backup->file_path); } } return $total_size; } /** * Numbers shown on the dashboard. */ public function get_statistics() { global $wpdb; $table = $this->table(); return array( 'total_backups' => (int) $wpdb->get_var($wpdb->prepare('SELECT COUNT(*) FROM %i', $table)), 'completed_backups' => (int) $wpdb->get_var($wpdb->prepare('SELECT COUNT(*) FROM %i WHERE status = %s', $table, 'completed')), 'failed_backups' => (int) $wpdb->get_var($wpdb->prepare('SELECT COUNT(*) FROM %i WHERE status = %s', $table, 'failed')), 'last_backup' => $wpdb->get_var($wpdb->prepare('SELECT MAX(created_at) FROM %i WHERE status = %s AND backup_type <> %s', $table, 'completed', 'imported')), 'total_size' => $this->get_total_backup_size(), ); } /** * Keep only the newest N backups created on this site (uploaded files are not touched). */ public function cleanup_old_backups($keep_count) { global $wpdb; $keep_count = max(1, (int) $keep_count); $old = $wpdb->get_col($wpdb->prepare( 'SELECT id FROM %i WHERE backup_type <> %s AND status = %s ORDER BY created_at DESC, id DESC LIMIT 1000 OFFSET %d', $this->table(), 'imported', 'completed', $keep_count )); foreach ($old as $id) { $this->delete_backup((int) $id); } } }