No field groups found.
[post, config] ] */ private function get_all_groups() { $posts = get_posts( array( 'post_type' => 'metaforge_group', 'posts_per_page' => -1, 'post_status' => 'publish', 'orderby' => 'menu_order', 'order' => 'ASC', ) ); $groups = array(); foreach ( $posts as $post ) { $config = get_post_meta( $post->ID, '_metaforge_group_config', true ); if ( is_array( $config ) ) { $groups[ $post->ID ] = array( 'post' => $post, 'config' => $config, ); } } return $groups; } private function get_all_post_types() { return get_option( 'metaforge_post_types', array() ); } private function get_all_taxonomies() { return get_option( 'metaforge_taxonomies', array() ); } private function get_all_options_pages() { return get_option( 'metaforge_options_pages', array() ); } // ── Export ─────────────────────────────────────────────────────────────── public function process_export() { if ( ! isset( $_GET['metaforge_action'] ) || $_GET['metaforge_action'] !== 'export' ) { return; } if ( ! isset( $_GET['nonce'] ) || ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_GET['nonce'] ) ), 'metaforge_export_nonce' ) ) { wp_die( 'Invalid nonce' ); } if ( ! current_user_can( 'manage_metaforge' ) ) { wp_die( 'Insufficient permissions.' ); } // ── Multi-select export via parameters ── $ids_raw = isset( $_GET['metaforge_ids'] ) ? sanitize_text_field( wp_unslash( $_GET['metaforge_ids'] ) ) : ''; $ids = array_filter( array_map( 'intval', explode( ',', $ids_raw ) ) ); $pts_raw = isset( $_GET['metaforge_pts'] ) ? sanitize_text_field( wp_unslash( $_GET['metaforge_pts'] ) ) : ''; $pt_slugs = array_filter( array_map( 'sanitize_key', explode( ',', $pts_raw ) ) ); $taxs_raw = isset( $_GET['metaforge_taxs'] ) ? sanitize_text_field( wp_unslash( $_GET['metaforge_taxs'] ) ) : ''; $tax_slugs = array_filter( array_map( 'sanitize_key', explode( ',', $taxs_raw ) ) ); $opts_raw = isset( $_GET['metaforge_opts'] ) ? sanitize_text_field( wp_unslash( $_GET['metaforge_opts'] ) ) : ''; $opt_slugs = array_filter( array_map( 'sanitize_key', explode( ',', $opts_raw ) ) ); if ( ! empty( $ids ) || ! empty( $pt_slugs ) || ! empty( $tax_slugs ) || ! empty( $opt_slugs ) ) { $export_data = array( 'metaforge_version' => METAFORGE_VERSION, 'exported_at' => gmdate( 'Y-m-d\TH:i:s\Z' ), 'export_type' => 'selective', ); if ( ! empty( $ids ) ) { $groups = array(); foreach ( $ids as $pid ) { $post = get_post( $pid ); if ( ! $post || $post->post_type !== 'metaforge_group' ) { continue; } $c = get_post_meta( $pid, '_metaforge_group_config', true ); if ( is_array( $c ) ) { $groups[] = $c; } } $export_data['metaforge_field_groups'] = $groups; } if ( ! empty( $pt_slugs ) ) { $all_pts = get_option( 'metaforge_post_types', array() ); $pts = array(); foreach ( $all_pts as $pt ) { if ( in_array( $pt['slug'] ?? '', $pt_slugs ) ) { $pts[] = $pt; } } $export_data['metaforge_post_types'] = $pts; } if ( ! empty( $tax_slugs ) ) { $all_taxs = get_option( 'metaforge_taxonomies', array() ); $taxs = array(); foreach ( $all_taxs as $tax ) { if ( in_array( $tax['slug'] ?? '', $tax_slugs ) ) { $taxs[] = $tax; } } $export_data['metaforge_taxonomies'] = $taxs; } if ( ! empty( $opt_slugs ) ) { $all_opts = get_option( 'metaforge_options_pages', array() ); $opts = array(); foreach ( $all_opts as $opt ) { if ( in_array( $opt['slug'] ?? '', $opt_slugs ) ) { $opts[] = $opt; } } $export_data['metaforge_options_pages'] = $opts; } MetaForge_Logger::log( 'data_selective_exported', array( 'groups' => count( $export_data['metaforge_field_groups'] ?? array() ), 'post_types' => count( $export_data['metaforge_post_types'] ?? array() ), 'taxonomies' => count( $export_data['metaforge_taxonomies'] ?? array() ), 'options' => count( $export_data['metaforge_options_pages'] ?? array() ), ) ); $this->send_download( $export_data, 'metaforge-selective-export-' . gmdate( 'Y-m-d' ) . '.json' ); return; } // ── Full export (all data) ── $groups = array(); foreach ( get_posts( array( 'post_type' => 'metaforge_group', 'posts_per_page' => -1, 'post_status' => 'publish', 'orderby' => 'menu_order', 'order' => 'ASC', ) ) as $post ) { $c = get_post_meta( $post->ID, '_metaforge_group_config', true ); if ( is_array( $c ) ) { $groups[] = $c; } } $this->send_download( array( 'metaforge_version' => METAFORGE_VERSION, 'exported_at' => gmdate( 'Y-m-d\TH:i:s\Z' ), 'export_type' => 'full', 'metaforge_field_groups' => $groups, 'metaforge_post_types' => get_option( 'metaforge_post_types', array() ), 'metaforge_taxonomies' => get_option( 'metaforge_taxonomies', array() ), 'metaforge_options_pages' => get_option( 'metaforge_options_pages', array() ), ), 'metaforge-full-export-' . gmdate( 'Y-m-d' ) . '.json' ); } private function send_download( $data, $filename ) { $json = wp_json_encode( $data, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE ); nocache_headers(); header( 'Content-Type: application/json; charset=' . get_option( 'blog_charset' ) ); header( 'Content-Disposition: attachment; filename="' . sanitize_file_name( $filename ) . '"' ); header( 'Content-Length: ' . strlen( $json ) ); echo wp_json_encode( $data, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE ); exit; } // ── Import ─────────────────────────────────────────────────────────────── public function process_import() { if ( ! isset( $_POST['metaforge_action'] ) || $_POST['metaforge_action'] !== 'import' ) { return; } if ( ! isset( $_POST['metaforge_import_nonce_field'] ) || ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['metaforge_import_nonce_field'] ) ), 'metaforge_import_nonce' ) ) { wp_die( 'Invalid nonce' ); } if ( ! current_user_can( 'manage_metaforge' ) ) { wp_die( 'Insufficient permissions.' ); } $json = ''; if ( ! empty( $_FILES['metaforge_import_file']['tmp_name'] ) ) { // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- File structure validated via finfo mime check below. $f = $_FILES['metaforge_import_file']; if ( $f['error'] !== UPLOAD_ERR_OK ) { wp_safe_redirect( admin_url( 'admin.php?page=metaforge_tools&metaforge_import=upload_error' ) ); exit; } if ( $f['size'] > 2097152 ) { wp_safe_redirect( admin_url( 'admin.php?page=metaforge_tools&metaforge_import=too_large' ) ); exit; } if ( strtolower( pathinfo( $f['name'], PATHINFO_EXTENSION ) ) !== 'json' ) { wp_safe_redirect( admin_url( 'admin.php?page=metaforge_tools&metaforge_import=bad_file_type' ) ); exit; } // S-4: Verify the actual MIME type server-side (extension alone is trivially spoofed). $detected_mime = ''; if ( function_exists( 'finfo_file' ) ) { $finfo = finfo_open( FILEINFO_MIME_TYPE ); $detected_mime = finfo_file( $finfo, $f['tmp_name'] ); finfo_close( $finfo ); } elseif ( function_exists( 'mime_content_type' ) ) { $detected_mime = mime_content_type( $f['tmp_name'] ); } $allowed_mimes = array( 'application/json', 'text/plain', 'text/json', 'application/octet-stream' ); if ( $detected_mime && ! in_array( $detected_mime, $allowed_mimes, true ) ) { wp_safe_redirect( admin_url( 'admin.php?page=metaforge_tools&metaforge_import=bad_file_type' ) ); exit; } global $wp_filesystem; if ( empty( $wp_filesystem ) ) { require_once ABSPATH . 'wp-admin/includes/file.php'; WP_Filesystem(); } $json = $wp_filesystem ? $wp_filesystem->get_contents( $f['tmp_name'] ) : false; } else { $json = sanitize_textarea_field( wp_unslash( $_POST['metaforge_import_json'] ?? '' ) ); if ( strlen( $json ) > 500000 ) { wp_safe_redirect( admin_url( 'admin.php?page=metaforge_tools&metaforge_import=too_large' ) ); exit; } } if ( empty( trim( $json ) ) ) { wp_safe_redirect( admin_url( 'admin.php?page=metaforge_tools&metaforge_import=empty' ) ); exit; } $data = json_decode( $json, true, 64 ); if ( json_last_error() !== JSON_ERROR_NONE || ! is_array( $data ) ) { wp_safe_redirect( admin_url( 'admin.php?page=metaforge_tools&metaforge_import=invalid_json' ) ); exit; } // Map legacy mfe_ keys to metaforge_ keys $legacy_key_map = array( 'mfe_field_groups' => 'metaforge_field_groups', 'mfe_post_types' => 'metaforge_post_types', 'mfe_taxonomies' => 'metaforge_taxonomies', 'mfe_options_pages' => 'metaforge_options_pages', ); foreach ( $legacy_key_map as $old_key => $new_key ) { if ( isset( $data[ $old_key ] ) && ! isset( $data[ $new_key ] ) ) { $data[ $new_key ] = $data[ $old_key ]; unset( $data[ $old_key ] ); } } // Check if data is an ACF export format and convert to MFE schema if ( ! isset( $data['metaforge_field_groups'] ) && ( isset( $data['key'] ) || ( isset( $data[0] ) && is_array( $data[0] ) && isset( $data[0]['key'] ) ) ) ) { $data = self::convert_acf_json_to_mfe( $data ); } // Direct list of groups: [ { "group_name": "..." }, ... ] if ( ! isset( $data['metaforge_field_groups'] ) && isset( $data[0] ) && is_array( $data[0] ) && ( isset( $data[0]['group_name'] ) || isset( $data[0]['fields'] ) ) ) { $data = array( 'metaforge_field_groups' => $data ); } // Single group object: { "group_name": "...", "fields": [...] } if ( ! isset( $data['metaforge_field_groups'] ) && isset( $data['group_name'] ) && isset( $data['fields'] ) ) { $data = array( 'metaforge_field_groups' => array( $data ) ); } $data = array_intersect_key( $data, array_flip( array( 'metaforge_field_groups', 'metaforge_post_types', 'metaforge_taxonomies', 'metaforge_options_pages' ) ) ); if ( empty( $data ) ) { wp_safe_redirect( admin_url( 'admin.php?page=metaforge_tools&metaforge_import=no_valid_data' ) ); exit; } $data = map_deep( $data, 'sanitize_textarea_field' ); $strategy = sanitize_text_field( wp_unslash( $_POST['metaforge_import_strategy'] ?? 'merge' ) ); $converted_repeaters = 0; $is_pro = function_exists( 'metaforge_is_pro_active' ) ? metaforge_is_pro_active() : ( defined( 'METAFORGE_PRO_VERSION' ) || apply_filters( 'metaforge_is_pro_active', false ) ); if ( ! $is_pro && isset( $data['metaforge_field_groups'] ) && is_array( $data['metaforge_field_groups'] ) ) { foreach ( $data['metaforge_field_groups'] as &$g ) { if ( ! empty( $g['fields'] ) && is_array( $g['fields'] ) ) { $converted_repeaters += self::convert_repeaters_to_groups( $g['fields'] ); } } unset( $g ); } if ( isset( $data['metaforge_field_groups'] ) && is_array( $data['metaforge_field_groups'] ) ) { if ( $strategy === 'replace' ) { $valid = array_filter( $data['metaforge_field_groups'], function ( $g ) { return is_array( $g ) && ! empty( $g['group_name'] ); } ); if ( ! empty( $valid ) ) { foreach ( get_posts( array( 'post_type' => 'metaforge_group', 'posts_per_page' => -1, ) ) as $p ) { wp_delete_post( $p->ID, true ); } } $data['metaforge_field_groups'] = array_values( $valid ); } foreach ( $data['metaforge_field_groups'] as $i => $group ) { if ( ! is_array( $group ) || empty( $group['group_name'] ) ) { continue; } $sanitized_group = MetaForge_Loader::sanitize_group_config( $group ); if ( ! $sanitized_group ) { continue; } $title = $sanitized_group['group_name']; $existing_id = null; if ( $strategy !== 'replace' ) { $existing = get_posts( array( 'post_type' => 'metaforge_group', 'title' => $title, 'post_status' => 'publish', 'numberposts' => 1, ) ); if ( ! empty( $existing ) ) { $existing_id = $existing[0]->ID; } } if ( $existing_id ) { update_post_meta( $existing_id, '_metaforge_group_config', $sanitized_group ); } else { $pid = wp_insert_post( array( 'post_title' => $title, 'post_type' => 'metaforge_group', 'post_status' => 'publish', 'menu_order' => $i, ) ); if ( $pid && ! is_wp_error( $pid ) ) { update_post_meta( $pid, '_metaforge_group_config', $sanitized_group ); } } } MetaForge_Loader::clear_cache(); } if ( isset( $data['metaforge_post_types'] ) && is_array( $data['metaforge_post_types'] ) ) { $sanitized_pts = array(); foreach ( $data['metaforge_post_types'] as $pt ) { $s_pt = MetaForge_Loader::sanitize_post_type_config( $pt ); if ( $s_pt && ! empty( $s_pt['slug'] ) ) { $sanitized_pts[] = $s_pt; } } if ( $strategy === 'replace' ) { update_option( 'metaforge_post_types', $sanitized_pts ); } else { $e = get_option( 'metaforge_post_types', array() ); $s = array_column( $e, 'slug' ); foreach ( $sanitized_pts as $pt ) { if ( ! in_array( $pt['slug'], $s, true ) ) { $e[] = $pt; } } update_option( 'metaforge_post_types', $e ); } } if ( isset( $data['metaforge_taxonomies'] ) && is_array( $data['metaforge_taxonomies'] ) ) { $sanitized_taxs = array(); foreach ( $data['metaforge_taxonomies'] as $tax ) { $s_tax = MetaForge_Loader::sanitize_taxonomy_config( $tax ); if ( $s_tax && ! empty( $s_tax['slug'] ) ) { $sanitized_taxs[] = $s_tax; } } if ( $strategy === 'replace' ) { update_option( 'metaforge_taxonomies', $sanitized_taxs ); } else { $e = get_option( 'metaforge_taxonomies', array() ); $s = array_column( $e, 'slug' ); foreach ( $sanitized_taxs as $tax ) { if ( ! in_array( $tax['slug'], $s, true ) ) { $e[] = $tax; } } update_option( 'metaforge_taxonomies', $e ); } } if ( isset( $data['metaforge_options_pages'] ) && is_array( $data['metaforge_options_pages'] ) ) { $sanitized_opts = array(); foreach ( $data['metaforge_options_pages'] as $op ) { $s_op = MetaForge_Loader::sanitize_options_page_config( $op ); if ( $s_op && ! empty( $s_op['slug'] ) ) { $sanitized_opts[] = $s_op; } } if ( $strategy === 'replace' ) { update_option( 'metaforge_options_pages', $sanitized_opts ); } else { $e = get_option( 'metaforge_options_pages', array() ); $s = array_column( $e, 'slug' ); foreach ( $sanitized_opts as $op ) { if ( ! in_array( $op['slug'], $s, true ) ) { $e[] = $op; } } update_option( 'metaforge_options_pages', $e ); } } MetaForge_Logger::log( 'data_imported', array( 'strategy' => $strategy, 'groups' => count( $data['metaforge_field_groups'] ?? array() ), 'post_types' => count( $data['metaforge_post_types'] ?? array() ), 'taxonomies' => count( $data['metaforge_taxonomies'] ?? array() ), 'options' => count( $data['metaforge_options_pages'] ?? array() ), 'converted_repeaters' => $converted_repeaters, ) ); flush_rewrite_rules(); $redirect_url = admin_url( 'admin.php?page=metaforge_tools&metaforge_import=success' ); if ( $converted_repeaters > 0 ) { $redirect_url = add_query_arg( 'converted_repeaters', $converted_repeaters, $redirect_url ); } wp_safe_redirect( $redirect_url ); exit; } public function process_clear_logs() { if ( ! isset( $_POST['metaforge_action'] ) || $_POST['metaforge_action'] !== 'clear_logs' ) { return; } if ( ! isset( $_POST['metaforge_clear_logs_nonce_field'] ) || ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['metaforge_clear_logs_nonce_field'] ) ), 'metaforge_clear_logs_nonce' ) ) { wp_die( 'Security check failed.' ); } if ( ! current_user_can( 'manage_metaforge' ) ) { wp_die( 'Insufficient permissions.' ); } MetaForge_Logger::clear_logs(); wp_safe_redirect( admin_url( 'admin.php?page=metaforge_tools&tab=logs&metaforge_logs_cleared=1' ) ); exit; } public function process_direct_migration() { if ( ! isset( $_POST['metaforge_action'] ) || $_POST['metaforge_action'] !== 'direct_acf_migrate' ) { return; } if ( ! isset( $_POST['metaforge_migrate_nonce_field'] ) || ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['metaforge_migrate_nonce_field'] ) ), 'metaforge_migrate_acf_nonce' ) ) { wp_die( 'Security check failed.' ); } if ( ! current_user_can( 'manage_metaforge' ) ) { wp_die( 'Insufficient permissions.' ); } $acf_posts = get_posts( array( 'post_type' => 'acf-field-group', 'posts_per_page' => -1, 'post_status' => 'any', ) ); $migrated_count = 0; foreach ( $acf_posts as $post ) { $raw_fields = array(); $sub_field_posts = get_posts( array( 'post_type' => 'acf-field', 'post_parent' => $post->ID, 'posts_per_page' => -1, 'orderby' => 'menu_order', 'order' => 'ASC', ) ); foreach ( $sub_field_posts as $sfp ) { $field_data = maybe_unserialize( $sfp->post_content ); if ( is_array( $field_data ) ) { $raw_fields[] = $field_data; } } $acf_group_data = array( 'title' => $post->post_title, 'key' => $post->post_name ?: ( 'group_' . substr( md5( $post->post_title ), 0, 12 ) ), 'fields' => $raw_fields, 'location' => maybe_unserialize( get_post_meta( $post->ID, 'rule', true ) ?: array() ), ); $converted = self::convert_acf_json_to_mfe( array( $acf_group_data ) ); if ( ! empty( $converted['metaforge_field_groups'] ) ) { foreach ( $converted['metaforge_field_groups'] as $cfg ) { $sanitized = MetaForge_Loader::sanitize_group_config( $cfg ); if ( $sanitized ) { $new_id = wp_insert_post( array( 'post_title' => $sanitized['group_name'], 'post_type' => 'metaforge_group', 'post_status' => 'publish', ) ); if ( $new_id && ! is_wp_error( $new_id ) ) { update_post_meta( $new_id, '_metaforge_group_config', $sanitized ); ++$migrated_count; } } } } } MetaForge_Loader::clear_cache(); MetaForge_Logger::log( 'acf_migration_completed', array( 'migrated_count' => $migrated_count ) ); wp_safe_redirect( admin_url( 'admin.php?page=metaforge_tools&tab=migrate&metaforge_migrated=' . $migrated_count ) ); exit; } // ── Admin Page ──────────────────────────────────────────────────────────── public function admin_page() { // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Read-only UI navigation parameter. $active_tab = isset( $_GET['tab'] ) ? sanitize_key( wp_unslash( $_GET['tab'] ) ) : 'import_export'; $all_groups = $this->get_all_groups(); $all_pts = $this->get_all_post_types(); $all_taxs = $this->get_all_taxonomies(); $all_opts = $this->get_all_options_pages(); $full_url = wp_nonce_url( admin_url( 'admin.php?page=metaforge_tools&metaforge_action=export' ), 'metaforge_export_nonce', 'nonce' ); $base_export = wp_nonce_url( admin_url( 'admin.php?page=metaforge_tools&metaforge_action=export' ), 'metaforge_export_nonce', 'nonce' ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Read-only notice query parameter. $status = isset( $_GET['metaforge_import'] ) ? sanitize_key( wp_unslash( $_GET['metaforge_import'] ) ) : ''; ?>
Error: Invalid JSON format.
Error: File too large (max 2 MB upload / 500 KB paste).
Error: Only .json files accepted.
Error: Upload failed. Check PHP upload_max_filesize.
Notice: No data provided.
Notice: No recognised MetaForge data keys found.
Success: Data imported successfully. 0 ) : ?> Note: Repeater automatically converted to Group because MetaForge Pro is deactivated.
Full Export
All field groups, post types, taxonomies & options pages
No field groups found.
No custom post types found.
No custom taxonomies found.
No options pages found.
Success: System audit logs cleared successfully.
No audit log records found.
| Timestamp | Event | User | Context Data |
|---|---|---|---|
| None'; } ?> |
Migration Complete: Successfully migrated field group(s) into native MetaForge Engine field groups! Your existing MetaForge field groups and data are 100% preserved.
No external ACF field groups were detected in your database. You can build field groups natively in MetaForge Engine or import schemas via the Import & Export tab.
Found external field group(s) ready for instant conversion: