'formipay/coupon-config', 'formipay-product' => 'formipay/product-config', 'formipay-form' => 'formipay/form-config', 'formipay-access' => 'formipay/access-config', ]; /** * Get complete field configuration for a post with saved values * * @param int $post_id Post ID * @param string $post_type Post type * @return array React-ready field configuration */ public static function get_config_for_post($post_id, $post_type) { $filter_name = self::$cpt_filter_map[$post_type] ?? null; if (!$filter_name) { return []; } // Get field configuration from filters $fields = apply_filters($filter_name, []); // Load saved values from post meta $values = self::load_post_meta_values($post_id, $fields); // Transform to React-ready format return self::transform_fields_config($fields, $values, $post_id, $post_type); } /** * Get configuration for settings page (wp_options based) * * @param string $option_name Option name * @return array React-ready field configuration */ public static function get_config_for_settings($option_name = 'formipay_settings') { // Get settings values $settings = get_option($option_name, []); // Get field definitions directly from Settings class $settings_instance = \Formipay\Settings::get_instance(); $tabs_config = $settings_instance->get_settings_fields(); // Transform to React-ready format return self::transform_settings_config($settings, $tabs_config, $option_name); } /** * Transform settings config to React-ready format * * @param array $settings Settings values * @param array $tabs_config Tab configuration from Settings class * @param string $option_name Option name * @return array React-ready configuration */ private static function transform_settings_config($settings, $tabs_config, $option_name) { $tabs = []; foreach ($tabs_config as $tab_key => $tab_data) { if (!isset($tab_data['name']) || !isset($tab_data['fields'])) { continue; } $tab = [ 'id' => self::slugify($tab_data['name']), 'label' => $tab_data['name'], 'fields' => [], ]; $current_group = null; foreach ($tab_data['fields'] as $field_name => $field) { // Handle group_title (section headers) if (isset($field['type']) && $field['type'] === 'group_title') { $group_value = $field['group'] ?? ''; if ($group_value === 'started') { $current_group = [ 'type' => 'section', 'label' => $field['label'] ?? '', 'description' => $field['description'] ?? '', ]; } elseif ($group_value === 'ended') { $current_group = null; } continue; } // Add section if we have one if ($current_group !== null) { $tab['fields'][] = $current_group; $current_group = null; } // Transform field configuration $transformed_field = self::transform_settings_field($field_name, $field, $settings); // Add to fields $tab['fields'][] = $transformed_field; } $tabs[] = $tab; } return [ 'tabs' => $tabs, 'optionName' => $option_name, 'globalCurrencies' => self::get_global_currencies_data(), 'nonce' => wp_create_nonce('formipay-field-config'), ]; } /** * Load saved post meta values for all fields * * @param int $post_id Post ID * @param array $fields Field configuration array * @return array Field values keyed by field name */ private static function load_post_meta_values($post_id, $fields) { $values = []; // The config structure is: $fields['formipay_{cpt}_settings'][tab_key] = ['name' => ..., 'fields' => [...]] foreach ($fields as $container_key => $container_data) { if (!is_array($container_data)) { continue; } foreach ($container_data as $tab_key => $tab_data) { if (!isset($tab_data['fields']) || !is_array($tab_data['fields'])) { continue; } foreach ($tab_data['fields'] as $field_name => $field) { // Skip group_title fields if (isset($field['type']) && $field['type'] === 'group_title') { continue; } $meta_value = get_post_meta($post_id, $field_name, true); $values[$field_name] = $meta_value !== '' ? $meta_value : ($field['value'] ?? null); } } } return $values; } /** * Transform fields config to React-ready format * * @param array $fields Raw field configuration from PHP * @param array $values Saved field values * @param int $post_id Post ID * @param string $post_type Post type * @return array React-ready configuration */ private static function transform_fields_config($fields, $values, $post_id, $post_type) { $tabs = []; // The config structure is: $fields['formipay_{cpt}_settings'][tab_key] = ['name' => ..., 'fields' => [...]] foreach ($fields as $container_key => $container_data) { if (!is_array($container_data)) { continue; } foreach ($container_data as $tab_key => $tab_data) { if (!isset($tab_data['name']) || !isset($tab_data['fields'])) { continue; } $tab = [ 'id' => $tab_key, 'label' => $tab_data['name'], 'fields' => [], ]; $current_group = null; foreach ($tab_data['fields'] as $field_name => $field) { // Handle group_title (section headers) if (isset($field['type']) && $field['type'] === 'group_title') { $group_value = $field['group'] ?? ''; if ($group_value === 'started') { $current_group = [ 'type' => 'section', 'label' => $field['label'] ?? '', 'description' => $field['description'] ?? '', ]; } elseif ($group_value === 'ended') { $current_group = null; } continue; } // Add section if we have one if ($current_group !== null) { $tab['fields'][] = $current_group; $current_group = null; } // Transform field configuration $transformed_field = self::transform_single_field($field_name, $field, $values); // Add to fields $tab['fields'][] = $transformed_field; } $tabs[] = $tab; } } return [ 'tabs' => $tabs, 'postId' => $post_id, 'postType' => $post_type, 'globalCurrencies' => self::get_global_currencies_data(), 'nonce' => wp_create_nonce('formipay-field-config'), ]; } /** * Transform a single field configuration * * @param string $field_name Field name * @param array $field Field configuration * @param array $values Saved values * @return array Transformed field config */ private static function transform_single_field($field_name, $field, $values) { $transformed = [ 'name' => $field_name, 'type' => self::transform_field_type($field['type'] ?? 'text'), 'label' => $field['label'] ?? '', 'description' => $field['description'] ?? '', 'value' => $values[$field_name] ?? $field['value'] ?? '', 'required' => !empty($field['required']), 'dependency' => isset($field['dependency']) ? self::transform_dependency($field['dependency']) : null, ]; // Add options for select/radio fields if (isset($field['options'])) { $transformed['options'] = $field['options']; } // Add subtype info for currency fields if (isset($field['step'])) { $transformed['step'] = $field['step']; } if (isset($field['min'])) { $transformed['min'] = $field['min']; } if (isset($field['placeholder'])) { $transformed['placeholder'] = $field['placeholder']; } // Handle special field types if (isset($field['repeater_fields'])) { $transformed['fields'] = $field['repeater_fields']; } // Pass post_type for autocomplete fields (CPTs) if (isset($field['post_type'])) { $transformed['post_type'] = $field['post_type']; } // Pass object_type for autocomplete fields (e.g., 'user' for WP Users) if (isset($field['object_type'])) { $transformed['object_type'] = $field['object_type']; } return $transformed; } /** * Transform field type from PHP to React format * * @param string $type PHP field type * @return string React field type */ private static function transform_field_type($type) { $type_map = [ 'checkbox' => 'switch', // Use toggle switch UI 'tinymce' => 'editor', // Rich text editor 'editor' => 'editor', // Map 'editor' type to tinymce field 'image' => 'image', // WordPress Media Library picker 'notification_message' => 'notification', // Notification banner component ]; return $type_map[$type] ?? $type; } /** * Transform dependency from PHP to React format * * @param array $dependency PHP dependency config * @return array React dependency config */ private static function transform_dependency($dependency) { // Handle multiple dependencies (AND logic) if (isset($dependency[0]) && is_array($dependency[0])) { return [ 'mode' => 'and', 'rules' => array_map([self::class, 'transform_single_dependency'], $dependency), ]; } return self::transform_single_dependency($dependency); } /** * Transform a single dependency rule * * @param array $dependency PHP dependency * @return array React dependency rule */ private static function transform_single_dependency($dependency) { $rule = [ 'field' => $dependency['key'] ?? '', ]; $value = $dependency['value'] ?? ''; // Handle special values if ($value === 'not_empty') { $rule['operator'] = 'not_empty'; } elseif ($value === 'empty') { $rule['operator'] = 'empty'; } else { $rule['value'] = $value; $rule['operator'] = 'eq'; } return $rule; } /** * Get global currencies data for React * * @return array Currencies data */ private static function get_global_currencies_data() { $currencies = get_global_currency_array(); return array_map(function($currency) { $parts = explode(':::', $currency['currency']); return [ 'currency' => $currency['currency'], 'code' => $parts[0] ?? '', 'title' => $parts[1] ?? '', 'symbol' => $parts[2] ?? $parts[1] ?? '', 'decimalDigits' => intval($currency['decimal_digits'] ?? 2), 'decimalSymbol' => $currency['decimal_symbol'] ?? '.', 'thousandSeparator' => $currency['thousand_separator'] ?? ',', 'flag' => formipay_get_flag_by_currency($currency['currency']), ]; }, $currencies); } /** * Transform a single settings field configuration * * @param string $field_name Field name * @param array $field Field configuration * @param array $settings Saved settings values * @return array Transformed field config */ private static function transform_settings_field($field_name, $field, $settings) { $transformed = [ 'name' => $field_name, 'type' => self::transform_field_type($field['type'] ?? 'text'), 'label' => $field['label'] ?? '', 'description' => $field['description'] ?? '', 'value' => $settings[$field_name] ?? $field['value'] ?? '', 'required' => !empty($field['required']), 'dependency' => isset($field['dependency']) ? self::transform_dependency($field['dependency']) : null, ]; // Add options for select/radio/multi_checkbox fields if (isset($field['options'])) { $transformed['options'] = $field['options']; } // Add options for image_select if (isset($field['options']) && $field['type'] === 'image_select') { $transformed['width'] = $field['width'] ?? 100; $transformed['height'] = $field['height'] ?? 100; } // Add hints for hint_textarea if (isset($field['hints'])) { $transformed['hints'] = $field['hints']; } // Add step/min for number fields if (isset($field['step'])) { $transformed['step'] = $field['step']; } if (isset($field['min'])) { $transformed['min'] = $field['min']; } if (isset($field['placeholder'])) { $transformed['placeholder'] = $field['placeholder']; } if (isset($field['rows'])) { $transformed['rows'] = $field['rows']; } // Handle repeater fields if (isset($field['fields'])) { // Transform sub-fields to include name property $sub_fields = []; foreach ($field['fields'] as $sub_field_name => $sub_field) { $sub_field['name'] = $sub_field_name; $sub_fields[] = $sub_field; } $transformed['fields'] = $sub_fields; } return $transformed; } /** * Convert string to URL-safe slug * * @param string $text Text to slugify * @return string URL-safe slug */ private static function slugify($text) { return strtolower(sanitize_title($text)); } }