id !== 'themes' ) { // return; // } // Enqueue admin CSS wp_enqueue_style( 'aptce-admin', plugins_url( 'assets/aptce-admin.css', AATCE_PLUGIN_FILE ), [], APTCE_VERSION ); // Enqueue admin JS wp_enqueue_script( 'aptce-admin', plugins_url( 'assets/aptce-admin.js', AATCE_PLUGIN_FILE ), ['jquery'], APTCE_VERSION, true ); wp_localize_script( 'aptce-admin', 'aptce', [ 'nonce' => wp_create_nonce( 'aptce_export' ), 'ajax_url' => admin_url( 'admin-ajax.php' ) ] ); // Prepare theme data $themes = wp_get_themes(); $export = []; foreach ( $themes as $slug => $theme ) { $export[ $slug ] = [ 'name' => $theme->get('Name'), 'aptce_download' => wp_nonce_url( admin_url( 'admin-post.php?action=aptce_download_theme&slug=' . $slug ), 'aptce_download_' . $slug ), ]; } // IMPORTANT: Do NOT overwrite wp.themes.* wp_add_inline_script( 'aptce-admin', 'window.aptceThemeData = ' . wp_json_encode( $export, JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_APOS | JSON_HEX_QUOT ) . ';', 'before' ); } public function aptce_register_menu() { add_management_page( __( 'Advanced Addons, Theme & Core Exporter', 'advanced-addons-theme-core-exporter' ), __( 'Advanced Addons, Theme & Core Exporter', 'advanced-addons-theme-core-exporter' ), 'manage_options', 'advanced-addons-theme-core-exporter', [ $this, 'aptce_render_admin_page' ] ); } public function aptce_add_settings_link( $links ) { // New correct settings page URL $url = admin_url( 'tools.php?page=advanced-addons-theme-core-exporter' ); // Create the link $settings_link = '' . __( 'Settings', 'advanced-addons-theme-core-exporter' ) . ''; // Add link at the first position array_unshift( $links, $settings_link ); return $links; } public function aptce_add_review_row_meta( $plugin_meta, $plugin_file ) { if ( plugin_basename( __FILE__ ) !== $plugin_file ) { return $plugin_meta; } $review_link = '' . __( 'Leave a review', 'advanced-addons-theme-core-exporter' ) . ''; $inserted = false; foreach ( $plugin_meta as $index => $meta_item ) { if ( false !== strpos( $meta_item, 'plugin-install.php?tab=plugin-information' ) ) { array_splice( $plugin_meta, $index + 1, 0, [ $review_link ] ); $inserted = true; break; } } if ( ! $inserted ) { $plugin_meta[] = $review_link; } return $plugin_meta; } public function aptce_render_admin_page() { if ( ! current_user_can( 'manage_options' ) ) { wp_die( __( 'Insufficient permissions', 'advanced-addons-theme-core-exporter' ) ); } // Check ZipArchive $zip_ok = class_exists( 'ZipArchive' ); ?>

aptce_render_plugins_table(); ?>

aptce_render_themes_table(); ?>

  aptce_get_directory_size( trailingslashit( $root_dir ) ); } echo esc_html( size_format( $full_100_size, 2 ) ); ?>
  aptce_get_directory_size_with_exclusions( $root, $exclude ); } echo esc_html( size_format( $full_size, 2 ) ); ?>
  aptce_get_directory_size( $uploads_dir ) : 0; // Output readable size echo esc_html( size_format( $uploads_size, 2 ) ); ?>
  aptce_get_directory_size_with_exclusions( $wpcontent_dir, $exclude_uploads ) : 0; echo esc_html( size_format( $wpcontent_size, 2 ) ); ?>
  aptce_get_directory_size( $admin_dir ) : 0; echo esc_html( size_format( $admin_size, 2 ) ); ?>
  aptce_get_directory_size( $includes_dir ) : 0; echo esc_html( size_format( $includes_size, 2 ) ); ?>
  aptce_get_database_size(); echo esc_html( size_format( $db_size, 2 ) ); ?>

 

$meta ) { $slug = dirname( $path ); if ( '.' === $slug ) $slug = basename( $path, '.php' ); $name = isset( $meta['Name'] ) ? $meta['Name'] : $path; $ver = isset( $meta['Version'] ) ? $meta['Version'] : ''; $full_plugin_file = WP_PLUGIN_DIR . '/' . $path; $plugin_dir = plugin_dir_path( $full_plugin_file ); $size = is_dir( $plugin_dir ) ? size_format( $this->aptce_get_directory_size( $plugin_dir ) ) : '—'; $download_url = wp_nonce_url( admin_url( 'admin-post.php?action=aptce_export_single&type=plugin&item=' . rawurlencode( $path ) ), 'aptce_export_single' ); ?>

$theme ) : $theme_dir = get_theme_root() . '/' . $slug; $size = is_dir( $theme_dir ) ? size_format( $this->aptce_get_directory_size( $theme_dir ) ) : '—'; $download_url = wp_nonce_url( admin_url( 'admin-post.php?action=aptce_export_single&type=theme&item=' . rawurlencode( $slug ) ), 'aptce_export_single' ); ?>
get( 'Name' ) ); ?>
get( 'Version' ) ); ?>
isFile() ) { $size += $file->getSize(); } } return $size; } /** * Get directory size with exclusions */ protected function aptce_get_directory_size_with_exclusions( $dir, $exclude = [] ) { if ( ! is_dir( $dir ) ) { return 0; } $size = 0; $files = new RecursiveIteratorIterator( new RecursiveDirectoryIterator( $dir, FilesystemIterator::SKIP_DOTS ), RecursiveIteratorIterator::LEAVES_ONLY ); foreach ( $files as $file ) { if ( $file->isDir() ) continue; $filePath = $file->getRealPath(); // Check exclusions $skip = false; foreach ( $exclude as $ex ) { if ( empty( $ex ) ) continue; // if $ex is an absolute path (realpath), compare prefix if ( realpath( $ex ) && strpos( $filePath, realpath( $ex ) ) === 0 ) { $skip = true; break; } // if $ex is just a filename like 'wp-config.php' if ( basename( $filePath ) === $ex ) { $skip = true; break; } } if ( $skip ) continue; if ( $file->isFile() ) { $size += $file->getSize(); } } return $size; } /** * Get database size */ protected function aptce_get_database_size() { global $wpdb; $size = 0; $tables = $wpdb->get_results( 'SHOW TABLE STATUS', ARRAY_A ); if ( $tables ) { foreach ( $tables as $table ) { if ( isset( $table['Data_length'] ) && isset( $table['Index_length'] ) ) { $size += $table['Data_length'] + $table['Index_length']; } } } return $size; } /** * Single plugin/theme download (existing) */ public function aptce_handle_export_single() { if ( ! current_user_can( 'manage_options' ) ) { wp_die( __( 'Insufficient permissions', 'advanced-addons-theme-core-exporter' ) ); } // Verify nonce for single export action $nonce = ''; if ( isset( $_GET['_wpnonce'] ) ) { $nonce = sanitize_text_field( wp_unslash( $_GET['_wpnonce'] ) ); } if ( empty( $nonce ) || ! wp_verify_nonce( $nonce, 'aptce_export_single' ) ) { wp_die( esc_html__( 'Security check failed.', 'advanced-addons-theme-core-exporter' ), esc_html__( 'Error', 'advanced-addons-theme-core-exporter' ), array( 'response' => 403, ) ); } $type = isset( $_GET['type'] ) ? sanitize_text_field( wp_unslash( $_GET['type'] ) ) : ''; $item = isset( $_GET['item'] ) ? sanitize_text_field( wp_unslash( $_GET['item'] ) ) : ''; if ( ! in_array( $type, ['plugin', 'theme'], true ) || empty( $item ) ) { wp_safe_redirect( wp_get_referer() ?: admin_url() ); exit; } // Get plugin/theme name for filename $item_name = ''; if ( 'plugin' === $type ) { if ( ! function_exists( 'get_plugin_data' ) ) { require_once AATCE_ADMIN_INCLUDES . 'plugin.php'; } $plugin_data = get_plugin_data( WP_PLUGIN_DIR . '/' . $item ); $item_name = ! empty( $plugin_data['Name'] ) ? $plugin_data['Name'] : dirname( $item ); } elseif ( 'theme' === $type ) { $theme = wp_get_theme( $item ); $item_name = $theme->get( 'Name' ) ? $theme->get( 'Name' ) : $item; } // Sanitize filename (remove special characters, spaces, etc.) $item_name = sanitize_file_name( $item_name ); // Ensure lowercase and replace any remaining spaces with hyphens $item_name = strtolower( str_replace( ' ', '-', $item_name ) ); $upload = wp_upload_dir(); // Ensure basedir exists and is writable $basedir = ! empty( $upload['basedir'] ) ? trailingslashit( wp_normalize_path( $upload['basedir'] ) ) : wp_normalize_path( AATCE_UPLOADS_DIR ); // Create directory if it doesn't exist if ( ! is_dir( $basedir ) ) { wp_mkdir_p( $basedir ); } // Check if directory is writable if ( ! is_writable( $basedir ) ) { wp_die( esc_html__( 'Upload directory is not writable. Please check folder permissions.', 'advanced-addons-theme-core-exporter' ) ); } // Temporary zip file path $tmp_zip = $basedir . 'aptce-single-' . time() . '.zip'; // Zip filename for download (sanitize for safety) $zip_filename = sanitize_file_name( $item_name ) . '.zip'; // ✅ Prefer ZipArchive if available if ( class_exists( 'ZipArchive' ) ) { $zip = new ZipArchive(); if ( $zip->open( $tmp_zip, ZipArchive::CREATE ) !== TRUE ) { wp_die( esc_html__( 'Could not create archive', 'advanced-addons-theme-core-exporter' ) ); } if ( 'plugin' === $type ) { // Build full plugin path from item (relative path) $plugin_dir = wp_normalize_path( WP_PLUGIN_DIR . '/' . dirname( $item ) ); if ( is_dir( $plugin_dir ) ) { $base = basename( $plugin_dir ); $plugin_dir_normalized = wp_normalize_path( rtrim( $plugin_dir, '/\\' ) ); $files = new RecursiveIteratorIterator( new RecursiveDirectoryIterator( $plugin_dir ), RecursiveIteratorIterator::LEAVES_ONLY ); foreach ( $files as $file ) { if ( $file->isDir() ) continue; $filePath = $file->getRealPath(); if ( ! $filePath ) continue; $filePath_normalized = wp_normalize_path( $filePath ); if ( strpos( $filePath_normalized, $plugin_dir_normalized ) === 0 ) { $relative = substr( $filePath_normalized, strlen( $plugin_dir_normalized ) ); $relative = ltrim( $relative, '/' ); $relative = str_replace( '\\', '/', $relative ); $zip->addFile( $filePath, $base . '/' . $relative ); } } } } elseif ( 'theme' === $type ) { $theme_dir = wp_normalize_path( get_theme_root() . '/' . $item ); if ( is_dir( $theme_dir ) ) { $base = basename( $theme_dir ); $theme_dir_normalized = wp_normalize_path( rtrim( $theme_dir, '/\\' ) ); $files = new RecursiveIteratorIterator( new RecursiveDirectoryIterator( $theme_dir ), RecursiveIteratorIterator::LEAVES_ONLY ); foreach ( $files as $file ) { if ( $file->isDir() ) continue; $filePath = $file->getRealPath(); if ( ! $filePath ) continue; $filePath_normalized = wp_normalize_path( $filePath ); if ( strpos( $filePath_normalized, $theme_dir_normalized ) === 0 ) { $relative = substr( $filePath_normalized, strlen( $theme_dir_normalized ) ); $relative = ltrim( $relative, '/' ); $relative = str_replace( '\\', '/', $relative ); $zip->addFile( $filePath, $base . '/' . $relative ); } } } } $zip->close(); } else { // ✅ Fallback to WordPress bundled PclZip if ( ! class_exists( 'PclZip' ) ) { include_once AATCE_ADMIN_INCLUDES . 'class-pclzip.php'; } $file_paths = array(); if ( 'plugin' === $type ) { // Build full plugin path from item (relative path) $plugin_dir = wp_normalize_path( WP_PLUGIN_DIR . '/' . dirname( $item ) ); if ( is_dir( $plugin_dir ) ) { $files = new RecursiveIteratorIterator( new RecursiveDirectoryIterator( $plugin_dir ), RecursiveIteratorIterator::LEAVES_ONLY ); foreach ( $files as $file ) { if ( $file->isDir() ) continue; $filePath = $file->getRealPath(); if ( file_exists( $filePath ) ) { $file_paths[] = $filePath; } } } } elseif ( 'theme' === $type ) { $theme_dir = wp_normalize_path( get_theme_root() . '/' . $item ); if ( is_dir( $theme_dir ) ) { $files = new RecursiveIteratorIterator( new RecursiveDirectoryIterator( $theme_dir ), RecursiveIteratorIterator::LEAVES_ONLY ); foreach ( $files as $file ) { if ( $file->isDir() ) continue; $filePath = $file->getRealPath(); if ( file_exists( $filePath ) ) { $file_paths[] = $filePath; } } } } if ( ! empty( $file_paths ) ) { $archive = new PclZip( $tmp_zip ); if ( 'plugin' === $type ) { $plugin_dir = wp_normalize_path( WP_PLUGIN_DIR . '/' . dirname( $item ) ); $archive->create( $file_paths, PCLZIP_OPT_REMOVE_PATH, dirname( $plugin_dir ) ); } else { $theme_dir = wp_normalize_path( get_theme_root() . '/' . $item ); $archive->create( $file_paths, PCLZIP_OPT_REMOVE_PATH, dirname( $theme_dir ) ); } } } // Verify ZIP file was created successfully if ( ! file_exists( $tmp_zip ) ) { wp_die( esc_html__( 'ZIP creation failed11: File was not created. Check directory permissions and available disk space.', 'advanced-addons-theme-core-exporter' ) ); } if ( filesize( $tmp_zip ) === 0 ) { @unlink( $tmp_zip ); wp_die( esc_html__( 'ZIP creation failed11: File is empty. The item may contain no files or read permissions are restricted.', 'advanced-addons-theme-core-exporter' ) ); } if ( is_file( $tmp_zip ) ) { header( 'Content-Description: File Transfer' ); header( 'Content-Type: application/zip' ); header( 'Content-Disposition: attachment; filename="' . esc_attr( $zip_filename ) . '"' ); header( 'Content-Length: ' . filesize( $tmp_zip ) ); readfile( $tmp_zip ); @unlink( $tmp_zip ); exit; } wp_die( __( 'ZIP creation failed11', 'advanced-addons-theme-core-exporter' ) ); } /** * Single core download handler (for the Download buttons) */ public function aptce_handle_download_core_single() { // Verify nonce for core download action $nonce = ''; if ( isset( $_REQUEST['_wpnonce'] ) ) { $nonce = sanitize_text_field( wp_unslash( $_REQUEST['_wpnonce'] ) ); } if ( empty( $nonce ) || ! wp_verify_nonce( $nonce, 'aptce_download_core' ) ) { wp_die( esc_html__( 'Security check failed.', 'advanced-addons-theme-core-exporter' ), esc_html__( 'Error', 'advanced-addons-theme-core-exporter' ), array( 'response' => 403, ) ); } if ( ! current_user_can( 'manage_options' ) ) { wp_die( __( 'Insufficient permissions', 'advanced-addons-theme-core-exporter' ) ); } $type = isset( $_GET['type'] ) ? sanitize_text_field( wp_unslash( $_GET['type'] ) ) : ''; $upload = wp_upload_dir(); switch ( $type ) { case 'full_100': // Full WordPress root $source = ABSPATH; // no realpath() $zip_name = 'wordpress-full-100-percent-' . date( 'Ymd-His' ) . '.zip'; $exclude = []; // include everything break; case 'full': // Full root except uploads + wp-config $source = ABSPATH; $uploads_dir = $upload['basedir']; $exclude = [ $uploads_dir, ABSPATH . 'wp-config.php', ]; $zip_name = 'wordpress-core-full-' . date( 'Ymd-His' ) . '.zip'; break; case 'uploads': // Only uploads – safe via wp_upload_dir() $source = $upload['basedir']; $zip_name = 'wp-uploads-' . date( 'Ymd-His' ) . '.zip'; $exclude = []; break; case 'wpcontent': // wp-content excluding uploads $wpcontent_dir = WP_CONTENT_DIR; $uploads_dir = $upload['basedir']; $source = $wpcontent_dir; $exclude = [ $uploads_dir, ]; $zip_name = 'wp-content-no-uploads-' . date( 'Ymd-His' ) . '.zip'; break; case 'admin': // wp-admin folder properly resolved $source = trailingslashit( ABSPATH ) . 'wp-admin'; $zip_name = 'wp-admin-' . date( 'Ymd-His' ) . '.zip'; $exclude = []; break; case 'includes': // wp-includes folder properly resolved $source = trailingslashit( ABSPATH ) . 'wp-includes'; $zip_name = 'wp-includes-' . date( 'Ymd-His' ) . '.zip'; $exclude = []; break; default: wp_die( __( 'Invalid download type', 'advanced-addons-theme-core-exporter' ) ); } if ( ! $source || ! is_dir( $source ) ) { wp_die( __( 'Directory not found', 'advanced-addons-theme-core-exporter' ) ); } $tmp_zip = $upload['basedir'] . '/aptce-core-' . time() . '.zip'; // ✅ Prefer ZipArchive if available if ( class_exists( 'ZipArchive' ) ) { $zip = new ZipArchive(); if ( $zip->open( $tmp_zip, ZipArchive::CREATE ) !== TRUE ) { wp_die( esc_html__( 'Could not create archive', 'advanced-addons-theme-core-exporter' ) ); } $this->aptce_add_folder_to_zip( $zip, $source, $source, $exclude ); $zip->close(); } else { // ✅ Fallback to WordPress bundled PclZip if ( ! class_exists( 'PclZip' ) ) { include_once AATCE_ADMIN_INCLUDES . 'class-pclzip.php'; } $file_paths = array(); $files = new RecursiveIteratorIterator( new RecursiveDirectoryIterator( $source, FilesystemIterator::SKIP_DOTS ), RecursiveIteratorIterator::LEAVES_ONLY ); foreach ( $files as $file ) { if ( $file->isDir() ) continue; $filePath = $file->getRealPath(); // Exclude by absolute path or by basename (wp-config.php) $skip = false; foreach ( $exclude as $ex ) { if ( empty( $ex ) ) continue; // if $ex is an absolute path (realpath), compare prefix if ( realpath( $ex ) && strpos( $filePath, realpath( $ex ) ) === 0 ) { $skip = true; break; } // if $ex is just a filename like 'wp-config.php' if ( basename( $filePath ) === $ex ) { $skip = true; break; } } if ( $skip ) continue; if ( file_exists( $filePath ) ) { $file_paths[] = $filePath; } } if ( ! empty( $file_paths ) ) { $archive = new PclZip( $tmp_zip ); $archive->create( $file_paths, PCLZIP_OPT_REMOVE_PATH, dirname( $source ) ); } } if ( is_file( $tmp_zip ) ) { header( 'Content-Description: File Transfer' ); header( 'Content-Type: application/zip' ); header( 'Content-Disposition: attachment; filename="' . $zip_name . '"' ); header( 'Content-Length: ' . filesize( $tmp_zip ) ); readfile( $tmp_zip ); @unlink( $tmp_zip ); exit; } wp_die( __( 'ZIP creation failed', 'advanced-addons-theme-core-exporter' ) ); } /** * Database download handler */ public function aptce_handle_download_database() { // Verify nonce $nonce = isset( $_REQUEST['_wpnonce'] ) ? wp_unslash( $_REQUEST['_wpnonce'] ) : ''; if ( ! wp_verify_nonce( $nonce, 'aptce_download_core' ) ) { wp_die( __( 'Security check failed.', 'advanced-addons-theme-core-exporter' ), 403 ); } if ( ! current_user_can( 'manage_options' ) ) { wp_die( __( 'Insufficient permissions.', 'advanced-addons-theme-core-exporter' ) ); } global $wpdb; $filename = 'wordpress-database-' . date( 'Ymd-His' ) . '.sql'; $db_name = DB_NAME; $db_charset = defined( 'DB_CHARSET' ) ? DB_CHARSET : 'utf8mb4'; $nl = "\n"; // Force download headers nocache_headers(); header( 'Content-Type: application/octet-stream' ); header( 'Content-Disposition: attachment; filename="' . $filename . '"' ); header( 'Content-Transfer-Encoding: binary' ); // SQL Header echo "-- WordPress Database Dump{$nl}"; echo "-- Generated: " . date( 'Y-m-d H:i:s' ) . "{$nl}"; echo "-- Database: {$db_name}{$nl}"; echo "--{$nl}{$nl}"; echo "SET NAMES {$db_charset};{$nl}"; echo "SET SQL_MODE = \"NO_AUTO_VALUE_ON_ZERO\";{$nl}"; echo "SET time_zone = \"+00:00\";{$nl}{$nl}"; echo "/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;{$nl}"; echo "/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;{$nl}"; echo "/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;{$nl}"; echo "/*!40101 SET NAMES {$db_charset} */;{$nl}{$nl}"; echo "/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;{$nl}"; echo "/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;{$nl}{$nl}"; // Fetch tables $tables = $wpdb->get_results( 'SHOW TABLES', ARRAY_N ); foreach ( $tables as $table ) { $table_name = $table[0]; echo "{$nl}--{$nl}-- Table structure for table `{$table_name}`{$nl}--{$nl}{$nl}"; echo "DROP TABLE IF EXISTS `{$table_name}`;{$nl}"; $create_table = $wpdb->get_row( "SHOW CREATE TABLE `{$table_name}`", ARRAY_A ); if ( isset( $create_table['Create Table'] ) ) { echo rtrim( $create_table['Create Table'], ';' ) . ";{$nl}{$nl}"; } // Table data $rows = $wpdb->get_results( "SELECT * FROM `{$table_name}`", ARRAY_A ); if ( empty( $rows ) ) { continue; } echo "{$nl}--{$nl}-- Dumping data for table `{$table_name}`{$nl}--{$nl}{$nl}"; $columns = array_keys( $rows[0] ); $column_list = '`' . implode( '`, `', $columns ) . '`'; $chunk_size = 100; $total_rows = count( $rows ); for ( $i = 0; $i < $total_rows; $i += $chunk_size ) { $chunk = array_slice( $rows, $i, $chunk_size ); echo "INSERT INTO `{$table_name}` ({$column_list}) VALUES{$nl}"; $values = []; foreach ( $chunk as $row ) { $row_values = []; foreach ( $row as $value ) { if ( is_null( $value ) ) { $row_values[] = 'NULL'; } elseif ( is_numeric( $value ) && ! is_string( $value ) ) { $row_values[] = $value; } else { $escaped = (string) $value; $escaped = str_replace( "\r\n", "\n", $escaped ); $escaped = str_replace( "\r", "\n", $escaped ); $escaped = str_replace( '\\', '\\\\', $escaped ); $escaped = str_replace( "'", "''", $escaped ); $escaped = str_replace( "\x00", "\\0", $escaped ); $escaped = str_replace( "\x1a", "\\Z", $escaped ); $escaped = str_replace( "\n", "\\n", $escaped ); $row_values[] = "'" . $escaped . "'"; } } $values[] = '(' . implode( ', ', $row_values ) . ')'; } echo implode( ",{$nl}", $values ) . ";{$nl}{$nl}"; } } // Footer echo "{$nl}/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;{$nl}"; echo "/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;{$nl}{$nl}"; echo "--{$nl}-- End of database dump{$nl}--{$nl}"; echo "/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;{$nl}"; echo "/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;{$nl}"; echo "/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;{$nl}"; exit; } /** * Helper: Generate database dump to a file * Returns the file path on success, false on failure * Cross-platform compatible (Windows/Linux) */ protected function aptce_generate_database_dump_file( $file_path ) { global $wpdb; $db_name = DB_NAME; $db_charset = defined( 'DB_CHARSET' ) ? DB_CHARSET : 'utf8mb4'; // Open file in binary mode for cross-platform compatibility (ensures consistent line endings) $handle = fopen( $file_path, 'wb' ); if ( ! $handle ) { return false; } // Use LF line endings for cross-platform compatibility (Linux/Unix standard) $nl = "\n"; // Write SQL header with UTF-8 BOM for better compatibility fwrite( $handle, "-- WordPress Database Dump{$nl}" ); fwrite( $handle, "-- Generated: " . date( 'Y-m-d H:i:s' ) . "{$nl}" ); fwrite( $handle, "-- Database: " . $db_name . "{$nl}" ); fwrite( $handle, "--{$nl}{$nl}" ); fwrite( $handle, "SET NAMES utf8mb4;{$nl}" ); fwrite( $handle, "SET SQL_MODE = \"NO_AUTO_VALUE_ON_ZERO\";{$nl}" ); fwrite( $handle, "SET time_zone = \"+00:00\";{$nl}{$nl}" ); fwrite( $handle, "/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;{$nl}" ); fwrite( $handle, "/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;{$nl}" ); fwrite( $handle, "/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;{$nl}" ); fwrite( $handle, "/*!40101 SET NAMES " . $db_charset . " */;{$nl}{$nl}" ); // Disable foreign key checks for better import compatibility fwrite( $handle, "/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;{$nl}" ); fwrite( $handle, "/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;{$nl}{$nl}" ); // Get all tables $tables = $wpdb->get_results( 'SHOW TABLES', ARRAY_N ); if ( empty( $tables ) ) { fclose( $handle ); return false; } foreach ( $tables as $table ) { $table_name = $table[0]; // Skip non-existent table if ( ! $wpdb->get_var( $wpdb->prepare( "SHOW TABLES LIKE %s", $table_name ) ) ) { continue; } // Table structure fwrite( $handle, "{$nl}--{$nl}-- Table structure for table `" . $table_name . "`{$nl}--{$nl}{$nl}" ); fwrite( $handle, "DROP TABLE IF EXISTS `" . $table_name . "`;{$nl}" ); $create_table = $wpdb->get_row( "SHOW CREATE TABLE `{$table_name}`", ARRAY_A ); if ( isset( $create_table['Create Table'] ) ) { // Ensure CREATE TABLE statement ends with semicolon and newline $create_sql = rtrim( $create_table['Create Table'], " \t\n\r\0\x0B;" ) . ";{$nl}{$nl}"; fwrite( $handle, $create_sql ); } // Table data $rows = $wpdb->get_results( "SELECT * FROM `{$table_name}`", ARRAY_A ); if ( ! empty( $rows ) ) { fwrite( $handle, "{$nl}--{$nl}-- Dumping data for table `" . $table_name . "`{$nl}--{$nl}{$nl}" ); $columns = array_keys( $rows[0] ); $column_list = '`' . implode( '`, `', array_map( 'esc_sql', $columns ) ) . '`'; $chunk_size = 100; $total_rows = count( $rows ); for ( $i = 0; $i < $total_rows; $i += $chunk_size ) { $chunk = array_slice( $rows, $i, $chunk_size ); fwrite( $handle, "INSERT INTO `{$table_name}` ({$column_list}) VALUES{$nl}" ); $values = []; foreach ( $chunk as $row ) { $row_values = []; foreach ( $row as $value ) { if ( is_null( $value ) ) { $row_values[] = 'NULL'; } else { // Use MySQL's proper escaping for cross-platform compatibility if ( is_numeric( $value ) && ! is_string( $value ) ) { // For numeric values, use them directly without quotes $row_values[] = $value; } else { // For strings, use MySQL standard escaping (works on Windows & Linux) $value_str = (string) $value; // Normalize line endings first (before escaping backslashes) $escaped = str_replace( "\r\n", "\n", $value_str ); // Windows CRLF -> LF $escaped = str_replace( "\r", "\n", $escaped ); // Old Mac CR -> LF // Escape backslashes (critical: must be done before other escapes) $escaped = str_replace( '\\', '\\\\', $escaped ); // Escape single quotes (MySQL standard: double the quote) $escaped = str_replace( "'", "''", $escaped ); // Handle control characters that can break SQL imports $escaped = str_replace( "\x00", "\\0", $escaped ); // NULL byte $escaped = str_replace( "\x1a", "\\Z", $escaped ); // EOF marker // Escape normalized line endings for SQL $escaped = str_replace( "\n", "\\n", $escaped ); // Unix LF -> \n $row_values[] = "'" . $escaped . "'"; } } } $values[] = '(' . implode( ', ', $row_values ) . ')'; } fwrite( $handle, implode( ",{$nl}", $values ) . ";{$nl}{$nl}" ); } } } // Re-enable foreign key checks fwrite( $handle, "{$nl}/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;{$nl}" ); fwrite( $handle, "/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;{$nl}{$nl}" ); // SQL footer fwrite( $handle, "--{$nl}-- End of database dump{$nl}--{$nl}" ); fwrite( $handle, "/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;{$nl}" ); fwrite( $handle, "/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;{$nl}" ); fwrite( $handle, "/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;{$nl}" ); fclose( $handle ); return file_exists( $file_path ) ? $file_path : false; } /** * Helper: add folder recursively to open ZipArchive * $root_source is used to calculate relative paths correctly * $exclude is an array of absolute paths (realpath) or filenames to skip */ protected function aptce_add_folder_to_zip( $zip, $folder, $root_source, $exclude = [] ) { $folder = rtrim( $folder, '/\\' ); if ( ! is_dir( $folder ) ) return; $files = new RecursiveIteratorIterator( new RecursiveDirectoryIterator( $folder, FilesystemIterator::SKIP_DOTS ), RecursiveIteratorIterator::LEAVES_ONLY ); // Normalize root_source for consistent path comparison $root_source_normalized = wp_normalize_path( rtrim( $root_source, '/\\' ) ); foreach ( $files as $file ) { if ( $file->isDir() ) continue; $filePath = $file->getRealPath(); if ( ! $filePath ) continue; // Normalize file path for consistent comparison $filePath_normalized = wp_normalize_path( $filePath ); // Exclude by absolute path or by basename (wp-config.php) $skip = false; foreach ( $exclude as $ex ) { if ( empty( $ex ) ) continue; // if $ex is an absolute path (realpath), compare prefix $ex_path = realpath( $ex ); if ( $ex_path && strpos( $filePath_normalized, wp_normalize_path( $ex_path ) ) === 0 ) { $skip = true; break; } // if $ex is just a filename like 'wp-config.php' if ( basename( $filePath ) === $ex ) { $skip = true; break; } } if ( $skip ) continue; // Calculate relative path using normalized paths if ( strpos( $filePath_normalized, $root_source_normalized ) === 0 ) { $localPath = substr( $filePath_normalized, strlen( $root_source_normalized ) ); // Remove leading slash if present $localPath = ltrim( $localPath, '/' ); // Ensure forward slashes for ZIP compatibility $localPath = str_replace( '\\', '/', $localPath ); $zip->addFile( $filePath, $localPath ); } } } /** * Bulk export handler (form submit) */ public function aptce_handle_export() { if ( empty( $_POST ) ) { wp_safe_redirect( wp_get_referer() ?: admin_url() ); exit; } // Verify POST nonce for export action if ( empty( $_POST['aptce_nonce'] ) ) { wp_die( esc_html__( 'Security check failed: nonce missing.', 'advanced-addons-theme-core-exporter' ), esc_html__( 'Error', 'advanced-addons-theme-core-exporter' ), array( 'response' => 403, ) ); } $nonce = sanitize_text_field( wp_unslash( $_POST['aptce_nonce'] ) ); if ( ! wp_verify_nonce( $nonce, 'aptce_export' ) ) { wp_die( esc_html__( 'Security check failed: invalid nonce.', 'advanced-addons-theme-core-exporter' ), esc_html__( 'Error', 'advanced-addons-theme-core-exporter' ), array( 'response' => 403, ) ); } if ( ! current_user_can( 'manage_options' ) ) { wp_die( __( 'Insufficient permissions', 'advanced-addons-theme-core-exporter' ) ); } $files_to_add = []; $temp_files = []; // Plugins selected $plugins = isset( $_POST['aptce_plugins'] ) && is_array( $_POST['aptce_plugins'] ) ? array_map( 'sanitize_text_field', wp_unslash( $_POST['aptce_plugins'] ) ) : []; if ( $plugins ) { if ( is_admin() && ! function_exists( 'is_plugin_active' ) ) { include_once AATCE_ADMIN_INCLUDES . 'plugin.php'; } foreach ( $plugins as $plugin_path ) { // Build full plugin path from relative path $plugin_dir = wp_normalize_path( WP_PLUGIN_DIR . '/' . dirname( $plugin_path ) ); if ( is_dir( $plugin_dir ) ) { $files_to_add[] = realpath( $plugin_dir ); } } } // Themes selected $themes = isset( $_POST['aptce_themes'] ) && is_array( $_POST['aptce_themes'] ) ? array_map( 'sanitize_text_field', wp_unslash( $_POST['aptce_themes'] ) ) : []; if ( $themes ) { foreach ( $themes as $slug ) { $theme_dir = get_theme_root() . '/' . $slug; if ( is_dir( $theme_dir ) ) { $files_to_add[] = realpath( $theme_dir ); } } } // Core selections (if user checked the "Export selected WordPress core options" box) $export_core = isset( $_POST['aptce_export_core'] ) && '1' == $_POST['aptce_export_core']; if ( $export_core ) { // For each core checkbox, add a special marker or real path if ( isset( $_POST['aptce_core_full'] ) && '1' == $_POST['aptce_core_full'] ) { // Full core -> mark as root|core (we treat as special) $root_path = trailingslashit( realpath( ABSPATH ) ); if ( $root_path ) { $files_to_add[] = $root_path . '|core'; } } if ( isset( $_POST['aptce_core_uploads'] ) && '1' == $_POST['aptce_core_uploads'] ) { $upload_info = wp_upload_dir(); $uploads_dir = isset( $upload_info['basedir'] ) ? $upload_info['basedir'] : ''; if ( ! empty( $uploads_dir ) && is_dir( $uploads_dir ) ) { $files_to_add[] = trailingslashit( $uploads_dir ); } } if ( isset( $_POST['aptce_core_wpcontent'] ) && '1' == $_POST['aptce_core_wpcontent'] ) { $wpcontent_dir = wp_normalize_path( WP_CONTENT_DIR ); if ( ! empty( $wpcontent_dir ) && is_dir( $wpcontent_dir ) ) { $files_to_add[] = array( 'path' => trailingslashit( $wpcontent_dir ), 'type' => 'wpcontent_no_uploads', 'exclude' => array( wp_normalize_path( AATCE_UPLOADS_DIR ) ), ); } } if ( isset( $_POST['aptce_core_admin'] ) && '1' == $_POST['aptce_core_admin'] ) { $admin_dir = wp_normalize_path( AATCE_ADMIN ); if ( ! empty( $admin_dir ) && is_dir( $admin_dir ) ) { $files_to_add[] = array( 'path' => trailingslashit( $admin_dir ), 'type' => 'admin', ); } } if ( isset( $_POST['aptce_core_includes'] ) && '1' == $_POST['aptce_core_includes'] ) { $includes_dir = wp_normalize_path( ABSPATH . 'wp-includes' ); if ( ! empty( $includes_dir ) && is_dir( $includes_dir ) ) { $files_to_add[] = array( 'path' => trailingslashit( $includes_dir ), 'type' => 'includes', ); } } if ( isset( $_POST['aptce_core_full_100'] ) && '1' == $_POST['aptce_core_full_100'] ) { //$root_dir = wp_normalize_path( ABSPATH ); $root_dir = wp_normalize_path( trailingslashit( ABSPATH ) ); if ( ! empty( $root_dir ) && is_dir( $root_dir ) ) { $files_to_add[] = array( 'path' => trailingslashit( $root_dir ), 'type' => 'core_100', // Full WordPress export (no exclusions) ); } } } // Remote repo download by slug (optional) $remote_slug = isset( $_POST['aptce_remote_slug'] ) ? sanitize_text_field( wp_unslash( $_POST['aptce_remote_slug'] ) ) : ''; $remote_type = isset( $_POST['aptce_remote_type'] ) ? sanitize_text_field( wp_unslash( $_POST['aptce_remote_type'] ) ) : ''; if ( $remote_slug && in_array( $remote_type, ['plugin', 'theme'], true ) ) { $zip_url = ''; if ( 'plugin' === $remote_type ) { $zip_url = 'https://downloads.wordpress.org/plugin/' . rawurlencode( $remote_slug ) . '.zip'; } else { $zip_url = 'https://downloads.wordpress.org/theme/' . rawurlencode( $remote_slug ) . '.zip'; } $response = wp_remote_get( $zip_url, [ 'timeout' => 30 ] ); if ( ! is_wp_error( $response ) && 200 === wp_remote_retrieve_response_code( $response ) ) { $body = wp_remote_retrieve_body( $response ); if ( $body ) { $tmp = wp_tempnam( $zip_url ); file_put_contents( $tmp, $body ); $temp_files[] = $tmp; } } } // Database export (if checkbox is checked) $database_file = null; if ( isset( $_POST['aptce_download_database'] ) && '1' == $_POST['aptce_download_database'] ) { $upload = wp_upload_dir(); $db_file_path = $upload['basedir'] . '/aptce-database-' . time() . '.sql'; $database_file = $this->aptce_generate_database_dump_file( $db_file_path ); if ( $database_file ) { $temp_files[] = $database_file; } } if ( empty( $files_to_add ) && empty( $temp_files ) ) { wp_safe_redirect( wp_get_referer() ?: admin_url() ); exit; } $upload = wp_upload_dir(); $tmp_zip = $upload['basedir'] . '/aptce-export-' . time() . '.zip'; // ✅ Prefer ZipArchive if available if ( class_exists( 'ZipArchive' ) ) { $zip = new ZipArchive(); if ( $zip->open( $tmp_zip, ZipArchive::CREATE ) !== TRUE ) { wp_die( esc_html__( 'Could not create archive', 'advanced-addons-theme-core-exporter' ) ); } // Track added files to prevent duplicates $added_files = array(); // Add items to main ZIP foreach ( $files_to_add as $item ) { // Handle array-based items (with type and exclude info) if ( is_array( $item ) ) { $item_path = isset( $item['path'] ) ? $item['path'] : ''; $item_type = isset( $item['type'] ) ? $item['type'] : ''; $item_exclude = isset( $item['exclude'] ) ? (array) $item['exclude'] : []; if ( empty( $item_path ) ) { continue; } // Handle different types if ( 'core_100' === $item_type ) { // Full core with no exclusions $root = AATCE_ROOT_PATH; if ( $root ) { $root_normalized = wp_normalize_path( rtrim( $root, '/\\' ) ); $iterator = new RecursiveIteratorIterator( new RecursiveDirectoryIterator( $root, FilesystemIterator::SKIP_DOTS ), RecursiveIteratorIterator::LEAVES_ONLY ); foreach ( $iterator as $file ) { if ( $file->isDir() ) continue; $filePath = $file->getRealPath(); if ( ! $filePath ) continue; $filePath_normalized = wp_normalize_path( $filePath ); if ( strpos( $filePath_normalized, $root_normalized ) === 0 ) { $localPath = substr( $filePath_normalized, strlen( $root_normalized ) ); $localPath = ltrim( $localPath, '/' ); $localPath = str_replace( '\\', '/', $localPath ); if ( ! isset( $added_files[ $localPath ] ) ) { $zip->addFile( $filePath, $localPath ); $added_files[ $localPath ] = true; } } } } } elseif ( 'wpcontent_no_uploads' === $item_type ) { // wp-content excluding uploads $base_path = realpath( $item_path ); if ( $base_path ) { $files = new RecursiveIteratorIterator( new RecursiveDirectoryIterator( $base_path, FilesystemIterator::SKIP_DOTS ), RecursiveIteratorIterator::LEAVES_ONLY ); foreach ( $files as $file ) { if ( $file->isDir() ) continue; $filePath = $file->getRealPath(); // Check exclusions $skip = false; foreach ( $item_exclude as $exclude_path ) { if ( realpath( $exclude_path ) && strpos( $filePath, realpath( $exclude_path ) ) === 0 ) { $skip = true; break; } } if ( $skip ) continue; $base_path_normalized = wp_normalize_path( rtrim( $base_path, '/\\' ) ); $filePath_normalized = wp_normalize_path( $filePath ); if ( strpos( $filePath_normalized, $base_path_normalized ) === 0 ) { $relative = substr( $filePath_normalized, strlen( $base_path_normalized ) ); $relative = ltrim( $relative, '/' ); $localPath = 'wp-content/' . str_replace( '\\', '/', $relative ); } else { continue; } if ( ! isset( $added_files[ $localPath ] ) ) { $zip->addFile( $filePath, $localPath ); $added_files[ $localPath ] = true; } } } } elseif ( 'admin' === $item_type || 'includes' === $item_type ) { // Admin or includes directory $dir_path = realpath( $item_path ); if ( $dir_path ) { $base = basename( $dir_path ); $files = new RecursiveIteratorIterator( new RecursiveDirectoryIterator( $dir_path, FilesystemIterator::SKIP_DOTS ), RecursiveIteratorIterator::LEAVES_ONLY ); foreach ( $files as $file ) { if ( $file->isDir() ) continue; $filePath = $file->getRealPath(); if ( ! $filePath ) continue; $dir_path_normalized = wp_normalize_path( rtrim( $dir_path, '/\\' ) ); $filePath_normalized = wp_normalize_path( $filePath ); if ( strpos( $filePath_normalized, $dir_path_normalized ) === 0 ) { $relative = substr( $filePath_normalized, strlen( $dir_path_normalized ) ); $relative = ltrim( $relative, '/' ); $localPath = $base . '/' . str_replace( '\\', '/', $relative ); } else { continue; } if ( ! isset( $added_files[ $localPath ] ) ) { $zip->addFile( $filePath, $localPath ); $added_files[ $localPath ] = true; } } } } continue; } // Handle string-based items if ( ! is_string( $item ) ) { continue; } // core 100% special handling - include everything, no exclusions if ( false !== strpos( $item, '|core_100' ) ) { $root = AATCE_ROOT_PATH; if ( $root ) { $root_normalized = wp_normalize_path( rtrim( $root, '/\\' ) ); $iterator = new RecursiveIteratorIterator( new RecursiveDirectoryIterator( $root, FilesystemIterator::SKIP_DOTS ), RecursiveIteratorIterator::LEAVES_ONLY ); foreach ( $iterator as $file ) { if ( $file->isDir() ) continue; $filePath = $file->getRealPath(); if ( ! $filePath ) continue; $filePath_normalized = wp_normalize_path( $filePath ); if ( strpos( $filePath_normalized, $root_normalized ) === 0 ) { $localPath = substr( $filePath_normalized, strlen( $root_normalized ) ); $localPath = ltrim( $localPath, '/' ); $localPath = str_replace( '\\', '/', $localPath ); // Check for duplicates if ( ! isset( $added_files[ $localPath ] ) ) { $zip->addFile( $filePath, $localPath ); $added_files[ $localPath ] = true; } } } } continue; } // core special handling (excludes uploads and wp-config.php) if ( false !== strpos( $item, '|core' ) ) { $root = AATCE_ROOT_PATH; if ( $root ) { $iterator = new RecursiveIteratorIterator( new RecursiveDirectoryIterator( $root, FilesystemIterator::SKIP_DOTS ), RecursiveIteratorIterator::LEAVES_ONLY ); foreach ( $iterator as $file ) { if ( $file->isDir() ) continue; $filePath = $file->getRealPath(); // exclude uploads //if ( 0 === strpos( $filePath, realpath( WP_CONTENT_DIR . '/uploads' ) ) ) continue; $uploads = wp_upload_dir(); $uploads_dir = wp_normalize_path( $uploads['basedir'] ); if ( 0 === strpos( wp_normalize_path( $filePath ), $uploads_dir ) ) { continue; } // exclude wp-config.php if ( basename( $filePath ) === 'wp-config.php' ) continue; $root_normalized = wp_normalize_path( rtrim( $root, '/\\' ) ); $filePath_normalized = wp_normalize_path( $filePath ); if ( strpos( $filePath_normalized, $root_normalized ) === 0 ) { $localPath = substr( $filePath_normalized, strlen( $root_normalized ) ); $localPath = ltrim( $localPath, '/' ); $localPath = str_replace( '\\', '/', $localPath ); // Check for duplicates if ( ! isset( $added_files[ $localPath ] ) ) { $zip->addFile( $filePath, $localPath ); $added_files[ $localPath ] = true; } } } } continue; } if ( false !== strpos( $item, '|wpcontent_no_uploads' ) ) { $base_path = realpath( WP_CONTENT_DIR ); if ( $base_path ) { $files = new RecursiveIteratorIterator( new RecursiveDirectoryIterator( $base_path, FilesystemIterator::SKIP_DOTS ), RecursiveIteratorIterator::LEAVES_ONLY ); foreach ( $files as $file ) { if ( $file->isDir() ) continue; $filePath = $file->getRealPath(); //if ( 0 === strpos( $filePath, realpath( WP_CONTENT_DIR . '/uploads' ) ) ) continue; $uploads = wp_upload_dir(); $uploads_dir = wp_normalize_path( $uploads['basedir'] ); if ( 0 === strpos( wp_normalize_path( $filePath ), $uploads_dir ) ) { continue; } $base_path_normalized = wp_normalize_path( rtrim( $base_path, '/\\' ) ); $filePath_normalized = wp_normalize_path( $filePath ); if ( strpos( $filePath_normalized, $base_path_normalized ) === 0 ) { $relative = substr( $filePath_normalized, strlen( $base_path_normalized ) ); $relative = ltrim( $relative, '/' ); $localPath = 'wp-content/' . str_replace( '\\', '/', $relative ); } else { continue; } // Check for duplicates if ( ! isset( $added_files[ $localPath ] ) ) { $zip->addFile( $filePath, $localPath ); $added_files[ $localPath ] = true; } } } continue; } // regular directory (plugins, themes, etc.) if ( is_dir( $item ) ) { $item_realpath = realpath( $item ); if ( $item_realpath ) { $base = basename( $item_realpath ); $files = new RecursiveIteratorIterator( new RecursiveDirectoryIterator( $item_realpath, FilesystemIterator::SKIP_DOTS ), RecursiveIteratorIterator::LEAVES_ONLY ); foreach ( $files as $file ) { if ( $file->isDir() ) continue; $filePath = $file->getRealPath(); if ( ! $filePath ) continue; $item_realpath_normalized = wp_normalize_path( rtrim( $item_realpath, '/\\' ) ); $filePath_normalized = wp_normalize_path( $filePath ); if ( strpos( $filePath_normalized, $item_realpath_normalized ) === 0 ) { $relative = substr( $filePath_normalized, strlen( $item_realpath_normalized ) ); $relative = ltrim( $relative, '/' ); $localPath = $base . '/' . str_replace( '\\', '/', $relative ); } else { continue; } // Check for duplicates if ( ! isset( $added_files[ $localPath ] ) ) { $zip->addFile( $filePath, $localPath ); $added_files[ $localPath ] = true; } } } } } // add any temp files (database or remote zips) foreach ( $temp_files as $tf ) { if ( is_file( $tf ) ) { // Check if it's a database file if ( false !== strpos( $tf, 'aptce-database' ) ) { $zip->addFile( $tf, 'wordpress-database-' . date( 'Ymd-His' ) . '.sql' ); } else { // Remote zips go in 'remote' folder $zip->addFile( $tf, 'remote/' . basename( $tf ) ); } } } $zip->close(); } else { // ✅ Fallback to WordPress bundled PclZip if ( ! class_exists( 'PclZip' ) ) { include_once AATCE_ADMIN_INCLUDES . 'class-pclzip.php'; } $archive = new PclZip( $tmp_zip ); $added_files = array(); // Add items to main ZIP foreach ( $files_to_add as $item ) { // Handle array-based items (with type and exclude info) if ( is_array( $item ) ) { $item_path = isset( $item['path'] ) ? $item['path'] : ''; $item_type = isset( $item['type'] ) ? $item['type'] : ''; $item_exclude = isset( $item['exclude'] ) ? (array) $item['exclude'] : []; if ( empty( $item_path ) ) { continue; } // Handle different types if ( 'core_100' === $item_type ) { // Full core with no exclusions $root = AATCE_ROOT_PATH; if ( $root ) { $archive->add( $root, PCLZIP_OPT_REMOVE_PATH, dirname( $root ) ); } } elseif ( 'wpcontent_no_uploads' === $item_type ) { // wp-content excluding uploads $base_path = realpath( $item_path ); if ( $base_path ) { $files = new RecursiveIteratorIterator( new RecursiveDirectoryIterator( $base_path, FilesystemIterator::SKIP_DOTS ), RecursiveIteratorIterator::LEAVES_ONLY ); $file_list = array(); foreach ( $files as $file ) { if ( $file->isDir() ) continue; $filePath = $file->getRealPath(); // Check exclusions $skip = false; foreach ( $item_exclude as $exclude_path ) { if ( realpath( $exclude_path ) && strpos( $filePath, realpath( $exclude_path ) ) === 0 ) { $skip = true; break; } } if ( $skip ) continue; if ( file_exists( $filePath ) ) { $file_list[] = $filePath; } } if ( ! empty( $file_list ) ) { $archive->add( $file_list, PCLZIP_OPT_REMOVE_PATH, dirname( $base_path ) ); } } } elseif ( 'admin' === $item_type || 'includes' === $item_type ) { // Admin or includes directory $dir_path = realpath( $item_path ); if ( $dir_path ) { $archive->add( $dir_path, PCLZIP_OPT_REMOVE_PATH, dirname( $dir_path ) ); } } continue; } // Handle string-based items if ( ! is_string( $item ) ) { continue; } // core 100% special handling - include everything, no exclusions if ( false !== strpos( $item, '|core_100' ) ) { $root = AATCE_ROOT_PATH; if ( $root ) { $archive->add( $root, PCLZIP_OPT_REMOVE_PATH, dirname( $root ) ); } continue; } // core special handling (excludes uploads and wp-config.php) if ( false !== strpos( $item, '|core' ) ) { $root = AATCE_ROOT_PATH; if ( $root ) { $files = new RecursiveIteratorIterator( new RecursiveDirectoryIterator( $root, FilesystemIterator::SKIP_DOTS ), RecursiveIteratorIterator::LEAVES_ONLY ); $file_list = array(); foreach ( $files as $file ) { if ( $file->isDir() ) continue; $filePath = $file->getRealPath(); // exclude uploads //if ( 0 === strpos( $filePath, realpath( WP_CONTENT_DIR . '/uploads' ) ) ) continue; $uploads = wp_upload_dir(); $uploads_dir = wp_normalize_path( $uploads['basedir'] ); if ( 0 === strpos( wp_normalize_path( $filePath ), $uploads_dir ) ) { continue; } // exclude wp-config.php if ( basename( $filePath ) === 'wp-config.php' ) continue; if ( file_exists( $filePath ) ) { $file_list[] = $filePath; } } if ( ! empty( $file_list ) ) { $archive->add( $file_list, PCLZIP_OPT_REMOVE_PATH, dirname( $root ) ); } } continue; } if ( false !== strpos( $item, '|wpcontent_no_uploads' ) ) { $base_path = realpath( WP_CONTENT_DIR ); if ( $base_path ) { $files = new RecursiveIteratorIterator( new RecursiveDirectoryIterator( $base_path, FilesystemIterator::SKIP_DOTS ), RecursiveIteratorIterator::LEAVES_ONLY ); $file_list = array(); foreach ( $files as $file ) { if ( $file->isDir() ) continue; $filePath = $file->getRealPath(); //if ( 0 === strpos( $filePath, realpath( WP_CONTENT_DIR . '/uploads' ) ) ) continue; $uploads = wp_upload_dir(); $uploads_dir = wp_normalize_path( $uploads['basedir'] ); if ( 0 === strpos( wp_normalize_path( $filePath ), $uploads_dir ) ) { continue; } if ( file_exists( $filePath ) ) { $file_list[] = $filePath; } } if ( ! empty( $file_list ) ) { $archive->add( $file_list, PCLZIP_OPT_REMOVE_PATH, dirname( $base_path ) ); } } continue; } // regular directory (plugins, themes, etc.) if ( is_dir( $item ) ) { $item_realpath = realpath( $item ); if ( $item_realpath ) { // For plugins/themes, preserve the folder structure by removing parent directory $parent_dir = dirname( $item_realpath ); $archive->add( $item_realpath, PCLZIP_OPT_REMOVE_PATH, $parent_dir ); } } } // add any temp files (database or remote zips) foreach ( $temp_files as $tf ) { if ( is_file( $tf ) && file_exists( $tf ) ) { // Check if it's a database file if ( false !== strpos( $tf, 'aptce-database' ) ) { // Create temp file with proper name for PclZip $db_filename = 'wordpress-database-' . date( 'Ymd-His' ) . '.sql'; $temp_db_file = dirname( $tf ) . '/' . $db_filename; if ( copy( $tf, $temp_db_file ) ) { $archive->add( $temp_db_file, PCLZIP_OPT_REMOVE_PATH, dirname( $temp_db_file ) ); // Clean up temp file after adding @unlink( $temp_db_file ); } } else { // Remote zips go in 'remote' folder $archive->add( $tf, PCLZIP_OPT_ADD_PATH, 'remote' ); } } } } if ( is_file( $tmp_zip ) ) { header( 'Content-Description: File Transfer' ); header( 'Content-Type: application/zip' ); header( 'Content-Disposition: attachment; filename="' . basename( $tmp_zip ) . '"' ); header( 'Content-Length: ' . filesize( $tmp_zip ) ); readfile( $tmp_zip ); @unlink( $tmp_zip ); foreach ( $temp_files as $f ) { @unlink( $f ); } exit; } wp_die( __( 'ZIP creation failed', 'advanced-addons-theme-core-exporter' ) ); } /** * Add download link to plugin action links */ function aptce_add_plugin_download_link( $actions, $plugin_file ) { if ( ! current_user_can( 'manage_options' ) ) { return $actions; } // Ensure get_plugins() is loaded if ( ! function_exists( 'get_plugins' ) ) { require_once AATCE_ADMIN_INCLUDES . 'plugin.php'; } $all_plugins = get_plugins(); if ( ! isset( $all_plugins[ $plugin_file ] ) ) { return $actions; // plugin not found } // Generate download URL $download_url = wp_nonce_url( admin_url( 'admin-post.php?action=aptce_export_single&type=plugin&item=' . rawurlencode( $plugin_file ) ), 'aptce_export_single' ); // Build download link $download_link = '' . esc_html__( 'Download', 'advanced-addons-theme-core-exporter' ) . ''; // Insert the download link at the beginning of action links $actions = array_merge( [ 'aptce_download' => $download_link ], $actions ); return $actions; } /** * Add download link to theme action links */ public function aptce_add_theme_download_link( $actions, $theme, $context = 'all' ) { // Check permissions if ( ! current_user_can( 'manage_options' ) ) { return $actions; } // Ensure $actions is an array if ( ! is_array( $actions ) ) { $actions = array(); } // Ensure $theme is a WP_Theme object if ( ! is_a( $theme, 'WP_Theme' ) ) { return $actions; } // Get theme slug $theme_slug = $theme->get_stylesheet(); if ( empty( $theme_slug ) ) { return $actions; } $theme_dir = get_theme_root() . '/' . $theme_slug; if ( ! is_dir( $theme_dir ) ) { return $actions; } $download_url = wp_nonce_url( admin_url( 'admin-post.php?action=aptce_export_single&type=theme&item=' . rawurlencode( $theme_slug ) ), 'aptce_export_single' ); $download_link = '' . esc_html__( 'Download', 'advanced-addons-theme-core-exporter' ) . ''; // Add download link to actions array // Use array_merge to preserve existing actions and add ours at the beginning $actions = array_merge( array( 'aptce_download' => $download_link ), $actions ); return $actions; } /** * Add download link to themes prepared for JavaScript (wp_prepare_themes_for_js filter) */ public function aptce_prepare_themes_for_js( $themes ) { // Check permissions if ( ! current_user_can( 'manage_options' ) ) { return $themes; } if ( ! is_array( $themes ) ) { return $themes; } foreach ( $themes as &$theme ) { if ( empty( $theme['stylesheet'] ) ) continue; $slug = $theme['stylesheet']; // Generate export link $download_url = wp_nonce_url( admin_url( 'admin-post.php?action=aptce_export_single&type=theme&item=' . rawurlencode( $slug ) ), 'aptce_export_single' ); // Attach to REST API response $theme['aptce_download'] = esc_url( $download_url ); } return $themes; } /** * Download theme handler */ public function aptce_download_theme() { // ---- Required params check ---- if ( ! isset( $_GET['slug'], $_GET['_wpnonce'] ) ) { wp_die( __( 'Invalid request.', 'advanced-addons-theme-core-exporter' ), __( 'Error', 'advanced-addons-theme-core-exporter' ), array( 'response' => 400 ) ); } // ---- Sanitize & validate slug FIRST ---- $slug = sanitize_key( wp_unslash( $_GET['slug'] ) ); if ( empty( $slug ) ) { wp_die( __( 'Invalid theme slug.', 'advanced-addons-theme-core-exporter' ), __( 'Error', 'advanced-addons-theme-core-exporter' ), array( 'response' => 400 ) ); } // ---- Sanitize nonce ---- $nonce = sanitize_text_field( wp_unslash( $_GET['_wpnonce'] ) ); // ---- Construct & verify nonce ---- $nonce_action = 'aptce_download_' . $slug; if ( ! wp_verify_nonce( $nonce, $nonce_action ) ) { wp_die( __( 'Security check failed (invalid nonce).', 'advanced-addons-theme-core-exporter' ), __( 'Error', 'advanced-addons-theme-core-exporter' ), array( 'response' => 403 ) ); } // ---- Capability check ---- if ( ! current_user_can( 'manage_options' ) ) { wp_die( __( 'You do not have permission to download themes.', 'advanced-addons-theme-core-exporter' ), __( 'Error', 'advanced-addons-theme-core-exporter' ), array( 'response' => 403 ) ); } // ---- Validate theme directory ---- $theme_dir = trailingslashit( get_theme_root() ) . $slug; if ( ! is_dir( $theme_dir ) ) { wp_die( __( 'Theme directory not found.', 'advanced-addons-theme-core-exporter' ), __( 'Error', 'advanced-addons-theme-core-exporter' ), array( 'response' => 404 ) ); } // ---- Temp ZIP directory safe fallback ---- $temp_dir = wp_normalize_path( sys_get_temp_dir() ); if ( ! is_writable( $temp_dir ) ) { $upload = wp_upload_dir(); $temp_dir = wp_normalize_path( $upload['basedir'] ); } if ( ! is_dir( $temp_dir ) ) { wp_mkdir_p( $temp_dir ); } $zip_path = $temp_dir . '/aptce_' . time() . '_' . wp_generate_password( 8, false ) . '.zip'; /** * ================================================= * 1. TRY ZipArchive FIRST * ================================================= */ if ( class_exists( 'ZipArchive' ) ) { $zip = new ZipArchive(); if ( $zip->open( $zip_path, ZipArchive::CREATE ) === true ) { $files = new RecursiveIteratorIterator( new RecursiveDirectoryIterator( $theme_dir, RecursiveDirectoryIterator::SKIP_DOTS ), RecursiveIteratorIterator::SELF_FIRST ); $theme_dir_normalized = wp_normalize_path( rtrim( $theme_dir, '/\\' ) ); foreach ( $files as $file ) { $real = $file->getRealPath(); if ( ! $real ) continue; $real_normalized = wp_normalize_path( $real ); if ( strpos( $real_normalized, $theme_dir_normalized ) === 0 ) { $local = substr( $real_normalized, strlen( $theme_dir_normalized ) ); $local = ltrim( $local, '/' ); $local = str_replace( '\\', '/', $local ); if ( $file->isDir() ) { $zip->addEmptyDir( $local ); } else { $zip->addFile( $real, $local ); } } } $zip->close(); } else { wp_die( __( 'Failed to create ZIP using ZipArchive.', 'advanced-addons-theme-core-exporter' ) ); } } else { /** * ================================================= * 2. FALLBACK TO PclZip * ================================================= */ if ( ! class_exists( 'PclZip' ) ) { $pclzip_path = AATCE_ADMIN_INCLUDES . 'class-pclzip.php'; if ( file_exists( $pclzip_path ) ) { include_once $pclzip_path; } else { wp_die( __( 'Neither ZipArchive nor PclZip are available on this server.', 'advanced-addons-theme-core-exporter' ) ); } } $archive = new PclZip( $zip_path ); $result = $archive->create( $theme_dir, PCLZIP_OPT_REMOVE_PATH, dirname( $theme_dir ) ); if ( ! $result ) { wp_die( esc_html__( 'PclZip failed: ', 'advanced-addons-theme-core-exporter' ) . esc_html( $archive->errorInfo( true ) ) ); } } // ---- Send ZIP ---- if ( ! file_exists( $zip_path ) || filesize( $zip_path ) === 0 ) { wp_die( __( 'ZIP file creation failed.', 'advanced-addons-theme-core-exporter' ) ); } header( 'Content-Type: application/zip' ); header( 'Content-Disposition: attachment; filename="' . $slug . '.zip"' ); header( 'Content-Length: ' . filesize( $zip_path ) ); readfile( $zip_path ); unlink( $zip_path ); exit; } /** * AJAX handler for plugin download */ public function aptce_ajax_download_plugin() { check_ajax_referer( 'aptce_export', 'nonce' ); if ( ! current_user_can( 'manage_options' ) ) { wp_send_json_error( [ 'message' => __( 'Insufficient permissions', 'advanced-addons-theme-core-exporter' ) ] ); } $plugin_path = isset( $_POST['plugin'] ) ? sanitize_text_field( wp_unslash( $_POST['plugin'] ) ) : ''; if ( empty( $plugin_path ) ) { wp_send_json_error( [ 'message' => __( 'Invalid plugin', 'advanced-addons-theme-core-exporter' ) ] ); } // Create the zip file $result = $this->aptce_create_plugin_zip( $plugin_path ); if ( $result['success'] ) { wp_send_json_success( [ 'file' => $result['file'], 'url' => $result['url'], 'filename' => $result['filename'] ] ); } else { wp_send_json_error( [ 'message' => $result['message'] ] ); } } /** * AJAX handler for theme download */ public function aptce_ajax_download_theme() { check_ajax_referer( 'aptce_export', 'nonce' ); if ( ! current_user_can( 'manage_options' ) ) { wp_send_json_error( [ 'message' => __( 'Insufficient permissions', 'advanced-addons-theme-core-exporter' ) ] ); } $theme_slug = isset( $_POST['theme'] ) ? sanitize_text_field( wp_unslash( $_POST['theme'] ) ) : ''; if ( empty( $theme_slug ) ) { wp_send_json_error( [ 'message' => __( 'Invalid theme', 'advanced-addons-theme-core-exporter' ) ] ); } // Create the zip file $result = $this->aptce_create_theme_zip( $theme_slug ); if ( $result['success'] ) { wp_send_json_success( [ 'file' => $result['file'], 'url' => $result['url'], 'filename' => $result['filename'] ] ); } else { wp_send_json_error( [ 'message' => $result['message'] ] ); } } /** * AJAX handler for core files download */ public function aptce_ajax_download_core() { check_ajax_referer( 'aptce_export', 'nonce' ); if ( ! current_user_can( 'manage_options' ) ) { wp_send_json_error( [ 'message' => __( 'Insufficient permissions', 'advanced-addons-theme-core-exporter' ) ] ); } $type = isset( $_POST['type'] ) ? sanitize_text_field( wp_unslash( $_POST['type'] ) ) : ''; if ( empty( $type ) ) { wp_send_json_error( [ 'message' => __( 'Invalid type', 'advanced-addons-theme-core-exporter' ) ] ); } // Create the zip file $result = $this->aptce_create_core_zip( $type ); if ( $result['success'] ) { wp_send_json_success( [ 'file' => $result['file'], 'url' => $result['url'], 'filename' => $result['filename'] ] ); } else { wp_send_json_error( [ 'message' => $result['message'] ] ); } } /** * AJAX handler for database download */ public function aptce_ajax_download_database() { check_ajax_referer( 'aptce_export', 'nonce' ); if ( ! current_user_can( 'manage_options' ) ) { wp_send_json_error( [ 'message' => __( 'Insufficient permissions', 'advanced-addons-theme-core-exporter' ) ] ); } // Create the database dump file $result = $this->aptce_create_database_dump(); if ( $result['success'] ) { wp_send_json_success( [ 'file' => $result['file'], 'url' => $result['url'], 'filename' => $result['filename'] ] ); } else { wp_send_json_error( [ 'message' => $result['message'] ] ); } } /** * Helper: Create plugin zip */ protected function aptce_create_plugin_zip( $plugin_path ) { if ( ! function_exists( 'get_plugin_data' ) ) { require_once AATCE_ADMIN_INCLUDES . 'plugin.php'; } $plugin_data = get_plugin_data( WP_PLUGIN_DIR . '/' . $plugin_path ); $item_name = ! empty( $plugin_data['Name'] ) ? $plugin_data['Name'] : dirname( $plugin_path ); $item_name = sanitize_file_name( strtolower( str_replace( ' ', '-', $item_name ) ) ); $upload = wp_upload_dir(); $basedir = trailingslashit( wp_normalize_path( $upload['basedir'] ) ); $tmp_zip = $basedir . 'aptce-plugin-' . time() . '.zip'; $zip_filename = $item_name . '.zip'; try { if ( class_exists( 'ZipArchive' ) ) { $zip = new ZipArchive(); if ( $zip->open( $tmp_zip, ZipArchive::CREATE ) !== TRUE ) { return [ 'success' => false, 'message' => __( 'Could not create archive', 'advanced-addons-theme-core-exporter' ) ]; } $plugin_dir = wp_normalize_path( WP_PLUGIN_DIR . '/' . dirname( $plugin_path ) ); if ( is_dir( $plugin_dir ) ) { $base = basename( $plugin_dir ); $plugin_dir_normalized = wp_normalize_path( rtrim( $plugin_dir, '/\\\\' ) ); $files = new RecursiveIteratorIterator( new RecursiveDirectoryIterator( $plugin_dir ), RecursiveIteratorIterator::LEAVES_ONLY ); foreach ( $files as $file ) { if ( $file->isDir() ) continue; $filePath = $file->getRealPath(); if ( ! $filePath ) continue; $filePath_normalized = wp_normalize_path( $filePath ); if ( strpos( $filePath_normalized, $plugin_dir_normalized ) === 0 ) { $relative = substr( $filePath_normalized, strlen( $plugin_dir_normalized ) ); $relative = ltrim( $relative, '/' ); $relative = str_replace( '\\\\', '/', $relative ); $zip->addFile( $filePath, $base . '/' . $relative ); } } } $zip->close(); } else { return [ 'success' => false, 'message' => __( 'ZipArchive not available', 'advanced-addons-theme-core-exporter' ) ]; } if ( ! file_exists( $tmp_zip ) || filesize( $tmp_zip ) === 0 ) { return [ 'success' => false, 'message' => __( 'ZIP creation failed', 'advanced-addons-theme-core-exporter' ) ]; } return [ 'success' => true, 'file' => basename( $tmp_zip ), 'url' => $upload['baseurl'] . '/' . basename( $tmp_zip ), 'filename' => $zip_filename ]; } catch ( Exception $e ) { return [ 'success' => false, 'message' => $e->getMessage() ]; } } /** * Helper: Create theme zip */ protected function aptce_create_theme_zip( $theme_slug ) { $theme = wp_get_theme( $theme_slug ); $item_name = $theme->get( 'Name' ) ? $theme->get( 'Name' ) : $theme_slug; $item_name = sanitize_file_name( strtolower( str_replace( ' ', '-', $item_name ) ) ); $upload = wp_upload_dir(); $basedir = trailingslashit( wp_normalize_path( $upload['basedir'] ) ); $tmp_zip = $basedir . 'aptce-theme-' . time() . '.zip'; $zip_filename = $item_name . '.zip'; try { if ( class_exists( 'ZipArchive' ) ) { $zip = new ZipArchive(); if ( $zip->open( $tmp_zip, ZipArchive::CREATE ) !== TRUE ) { return [ 'success' => false, 'message' => __( 'Could not create archive', 'advanced-addons-theme-core-exporter' ) ]; } $theme_dir = wp_normalize_path( get_theme_root() . '/' . $theme_slug ); if ( is_dir( $theme_dir ) ) { $base = basename( $theme_dir ); $theme_dir_normalized = wp_normalize_path( rtrim( $theme_dir, '/\\\\' ) ); $files = new RecursiveIteratorIterator( new RecursiveDirectoryIterator( $theme_dir ), RecursiveIteratorIterator::LEAVES_ONLY ); foreach ( $files as $file ) { if ( $file->isDir() ) continue; $filePath = $file->getRealPath(); if ( ! $filePath ) continue; $filePath_normalized = wp_normalize_path( $filePath ); if ( strpos( $filePath_normalized, $theme_dir_normalized ) === 0 ) { $relative = substr( $filePath_normalized, strlen( $theme_dir_normalized ) ); $relative = ltrim( $relative, '/' ); $relative = str_replace( '\\\\', '/', $relative ); $zip->addFile( $filePath, $base . '/' . $relative ); } } } $zip->close(); } else { return [ 'success' => false, 'message' => __( 'ZipArchive not available', 'advanced-addons-theme-core-exporter' ) ]; } if ( ! file_exists( $tmp_zip ) || filesize( $tmp_zip ) === 0 ) { return [ 'success' => false, 'message' => __( 'ZIP creation failed', 'advanced-addons-theme-core-exporter' ) ]; } return [ 'success' => true, 'file' => basename( $tmp_zip ), 'url' => $upload['baseurl'] . '/' . basename( $tmp_zip ), 'filename' => $zip_filename ]; } catch ( Exception $e ) { return [ 'success' => false, 'message' => $e->getMessage() ]; } } /** * Helper: Create core files zip */ protected function aptce_create_core_zip( $type ) { $upload = wp_upload_dir(); switch ( $type ) { case 'full_100': $source = ABSPATH; $zip_name = 'wordpress-full-100-percent-' . date( 'Ymd-His' ) . '.zip'; $exclude = []; break; case 'full': $source = ABSPATH; $uploads_dir = $upload['basedir']; $exclude = [ $uploads_dir, ABSPATH . 'wp-config.php' ]; $zip_name = 'wordpress-core-full-' . date( 'Ymd-His' ) . '.zip'; break; case 'uploads': $source = $upload['basedir']; $zip_name = 'wp-uploads-' . date( 'Ymd-His' ) . '.zip'; $exclude = []; break; case 'wpcontent': $source = WP_CONTENT_DIR; $uploads_dir = $upload['basedir']; $exclude = [ $uploads_dir ]; $zip_name = 'wp-content-no-uploads-' . date( 'Ymd-His' ) . '.zip'; break; case 'admin': $source = trailingslashit( ABSPATH ) . 'wp-admin'; $zip_name = 'wp-admin-' . date( 'Ymd-His' ) . '.zip'; $exclude = []; break; case 'includes': $source = trailingslashit( ABSPATH ) . 'wp-includes'; $zip_name = 'wp-includes-' . date( 'Ymd-His' ) . '.zip'; $exclude = []; break; default: return [ 'success' => false, 'message' => __( 'Invalid type', 'advanced-addons-theme-core-exporter' ) ]; } if ( ! $source || ! is_dir( $source ) ) { return [ 'success' => false, 'message' => __( 'Directory not found', 'advanced-addons-theme-core-exporter' ) ]; } $tmp_zip = $upload['basedir'] . '/aptce-core-' . time() . '.zip'; try { if ( class_exists( 'ZipArchive' ) ) { $zip = new ZipArchive(); if ( $zip->open( $tmp_zip, ZipArchive::CREATE ) !== TRUE ) { return [ 'success' => false, 'message' => __( 'Could not create archive', 'advanced-addons-theme-core-exporter' ) ]; } $this->aptce_add_folder_to_zip( $zip, $source, $source, $exclude ); $zip->close(); } else { return [ 'success' => false, 'message' => __( 'ZipArchive not available', 'advanced-addons-theme-core-exporter' ) ]; } if ( ! file_exists( $tmp_zip ) || filesize( $tmp_zip ) === 0 ) { return [ 'success' => false, 'message' => __( 'ZIP creation failed', 'advanced-addons-theme-core-exporter' ) ]; } return [ 'success' => true, 'file' => basename( $tmp_zip ), 'url' => $upload['baseurl'] . '/' . basename( $tmp_zip ), 'filename' => $zip_name ]; } catch ( Exception $e ) { return [ 'success' => false, 'message' => $e->getMessage() ]; } } /** * Helper: Create database dump */ protected function aptce_create_database_dump() { $upload = wp_upload_dir(); $db_file_path = $upload['basedir'] . '/aptce-database-' . time() . '.sql'; $filename = 'wordpress-database-' . date( 'Ymd-His' ) . '.sql'; $result = $this->aptce_generate_database_dump_file( $db_file_path ); if ( $result ) { return [ 'success' => true, 'file' => basename( $db_file_path ), 'url' => $upload['baseurl'] . '/' . basename( $db_file_path ), 'filename' => $filename ]; } else { return [ 'success' => false, 'message' => __( 'Database dump failed', 'advanced-addons-theme-core-exporter' ) ]; } } /** * AJAX handler to cleanup temporary files */ public function aptce_cleanup_file() { check_ajax_referer( 'aptce_export', 'nonce' ); if ( ! current_user_can( 'manage_options' ) ) { wp_send_json_error(); } $file = isset( $_POST['file'] ) ? sanitize_file_name( wp_unslash( $_POST['file'] ) ) : ''; if ( empty( $file ) ) { wp_send_json_error(); } $upload = wp_upload_dir(); $file_path = $upload['basedir'] . '/' . $file; if ( file_exists( $file_path ) && strpos( $file_path, 'aptce-' ) !== false ) { @unlink( $file_path ); wp_send_json_success(); } wp_send_json_error(); } /** * AJAX handler for bulk export */ public function aptce_ajax_bulk_export() { check_ajax_referer( 'aptce_export', 'nonce' ); if ( ! current_user_can( 'manage_options' ) ) { wp_send_json_error( [ 'message' => __( 'Insufficient permissions', 'advanced-addons-theme-core-exporter' ) ] ); } $plugins = isset( $_POST['plugins'] ) && is_array( $_POST['plugins'] ) ? array_map( 'sanitize_text_field', wp_unslash( $_POST['plugins'] ) ) : []; $themes = isset( $_POST['themes'] ) && is_array( $_POST['themes'] ) ? array_map( 'sanitize_text_field', wp_unslash( $_POST['themes'] ) ) : []; $export_core = isset( $_POST['export_core'] ) && '1' == $_POST['export_core']; $core_options = isset( $_POST['core_options'] ) && is_array( $_POST['core_options'] ) ? array_map( 'sanitize_text_field', wp_unslash( $_POST['core_options'] ) ) : []; // Create the bulk export zip $result = $this->aptce_create_bulk_export( $plugins, $themes, $export_core, $core_options ); if ( $result['success'] ) { wp_send_json_success( [ 'file' => $result['file'], 'url' => $result['url'], 'filename' => $result['filename'] ] ); } else { wp_send_json_error( [ 'message' => $result['message'] ] ); } } /** * Helper: Create bulk export zip */ protected function aptce_create_bulk_export( $plugins, $themes, $export_core, $core_options ) { $files_to_add = []; $temp_files = []; // Add selected plugins if ( ! empty( $plugins ) ) { foreach ( $plugins as $plugin_path ) { $plugin_dir = wp_normalize_path( WP_PLUGIN_DIR . '/' . dirname( $plugin_path ) ); if ( is_dir( $plugin_dir ) ) { $files_to_add[] = realpath( $plugin_dir ); } } } // Add selected themes if ( ! empty( $themes ) ) { foreach ( $themes as $slug ) { $theme_dir = get_theme_root() . '/' . $slug; if ( is_dir( $theme_dir ) ) { $files_to_add[] = realpath( $theme_dir ); } } } // Add core files if selected if ( $export_core && ! empty( $core_options ) ) { $upload = wp_upload_dir(); foreach ( $core_options as $option ) { switch ( $option ) { case 'full_100': $root_dir = wp_normalize_path( trailingslashit( ABSPATH ) ); if ( ! empty( $root_dir ) && is_dir( $root_dir ) ) { $files_to_add[] = [ 'path' => trailingslashit( $root_dir ), 'type' => 'core_100', ]; } break; case 'full': $root_path = trailingslashit( realpath( ABSPATH ) ); if ( $root_path ) { $files_to_add[] = $root_path . '|core'; } break; case 'uploads': $uploads_dir = isset( $upload['basedir'] ) ? $upload['basedir'] : ''; if ( ! empty( $uploads_dir ) && is_dir( $uploads_dir ) ) { $files_to_add[] = trailingslashit( $uploads_dir ); } break; case 'wpcontent': $wpcontent_dir = wp_normalize_path( WP_CONTENT_DIR ); if ( ! empty( $wpcontent_dir ) && is_dir( $wpcontent_dir ) ) { $files_to_add[] = [ 'path' => trailingslashit( $wpcontent_dir ), 'type' => 'wpcontent_no_uploads', 'exclude' => [ wp_normalize_path( $upload['basedir'] ) ], ]; } break; case 'admin': $admin_dir = wp_normalize_path( AATCE_ADMIN ); if ( ! empty( $admin_dir ) && is_dir( $admin_dir ) ) { $files_to_add[] = [ 'path' => trailingslashit( $admin_dir ), 'type' => 'admin', ]; } break; case 'includes': $includes_dir = wp_normalize_path( ABSPATH . 'wp-includes' ); if ( ! empty( $includes_dir ) && is_dir( $includes_dir ) ) { $files_to_add[] = [ 'path' => trailingslashit( $includes_dir ), 'type' => 'includes', ]; } break; case 'database': $db_file_path = $upload['basedir'] . '/aptce-database-' . time() . '.sql'; $database_file = $this->aptce_generate_database_dump_file( $db_file_path ); if ( $database_file ) { $temp_files[] = $database_file; } break; } } } if ( empty( $files_to_add ) && empty( $temp_files ) ) { return [ 'success' => false, 'message' => __( 'No items selected', 'advanced-addons-theme-core-exporter' ) ]; } $upload = wp_upload_dir(); $tmp_zip = $upload['basedir'] . '/aptce-export-' . time() . '.zip'; try { if ( ! class_exists( 'ZipArchive' ) ) { return [ 'success' => false, 'message' => __( 'ZipArchive not available', 'advanced-addons-theme-core-exporter' ) ]; } $zip = new ZipArchive(); if ( $zip->open( $tmp_zip, ZipArchive::CREATE ) !== TRUE ) { return [ 'success' => false, 'message' => __( 'Could not create archive', 'advanced-addons-theme-core-exporter' ) ]; } $added_files = []; // Add items to ZIP foreach ( $files_to_add as $item ) { if ( is_array( $item ) ) { $item_path = isset( $item['path'] ) ? $item['path'] : ''; $item_type = isset( $item['type'] ) ? $item['type'] : ''; $item_exclude = isset( $item['exclude'] ) ? (array) $item['exclude'] : []; if ( empty( $item_path ) ) continue; if ( 'core_100' === $item_type ) { $root = AATCE_ROOT_PATH; if ( $root ) { $root_normalized = wp_normalize_path( rtrim( $root, '/\\' ) ); $iterator = new RecursiveIteratorIterator( new RecursiveDirectoryIterator( $root, FilesystemIterator::SKIP_DOTS ), RecursiveIteratorIterator::LEAVES_ONLY ); foreach ( $iterator as $file ) { if ( $file->isDir() ) continue; $filePath = $file->getRealPath(); if ( ! $filePath ) continue; $filePath_normalized = wp_normalize_path( $filePath ); if ( strpos( $filePath_normalized, $root_normalized ) === 0 ) { $localPath = substr( $filePath_normalized, strlen( $root_normalized ) ); $localPath = ltrim( $localPath, '/' ); $localPath = str_replace( '\\', '/', $localPath ); if ( ! isset( $added_files[ $localPath ] ) ) { $zip->addFile( $filePath, $localPath ); $added_files[ $localPath ] = true; } } } } } elseif ( 'wpcontent_no_uploads' === $item_type ) { $base_path = realpath( $item_path ); if ( $base_path ) { $files = new RecursiveIteratorIterator( new RecursiveDirectoryIterator( $base_path, FilesystemIterator::SKIP_DOTS ), RecursiveIteratorIterator::LEAVES_ONLY ); foreach ( $files as $file ) { if ( $file->isDir() ) continue; $filePath = $file->getRealPath(); $skip = false; foreach ( $item_exclude as $exclude_path ) { if ( realpath( $exclude_path ) && strpos( $filePath, realpath( $exclude_path ) ) === 0 ) { $skip = true; break; } } if ( $skip ) continue; $base_path_normalized = wp_normalize_path( rtrim( $base_path, '/\\' ) ); $filePath_normalized = wp_normalize_path( $filePath ); if ( strpos( $filePath_normalized, $base_path_normalized ) === 0 ) { $relative = substr( $filePath_normalized, strlen( $base_path_normalized ) ); $relative = ltrim( $relative, '/' ); $localPath = 'wp-content/' . str_replace( '\\', '/', $relative ); if ( ! isset( $added_files[ $localPath ] ) ) { $zip->addFile( $filePath, $localPath ); $added_files[ $localPath ] = true; } } } } } elseif ( 'admin' === $item_type || 'includes' === $item_type ) { $dir_path = realpath( $item_path ); if ( $dir_path ) { $base = basename( $dir_path ); $files = new RecursiveIteratorIterator( new RecursiveDirectoryIterator( $dir_path, FilesystemIterator::SKIP_DOTS ), RecursiveIteratorIterator::LEAVES_ONLY ); foreach ( $files as $file ) { if ( $file->isDir() ) continue; $filePath = $file->getRealPath(); if ( ! $filePath ) continue; $dir_path_normalized = wp_normalize_path( rtrim( $dir_path, '/\\' ) ); $filePath_normalized = wp_normalize_path( $filePath ); if ( strpos( $filePath_normalized, $dir_path_normalized ) === 0 ) { $relative = substr( $filePath_normalized, strlen( $dir_path_normalized ) ); $relative = ltrim( $relative, '/' ); $localPath = $base . '/' . str_replace( '\\', '/', $relative ); if ( ! isset( $added_files[ $localPath ] ) ) { $zip->addFile( $filePath, $localPath ); $added_files[ $localPath ] = true; } } } } } continue; } if ( ! is_string( $item ) ) continue; if ( false !== strpos( $item, '|core' ) ) { $root = AATCE_ROOT_PATH; if ( $root ) { $iterator = new RecursiveIteratorIterator( new RecursiveDirectoryIterator( $root, FilesystemIterator::SKIP_DOTS ), RecursiveIteratorIterator::LEAVES_ONLY ); foreach ( $iterator as $file ) { if ( $file->isDir() ) continue; $filePath = $file->getRealPath(); $uploads = wp_upload_dir(); $uploads_dir = wp_normalize_path( $uploads['basedir'] ); if ( 0 === strpos( wp_normalize_path( $filePath ), $uploads_dir ) ) continue; if ( basename( $filePath ) === 'wp-config.php' ) continue; $root_normalized = wp_normalize_path( rtrim( $root, '/\\' ) ); $filePath_normalized = wp_normalize_path( $filePath ); if ( strpos( $filePath_normalized, $root_normalized ) === 0 ) { $localPath = substr( $filePath_normalized, strlen( $root_normalized ) ); $localPath = ltrim( $localPath, '/' ); $localPath = str_replace( '\\', '/', $localPath ); if ( ! isset( $added_files[ $localPath ] ) ) { $zip->addFile( $filePath, $localPath ); $added_files[ $localPath ] = true; } } } } continue; } if ( is_dir( $item ) ) { $item_realpath = realpath( $item ); if ( $item_realpath ) { $base = basename( $item_realpath ); $files = new RecursiveIteratorIterator( new RecursiveDirectoryIterator( $item_realpath, FilesystemIterator::SKIP_DOTS ), RecursiveIteratorIterator::LEAVES_ONLY ); foreach ( $files as $file ) { if ( $file->isDir() ) continue; $filePath = $file->getRealPath(); if ( ! $filePath ) continue; $item_realpath_normalized = wp_normalize_path( rtrim( $item_realpath, '/\\' ) ); $filePath_normalized = wp_normalize_path( $filePath ); if ( strpos( $filePath_normalized, $item_realpath_normalized ) === 0 ) { $relative = substr( $filePath_normalized, strlen( $item_realpath_normalized ) ); $relative = ltrim( $relative, '/' ); $localPath = $base . '/' . str_replace( '\\', '/', $relative ); if ( ! isset( $added_files[ $localPath ] ) ) { $zip->addFile( $filePath, $localPath ); $added_files[ $localPath ] = true; } } } } } } // Add temp files (database) foreach ( $temp_files as $tf ) { if ( is_file( $tf ) ) { if ( false !== strpos( $tf, 'aptce-database' ) ) { $zip->addFile( $tf, 'wordpress-database-' . date( 'Ymd-His' ) . '.sql' ); } } } $zip->close(); // Clean up temp files foreach ( $temp_files as $f ) { @unlink( $f ); } if ( ! file_exists( $tmp_zip ) || filesize( $tmp_zip ) === 0 ) { return [ 'success' => false, 'message' => __( 'ZIP creation failed', 'advanced-addons-theme-core-exporter' ) ]; } return [ 'success' => true, 'file' => basename( $tmp_zip ), 'url' => $upload['baseurl'] . '/' . basename( $tmp_zip ), 'filename' => basename( $tmp_zip ) ]; } catch ( Exception $e ) { return [ 'success' => false, 'message' => $e->getMessage() ]; } } } new APTCE_Download_Exporter();