slug = $slug; add_action('admin_menu', array($this, 'add_import_export_buttons'), 20); add_action('admin_post_kadence_export_posts-' . $slug, array($this, 'handle_export')); add_action('admin_post_kadence_import_posts-' . $slug, array($this, 'handle_import')); add_action('admin_notices', array($this, 'display_import_notices')); add_action('admin_enqueue_scripts', array($this, 'enqueue_scripts')); add_action('admin_footer', array($this, 'add_import_modal_styles')); add_filter('bulk_actions-edit-' . $slug, array($this, 'register_bulk_export_action')); add_filter('handle_bulk_actions-edit-' . $slug, array($this, 'handle_bulk_export'), 10, 3); } } public function handle_bulk_export($redirect_to, $action, $post_ids) { if ($action !== 'export_selected') { return $redirect_to; } if (!current_user_can('manage_options')) { wp_die(__('You do not have sufficient permissions to export content.', 'kadence-blocks')); } $this->handle_export($post_ids, false); } public function enqueue_scripts($hook) { if ('edit.php' === $hook && $this->slug === get_current_screen()->post_type) { wp_register_script( 'kadence-cpt-import-export', '', // Empty source as we're using inline script array('jquery'), '1.0', true ); wp_enqueue_script('kadence-cpt-import-export'); wp_add_inline_script('kadence-cpt-import-export', ' jQuery(document).ready(function($) { // Move buttons to after views var $buttons = $(".kadence-import-export-buttons"); $buttons.insertAfter(".subsubsub"); // Handle import button click $("#kadence-reveal-import").on("click", function(e) { e.preventDefault(); $(".kadence-import-form").slideToggle(); }); }); '); } } /** * Register bulk action */ public function register_bulk_export_action($bulk_actions) { $bulk_actions['export_selected'] = __('Export', 'kadence-blocks'); return $bulk_actions; } /** * Add styles for import modal */ public function add_import_modal_styles() { if (get_current_screen()->post_type !== $this->slug) { return; } ?> slug || empty($_GET['import_status'])) { return; } if ($_GET['import_status'] === 'success') { ?>

slug === $typenow && current_user_can('manage_options') ) { add_action('admin_notices', array($this, 'render_import_export_buttons')); } } /** * Render the import/export buttons */ public function render_import_export_buttons() { ?>
redirect_with_error( __('You do not have sufficient permissions to export content.', 'kadence-blocks') ); } if( $check_referrer ) { check_admin_referer('kadence_export_posts_nonce', 'kadence_export_nonce'); } $posts_args = array( 'post_type' => $this->slug, 'posts_per_page' => -1, 'post_status' => 'any', ); if( ! empty( $post_ids ) ) { $posts_args['post__in'] = $post_ids; } $posts = get_posts($posts_args); $export_data = array( 'post_type' => $this->slug, 'posts' => array(), 'related_posts' => array(), 'relationship_map' => array() ); $this->processed_posts = array(); $this->relationship_map = array(); foreach ($posts as $post) { $post_data = $this->prepare_post_for_export($post); $export_data['posts'][] = $post_data; $this->processed_posts[] = $post->ID; $this->get_related_posts_recursive($post->post_content, $export_data['related_posts'], $post->ID); } $export_data['related_posts'] = array_values(array_unique($export_data['related_posts'], SORT_REGULAR)); $export_data['relationship_map'] = $this->relationship_map; $temp_dir = get_temp_dir(); $filename = $this->slug . '_export_' . date('Y-m-d_H-i-s'); $json_file = $temp_dir . $filename . '.json'; $zip_file = $temp_dir . $filename . '.zip'; file_put_contents($json_file, wp_json_encode($export_data)); $zip = new ZipArchive(); $zip->open($zip_file, ZipArchive::CREATE | ZipArchive::OVERWRITE); $zip->addFile($json_file, 'export.json'); $zip->close(); header('Content-Type: application/zip'); header('Content-Disposition: attachment; filename=' . basename($zip_file)); header('Content-Length: ' . filesize($zip_file)); readfile($zip_file); unlink($json_file); unlink($zip_file); } /** * Recursively get related posts */ private function get_related_posts_recursive($content, &$related_posts, $parent_id = null) { $blocks = parse_blocks($content); foreach ($blocks as $block) { if( in_array( $block['blockName'], $this->kadence_cpt_blocks ) && !empty( $block['attrs']['id'] ) ) { $nested_id = $block['attrs']['id']; if ($parent_id !== null) { if (!isset($this->relationship_map[$parent_id])) { $this->relationship_map[$parent_id] = []; } $this->relationship_map[$parent_id][] = $nested_id; } if ( ! in_array( $nested_id, $this->processed_posts ) ) { $nested_post = get_post( $nested_id ); if ( $nested_post ) { $related_posts[] = $this->prepare_post_for_export( $nested_post ); $this->processed_posts[] = $nested_id; $this->get_related_posts_recursive($nested_post->post_content, $related_posts, $nested_id); } } } if (!empty($block['innerBlocks'])) { foreach ($block['innerBlocks'] as $inner_block) { $this->get_related_posts_recursive(serialize_blocks(array($inner_block)), $related_posts, $parent_id); } } } } public function handle_import() { if (!current_user_can('manage_options')) { $this->redirect_with_error( __('You do not have sufficient permissions to import content.', 'kadence-blocks' ) ); return; } check_admin_referer('kadence_import_posts_nonce', 'kadence_import_nonce'); if (!isset($_FILES['import_file'])) { $this->redirect_with_error( __( 'Please upload a file to import.', 'kadence-blocks' ) ); return; } $file = $_FILES['import_file']; if ($file['error'] !== UPLOAD_ERR_OK) { $this->redirect_with_error( __('File upload failed.', 'kadence-blocks' ) ); return; } if ($file['type'] !== 'application/zip' && $file['type'] !== 'application/x-zip-compressed') { $this->redirect_with_error( __('Invalid file type. Please upload a ZIP file.', 'kadence-blocks' ) ); return; } $temp_dir = get_temp_dir(); $zip = new ZipArchive(); if ($zip->open($file['tmp_name']) === TRUE) { if ($zip->numFiles > 5) { $this->redirect_with_error( __('Invalid data in import file.', 'kadence-blocks' ) ); return; } $zip->extractTo($temp_dir); $zip->close(); if (!file_exists($temp_dir . 'export.json')) { $this->redirect_with_error( __( 'Invalid import file structure. Missing export.json', 'kadence-blocks' ) ); return; } $json_content = file_get_contents($temp_dir . 'export.json'); $import_data = json_decode($json_content, true); if (json_last_error() !== JSON_ERROR_NONE) { $this->redirect_with_error( __('Invalid JSON data in import file.', 'kadence-blocks' ) ); return; } try { $id_map = array(); if (!empty($import_data['related_posts'])) { foreach ($import_data['related_posts'] as $related_post) { $new_id = $this->import_single_post($related_post); if ($new_id) { $id_map[$related_post['ID']] = $new_id; } } } foreach (array_merge($import_data['related_posts'], $import_data['posts']) as $post_data) { $post_content = $post_data['post_content']; $updated_content = $this->update_block_ids($post_content, $id_map); $new_post_id = $id_map[$post_data['ID']] ?? null; if ($new_post_id) { wp_update_post(array( 'ID' => $new_post_id, 'post_content' => wp_slash($updated_content) )); } } foreach ($import_data['posts'] as $post_data) { $this->import_single_post($post_data, $id_map); } unlink($temp_dir . 'export.json'); wp_redirect(add_query_arg( array( 'post_type' => $this->slug, 'import_status' => 'success' ), admin_url('edit.php') )); exit; } catch (Exception $e) { $this->redirect_with_error('Import failed: ' . $e->getMessage()); return; } } else { $this->redirect_with_error('Failed to process the import file.'); return; } } private function prepare_post_for_export($post) { $post_data = array( 'ID' => $post->ID, 'post_content' => $post->post_content, 'post_title' => $post->post_title, 'post_excerpt' => $post->post_excerpt, 'post_status' => $post->post_status, 'post_type' => $post->post_type, 'meta' => array() ); $meta = get_post_custom($post->ID); foreach ($meta as $key => $values) { if ( ! in_array( $key, $this->excluded_meta_keys ) ) { $post_data['meta'][$key] = array_map('maybe_unserialize', $values); } } return $post_data; } private function import_single_post($post_data, $id_map = array()) { $temp_content = $post_data['post_content']; $post_data['post_content'] = ''; unset($post_data['ID']); $new_post_id = wp_insert_post($post_data, true); if (!is_wp_error($new_post_id)) { if (!empty($post_data['meta'])) { foreach ($post_data['meta'] as $meta_key => $meta_values) { foreach ($meta_values as $meta_value) { add_post_meta($new_post_id, $meta_key, $meta_value); } } } $updated_content = $this->update_block_ids($temp_content, $id_map); wp_update_post(array( 'ID' => $new_post_id, 'post_content' => wp_slash($updated_content) )); return $new_post_id; } return false; } /** * Update block ID in content with new ID */ private function update_block_ids($content, $id_map) { $blocks = parse_blocks($content); foreach ($blocks as &$block) { if ( in_array( $block['blockName'], $this->kadence_cpt_blocks ) && !empty($block['attrs']['id']) && isset($id_map[$block['attrs']['id']])) { $block['attrs']['id'] = $id_map[$block['attrs']['id']]; } if (!empty($block['innerBlocks'])) { $inner_content = serialize_blocks($block['innerBlocks']); $updated_inner_content = $this->update_block_ids($inner_content, $id_map); $block['innerBlocks'] = parse_blocks($updated_inner_content); } } return serialize_blocks($blocks); } private function redirect_with_error($message) { wp_redirect(add_query_arg( array( 'post_type' => $this->slug, 'import_status' => 'error', 'error_message' => urlencode($message) ), admin_url('edit.php') ), 302 ); exit; } }