feat: add React FieldRenderer system for settings and metaboxes
Complete React-based field rendering system that replaces WPCFTO Vue.js layer while maintaining PHP field configuration compatibility. Components: - FieldRenderer: Main renderer with tabs support (metabox) and direct mode (settings) - FieldTypes: 15+ field types (Text, Number, Select, Radio, Date, etc.) - RepeaterField: Collapsible repeater with currency label parsing - DependencyEngine: Show/hide fields based on conditions - ValidationEngine: Client-side validation with error messages - SettingsRenderer: Settings page with AJAX save to wp_options Features: - Repeater rows collapsed by default with readable currency titles - Searchable dropdowns using Popover + Command pattern - Proper label resolution for pre-selected values - Hidden input sync for WordPress form submission Also includes: - FieldConfigBridge: Transform PHP configs to React format - Updated Settings.php for React-based settings page - Radio-group UI component - wp-admin-restore.css for admin panel isolation
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
<?php
|
||||
namespace Formipay;
|
||||
use Formipay\Traits\SingletonTrait;
|
||||
use Formipay\Admin\FieldConfigBridge;
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) exit;
|
||||
|
||||
@@ -11,16 +12,39 @@ class Settings {
|
||||
/**
|
||||
* Initializes the plugin by setting filters and administration functions.
|
||||
*/
|
||||
|
||||
|
||||
protected function __construct() {
|
||||
|
||||
add_filter( 'wpcfto_options_page_setup', [$this, 'theme_option'] );
|
||||
// Register our submenu page
|
||||
add_action( 'admin_menu', [$this, 'add_settings_page'] );
|
||||
|
||||
add_action( 'admin_enqueue_scripts', [$this, 'enqueue'] );
|
||||
add_action( 'admin_footer', [$this, 'render_react_settings_template'] );
|
||||
|
||||
// AJAX handler for saving settings from React
|
||||
add_action( 'wp_ajax_formipay_save_settings', [$this, 'ajax_save_settings'] );
|
||||
|
||||
}
|
||||
|
||||
public function theme_option($setups){
|
||||
/**
|
||||
* Add settings submenu page
|
||||
*/
|
||||
public function add_settings_page() {
|
||||
add_submenu_page(
|
||||
'formipay', // Parent slug
|
||||
__('Formipay Settings', 'formipay'), // Page title
|
||||
__('Settings', 'formipay'), // Menu title
|
||||
'manage_options', // Capability
|
||||
'formipay-settings', // Menu slug
|
||||
[$this, 'render_settings_page'] // Callback function
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get settings field configuration for React
|
||||
* Direct method without WPCFTO dependency
|
||||
*/
|
||||
public function get_settings_fields() {
|
||||
$gateways = apply_filters( 'formipay/form-config/tab:payments/gateways', [] );
|
||||
|
||||
$payment_checkboxes = [];
|
||||
@@ -253,7 +277,7 @@ class Settings {
|
||||
'value' => __( 'Input your {{media}} to get new access link.', 'formipay' ),
|
||||
'submenu' => __( 'Thank-You Page', 'formipay' ),
|
||||
'hints' => array(
|
||||
'media' => __( 'Contact Media', 'formipay' )
|
||||
'media' => __( 'Contact Media', 'formipay' )
|
||||
),
|
||||
'description' => __( 'Use {{media}} shortcode to define what media of contact the buyer can receive the access link.', 'formipay' )
|
||||
),
|
||||
@@ -268,59 +292,115 @@ class Settings {
|
||||
|
||||
$pages_fields = apply_filters( 'formipay/global-settings/tab:pages', $pages_fields );
|
||||
|
||||
$global = array(
|
||||
'General' => array(
|
||||
$tabs_config = [
|
||||
'General' => [
|
||||
'name' => __( 'General', 'formipay' ),
|
||||
'fields' => $general_fields
|
||||
),
|
||||
'Pages' => array(
|
||||
],
|
||||
'Pages' => [
|
||||
'name' => __( 'Pages', 'formipay' ),
|
||||
'fields' => $pages_fields
|
||||
)
|
||||
);
|
||||
]
|
||||
];
|
||||
|
||||
$global = apply_filters( 'formipay/global-settings', $global );
|
||||
// Allow other modules to add/modify tabs
|
||||
$tabs_config = apply_filters( 'formipay/global-settings', $tabs_config );
|
||||
|
||||
foreach($global as $key => $value){
|
||||
$fields[$key] = $value;
|
||||
}
|
||||
return $tabs_config;
|
||||
}
|
||||
|
||||
$setups[] = array(
|
||||
'option_name' => 'formipay_settings',
|
||||
'title' => __('Formipay', 'formipay'),
|
||||
'sub_title' => __('Settings', 'formipay'),
|
||||
'logo' => FORMIPAY_URL . 'admin/assets/img/formipay-logo-circle-white.png',
|
||||
'page' => array(
|
||||
'parent_slug' => 'formipay',
|
||||
'page_title' => __('Formipay Settings', 'formipay'),
|
||||
'menu_title' => __('Settings', 'formipay'),
|
||||
'menu_slug' => 'formipay-settings',
|
||||
'position' => 40,
|
||||
),
|
||||
|
||||
'fields' => $fields
|
||||
);
|
||||
|
||||
return $setups;
|
||||
/**
|
||||
* Render settings page (empty container for React)
|
||||
*/
|
||||
public function render_settings_page() {
|
||||
?>
|
||||
<div class="wrap">
|
||||
<div id="formipay-settings-page-container"></div>
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
|
||||
public function enqueue() {
|
||||
|
||||
|
||||
global $current_screen;
|
||||
|
||||
if ( $current_screen->id === 'formipay_page_formipay-settings' ) {
|
||||
wp_enqueue_style('admin-setting-style', FORMIPAY_URL . 'admin/assets/css/global-setting.css', [], FORMIPAY_VERSION, 'all' );
|
||||
wp_enqueue_script('admin-setting-script', FORMIPAY_URL . 'admin/assets/js/admin-setting.js', ['jquery'], FORMIPAY_VERSION, true);
|
||||
// Enqueue React admin assets for FieldRenderer
|
||||
wp_enqueue_script( 'formipay-admin', FORMIPAY_URL . 'build/admin.js', ['react', 'react-dom'], FORMIPAY_VERSION, true );
|
||||
wp_enqueue_style( 'formipay-admin', FORMIPAY_URL . 'build/admin.css', [], FORMIPAY_VERSION, 'all' );
|
||||
}
|
||||
}
|
||||
|
||||
wp_localize_script( 'admin-setting-script', 'formipay_admin_setting', [
|
||||
'ajax_url' => admin_url('admin-ajax.php'),
|
||||
'site_url' => site_url(),
|
||||
'nonce' => wp_create_nonce('formipay-admin-nonce'),
|
||||
'multicurrency' => formipay_is_multi_currency_active(),
|
||||
'all_currencies' => formipay_currency_as_options(),
|
||||
'global_selected_currencies' => formipay_global_currency_options(),
|
||||
'default_currency' => formipay_default_currency()
|
||||
] );
|
||||
/**
|
||||
* Render React settings template in admin footer
|
||||
* This outputs the config JSON and mount point for the React FieldRenderer
|
||||
*/
|
||||
public function render_react_settings_template() {
|
||||
global $current_screen;
|
||||
|
||||
// Only render on settings page
|
||||
if ( $current_screen->id !== 'formipay_page_formipay-settings' ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the configuration for settings
|
||||
$config = FieldConfigBridge::get_config_for_settings('formipay_settings');
|
||||
$config_json = wp_json_encode($config);
|
||||
|
||||
?>
|
||||
<div id="formipay-settings-react" data-formipay-settings-config="<?php echo esc_attr($config_json); ?>"></div>
|
||||
<script>
|
||||
// Move the React mount point to our page container
|
||||
jQuery(document).ready(function($) {
|
||||
$('#formipay-settings-react').appendTo('#formipay-settings-page-container');
|
||||
});
|
||||
</script>
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
* AJAX handler for saving settings from React
|
||||
*/
|
||||
public function ajax_save_settings() {
|
||||
// Verify nonce
|
||||
check_ajax_referer( 'formipay-field-config', 'nonce', true );
|
||||
|
||||
// Check permissions
|
||||
if (!current_user_can('manage_options')) {
|
||||
wp_send_json_error([
|
||||
'message' => __( 'You do not have permission to save settings.', 'formipay' )
|
||||
]);
|
||||
}
|
||||
|
||||
// Get settings data
|
||||
$settings = isset($_POST['settings']) ? json_decode(sanitize_text_field(wp_unslash($_POST['settings'])), true) : [];
|
||||
|
||||
if (empty($settings)) {
|
||||
wp_send_json_error([
|
||||
'message' => __( 'No settings data received.', 'formipay' )
|
||||
]);
|
||||
}
|
||||
|
||||
// Remove nonce from settings before saving
|
||||
unset($settings['nonce']);
|
||||
|
||||
// Get existing settings
|
||||
$existing_settings = get_option('formipay_settings', []);
|
||||
|
||||
// Merge with existing settings to preserve values not in current form
|
||||
$updated_settings = array_merge($existing_settings, $settings);
|
||||
|
||||
// Update option
|
||||
$result = update_option('formipay_settings', $updated_settings);
|
||||
|
||||
if ($result) {
|
||||
wp_send_json_success([
|
||||
'message' => __( 'Settings saved successfully.', 'formipay' )
|
||||
]);
|
||||
} else {
|
||||
wp_send_json_error([
|
||||
'message' => __( 'Failed to save settings.', 'formipay' )
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user