[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'] ) ) : ''; ?>
render_logs_tab(); ?> render_migrate_tab(); ?>

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.

Export Data

Full Export

All field groups, post types, taxonomies & options pages

Export All
Field Groups
0 selected
$item ) : $config = $item['config']; $group_name = esc_html( $config['group_name'] ?? 'Unnamed Group' ); $field_count = count( $config['fields'] ?? array() ); $post_type = esc_html( $config['post_type'] ?? '' ); ?>

No field groups found.

Post Types
0 selected

No custom post types found.

Taxonomies
0 selected

No custom taxonomies found.

Options Pages
0 selected

No options pages found.

Import Data

Drag & drop or

MetaForge Pro is deactivated. Existing layout and sub-fields are preserved. Any Repeater fields in imported JSON will automatically be converted to Group fields.
Or paste JSON directly
MetaForge Pro is deactivated. Existing layout and sub-fields are preserved. Any Repeater fields in imported JSON will automatically be converted to Group fields.

Import Strategy

Success: System audit logs cleared successfully.

System Logs & Audit Trail

No audit log records found.

Timestamp Event User Context Data
None'; } ?>
'acf-field-group', 'posts_per_page' => -1, 'post_status' => 'any', ) ); ?>

Migration Complete: Successfully migrated field group(s) into native MetaForge Engine field groups! Your existing MetaForge field groups and data are 100% preserved.

Switch to MetaForge: Direct Field Group Migration

Zero Lock-In & Non-Destructive Migration

This tool scans your database for external ACF (Advanced Custom Fields) field groups and converts them into native MetaForge Engine (MFE) field groups in 1 click. Your existing MetaForge field groups and database values will NOT be deleted or overwritten.

Detected External Field Groups

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:

  • post_title ?: 'Untitled Group' ); ?> (ID: #ID ); ?>)
$param, 'operator' => $rule['operator'] ?? '==', 'value' => $rule['value'] ?? '', ); } $location_rules[] = $metaforge_rule_group; } } $primary_pt = 'post'; foreach ( $location_rules as $rg ) { foreach ( $rg as $r ) { $param = $r['param'] ?? ''; $val = $r['value'] ?? ''; if ( $param === 'post_type' && ! empty( $val ) ) { $primary_pt = $val; break 2; } elseif ( in_array( $param, array( 'page_template', 'page_type', 'page_parent', 'page' ), true ) ) { $primary_pt = 'page'; } } } $metaforge_groups[] = array( 'group_name' => $group_name, 'group_key' => $group_key, 'post_type' => $primary_pt, 'fields' => $fields, 'location_rules' => $location_rules, ); } return array( 'metaforge_field_groups' => $metaforge_groups ); } /** * Recursively collect ACF field key => field name mappings for conditional logic resolution. */ private static function collect_acf_field_keys( array $fields, array &$map ) { foreach ( $fields as $f ) { if ( ! is_array( $f ) ) { continue; } $key = $f['key'] ?? ''; $name = $f['name'] ?? ( ! empty( $f['label'] ) ? sanitize_title( $f['label'] ) : '' ); if ( ! empty( $key ) && ! empty( $name ) ) { $map[ $key ] = $name; } if ( ! empty( $f['sub_fields'] ) && is_array( $f['sub_fields'] ) ) { self::collect_acf_field_keys( $f['sub_fields'], $map ); } if ( ! empty( $f['layouts'] ) && is_array( $f['layouts'] ) ) { foreach ( $f['layouts'] as $layout ) { if ( ! empty( $layout['sub_fields'] ) && is_array( $layout['sub_fields'] ) ) { self::collect_acf_field_keys( $layout['sub_fields'], $map ); } } } } } private static function convert_acf_fields_to_mfe( array $acf_fields, array $key_to_name_map = array() ) { $type_map = array( 'text' => 'text', 'textarea' => 'textarea', 'number' => 'number', 'range' => 'range', 'email' => 'email', 'url' => 'url', 'password' => 'password', 'image' => 'image', 'file' => 'file', 'wysiwyg' => 'wysiwyg', 'oembed' => 'oembed', 'select' => 'select', 'checkbox' => 'checkbox', 'radio' => 'radio', 'button_group' => 'radio', 'true_false' => 'true_false', 'link' => 'link', 'post_object' => 'post_type_selector', 'page_link' => 'link', 'relationship' => 'relationship', 'taxonomy' => 'taxonomy', 'user' => 'user', 'google_map' => 'text', 'date_picker' => 'date_time', 'date_time_picker' => 'date_time', 'time_picker' => 'date_time', 'color_picker' => 'color_picker', 'message' => 'text', 'accordion' => 'accordion', 'tab' => 'tab', 'group' => 'group', 'repeater' => 'repeater', 'flexible_content' => 'flexible_content', 'gallery' => 'gallery', ); $metaforge_fields = array(); foreach ( $acf_fields as $f ) { if ( ! is_array( $f ) ) { continue; } $acf_type = $f['type'] ?? 'text'; $metaforge_type = $type_map[ $acf_type ] ?? 'text'; // Process Conditional Logic $conditional_logic = 0; $conditions = array(); if ( ! empty( $f['conditional_logic'] ) && is_array( $f['conditional_logic'] ) ) { foreach ( $f['conditional_logic'] as $rule_group ) { if ( ! is_array( $rule_group ) ) { continue; } foreach ( $rule_group as $rule ) { if ( ! is_array( $rule ) || empty( $rule['field'] ) ) { continue; } $target_field = $rule['field']; if ( isset( $key_to_name_map[ $target_field ] ) ) { $target_field = $key_to_name_map[ $target_field ]; } $raw_op = $rule['operator'] ?? '=='; $op_map = array( '==' => '==', '!=' => '!=', '>' => '>', '<' => '<', '==empty' => 'is_empty', '!=empty' => 'has_any_value', ); $operator = $op_map[ $raw_op ] ?? '=='; $val = $rule['value'] ?? ''; $conditions[] = array( 'field' => sanitize_key( $target_field ), 'operator' => $operator, 'value' => (string) $val, ); } } if ( ! empty( $conditions ) ) { $conditional_logic = 1; } } $field = array( 'label' => $f['label'] ?? ( $f['name'] ?? 'Field' ), 'name' => $f['name'] ?? sanitize_title( $f['label'] ?? 'field' ), 'type' => $metaforge_type, 'required' => ! empty( $f['required'] ) ? 1 : 0, 'placeholder' => $f['placeholder'] ?? '', 'instructions' => $f['instructions'] ?? '', 'conditional_logic' => $conditional_logic, 'conditions' => $conditions, ); // Width wrapper if ( ! empty( $f['wrapper']['width'] ) ) { $w = preg_replace( '/[^0-9]/', '', (string) $f['wrapper']['width'] ); if ( ! empty( $w ) ) { $field['width'] = $w; } } // Sub layout for repeaters and groups if ( ! empty( $f['layout'] ) && in_array( $f['layout'], array( 'table', 'block', 'row' ), true ) ) { $field['sub_layout'] = $f['layout']; } // Textarea settings if ( isset( $f['rows'] ) && $f['rows'] !== '' ) { $field['rows'] = (string) $f['rows']; } if ( isset( $f['new_lines'] ) ) { $field['new_lines'] = ( $f['new_lines'] === '' ) ? 'none' : $f['new_lines']; } // Min, max, step if ( isset( $f['min'] ) && $f['min'] !== '' ) { $field['min'] = (string) $f['min']; } if ( isset( $f['max'] ) && $f['max'] !== '' ) { $field['max'] = (string) $f['max']; } if ( isset( $f['step'] ) && $f['step'] !== '' ) { $field['step'] = (string) $f['step']; } // Return format for image / file if ( ! empty( $f['return_format'] ) ) { $field['image_return_format'] = $f['return_format']; } // Default value if ( isset( $f['default_value'] ) && is_scalar( $f['default_value'] ) ) { $field['default_value'] = (string) $f['default_value']; } if ( ! empty( $f['sub_fields'] ) && is_array( $f['sub_fields'] ) ) { $field['sub_fields'] = self::convert_acf_fields_to_mfe( $f['sub_fields'], $key_to_name_map ); } if ( ! empty( $f['layouts'] ) && is_array( $f['layouts'] ) ) { $field['layouts'] = array(); foreach ( $f['layouts'] as $layout ) { $layout_sub = array(); if ( ! empty( $layout['sub_fields'] ) && is_array( $layout['sub_fields'] ) ) { $layout_sub = self::convert_acf_fields_to_mfe( $layout['sub_fields'], $key_to_name_map ); } $field['layouts'][] = array( 'name' => $layout['name'] ?? '', 'label' => $layout['label'] ?? '', 'sub_fields' => $layout_sub, ); } } if ( ! empty( $f['choices'] ) && is_array( $f['choices'] ) ) { $options_array = array(); foreach ( $f['choices'] as $k => $v ) { $key = is_scalar( $k ) ? (string) $k : ''; $val = is_scalar( $v ) ? (string) $v : ( is_array( $v ) ? ( $v['label'] ?? $v['value'] ?? $key ) : $key ); $options_array[ $key ] = $val; } $field['options'] = $options_array; } $metaforge_fields[] = $field; } return $metaforge_fields; } }