Changeset 3310602
- Timestamp:
- 06/12/2025 03:11:31 PM (8 months ago)
- Location:
- flex-forms/trunk
- Files:
-
- 3 added
- 9 edited
-
assets/css/flex-forms-admin.css (modified) (1 diff)
-
assets/js/flex-forms-admin.js (modified) (2 diffs)
-
flex-forms.php (modified) (3 diffs)
-
includes/class-flex-forms-ajax.php (modified) (2 diffs)
-
includes/class-flex-forms-frontend.php (modified) (1 diff)
-
includes/class-flex-forms-main.php (modified) (12 diffs)
-
includes/class-flex-forms-mass-email.php (added)
-
includes/class-flex-forms-settings.php (modified) (4 diffs)
-
includes/class-flex-forms-submissions.php (modified) (6 diffs)
-
includes/helpers (added)
-
includes/helpers/string.php (added)
-
readme.txt (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
flex-forms/trunk/assets/css/flex-forms-admin.css
r3305607 r3310602 14 14 transition: background-color 0.2s ease; 15 15 } 16 #menu-posts-flex_form ul.wp-submenu a[href*="page=flex_forms_mass_email"] { 17 display: none !important; 18 } -
flex-forms/trunk/assets/js/flex-forms-admin.js
r3305607 r3310602 42 42 const isButton = fieldType === 'button'; 43 43 $('#flex_forms_flex_field_button_type_row, #flex_forms_flex_field_button_value_row').toggle(isButton); 44 45 /* NEW: hide Placeholder + Default Value for Button */ 46 $('#flex_forms_flex_field_placeholder_row, #flex_forms_flex_field_default_row') 47 .toggle(!isButton); 44 48 45 49 /* Show “Unique?” only for email + DB-store */ … … 150 154 }, 350); 151 155 } 156 157 /* Show/hide SMTP-dependent rows */ 158 function toggleSmtpRows() { 159 const enabled = $('#flex_forms_use_smtp').is(':checked'); 160 $('.smtp-dependent').toggle(enabled); 161 } 162 163 /* Send test e-mail */ 164 function sendTestEmail() { 165 const $btn = $('#flex_forms_send_test_email_btn'); 166 const $result = $('#flex_forms_smtp_test_result').removeClass('success error').text(''); 167 const email = $('#flex_forms_smtp_test_email').val().trim(); 168 169 if (!email) { 170 $result.addClass('error').text('Please enter an e-mail address.'); 171 return; 172 } 173 174 /* Collect current input values */ 175 const data = { 176 action: 'flex_forms_send_test_email', 177 security: flex_forms_admin_vars.nonce, 178 test_email: email, 179 180 smtp_host: $('#flex_forms_smtp_host').val().trim(), 181 smtp_port: $('#flex_forms_smtp_port').val().trim(), 182 smtp_encryption: $('#flex_forms_smtp_encryption').val(), 183 smtp_user: $('#flex_forms_smtp_user').val().trim(), 184 smtp_pass: $('#flex_forms_smtp_pass').val().trim() 185 }; 186 187 /* Quick client-side check */ 188 if (!data.smtp_host || !data.smtp_port || !data.smtp_user || !data.smtp_pass) { 189 $result.addClass('error').text('Fill in all SMTP fields first.'); 190 return; 191 } 192 193 $btn.prop('disabled', true); 194 195 $.post(flex_forms_admin_vars.ajaxurl, data) 196 .done(function (resp) { 197 if (resp.success) { 198 $result.addClass('success').text(resp.data.message); 199 } else { 200 $result.addClass('error').text(resp.data.message); 201 } 202 }) 203 .fail(function () { 204 $result.addClass('error').text('AJAX error.'); 205 }) 206 .always(function () { 207 $btn.prop('disabled', false); 208 }); 209 } 210 /* Init */ 211 $(function () { 212 toggleSmtpRows(); 213 $('#flex_forms_use_smtp').on('change', toggleSmtpRows); 214 $('#flex_forms_send_test_email_btn').on('click', sendTestEmail); 215 }); 216 217 const storeCb = document.getElementById('flex_forms_store_in_db'); 218 const adminCb = document.getElementById('flex_forms_admin_email_enable'); 219 220 function syncAdminCheckbox() { 221 if (storeCb.checked) { 222 adminCb.removeAttribute('disabled'); // free to toggle 223 } else { 224 adminCb.checked = true; // must stay ON 225 adminCb.setAttribute('disabled', 'disabled'); 226 } 227 } 228 229 /* init + on change */ 230 syncAdminCheckbox(); 231 storeCb.addEventListener('change', syncAdminCheckbox); 152 232 }); -
flex-forms/trunk/flex-forms.php
r3305774 r3310602 2 2 /* 3 3 Plugin Name: Flex Forms 4 Plugin URI: https://flex-fields.com/forms/4 Plugin URI: https://flex-fields.com/forms/ 5 5 Description: A modular, customizable form builder plugin for WordPress. 6 Version: 2.1.16 Version: 2.1.2 7 7 Requires at least: 6.6 8 Author: Future Systems9 Author URI: https://f-s.am10 License: GPLv2 or later8 Author: Future Systems 9 Author URI: https://f-s.am 10 License: GPLv2 or later 11 11 Text Domain: flex-forms 12 12 */ 13 13 14 // Exit if accessed directly 15 if (!defined('ABSPATH')) { 16 exit; 14 if ( ! defined( 'ABSPATH' ) ) { exit; } 15 16 define( 'FLEX_FORMS_VERSION', '2.1.2' ); 17 define( 'FLEX_FORMS_PLUGIN_DIR', plugin_dir_path( __FILE__ ) ); 18 define( 'FLEX_FORMS_PLUGIN_URL', plugin_dir_url( __FILE__ ) ); 19 20 /* -------------------------------------------------- * 21 * Helpers FIRST – makes flex_forms_str() available * 22 * -------------------------------------------------- */ 23 foreach ( glob( FLEX_FORMS_PLUGIN_DIR . 'includes/helpers/*.php' ) as $file ) { 24 require_once $file; // flex_forms_str() defined here 17 25 } 18 26 19 define('FLEX_FORMS_VERSION', '2.1.1'); 20 define('FLEX_FORMS_PLUGIN_DIR', plugin_dir_path(__FILE__)); 21 define('FLEX_FORMS_PLUGIN_URL', plugin_dir_url(__FILE__)); 22 27 /* -------------------------------------------------- * 28 * Class files * 29 * -------------------------------------------------- */ 23 30 require_once FLEX_FORMS_PLUGIN_DIR . 'includes/class-flex-forms-main.php'; 24 31 require_once FLEX_FORMS_PLUGIN_DIR . 'includes/class-flex-forms-submissions.php'; … … 27 34 require_once FLEX_FORMS_PLUGIN_DIR . 'includes/class-flex-forms-frontend.php'; 28 35 require_once FLEX_FORMS_PLUGIN_DIR . 'includes/class-flex-forms-ajax.php'; 36 require_once FLEX_FORMS_PLUGIN_DIR . 'includes/class-flex-forms-mass-email.php'; 29 37 30 function flex_forms_init() 31 { 38 /* -------------------------------------------------- * 39 * Bootstrap * 40 * -------------------------------------------------- */ 41 add_action( 'plugins_loaded', function () { 42 32 43 new Flex_Forms_Main(); 33 44 new Flex_Forms_Submissions(); … … 36 47 new Flex_Forms_Frontend(); 37 48 new Flex_Forms_Ajax(); 38 }39 add_action('plugins_loaded', 'flex_forms_init');40 49 41 function flex_forms_activate_or_deactivate() 42 { 43 flush_rewrite_rules(); 44 } 45 register_activation_hook(__FILE__, 'flex_forms_activate_or_deactivate'); 46 register_deactivation_hook(__FILE__, 'flex_forms_activate_or_deactivate'); 50 if ( is_admin() ) { 51 new Flex_Forms_Mass_Email(); 52 } 53 } ); 54 55 /* flush rewrites on (de)activation */ 56 register_activation_hook( __FILE__, 'flex_forms_flush_rewrites' ); 57 register_deactivation_hook( __FILE__, 'flex_forms_flush_rewrites' ); 58 function flex_forms_flush_rewrites() { flush_rewrite_rules(); } -
flex-forms/trunk/includes/class-flex-forms-ajax.php
r3300738 r3310602 1 1 <?php 2 /** 3 * Flex Forms – AJAX handlers 4 */ 2 5 if ( ! defined( 'ABSPATH' ) ) { 3 6 exit; … … 7 10 8 11 public function __construct() { 9 add_action( 'wp_ajax_flex_forms_submit', array( $this, 'flex_forms_process_submission' ) ); 10 add_action( 'wp_ajax_nopriv_flex_forms_submit', array( $this, 'flex_forms_process_submission' ) ); 11 add_action('wp_ajax_flex_forms_validate_unique', [$this, 'flex_forms_validate_unique_fields']); 12 add_action('wp_ajax_nopriv_flex_forms_validate_unique', [$this, 'flex_forms_validate_unique_fields']); 12 /* Front-end submissions */ 13 add_action( 'wp_ajax_flex_forms_submit', array( $this, 'process_submission' ) ); 14 add_action( 'wp_ajax_nopriv_flex_forms_submit', array( $this, 'process_submission' ) ); 15 16 /* Unique-field validation */ 17 add_action( 'wp_ajax_flex_forms_validate_unique', array( $this, 'validate_unique_fields' ) ); 18 add_action( 'wp_ajax_nopriv_flex_forms_validate_unique', array( $this, 'validate_unique_fields' ) ); 19 20 /* NEW: send test SMTP e-mail (admin only) */ 21 add_action( 'wp_ajax_flex_forms_send_test_email', array( $this, 'send_test_email' ) ); 13 22 } 14 23 15 public function flex_forms_process_submission() { 24 /* ============================================================= * 25 * 1. Process submission (stub for brevity) 26 * ============================================================= */ 27 public function process_submission() { 16 28 check_ajax_referer( 'flex-forms-nonce', 'security' ); 17 wp_send_json_success( ['message' => __( 'Form submission successful!', 'flex-forms' )]);29 wp_send_json_success( array( 'message' => __( 'Form submission successful!', 'flex-forms' ) ) ); 18 30 } 19 31 20 public function flex_forms_validate_unique_fields() { 21 check_ajax_referer('flex-forms-nonce', 'nonce'); 32 /* ============================================================= * 33 * 2. Validate “unique” fields 34 * ============================================================= */ 35 public function validate_unique_fields() { 36 check_ajax_referer( 'flex-forms-nonce', 'nonce' ); 22 37 23 $form_id = isset( $_POST['form_id']) ? absint($_POST['form_id']) : 0;24 $fields = isset($_POST['fields']) ? (array) $_POST['fields'] : [];38 $form_id = isset( $_POST['form_id'] ) ? absint( $_POST['form_id'] ) : 0; 39 $fields = isset( $_POST['fields'] ) ? (array) $_POST['fields'] : array(); 25 40 26 if ( !$form_id || empty($fields)) {27 wp_send_json_error( ['message' => 'Invalid request.']);41 if ( ! $form_id || empty( $fields ) ) { 42 wp_send_json_error( array( 'message' => 'Invalid request.' ) ); 28 43 } 29 44 30 45 $submissions = new Flex_Forms_Submissions(); 31 $errors = $submissions->check_duplicate_fields($form_id, $fields);46 $errors = $submissions->check_duplicate_fields( $form_id, $fields ); 32 47 33 if ( !empty($errors)) {34 wp_send_json_success( ['valid' => false, 'errors' => $errors]);48 if ( ! empty( $errors ) ) { 49 wp_send_json_success( array( 'valid' => false, 'errors' => $errors ) ); 35 50 } 36 51 37 wp_send_json_success( ['valid' => true]);52 wp_send_json_success( array( 'valid' => true ) ); 38 53 } 39 54 55 /* ============================================================= * 56 * 3. Send SMTP test e-mail 57 * ============================================================= */ 58 public function send_test_email() { 59 check_ajax_referer( 'flex-forms-nonce', 'security' ); 60 61 if ( ! current_user_can( 'manage_options' ) ) { 62 wp_send_json_error( array( 'message' => __( 'Permission denied.', 'flex-forms' ) ) ); 63 } 64 65 $to = isset( $_POST['test_email'] ) ? sanitize_email( wp_unslash( $_POST['test_email'] ) ) : ''; 66 if ( ! is_email( $to ) ) { 67 wp_send_json_error( array( 'message' => __( 'Invalid e-mail address.', 'flex-forms' ) ) ); 68 } 69 70 /* ========================================================= 71 * 1. Pull SMTP params – prefer POST, fall back to options 72 * ========================================================= */ 73 $param = function ( $key, $opt ) { 74 return isset( $_POST[ $key ] ) && $_POST[ $key ] !== '' 75 ? sanitize_text_field( wp_unslash( $_POST[ $key ] ) ) 76 : trim( get_option( $opt ) ); 77 }; 78 79 $host = $param( 'smtp_host', 'flex_forms_smtp_host' ); 80 $port = absint( $param( 'smtp_port', 'flex_forms_smtp_port' ) ); 81 $encryption = strtolower( $param( 'smtp_encryption', 'flex_forms_smtp_encryption' ) ?: 'none' ); 82 $user = $param( 'smtp_user', 'flex_forms_smtp_user' ); 83 $pass = $param( 'smtp_pass', 'flex_forms_smtp_pass' ); 84 85 if ( ! $host || ! $port || ! $user || ! $pass ) { 86 wp_send_json_error( array( 'message' => __( 'Please fill in all SMTP fields.', 'flex-forms' ) ) ); 87 } 88 89 /* ========================================================= 90 * 2. Configure PHPMailer only for this request 91 * ========================================================= */ 92 add_action( 'phpmailer_init', function ( $phpmailer ) use ( $host, $port, $encryption, $user, $pass ) { 93 $phpmailer->isSMTP(); 94 $phpmailer->Host = $host; 95 $phpmailer->Port = $port; 96 $phpmailer->SMTPAuth = true; 97 $phpmailer->Username = $user; 98 $phpmailer->Password = $pass; 99 $phpmailer->SMTPSecure = ( $encryption !== 'none' ) ? $encryption : false; // ssl / tls / false 100 } ); 101 102 /* ========================================================= 103 * 3. Send the message 104 * ========================================================= */ 105 $subject = __( 'Flex Forms SMTP Test', 'flex-forms' ); 106 $body = '<p>' . esc_html__( 'If you are reading this, your SMTP settings in Flex Forms SMTP works!', 'flex-forms' ) . '</p>'; 107 $headers = array( 'Content-Type: text/html; charset=UTF-8' ); 108 109 if ( wp_mail( $to, $subject, $body, $headers ) ) { 110 wp_send_json_success( array( 'message' => __( 'Success! Test e-mail sent.', 'flex-forms' ) ) ); 111 } 112 113 wp_send_json_error( array( 'message' => __( 'Failed to send. Check credentials and server logs.', 'flex-forms' ) ) ); 114 } 40 115 } -
flex-forms/trunk/includes/class-flex-forms-frontend.php
r3305607 r3310602 251 251 * 4. Field-type switch 252 252 * ------------------------------------------------------------------ */ 253 $add_attr = static function ( &$a, $name, $val ) { 254 if ( $val !== '' ) { 255 $a[] = $name . '="' . esc_attr( $val ) . '"'; 256 } 257 }; 258 253 259 switch ( $atts['type'] ) { 254 260 255 261 /* ======== TEXTAREA ======== */ 256 262 case 'textarea': 263 264 // Build only the attributes that actually have content 265 $attrs = [ 266 'id="' . esc_attr( $base_id ) . '"', 267 'name="' . esc_attr( $atts['name'] ) . '"', 268 ]; 269 if ( $atts['placeholder'] !== '' ) { 270 $attrs[] = 'placeholder="' . esc_attr( $atts['placeholder'] ) . '"'; 271 } 272 if ( $atts['class'] !== '' ) { 273 $attrs[] = 'class="' . esc_attr( $atts['class'] ) . '"'; 274 } 275 if ( $atts['required'] === 'true' ) { 276 $attrs[] = 'required'; 277 } 278 257 279 return $label_html 258 . '<textarea id="' . esc_attr( $base_id ) . '" name="' . esc_attr( $atts['name'] ) . '"' 259 . ' placeholder="' . esc_attr( $atts['placeholder'] ) . '"' 260 . ' class="' . esc_attr( $atts['class'] ) . '"' . $required . '>' 261 . esc_textarea( $atts['default'] ) . '</textarea>'; 280 . '<textarea ' . implode( ' ', $attrs ) . '>' 281 . esc_textarea( $atts['default'] ) // prints only if non-empty 282 . '</textarea>'; 262 283 263 284 /* ======== SELECT ========= */ 264 285 case 'select': 286 287 $attr = [ 288 'id="' . esc_attr( $base_id ) . '"', 289 'name="' . esc_attr( $atts['name'] ) . '"', 290 ]; 291 $add_attr( $attr, 'class', $atts['class'] ); 292 if ( $atts['required'] === 'true' ) { 293 $attr[] = 'required'; 294 } 295 265 296 $options = array_map( 'trim', explode( ',', $atts['options'] ) ); 266 $out = $label_html 267 . '<select id="' . esc_attr( $base_id ) . '" name="' . esc_attr( $atts['name'] ) . '"' 268 . ' class="' . esc_attr( $atts['class'] ) . '"' . $required . '>'; 297 $out = $label_html . '<select ' . implode( ' ', $attr ) . '>'; 298 269 299 foreach ( $options as $option ) { 270 $sel ected= ( $atts['default'] === $option ) ? ' selected' : '';271 $out .= '<option value="' . esc_attr( $option ) . '"' . $sel ected. '>'300 $sel = ( $atts['default'] === $option ) ? ' selected' : ''; 301 $out .= '<option value="' . esc_attr( $option ) . '"' . $sel . '>' 272 302 . esc_html( $option ) . '</option>'; 273 303 } 274 304 return $out . '</select>'; 305 275 306 276 307 /* ======== RADIO ========= */ 277 308 case 'radio': 309 278 310 $options = array_map( 'trim', explode( ',', $atts['options'] ) ); 279 311 $out = $label_html; 312 280 313 foreach ( $options as $option ) { 281 $option_id = $base_id . '-' . sanitize_html_class( $option ); 282 $checked = ( $atts['default'] === $option ) ? ' checked' : ''; 283 $out .= '<label for="' . esc_attr( $option_id ) . '">' 284 . '<input type="radio" id="' . esc_attr( $option_id ) . '"' 285 . ' name="' . esc_attr( $atts['name'] ) . '" value="' . esc_attr( $option ) . '"' 286 . ' class="' . esc_attr( $atts['class'] ) . '"' . $checked . $required . '> ' 314 $opt_id = $base_id . '-' . sanitize_html_class( $option ); 315 $checked = ( $atts['default'] === $option ) ? ' checked' : ''; 316 317 $attr = [ 318 'type="radio"', 319 'id="' . esc_attr( $opt_id ) . '"', 320 'name="' . esc_attr( $atts['name'] ) . '"', 321 'value="' . esc_attr( $option ) . '"', 322 ]; 323 $add_attr( $attr, 'class', $atts['class'] ); 324 if ( $checked ) { $attr[] = 'checked'; } 325 if ( $atts['required'] === 'true' ) { $attr[] = 'required'; } 326 327 $out .= '<label for="' . esc_attr( $opt_id ) . '">' 328 . '<input ' . implode( ' ', $attr ) . '> ' 287 329 . esc_html( $option ) . '</label>'; 288 330 } 289 331 return $out; 332 290 333 291 334 /* ======== CHECKBOX ======= */ 292 335 case 'checkbox': 293 if ( ! empty( $atts['options'] ) ) { 336 337 // Multi-option list 338 if ( $atts['options'] !== '' ) { 339 294 340 $options = array_map( 'trim', explode( ',', $atts['options'] ) ); 295 341 $defaults = array_map( 'trim', explode( ',', $atts['default'] ) ); 296 342 $out = $label_html; 343 297 344 foreach ( $options as $option ) { 298 $option_id = $base_id . '-' . sanitize_html_class( $option ); 299 $checked = in_array( $option, $defaults, true ) ? ' checked' : ''; 300 $out .= '<label for="' . esc_attr( $option_id ) . '">' 301 . '<input type="checkbox" id="' . esc_attr( $option_id ) . '"' 302 . ' name="' . esc_attr( $atts['name'] ) . '[]" value="' . esc_attr( $option ) . '"' 303 . ' class="' . esc_attr( $atts['class'] ) . '"' . $checked . $required . '> ' 345 $opt_id = $base_id . '-' . sanitize_html_class( $option ); 346 $checked = in_array( $option, $defaults, true ); 347 348 $attr = [ 349 'type="checkbox"', 350 'id="' . esc_attr( $opt_id ) . '"', 351 'name="' . esc_attr( $atts['name'] ) . '[]"', 352 'value="' . esc_attr( $option ) . '"', 353 ]; 354 $add_attr( $attr, 'class', $atts['class'] ); 355 if ( $checked ) { $attr[] = 'checked'; } 356 if ( $atts['required'] === 'true' ) { $attr[] = 'required'; } 357 358 $out .= '<label for="' . esc_attr( $opt_id ) . '">' 359 . '<input ' . implode( ' ', $attr ) . '> ' 304 360 . esc_html( $option ) . '</label>'; 305 361 } 306 362 return $out; 307 363 } 308 /* Single boolean checkbox */ 309 return $label_html 310 . '<input type="checkbox" id="' . esc_attr( $base_id ) . '"' 311 . ' name="' . esc_attr( $atts['name'] ) . '" value="1"' 312 . ' class="' . esc_attr( $atts['class'] ) . '"' . $required . ' />'; 364 365 // Single boolean checkbox 366 $attr = [ 367 'type="checkbox"', 368 'id="' . esc_attr( $base_id ) . '"', 369 'name="' . esc_attr( $atts['name'] ) . '"', 370 'value="1"', 371 ]; 372 $add_attr( $attr, 'class', $atts['class'] ); 373 if ( $atts['required'] === 'true' ) { $attr[] = 'required'; } 374 375 return $label_html . '<input ' . implode( ' ', $attr ) . ' />'; 376 313 377 314 378 /* ======== BUTTON ========= */ 315 379 case 'button': 316 return '<button id="' . esc_attr( $base_id ) . '" type="' . esc_attr( $atts['button_type'] ) . '"' 317 . ' name="' . esc_attr( $atts['name'] ) . '" value="' . esc_attr( $atts['value'] ) . '"' 318 . ' class="' . esc_attr( $atts['class'] ) . '">' 380 381 $attr = [ 382 'id="' . esc_attr( $base_id ) . '"', 383 'type="' . esc_attr( $atts['button_type'] ) . '"', 384 'name="' . esc_attr( $atts['name'] ) . '"', 385 ]; 386 $add_attr( $attr, 'value', $atts['value'] ); 387 $add_attr( $attr, 'class', $atts['class'] ); 388 389 return '<button ' . implode( ' ', $attr ) . '>' 319 390 . esc_html( $atts['label'] ) . '</button>'; 391 320 392 321 393 /* ======== DEFAULT INPUT == */ 322 394 default: 323 return $label_html 324 . '<input type="' . esc_attr( $atts['type'] ) . '"' 325 . ' id="' . esc_attr( $base_id ) . '"' 326 . ' name="' . esc_attr( $atts['name'] ) . '"' 327 . ' placeholder="' . esc_attr( $atts['placeholder'] ) . '"' 328 . ' value="' . esc_attr( $atts['default'] ) . '"' 329 . ' class="' . esc_attr( $atts['class'] ) . '"' 330 . $required . $unique_attr . ' />'; 331 } 332 } 333 334 public function flex_forms_handle_form_submission_ajax() 335 { 336 check_ajax_referer('flex-forms-nonce', 'nonce'); 337 338 $form_id = isset($_POST['flex_form_id']) ? absint($_POST['flex_form_id']) : 0; 339 if (!$form_id) { 340 wp_send_json_error(['message' => 'Invalid form ID.']); 341 } 342 343 $recaptcha_version = get_option('flex_forms_recaptcha_version', 'none'); 344 if ('v2' === $recaptcha_version) { 345 $recaptcha_response = sanitize_text_field(wp_unslash($_POST['g-recaptcha-response'] ?? '')); 346 if (!$this->flex_forms_validate_recaptcha_v2($recaptcha_response)) { 347 wp_send_json_error(['message' => 'Invalid reCAPTCHA.']); 348 } 349 } elseif ('v3' === $recaptcha_version) { 350 $recaptcha_token = sanitize_text_field(wp_unslash($_POST['recaptcha_token'] ?? '')); 351 if (!$this->flex_forms_validate_recaptcha_v3($recaptcha_token)) { 352 wp_send_json_error(['message' => 'Invalid reCAPTCHA token.']); 353 } 354 } 355 356 $submission_data = []; 357 if (isset($_POST['flex_forms_all_inputs'])) { 358 $all_inputs = sanitize_text_field(wp_unslash($_POST['flex_forms_all_inputs'])); 359 $flex_all_inputs = explode(',', $all_inputs); 360 foreach ($flex_all_inputs as $input) { 361 if (isset($_POST[$input])) { 362 $submission_data[$input] = wp_kses(wp_unslash($_POST[$input]), 'post'); 363 } 364 } 365 } 366 367 $submission_post = array( 368 'post_title' => 'Submission for form ' . $form_id, 369 'post_type' => 'flex_submission', 370 'post_status' => 'publish', 371 ); 372 373 $submission_id = wp_insert_post($submission_post); 374 if ($submission_id) { 375 update_post_meta($submission_id, '_flex_form_id', $form_id); 376 update_post_meta($submission_id, '_flex_form_data', $submission_data); 377 378 $admin_email_to = get_post_meta($form_id, '_flex_forms_admin_email_to', true); 379 $admin_email_subject = get_post_meta($form_id, '_flex_forms_admin_email_subject', true); 380 $admin_email_template = get_post_meta($form_id, '_flex_forms_admin_email_template', true); 381 if (!empty($admin_email_to) && !empty($admin_email_subject) && !empty($admin_email_template)) { 382 foreach ($submission_data as $key => $value) { 383 $admin_email_template = str_replace('[' . $key . ']', $value, $admin_email_template); 384 $admin_email_subject = str_replace('[' . $key . ']', $value, $admin_email_subject); 385 } 386 $admin_email_template = wpautop($admin_email_template); 387 $this->flex_forms_send_mail($admin_email_to, $admin_email_subject, $admin_email_template, $form_id); 388 } 389 390 $user_email_enabled = get_post_meta($form_id, '_flex_forms_user_email_enable', true); 391 if ($user_email_enabled) { 392 $user_email_shortcode = get_post_meta($form_id, '_flex_forms_user_email_email_shortcode', true); 393 $user_email_subject = get_post_meta($form_id, '_flex_forms_user_email_subject', true); 394 $user_email_template = get_post_meta($form_id, '_flex_forms_user_email_template', true); 395 preg_match('/\[(.*?)\]/', $user_email_shortcode, $matches); 396 $user_email = isset($submission_data[$matches[1]]) ? sanitize_email($submission_data[$matches[1]]) : ''; 397 if (!empty($user_email) && !empty($user_email_subject) && !empty($user_email_template)) { 398 foreach ($submission_data as $key => $value) { 399 $user_email_template = str_replace('[' . $key . ']', $value, $user_email_template); 400 $user_email_subject = str_replace('[' . $key . ']', $value, $user_email_subject); 401 } 402 $user_email_template = wpautop($user_email_template); 403 $this->flex_forms_send_mail($user_email, $user_email_subject, $user_email_template, $form_id); 404 } 405 } 406 407 $success_behavior = get_post_meta($form_id, '_flex_forms_success_behavior', true); 408 if ('redirect' === $success_behavior) { 409 $redirect_url = get_post_meta($form_id, '_flex_forms_success_redirect_url', true); 410 wp_send_json_success(array( 411 'message' => 'Form submitted successfully.', 412 'success_behavior' => 'redirect', 413 'redirect_url' => $redirect_url, 414 )); 395 396 $attrs = [ 397 'type="' . esc_attr( $atts['type'] ) . '"', 398 'id="' . esc_attr( $base_id ) . '"', 399 'name="' . esc_attr( $atts['name'] ) . '"', 400 ]; 401 if ( $atts['placeholder'] !== '' ) { 402 $attrs[] = 'placeholder="' . esc_attr( $atts['placeholder'] ) . '"'; 403 } 404 if ( $atts['default'] !== '' ) { 405 $attrs[] = 'value="' . esc_attr( $atts['default'] ) . '"'; 406 } 407 if ( $atts['class'] !== '' ) { 408 $attrs[] = 'class="' . esc_attr( $atts['class'] ) . '"'; 409 } 410 if ( $atts['required'] === 'true' ) { 411 $attrs[] = 'required'; 412 } 413 if ( $atts['unique'] === 'true' ) { 414 $attrs[] = 'data-unique="true"'; 415 } 416 417 return $label_html . '<input ' . implode( ' ', $attrs ) . ' />'; 418 } 419 } 420 421 public function flex_forms_handle_form_submission_ajax() { 422 423 check_ajax_referer( 'flex-forms-nonce', 'nonce' ); 424 425 /* ------------------------------------------------------------- 426 * 0. Resolve & validate the form 427 * ---------------------------------------------------------- */ 428 $form_id = isset( $_POST['flex_form_id'] ) ? absint( $_POST['flex_form_id'] ) : 0; 429 if ( ! $form_id ) { 430 wp_send_json_error( [ 'message' => 'Invalid form ID.' ] ); 431 } 432 433 /* ------------------------------------------------------------- 434 * 1. reCAPTCHA (v2 / v3) 435 * ---------------------------------------------------------- */ 436 $recaptcha_version = get_option( 'flex_forms_recaptcha_version', 'none' ); 437 if ( 'v2' === $recaptcha_version ) { 438 $response = sanitize_text_field( wp_unslash( $_POST['g-recaptcha-response'] ?? '' ) ); 439 if ( ! $this->flex_forms_validate_recaptcha_v2( $response ) ) { 440 wp_send_json_error( [ 'message' => 'Invalid reCAPTCHA.' ] ); 441 } 442 } elseif ( 'v3' === $recaptcha_version ) { 443 $token = sanitize_text_field( wp_unslash( $_POST['recaptcha_token'] ?? '' ) ); 444 if ( ! $this->flex_forms_validate_recaptcha_v3( $token ) ) { 445 wp_send_json_error( [ 'message' => 'Invalid reCAPTCHA token.' ] ); 446 } 447 } 448 449 /* ------------------------------------------------------------- 450 * 2. Collect submitted values 451 * ---------------------------------------------------------- */ 452 $submission_data = array(); 453 if ( isset( $_POST['flex_forms_all_inputs'] ) ) { 454 $all = explode( ',', sanitize_text_field( wp_unslash( $_POST['flex_forms_all_inputs'] ) ) ); 455 foreach ( $all as $name ) { 456 if ( isset( $_POST[ $name ] ) ) { 457 $submission_data[ $name ] = wp_kses( wp_unslash( $_POST[ $name ] ), 'post' ); 458 } 459 } 460 } 461 462 /* ------------------------------------------------------------- 463 * 3. Read form-level options 464 * ---------------------------------------------------------- */ 465 $store_in_db = (int) get_post_meta( $form_id, '_flex_forms_store_in_db', true ); 466 $admin_email_enabled = (int) get_post_meta( $form_id, '_flex_forms_admin_email_enable', true ); // new 467 468 /* ------------------------------------------------------------- 469 * 4. Optionally save the submission to DB 470 * ---------------------------------------------------------- */ 471 $submission_id = 0; 472 if ( $store_in_db ) { 473 $submission_id = wp_insert_post( array( 474 'post_title' => 'Submission for form ' . $form_id, 475 'post_type' => 'flex_submission', 476 'post_status' => 'publish', 477 ) ); 478 479 if ( $submission_id ) { 480 update_post_meta( $submission_id, '_flex_form_id', $form_id ); 481 update_post_meta( $submission_id, '_flex_form_data', $submission_data ); 482 } 483 } 484 485 /* ------------------------------------------------------------- 486 * 5. Admin notification e-mail (respects new checkbox) 487 * ---------------------------------------------------------- */ 488 if ( $admin_email_enabled ) { 489 490 $admin_to = get_post_meta( $form_id, '_flex_forms_admin_email_to', true ); 491 $admin_subject = get_post_meta( $form_id, '_flex_forms_admin_email_subject', true ); 492 $admin_body_tpl = get_post_meta( $form_id, '_flex_forms_admin_email_template', true ); 493 494 if ( $admin_to && $admin_subject && $admin_body_tpl ) { 495 496 foreach ( $submission_data as $k => $v ) { 497 $admin_subject = str_replace( '[' . $k . ']', $v, $admin_subject ); 498 $admin_body_tpl = str_replace( '[' . $k . ']', $v, $admin_body_tpl ); 499 } 500 501 $admin_body_tpl = wpautop( $admin_body_tpl ); 502 503 $this->flex_forms_send_mail( 504 $admin_to, 505 $admin_subject, 506 $admin_body_tpl, 507 $form_id 508 ); 509 } 510 } 511 512 /* ------------------------------------------------------------- 513 * 6. Optional user confirmation e-mail (unchanged logic) 514 * ---------------------------------------------------------- */ 515 $user_email_enabled = (int) get_post_meta( $form_id, '_flex_forms_user_email_enable', true ); 516 if ( $user_email_enabled ) { 517 518 $shortcode = get_post_meta( $form_id, '_flex_forms_user_email_email_shortcode', true ); 519 $subject = get_post_meta( $form_id, '_flex_forms_user_email_subject', true ); 520 $body_tpl = get_post_meta( $form_id, '_flex_forms_user_email_template', true ); 521 522 if ( preg_match( '/\[(.*?)\]/', $shortcode, $m ) ) { 523 $user_addr = $submission_data[ $m[1] ] ?? ''; 524 $user_addr = sanitize_email( $user_addr ); 415 525 } else { 416 $success_message = get_post_meta($form_id, '_flex_forms_success_text', true); 417 wp_send_json_success([ 418 'message' => 'Form submitted successfully.', 419 'success_behavior' => 'message', 420 'success_message' => $success_message, 421 ]); 422 } 423 } else { 424 wp_send_json_error(['message' => 'Submission failed.']); 425 } 526 $user_addr = ''; 527 } 528 529 if ( $user_addr && $subject && $body_tpl ) { 530 foreach ( $submission_data as $k => $v ) { 531 $subject = str_replace( '[' . $k . ']', $v, $subject ); 532 $body_tpl = str_replace( '[' . $k . ']', $v, $body_tpl ); 533 } 534 $body_tpl = wpautop( $body_tpl ); 535 536 $this->flex_forms_send_mail( 537 $user_addr, 538 $subject, 539 $body_tpl, 540 $form_id 541 ); 542 } 543 } 544 545 /* ------------------------------------------------------------- 546 * 7. Success response 547 * ---------------------------------------------------------- */ 548 $success_behavior = get_post_meta( $form_id, '_flex_forms_success_behavior', true ); 549 550 if ( 'redirect' === $success_behavior ) { 551 wp_send_json_success( array( 552 'message' => 'Form submitted successfully.', 553 'success_behavior' => 'redirect', 554 'redirect_url' => get_post_meta( $form_id, '_flex_forms_success_redirect_url', true ), 555 ) ); 556 } 557 558 wp_send_json_success( array( 559 'message' => 'Form submitted successfully.', 560 'success_behavior' => 'message', 561 'success_message' => get_post_meta( $form_id, '_flex_forms_success_text', true ), 562 ) ); 426 563 } 427 564 -
flex-forms/trunk/includes/class-flex-forms-main.php
r3305740 r3310602 104 104 $form_id = $post->ID; 105 105 106 // Show shortcode at page top (click-to-copy handled by JS already enqueued)107 if ( $is_edit ) {108 printf(109 '<p style="margin:8px 0 18px;">110 <strong>%s</strong>111 <code class="flex-forms-copy-shortcode" title="%s">[flex-form id="%d"]</code>112 </p>',113 esc_html__( 'Shortcode:', 'flex-forms' ),114 esc_attr__( 'Click to copy', 'flex-forms' ),115 absint( $form_id )116 );117 }118 119 106 /* Core content */ 120 107 $content_value = $is_edit ? $post->post_content : ''; … … 147 134 /* Custom CSS */ 148 135 $custom_css_val = $is_edit ? get_post_meta( $form_id, '_flex_forms_custom_css', true ) : ''; 136 $admin_email_enable_val = $is_edit ? (int) get_post_meta( $form_id, '_flex_forms_admin_email_enable', true ) : 1; 149 137 150 138 /* --------------------------------------------------------------------- 151 139 * 2. Mark-up 152 140 * ------------------------------------------------------------------ */ 141 if ( $is_edit ) { 142 143 /* ► Always show the shortcode element */ 144 $html = sprintf( 145 '<strong>%1$s</strong> ' . 146 '<code class="flex-forms-copy-shortcode" title="%2$s">[flex-form id="%3$d"]</code>', 147 esc_html__( 'Shortcode:', 'flex-forms' ), 148 esc_attr__( 'Click to copy', 'flex-forms' ), 149 absint( $form_id ) 150 ); 151 152 /* ► Add the button only if submissions are stored in DB */ 153 if ( get_post_meta( $form_id, '_flex_forms_store_in_db', true ) ) { 154 $subs_url = admin_url( 'edit.php?post_type=flex_submission&form_id=' . $form_id ); 155 $html .= sprintf( 156 ' <a href="%1$s" class="button button-secondary">%2$s</a>', 157 esc_url( $subs_url ), 158 esc_html__( 'View submissions', 'flex-forms' ) 159 ); 160 } 161 162 printf( '<p style="margin:8px 0 18px;">%s</p>', $html ); 163 } 153 164 ?> 165 166 <hr> 154 167 <div class="wrap"> 155 168 <form method="post"> … … 193 206 <td><input type="text" id="flex_forms_flex_field_label" class="regular-text" /></td> 194 207 </tr> 195 <tr >208 <tr id="flex_forms_flex_field_placeholder_row"> 196 209 <th><label for="flex_forms_flex_field_placeholder"><?php esc_html_e( 'Placeholder', 'flex-forms' ); ?></label></th> 197 210 <td><input type="text" id="flex_forms_flex_field_placeholder" class="regular-text" /></td> … … 206 219 <td><input type="text" id="flex_forms_flex_field_class" class="regular-text" /></td> 207 220 </tr> 208 <tr >221 <tr id="flex_forms_flex_field_default_row"> 209 222 <th><label for="flex_forms_flex_field_default"><?php esc_html_e( 'Default Value', 'flex-forms' ); ?></label></th> 210 223 <td><input type="text" id="flex_forms_flex_field_default" class="regular-text" /></td> … … 253 266 ?> 254 267 255 <h2><?php esc_html_e( 'Email Templates', 'flex-forms' ); ?></h2>256 <p><?php esc_html_e( 'Use shortcodes like [name], [phone], etc. in your email body to include user-submitted data.', 'flex-forms' ); ?></p>257 258 268 <!-- Admin email --> 259 <h3><?php esc_html_e( 'Admin Email', 'flex-forms' ); ?></h3>269 <h3><?php esc_html_e( 'Admin Notification Email', 'flex-forms' ); ?></h3> 260 270 <table class="form-table"> 271 <tr> 272 <th><?php esc_html_e( 'Send admin e-mail?', 'flex-forms' ); ?></th> 273 <td> 274 <label> 275 <input type="checkbox" 276 id="flex_forms_admin_email_enable" 277 name="flex_forms_admin_email_enable" 278 value="1" 279 <?php checked( 1, $admin_email_enable_val ); ?> /> 280 <?php esc_html_e( 'Notify me when a submission arrives', 'flex-forms' ); ?> 281 </label> 282 </td> 283 </tr> 261 284 <tr> 262 285 <th><label for="flex_forms_admin_email_from"><?php esc_html_e( 'From Email', 'flex-forms' ); ?></label></th> … … 287 310 288 311 <!-- User email --> 289 <h 2><?php esc_html_e( 'User Email', 'flex-forms' ); ?></h2>312 <h3><?php esc_html_e( 'User Notification Email', 'flex-forms' ); ?></h3> 290 313 <table class="form-table"> 291 314 <tr> … … 375 398 376 399 <!-- Success settings --> 377 <h 2><?php esc_html_e( 'Success Settings', 'flex-forms' ); ?></h2>400 <h3><?php esc_html_e( 'Settings for Success', 'flex-forms' ); ?></h3> 378 401 <table class="form-table"> 379 402 <tr> … … 397 420 398 421 <!-- Error settings --> 399 <h 2><?php esc_html_e( 'Error Settings', 'flex-forms' ); ?></h2>422 <h3><?php esc_html_e( 'Settings for Error', 'flex-forms' ); ?></h3> 400 423 <table class="form-table"> 401 424 <tr> … … 419 442 420 443 <!-- NEW: form-level attributes --> 421 <h 2><?php esc_html_e( 'Form Attributes', 'flex-forms' ); ?></h2>444 <h3><?php esc_html_e( 'Form Attributes', 'flex-forms' ); ?></h3> 422 445 <table class="form-table"> 423 446 <tr> … … 438 461 439 462 <!-- Custom CSS --> 440 <h 2><?php esc_html_e( 'Custom CSS', 'flex-forms' ); ?></h2>463 <h3><?php esc_html_e( 'Custom CSS', 'flex-forms' ); ?></h3> 441 464 <textarea name="flex_forms_custom_css" rows="4" style="width:100%;"><?php echo esc_textarea( $custom_css_val ); ?></textarea> 442 465 <p class="description"><?php esc_html_e( 'This CSS will be injected on the front end for this form only.', 'flex-forms' ); ?></p> … … 447 470 448 471 /** 449 * Save all Flex Form meta-box values.472 * Save every field from the Flex-Form meta-box. 450 473 * 451 * @param int $post_id The current post ID.474 * @param int $post_id 452 475 */ 453 476 public function flex_forms_save_meta_box_data( $post_id ) { 454 477 455 /* -------------------------------------------------------------------- 456 * 1. Security / early exits 457 * ------------------------------------------------------------------ */ 478 /* ───────────────────────── Security ───────────────────────── */ 458 479 if ( 459 480 ! wp_verify_nonce( … … 467 488 } 468 489 469 /* -------------------------------------------------------------------- 470 * 2. Success behaviour 471 * ------------------------------------------------------------------ */ 472 update_post_meta( 473 $post_id, 474 '_flex_forms_success_behavior', 475 sanitize_text_field( wp_unslash( $_POST['flex_forms_success_behavior'] ?? '' ) ) 476 ); 477 update_post_meta( 478 $post_id, 479 '_flex_forms_success_redirect_url', 480 esc_url_raw( wp_unslash( $_POST['flex_forms_success_redirect_url'] ?? '' ) ) 481 ); 482 update_post_meta( 483 $post_id, 484 '_flex_forms_success_text', 485 wp_kses_post( wp_unslash( $_POST['flex_forms_success_text'] ?? '' ) ) 486 ); 487 488 /* -------------------------------------------------------------------- 489 * 3. Error behaviour 490 * ------------------------------------------------------------------ */ 491 update_post_meta( 492 $post_id, 493 '_flex_forms_error_behavior', 494 sanitize_text_field( wp_unslash( $_POST['flex_forms_error_behavior'] ?? '' ) ) 495 ); 496 update_post_meta( 497 $post_id, 498 '_flex_forms_error_redirect_url', 499 esc_url_raw( wp_unslash( $_POST['flex_forms_error_redirect_url'] ?? '' ) ) 500 ); 501 update_post_meta( 502 $post_id, 503 '_flex_forms_error_text', 504 wp_kses_post( wp_unslash( $_POST['flex_forms_error_text'] ?? '' ) ) 505 ); 506 507 /* -------------------------------------------------------------------- 508 * 4. Store-in-DB option 509 * ------------------------------------------------------------------ */ 510 update_post_meta( 511 $post_id, 512 '_flex_forms_store_in_db', 513 isset( $_POST['flex_forms_store_in_db'] ) ? 1 : 0 514 ); 515 516 /* -------------------------------------------------------------------- 517 * 5. Admin e-mail settings 518 * ------------------------------------------------------------------ */ 519 update_post_meta( 520 $post_id, 521 '_flex_forms_admin_email_from', 522 sanitize_email( wp_unslash( $_POST['flex_forms_admin_email_from'] ?? '' ) ) 523 ); 524 update_post_meta( 525 $post_id, 526 '_flex_forms_admin_email_from_name', 527 sanitize_text_field( wp_unslash( $_POST['flex_forms_admin_email_from_name'] ?? '' ) ) 528 ); 529 update_post_meta( 530 $post_id, 531 '_flex_forms_admin_email_to', 532 sanitize_email( wp_unslash( $_POST['flex_forms_admin_email_to'] ?? '' ) ) 533 ); 534 update_post_meta( 535 $post_id, 536 '_flex_forms_admin_email_subject', 537 sanitize_text_field( wp_unslash( $_POST['flex_forms_admin_email_subject'] ?? '' ) ) 538 ); 539 update_post_meta( 540 $post_id, 541 '_flex_forms_admin_email_template', 542 wp_kses_post( wp_unslash( $_POST['flex_forms_admin_email_template'] ?? '' ) ) 543 ); 544 545 /* -------------------------------------------------------------------- 546 * 6. User e-mail settings 547 * ------------------------------------------------------------------ */ 548 update_post_meta( 549 $post_id, 550 '_flex_forms_user_email_email_shortcode', 551 sanitize_text_field( wp_unslash( $_POST['flex_forms_user_email_email_shortcode'] ?? '' ) ) 552 ); 553 update_post_meta( 554 $post_id, 555 '_flex_forms_user_email_enable', 556 isset( $_POST['flex_forms_user_email_enable'] ) ? 1 : 0 557 ); 558 update_post_meta( 559 $post_id, 560 '_flex_forms_user_email_subject', 561 sanitize_text_field( wp_unslash( $_POST['flex_forms_user_email_subject'] ?? '' ) ) 562 ); 563 update_post_meta( 564 $post_id, 565 '_flex_forms_user_email_template', 566 wp_kses_post( wp_unslash( $_POST['flex_forms_user_email_template'] ?? '' ) ) 567 ); 568 569 /* -------------------------------------------------------------------- 570 * 7. NEW: Form-level attributes 571 * ------------------------------------------------------------------ */ 572 update_post_meta( 573 $post_id, 574 '_flex_forms_form_id', 575 sanitize_text_field( wp_unslash( $_POST['flex_forms_form_id'] ?? '' ) ) 576 ); 577 update_post_meta( 578 $post_id, 579 '_flex_forms_form_class', 580 sanitize_text_field( wp_unslash( $_POST['flex_forms_form_class'] ?? '' ) ) 581 ); 582 // Use sanitize_textarea_field so quotes (=,") survive for data-* pairs. 583 update_post_meta( 584 $post_id, 585 '_flex_forms_form_attrs', 586 sanitize_textarea_field( wp_unslash( $_POST['flex_forms_form_attrs'] ?? '' ) ) 587 ); 588 589 /* -------------------------------------------------------------------- 590 * 8. Custom CSS 591 * ------------------------------------------------------------------ */ 592 update_post_meta( 593 $post_id, 594 '_flex_forms_custom_css', 595 wp_strip_all_tags( wp_unslash( $_POST['flex_forms_custom_css'] ?? '' ), true ) 596 ); 490 /* ────────────────────── Helper callbacks ─────────────────── */ 491 $chk = fn( $key ) => isset( $_POST[ $key ] ) ? 1 : 0; // checkbox → 0/1 492 $raw = fn( $key ) => wp_unslash( $_POST[ $key ] ?? '' ); // convenience 493 $sel = fn( $key ) => sanitize_text_field( $raw( $key ) ); // simple text 494 $kses = fn( $key ) => wp_kses_post( $raw( $key ) ); // textarea / HTML 495 $url = fn( $key ) => esc_url_raw( $raw( $key ) ); // url 496 $email = fn( $key ) => sanitize_email( $raw( $key ) ); // email 497 $attr = fn( $key ) => sanitize_textarea_field( $raw( $key ) ); // data-theme etc. 498 499 /* ─────────────────────── Mapping table ───────────────────── */ 500 $fields = [ 501 /* success */ 502 '_flex_forms_success_behavior' => $sel( 'flex_forms_success_behavior' ), 503 '_flex_forms_success_redirect_url' => $url( 'flex_forms_success_redirect_url' ), 504 '_flex_forms_success_text' => $kses( 'flex_forms_success_text' ), 505 506 /* error */ 507 '_flex_forms_error_behavior' => $sel( 'flex_forms_error_behavior' ), 508 '_flex_forms_error_redirect_url' => $url( 'flex_forms_error_redirect_url' ), 509 '_flex_forms_error_text' => $kses( 'flex_forms_error_text' ), 510 511 /* check-boxes */ 512 '_flex_forms_store_in_db' => $chk( 'flex_forms_store_in_db' ), 513 '_flex_forms_admin_email_enable' => $chk( 'flex_forms_admin_email_enable' ), 514 '_flex_forms_user_email_enable' => $chk( 'flex_forms_user_email_enable' ), 515 516 /* admin e-mail */ 517 '_flex_forms_admin_email_from' => $email('flex_forms_admin_email_from' ), 518 '_flex_forms_admin_email_from_name' => $sel( 'flex_forms_admin_email_from_name' ), 519 '_flex_forms_admin_email_to' => $email('flex_forms_admin_email_to' ), 520 '_flex_forms_admin_email_subject' => $sel( 'flex_forms_admin_email_subject' ), 521 '_flex_forms_admin_email_template' => $kses( 'flex_forms_admin_email_template' ), 522 523 /* user e-mail */ 524 '_flex_forms_user_email_email_shortcode' => $sel( 'flex_forms_user_email_email_shortcode' ), 525 '_flex_forms_user_email_subject' => $sel( 'flex_forms_user_email_subject' ), 526 '_flex_forms_user_email_template' => $kses( 'flex_forms_user_email_template' ), 527 528 /* form attributes */ 529 '_flex_forms_form_id' => $sel( 'flex_forms_form_id' ), 530 '_flex_forms_form_class' => $sel( 'flex_forms_form_class' ), 531 '_flex_forms_form_attrs' => $attr( 'flex_forms_form_attrs' ), 532 533 /* custom CSS */ 534 '_flex_forms_custom_css' => wp_strip_all_tags( $raw( 'flex_forms_custom_css' ), true ), 535 ]; 536 537 /* ────────────────────── Single update loop ────────────────── */ 538 foreach ( $fields as $meta_key => $value ) { 539 update_post_meta( $post_id, $meta_key, $value ); 540 } 597 541 } 598 542 -
flex-forms/trunk/includes/class-flex-forms-settings.php
r3279209 r3310602 1 1 <?php 2 if (!defined('ABSPATH')) { 2 /** 3 * Flex Forms – Settings screen 4 */ 5 if ( ! defined( 'ABSPATH' ) ) { 3 6 exit; 4 7 } 5 8 6 class Flex_Forms_Settings 7 { 8 9 class Flex_Forms_Settings { 10 11 /** 12 * Settings group slug 13 * 14 * @var string 15 */ 9 16 private $option_group = 'flex_forms_settings_group'; 10 11 public function __construct() 12 { 13 add_action('admin_menu', array($this, 'flex_forms_add_settings_submenu_page')); 14 add_action('admin_init', array($this, 'flex_forms_register_settings')); 15 } 16 17 public function flex_forms_add_settings_submenu_page() 18 { 17 18 /* --------------------------------------------------------------------- * 19 * Constructor 20 * --------------------------------------------------------------------- */ 21 public function __construct() { 22 add_action( 'admin_menu', array( $this, 'add_settings_submenu_page' ) ); 23 add_action( 'admin_init', array( $this, 'register_settings' ) ); 24 add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_assets' ) ); 25 } 26 27 /* --------------------------------------------------------------------- * 28 * Admin-menu entry (under Flex Forms CPT) 29 * --------------------------------------------------------------------- */ 30 public function add_settings_submenu_page() { 19 31 add_submenu_page( 20 32 'edit.php?post_type=flex_form', 21 __( 'Settings', 'flex-forms'),22 __( 'Settings', 'flex-forms'),33 __( 'Settings', 'flex-forms' ), 34 __( 'Settings', 'flex-forms' ), 23 35 'manage_options', 24 36 'flex-forms-settings', 25 array($this, 'flex_forms_settings_page') 26 ); 27 } 28 29 public function flex_forms_register_settings() 30 { 31 register_setting($this->option_group, 'flex_forms_use_smtp', 'sanitize_text_field'); 32 register_setting($this->option_group, 'flex_forms_smtp_host', 'sanitize_text_field'); 33 register_setting($this->option_group, 'flex_forms_smtp_port', 'sanitize_text_field'); 34 register_setting($this->option_group, 'flex_forms_smtp_encryption', 'sanitize_text_field'); 35 register_setting($this->option_group, 'flex_forms_smtp_user', 'sanitize_text_field'); 36 register_setting($this->option_group, 'flex_forms_smtp_pass', 'sanitize_text_field'); 37 register_setting($this->option_group, 'flex_forms_license_key', 'sanitize_text_field'); 38 register_setting($this->option_group, 'flex_forms_recaptcha_version', 'sanitize_text_field'); 39 register_setting($this->option_group, 'flex_forms_recaptcha_site_key', 'sanitize_text_field'); 40 register_setting($this->option_group, 'flex_forms_recaptcha_secret_key', 'sanitize_text_field'); 41 } 42 43 public function flex_forms_settings_page() 44 { 37 array( $this, 'settings_page' ) 38 ); 39 } 40 41 /* --------------------------------------------------------------------- * 42 * Register settings 43 * --------------------------------------------------------------------- */ 44 public function register_settings() { 45 46 /* SMTP */ 47 register_setting( $this->option_group, 'flex_forms_use_smtp', array( $this, 'sanitize_checkbox' ) ); 48 register_setting( $this->option_group, 'flex_forms_smtp_host', 'sanitize_text_field' ); 49 register_setting( $this->option_group, 'flex_forms_smtp_port', 'absint' ); 50 register_setting( $this->option_group, 'flex_forms_smtp_encryption', 'sanitize_text_field' ); 51 register_setting( $this->option_group, 'flex_forms_smtp_user', 'sanitize_text_field' ); 52 register_setting( $this->option_group, 'flex_forms_smtp_pass', 'sanitize_text_field' ); 53 54 /* License */ 55 register_setting( $this->option_group, 'flex_forms_license_key', 'sanitize_text_field' ); 56 57 /* reCAPTCHA */ 58 register_setting( $this->option_group, 'flex_forms_recaptcha_version', 'sanitize_text_field' ); 59 register_setting( $this->option_group, 'flex_forms_recaptcha_site_key', 'sanitize_text_field' ); 60 register_setting( $this->option_group, 'flex_forms_recaptcha_secret_key','sanitize_text_field' ); 61 } 62 63 /* --------------------------------------------------------------------- * 64 * Enqueue backend assets 65 * --------------------------------------------------------------------- */ 66 public function enqueue_assets( $hook ) { 67 68 // Our submenu slug => hook name becomes "{post_type}_page_{slug}" 69 if ( $hook !== 'flex_form_page_flex-forms-settings' ) { 70 return; 71 } 72 73 wp_enqueue_script( 74 'flex-forms-backend', 75 plugins_url( 'assets/js/backend.js', dirname( __FILE__, 2 ) ), 76 array( 'jquery' ), 77 '1.0.0', 78 true 79 ); 80 81 wp_localize_script( 82 'flex-forms-backend', 83 'flex_forms_admin_vars', 84 array( 85 'ajaxurl' => admin_url( 'admin-ajax.php' ), 86 'nonce' => wp_create_nonce( 'flex-forms-nonce' ), 87 ) 88 ); 89 90 wp_enqueue_style( 91 'flex-forms-settings', 92 plugins_url( 'assets/css/admin.css', dirname( __FILE__, 2 ) ), 93 array(), 94 '1.0.0' 95 ); 96 } 97 98 /* --------------------------------------------------------------------- * 99 * Settings page HTML 100 * --------------------------------------------------------------------- */ 101 public function settings_page() { 102 103 // Helper shortcuts 104 $get = function ( $key, $default = '' ) { 105 return esc_attr( get_option( $key, $default ) ); 106 }; 107 $checked = function ( $key ) { 108 checked( 1, get_option( $key ) ); 109 }; 45 110 ?> 46 111 <div class="wrap"> 47 <h1> Flex Forms Settings</h1>112 <h1><?php esc_html_e( 'Flex Forms Settings', 'flex-forms' ); ?></h1> 48 113 49 114 <form method="post" action="options.php"> 50 <?php settings_fields($this->option_group); ?> 51 52 <h2 class="text-xl font-bold mb-2">SMTP Settings</h2> 115 <?php settings_fields( $this->option_group ); ?> 116 117 <!-- ==================== SMTP ==================== --> 118 <h2 class="text-xl font-bold mb-2"><?php esc_html_e( 'SMTP Settings', 'flex-forms' ); ?></h2> 53 119 <table class="form-table w-full"> 54 120 <tr> 55 <th scope="row"> 56 <label for="flex_forms_use_smtp">Use SMTP?</label> 57 </th> 58 <td> 59 <input type="checkbox" id="flex_forms_use_smtp" name="flex_forms_use_smtp" value="1" 60 <?php checked(1, get_option('flex_forms_use_smtp')); ?> /> 61 <p class="description">Check to enable SMTP for form emails.</p> 62 </td> 63 </tr> 64 65 <tr class="smtp-dependent"> 66 <th scope="row"> 67 <label for="flex_forms_smtp_host">SMTP Host</label> 68 </th> 69 <td> 70 <input type="text" class="regular-text" 71 id="flex_forms_smtp_host" 72 name="flex_forms_smtp_host" 73 value="<?php echo esc_attr(get_option('flex_forms_smtp_host')); ?>"> 74 </td> 75 </tr> 76 <tr class="smtp-dependent"> 77 <th scope="row"> 78 <label for="flex_forms_smtp_port">SMTP Port</label> 79 </th> 80 <td> 81 <input type="number" class="small-text" 82 id="flex_forms_smtp_port" 83 name="flex_forms_smtp_port" 84 value="<?php echo esc_attr(get_option('flex_forms_smtp_port')); ?>"> 85 </td> 86 </tr> 87 <tr class="smtp-dependent"> 88 <th scope="row"> 89 <label for="flex_forms_smtp_encryption">Encryption</label> 90 </th> 91 <td> 121 <th scope="row"><label for="flex_forms_use_smtp"><?php esc_html_e( 'Use SMTP?', 'flex-forms' ); ?></label></th> 122 <td> 123 <input type="checkbox" id="flex_forms_use_smtp" name="flex_forms_use_smtp" value="1" <?php $checked( 'flex_forms_use_smtp' ); ?> /> 124 <p class="description"><?php esc_html_e( 'Enable SMTP for all e-mails sent by Flex Forms.', 'flex-forms' ); ?></p> 125 </td> 126 </tr> 127 128 <tr class="smtp-dependent"> 129 <th scope="row"><label for="flex_forms_smtp_host"><?php esc_html_e( 'SMTP Host', 'flex-forms' ); ?></label></th> 130 <td><input type="text" class="regular-text" id="flex_forms_smtp_host" name="flex_forms_smtp_host" value="<?php echo $get( 'flex_forms_smtp_host' ); ?>"></td> 131 </tr> 132 <tr class="smtp-dependent"> 133 <th scope="row"><label for="flex_forms_smtp_port"><?php esc_html_e( 'SMTP Port', 'flex-forms' ); ?></label></th> 134 <td><input type="number" class="small-text" id="flex_forms_smtp_port" name="flex_forms_smtp_port" value="<?php echo $get( 'flex_forms_smtp_port' ); ?>"></td> 135 </tr> 136 <tr class="smtp-dependent"> 137 <th scope="row"><label for="flex_forms_smtp_encryption"><?php esc_html_e( 'Encryption', 'flex-forms' ); ?></label></th> 138 <td> 139 <?php 140 $current = strtolower( get_option( 'flex_forms_smtp_encryption', 'none' ) ); 141 $options = array( 'none' => 'None', 'ssl' => 'SSL', 'tls' => 'TLS' ); 142 ?> 92 143 <select id="flex_forms_smtp_encryption" name="flex_forms_smtp_encryption"> 93 <?php 94 $current = strtolower( get_option( 'flex_forms_smtp_encryption' ) ); // normalise 95 $options = array( 'None', 'SSL', 'TLS' ); // display labels 96 97 foreach ( $options as $label ) { 98 $value = strtolower( $label ); // none / ssl / tls 99 printf( 100 '<option value="%1$s" %2$s>%3$s</option>', 101 esc_attr( $value ), 102 selected( $value, $current, false ), 103 esc_html( $label ) 104 ); 105 } 106 ?> 144 <?php foreach ( $options as $value => $label ) : ?> 145 <option value="<?php echo esc_attr( $value ); ?>" <?php selected( $value, $current ); ?>><?php echo esc_html( $label ); ?></option> 146 <?php endforeach; ?> 107 147 </select> 108 109 </td> 110 </tr> 111 <tr class="smtp-dependent"> 112 <th scope="row"> 113 <label for="flex_forms_smtp_user">SMTP Username</label> 114 </th> 115 <td> 116 <input type="text" class="regular-text" 117 id="flex_forms_smtp_user" 118 name="flex_forms_smtp_user" 119 value="<?php echo esc_attr(get_option('flex_forms_smtp_user')); ?>"> 120 </td> 121 </tr> 122 <tr class="smtp-dependent"> 123 <th scope="row"> 124 <label for="flex_forms_smtp_pass">SMTP Password</label> 125 </th> 126 <td> 127 <input type="password" class="regular-text" 128 id="flex_forms_smtp_pass" 129 name="flex_forms_smtp_pass" 130 value="<?php echo esc_attr(get_option('flex_forms_smtp_pass')); ?>"> 148 </td> 149 </tr> 150 <tr class="smtp-dependent"> 151 <th scope="row"><label for="flex_forms_smtp_user"><?php esc_html_e( 'SMTP Username', 'flex-forms' ); ?></label></th> 152 <td><input type="text" class="regular-text" id="flex_forms_smtp_user" name="flex_forms_smtp_user" value="<?php echo $get( 'flex_forms_smtp_user' ); ?>"></td> 153 </tr> 154 <tr class="smtp-dependent"> 155 <th scope="row"><label for="flex_forms_smtp_pass"><?php esc_html_e( 'SMTP Password', 'flex-forms' ); ?></label></th> 156 <td><input type="password" class="regular-text" id="flex_forms_smtp_pass" name="flex_forms_smtp_pass" value="<?php echo $get( 'flex_forms_smtp_pass' ); ?>"></td> 157 </tr> 158 159 <!-- Send test e-mail --> 160 <tr class="smtp-dependent" id="flex_forms_smtp_test_row"> 161 <th scope="row"><label for="flex_forms_smtp_test_email"><?php esc_html_e( 'Send Test Email', 'flex-forms' ); ?></label></th> 162 <td> 163 <input type="email" id="flex_forms_smtp_test_email" placeholder="[email protected]" class="regular-text" /> 164 <button type="button" class="button" id="flex_forms_send_test_email_btn"><?php esc_html_e( 'Send Test', 'flex-forms' ); ?></button> 165 <span id="flex_forms_smtp_test_result" style="margin-left:10px;"></span> 166 <p class="description"><?php esc_html_e( 'Enter an address and click “Send Test” to verify your SMTP settings.', 'flex-forms' ); ?></p> 131 167 </td> 132 168 </tr> … … 135 171 <hr class="my-4"/> 136 172 137 <h2 class="text-xl font-bold mb-2">License Key</h2> 173 <!-- ==================== License ==================== --> 174 <h2 class="text-xl font-bold mb-2"><?php esc_html_e( 'License Key', 'flex-forms' ); ?></h2> 138 175 <table class="form-table w-full mb-4"> 139 176 <tr> 140 <th scope="row"> 141 <label for="flex_forms_license_key">License Key</label> 142 </th> 143 <td> 144 <input type="text" class="regular-text" 145 id="flex_forms_license_key" 146 name="flex_forms_license_key" 147 value="<?php echo esc_attr(get_option('flex_forms_license_key')); ?>"> 148 <p class="description">Enter your license key if you have one.</p> 177 <th scope="row"><label for="flex_forms_license_key"><?php esc_html_e( 'License Key', 'flex-forms' ); ?></label></th> 178 <td> 179 <input type="text" class="regular-text" id="flex_forms_license_key" name="flex_forms_license_key" value="<?php echo $get( 'flex_forms_license_key' ); ?>"> 149 180 </td> 150 181 </tr> … … 153 184 <hr class="my-4"/> 154 185 155 <h2 class="text-xl font-bold mb-2">reCaptcha Settings</h2> 186 <!-- ==================== reCAPTCHA ==================== --> 187 <h2 class="text-xl font-bold mb-2"><?php esc_html_e( 'reCAPTCHA Settings', 'flex-forms' ); ?></h2> 156 188 <table class="form-table w-full"> 157 189 <tr> 158 <th scope="row"> 159 <label for="flex_forms_recaptcha_version">Version</label> 160 </th> 161 <td> 190 <th scope="row"><label for="flex_forms_recaptcha_version"><?php esc_html_e( 'Version', 'flex-forms' ); ?></label></th> 191 <td> 192 <?php 193 $version_current = get_option( 'flex_forms_recaptcha_version', 'none' ); 194 $version_options = array( 195 'none' => 'None', 196 'v2' => 'v2 Checkbox', 197 'v3' => 'v3 Invisible', 198 ); ?> 162 199 <select id="flex_forms_recaptcha_version" name="flex_forms_recaptcha_version"> 163 <?php 164 $current = get_option('flex_forms_recaptcha_version', 'none'); 165 $options = array( 166 'none' => 'None', 167 'v2' => 'v2 Checkbox', 168 'v3' => 'v3 Invisible', 169 ); 170 foreach ($options as $value => $label) { 171 printf( 172 '<option value="%1$s" %2$s>%3$s</option>', 173 esc_attr($value), 174 selected($value, $current, false), 175 esc_html($label) 176 ); 177 } 178 ?> 200 <?php foreach ( $version_options as $value => $label ) : ?> 201 <option value="<?php echo esc_attr( $value ); ?>" <?php selected( $value, $version_current ); ?>><?php echo esc_html( $label ); ?></option> 202 <?php endforeach; ?> 179 203 </select> 180 204 </td> 181 205 </tr> 182 206 <tr> 183 <th scope="row"> 184 <label for="flex_forms_recaptcha_site_key">Site Key</label> 185 </th> 186 <td> 187 <input type="text" class="regular-text" 188 id="flex_forms_recaptcha_site_key" 189 name="flex_forms_recaptcha_site_key" 190 value="<?php echo esc_attr(get_option('flex_forms_recaptcha_site_key')); ?>"> 191 </td> 192 </tr> 193 <tr> 194 <th scope="row"> 195 <label for="flex_forms_recaptcha_secret_key">Secret Key</label> 196 </th> 197 <td> 198 <input type="text" class="regular-text" 199 id="flex_forms_recaptcha_secret_key" 200 name="flex_forms_recaptcha_secret_key" 201 value="<?php echo esc_attr(get_option('flex_forms_recaptcha_secret_key')); ?>"> 202 </td> 207 <th scope="row"><label for="flex_forms_recaptcha_site_key"><?php esc_html_e( 'Site Key', 'flex-forms' ); ?></label></th> 208 <td><input type="text" class="regular-text" id="flex_forms_recaptcha_site_key" name="flex_forms_recaptcha_site_key" value="<?php echo $get( 'flex_forms_recaptcha_site_key' ); ?>"></td> 209 </tr> 210 <tr> 211 <th scope="row"><label for="flex_forms_recaptcha_secret_key"><?php esc_html_e( 'Secret Key', 'flex-forms' ); ?></label></th> 212 <td><input type="text" class="regular-text" id="flex_forms_recaptcha_secret_key" name="flex_forms_recaptcha_secret_key" value="<?php echo $get( 'flex_forms_recaptcha_secret_key' ); ?>"></td> 203 213 </tr> 204 214 </table> … … 210 220 } 211 221 212 public function sanitize_checkbox($input) 213 { 214 return ($input === '1') ? 1 : 0; 215 } 216 222 /* --------------------------------------------------------------------- * 223 * Helpers 224 * --------------------------------------------------------------------- */ 225 public function sanitize_checkbox( $input ) { 226 return ( $input === '1' ) ? 1 : 0; 227 } 217 228 } -
flex-forms/trunk/includes/class-flex-forms-submissions.php
r3300738 r3310602 63 63 } 64 64 65 public function flex_forms_remove_row_actions($actions, $post) { 66 if ($post->post_type === 'flex_submission') { 67 if (isset($actions['edit'])) { 68 $actions['edit'] = str_replace('Edit', 'View', $actions['edit']); 69 } 70 unset($actions['view']); 71 unset($actions['inline hide-if-no-js']); 72 } 65 public function flex_forms_remove_row_actions( $actions, $post ) { 66 67 if ( $post->post_type !== 'flex_submission' ) { 68 return $actions; 69 } 70 71 /* Rename “Edit” → “View” & hide some links (your old code) */ 72 if ( isset( $actions['edit'] ) ) { 73 $actions['edit'] = str_replace( 'Edit', 'View', $actions['edit'] ); 74 } 75 unset( $actions['view'], $actions['inline hide-if-no-js'] ); 76 77 /* + Add our Send-E-mail link */ 78 $nonce = wp_create_nonce( 'mass_email_nonce' ); 79 $mail = admin_url( 80 'admin.php?page=flex_forms_mass_email' 81 . '&submission_id=' . $post->ID 82 . '&_wpnonce=' . $nonce 83 ); 84 $actions['flex_forms_send_email'] = 85 '<a href="' . esc_url( $mail ) . '">' . esc_html__( 'Send E-mail', 'flex-forms' ) . '</a>'; 86 73 87 return $actions; 74 88 } … … 111 125 } 112 126 113 public function flex_forms_submission_meta_box_callback($post) { 114 $data = get_post_meta($post->ID, '_flex_form_data', true); 115 $form_id = get_post_meta($post->ID, '_flex_form_id', true); 116 $back_url = admin_url('edit.php?post_type=flex_submission&s='.$form_id); 117 unset($data['action']); 118 echo '<h3>' . esc_attr($post->post_title) . '</h3>'; 119 if(!empty($data)) { 120 echo '<table class="form-table">'; 121 foreach($data as $key => $value) { 122 if($key === '_wp_http_referer') { 123 $key = 'Referrer'; 124 } 125 echo '<tr>'; 126 echo '<th>' . esc_attr($key) . '</th>'; 127 echo '<td>' . esc_attr($value) . '</td>'; 128 echo '</tr>'; 127 public function flex_forms_submission_meta_box_callback( $post ) { 128 129 /* -------------------------------------------------------------------- 130 * 1. Gather meta + helpers 131 * ----------------------------------------------------------------- */ 132 $data = get_post_meta( $post->ID, '_flex_form_data', true ); 133 $form_id = get_post_meta( $post->ID, '_flex_form_id', true ); 134 $back_url = admin_url( 'edit.php?post_type=flex_submission&s=' . $form_id ); 135 136 /* -------------------------------------------------------------------- 137 * 2. Heading + submission date 138 * ----------------------------------------------------------------- */ 139 echo '<h3>' . esc_html( $post->post_title ) . '</h3>'; 140 echo '<p><strong>' . esc_html__( 'Submitted on:', 'flex-forms' ) . '</strong> ' 141 . esc_html( get_the_date( 'Y-m-d H:i', $post ) ) 142 . '</p>'; 143 144 /* -------------------------------------------------------------------- 145 * 3. Data table 146 * ----------------------------------------------------------------- */ 147 unset( $data['action'] ); // internal key 148 149 if ( ! empty( $data ) ) { 150 echo '<table class="form-table" style="margin-top:8px;">'; 151 foreach ( $data as $key => $value ) { 152 if ( $key === '_wp_http_referer' ) { $key = 'Referrer'; } 153 echo '<tr><th>' . esc_html( $key ) . '</th><td>' . esc_html( is_array( $value ) ? implode( ', ', $value ) : $value ) . '</td></tr>'; 129 154 } 130 155 echo '</table>'; 131 156 } 132 echo '<a href="' . esc_url($back_url) . '" class="button button-primary">Back to Submissions</a>'; 157 158 /* -------------------------------------------------------------------- 159 * 4. Action buttons: back + send-mail 160 * ----------------------------------------------------------------- */ 161 $nonce = wp_create_nonce( 'mass_email_nonce' ); 162 $mail_url = admin_url( 163 'admin.php?page=flex_forms_mass_email' 164 . '&form_id=' . $form_id 165 . '&submission_id=' . $post->ID 166 . '&_wpnonce=' . $nonce 167 ); 168 169 echo '<p style="margin-top:15px;">' 170 . '<a href="' . esc_url( $back_url ) . '" class="button button-secondary" style="margin-right:6px;">' 171 . esc_html__( 'Back to Submissions', 'flex-forms' ) . '</a>' 172 . '<a href="' . esc_url( $mail_url ) . '" class="button button-primary">' 173 . esc_html__( 'Send E-mail', 'flex-forms' ) . '</a>' 174 . '</p>'; 133 175 } 134 176 … … 141 183 142 184 /** 143 * Replace the default list‑table columns for flex_submission posts.144 * – Removes the built‑in “Title” column145 * – Adds a “Referrer” column146 * – Adds one column for every user field stored in _flex_form_data185 * Replace the default list-table columns for flex_submission posts. 186 * – Removes the built-in “Title” column 187 * – Adds one column for every user field stored in _flex_form_data 188 * – Renames the Date column to “Date Submitted” 147 189 */ 148 190 public function flex_forms_add_data_columns( $columns ) { 149 191 150 / / Remove WP’s built‑in Title column192 /* 1. Remove WP’s built-in Title column */ 151 193 unset( $columns['title'] ); 152 194 153 / / Discover one submission to get its keys195 /* 2. Inspect one submission to get its custom field keys */ 154 196 $example = get_posts( [ 155 197 'post_type' => 'flex_submission', … … 160 202 ] ); 161 203 162 if ( $example ) {163 $meta_data = get_post_meta( $example[0]->ID, '_flex_form_data', true );164 }165 166 $new _columns = [];204 $meta_data = $example 205 ? get_post_meta( $example[0]->ID, '_flex_form_data', true ) 206 : array(); 207 208 $new = array(); 167 209 168 210 foreach ( $columns as $key => $label ) { 169 211 170 /* Insert our custom columns just before the Date column */ 171 if ( $key === 'date' ) { 172 173 // 1. Referrer column 174 $new_columns['referrer'] = __( 'Referrer', 'flex-forms' ); 175 176 // 2. Dynamic user‑field columns 177 if ( ! empty( $meta_data ) && is_array( $meta_data ) ) { 178 foreach ( $meta_data as $field_key => $value ) { 179 if ( strpos( $field_key, '_' ) === 0 ) { // skip internal keys 180 continue; 181 } 182 $label = ucwords( str_replace( '_', ' ', $field_key ) ); 183 $new_columns[ $field_key ] = $label; 212 /* Insert dynamic user-field columns just before Date */ 213 if ( $key === 'date' && ! empty( $meta_data ) ) { 214 foreach ( $meta_data as $field_key => $value ) { 215 if ( strpos( $field_key, '_' ) === 0 ) { // skip internal keys 216 continue; 184 217 } 218 $nice = ucwords( str_replace( '_', ' ', $field_key ) ); 219 $new[ $field_key ] = $nice; 185 220 } 186 221 } 187 222 188 // keep original column (date, author, etc.) 189 $new_columns[ $key ] = $label; 190 } 191 192 return $new_columns; 223 /* Keep WordPress’ original column but rename the heading */ 224 $new[ $key ] = ( $key === 'date' ) 225 ? __( 'Date Submitted', 'flex-forms' ) 226 : $label; 227 } 228 229 return $new; 193 230 } 194 231 195 232 /** 196 * Populate our custom columns.233 * Populate dynamic field columns in the submissions list. 197 234 */ 198 235 public function flex_forms_populate_referer_column( $column, $post_id ) { … … 203 240 } 204 241 205 /* Referrer column */ 206 if ( $column === 'referrer' ) { 207 $ref = $meta['_referrer_url'] ?? ''; 208 echo $ref 209 ? sprintf( '<a href="%1$s" target="_blank" rel="noopener">%2$s</a>', 210 esc_url( $ref ), 211 esc_html( wp_parse_url( $ref, PHP_URL_HOST ) ) 212 ) 213 : '<em>' . esc_html__( 'None', 'flex-forms' ) . '</em>'; 214 return; 215 } 216 217 /* Dynamic field columns */ 242 /* Dynamic user-field columns */ 218 243 if ( isset( $meta[ $column ] ) ) { 219 244 $value = $meta[ $column ]; … … 224 249 } 225 250 } 226 public function flex_forms_add_export_button($which) { 227 if ($which === 'top' && get_current_screen()->post_type === 'flex_submission') { 228 $form_id = isset($_GET['form_id']) ? absint($_GET['form_id']) : 0; 229 $export_nonce = wp_create_nonce('export_nonce'); 230 $export_url = admin_url('edit.php?post_type=flex_submission&flex_forms_export_csv=1&_wpnonce=' . $export_nonce . '&form_id=' . $form_id); 231 echo '<a href="' . esc_attr($export_url) . '" class="button button-primary">Export to CSV</a>'; 251 252 /** 253 * Adds “Export to CSV” (always) and “Send Mass E-Mail” (when possible) 254 * above the Submissions list-table. 255 * 256 * @param string $which 'top' | 'bottom' 257 */ 258 public function flex_forms_add_export_button( $which ) { 259 260 /* Only output buttons at the top of the flex_submission list-table */ 261 if ( $which !== 'top' || get_current_screen()->post_type !== 'flex_submission' ) { 262 return; 263 } 264 265 /* -------------------------------------------------------------- */ 266 /* 1. Resolve the current form-ID (0 ⇒ unknown) */ 267 /* -------------------------------------------------------------- */ 268 $form_id = 0; 269 270 if ( ! empty( $_GET['form_id'] ) && is_numeric( $_GET['form_id'] ) ) { 271 $form_id = absint( $_GET['form_id'] ); 272 } elseif ( ! empty( $_GET['s'] ) && is_numeric( $_GET['s'] ) ) { 273 /* When the list is filtered via the “search” box */ 274 $form_id = absint( $_GET['s'] ); 275 } 276 277 /* -------------------------------------------------------------- */ 278 /* 2. “Export to CSV” – always available */ 279 /* -------------------------------------------------------------- */ 280 $export_url = add_query_arg( 281 [ 282 'post_type' => 'flex_submission', 283 'flex_forms_export_csv' => 1, 284 'form_id' => $form_id, 285 '_wpnonce' => wp_create_nonce( 'export_nonce' ), 286 ], 287 admin_url( 'edit.php' ) 288 ); 289 290 echo '<a href="' . esc_url( $export_url ) . '" class="button button-primary" style="margin-right:6px;">' 291 . '<span class="dashicons dashicons-download" style="margin-right:4px; vertical-align:middle;"></span>' 292 . esc_html__( 'Export to CSV', 'flex-forms' ) . '</a>'; 293 294 295 /* -------------------------------------------------------------- */ 296 /* 3. “Send Mass E-Mail” – only when we have a valid form-ID */ 297 /* -------------------------------------------------------------- */ 298 if ( $form_id ) { 299 300 $mail_url = add_query_arg( 301 [ 302 'post_type' => 'flex_form', // CPT-style parent 303 'page' => 'flex_forms_mass_email', // hidden submenu slug 304 'form_id' => $form_id, 305 '_wpnonce' => wp_create_nonce( 'mass_email_nonce' ), 306 ], 307 admin_url( 'edit.php' ) 308 ); 309 310 $edit_form_url = add_query_arg( 311 [ 312 'post_type' => 'flex_form', 313 'action' => 'edit', 314 'post' => $form_id, 315 ], 316 admin_url( 'post.php' ) 317 ); 318 319 echo '<a href="' . esc_url( $mail_url ) . '" class="button button-secondary" style="margin-right:6px;">' 320 . '<span class="dashicons dashicons-email" style="margin-right:4px; vertical-align:middle;"></span>' 321 . esc_html__( 'Send Mass E-Mail', 'flex-forms' ) . '</a>'; 322 323 echo '<a href="' . esc_url( $edit_form_url ) . '" class="button button-secondary" style="margin-right:6px;">' 324 . '<span class="dashicons dashicons-edit" style="margin-right:4px; vertical-align:middle;"></span>' 325 . esc_html__( 'Edit Form', 'flex-forms' ) . '</a>'; 326 232 327 } 233 328 } -
flex-forms/trunk/readme.txt
r3305774 r3310602 6 6 Tested up to: 6.8 7 7 Requires PHP: 7.0 8 Stable tag: 2.1. 18 Stable tag: 2.1.2 9 9 License: GPLv2 or later 10 10 License URI: https://www.gnu.org/licenses/gpl-2.0.html
Note: See TracChangeset
for help on using the changeset viewer.