$post_type ) ); $formatted_groups = array(); foreach ( $field_groups as $group ) { $formatted_groups[] = array( 'id' => $group['key'], 'title' => $group['title'], 'fields' => $this->get_fields_for_group( $group['key'] ), ); } return $formatted_groups; } /** * Get fields for group * * @param string $group_id Group ID/key. * @return array Fields. */ public function get_fields_for_group( $group_id ) { if ( ! function_exists( 'acf_get_fields' ) ) { return array(); } $fields = acf_get_fields( $group_id ); if ( ! $fields ) { return array(); } $formatted_fields = array(); foreach ( $fields as $field ) { $formatted_field = array( 'key' => $field['key'], 'name' => $field['name'], 'label' => $field['label'], 'type' => $field['type'], 'required' => $field['required'] ?? false, 'instructions' => $field['instructions'] ?? '', 'default_value' => $field['default_value'] ?? '', 'placeholder' => $field['placeholder'] ?? '', 'choices' => $field['choices'] ?? array(), 'rows' => $field['rows'] ?? 5, 'max_size' => $field['max_size'] ?? '', 'mime_types' => $field['mime_types'] ?? '', 'min' => $field['min'] ?? '', 'max' => $field['max'] ?? '', 'button_label' => $field['button_label'] ?? '', 'message' => $field['message'] ?? '', ); // Add post_type, multiple, allow_null for relationship fields. if ( in_array( $field['type'], array( 'relationship', 'post_object', 'page_link' ), true ) ) { // Ensure post_type is always an array. $post_type = $field['post_type'] ?? ''; if ( is_string( $post_type ) ) { $post_type = ! empty( $post_type ) ? array( $post_type ) : array( 'post' ); } elseif ( ! is_array( $post_type ) ) { $post_type = array( 'post' ); } $formatted_field['post_type'] = $post_type; $formatted_field['multiple'] = $field['multiple'] ?? false; $formatted_field['allow_null'] = $field['allow_null'] ?? true; } // Add sub_fields for repeater and group. if ( in_array( $field['type'], array( 'repeater', 'group' ), true ) ) { // For group/repeater fields, ACF might not include sub_fields in the main field array. // We need to explicitly fetch them using acf_get_field for the complete field data. if ( empty( $field['sub_fields'] ) ) { // Try to get the full field data which includes sub_fields. if ( function_exists( 'acf_get_field' ) && ! empty( $field['key'] ) ) { $full_field = acf_get_field( $field['key'] ); if ( ! empty( $full_field['sub_fields'] ) ) { $field['sub_fields'] = $full_field['sub_fields']; } } } // Now format the sub-fields if we have them. if ( ! empty( $field['sub_fields'] ) ) { $formatted_field['sub_fields'] = $this->format_sub_fields( $field['sub_fields'] ); } } // Add layouts for flexible_content. if ( 'flexible_content' === $field['type'] ) { // Get layouts from field. if ( empty( $field['layouts'] ) ) { // Try to get the full field data. if ( function_exists( 'acf_get_field' ) && ! empty( $field['key'] ) ) { $full_field = acf_get_field( $field['key'] ); if ( ! empty( $full_field['layouts'] ) ) { $field['layouts'] = $full_field['layouts']; } } } if ( ! empty( $field['layouts'] ) ) { $formatted_field['layouts'] = $this->format_flexible_layouts( $field['layouts'] ); } $formatted_field['button_label'] = $field['button_label'] ?? __( 'Add Row', 'airy-frontend-forms' ); $formatted_field['min'] = $field['min'] ?? 0; $formatted_field['max'] = $field['max'] ?? 0; } // Add taxonomy field properties. if ( 'taxonomy' === $field['type'] ) { $formatted_field['taxonomy'] = $field['taxonomy'] ?? 'category'; $formatted_field['field_type'] = $field['field_type'] ?? 'checkbox'; $formatted_field['allow_null'] = $field['allow_null'] ?? true; $formatted_field['add_term'] = $field['add_term'] ?? false; $formatted_field['save_terms'] = $field['save_terms'] ?? false; $formatted_field['load_terms'] = $field['load_terms'] ?? false; $formatted_field['return_format'] = $field['return_format'] ?? 'id'; } // Add user field properties. if ( 'user' === $field['type'] ) { $formatted_field['role'] = $field['role'] ?? ''; $formatted_field['multiple'] = $field['multiple'] ?? false; $formatted_field['allow_null'] = $field['allow_null'] ?? true; } // Add link field properties. if ( 'link' === $field['type'] ) { $formatted_field['return_format'] = $field['return_format'] ?? 'array'; } // Add nav_menu field properties. if ( 'nav_menu' === $field['type'] ) { $formatted_field['allow_null'] = $field['allow_null'] ?? true; $formatted_field['return_format'] = $field['return_format'] ?? 'id'; } // Add google_map field properties. if ( 'google_map' === $field['type'] ) { $formatted_field['center_lat'] = $field['center_lat'] ?? ''; $formatted_field['center_lng'] = $field['center_lng'] ?? ''; $formatted_field['zoom'] = $field['zoom'] ?? 14; $formatted_field['height'] = $field['height'] ?? 400; } // Add clone field properties. if ( 'clone' === $field['type'] ) { // Clone fields copy other fields - get the sub_fields. if ( empty( $field['sub_fields'] ) && function_exists( 'acf_get_field' ) && ! empty( $field['key'] ) ) { $full_field = acf_get_field( $field['key'] ); if ( ! empty( $full_field['sub_fields'] ) ) { $field['sub_fields'] = $full_field['sub_fields']; } } if ( ! empty( $field['sub_fields'] ) ) { $formatted_field['sub_fields'] = $this->format_sub_fields( $field['sub_fields'] ); } $formatted_field['clone'] = $field['clone'] ?? array(); $formatted_field['display'] = $field['display'] ?? 'seamless'; $formatted_field['prefix_label'] = $field['prefix_label'] ?? false; $formatted_field['prefix_name'] = $field['prefix_name'] ?? false; } // Add range field properties. if ( 'range' === $field['type'] ) { $formatted_field['min'] = $field['min'] ?? 0; $formatted_field['max'] = $field['max'] ?? 100; $formatted_field['step'] = $field['step'] ?? 1; $formatted_field['prepend'] = $field['prepend'] ?? ''; $formatted_field['append'] = $field['append'] ?? ''; } // Add accordion field properties. if ( 'accordion' === $field['type'] ) { $formatted_field['open'] = $field['open'] ?? false; $formatted_field['multi_expand'] = $field['multi_expand'] ?? false; $formatted_field['endpoint'] = $field['endpoint'] ?? false; } // Add tab field properties. if ( 'tab' === $field['type'] ) { $formatted_field['placement'] = $field['placement'] ?? 'top'; $formatted_field['endpoint'] = $field['endpoint'] ?? false; } $formatted_fields[] = $formatted_field; } return $formatted_fields; } /** * Format sub-fields (recursive for nested groups) * * @param array $sub_fields Sub-fields array. * @return array Formatted sub-fields. */ private function format_sub_fields( $sub_fields ) { $formatted = array(); foreach ( $sub_fields as $field ) { $formatted_field = array( 'key' => $field['key'], 'name' => $field['name'], 'label' => $field['label'], 'type' => $field['type'], 'required' => $field['required'] ?? false, 'instructions' => $field['instructions'] ?? '', 'default_value' => $field['default_value'] ?? '', 'placeholder' => $field['placeholder'] ?? '', 'choices' => $field['choices'] ?? array(), 'rows' => $field['rows'] ?? 5, 'message' => $field['message'] ?? '', 'min' => $field['min'] ?? '', 'max' => $field['max'] ?? '', ); // Handle nested groups recursively. if ( 'group' === $field['type'] ) { // Try to get sub-fields if not present using acf_get_field for full field data. if ( empty( $field['sub_fields'] ) && function_exists( 'acf_get_field' ) && ! empty( $field['key'] ) ) { $full_field = acf_get_field( $field['key'] ); if ( ! empty( $full_field['sub_fields'] ) ) { $field['sub_fields'] = $full_field['sub_fields']; } } if ( ! empty( $field['sub_fields'] ) ) { $formatted_field['sub_fields'] = $this->format_sub_fields( $field['sub_fields'] ); } } // Handle repeaters inside groups/repeaters. if ( 'repeater' === $field['type'] ) { // Try to get sub-fields if not present using acf_get_field for full field data. if ( empty( $field['sub_fields'] ) && function_exists( 'acf_get_field' ) && ! empty( $field['key'] ) ) { $full_field = acf_get_field( $field['key'] ); if ( ! empty( $full_field['sub_fields'] ) ) { $field['sub_fields'] = $full_field['sub_fields']; } } if ( ! empty( $field['sub_fields'] ) ) { $formatted_field['sub_fields'] = $this->format_sub_fields( $field['sub_fields'] ); } $formatted_field['button_label'] = $field['button_label'] ?? __( 'Add Row', 'airy-frontend-forms' ); $formatted_field['min'] = $field['min'] ?? 0; $formatted_field['max'] = $field['max'] ?? 0; } // Handle flexible_content inside groups/repeaters. if ( 'flexible_content' === $field['type'] ) { if ( empty( $field['layouts'] ) && function_exists( 'acf_get_field' ) && ! empty( $field['key'] ) ) { $full_field = acf_get_field( $field['key'] ); if ( ! empty( $full_field['layouts'] ) ) { $field['layouts'] = $full_field['layouts']; } } if ( ! empty( $field['layouts'] ) ) { $formatted_field['layouts'] = $this->format_flexible_layouts( $field['layouts'] ); } $formatted_field['button_label'] = $field['button_label'] ?? __( 'Add Row', 'airy-frontend-forms' ); $formatted_field['min'] = $field['min'] ?? 0; $formatted_field['max'] = $field['max'] ?? 0; } // Taxonomy field properties. if ( 'taxonomy' === $field['type'] ) { $formatted_field['taxonomy'] = $field['taxonomy'] ?? 'category'; $formatted_field['field_type'] = $field['field_type'] ?? 'select'; $formatted_field['allow_null'] = $field['allow_null'] ?? true; } // User field properties. if ( 'user' === $field['type'] ) { $formatted_field['role'] = $field['role'] ?? ''; $formatted_field['multiple'] = $field['multiple'] ?? false; $formatted_field['allow_null'] = $field['allow_null'] ?? true; } // Relationship/post_object/page_link field properties. if ( in_array( $field['type'], array( 'relationship', 'post_object', 'page_link' ), true ) ) { $post_type = $field['post_type'] ?? array( 'post' ); if ( is_string( $post_type ) ) { $post_type = ! empty( $post_type ) ? array( $post_type ) : array( 'post' ); } $formatted_field['post_type'] = $post_type; $formatted_field['multiple'] = $field['multiple'] ?? ( 'relationship' === $field['type'] ); $formatted_field['allow_null'] = $field['allow_null'] ?? true; } // Link field properties. if ( 'link' === $field['type'] ) { $formatted_field['return_format'] = $field['return_format'] ?? 'array'; } // Google map field properties. if ( 'google_map' === $field['type'] ) { $formatted_field['center_lat'] = $field['center_lat'] ?? ''; $formatted_field['center_lng'] = $field['center_lng'] ?? ''; $formatted_field['zoom'] = $field['zoom'] ?? 14; $formatted_field['height'] = $field['height'] ?? 400; } // Clone field properties. if ( 'clone' === $field['type'] ) { if ( empty( $field['sub_fields'] ) && function_exists( 'acf_get_field' ) && ! empty( $field['key'] ) ) { $full_field = acf_get_field( $field['key'] ); if ( ! empty( $full_field['sub_fields'] ) ) { $field['sub_fields'] = $full_field['sub_fields']; } } if ( ! empty( $field['sub_fields'] ) ) { $formatted_field['sub_fields'] = $this->format_sub_fields( $field['sub_fields'] ); } $formatted_field['clone'] = $field['clone'] ?? array(); $formatted_field['display'] = $field['display'] ?? 'seamless'; $formatted_field['prefix_label'] = $field['prefix_label'] ?? false; $formatted_field['prefix_name'] = $field['prefix_name'] ?? false; } // Range field properties. if ( 'range' === $field['type'] ) { $formatted_field['min'] = $field['min'] ?? 0; $formatted_field['max'] = $field['max'] ?? 100; $formatted_field['step'] = $field['step'] ?? 1; $formatted_field['prepend'] = $field['prepend'] ?? ''; $formatted_field['append'] = $field['append'] ?? ''; } // Nav menu field properties. if ( 'nav_menu' === $field['type'] ) { $formatted_field['allow_null'] = $field['allow_null'] ?? true; $formatted_field['return_format'] = $field['return_format'] ?? 'id'; } // Icon picker field properties. if ( 'icon_picker' === $field['type'] ) { $formatted_field['return_format'] = $field['return_format'] ?? 'string'; } // Accordion field properties. if ( 'accordion' === $field['type'] ) { $formatted_field['open'] = $field['open'] ?? false; $formatted_field['multi_expand'] = $field['multi_expand'] ?? false; $formatted_field['endpoint'] = $field['endpoint'] ?? false; } // Tab field properties. if ( 'tab' === $field['type'] ) { $formatted_field['placement'] = $field['placement'] ?? 'top'; $formatted_field['endpoint'] = $field['endpoint'] ?? false; } $formatted[] = $formatted_field; } return $formatted; } /** * Format flexible content layouts * * @param array $layouts Layouts array. * @return array Formatted layouts. */ private function format_flexible_layouts( $layouts ) { $formatted = array(); foreach ( $layouts as $layout ) { $formatted_layout = array( 'key' => $layout['key'] ?? '', 'name' => $layout['name'] ?? '', 'label' => $layout['label'] ?? $layout['name'] ?? '', 'min' => $layout['min'] ?? '', 'max' => $layout['max'] ?? '', ); // Try to get sub-fields if not present in layout data. if ( empty( $layout['sub_fields'] ) && function_exists( 'acf_get_fields' ) && ! empty( $layout['key'] ) ) { $layout_sub_fields = acf_get_fields( $layout['key'] ); if ( ! empty( $layout_sub_fields ) ) { $layout['sub_fields'] = $layout_sub_fields; } } // Format sub-fields for the layout. if ( ! empty( $layout['sub_fields'] ) ) { $formatted_layout['sub_fields'] = $this->format_sub_fields( $layout['sub_fields'] ); } else { $formatted_layout['sub_fields'] = array(); } $formatted[] = $formatted_layout; } return $formatted; } /** * Get field * * @param string $field_key Field key. * @return array|null. */ public function get_field( $field_key ) { if ( ! function_exists( 'acf_get_field' ) ) { return null; } return acf_get_field( $field_key ); } /** * Update field value * * @param string $field_key Field key. * @param mixed $value Value. * @param int $post_id Post ID. * @return bool. */ public function update_field( $field_key, $value, $post_id ) { if ( ! function_exists( 'update_field' ) ) { return false; } return update_field( $field_key, $value, $post_id ); } /** * Get field value * * @param string $field_key Field key. * @param int $post_id Post ID. * @return mixed. */ public function get_field_value( $field_key, $post_id ) { if ( ! function_exists( 'get_field' ) ) { return null; } $value = get_field( $field_key, $post_id ); return $value; } /** * Get ACF version * * @return string|null. */ public function get_version() { if ( defined( 'ACF_VERSION' ) ) { return ACF_VERSION; } if ( function_exists( 'acf_get_setting' ) ) { return acf_get_setting( 'version' ); } return null; } }