__( 'Security check failed.', 'forumax' ) ) ); } // Check user capabilities. if ( ! current_user_can( 'manage_options' ) ) { wp_send_json_error( array( 'message' => __( 'You do not have permission to import data.', 'forumax' ) ) ); } // Check if file exists. $xml_file = FORUMAX_PATH . 'sample-data/forumax-sample-data.xml'; if ( ! file_exists( $xml_file ) ) { wp_send_json_error( array( 'message' => __( 'Demo data file not found.', 'forumax' ) ) ); } // Load WordPress Importer if needed. if ( ! class_exists( 'WP_Import' ) ) { $importer_file = ABSPATH . 'wp-admin/includes/class-wp-importer.php'; if ( file_exists( $importer_file ) ) { require_once $importer_file; } // Try loading the WordPress Importer plugin. $plugin_importer = WP_PLUGIN_DIR . '/wordpress-importer/wordpress-importer.php'; if ( file_exists( $plugin_importer ) ) { require_once $plugin_importer; } } // If WP_Import still not available, use custom parser. if ( ! class_exists( 'WP_Import' ) ) { $result = forumax_custom_import_demo_data( $xml_file ); if ( is_wp_error( $result ) ) { wp_send_json_error( array( 'message' => $result->get_error_message() ) ); } forumax_recalculate_counts_after_import(); wp_send_json_success( array( 'message' => $result ) ); } // Use WP_Import if available. $importer = new WP_Import(); $importer->fetch_attachments = false; ob_start(); $importer->import( $xml_file ); $output = ob_get_clean(); forumax_recalculate_counts_after_import(); wp_send_json_success( array( 'message' => __( 'Demo data imported successfully! Refreshing page...', 'forumax' ), ) ); } add_action( 'wp_ajax_forumax_import_demo_data', 'forumax_import_demo_data' ); /** * Custom XML parser for importing demo data when WP_Import is not available. * * @param string $xml_file Path to XML file. * @return string|WP_Error Success message or error. */ /** * Custom XML parser for importing demo data when WP_Import is not available. * * @param string $xml_file Path to XML file. * @return string|WP_Error Success message or error. */ function forumax_custom_import_demo_data( $xml_file ) { // Load XML. libxml_use_internal_errors( true ); $xml = simplexml_load_file( $xml_file ); if ( false === $xml ) { $errors = libxml_get_errors(); libxml_clear_errors(); return new WP_Error( 'xml_parse_error', __( 'Failed to parse XML file.', 'forumax' ) ); } // Register namespaces. $namespaces = $xml->getNamespaces( true ); $wp_ns = isset( $namespaces['wp'] ) ? $namespaces['wp'] : 'http://wordpress.org/export/1.2/'; $dc_ns = isset( $namespaces['dc'] ) ? $namespaces['dc'] : 'http://purl.org/dc/elements/1.1/'; $content_ns = isset( $namespaces['content'] ) ? $namespaces['content'] : 'http://purl.org/rss/1.0/modules/content/'; $imported = array( 'forums' => 0, 'topics' => 0, 'replies' => 0, ); $post_id_map = array(); $author_map = array(); $current_user_id = get_current_user_id(); // Import/Map Authors. if ( isset( $xml->channel->children( $wp_ns )->author ) ) { foreach ( $xml->channel->children( $wp_ns )->author as $author ) { $login = (string) $author->author_login; $email = (string) $author->author_email; $display_name = (string) $author->author_display_name; // Check if user exists by login. $user = get_user_by( 'login', $login ); if ( ! $user ) { // Check if user exists by email. $user = get_user_by( 'email', $email ); } if ( ! $user ) { // Create new user. $user_id = wp_create_user( $login, wp_generate_password(), $email ); if ( ! is_wp_error( $user_id ) ) { wp_update_user( array( 'ID' => $user_id, 'display_name' => $display_name, 'role' => 'subscriber', // Default role. ) ); $author_map[ $login ] = $user_id; } else { // Fallback to current user if creation fails. $author_map[ $login ] = $current_user_id; } } else { $author_map[ $login ] = $user->ID; } } } // Process items in order (forums first, then topics, then replies). $items_by_type = array( 'forum' => array(), 'topic' => array(), 'reply' => array(), ); foreach ( $xml->channel->item as $item ) { $wp = $item->children( $wp_ns ); $post_type = (string) $wp->post_type; if ( isset( $items_by_type[ $post_type ] ) ) { $items_by_type[ $post_type ][] = $item; } else { // Handle other post types (like attachments) if needed, or put them in a generic bucket. // For now, we mainly care about forums, topics, and replies, but attachments are often 'attachment' post_type. if ( 'attachment' === $post_type ) { $items_by_type['attachment'][] = $item; } } } // Helper to run import loop. $run_import = function ( $items ) use ( $wp_ns, $dc_ns, $content_ns, &$post_id_map, $current_user_id, $author_map ) { $count = 0; if ( ! empty( $items ) ) { foreach ( $items as $item ) { $result = forumax_import_single_item( $item, $wp_ns, $dc_ns, $content_ns, $post_id_map, $current_user_id, $author_map ); if ( ! is_wp_error( $result ) && $result > 0 ) { $count++; } } } return $count; }; // Import order: Attachments -> Forums -> Topics -> Replies. if ( isset( $items_by_type['attachment'] ) ) { $run_import( $items_by_type['attachment'] ); } $imported['forums'] = $run_import( $items_by_type['forum'] ); $imported['topics'] = $run_import( $items_by_type['topic'] ); $imported['replies'] = $run_import( $items_by_type['reply'] ); // Flush rewrite rules. flush_rewrite_rules(); return sprintf( /* translators: %1$d: forums count, %2$d: topics count, %3$d: replies count */ __( 'Successfully imported %1$d forums, %2$d topics, and %3$d replies. Refreshing page...', 'forumax' ), $imported['forums'], $imported['topics'], $imported['replies'] ); } /** * Import a single item from XML. * * @param SimpleXMLElement $item The item to import. * @param string $wp_ns WordPress namespace. * @param string $dc_ns Dublin Core namespace. * @param string $content_ns Content namespace. * @param array $post_id_map Reference to post ID mapping array. * @param int $current_user_id Current user ID. * @param array $author_map Map of XML login to WP user ID. * @return int|WP_Error New post ID or error. */ function forumax_import_single_item( $item, $wp_ns, $dc_ns, $content_ns, &$post_id_map, $current_user_id, $author_map = array() ) { $wp = $item->children( $wp_ns ); $dc = $item->children( $dc_ns ); $content = $item->children( $content_ns ); $post_type = (string) $wp->post_type; $old_post_id = (int) $wp->post_id; $old_parent = (int) $wp->post_parent; $title = (string) $item->title; $post_name = (string) $wp->post_name; $post_content = (string) $content->encoded; $post_status = (string) $wp->status; $menu_order = (int) $wp->menu_order; $creator = (string) $dc->creator; $attachment_url = (string) $wp->attachment_url; // Determine author. $post_author = $current_user_id; if ( ! empty( $creator ) && isset( $author_map[ $creator ] ) ) { $post_author = $author_map[ $creator ]; } // Map old parent ID to new ID. $new_parent = 0; if ( $old_parent > 0 && isset( $post_id_map[ $old_parent ] ) ) { $new_parent = $post_id_map[ $old_parent ]; } // Check if post already exists. $existing = get_page_by_path( $post_name, OBJECT, $post_type ); if ( $existing && 'attachment' !== $post_type ) { $post_id_map[ $old_post_id ] = $existing->ID; return $existing->ID; } // Prepare post data. $post_data = array( 'post_title' => $title, 'post_name' => $post_name, 'post_content' => $post_content, 'post_status' => $post_status, 'post_type' => $post_type, 'post_parent' => $new_parent, 'menu_order' => $menu_order, 'post_author' => $post_author, ); // Handle attachment-specific logic (sideloading). if ( 'attachment' === $post_type && ! empty( $attachment_url ) ) { // Simple check to avoid re-uploading if exists is tricky without hash, // but let's just try to create it. // Note: For a robust importer, we'd use media_sideload_image or verify existence. // However, since this is a simple "custom" importer when WP_Import fails, // we might just create the post entry. But actually, attachments need files. // If we can't download the file, we can't really make a valid attachment. // For this demo, let's assume we just create the post object for reference, // or skipping real file download to keep it simple unless requested. // Given the constraints, let's just insert the post object so ID mapping works. // Real file sideloading might timeout or require filesystem access. } // Insert the post. $new_post_id = wp_insert_post( $post_data, true ); if ( is_wp_error( $new_post_id ) ) { return $new_post_id; } // Map old ID to new ID. $post_id_map[ $old_post_id ] = $new_post_id; // Import post meta. foreach ( $wp->postmeta as $meta ) { $meta_key = (string) $meta->meta_key; $meta_value = (string) $meta->meta_value; // Update parent IDs in meta. if ( in_array( $meta_key, array( '_bbp_forum_id', '_bbp_topic_id', '_bbp_reply_to', '_thumbnail_id' ), true ) ) { $old_meta_id = (int) $meta_value; if ( isset( $post_id_map[ $old_meta_id ] ) ) { $meta_value = $post_id_map[ $old_meta_id ]; } } update_post_meta( $new_post_id, $meta_key, $meta_value ); } // Handle topic tags. foreach ( $item->category as $category ) { $domain = (string) $category['domain']; if ( 'topic-tag' === $domain ) { $tag_name = (string) $category; $tag_slug = (string) $category['nicename']; wp_set_object_terms( $new_post_id, $tag_name, 'topic-tag', true ); } } // Handle sticky. if ( 'topic' === $post_type && '1' === (string) $wp->is_sticky ) { update_post_meta( $new_post_id, '_bbp_topic_sticky', 'stick' ); } // Update reply to mapping for threaded replies if missed in standard meta loop (usually captured above). // The meta loop above handles _bbp_reply_to if it's in postmeta. return $new_post_id; } /** * Recalculate counts after import. */ function forumax_recalculate_counts_after_import() { if ( ! function_exists( 'bbp_admin_repair_forum_topic_count' ) ) { if ( defined( 'BBP_PLUGIN_DIR' ) ) { require_once BBP_PLUGIN_DIR . '/includes/admin/tools/repair.php'; } elseif ( file_exists( FORUMAX_DIR . 'lib/bbpress/includes/admin/tools/repair.php' ) ) { require_once FORUMAX_DIR . 'lib/bbpress/includes/admin/tools/repair.php'; } } if ( function_exists( 'bbp_admin_repair_forum_topic_count' ) ) { bbp_admin_repair_forum_topic_count(); bbp_admin_repair_forum_reply_count(); bbp_admin_repair_topic_reply_count(); bbp_admin_repair_freshness(); // Also repair forum meta (parent/child relationships) bbp_admin_repair_forum_meta(); } }