'evqra_paypal_test_connection', 'nonce' => wp_create_nonce('evqra_paypal_test_connection'), 'mode' => strtoupper(get_option('evqra_paypal_mode', 'sandbox')), 'testingText' => __('Testing connection…', 'eventqora'), 'testText' => __('Test PayPal Connection', 'eventqora'), 'verifiedText' => __('Connection verified', 'eventqora'), 'failedText' => __('Connection failed', 'eventqora'), 'successText' => __('PayPal connection verified successfully.', 'eventqora'), 'failureText' => __('PayPal connection test failed.', 'eventqora'), ]) . ';', 'before'); } } public function render_settings_page() { $tabs = [ 'general' => ['label' => __('General', 'eventqora'), 'icon' => '⚙'], 'display' => ['label' => __('Display & Directories', 'eventqora'), 'icon' => '▦'], 'email' => ['label' => __('Email Notifications', 'eventqora'), 'icon' => '✉'], 'google_maps' => ['label' => __('Google Maps API', 'eventqora'), 'icon' => '⌖'], 'paypal' => ['label' => __('PayPal Settings', 'eventqora'), 'icon' => '◈'], ]; $current_tab = filter_input(INPUT_GET, 'tab', FILTER_SANITIZE_SPECIAL_CHARS) ? sanitize_key(wp_unslash(filter_input(INPUT_GET, 'tab', FILTER_SANITIZE_SPECIAL_CHARS))) : 'general'; if (!isset($tabs[$current_tab])) { $current_tab = 'general'; } echo '
'; echo '
'; echo '
' . esc_html__('EventQora', 'eventqora') . ''; echo '

' . esc_html__('Settings', 'eventqora') . '

'; echo '

' . esc_html__('Configure your event calendar, frontend directories, notifications, maps, and payments from one place.', 'eventqora') . '

'; echo '
'; echo ''; echo '
'; settings_errors(); echo '
'; settings_fields('evqra_settings_' . $current_tab); do_settings_sections('evqra-settings-' . $current_tab); echo '
'; echo '
' . esc_html__('Changes are saved per section', 'eventqora') . '' . esc_html__('Review your options, then save when ready.', 'eventqora') . '
'; submit_button(__('Save Changes', 'eventqora'), 'primary evqra-settings-save', 'submit', false); echo '
'; echo '
'; } public function redirect_legacy_settings() { if (!is_admin() || !current_user_can('manage_options')) { return; } if (filter_input(INPUT_GET, 'page', FILTER_SANITIZE_SPECIAL_CHARS) && sanitize_key(wp_unslash(filter_input(INPUT_GET, 'page', FILTER_SANITIZE_SPECIAL_CHARS))) === 'evqra-event-settings') { wp_safe_redirect(admin_url('edit.php?post_type=evqra_event&page=eventqora-settings')); exit; } } public function sanitize_date_format($value) { return sanitize_text_field($value); } public function sanitize_timezone($value) { $value = sanitize_text_field($value); return in_array($value, timezone_identifiers_list(), true) ? $value : wp_timezone_string(); } public function sanitize_default_view($value) { $value = sanitize_key($value); $legacy = ['month-view' => 'month', 'week-view' => 'week', 'day-view' => 'day', 'list-view' => 'list']; $value = $legacy[$value] ?? $value; $allowed = ['month', 'week', 'day', 'list', 'photo', 'map']; return in_array($value, $allowed, true) ? $value : 'month'; } public function sanitize_calendar_time_format($value) { $value = sanitize_key($value); return in_array($value, ['wordpress', '24h', '12h'], true) ? $value : 'wordpress'; } public function sanitize_calendar_enabled_views($value) { $allowed = ['month', 'week', 'day', 'list', 'photo', 'map']; $views = is_array($value) ? array_map('sanitize_key', $value) : []; $views = array_values(array_intersect($allowed, $views)); return $views ? $views : ['month']; } public function sanitize_calendar_category_colors($value) { $value = sanitize_key($value); return in_array($value, ['line', 'background', 'off'], true) ? $value : 'background'; } public function sanitize_events_per_page($value) { return max(1, min(200, absint($value))); } public function sanitize_currency($value) { $value = strtoupper(sanitize_text_field($value)); $allowed = ['USD','EUR','GBP','INR','AUD','CAD','SGD','AED']; return in_array($value, $allowed, true) ? $value : 'USD'; } public function sanitize_bool($value) { return !empty($value) ? 1 : 0; } public function sanitize_google_maps_key($value) { return sanitize_text_field($value); } public function sanitize_zoom($value) { return max(1, min(21, absint($value))); } public function register_settings() { // General Tab register_setting('evqra_settings_general', 'evqra_date_format', ['type' => 'string', 'default' => 'Y-m-d', 'sanitize_callback' => [$this, 'sanitize_date_format']]); register_setting('evqra_settings_general', 'evqra_timezone', ['type' => 'string', 'default' => wp_timezone_string(), 'sanitize_callback' => [$this, 'sanitize_timezone']]); register_setting('evqra_settings_general', 'evqra_currency', ['type' => 'string', 'default' => 'USD', 'sanitize_callback' => [$this, 'sanitize_currency']]); add_settings_section('evqra_general_section', '', null, 'evqra-settings-general'); add_settings_field('evqra_date_format', __('Date Format', 'eventqora'), [$this, 'render_text_input'], 'evqra-settings-general', 'evqra_general_section', [ 'id' => 'evqra_date_format', 'desc' => __('Use PHP date format (e.g., Y-m-d, d/m/Y)', 'eventqora') ]); add_settings_field('evqra_timezone', __('Time Zone', 'eventqora'), [$this, 'render_select_input'], 'evqra-settings-general', 'evqra_general_section', [ 'id' => 'evqra_timezone', 'options' => timezone_identifiers_list() ]); add_settings_field('evqra_currency', __('Currency', 'eventqora'), [$this, 'render_select_input'], 'evqra-settings-general', 'evqra_general_section', [ 'id' => 'evqra_currency', 'options' => ['USD'=>'USD','EUR'=>'EUR','GBP'=>'GBP','INR'=>'INR','AUD'=>'AUD','CAD'=>'CAD','SGD'=>'SGD','AED'=>'AED'] ]); // Display & Directories Tab: calendar controls share the display settings form. register_setting('evqra_settings_display', 'evqra_default_view', ['type' => 'string', 'default' => 'month', 'sanitize_callback' => [$this, 'sanitize_default_view']]); register_setting('evqra_settings_display', 'evqra_events_per_page', ['type' => 'integer', 'default' => 10, 'sanitize_callback' => [$this, 'sanitize_events_per_page']]); register_setting('evqra_settings_display', 'evqra_calendar_time_format', ['type' => 'string', 'default' => 'wordpress', 'sanitize_callback' => [$this, 'sanitize_calendar_time_format']]); register_setting('evqra_settings_display', 'evqra_calendar_enabled_views', ['type' => 'array', 'default' => ['month', 'week', 'list', 'photo', 'map', 'day'], 'sanitize_callback' => [$this, 'sanitize_calendar_enabled_views']]); register_setting('evqra_settings_display', 'evqra_calendar_show_filters', ['type' => 'boolean', 'default' => 1, 'sanitize_callback' => [$this, 'sanitize_bool']]); register_setting('evqra_settings_display', 'evqra_calendar_category_colors', ['type' => 'string', 'default' => 'background', 'sanitize_callback' => [$this, 'sanitize_calendar_category_colors']]); register_setting('evqra_settings_display', 'evqra_calendar_full_event_names', ['type' => 'boolean', 'default' => 0, 'sanitize_callback' => [$this, 'sanitize_bool']]); add_settings_section('evqra_calendar_display_section', '', null, 'evqra-settings-display'); add_settings_field('evqra_calendar_display_settings', '', [$this, 'render_calendar_display_settings'], 'evqra-settings-display', 'evqra_calendar_display_section'); register_setting('evqra_settings_display', 'evqra_directory_settings', [ 'type' => 'array', 'default' => $this->get_directory_defaults(), 'sanitize_callback' => [$this, 'sanitize_directory_settings'], ]); add_settings_section('evqra_directory_section', '', null, 'evqra-settings-display'); add_settings_field('evqra_directory_settings', '', [$this, 'render_directory_settings'], 'evqra-settings-display', 'evqra_directory_section'); // Email Tab register_setting('evqra_settings_email', 'evqra_event_email_settings', [ 'type' => 'array', 'default' => $this->get_email_defaults(), 'sanitize_callback' => [$this, 'sanitize_email_settings'], ]); register_setting('evqra_settings_email', 'evqra_disable_admin_emails', ['type' => 'boolean', 'default' => 0, 'sanitize_callback' => [$this, 'sanitize_bool']]); register_setting('evqra_settings_email', 'evqra_disable_frontend_emails', ['type' => 'boolean', 'default' => 0, 'sanitize_callback' => [$this, 'sanitize_bool']]); add_settings_section('evqra_email_section', '', null, 'evqra-settings-email'); $emails = [ 'user_registration' => 'User Registration Email', 'booking_pending' => 'Booking Pending Email', 'booking_confirmation' => 'Booking Confirmation Email', 'booking_cancellation' => 'Booking Cancellation Email', 'reset_password' => 'Reset Password Email', 'booking_refund' => 'Booking Refund Email', 'frontend_submission' => 'Frontend Event Submission Email', 'frontend_approval' => 'Frontend Submission Approval Email', 'attendee_checkin' => 'Attendee Check-in Email' ]; $default_templates = [ 'user_registration' => [ 'subject' => 'Welcome to {event_name}, {user_name}!', 'content' => 'Hello {user_name},\n\nThank you for registering for {event_name}. We’re excited to have you with us!' // Add more as needed ], 'booking_pending' => [ 'subject' => 'Your booking for {event_name} is pending', 'content' => 'Hi {user_name},\n\nYour booking (ID: {booking_id}) for {event_name} is currently pending. We will notify you upon confirmation.' ], 'booking_confirmation' => [ 'subject' => 'Your booking is confirmed: {event_name}', 'content' => 'Hi {user_name},\n\nGreat news! Your booking for {event_name} is confirmed. Booking ID: {booking_id}.' ], 'booking_cancellation' => [ 'subject' => 'Booking Cancelled for {event_name}', 'content' => 'Hi {user_name},\n\nYour booking for {event_name} (ID: {booking_id}) has been cancelled.' ], 'reset_password' => [ 'subject' => 'Reset Your Password', 'content' => 'Hi {user_name},\n\nTo reset your password, please click the link below.\n\n{reset_link}' ], 'booking_refund' => [ 'subject' => 'Refund Processed for {event_name}', 'content' => 'Hi {user_name},\n\nWe have processed your refund for {event_name}. Booking ID: {booking_id}.' ], 'frontend_submission' => [ 'subject' => 'Event Submission Received', 'content' => 'Hi {user_name},\n\nWe’ve received your event submission: {event_name}. It is currently under review.' ], 'frontend_approval' => [ 'subject' => 'Your Event Has Been Approved', 'content' => 'Hi {user_name},\n\nYour submitted event {event_name} has been approved and published!' ], 'attendee_checkin' => [ 'subject' => 'Check-in recorded: {event_name}', 'content' => 'Hi {user_name},\n\nA check-in was recorded for {event_name}.\nChecked in: {quantity}\nTotal checked in: {checked_in_quantity}' ] ]; foreach ($emails as $key => $label) { add_settings_field($key, esc_html($label), [$this, 'render_email_field'], 'evqra-settings-email', 'evqra_email_section', [ 'key' => $key, 'default' => $default_templates[$key], ]); } add_settings_field('evqra_disable_admin_emails', __('Disable Admin Emails', 'eventqora'), [$this, 'render_disable_admin_emails'], 'evqra-settings-email', 'evqra_email_section'); add_settings_field('evqra_disable_frontend_emails', __('Disable Frontend Emails', 'eventqora'), [$this, 'render_disable_frontend_emails'], 'evqra-settings-email', 'evqra_email_section'); // Google Maps Tab register_setting('evqra_settings_google_maps', 'evqra_google_maps_api_key', ['type' => 'string', 'default' => '', 'sanitize_callback' => [$this, 'sanitize_google_maps_key']]); register_setting('evqra_settings_google_maps', 'evqra_google_maps_zoom', ['type' => 'integer', 'default' => 15, 'sanitize_callback' => [$this, 'sanitize_zoom']]); register_setting('evqra_settings_google_maps', 'evqra_google_maps_enabled', ['type' => 'boolean', 'default' => 0, 'sanitize_callback' => [$this, 'sanitize_bool']]); add_settings_section('evqra_google_maps_section', '', null, 'evqra-settings-google_maps'); // API Key add_settings_field('evqra_google_maps_api_key', __('API Key', 'eventqora'), [$this, 'render_text_input'], 'evqra-settings-google_maps', 'evqra_google_maps_section', [ 'id' => 'evqra_google_maps_api_key', 'desc' => __('Enter your Google Maps Embed API key.', 'eventqora') ]); // Zoom add_settings_field('evqra_google_maps_zoom', __('Default Zoom Level', 'eventqora'), [$this, 'render_text_input'], 'evqra-settings-google_maps', 'evqra_google_maps_section', [ 'id' => 'evqra_google_maps_zoom', 'desc' => __('Recommended between 10–18. Default is 15.', 'eventqora') ]); // Enabled Toggle add_settings_field('evqra_google_maps_enabled', __('Enable Map Display', 'eventqora'), [$this, 'render_checkbox_input'], 'evqra-settings-google_maps', 'evqra_google_maps_section'); // PayPal Tab register_setting('evqra_settings_paypal', 'evqra_paypal_enabled', [ 'type' => 'boolean', 'default' => 0, 'sanitize_callback' => function ($value) { return !empty($value) ? 1 : 0; }, ]); register_setting('evqra_settings_paypal', 'evqra_paypal_mode', [ 'type' => 'string', 'default' => 'sandbox', 'sanitize_callback' => function ($value) { return $value === 'live' ? 'live' : 'sandbox'; }, ]); register_setting('evqra_settings_paypal', 'evqra_paypal_sandbox_client_id', [ 'type' => 'string', 'default' => '', 'sanitize_callback' => [$this, 'sanitize_paypal_credential'], ]); register_setting('evqra_settings_paypal', 'evqra_paypal_sandbox_secret', [ 'type' => 'string', 'default' => '', 'sanitize_callback' => [$this, 'sanitize_paypal_credential'], ]); register_setting('evqra_settings_paypal', 'evqra_paypal_live_client_id', [ 'type' => 'string', 'default' => '', 'sanitize_callback' => [$this, 'sanitize_paypal_credential'], ]); register_setting('evqra_settings_paypal', 'evqra_paypal_live_secret', [ 'type' => 'string', 'default' => '', 'sanitize_callback' => [$this, 'sanitize_paypal_credential'], ]); register_setting('evqra_settings_paypal', 'evqra_paypal_webhook_id', [ 'type' => 'string', 'default' => '', 'sanitize_callback' => [$this, 'sanitize_paypal_webhook_id'], ]); add_settings_section('evqra_paypal_section', '', null, 'evqra-settings-paypal'); add_settings_field('evqra_paypal_enabled', __('Enable PayPal Payments', 'eventqora'), [$this, 'render_paypal_enabled'], 'evqra-settings-paypal', 'evqra_paypal_section'); // Mode add_settings_field('evqra_paypal_mode', __('PayPal Mode', 'eventqora'), [$this, 'render_select_input'], 'evqra-settings-paypal', 'evqra_paypal_section', [ 'id' => 'evqra_paypal_mode', 'options' => [ 'sandbox' => 'Sandbox', 'live' => 'Live' ], 'desc' => __('Select whether to use PayPal in Sandbox (testing) or Live mode for transactions.', 'eventqora') ]); // Sandbox Client ID add_settings_field('evqra_paypal_sandbox_client_id', __('Sandbox Client ID', 'eventqora'), [$this, 'render_text_input'], 'evqra-settings-paypal', 'evqra_paypal_section', [ 'id' => 'evqra_paypal_sandbox_client_id', 'desc' => __('Enter your PayPal Sandbox Client ID.', 'eventqora') ]); // Sandbox Secret add_settings_field('evqra_paypal_sandbox_secret', __('Sandbox Secret', 'eventqora'), [$this, 'render_text_input'], 'evqra-settings-paypal', 'evqra_paypal_section', [ 'id' => 'evqra_paypal_sandbox_secret', 'desc' => __('Enter your PayPal Sandbox Secret.', 'eventqora') ]); // Live Client ID add_settings_field('evqra_paypal_live_client_id', __('Live Client ID', 'eventqora'), [$this, 'render_text_input'], 'evqra-settings-paypal', 'evqra_paypal_section', [ 'id' => 'evqra_paypal_live_client_id', 'desc' => __('Enter your PayPal Live Client ID.', 'eventqora') ]); // Live Secret add_settings_field('evqra_paypal_live_secret', __('Live Secret', 'eventqora'), [$this, 'render_text_input'], 'evqra-settings-paypal', 'evqra_paypal_section', [ 'id' => 'evqra_paypal_live_secret', 'desc' => __('Enter your PayPal Live Secret.', 'eventqora') ]); add_settings_field('evqra_paypal_webhook_id', __('PayPal Webhook ID', 'eventqora'), [$this, 'render_text_input'], 'evqra-settings-paypal', 'evqra_paypal_section', [ 'id' => 'evqra_paypal_webhook_id', 'desc' => __('Enter the webhook ID created in your PayPal Developer Dashboard. It is required for signed webhook verification.', 'eventqora') ]); add_settings_field('evqra_paypal_status', __('Configuration Status', 'eventqora'), [$this, 'render_paypal_status'], 'evqra-settings-paypal', 'evqra_paypal_section'); add_settings_field('evqra_paypal_help_note', '', function () { echo '

Need help creating PayPal credentials?
'; echo 'Visit the PayPal Developer Dashboard to create or manage your sandbox and live API credentials.

'; }, 'evqra-settings-paypal', 'evqra_paypal_section'); } private function get_directory_defaults() { return [ 'show_view_switcher' => 1, 'categories' => [ 'view' => 'cards', 'per_page' => 24, 'columns' => 3, 'show_images' => 1, 'show_count' => 1, 'show_meta' => 1, ], 'venues' => [ 'view' => 'cards', 'per_page' => 24, 'columns' => 3, 'show_images' => 1, 'show_count' => 1, 'show_meta' => 1, ], 'organizers' => [ 'view' => 'cards', 'per_page' => 24, 'columns' => 3, 'show_images' => 1, 'show_count' => 1, 'show_meta' => 1, ], ]; } public function sanitize_directory_settings($input) { $defaults = $this->get_directory_defaults(); $input = is_array($input) ? $input : []; $output = ['show_view_switcher' => !empty($input['show_view_switcher']) ? 1 : 0]; foreach (['categories', 'venues', 'organizers'] as $type) { $row = isset($input[$type]) && is_array($input[$type]) ? $input[$type] : []; $view = isset($row['view']) ? sanitize_key($row['view']) : $defaults[$type]['view']; if (!in_array($view, ['cards', 'list', 'compact'], true)) { $view = $defaults[$type]['view']; } $per_page = isset($row['per_page']) ? absint($row['per_page']) : $defaults[$type]['per_page']; $columns = isset($row['columns']) ? absint($row['columns']) : $defaults[$type]['columns']; $output[$type] = [ 'view' => $view, 'per_page' => max(1, min(100, $per_page)), 'columns' => max(2, min(4, $columns)), 'show_images' => !empty($row['show_images']) ? 1 : 0, 'show_count' => !empty($row['show_count']) ? 1 : 0, 'show_meta' => !empty($row['show_meta']) ? 1 : 0, ]; } return $output; } public function render_calendar_display_settings() { $view = get_option('evqra_default_view', 'month'); $view = sanitize_key($view); $legacy_views = ['month-view' => 'month', 'week-view' => 'week', 'day-view' => 'day', 'list-view' => 'list']; $view = $legacy_views[$view] ?? $view; if (!in_array($view, ['month', 'week', 'day', 'list', 'photo', 'map'], true)) { $view = 'month'; } $per_page = max(1, min(200, absint(get_option('evqra_events_per_page', 10)))); $time_format = get_option('evqra_calendar_time_format', 'wordpress'); $time_formats = [ 'wordpress' => sprintf(__('Same as WordPress (%s)', 'eventqora'), wp_date(get_option('time_format'), time())), '24h' => sprintf(__('24-hour (%s)', 'eventqora'), wp_date('H:i', time())), '12h' => sprintf(__('12-hour (%s)', 'eventqora'), wp_date('g:i a', time())), ]; ?>

__('Month', 'eventqora'), 'week' => __('Week', 'eventqora'), 'list' => __('List', 'eventqora'), 'photo' => __('Photo', 'eventqora'), 'map' => __('Map', 'eventqora'), 'day' => __('Day', 'eventqora')] as $key => $label) : ?>
render_calendar_checkbox('evqra_calendar_show_filters', __('Show search and filters (category, venue, organizer) above the calendar', 'eventqora'), 1); ?> render_calendar_checkbox('evqra_calendar_full_event_names', __('Show full event names in the month view, wrapping long names onto more lines instead of cutting them short', 'eventqora'), 0); ?>

render_calendar_checkbox('evqra_calendar_show_weekends', __('Show weekends', 'eventqora'), 1); ?> render_calendar_checkbox('evqra_calendar_show_event_end', __('Show event end time', 'eventqora'), 1); ?>
'; echo ''; } public function render_directory_settings() { $settings = wp_parse_args(get_option('evqra_directory_settings', []), $this->get_directory_defaults()); $labels = [ 'categories' => [ 'title' => __('Categories', 'eventqora'), 'description' => __('Control how visitors browse your event categories.', 'eventqora'), ], 'venues' => [ 'title' => __('Venues', 'eventqora'), 'description' => __('Choose the presentation for venue discovery pages.', 'eventqora'), ], 'organizers' => [ 'title' => __('Organizers', 'eventqora'), 'description' => __('Choose the presentation for organizer discovery pages.', 'eventqora'), ], ]; echo '
' . esc_html__('Frontend experience', 'eventqora') . '

' . esc_html__('Directory presentation', 'eventqora') . '

' . esc_html__('Set the default layout for Categories, Venues, and Organizers. Visitors can optionally switch layouts from the frontend.', 'eventqora') . '

'; echo '
'; echo '
'; foreach ($labels as $type => $label) { $row = wp_parse_args($settings[$type] ?? [], $this->get_directory_defaults()[$type]); echo '
'; echo '
' . esc_html($type === 'categories' ? '◈' : ($type === 'venues' ? '⌖' : '◎')) . '

' . esc_html($label['title']) . '

' . esc_html($label['description']) . '

'; echo '
'; echo ''; echo ''; echo ''; echo '
'; echo ''; echo ''; echo ''; echo '
'; } echo '
'; echo '
' . esc_html__('Shortcode overrides still work.', 'eventqora') . ' ' . esc_html__('Use the shortcode attributes when a specific page needs a different result from the global default.', 'eventqora') . '
'; } /** * Preserve PayPal credential characters while removing surrounding whitespace. * PayPal secrets are opaque values and must not be passed through sanitize_text_field(). */ public function sanitize_paypal_credential($value) { return is_string($value) ? trim($value) : ''; } /** * PayPal webhook IDs are opaque provider identifiers. */ public function sanitize_paypal_webhook_id($value) { return is_string($value) ? sanitize_text_field(trim($value)) : ''; } /** * Return a non-secret fingerprint for the currently selected PayPal configuration. */ private function paypal_connection_fingerprint($mode, $client, $secret) { return wp_hash($mode . "\0" . $client . "\0" . $secret, 'auth'); } public function render_paypal_enabled() { $enabled = (bool) get_option('evqra_paypal_enabled', 1); ?>

paypal_connection_fingerprint($mode, $client, $secret) : ''; $saved_fingerprint = (string) get_option('evqra_paypal_connection_fingerprint', ''); $connection_state = (string) get_option('evqra_paypal_connection_status', ''); $verified_for_current_credentials = $ready && $saved_fingerprint !== '' && hash_equals($saved_fingerprint, $fingerprint); if (!$enabled) { $label = __('Disabled', 'eventqora'); $class = 'evqra-paypal-status evqra-paypal-status--disabled'; } elseif (!$ready) { $label = __('Action required', 'eventqora'); $class = 'evqra-paypal-status evqra-paypal-status--warning'; } elseif ($verified_for_current_credentials && $connection_state === 'verified') { $label = __('Connection verified', 'eventqora'); $class = 'evqra-paypal-status evqra-paypal-status--ready'; } elseif ($verified_for_current_credentials && $connection_state === 'failed') { $label = __('Connection failed', 'eventqora'); $class = 'evqra-paypal-status evqra-paypal-status--warning'; } else { $label = __('Credentials configured', 'eventqora'); $class = 'evqra-paypal-status evqra-paypal-status--warning'; } echo '' . esc_html($label) . '' . esc_html(strtoupper($mode)) . ''; if ($ready) { echo '

'; echo '

' . esc_html__('Tests OAuth authentication using the saved credentials. No order is created and no payment data is changed.', 'eventqora') . '

'; if ($verified_for_current_credentials && $connection_state === 'verified') { echo '

' . esc_html__('The saved credentials were verified for this environment. Re-run the test after changing credentials or switching environments.', 'eventqora') . '

'; } echo '

'; ?> ' . esc_html__('Add the selected environment Client ID and Secret, save settings, then test the connection before accepting payments.', 'eventqora') . '

'; } } public function render_text_input($args) { $defaults = [ 'evqra_date_format' => 'Y-m-d', 'evqra_events_per_page' => '10' ]; $value = get_option($args['id'], $defaults[$args['id']] ?? ''); $type = strpos($args['id'] ?? '', 'secret') !== false ? 'password' : 'text'; echo ''; if (!empty($args['desc'])) { echo '

' . esc_html($args['desc']) . '

'; } } public function render_select_input($args) { $id = isset($args['id']) ? $args['id'] : ''; $options = isset($args['options']) && is_array($args['options']) ? $args['options'] : []; $value = get_option($id, ''); echo ''; if (!empty($args['desc'])) { echo '

' . wp_kses_post($args['desc']) . '

'; } } public function render_checkbox_input($args) { $value = get_option('evqra_google_maps_enabled', 0); ?> get_email_defaults(); $settings = get_option('evqra_event_email_settings', []); if (!is_array($settings)) { $settings = []; } $changed = false; foreach ($defaults as $key => $default) { if (!isset($settings[$key]) || !is_array($settings[$key])) { $settings[$key] = $default; $changed = true; continue; } if (!isset($settings[$key]['enabled'])) { $settings[$key]['enabled'] = $default['enabled']; $changed = true; } if (empty($settings[$key]['subject'])) { $settings[$key]['subject'] = $default['subject']; $changed = true; } if (empty($settings[$key]['content'])) { $settings[$key]['content'] = $default['content']; $changed = true; } } if ($changed) { update_option('evqra_event_email_settings', $settings); } } public function get_email_defaults() { return [ 'user_registration' => [ 'enabled' => 0, 'subject' => 'Welcome to {event_name}, {user_name}!', 'content' => "Hello {user_name},\n\nThank you for registering for {event_name}. We’re excited to have you with us!", ], 'booking_pending' => [ 'enabled' => 1, 'subject' => 'Your booking for {event_name} is pending', 'content' => "Hi {user_name},\n\nYour booking (ID: {booking_id}) for {event_name} is currently pending. We will notify you upon confirmation.", ], 'booking_confirmation' => [ 'enabled' => 1, 'subject' => 'Your booking is confirmed: {event_name}', 'content' => "Hi {user_name},\n\nGreat news! Your booking for {event_name} is confirmed. Booking ID: {booking_id}.", ], 'booking_cancellation' => [ 'enabled' => 1, 'subject' => 'Booking Cancelled for {event_name}', 'content' => "Hi {user_name},\n\nYour booking for {event_name} (ID: {booking_id}) has been cancelled.", ], 'reset_password' => [ 'enabled' => 0, 'subject' => 'Reset Your Password', 'content' => "Hi {user_name},\n\nTo reset your password, please click the link below.\n\n{reset_link}", ], 'booking_refund' => [ 'enabled' => 1, 'subject' => 'Refund Processed for {event_name}', 'content' => "Hi {user_name},\n\nWe have processed your refund for {event_name}. Booking ID: {booking_id}.", ], 'frontend_submission' => [ 'enabled' => 0, 'subject' => 'Event Submission Received', 'content' => "Hi {user_name},\n\nWe’ve received your event submission: {event_name}. It is currently under review.", ], 'frontend_approval' => [ 'enabled' => 0, 'subject' => 'Your Event Has Been Approved', 'content' => "Hi {user_name},\n\nYour submitted event {event_name} has been approved and published!", ], 'attendee_checkin' => [ 'enabled' => 0, 'subject' => 'Check-in recorded: {event_name}', 'content' => "Hi {user_name},\n\nA check-in was recorded for {event_name}.\nChecked in: {quantity}\nTotal checked in: {checked_in_quantity}", ], ]; } public function sanitize_email_settings($input) { $defaults = $this->get_email_defaults(); $input = is_array($input) ? $input : []; $output = []; foreach ($defaults as $key => $default) { $row = isset($input[$key]) && is_array($input[$key]) ? $input[$key] : []; $subject = isset($row['subject']) ? sanitize_text_field($row['subject']) : ''; $content = isset($row['content']) ? sanitize_textarea_field($row['content']) : ''; $output[$key] = [ 'enabled' => !empty($row['enabled']) ? 1 : 0, // Keep a useful template whenever the administrator leaves a field empty. 'subject' => $subject !== '' ? $subject : $default['subject'], 'content' => $content !== '' ? $content : $default['content'], ]; } return $output; } public function render_email_field($args) { $defaults = $this->get_email_defaults(); $options = get_option('evqra_event_email_settings', []); $key = sanitize_key($args['key'] ?? ''); $data = isset($options[$key]) && is_array($options[$key]) ? wp_parse_args($options[$key], $defaults[$key] ?? []) : ($defaults[$key] ?? []); // Treat an explicitly empty saved field as "use the default template". if (isset($defaults[$key])) { if (empty($data['subject'])) { $data['subject'] = $defaults[$key]['subject']; } if (empty($data['content'])) { $data['content'] = $defaults[$key]['content']; } } $enabled = !empty($data['enabled']); $labels = [ 'user_registration' => __('User Registration Email', 'eventqora'), 'booking_pending' => __('Booking Pending Email', 'eventqora'), 'booking_confirmation' => __('Booking Confirmation Email', 'eventqora'), 'booking_cancellation' => __('Booking Cancellation Email', 'eventqora'), 'reset_password' => __('Reset Password Email', 'eventqora'), 'booking_refund' => __('Booking Refund Email', 'eventqora'), 'frontend_submission' => __('Frontend Event Submission Email', 'eventqora'), 'frontend_approval' => __('Frontend Submission Approval Email', 'eventqora'), 'attendee_checkin' => __('Attendee Check-in Email', 'eventqora'), ]; $status = $enabled ? __('Enabled', 'eventqora') : __('Disabled', 'eventqora'); $event_names = [ 'user_registration' => __('Account / registration', 'eventqora'), 'booking_pending' => __('Booking lifecycle', 'eventqora'), 'booking_confirmation' => __('Booking lifecycle', 'eventqora'), 'booking_cancellation' => __('Booking lifecycle', 'eventqora'), 'reset_password' => __('Account / password', 'eventqora'), 'booking_refund' => __('Payment / refund', 'eventqora'), 'frontend_submission' => __('Frontend submissions', 'eventqora'), 'frontend_approval' => __('Frontend submissions', 'eventqora'), 'attendee_checkin' => __('Attendee check-in', 'eventqora'), ]; $future_notifications = [ 'user_registration', 'reset_password', 'frontend_submission', 'frontend_approval', ]; $is_future = in_array($key, $future_notifications, true); $description = $event_names[$key] ?? __('Notification', 'eventqora'); ?>
>
0