Plugin Directory

Changeset 3310602


Ignore:
Timestamp:
06/12/2025 03:11:31 PM (8 months ago)
Author:
flexfields
Message:

Updated trunk to version2.1.2

Location:
flex-forms/trunk
Files:
3 added
9 edited

Legend:

Unmodified
Added
Removed
  • flex-forms/trunk/assets/css/flex-forms-admin.css

    r3305607 r3310602  
    1414    transition: background-color 0.2s ease;
    1515}
     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  
    4242        const isButton = fieldType === 'button';
    4343        $('#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);
    4448
    4549        /* Show “Unique?” only for email + DB-store */
     
    150154        }, 350);
    151155    }
     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);
    152232});
  • flex-forms/trunk/flex-forms.php

    r3305774 r3310602  
    22/*
    33Plugin Name: Flex Forms
    4 Plugin URI: https://flex-fields.com/forms/
     4Plugin URI:  https://flex-fields.com/forms/
    55Description: A modular, customizable form builder plugin for WordPress.
    6 Version: 2.1.1
     6Version:     2.1.2
    77Requires at least: 6.6
    8 Author: Future Systems
    9 Author URI: https://f-s.am
    10 License: GPLv2 or later
     8Author:      Future Systems
     9Author URI:  https://f-s.am
     10License:     GPLv2 or later
    1111Text Domain: flex-forms
    1212*/
    1313
    14 // Exit if accessed directly
    15 if (!defined('ABSPATH')) {
    16     exit;
     14if ( ! defined( 'ABSPATH' ) ) { exit; }
     15
     16define( 'FLEX_FORMS_VERSION',    '2.1.2' );
     17define( 'FLEX_FORMS_PLUGIN_DIR', plugin_dir_path( __FILE__ ) );
     18define( 'FLEX_FORMS_PLUGIN_URL', plugin_dir_url(  __FILE__ ) );
     19
     20/* -------------------------------------------------- *
     21 *  Helpers FIRST – makes flex_forms_str() available  *
     22 * -------------------------------------------------- */
     23foreach ( glob( FLEX_FORMS_PLUGIN_DIR . 'includes/helpers/*.php' ) as $file ) {
     24    require_once $file;                // flex_forms_str() defined here
    1725}
    1826
    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 * -------------------------------------------------- */
    2330require_once FLEX_FORMS_PLUGIN_DIR . 'includes/class-flex-forms-main.php';
    2431require_once FLEX_FORMS_PLUGIN_DIR . 'includes/class-flex-forms-submissions.php';
     
    2734require_once FLEX_FORMS_PLUGIN_DIR . 'includes/class-flex-forms-frontend.php';
    2835require_once FLEX_FORMS_PLUGIN_DIR . 'includes/class-flex-forms-ajax.php';
     36require_once FLEX_FORMS_PLUGIN_DIR . 'includes/class-flex-forms-mass-email.php';
    2937
    30 function flex_forms_init()
    31 {
     38/* -------------------------------------------------- *
     39 *  Bootstrap                                         *
     40 * -------------------------------------------------- */
     41add_action( 'plugins_loaded', function () {
     42
    3243    new Flex_Forms_Main();
    3344    new Flex_Forms_Submissions();
     
    3647    new Flex_Forms_Frontend();
    3748    new Flex_Forms_Ajax();
    38 }
    39 add_action('plugins_loaded', 'flex_forms_init');
    4049
    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 */
     56register_activation_hook(   __FILE__, 'flex_forms_flush_rewrites' );
     57register_deactivation_hook( __FILE__, 'flex_forms_flush_rewrites' );
     58function flex_forms_flush_rewrites() { flush_rewrite_rules(); }
  • flex-forms/trunk/includes/class-flex-forms-ajax.php

    r3300738 r3310602  
    11<?php
     2/**
     3 * Flex Forms – AJAX handlers
     4 */
    25if ( ! defined( 'ABSPATH' ) ) {
    36    exit;
     
    710
    811    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' ) );
    1322    }
    1423
    15     public function flex_forms_process_submission() {
     24    /* ============================================================= *
     25     *  1. Process submission (stub for brevity)
     26     * ============================================================= */
     27    public function process_submission() {
    1628        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' ) ) );
    1830    }
    1931
    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' );
    2237
    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();
    2540
    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.' ) );
    2843        }
    2944
    3045        $submissions = new Flex_Forms_Submissions();
    31         $errors = $submissions->check_duplicate_fields($form_id, $fields);
     46        $errors      = $submissions->check_duplicate_fields( $form_id, $fields );
    3247
    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 ) );
    3550        }
    3651
    37         wp_send_json_success(['valid' => true]);
     52        wp_send_json_success( array( 'valid' => true ) );
    3853    }
    3954
     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    }
    40115}
  • flex-forms/trunk/includes/class-flex-forms-frontend.php

    r3305607 r3310602  
    251251         * 4. Field-type switch
    252252         * ------------------------------------------------------------------ */
     253        $add_attr = static function ( &$a, $name, $val ) {
     254            if ( $val !== '' ) {
     255                $a[] = $name . '="' . esc_attr( $val ) . '"';
     256            }
     257        };
     258
    253259        switch ( $atts['type'] ) {
    254260
    255261            /* ======== TEXTAREA ======== */
    256262            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
    257279                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>';
    262283
    263284            /* ======== SELECT ========= */
    264285            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
    265296                $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
    269299                foreach ( $options as $option ) {
    270                     $selected = ( $atts['default'] === $option ) ? ' selected' : '';
    271                     $out .= '<option value="' . esc_attr( $option ) . '"' . $selected . '>'
     300                    $sel = ( $atts['default'] === $option ) ? ' selected' : '';
     301                    $out .= '<option value="' . esc_attr( $option ) . '"' . $sel . '>'
    272302                        . esc_html( $option ) . '</option>';
    273303                }
    274304                return $out . '</select>';
     305
    275306
    276307            /* ======== RADIO ========= */
    277308            case 'radio':
     309
    278310                $options = array_map( 'trim', explode( ',', $atts['options'] ) );
    279311                $out     = $label_html;
     312
    280313                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 ) . '> '
    287329                        . esc_html( $option ) . '</label>';
    288330                }
    289331                return $out;
     332
    290333
    291334            /* ======== CHECKBOX ======= */
    292335            case 'checkbox':
    293                 if ( ! empty( $atts['options'] ) ) {
     336
     337                // Multi-option list
     338                if ( $atts['options'] !== '' ) {
     339
    294340                    $options  = array_map( 'trim', explode( ',', $atts['options'] ) );
    295341                    $defaults = array_map( 'trim', explode( ',', $atts['default'] ) );
    296342                    $out      = $label_html;
     343
    297344                    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 ) . '> '
    304360                            . esc_html( $option ) . '</label>';
    305361                    }
    306362                    return $out;
    307363                }
    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
    313377
    314378            /* ======== BUTTON ========= */
    315379            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 ) . '>'
    319390                    . esc_html( $atts['label'] ) . '</button>';
     391
    320392
    321393            /* ======== DEFAULT INPUT == */
    322394            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 );
    415525            } 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        ) );
    426563    }
    427564
  • flex-forms/trunk/includes/class-flex-forms-main.php

    r3305740 r3310602  
    104104        $form_id  = $post->ID;
    105105
    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 
    119106        /* Core content */
    120107        $content_value                = $is_edit ? $post->post_content : '';
     
    147134        /* Custom CSS */
    148135        $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;
    149137
    150138        /* ---------------------------------------------------------------------
    151139         * 2. Mark-up
    152140         * ------------------------------------------------------------------ */
     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                    '&nbsp;&nbsp;<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        }
    153164        ?>
     165
     166        <hr>
    154167        <div class="wrap">
    155168            <form method="post">
     
    193206                                <td><input type="text" id="flex_forms_flex_field_label" class="regular-text" /></td>
    194207                            </tr>
    195                             <tr>
     208                            <tr id="flex_forms_flex_field_placeholder_row">
    196209                                <th><label for="flex_forms_flex_field_placeholder"><?php esc_html_e( 'Placeholder', 'flex-forms' ); ?></label></th>
    197210                                <td><input type="text" id="flex_forms_flex_field_placeholder" class="regular-text" /></td>
     
    206219                                <td><input type="text" id="flex_forms_flex_field_class" class="regular-text" /></td>
    207220                            </tr>
    208                             <tr>
     221                            <tr id="flex_forms_flex_field_default_row">
    209222                                <th><label for="flex_forms_flex_field_default"><?php esc_html_e( 'Default Value', 'flex-forms' ); ?></label></th>
    210223                                <td><input type="text" id="flex_forms_flex_field_default" class="regular-text" /></td>
     
    253266                ?>
    254267
    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 
    258268                <!-- 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>
    260270                <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>
    261284                    <tr>
    262285                        <th><label for="flex_forms_admin_email_from"><?php esc_html_e( 'From Email', 'flex-forms' ); ?></label></th>
     
    287310
    288311                <!-- User email -->
    289                 <h2><?php esc_html_e( 'User Email', 'flex-forms' ); ?></h2>
     312                <h3><?php esc_html_e( 'User Notification Email', 'flex-forms' ); ?></h3>
    290313                <table class="form-table">
    291314                    <tr>
     
    375398
    376399                <!-- Success settings -->
    377                 <h2><?php esc_html_e( 'Success Settings', 'flex-forms' ); ?></h2>
     400                <h3><?php esc_html_e( 'Settings for Success', 'flex-forms' ); ?></h3>
    378401                <table class="form-table">
    379402                    <tr>
     
    397420
    398421                <!-- Error settings -->
    399                 <h2><?php esc_html_e( 'Error Settings', 'flex-forms' ); ?></h2>
     422                <h3><?php esc_html_e( 'Settings for Error', 'flex-forms' ); ?></h3>
    400423                <table class="form-table">
    401424                    <tr>
     
    419442
    420443                <!-- NEW: form-level attributes -->
    421                 <h2><?php esc_html_e( 'Form Attributes', 'flex-forms' ); ?></h2>
     444                <h3><?php esc_html_e( 'Form Attributes', 'flex-forms' ); ?></h3>
    422445                <table class="form-table">
    423446                    <tr>
     
    438461
    439462                <!-- Custom CSS -->
    440                 <h2><?php esc_html_e( 'Custom CSS', 'flex-forms' ); ?></h2>
     463                <h3><?php esc_html_e( 'Custom CSS', 'flex-forms' ); ?></h3>
    441464                <textarea name="flex_forms_custom_css" rows="4" style="width:100%;"><?php echo esc_textarea( $custom_css_val ); ?></textarea>
    442465                <p class="description"><?php esc_html_e( 'This CSS will be injected on the front end for this form only.', 'flex-forms' ); ?></p>
     
    447470
    448471    /**
    449      * Save all Flex Form meta-box values.
     472     * Save every field from the Flex-Form meta-box.
    450473     *
    451      * @param int $post_id The current post ID.
     474     * @param int $post_id
    452475     */
    453476    public function flex_forms_save_meta_box_data( $post_id ) {
    454477
    455         /* --------------------------------------------------------------------
    456          * 1. Security / early exits
    457          * ------------------------------------------------------------------ */
     478        /* ───────────────────────── Security ───────────────────────── */
    458479        if (
    459480            ! wp_verify_nonce(
     
    467488        }
    468489
    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        }
    597541    }
    598542
  • flex-forms/trunk/includes/class-flex-forms-settings.php

    r3279209 r3310602  
    11<?php
    2 if (!defined('ABSPATH')) {
     2/**
     3 * Flex Forms – Settings screen
     4 */
     5if ( ! defined( 'ABSPATH' ) ) {
    36    exit;
    47}
    58
    6 class Flex_Forms_Settings
    7 {
    8    
     9class Flex_Forms_Settings {
     10
     11    /**
     12     * Settings group slug
     13     *
     14     * @var string
     15     */
    916    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() {
    1931        add_submenu_page(
    2032            'edit.php?post_type=flex_form',
    21             __('Settings', 'flex-forms'),
    22             __('Settings', 'flex-forms'),
     33            __( 'Settings', 'flex-forms' ),
     34            __( 'Settings', 'flex-forms' ),
    2335            'manage_options',
    2436            '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        };
    45110        ?>
    46111        <div class="wrap">
    47             <h1>Flex Forms Settings</h1>
     112            <h1><?php esc_html_e( 'Flex Forms Settings', 'flex-forms' ); ?></h1>
    48113
    49114            <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>
    53119                <table class="form-table w-full">
    54120                    <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                            ?>
    92143                            <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; ?>
    107147                            </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>
    131167                        </td>
    132168                    </tr>
     
    135171                <hr class="my-4"/>
    136172
    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>
    138175                <table class="form-table w-full mb-4">
    139176                    <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' ); ?>">
    149180                        </td>
    150181                    </tr>
     
    153184                <hr class="my-4"/>
    154185
    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>
    156188                <table class="form-table w-full">
    157189                    <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                            ); ?>
    162199                            <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; ?>
    179203                            </select>
    180204                        </td>
    181205                    </tr>
    182206                    <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>
    203213                    </tr>
    204214                </table>
     
    210220    }
    211221
    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    }
    217228}
  • flex-forms/trunk/includes/class-flex-forms-submissions.php

    r3300738 r3310602  
    6363    }
    6464
    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
    7387        return $actions;
    7488    }
     
    111125    }
    112126
    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>';
    129154            }
    130155            echo '</table>';
    131156        }
    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>';
    133175    }
    134176
     
    141183
    142184    /**
    143      *  Replace the default list‑table columns for flex_submission posts.
    144      *  – Removes the built‑in “Title” column
    145      *  – Adds a “Referrer” column
    146      *  – Adds one column for every user field stored in _flex_form_data
     185     * 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”
    147189     */
    148190    public function flex_forms_add_data_columns( $columns ) {
    149191
    150         // Remove WP’s built‑in Title column
     192        /* 1. Remove WP’s built-in Title column */
    151193        unset( $columns['title'] );
    152194
    153         // Discover one submission to get its keys
     195        /* 2. Inspect one submission to get its custom field keys */
    154196        $example = get_posts( [
    155197            'post_type'      => 'flex_submission',
     
    160202        ] );
    161203
    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();
    167209
    168210        foreach ( $columns as $key => $label ) {
    169211
    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;
    184217                    }
     218                    $nice = ucwords( str_replace( '_', ' ', $field_key ) );
     219                    $new[ $field_key ] = $nice;
    185220                }
    186221            }
    187222
    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;
    193230    }
    194231
    195232    /**
    196      *  Populate our custom columns.
     233     * Populate dynamic field columns in the submissions list.
    197234     */
    198235    public function flex_forms_populate_referer_column( $column, $post_id ) {
     
    203240        }
    204241
    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 */
    218243        if ( isset( $meta[ $column ] ) ) {
    219244            $value = $meta[ $column ];
     
    224249        }
    225250    }
    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
    232327        }
    233328    }
  • flex-forms/trunk/readme.txt

    r3305774 r3310602  
    66Tested up to: 6.8
    77Requires PHP: 7.0
    8 Stable tag: 2.1.1
     8Stable tag: 2.1.2
    99License: GPLv2 or later
    1010License URI: https://www.gnu.org/licenses/gpl-2.0.html
Note: See TracChangeset for help on using the changeset viewer.