PluginProbe
Contact Forms by Cimatti / 1.9.2
Contact Forms by Cimatti v1.9.2
2.3.6 2.3.5 2.3.0 2.2.32 2.2.4 2.2.0 2.1.2 2.1.1 trunk 1.0 1.1 1.2 1.2.1 1.3 1.3.1 1.3.2 1.3.3 1.3.4 1.3.5 1.3.6 1.3.7 1.3.8 1.3.9 1.4.0 1.4.1 All 62 releases
← All changes | accua-forms.php +2518 -2692 2.3.51.9.2 View file →
@@ -1,85 +1,11 @@
1 1 <?php
2 -if ( ! defined( 'ABSPATH' ) ) exit;
3 -
4 -require_once __DIR__ . '/admin/fields-page.php';
5 -require_once __DIR__ . '/admin/settings-page.php';
6 -require_once __DIR__ . '/admin/form-editor.php';
7 -require_once __DIR__ . '/includes/data-deletion.php';
8 -require_once __DIR__ . '/includes/privacy.php';
9 -require_once __DIR__ . '/includes/spam-blocklist.php';
10 -
11 -/**
12 - * Base fill colour for the admin sidebar menu icon.
13 - *
14 - * WordPress core (svg-painter.js) recolours base64 SVG menu icons to the active
15 - * admin colour scheme on load. We resolve that same base colour here and bake it
16 - * into the icon so the first server-rendered paint already matches the painted
17 - * result, avoiding a brief flash of a differently coloured icon before the JS
18 - * repaint. Colour schemes are registered on admin_init (priority 1) which runs
19 - * after admin_menu, so the exact colour is applied later by
20 - * accua_forms_paint_menu_icon() rather than at menu-registration time.
21 - */
22 -function accua_forms_admin_menu_icon_color(){
23 - global $_wp_admin_css_colors;
24 - $scheme = get_user_option('admin_color');
25 -
26 - if ( empty($scheme) || ! isset($_wp_admin_css_colors[$scheme]) ) {
27 - $scheme = 'modern';
28 - }
29 -
30 - if ( ! empty($_wp_admin_css_colors[$scheme]->icon_colors['base']) ) {
31 - return $_wp_admin_css_colors[$scheme]->icon_colors['base'];
32 - }
33 -
34 - if ( ! empty($_wp_admin_css_colors['modern']->icon_colors['base']) ) {
35 - return $_wp_admin_css_colors['modern']->icon_colors['base'];
36 - }
37 -
38 - return '#a7aaad'; // WordPress default menu icon base colour.
39 -}
40 -
41 -/**
42 - * Monochrome sidebar menu icon as a base64 data URI.
43 - *
44 - * The standalone brand icon (assets/img/accua-contacts-forms.svg) stays coloured
45 - * and is used unchanged in page headers and other contexts; only the sidebar menu
46 - * icon is neutral, per the WordPress.org plugin guidelines.
47 - */
48 -function accua_forms_admin_menu_icon(){
49 - $color = accua_forms_admin_menu_icon_color();
50 - $svg = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 44.46 44.46"><path fill="' . esc_attr($color) . '" d="m23.97,28.72c1.85,0,2.93-.11,2.93-.11,1.49-.15,2.75.95,2.8,2.44l.01.14c.05,1.5-1.11,2.96-2.58,3.25,0,0-2.53.5-5.25.5-7.24,0-10.11-3.84-10.11-12.98,0-8.6,3.01-12.44,10.26-12.44,2.82,0,5.11.47,5.11.47,1.47.3,2.63,1.78,2.57,3.27l-.01.15c-.05,1.5-1.31,2.6-2.8,2.45,0,0-1.13-.12-2.98-.12-4.67,0-5.54,1.6-5.54,6.22,0,5.2.92,6.76,5.59,6.76M33.36,1.93c-1.06-1.06-3.15-1.93-4.65-1.93H15.75c-1.5,0-3.59.87-4.65,1.93L1.93,11.1C.87,12.16,0,14.25,0,15.75v12.97c0,1.5.87,3.59,1.93,4.65l9.17,9.17c1.06,1.06,3.15,1.93,4.65,1.93h12.97c1.5,0,3.59-.87,4.65-1.93l9.17-9.17c1.06-1.06,1.93-3.15,1.93-4.65V15.75c0-1.5-.87-3.59-1.93-4.65z"/></svg>';
51 - return 'data:image/svg+xml;base64,' . base64_encode($svg);
52 -}
53 -
54 -/**
55 - * Repaint the sidebar menu icon with the active colour scheme's base colour.
56 - *
57 - * Runs on admin_init (priority 20, after register_admin_color_schemes at 1) when
58 - * the colour schemes are available. The icon set at menu-registration time uses
59 - * the fallback colour; here we overwrite it in the $menu global with the exact
60 - * scheme colour so the first paint matches svg-painter.js and there is no flash.
61 - */
62 -add_action('admin_init', 'accua_forms_paint_menu_icon', 20);
63 -function accua_forms_paint_menu_icon(){
64 - global $menu;
65 - if ( ! is_array($menu) ) {
66 - return;
67 - }
68 - foreach ( $menu as $i => $item ) {
69 - if ( isset($item[2]) && 'accua_forms' === $item[2] ) {
70 - $menu[$i][6] = accua_forms_admin_menu_icon();
71 - break;
72 - }
73 - }
74 -}
75 -
76 2 add_action('admin_menu', 'accua_forms_menu', -95);
77 3 function accua_forms_menu(){
78 - $dashboard_admin_page=add_menu_page('Contact Forms by Cimatti', 'Contact Forms', 'manage_options', 'accua_forms', 'accua_forms_dashboard_page', accua_forms_admin_menu_icon(), '90.90300');
4 + $dashboard_admin_page=add_menu_page('Wordpress Contact Forms by Cimatti', 'Contact Forms', 'manage_options', 'accua_forms', 'accua_forms_dashboard_page', ACCUA_FORMS_DIR_URL.'img/cimatti-icon-10.png', '90.90300');
79 5 add_action('load-'.$dashboard_admin_page, 'accua_forms_dashboard_page_head');
80 6
81 - add_submenu_page('accua_forms', 'Contact Forms by Cimatti', 'Dashboard', 'manage_options', "accua_forms", 'accua_forms_dashboard_page');
7 + add_submenu_page('accua_forms', 'Wordpress Contact Forms by Cimatti', 'Dashboard', 'manage_options', "accua_forms", 'accua_forms_dashboard_page');
82 8
83 9 $form_edit_page = add_submenu_page('accua_forms', 'Forms', 'Forms', 'manage_options', "accua_forms_list", 'accua_forms_list_page');
84 10 add_action('admin_head-'.$form_edit_page, 'accua_forms_edit_page_head');
85 11 add_action( 'admin_print_styles-'.$form_edit_page, 'accua_forms_edit_page_head_styles');
@@ -90,15 +16,14 @@
90 16 add_action( 'admin_print_styles-'.$form_add_page, 'accua_forms_edit_page_head_styles');
91 17 add_action( 'admin_print_scripts-'.$form_add_page, 'accua_forms_edit_page_head_scripts');
92 18
93 19 $form_submissions_page = add_submenu_page('accua_forms', __('Forms submissions', 'contact-forms') , __('Submissions', 'contact-forms'), 'manage_options', "accua_forms_submissions_list", '__accua_forms_submissions_list_page');
94 - add_action('load-'.$form_submissions_page, 'accua_forms_submissions_list_page_load');
95 20 add_action('admin_head-'.$form_submissions_page, 'accua_forms_submissions_list_page_head');
96 21 add_action( 'admin_print_styles-'.$form_submissions_page, 'accua_forms_edit_page_head_styles');
97 22
98 23 $form_fields_page = add_submenu_page('accua_forms', __( 'Form fields', 'contact-forms'), __('Fields', 'contact-forms'), 'manage_options', "accua_forms_fields", 'accua_forms_fields_page');
24 + //add_action('admin_head-'.$form_fields_page, 'accua_forms_fields_page_head');
99 25 add_action( 'admin_print_styles-'.$form_fields_page, 'accua_forms_edit_page_head_styles');
100 - add_action( 'admin_print_scripts-'.$form_fields_page, 'accua_forms_fields_page_enqueue_scripts');
101 26
102 27 $settings_page = add_submenu_page('accua_forms', __( 'Default Forms settings', 'contact-forms'), __('Settings', 'contact-forms'), 'manage_options', "accua_forms_settings", 'accua_forms_settings_page');
103 28 add_action( 'admin_print_styles-'.$settings_page, 'accua_forms_edit_page_head_styles');
104 29 add_action( 'admin_print_scripts-'.$settings_page, 'accua_forms_settings_page_head_scripts');
@@ -105,53 +30,173 @@
105 30
106 31 wp_enqueue_script('jquery-form');
107 32 wp_enqueue_script('jquery-color');
108 33 wp_enqueue_script('jquery-ui-core');
34 + wp_enqueue_script('jquery-ui-tabs');
109 35 wp_enqueue_script('jquery-ui-sortable');
110 36 wp_enqueue_script('jquery-ui-draggable');
111 37 wp_enqueue_script('jquery-ui-droppable');
38 + wp_enqueue_script('jquery-ui-selectable');
112 39 wp_enqueue_script('jquery-ui-resizable');
40 + wp_enqueue_script('jquery-ui-dialog');
41 + wp_enqueue_style('wp-jquery-ui-dialog');
113 42 }
114 43
44 +function accua_forms_report_page_head(){
45 + $column_list = array(
46 + 'month' => __( 'Month', 'contact-forms'),
47 + 'unique_submissions' => __( 'Unique submissions', 'contact-forms') ,
48 + 'submissions' => __('Total submissions', 'contact-forms'),
49 + );
50 + global $hook_suffix;
51 + register_column_headers($hook_suffix, $column_list);
52 +
53 + //$baseurl = WP_PLUGIN_URL.'/'.substr(plugin_basename(__FILE__),0,-strlen(basename(__FILE__)));
54 + //echo '<link href="'.$baseurl.'/flot/layout.css" rel="stylesheet" type="text/css">';
55 + //echo '<!--[if lte IE 8]><script language="javascript" type="text/javascript" src="'.$baseurl.'/flot/excanvas.min.js"></script><![endif]-->';
56 + //echo '<script language="javascript" type="text/javascript" src="'.$baseurl.'/flot/jquery.flot.js"></script>';
57 +
58 +}
59 +
60 +
61 +function accua_forms_report_page() {
62 +?>
63 + <div id="accua_forms_report_page" class="accua_forms_admin_page wrap">
64 + <h2>Forms submissions report</h2>
65 +
66 +<?php
67 + global $wpdb, $hook_suffix;
68 + $months = array(1 => 'January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December');
69 +
70 + $query = "SELECT YEAR(sub_date) AS `year`, MONTH(sub_date) AS `month`, COUNT(DISTINCT `email`) AS `unique_submissions`, COUNT(*) AS `submissions`
71 + FROM `{$wpdb->prefix}cformssubmissions`
72 + GROUP BY `year`, `month`
73 + ORDER BY `year` DESC, `month` DESC";
74 +
75 + $results = $wpdb->get_results($query);
76 +
77 + if ($results) {
78 +?>
79 + <style type="text/css">
80 + .column-submissions, .column-unique_submissions {
81 + text-align: right !important;
82 + }
83 + </style>
84 + <div id="accua-form-report-graph" style="height:300px;"></div>
85 + <table class="widefat" id="stnl_review_reviewed">
86 + <thead>
87 + <tr><?php print_column_headers($hook_suffix); ?></tr>
88 + </thead>
89 +
90 + <tfoot>
91 + <tr><?php print_column_headers($hook_suffix, false); ?></tr>
92 + </tfoot>
93 +
94 + <tbody>
95 +<?php
96 + $alternate = false;
97 + $hidden = get_hidden_columns($hook_suffix);
98 + $data = array(
99 + array( 'label' => __( 'Unique submissions', 'contact-forms'), 'data' => array()),
100 + array( 'label' => __( 'Total submissions', 'contact-forms'), 'data' => array()),
101 + );
102 + foreach ($results as $result){
103 + $month = $months[$result->month];
104 + echo "<tr class='iedit ".(($alternate = !$alternate)?'alternate':'')."'>\n";
105 + echo "<td class='column-month'".(in_array('month', $hidden)?" style='display:none;'":'').">$month {$result->year}</td>\n";
106 + echo "<td class='column-unique_submissions'".(in_array('unique_submissions', $hidden)?" style='display:none;'":'').">{$result->unique_submissions}</td>\n";
107 + echo "<td class='column-submissions'".(in_array('submissions', $hidden)?" style='display:none;'":'').">{$result->submissions}</td>\n";
108 + echo "</tr>\n";
109 + $time = mktime(0, 0, 0, $result->month, 1, $result->year) * 1000;
110 + $data[0]['data'][] = array($time, (int)$result->unique_submissions);
111 + $data[1]['data'][] = array($time, (int)$result->submissions);
112 + }
113 + /*
114 + $year = $results[0]->year;
115 + $month = $results[0]->month;
116 + while ($year <= $result->year || $month <= $result->month) {
117 +
118 + $month++;
119 + if ($month > 12) {
120 + $year++;
121 + $month = 1;
122 + }
123 + }
124 + */
125 +?>
126 + </tbody>
127 + </table>
128 +<script type="text/javascript">
129 +jQuery(function($){
130 + var data = <?php print _accua_forms_json_encode($data); ?> ;
131 + var options = {
132 + xaxis: {
133 + //autoscaleMargin: 0.005,
134 + mode: "time",
135 + timeformat: "%b %y",
136 + minTickSize: [1, "month"]
137 + },
138 + legend: {
139 + position: "nw"
140 + }
141 + };
142 + $.plot($("#accua-form-report-graph"), data, options);
143 +});
144 +</script>
145 +<?php
146 + }
147 +?>
148 +
149 + </div>
150 +<?php
151 +}
152 +
115 153 function accua_forms_edit_page_head_styles() {
116 - wp_enqueue_style( 'accua-forms-admin', plugins_url('assets/css/admin.css', ACCUA_FORMS_FILE), array(), ACCUA_FORMS_CSS_VERSION); //
154 + //wp_admin_css( 'widgets' );
155 + wp_enqueue_style( 'wp-pointer' ); //for tooltips
156 + wp_enqueue_style( 'accua-forms-admin', plugins_url('accua-forms-admin.css', ACCUA_FORMS_FILE), array(), ACCUA_FORMS_CSS_VERSION); //
117 157 }
118 158
119 -add_action( 'admin_enqueue_scripts', 'accua_forms_enqueue_deactivation_modal' );
120 -function accua_forms_enqueue_deactivation_modal( $hook ) {
121 - if ( $hook !== 'plugins.php' ) {
122 - return;
123 - }
159 +function accua_forms_edit_page_head_scripts() {
160 + //wp_enqueue_script('admin-widgets');
161 + /*wp_enqueue_script('jquery-ui-sortable');
162 + wp_enqueue_script('jquery-ui-draggable');
163 + wp_enqueue_script('jquery-ui-droppable');*/
164 + wp_enqueue_script( 'wp-pointer' ); //for tooltips
165 + wp_enqueue_script('accua-jqColorPicker', plugins_url('/js/jqColorPicker.min.js', ACCUA_FORMS_FILE ), array( 'jquery' ), ACCUA_FORMS_JS_VERSION);
124 166
125 - wp_enqueue_script(
126 - 'accua-forms-deactivation-modal',
127 - plugins_url( 'assets/js/admin/deactivation-modal.js', ACCUA_FORMS_FILE ),
128 - array( 'jquery' ),
129 - ACCUA_FORMS_JS_VERSION,
130 - true
131 - );
167 + wp_enqueue_script( 'accua-form-fields', plugins_url( 'form-fields.js' , ACCUA_FORMS_FILE ), array( 'jquery-ui-sortable', 'jquery-ui-draggable', 'jquery-ui-droppable' ), ACCUA_FORMS_JS_VERSION);
168 + wp_enqueue_script( 'accua-form-settings', plugins_url('form-settings.js', ACCUA_FORMS_FILE), array('jquery'), ACCUA_FORMS_JS_VERSION);
169 +}
132 170
133 - wp_localize_script( 'accua-forms-deactivation-modal', 'accuaFormsDeactivation', array(
134 - 'ajaxUrl' => admin_url( 'admin-ajax.php' ),
135 - 'nonce' => wp_create_nonce( 'accua_forms_deactivation_cleanup' ),
136 - 'pluginBasename' => plugin_basename( ACCUA_FORMS_FILE ),
137 - 'i18n' => array(
138 - 'title' => __( 'What would you like to do with your Contact Forms data?', 'contact-forms' ),
139 - 'description' => __( 'You are about to deactivate Contact Forms. Choose what to do with your existing data:', 'contact-forms' ),
140 - 'deleteAll' => __( 'Delete all data', 'contact-forms' ),
141 - 'deleteAllDesc' => __( 'Permanently remove all forms, submissions, settings, and uploaded files. This cannot be undone.', 'contact-forms' ),
142 - 'anonymizeAll' => __( 'Anonymize all submissions', 'contact-forms' ),
143 - 'anonymizeAllDesc'=> __( 'Replace personal data with placeholders and set IPs to 0.0.0.0. Forms and settings will be kept. This cannot be undone.', 'contact-forms' ),
144 - 'skip' => __( 'Just deactivate', 'contact-forms' ),
145 - 'skipDesc' => __( 'Keep all data. You can reactivate the plugin later.', 'contact-forms' ),
146 - 'confirmDelete' => __( 'Are you sure? This will permanently delete ALL forms, submissions, settings, and uploaded files. This cannot be undone.', 'contact-forms' ),
147 - 'confirmAnonymize'=> __( 'Are you sure? This will anonymize ALL submissions, replacing personal data with placeholders. This cannot be undone.', 'contact-forms' ),
148 - 'processing' => __( 'Processing…', 'contact-forms' ),
149 - 'cancel' => __( 'Cancel', 'contact-forms' ),
150 - ),
151 - ) );
171 +function accua_forms_settings_page_head_scripts() {
172 + wp_enqueue_script('accua-jqColorPicker', plugins_url('/js/jqColorPicker.min.js', ACCUA_FORMS_FILE ), array( 'jquery' ), ACCUA_FORMS_JS_VERSION);
152 173 }
153 174
175 +function accua_forms_edit_page_head() {
176 +if (isset($_POST['accua-form-edit-action']) || (!isset($_GET['fid']))) {
177 + _accua_forms_form_edit_action();
178 + require_once('accua-forms-list-page.php');
179 + accua_forms_list_page_table(true);
180 +}
181 +
182 +?>
183 + <style type="text/css">
184 + .container > div {
185 + padding: 0px;
186 + margin-bottom: 6px;
187 + }
188 + .widget-liquid-right .widget, #wp_inactive_widgets .widget, .widget-liquid-right .sidebar-description, .widget-placeholder {
189 + width: 95%;
190 + }
191 + .column-submissions {
192 + text-align: right !important;
193 + }
194 + </style>
195 +<?php
196 +}
197 +
198 +add_action( 'wp_ajax_accua-form-fields-order' , 'accua_forms_form_fields_order');
154 199 function accua_forms_form_fields_order() {
155 200 if (!current_user_can('manage_options')){
156 201 wp_die( -1, 403 );
157 202 }
@@ -157,29 +202,28 @@
157 202 }
158 203 check_ajax_referer('edit_form', '_nonce_edit_form');
159 204
160 205 $post = stripslashes_deep($_POST);
206 + //update_option('accua_forms_form_fields_order_post', $post);
161 207
162 208 if (empty($post['sidebars'])) {
163 209 die('-1');
164 210 }
165 211
166 - // Save to draft instead of directly to database
167 - foreach ($post['sidebars'] as $sidebar_id => $order) {
168 - if (strpos($sidebar_id, 'cimatti-accua-fields-form-area-') !== 0){
212 + $forms_data = get_option('accua_forms_saved_forms', array());
213 +
214 + foreach ($post['sidebars'] as $fid => $order) {
215 + if (strpos($fid, 'cimatti-accua-fields-form-area-') !== 0){
169 216 die('-1');
170 217 }
171 - $fid = substr($sidebar_id, 31);
218 + $fid = substr($fid, 31);
172 219
173 - // Get draft data for this form
174 - $draft_data = _accua_forms_get_draft_data($fid);
175 -
176 - if (empty($draft_data['fields'])) {
220 + if (empty($forms_data[$fid]['fields'])) {
177 221 die('-1');
178 222 }
179 223
180 - $old_fields = $draft_data['fields'];
181 - unset($draft_data['fields']);
224 + $old_fields = $forms_data[$fid]['fields'];
225 + unset($forms_data[$fid]['fields']);
182 226 $new_fields = array();
183 227
184 228 $order = explode(',', $order);
185 229
@@ -193,19 +237,18 @@
193 237
194 238 if($old_fields){
195 239 $new_fields += $old_fields;
196 240 }
197 - $draft_data['fields'] = $new_fields;
241 + $forms_data[$fid]['fields'] = $new_fields;
242 + }
198 243
199 - // Save to draft (not to live database)
200 - _accua_forms_save_draft($fid, $draft_data);
201 - }
244 + update_option('accua_forms_saved_forms', $forms_data);
202 245
203 246 die('1');
204 247 }
205 248
206 249 add_action( 'wp_ajax_accua-save-form-field', 'accua_forms_save_form_field');
207 -/* azione dove vengono salvati i campi dei un form - saves to draft */
250 +/* azione dove vengono salvati i campi dei un form */
208 251 function accua_forms_save_form_field() {
209 252 if (!current_user_can('manage_options')){
210 253 wp_die( -1, 403 );
211 254 }
@@ -212,17 +255,17 @@
212 255 check_ajax_referer('edit_form', '_nonce_edit_form');
213 256
214 257 $post = stripslashes_deep($_POST);
215 258
216 - $fid = isset($post['form-id']) ? $post['form-id'] : '';
259 + //update_option('accua_forms_save_form_field_post', $post);
260 +
261 + $forms_data = get_option('accua_forms_saved_forms', array());
262 + $fid = $post['form-id'];
217 263 if (accua_forms_validate_form_id($fid) !== '') {
218 264 die('-1');
219 265 }
220 -
221 - // Get draft data instead of live data
222 - $draft_data = _accua_forms_get_draft_data($fid);
223 - if (empty($draft_data['fields'])) {
224 - $draft_data['fields'] = array();
266 + if (empty($forms_data[$fid]['fields'])) {
267 + $forms_data[$fid]['fields'] = array();
225 268 }
226 269
227 270 $avail_fields = get_option('accua_forms_avail_fields', array());
228 271 @ $wid = (string) $post['widget-id'];
@@ -235,8 +278,9 @@
235 278 die('-1');
236 279 }
237 280 }
238 281 if (empty($post['delete_widget'])) {
282 + //$istance_id = $post['multi_number'];
239 283 @ $ref = $post['id_base'];
240 284 if ($ref !== $check_ref) {
241 285 die('-1');
242 286 }
@@ -242,15 +286,15 @@
242 286 }
243 287 $required = !empty($post["form-field-{$wid}-required"]);
244 288 $widget_number = empty($post['multi_number']) ? (empty($post['widget_number']) ? '' : (int)$post['widget_number']) : (int)$post['multi_number'];
245 289
246 - if (isset($draft_data['fields'][$wid])) {
247 - $old_istance_data = $draft_data['fields'][$wid];
290 + if (isset($forms_data[$fid]['fields'][$wid])) {
291 + $old_istance_data = $forms_data[$fid]['fields'][$wid];
248 292 } else {
249 293 $old_istance_data = array();
250 294 }
251 295
252 - $draft_data['fields'][$wid] = array (
296 + $forms_data[$fid]['fields'][$wid] = array (
253 297 'version' => 2,
254 298 'istance_id' => $wid,
255 299 'widget_number' => $widget_number,
256 300 'ref' => $ref,
@@ -261,9 +305,9 @@
261 305 @ $label = (string) $post["form-field-{$wid}-label"];
262 306 if (!current_user_can('unfiltered_html')) {
263 307 $label = wp_kses($label, 'post');
264 308 }
265 - $draft_data['fields'][$wid]['label'] = $label;
309 + $forms_data[$fid]['fields'][$wid]['label'] = $label;
266 310 }
267 311
268 312 $is_file = false;
269 313 $is_date = false;
@@ -269,9 +313,9 @@
269 313 $is_date = false;
270 314 if (isset($avail_fields[$wid]['type'])) {
271 315 if ($avail_fields[$wid]['type'] == 'file') {
272 316 $is_file = true;
273 - } elseif ($avail_fields[$wid]['type'] == 'date') {
317 + } else if ($avail_fields[$wid]['type'] == 'date') {
274 318 $is_date = true;
275 319 }
276 320 }
277 321
@@ -278,140 +322,36 @@
278 322 if (!empty($post["form-field-{$wid}-override-default-value"])) {
279 323 @ $default_value = (string) $post["form-field-{$wid}-default-value"];
280 324 if ($is_date) {
281 325 $default_value = accua_forms_filter_date($default_value);
282 - } elseif (!current_user_can('unfiltered_html')) {
326 + } else if (!current_user_can('unfiltered_html')) {
283 327 //This is filtered in any case because field type can change
284 328 $default_value = wp_kses($default_value, 'post');
285 329 }
286 - $draft_data['fields'][$wid]['default_value'] = $default_value;
330 + $forms_data[$fid]['fields'][$wid]['default_value'] = $default_value;
287 331 }
288 332
289 333 if (!empty($post["form-field-{$wid}-override-allowed-values"])) {
290 334 @ $allowed_values = (string) $post["form-field-{$wid}-allowed-values"];
291 335 if ($is_file){
292 - $draft_data['fields'][$wid]['allowed_extensions'] = accua_forms_filter_extensions($allowed_values);
336 + $forms_data[$fid]['fields'][$wid]['allowed_extensions'] = accua_forms_filter_extensions($allowed_values);
293 337 } else {
294 - $draft_data['fields'][$wid]['allowed_values'] = $allowed_values;
338 + $forms_data[$fid]['fields'][$wid]['allowed_values'] = $allowed_values;
295 339 }
296 340 }
297 341 if (!empty($post["form-field-{$wid}-override-datemin-values"])) {
298 342 @ $mindate_values = (string) $post["form-field-{$wid}-min-of-date"];
299 - $draft_data['fields'][$wid]['min_date'] = accua_forms_filter_date($mindate_values);
343 + $forms_data[$fid]['fields'][$wid]['min_date'] = accua_forms_filter_date($mindate_values);
300 344 }
301 345 if (!empty($post["form-field-{$wid}-override-datemax-values"])) {
302 346 @ $maxdate_values = (string) $post["form-field-{$wid}-max-of-date"];
303 - $draft_data['fields'][$wid]['max_date'] = accua_forms_filter_date($maxdate_values);
347 + $forms_data[$fid]['fields'][$wid]['max_date'] = accua_forms_filter_date($maxdate_values);
304 348 }
305 -
306 - // Save post_type for post-select and post-multicheckbox fields
307 - if (isset($post["form-field-{$wid}-post-type"])) {
308 - @ $post_type_value = (string) $post["form-field-{$wid}-post-type"];
309 - // Validate post type
310 - $valid_post_types = get_post_types(array('public' => true));
311 - if (isset($valid_post_types[$post_type_value])) {
312 - $draft_data['fields'][$wid]['post_type'] = $post_type_value;
313 - }
314 - }
315 -
316 - // Save spam action for reCAPTCHA v2/v3 fields (silent classification).
317 - // Only written when the "override" box is ticked - otherwise the instance
318 - // follows the site-wide default from the settings page.
319 - if (!empty($post["form-field-{$wid}-override-spam-action"]) && isset($post["form-field-{$wid}-spam-action"])) {
320 - $spam_action_value = sanitize_text_field($post["form-field-{$wid}-spam-action"]);
321 - if (isset(accua_forms_captcha_spam_action_options()[$spam_action_value])) {
322 - $draft_data['fields'][$wid]['spam_action'] = $spam_action_value;
323 - }
324 - }
325 -
326 - // Save the minimum reCAPTCHA v3 score for captcha_v3 fields
327 - if (!empty($post["form-field-{$wid}-override-score-threshold"]) && isset($post["form-field-{$wid}-score-threshold"])
328 - && is_numeric($post["form-field-{$wid}-score-threshold"])) {
329 - $draft_data['fields'][$wid]['score_threshold'] = accua_forms_recaptcha3_clamp_score($post["form-field-{$wid}-score-threshold"]);
330 - }
331 -
332 - // Save the hide-title flag for captcha fields. The override box decides
333 - // whether the value is stored at all: a missing key means the instance
334 - // follows the site-wide default resolved by
335 - // accua_forms_captcha_hide_title().
336 - if (!empty($post["form-field-{$wid}-override-hide-title"])
337 - && isset($avail_fields[$wid]['type'])
338 - && in_array($avail_fields[$wid]['type'], array('captcha', 'captcha_v3', 'cap'), true)) {
339 - $draft_data['fields'][$wid]['hide_title'] = empty($post["form-field-{$wid}-hide-title"]) ? 0 : 1;
340 - }
341 -
342 - // Save country_code for telephone fields (for libphonenumber validation)
343 - if (isset($post["form-field-{$wid}-country-code"])) {
344 - $country_code = strtoupper(sanitize_text_field($post["form-field-{$wid}-country-code"]));
345 - // Validate against the list of countries
346 - $valid_countries = accua_forms_get_countries();
347 - if (isset($valid_countries[$country_code])) {
348 - $draft_data['fields'][$wid]['country_code'] = $country_code;
349 - }
350 - }
351 -
352 - /**
353 - * Filter field instance data before saving to draft.
354 - *
355 - * @param array $field_instance The field instance data being saved.
356 - * @param string $widget_id The field widget ID.
357 - * @param array $post_data The raw POST data (already stripslashed).
358 - * @param array $field_def The field definition from avail_fields.
359 - */
360 - $draft_data['fields'][$wid] = apply_filters(
361 - 'accua_forms_save_field_data',
362 - $draft_data['fields'][$wid],
363 - $wid,
364 - $post,
365 - isset($avail_fields[$wid]) ? $avail_fields[$wid] : array()
366 - );
367 -
368 - // Save custom CSS class for the field wrapper
369 - if (isset($post["form-field-{$wid}-css-class"])) {
370 - $css_class_raw = sanitize_text_field($post["form-field-{$wid}-css-class"]);
371 - if ($css_class_raw !== '') {
372 - // Sanitize each class individually
373 - $classes = array_filter(array_map('sanitize_html_class', explode(' ', $css_class_raw)));
374 - $draft_data['fields'][$wid]['css_class'] = implode(' ', $classes);
375 - } else {
376 - $draft_data['fields'][$wid]['css_class'] = '';
377 - }
378 - }
379 -
380 - // Save custom CSS ID for the field wrapper
381 - if (isset($post["form-field-{$wid}-css-id"])) {
382 - $css_id_raw = sanitize_text_field($post["form-field-{$wid}-css-id"]);
383 - $draft_data['fields'][$wid]['css_id'] = sanitize_html_class($css_id_raw);
384 - }
385 -
386 - // Save fieldset style (fieldset-begin only)
387 - if (isset($post["form-field-{$wid}-fieldset-style"])) {
388 - $allowed_fieldset_styles = array(
389 - 'border-off-title-off', 'border-on-title-off',
390 - 'border-on-title-inline', 'border-on-title-outside',
391 - 'border-on-title-inside', 'border-off-title-on',
392 - );
393 - $fs = sanitize_text_field($post["form-field-{$wid}-fieldset-style"]);
394 - if (in_array($fs, $allowed_fieldset_styles, true)) {
395 - $draft_data['fields'][$wid]['fieldset_style'] = $fs;
396 - }
397 - }
398 -
399 - // Save custom required message override
400 - if (!empty($post["form-field-{$wid}-override-required-msg"])) {
401 - $draft_data['fields'][$wid]['custom_required_message'] = sanitize_text_field($post["form-field-{$wid}-custom-required-msg"]);
402 - }
403 -
404 - // Save custom format message override (email/phone)
405 - if (!empty($post["form-field-{$wid}-override-format-msg"])) {
406 - $draft_data['fields'][$wid]['custom_format_message'] = sanitize_text_field($post["form-field-{$wid}-custom-format-msg"]);
407 - }
408 349 } else {
409 - unset($draft_data['fields'][$wid]);
350 + unset($forms_data[$fid]['fields'][$wid]);
410 351 }
411 352
412 - // Save to draft (not to live database)
413 - _accua_forms_save_draft($fid, $draft_data);
353 + update_option('accua_forms_saved_forms', $forms_data);
414 354
415 355 die('1');
416 356 }
417 357
@@ -438,14 +378,23 @@
438 378 return accua_forms_filter_text($email);
439 379 }
440 380 }
441 381
382 +function accua_forms_filter_emails($emails) {
383 + $split_emails = preg_split("/\s*[,;]\s*/", $emails);
384 + $emails = array();
385 + foreach ($split_emails as $email) {
386 + $emails[] = accua_forms_filter_email($email);
387 + }
388 + return implode(', ', $emails);
389 +}
390 +
442 391 function accua_forms_filter_extensions($extensions) {
443 392 $cleaned_extensions = array();
444 393 $mimes = get_allowed_mime_types();
445 394 $extensions = explode("\n", $extensions);
446 395 foreach ($extensions as $extension) {
447 - $extension = strtolower( trim( ltrim( trim( $extension ), '.' ) ) );
396 + $extension = trim($extension);
448 397 if ($extension !== '') {
449 398 foreach ( $mimes as $ext_preg => $mime_match ) {
450 399 $ext_preg = '!^' . $ext_preg . '$!i';
451 400 if ( preg_match( $ext_preg, $extension ) ) {
@@ -469,14 +418,9 @@
469 418 //boolean
470 419 $form_settings[$k] = (bool) $v;
471 420 break;
472 421 case 'layout':
473 - // Only set if valid layout value, otherwise remove to use default
474 - if ($v === 'toplabel' || $v === 'inlinelabel' || $v === 'sidebyside') {
475 - $form_settings[$k] = $v;
476 - } else {
477 - unset($form_settings[$k]); // Reset to default
478 - }
422 + $form_settings[$k] = ($v === 'toplabel') ? 'toplabel' : 'sidebyside';
479 423 break;
480 424 case 'emails_from':
481 425 // single email
482 426 $form_settings[$k] = accua_forms_filter_email($v);
@@ -507,66 +451,8 @@
507 451 }
508 452 return $form_settings;
509 453 }
510 454
511 -/**
512 - * AJAX handler to restore default message values.
513 - *
514 - * Restores the default content for a specific message section:
515 - * - success_message: On-screen success message
516 - * - error_message: On-screen error message
517 - * - admin_emails: Admin notification email (subject + message only)
518 - * - confirmation_emails: Confirmation email (subject + message only)
519 - *
520 - * @since 2.0.0-beta.6
521 - */
522 -add_action('wp_ajax_accua_forms_restore_default_message', 'accua_forms_restore_default_message');
523 -function accua_forms_restore_default_message() {
524 - if (!current_user_can('manage_options')) {
525 - wp_send_json_error(array('message' => __('Permission denied.', 'contact-forms')), 403);
526 - }
527 -
528 - check_ajax_referer('accua_forms_restore_default', 'nonce');
529 -
530 - $message_type = isset($_POST['message_type']) ? sanitize_key($_POST['message_type']) : '';
531 -
532 - // Get default values
533 - $defaults = accua_forms_get_default_form_data();
534 -
535 - // Define which fields to restore for each message type
536 - $restore_map = array(
537 - 'success_message' => array('success_message'),
538 - 'error_message' => array('error_message'),
539 - 'admin_emails' => array('admin_emails_subject', 'admin_emails_message'),
540 - 'confirmation_emails' => array('confirmation_emails_subject', 'confirmation_emails_message'),
541 - );
542 -
543 - if (!isset($restore_map[$message_type])) {
544 - wp_send_json_error(array('message' => __('Invalid message type.', 'contact-forms')), 400);
545 - }
546 -
547 - // Get current form data
548 - $form_data = get_option('accua_forms_default_form_data', array());
549 - if (!is_array($form_data)) {
550 - $form_data = array();
551 - }
552 -
553 - // Restore the specified fields
554 - $restored_values = array();
555 - foreach ($restore_map[$message_type] as $field) {
556 - $form_data[$field] = $defaults[$field];
557 - $restored_values[$field] = $defaults[$field];
558 - }
559 -
560 - // Save updated form data
561 - update_option('accua_forms_default_form_data', $form_data);
562 -
563 - wp_send_json_success(array(
564 - 'message' => __('Default values restored successfully.', 'contact-forms'),
565 - 'values' => $restored_values,
566 - ));
567 -}
568 -
569 455 add_action( 'wp_ajax_accua-save-form-settings', 'accua_forms_save_form_settings');
570 456 function accua_forms_save_form_settings() {
571 457 if (!current_user_can('manage_options')){
572 458 wp_die( -1, 403 );
@@ -574,16 +460,14 @@
574 460 check_ajax_referer('edit_form', '_nonce_edit_form');
575 461
576 462 $post = stripslashes_deep($_POST);
577 463
578 - $fid = isset($post['form-id']) ? $post['form-id'] : '';
464 + $forms_data = get_option('accua_forms_saved_forms', array());
465 + $fid = $post['form-id'];
579 466 if (accua_forms_validate_form_id($fid) !== '') {
580 467 die('-1');
581 468 }
582 469
583 - // Get draft data instead of live data
584 - $draft_data = _accua_forms_get_draft_data($fid);
585 -
586 470 $settings = array(
587 471 'title',
588 472 'success_message',
589 473 'success_message_no_message',
@@ -598,9 +482,8 @@
598 482 'admin_emails_message_no_message',
599 483 'confirmation_emails_subject',
600 484 'confirmation_emails_message',
601 485 'confirmation_emails_message_no_message',
602 - 'gads_conversion_tracking_code',
603 486 //'use_ajax',
604 487
605 488 'layout',
606 489 'style_margin',
@@ -624,11 +507,8 @@
624 507 'style_submit_background_color',
625 508 'style_submit_padding',
626 509 'style_submit_color',
627 510 'style_submit_font_size',
628 - 'submission_retention_value',
629 - 'submission_retention_unit',
630 - 'submission_retention_mode',
631 511 );
632 512
633 513 // print_r($post);
634 514
@@ -636,328 +516,22 @@
636 516 foreach($settings as $i) {
637 517 if (isset($post[$i])) {
638 518 $new_form_settings[$i] = $post[$i];
639 519 }
640 - if (isset($draft_data[$i])) {
641 - unset($draft_data[$i]);
642 - }
520 + unset($forms_data[$fid][$i]);
643 521 }
644 522
645 - $draft_data += accua_forms_filter_settings($new_form_settings);
523 + $forms_data[$fid] += accua_forms_filter_settings($new_form_settings);
646 524
647 - $draft_data['use_ajax'] = !empty($post['use_ajax']);
648 - $draft_data['submission_retention_override'] = !empty($post['submission_retention_override']);
525 + $forms_data[$fid]['use_ajax'] = !empty($post['use_ajax']);
649 526
650 - // Save to draft (not to live database)
651 - _accua_forms_save_draft($fid, $draft_data);
527 + update_option('accua_forms_saved_forms', $forms_data);
652 528
653 - // Return JSON response for AJAX handler
654 - wp_send_json_success($draft_data);
655 -}
529 + //print_r($forms_data[$fid]);
656 530
657 -/**
658 - * AJAX handler to publish draft to live database.
659 - * Called when user clicks the Save button.
660 - */
661 -add_action( 'wp_ajax_accua-publish-form-draft', 'accua_forms_publish_form_draft');
662 -function accua_forms_publish_form_draft() {
663 - if (!current_user_can('manage_options')){
664 - wp_die( -1, 403 );
665 - }
666 - check_ajax_referer('edit_form', '_nonce_edit_form');
667 -
668 - $post = stripslashes_deep($_POST);
669 - $fid = isset($post['form-id']) ? $post['form-id'] : '';
670 -
671 - if (accua_forms_validate_form_id($fid) !== '') {
672 - wp_send_json_error(array('message' => __('Invalid form ID.', 'contact-forms')), 400);
673 - }
674 -
675 - // Publish the draft
676 - $result = _accua_forms_publish_draft($fid);
677 -
678 - if ($result) {
679 - wp_send_json_success(array('message' => __('Form saved successfully.', 'contact-forms')));
680 - } else {
681 - // Draft might not exist (nothing to publish) - this is OK for a new form
682 - // Check if form exists in database
683 - $forms_data = get_option('accua_forms_saved_forms', array());
684 - if (isset($forms_data[$fid])) {
685 - wp_send_json_success(array('message' => __('No changes to save.', 'contact-forms')));
686 - } else {
687 - wp_send_json_error(array('message' => __('Failed to save form.', 'contact-forms')), 500);
688 - }
689 - }
531 + die('');
690 532 }
691 533
692 -/**
693 - * AJAX handler to discard draft and reload from published data.
694 - * Called when user clicks "Discard changes".
695 - */
696 -add_action( 'wp_ajax_accua-discard-form-draft', 'accua_forms_discard_form_draft');
697 -function accua_forms_discard_form_draft() {
698 - if (!current_user_can('manage_options')){
699 - wp_die( -1, 403 );
700 - }
701 - check_ajax_referer('edit_form', '_nonce_edit_form');
702 -
703 - $post = stripslashes_deep($_POST);
704 - $fid = isset($post['form-id']) ? $post['form-id'] : '';
705 -
706 - if (accua_forms_validate_form_id($fid) !== '') {
707 - wp_send_json_error(array('message' => __('Invalid form ID.', 'contact-forms')), 400);
708 - }
709 -
710 - // Delete the draft
711 - _accua_forms_delete_draft($fid);
712 -
713 - wp_send_json_success(array('message' => __('Changes discarded.', 'contact-forms')));
714 -}
715 -
716 -/**
717 - * Filter an admin-configured post_status value for post fields down to the
718 - * statuses those fields may expose in a public dropdown: publish and private.
719 - *
720 - * Draft/pending/future content is never exposed, regardless of configuration.
721 - *
722 - * @since 2.2.27
723 - * @param string|array $post_status Comma-separated string or array of statuses.
724 - * @return array Allowed statuses (may be empty).
725 - */
726 -function accua_forms_filter_field_post_status($post_status) {
727 - if (!is_array($post_status)) {
728 - $post_status = explode(',', (string) $post_status);
729 - }
730 - $post_status = array_map('trim', $post_status);
731 - return array_values(array_intersect($post_status, array('publish', 'private')));
732 -}
733 -
734 -/**
735 - * Check whether an extra_args string received from the AJAX endpoint matches a
736 - * post-select / post-multicheckbox configuration actually stored by an admin,
737 - * for the post type the request resolved to.
738 - *
739 - * The extra_args string is echoed into the form markup and sent back by the
740 - * browser, so it is client-controlled. Privileged parameters (post_status=private)
741 - * are only honored when the exact string exists in a saved field configuration -
742 - * otherwise any visitor could craft a request that enumerates private post titles.
743 - * The post type is part of the match: a query string saved for one post type must
744 - * not unlock private posts of a different type (the field's post type lives in a
745 - * separate setting, so the string alone does not identify what it exposes).
746 - *
747 - * @since 2.2.27
748 - * @param string $extra_args Sanitized extra_args string from the request.
749 - * @param string $post_type Post type the request resolved to (after the
750 - * post_type override inside extra_args, if any).
751 - * @return bool True when a stored field configuration matches both.
752 - */
753 -function accua_forms_extra_args_is_saved_config($extra_args, $post_type) {
754 - $extra_args = trim($extra_args);
755 - if ($extra_args === '') {
756 - return false;
757 - }
758 -
759 - // Candidate configurations: array of (allowed_values, configured post type).
760 - $candidates = array();
761 - $avail_fields = get_option('accua_forms_avail_fields', array());
762 - foreach ($avail_fields as $field) {
763 - if (!empty($field['type']) && ($field['type'] === 'post-select' || $field['type'] === 'post-multicheckbox') && isset($field['allowed_values'])) {
764 - $candidates[] = array($field['allowed_values'], isset($field['post_type']) ? $field['post_type'] : 'page');
765 - }
766 - }
767 - $forms = get_option('accua_forms_saved_forms', array());
768 - foreach ($forms as $form) {
769 - if (empty($form['fields']) || !is_array($form['fields'])) {
770 - continue;
771 - }
772 - foreach ($form['fields'] as $inst) {
773 - if (!is_array($inst) || empty($inst['ref']) || !isset($avail_fields[$inst['ref']]['type'])) {
774 - continue;
775 - }
776 - $type = $avail_fields[$inst['ref']]['type'];
777 - if (($type === 'post-select' || $type === 'post-multicheckbox') && isset($inst['allowed_values'])) {
778 - $inst_post_type = isset($inst['post_type']) ? $inst['post_type']
779 - : (isset($avail_fields[$inst['ref']]['post_type']) ? $avail_fields[$inst['ref']]['post_type'] : 'page');
780 - $candidates[] = array($inst['allowed_values'], $inst_post_type);
781 - }
782 - }
783 - }
784 -
785 - foreach ($candidates as $candidate) {
786 - list($candidate_args, $candidate_post_type) = $candidate;
787 - if (trim(sanitize_text_field($candidate_args)) !== $extra_args) {
788 - continue;
789 - }
790 - // Resolve the candidate's effective post type the same way the request
791 - // does: a post_type override inside the string wins over the field setting.
792 - $candidate_extra = array();
793 - wp_parse_str($extra_args, $candidate_extra);
794 - if (!empty($candidate_extra['post_type'])) {
795 - $candidate_post_type = sanitize_text_field($candidate_extra['post_type']);
796 - }
797 - if ($candidate_post_type === $post_type) {
798 - return true;
799 - }
800 - }
801 - return false;
802 -}
803 -
804 -/**
805 - * AJAX handler to get posts for post-select fields with pagination.
806 - * Available to both logged-in and anonymous users (for frontend forms).
807 - *
808 - * @since 2.0.0-beta.29
809 - */
810 -add_action('wp_ajax_accua_forms_get_posts', 'accua_forms_ajax_get_posts');
811 -add_action('wp_ajax_nopriv_accua_forms_get_posts', 'accua_forms_ajax_get_posts');
812 -function accua_forms_ajax_get_posts() {
813 - // Verify nonce
814 - // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.MissingUnslash, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Nonce verification
815 - if (!isset($_REQUEST['_nonce']) || !wp_verify_nonce($_REQUEST['_nonce'], 'accua_forms_get_posts')) {
816 - wp_send_json_error(array('message' => __('Security check failed.', 'contact-forms')), 403);
817 - }
818 -
819 - // Sanitize inputs
820 - $post_type = isset($_REQUEST['post_type']) ? sanitize_text_field(wp_unslash($_REQUEST['post_type'])) : 'page';
821 - $search = isset($_REQUEST['search']) ? sanitize_text_field(wp_unslash($_REQUEST['search'])) : '';
822 - $page = isset($_REQUEST['page']) ? absint($_REQUEST['page']) : 1;
823 - $per_page = isset($_REQUEST['per_page']) ? min(absint($_REQUEST['per_page']), 100) : 50;
824 - $extra_args = isset($_REQUEST['extra_args']) ? sanitize_text_field(wp_unslash($_REQUEST['extra_args'])) : '';
825 - $selected = isset($_REQUEST['selected']) ? sanitize_text_field(wp_unslash($_REQUEST['selected'])) : '';
826 -
827 - // Validate post type
828 - $valid_post_types = get_post_types(array('public' => true));
829 - if (!isset($valid_post_types[$post_type])) {
830 - $post_type = 'page';
831 - }
832 -
833 - // Calculate offset
834 - $offset = ($page - 1) * $per_page;
835 -
836 - // Statuses the response may contain (extended below when the field
837 - // configuration explicitly requests private posts).
838 - $allowed_statuses = array('publish');
839 -
840 - // Build query arguments
841 - $args = array(
842 - 'post_type' => $post_type,
843 - 'number' => $per_page + 1, // Get one extra to check if there are more
844 - 'offset' => $offset,
845 - 's' => $search,
846 - );
847 -
848 - // Parse extra arguments (backward compatibility with allowed_values textarea)
849 - if (!empty($extra_args)) {
850 - // Parse the query string format
851 - $extra = array();
852 - wp_parse_str($extra_args, $extra);
853 -
854 - // Allow post_type override from extra_args (backward compatibility)
855 - if (isset($extra['post_type'])) {
856 - $override_post_type = sanitize_text_field($extra['post_type']);
857 - // Validate the overridden post type
858 - if (isset($valid_post_types[$override_post_type])) {
859 - $post_type = $override_post_type;
860 - $args['post_type'] = $post_type;
861 - }
862 - }
863 -
864 - // Merge only safe parameters
865 - $safe_params = array('meta_key', 'meta_value', 'authors', 'parent', 'child_of', 'exclude', 'include', 'sort_column', 'sort_order');
866 - foreach ($safe_params as $param) {
867 - if (isset($extra[$param])) {
868 - $args[$param] = $extra[$param];
869 - }
870 - }
871 -
872 - // post_status is a privileged parameter: only publish/private are ever
873 - // honored, and 'private' only when the extra_args string matches a field
874 - // configuration stored by an admin (or the user can read private posts,
875 - // e.g. the form editor preview). Otherwise a visitor could craft a request
876 - // that enumerates private post titles.
877 - if (!empty($extra['post_status'])) {
878 - $requested_statuses = accua_forms_filter_field_post_status($extra['post_status']);
879 - if (in_array('private', $requested_statuses, true)
880 - && !current_user_can('read_private_posts')
881 - && !accua_forms_extra_args_is_saved_config($extra_args, $post_type)) {
882 - $requested_statuses = array('publish');
883 - }
884 - if (!empty($requested_statuses)) {
885 - $args['post_status'] = $requested_statuses;
886 - $allowed_statuses = $requested_statuses;
887 - }
888 - }
889 - }
890 -
891 - // Get posts using WPML-compatible function
892 - $posts = accua_get_pages($args);
893 -
894 - // Check if there are more results
895 - $has_more = count($posts) > $per_page;
896 - if ($has_more) {
897 - array_pop($posts); // Remove the extra item
898 - }
899 -
900 - // Format results for the dropdown
901 - $results = array();
902 - foreach ($posts as $post) {
903 - $results[] = array(
904 - 'id' => $post->ID,
905 - 'text' => $post->post_title,
906 - );
907 - }
908 -
909 - // If this is the first page and we have a selected value, ensure it's in the list
910 - if ($page === 1 && !empty($selected) && is_numeric($selected)) {
911 - $selected_id = absint($selected);
912 - $found = false;
913 - foreach ($results as $result) {
914 - if ($result['id'] === $selected_id) {
915 - $found = true;
916 - break;
917 - }
918 - }
919 - // If selected post not in results, fetch it separately and prepend.
920 - // Only statuses the field is allowed to expose (publish, plus private when
921 - // explicitly configured): this endpoint is available to anonymous visitors,
922 - // so it must not disclose titles of other drafts/private/pending posts.
923 - if (!$found) {
924 - $selected_post = get_post($selected_id);
925 - if ($selected_post && $selected_post->post_type === $post_type && in_array($selected_post->post_status, $allowed_statuses, true)) {
926 - array_unshift($results, array(
927 - 'id' => $selected_post->ID,
928 - 'text' => $selected_post->post_title,
929 - ));
930 - }
931 - }
932 - }
933 -
934 - wp_send_json_success(array(
935 - 'results' => $results,
936 - 'more' => $has_more,
937 - 'page' => $page,
938 - ));
939 -}
940 -
941 -/**
942 - * Get available public post types for the post-select field editor.
943 - *
944 - * @since 2.0.0-beta.29
945 - * @return array Array of post type slug => label pairs.
946 - */
947 -function accua_forms_get_public_post_types() {
948 - $post_types = get_post_types(array('public' => true), 'objects');
949 - $options = array();
950 - foreach ($post_types as $post_type) {
951 - // Skip attachments
952 - if ($post_type->name === 'attachment') {
953 - continue;
954 - }
955 - $options[$post_type->name] = $post_type->labels->singular_name;
956 - }
957 - return $options;
958 -}
959 -
960 534 function accua_forms_field_settings_form_counter() {
961 535 static $i = 0;
962 536 $i++;
963 537 return $i;
@@ -997,10 +571,8 @@
997 571 $override_label = isset($istance_data['label']) ? 'checked="checked"' : '';
998 572 $override_default_value = isset($istance_data['default_value']) ? 'checked="checked"' : '';
999 573 $override_allowed_values = isset($istance_data['allowed_values']) ? 'checked="checked"' : '';
1000 574 $override_allowed_extensions = '';
1001 - $override_custom_required_msg = isset($istance_data['custom_required_message']) ? 'checked="checked"' : '';
1002 - $override_custom_format_msg = isset($istance_data['custom_format_message']) ? 'checked="checked"' : '';
1003 575
1004 576 if ($field_data['type'] == 'file') {
1005 577 if (isset($istance_data['version']) && $istance_data['version'] >= 2) {
1006 578 if (isset($istance_data['allowed_extensions'])) {
@@ -1027,8 +599,10 @@
1027 599
1028 600 if ($field_data['type'] == 'date') {
1029 601 $override_mindate_values = isset($istance_data['min_date']) ? 'checked="checked"' : '';
1030 602 $override_maxdate_values = isset($istance_data['max_date']) ? 'checked="checked"' : '';
603 + //$override_default_value = isset($istance_data['default_date_value']) ? 'checked="checked"' : '';
604 +
1031 605 $istance_data += array(
1032 606 'min_date' => $field_data['min_date'],
1033 607 'max_date' => $field_data['max_date'],
1034 608 'default_value' => $field_data['default_date_value'],
@@ -1044,22 +618,16 @@
1044 618 'default_value' => $field_data['default_value'],
1045 619 'allowed_values' => $field_data['allowed_values'],
1046 620 'allowed_extensions' => $field_data['allowed_extensions'],
1047 621 'required' => false,
1048 - 'post_type' => 'page', // Default post type for post-select fields
1049 - 'css_class' => '',
1050 - 'css_id' => '',
1051 - 'custom_required_message' => '',
1052 - 'custom_format_message' => '',
1053 - 'fieldset_style' => 'border-off-title-off',
1054 622 );
1055 623
1056 624 foreach ($istance_data as $key => $value) {
1057 - $istance_data[$key] = esc_attr($istance_data[$key]);
625 + $istance_data[$key] = htmlspecialchars($istance_data[$key], ENT_QUOTES);
1058 626 }
1059 627
1060 628 foreach ($field_data as $key => $value) {
1061 - $field_data[$key] = esc_attr($field_data[$key]);
629 + $field_data[$key] = htmlspecialchars($field_data[$key], ENT_QUOTES);
1062 630 }
1063 631
1064 632 $multi_number = '';
1065 633 $add_new = '';
@@ -1080,9 +648,9 @@
1080 648 $forceoverride_field = false;
1081 649 $add_new = $empty_istance ? 'single' : '';
1082 650 }
1083 651
1084 - $fid = esc_attr($fid);
652 + $fid = htmlspecialchars($fid, ENT_QUOTES);
1085 653 $testi_eot = array (
1086 654 'label' => __( 'Label', 'contact-forms'),
1087 655 'override' => __( 'override', 'contact-forms'),
1088 656 'default_value' => __( 'Default value', 'contact-forms'),
@@ -1093,10 +661,8 @@
1093 661 'allowed_extensions' => __( 'Allowed extensions', 'contact-forms'),
1094 662 'desc_all_ext' => __( 'Accepted file extensions. One per line, without dots.', 'contact-forms'),
1095 663 'required' => __( 'Required', 'contact-forms'),
1096 664 'custom_HTML_content' => __( 'Custom HTML content', 'contact-forms'),
1097 - 'refresh_preview' => __( 'Refresh Preview', 'contact-forms'),
1098 - 'add' => __( 'Add field', 'contact-forms'),
1099 665 'remove' => __( 'Remove', 'contact-forms'),
1100 666 'close' => __( 'Close', 'contact-forms'),
1101 667 'save' => __( 'Save', 'contact-forms'),
1102 668 'min-of-date' => __( 'Min date', 'contact-forms'),
@@ -1112,9 +678,8 @@
1112 678 $override_type = 'checkbox';
1113 679 $override_end = ')';
1114 680 }
1115 681
1116 - // phpcs:disable PluginCheck.CodeAnalysis.Heredoc.NotAllowed, WordPress.Security.EscapeOutput.HeredocOutputNotEscaped -- Heredoc used for HTML templates with pre-escaped variables
1117 682 $content = <<<EOT
1118 683 <p><label for="widget-{$istance_data['istance_id']}-label">{$testi_eot['label']}:</label>
1119 684 {$override_begin}<input type="{$override_type}" name="form-field-{$istance_data['istance_id']}-override-label" value="1" {$override_label} />{$override_end}<br>
1120 685 <input type="text" value="{$istance_data['label']}" name="form-field-{$istance_data['istance_id']}-label" id="widget-{$istance_data['istance_id']}-label" class="widefat"></p>
@@ -1152,43 +717,8 @@
1152 717 <p><label for="widget-{$istance_data['istance_id']}-required">{$testi_eot['required']}:</label>
1153 718 <input type="checkbox" value="1" {$required_checked} name="form-field-{$istance_data['istance_id']}-required" id="widget-{$istance_data['istance_id']}-required"></p>
1154 719 EOT;
1155 720
1156 - // Custom required message override (checkbox + text input, same pattern as custom label)
1157 - $custom_required_msg_label = __( 'Custom required message', 'contact-forms');
1158 - // translators: %s is the field name/label
1159 - $custom_required_msg_desc = __( 'Overrides the default "required" error message. Use %s for the field name.', 'contact-forms');
1160 - $custom_required_msg = <<<EOT
1161 - <p><label for="widget-{$istance_data['istance_id']}-custom-required-msg">{$custom_required_msg_label}:</label>
1162 - {$override_begin}<input type="{$override_type}" name="form-field-{$istance_data['istance_id']}-override-required-msg" value="1" {$override_custom_required_msg} />{$override_end}<br>
1163 - <input type="text" value="{$istance_data['custom_required_message']}" name="form-field-{$istance_data['istance_id']}-custom-required-msg" id="widget-{$istance_data['istance_id']}-custom-required-msg" class="widefat"><br>
1164 - <small>{$custom_required_msg_desc}</small></p>
1165 -EOT;
1166 -
1167 - // Custom format message override for email and telephone fields
1168 - $custom_format_msg = '';
1169 - if ($field_data['type'] === 'email' || $field_data['type'] === 'autoreply_email') {
1170 - $custom_format_msg_label = __( 'Custom invalid email message', 'contact-forms');
1171 - // translators: %s is the field name/label
1172 - $custom_format_msg_desc = __( 'Overrides the default email format error message. Use %s for the field name.', 'contact-forms');
1173 - $custom_format_msg = <<<EOT
1174 - <p><label for="widget-{$istance_data['istance_id']}-custom-format-msg">{$custom_format_msg_label}:</label>
1175 - {$override_begin}<input type="{$override_type}" name="form-field-{$istance_data['istance_id']}-override-format-msg" value="1" {$override_custom_format_msg} />{$override_end}<br>
1176 - <input type="text" value="{$istance_data['custom_format_message']}" name="form-field-{$istance_data['istance_id']}-custom-format-msg" id="widget-{$istance_data['istance_id']}-custom-format-msg" class="widefat"><br>
1177 - <small>{$custom_format_msg_desc}</small></p>
1178 -EOT;
1179 - } elseif ($field_data['type'] === 'telephone') {
1180 - $custom_format_msg_label = __( 'Custom invalid phone message', 'contact-forms');
1181 - // translators: %s is the field name/label
1182 - $custom_format_msg_desc = __( 'Overrides the default phone format error message. Use %s for the field name.', 'contact-forms');
1183 - $custom_format_msg = <<<EOT
1184 - <p><label for="widget-{$istance_data['istance_id']}-custom-format-msg">{$custom_format_msg_label}:</label>
1185 - {$override_begin}<input type="{$override_type}" name="form-field-{$istance_data['istance_id']}-override-format-msg" value="1" {$override_custom_format_msg} />{$override_end}<br>
1186 - <input type="text" value="{$istance_data['custom_format_message']}" name="form-field-{$istance_data['istance_id']}-custom-format-msg" id="widget-{$istance_data['istance_id']}-custom-format-msg" class="widefat"><br>
1187 - <small>{$custom_format_msg_desc}</small></p>
1188 -EOT;
1189 - }
1190 -
1191 721 if ($field_data['type'] == 'date'){
1192 722 $default_date_value = <<<EOT
1193 723 <p><label for="widget-{$istance_data['istance_id']}-default-value">{$testi_eot['default_value']}:</label>
1194 724 {$override_begin}<input type="{$override_type}" name="form-field-{$istance_data['istance_id']}-override-default-value" value="1" {$override_default_value} />{$override_end}<br>
@@ -1205,137 +735,8 @@
1205 735 <input type="date" value="{$istance_data['max_date']}" name="form-field-{$istance_data['istance_id']}-max-of-date" id="widget-{$istance_data['istance_id']}-max-of-date"></p>
1206 736 EOT;
1207 737 }
1208 738
1209 - // Post type selector for post-select and post-multicheckbox fields
1210 - $post_type_selector = '';
1211 - if ($field_data['type'] === 'post-select' || $field_data['type'] === 'post-multicheckbox') {
1212 - $override_post_type = isset($istance_data['post_type']) && $istance_data['post_type'] !== 'page' ? 'checked="checked"' : '';
1213 - $post_types = accua_forms_get_public_post_types();
1214 - $post_type_options = '';
1215 - $current_post_type = esc_attr($istance_data['post_type']);
1216 - foreach ($post_types as $pt_slug => $pt_label) {
1217 - $selected = ($pt_slug === $current_post_type) ? ' selected="selected"' : '';
1218 - $post_type_options .= '<option value="' . esc_attr($pt_slug) . '"' . $selected . '>' . esc_html($pt_label) . '</option>';
1219 - }
1220 - $post_type_label = __('Post type', 'contact-forms');
1221 - $post_type_desc = __('Select which post type to show in the dropdown.', 'contact-forms');
1222 - $query_params_label = __('Additional query parameters', 'contact-forms');
1223 - // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_value -- This is example help text, not actual code.
1224 - $query_params_desc = __('Optional: Filter posts using query parameters (e.g., authors=admin or meta_key=featured&meta_value=1). Add post_status=publish,private to also include private posts (their titles become visible to all visitors of this form). Leave empty for all published posts of the selected type.', 'contact-forms');
1225 - $post_type_selector = <<<EOT
1226 - <p><label for="widget-{$istance_data['istance_id']}-post-type">{$post_type_label}:</label>
1227 - {$override_begin}<input type="{$override_type}" name="form-field-{$istance_data['istance_id']}-override-post-type" value="1" {$override_post_type} />{$override_end}<br>
1228 - <select name="form-field-{$istance_data['istance_id']}-post-type" id="widget-{$istance_data['istance_id']}-post-type" class="widefat">{$post_type_options}</select><br />
1229 - {$post_type_desc}</p>
1230 - <p><label for="widget-{$istance_data['istance_id']}-allowed-values">{$query_params_label}:</label>
1231 - {$override_begin}<input type="{$override_type}" name="form-field-{$istance_data['istance_id']}-override-allowed-values" value="1" {$override_allowed_values} />{$override_end}<br>
1232 - <textarea rows="3" cols="50" name="form-field-{$istance_data['istance_id']}-allowed-values" id="widget-{$istance_data['istance_id']}-allowed-values" class="widefat">{$istance_data['allowed_values']}</textarea><br />
1233 - {$query_params_desc}</p>
1234 -EOT;
1235 - }
1236 -
1237 - // Country selector for telephone fields (for libphonenumber validation)
1238 - $country_selector = '';
1239 - if ($field_data['type'] === 'telephone') {
1240 - $countries = accua_forms_get_countries();
1241 - $current_country = isset($istance_data['country_code']) ? esc_attr($istance_data['country_code']) : 'IT';
1242 - $override_country = isset($istance_data['country_code']) && $istance_data['country_code'] !== 'IT' ? 'checked="checked"' : '';
1243 - $country_options = '';
1244 - foreach ($countries as $code => $country_name) {
1245 - $selected = ($code === $current_country) ? ' selected="selected"' : '';
1246 - $country_options .= '<option value="' . esc_attr($code) . '"' . $selected . '>' . esc_html($country_name) . '</option>';
1247 - }
1248 - $country_label = __('Default country', 'contact-forms');
1249 - // translators: Help text for phone field country selector in form editor
1250 - $country_desc = __('For numbers without international prefix, validation assumes this country.', 'contact-forms');
1251 - $country_selector = <<<EOT
1252 - <p><label for="widget-{$istance_data['istance_id']}-country-code">{$country_label}:</label>
1253 - {$override_begin}<input type="{$override_type}" name="form-field-{$istance_data['istance_id']}-override-country-code" value="1" {$override_country} />{$override_end}<br>
1254 - <select name="form-field-{$istance_data['istance_id']}-country-code" id="widget-{$istance_data['istance_id']}-country-code" class="widefat">{$country_options}</select><br />
1255 - {$country_desc}</p>
1256 -EOT;
1257 - }
1258 -
1259 - // Spam action selector for reCAPTCHA v2 and v3 fields (silent classification).
1260 - // Like every other field setting it is an override of the site-wide default
1261 - // configured in the plugin settings page.
1262 - $spam_action_selector = '';
1263 - if ($field_data['type'] === 'captcha' || $field_data['type'] === 'captcha_v3') {
1264 - $spam_actions = accua_forms_captcha_spam_action_options();
1265 - $current_spam_action = accua_forms_captcha_spam_action($istance_data, $field_data['type']);
1266 - $override_spam_action = isset($istance_data['spam_action']) ? 'checked="checked"' : '';
1267 - $spam_action_options = '';
1268 - foreach ($spam_actions as $sa_key => $sa_label) {
1269 - $sa_selected = ($sa_key === $current_spam_action) ? ' selected="selected"' : '';
1270 - $spam_action_options .= '<option value="' . esc_attr($sa_key) . '"' . $sa_selected . '>' . esc_html($sa_label) . '</option>';
1271 - }
1272 - $spam_action_label = __('When the spam check fails', 'contact-forms');
1273 - if ($field_data['type'] === 'captcha_v3') {
1274 - // translators: Help text for the reCAPTCHA v3 spam action selector in the form editor
1275 - $spam_action_desc = __('reCAPTCHA v3 classifies visitors silently with a score. Choose what happens to a submission that fails the check: accept it silently (normal success message, no notification emails) and mark it with the Spam lead status, move it to Trash, or delete it immediately without storing anything, or reject it with a visible error.', 'contact-forms');
1276 - } else {
1277 - // translators: Help text for the reCAPTCHA v2 spam action selector in the form editor
1278 - $spam_action_desc = __('Choose what happens to a submission whose reCAPTCHA verification fails: accept it silently (normal success message, no notification emails) and mark it with the Spam lead status, move it to Trash, or delete it immediately without storing anything, or reject it with a visible error so the visitor can retry the challenge.', 'contact-forms');
1279 - }
1280 - $spam_action_selector = <<<EOT
1281 - <p><label for="widget-{$istance_data['istance_id']}-spam-action">{$spam_action_label}:</label>
1282 - {$override_begin}<input type="{$override_type}" name="form-field-{$istance_data['istance_id']}-override-spam-action" value="1" {$override_spam_action} />{$override_end}<br>
1283 - <select name="form-field-{$istance_data['istance_id']}-spam-action" id="widget-{$istance_data['istance_id']}-spam-action" class="widefat">{$spam_action_options}</select><br>
1284 - <small>{$spam_action_desc}</small></p>
1285 -EOT;
1286 - }
1287 -
1288 - // Minimum score override for reCAPTCHA v3 fields
1289 - $score_threshold_field = '';
1290 - if ($field_data['type'] === 'captcha_v3') {
1291 - $current_score_threshold = esc_attr(number_format(accua_forms_recaptcha3_score_threshold($istance_data), 2, '.', ''));
1292 - $override_score_threshold = isset($istance_data['score_threshold']) ? 'checked="checked"' : '';
1293 - $score_threshold_label = __('Minimum score', 'contact-forms');
1294 - // translators: Help text for the reCAPTCHA v3 minimum score field in the form editor
1295 - $score_threshold_desc = __('reCAPTCHA v3 scores every visitor from 0.0 (almost certainly a bot) to 1.0 (almost certainly a person). Submissions scoring below this value fail the spam check. Google suggests 0.5; raise it to be stricter, lower it if legitimate visitors are being caught.', 'contact-forms');
1296 - $score_threshold_field = <<<EOT
1297 - <p><label for="widget-{$istance_data['istance_id']}-score-threshold">{$score_threshold_label}:</label>
1298 - {$override_begin}<input type="{$override_type}" name="form-field-{$istance_data['istance_id']}-override-score-threshold" value="1" {$override_score_threshold} />{$override_end}<br>
1299 - <input type="number" min="0" max="1" step="0.01" value="{$current_score_threshold}" name="form-field-{$istance_data['istance_id']}-score-threshold" id="widget-{$istance_data['istance_id']}-score-threshold" class="widefat"><br>
1300 - <small>{$score_threshold_desc}</small></p>
1301 -EOT;
1302 - }
1303 -
1304 - // Hide-title override for captcha fields
1305 - $hide_title_field = '';
1306 - if (in_array($field_data['type'], array('captcha', 'captcha_v3', 'cap'), true)) {
1307 - $hide_title_checked = accua_forms_captcha_hide_title($istance_data) ? 'checked="checked"' : '';
1308 - $override_hide_title = isset($istance_data['hide_title']) ? 'checked="checked"' : '';
1309 - $hide_title_label = __('Hide field title', 'contact-forms');
1310 - // translators: Help text for the hide-title checkbox on captcha fields in the form editor
1311 - $hide_title_desc = __('Do not display the field title in the form. The title stays in the markup for screen readers and error messages.', 'contact-forms');
1312 - $hide_title_field = <<<EOT
1313 - <p><label for="widget-{$istance_data['istance_id']}-hide-title">{$hide_title_label}:</label>
1314 - {$override_begin}<input type="{$override_type}" name="form-field-{$istance_data['istance_id']}-override-hide-title" value="1" {$override_hide_title} />{$override_end}<br>
1315 - <input type="checkbox" value="1" {$hide_title_checked} name="form-field-{$istance_data['istance_id']}-hide-title" id="widget-{$istance_data['istance_id']}-hide-title"><br>
1316 - <small>{$hide_title_desc}</small></p>
1317 -EOT;
1318 - }
1319 -
1320 - // CSS Class and CSS ID fields (universal, apply to all field types)
1321 - $css_class_label = __( 'CSS Class', 'contact-forms');
1322 - $css_id_label = __( 'CSS ID', 'contact-forms');
1323 - // translators: Help text for CSS Class field in form editor
1324 - $css_class_desc = __( 'Custom CSS class(es) for the field wrapper. Separate multiple classes with spaces.', 'contact-forms');
1325 - // translators: Help text for CSS ID field in form editor
1326 - $css_id_desc = __( 'Custom CSS ID for the field wrapper. Must be unique on the page.', 'contact-forms');
1327 - $css_class_field = <<<EOT
1328 - <p><label for="widget-{$istance_data['istance_id']}-css-class">{$css_class_label}:</label><br>
1329 - <input type="text" value="{$istance_data['css_class']}" name="form-field-{$istance_data['istance_id']}-css-class" id="widget-{$istance_data['istance_id']}-css-class" class="widefat"><br>
1330 - <small>{$css_class_desc}</small></p>
1331 -EOT;
1332 - $css_id_field = <<<EOT
1333 - <p><label for="widget-{$istance_data['istance_id']}-css-id">{$css_id_label}:</label><br>
1334 - <input type="text" value="{$istance_data['css_id']}" name="form-field-{$istance_data['istance_id']}-css-id" id="widget-{$istance_data['istance_id']}-css-id" class="widefat"><br>
1335 - <small>{$css_id_desc}</small></p>
1336 -EOT;
1337 -
1338 739 switch ($field_data['type']) {
1339 740 case 'textarea':
1340 741 $content .= <<<EOT
1341 742 <p><label for="widget-{$istance_data['istance_id']}-default-value">{$testi_eot['default_value']}:</label>
@@ -1341,9 +742,8 @@
1341 742 <p><label for="widget-{$istance_data['istance_id']}-default-value">{$testi_eot['default_value']}:</label>
1342 743 {$override_begin}<input type="{$override_type}" name="form-field-{$istance_data['istance_id']}-override-default-value" value="1" {$override_default_value} />{$override_end}<br>
1343 744 <textarea rows="6" cols="50" name="form-field-{$istance_data['istance_id']}-default-value" id="widget-{$istance_data['istance_id']}-default-value" class="widefat">{$istance_data['default_value']}</textarea></p>
1344 745 $required
1345 - $custom_required_msg
1346 746 EOT;
1347 747 break;
1348 748 case 'hidden':
1349 749 $content = $default_value;
@@ -1348,58 +748,26 @@
1348 748 case 'hidden':
1349 749 $content = $default_value;
1350 750 break;
1351 751 case 'checkbox':
1352 - $content .= $default_value . $required . $custom_required_msg;
752 + $content .= $default_value . $required;
1353 753 break;
1354 754 case 'select':
1355 755 case 'radio':
1356 - $content .= $default_value . $allowed_values . $required . $custom_required_msg;
1357 - break;
1358 756 case 'post-select':
1359 - $content .= $default_value . $post_type_selector . $required . $custom_required_msg;
757 + $content .= $default_value . $allowed_values . $required;
1360 758 break;
1361 759 case 'multiselect':
1362 760 case 'multicheckbox':
1363 - $content .= $default_values . $allowed_values . $required . $custom_required_msg;
1364 - break;
1365 761 case 'post-multicheckbox':
1366 - $content .= $default_values . $post_type_selector . $required . $custom_required_msg;
762 + $content .= $default_values . $allowed_values . $required;
1367 763 break;
1368 764 case 'file':
1369 - $content .= $allowed_ext . $required . $custom_required_msg;
1370 - break;
765 + $content .= $allowed_ext . $required;
1371 766 case 'submit':
767 + case 'fieldset-begin':
1372 768 //just the label
1373 769 break;
1374 - case 'fieldset-begin':
1375 - $fs_label_text = __('Border and Title', 'contact-forms');
1376 - $gt_label_text = __('Group Title', 'contact-forms');
1377 - // translators: Help text under the Group Title field for fieldset groups in the form editor
1378 - $gt_desc_text = __('Section heading. Shown in the form when a title option is selected.', 'contact-forms');
1379 - $fs_opts_map = array(
1380 - 'border-off-title-off' => __('Border OFF | Title OFF', 'contact-forms'),
1381 - 'border-on-title-off' => __('Border ON | Title OFF', 'contact-forms'),
1382 - 'border-on-title-inline' => __('Border ON | Title ON (inline)', 'contact-forms'),
1383 - 'border-on-title-outside' => __('Border ON | Title ON (outside)', 'contact-forms'),
1384 - 'border-on-title-inside' => __('Border ON | Title ON (inside)', 'contact-forms'),
1385 - 'border-off-title-on' => __('Border OFF | Title ON', 'contact-forms'),
1386 - );
1387 - $fs_options_html = '';
1388 - foreach ($fs_opts_map as $opt_val => $opt_label) {
1389 - $opt_selected = ($istance_data['fieldset_style'] === $opt_val) ? ' selected="selected"' : '';
1390 - $fs_options_html .= '<option value="' . esc_attr($opt_val) . '"' . $opt_selected . '>' . esc_html($opt_label) . '</option>';
1391 - }
1392 - $content = <<<EOT
1393 - <p><label for="widget-{$istance_data['istance_id']}-label">{$gt_label_text}:</label><br>
1394 - <input type="hidden" name="form-field-{$istance_data['istance_id']}-override-label" value="1">
1395 - <input type="text" value="{$istance_data['label']}" name="form-field-{$istance_data['istance_id']}-label" id="widget-{$istance_data['istance_id']}-label" class="widefat"><br>
1396 - <small>{$gt_desc_text}</small></p>
1397 - <p><label for="widget-{$istance_data['istance_id']}-fieldset-style">{$fs_label_text}:</label><br>
1398 - <select name="form-field-{$istance_data['istance_id']}-fieldset-style" id="widget-{$istance_data['istance_id']}-fieldset-style" class="widefat accua-fieldset-style-select">{$fs_options_html}</select></p>
1399 -EOT;
1400 - $content .= $css_class_field . $css_id_field;
1401 - break;
1402 770 case 'fieldset-end':
1403 771 //Nothing!
1404 772 $content = '';
1405 773 break;
@@ -1407,67 +775,28 @@
1407 775 $content = <<<EOT
1408 776 <p><label for="widget-{$istance_data['istance_id']}-default-value">{$testi_eot['custom_HTML_content']}</label>
1409 777 {$override_begin}<input type="{$override_type}" name="form-field-{$istance_data['istance_id']}-override-default-value" value="1" {$override_default_value} />{$override_end}<br>
1410 778 <textarea rows="6" cols="50" name="form-field-{$istance_data['istance_id']}-default-value" id="widget-{$istance_data['istance_id']}-default-value" class="widefat">{$istance_data['default_value']}</textarea></p>
1411 - <p><a href="#" class="accua-refresh-preview">{$testi_eot['refresh_preview']}</a></p>
1412 779 EOT;
1413 780 break;
1414 781 case 'date':
1415 - $content .= $default_date_value . $min_date . $max_date . $required . $custom_required_msg;
782 + $content .= $default_date_value . $min_date . $max_date . $required;
1416 783 break;
1417 - case 'telephone':
1418 - $content .= $default_value . $country_selector . $required . $custom_required_msg . $custom_format_msg;
1419 - break;
1420 784 case 'email':
1421 785 case 'autoreply_email':
1422 - $content .= $default_value . $required . $custom_required_msg . $custom_format_msg;
1423 - break;
1424 - case 'captcha':
1425 - case 'captcha_v3':
1426 - case 'cap':
1427 - case 'turnstile':
1428 - // Captcha fields consume neither default_value nor the custom required
1429 - // message (their validators are set in the element constructors), so
1430 - // those rows are not offered. The extension-settings action still fires
1431 - // for parity with the default case.
1432 - ob_start();
1433 - do_action( 'accua_forms_field_settings', $field_data['type'], $field_data, $istance_data );
1434 - $extra_settings = ob_get_clean();
1435 - $content .= $extra_settings . $hide_title_field . $score_threshold_field . $spam_action_selector . $required;
1436 - break;
1437 786 case 'textfield':
1438 787 case 'colorpicker':
1439 788 case 'datepicker':
1440 789 case 'dateselect':
1441 790 default:
1442 - /**
1443 - * Action to render additional field settings in the form editor.
1444 - *
1445 - * @param string $field_type The field type identifier.
1446 - * @param array $field_data The field definition.
1447 - * @param array $istance_data The field instance data.
1448 - * @param string $content The current settings HTML (passed by reference via output buffering).
1449 - */
1450 - ob_start();
1451 - do_action( 'accua_forms_field_settings', $field_data['type'], $field_data, $istance_data );
1452 - $extra_settings = ob_get_clean();
1453 - // The captcha-only rows (hide title, score, spam action) render in the
1454 - // dedicated captcha case above and are always empty here.
1455 - $content .= $default_value . $extra_settings . $required . $custom_required_msg;
791 + $content .= $default_value . $required;
1456 792 break;
1457 793 }
1458 -
1459 - // Append CSS Class and CSS ID fields to all types except fieldset-end (which has no settings)
1460 - if ($field_data['type'] !== 'fieldset-end' && $field_data['type'] !== 'fieldset-begin') {
1461 - $content .= $css_class_field . $css_id_field;
1462 - }
1463 -
1464 794 $adminurl = admin_url();
1465 795
1466 796 return <<<EOT
1467 -<div class="widget ui-draggable" id="widget-{$i}_{$istance_data['istance_id']}" data-field-type="{$field_data['type']}" $hidden> <div class="widget-top">
797 +<div class="widget ui-draggable" id="widget-{$i}_{$istance_data['istance_id']}" $hidden> <div class="widget-top">
1468 798 <div class="widget-title-action">
1469 - <a href="#add-field" class="widget-add-action hide-if-no-js" title="{$testi_eot['add']}" aria-label="{$testi_eot['add']}"></a>
1470 799 <a href="#available-widgets" class="widget-action hide-if-no-js"></a>
1471 800 </div>
1472 801 <div class="widget-title"><h4>{$field_data['name']}<span class="in-widget-title"></span></h4></div>
1473 802 </div>
@@ -1491,9 +820,10 @@
1491 820 <a href="#remove" class="widget-control-remove delete">{$testi_eot['remove']}</a> |
1492 821 <a href="#close" class="widget-control-close">{$testi_eot['close']}</a>
1493 822 </div>
1494 823 <div class="alignright">
1495 - <input type="submit" value="{$testi_eot['save']}" class="button button-primary widget-control-save accua-field-save-btn" id="widget-{$istance_data['istance_id']}-savewidget" name="savewidget">
824 + <img alt="" title="" class="ajax-feedback" src="{$adminurl}images/wpspin_light.gif">
825 + <input type="submit" value="{$testi_eot['save']}" class="button-primary widget-control-save" id="widget-{$istance_data['istance_id']}-savewidget" name="savewidget">
1496 826 </div>
1497 827 <br class="clear">
1498 828 </div>
1499 829 </form>
@@ -1504,17 +834,1853 @@
1504 834 </div>-->
1505 835 </div>
1506 836
1507 837 EOT;
1508 - // phpcs:enable PluginCheck.CodeAnalysis.Heredoc.NotAllowed, WordPress.Security.EscapeOutput.HeredocOutputNotEscaped
1509 838 }
1510 839
840 +function accua_forms_add_page($message='') {
841 + $forms_data = get_option('accua_forms_saved_forms', array());
842 + $trash_data = get_option('accua_forms_trash_forms', array());
843 + if (!empty($_GET['fid'])) {
844 + $fid = htmlspecialchars(stripslashes($_GET['fid']), ENT_QUOTES);
845 + } else {
846 + if ($message === '') {
847 + $fid = 1 + ((int) get_option('accua_forms_lastid', 0));
848 + while (isset($forms_data[$fid]) || isset($trash_data[$fid])) {
849 + $fid++;
850 + }
851 + update_option('accua_forms_lastid', $fid);
852 + $message = _accua_forms_test_clonefrom($fid);
853 + if ($message === '') {
854 + return accua_forms_edit_page($fid);
855 + }
856 + } else {
857 + $fid = '';
858 + }
859 + }
860 + if (!empty($_GET['clonefrom'])) {
861 + check_admin_referer('clone_posts');
862 + $clonefrom = stripslashes($_GET['clonefrom']);
863 + } else {
864 + $clonefrom = '';
865 + }
866 +?>
1511 867
1512 -// _accua_forms_get_abs_dest_path() now lives in includes/data-deletion.php, which
1513 -// uninstall.php requires on its own - the deletion needs the same path this file
1514 -// uploads to, and uninstall runs with the plugin unloaded.
868 +<div id="accua_forms_add_page" class="accua_forms_admin_page wrap">
869 +<h2><?php _e( 'Create a form', 'contact-forms'); ?> </h2>
870 +<?php if ($message !== '') {
871 + echo "<div style='border:1px solid; padding: 10px;'>$message</div>";
872 +} ?>
873 +<form action="admin.php" method="GET">
874 +<?php wp_nonce_field('edit_posts', '_wpnonce', false, true) ?>
875 +<input type="hidden" name="page" value="accua_forms_list" />
876 +<p>Form id: <input type="text" name="fid" value="<?php echo $fid; ?>" /></p>
877 +<?php
878 + if ($forms_data) {
879 + echo '<p><select name="clonefrom">
880 + <option value="">'.__( 'Empty form', 'contact-forms').'</option>
881 + <optgroup label="'.__( 'Clone form:', 'contact-forms').'">';
882 + foreach ($forms_data as $i => $formdata) {
883 + $sel = ($i == $clonefrom) ? " selected='selected'" : '';
884 + $i = htmlspecialchars($i, ENT_QUOTES);
885 + if (isset($formdata['title']) && ('' !== trim($formdata['title']))) {
886 + $formtitle = htmlspecialchars($formdata['title']);
887 + } else {
888 + $formtitle = $i;
889 + }
890 + echo "<option value='$i'$sel>$formtitle</option>\n";
891 + }
892 + echo '</optgroup></select></p>';
893 + }
894 +?>
895 +<p><input type="submit" value="<?php _e( 'Create', 'contact-forms'); ?>" /></p>
896 +</form>
897 +</div>
898 +<?php
899 +}
1515 900
1516 -// phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedFunctionFound -- Internal helper function, underscore prefix indicates private
901 +function _accua_forms_test_clonefrom($fid){
902 + $error = '';
903 + if (isset($_GET['clonefrom'])&&$_GET['clonefrom']!=='') {
904 + $clonefrom = stripslashes($_GET['clonefrom']);
905 + $forms_data = get_option('accua_forms_saved_forms', array());
906 + if (isset($forms_data[$fid])){
907 + $error .= "<p>".__( 'Form already exists', 'contact-forms')."</p>";
908 + } else if (empty($forms_data[$clonefrom])) {
909 + $error .= "<p>".__( 'Source form doesn\'t exists.', 'contact-forms')."</p>";
910 + } else {
911 + $forms_data[$fid] = $forms_data[$clonefrom];
912 + if (!isset($forms_data[$fid]['title'])) {
913 + $forms_data[$fid]['title'] = $clonefrom ." ".__( 'clone', 'contact-forms');
914 + } else {
915 + $forms_data[$fid]['title'] .= " ". __( 'clone', 'contact-forms');
916 + }
917 + update_option('accua_forms_saved_forms', $forms_data);
918 + }
919 + }
920 + return $error;
921 +}
922 +
923 +function _accua_forms_form_edit_action() {
924 + static $message = null;
925 + if ($message === null) {
926 + $message = '';
927 + if (isset($_POST['accua-form-edit-action'])){
928 + $post = stripslashes_deep($_POST);
929 + switch ($post['accua-form-edit-action']) {
930 + case 'delete':
931 + $fid = $post['form-id'];
932 + check_admin_referer('contact-forms-delete_'.$fid);
933 + $forms_data = get_option('accua_forms_saved_forms', array());
934 + unset($forms_data[$fid]);
935 + update_option('accua_forms_saved_forms', $forms_data);
936 + $fid = htmlspecialchars($fid);
937 + $message .= sprintf( __( 'Form "%s" deleted','contact-forms' ), $fid );
938 + break;
939 + }
940 + }
941 + }
942 + return $message;
943 +}
944 +
945 +function accua_forms_validate_form_id($fid) {
946 + $error = '';
947 + if (!preg_match('/^[a-z0-9_-]+$/i', $fid)) {
948 + $error .= "<p>".__( 'Only letters, numbers, hyphen and underscores allowed in form identificative name', 'contact-forms')."</p>";
949 + }
950 + if (substr($fid,0,2) == '__') {
951 + $error .= "<p>".__( 'The identificative name can\'t start with two underscores (__)', 'contact-forms')."</p>";
952 + }
953 + if (strlen($fid) > 70) {
954 + $error .= "<p>".__( 'You cannot use more than 70 characters for the identificative name', 'contact-forms')."</p>";
955 + }
956 + return $error;
957 +}
958 +
959 +function accua_forms_list_page() {
960 + $message = '';
961 + if (isset($_POST['accua-form-edit-action'])){
962 + $message = _accua_forms_form_edit_action();
963 + } else if (isset($_GET['fid'])) {
964 + check_admin_referer('edit_posts');
965 + $fid = stripslashes($_GET['fid']);
966 + $error = accua_forms_validate_form_id($fid);
967 + if ($error === '' && (isset($_GET['clonefrom'])&&$_GET['clonefrom']!=='')) {
968 + $error .= _accua_forms_test_clonefrom($fid);
969 + }
970 + if ($error === '') {
971 + return accua_forms_edit_page($fid);
972 + } else {
973 + return accua_forms_add_page($error);
974 + }
975 + }
976 +?>
977 +<div id="accua_forms_list_page" class="accua_forms_admin_page wrap">
978 +<?php if ($message !== '') {
979 + echo "<div style='border:1px solid; padding: 10px;'>$message</div>";
980 +} ?>
981 +<h2><img src="<?php echo ACCUA_FORMS_DIR_URL.'img/cimatti-icon-20.png'; ?>"/> <?php _e( 'Contact Forms', 'contact-forms'); ?>
982 + <a class="add-new-h2" href="<?php echo get_admin_url(); ?>admin.php?page=accua_forms_add"><?php _e('Add New','contact-forms'); ?></a>
983 +</h2>
984 +<div ><?php
985 + echo strtr(__( 'Use the turquoise blue %img_c button in the TinyMCE editor to include the forms in posts, pages or other content types (shortcode and php functions also available)', 'contact-forms'),
986 + array('%img_c'=>'<img alt="C" src="' . plugins_url('img/cimatti-icon-16.png', ACCUA_FORMS_FILE ) . '" />')
987 + );
988 +?></div>
989 +<?php
990 +accua_forms_list_page_table();
991 +?>
992 +</div>
993 +<?php
994 +}
995 +
996 +function accua_forms_edit_page($fid) {
997 + wp_enqueue_script('jquery-ui-tabs','','','',true);
998 + wp_enqueue_script('contact_forms_tabs', plugins_url('accua_tabs.js', ACCUA_FORMS_FILE ), array( 'jquery' ), ACCUA_FORMS_JS_VERSION);
999 +
1000 + if (!class_exists('AccuaFormsHelp')) {
1001 + require_once('accua-forms-help.php');
1002 + }
1003 + $accuaHelp = AccuaFormsHelp::getInstance();
1004 + /*
1005 + $avail_fields = array(
1006 + 'first_name' => array (
1007 + 'id' => "first_name",
1008 + 'name' => "First Name",
1009 + 'type' => "textfield",
1010 + 'description' => 'This is the first name',
1011 + ),
1012 + 'last_name' => array (
1013 + 'id' => "last_name",
1014 + 'name' => "Last Name",
1015 + 'type' => "textfield",
1016 + 'description' => 'This is the last name',
1017 + ),
1018 + 'email' => array (
1019 + 'id' => "email",
1020 + 'name' => "Email",
1021 + 'type' => "email",
1022 + 'description' => 'This is the email',
1023 + ),
1024 + );
1025 + */
1026 +
1027 + $avail_fields = get_option('accua_forms_avail_fields', array());
1028 + $default_form_data = get_option('accua_forms_default_form_data',array());
1029 +
1030 +
1031 +
1032 + $form_data = _accua_forms_get_form_data($fid, true, !empty($_GET['restore']));
1033 + $form_overrided_data = $form_data['_overrided'];
1034 +
1035 + $fid_esc = htmlspecialchars($fid, ENT_QUOTES);
1036 +
1037 + $adminurl = admin_url();
1038 +
1039 + global $wp_version;
1040 + if (version_compare($wp_version, '4') >= 0) {
1041 +?>
1042 +<style>
1043 +#widgets-right .accua-form-widget-scroll-wrapper .widget.ui-draggable {
1044 + height: auto !important;
1045 +}
1046 +</style>
1047 +<?php
1048 + }
1049 +
1050 +?>
1051 +<div id="accua_forms_edit_page" class="accua_forms_admin_page wrap">
1052 +<h2><img src="<?php echo ACCUA_FORMS_DIR_URL.'img/cimatti-icon-20.png'; ?>"/> <?php _e('Contact Forms - Edit Form', 'contact-forms'); ?></h2>
1053 +<div class="accua_form_save_settings_status"></div>
1054 +<?php wp_nonce_field('edit_form', '_nonce_edit_form'); ?>
1055 +<div id="titlediv"><br />
1056 + <label id="title-prompt-text" class="screen-reader-text" for="title"><?php _e( 'Enter title here', 'contact-forms'); ?></label>
1057 + <input id="title" type="text" autocomplete="off" value="<?php echo htmlspecialchars($form_data['title'], ENT_QUOTES) ?>" size="30" name="post_title">
1058 + <script type="text/javascript">
1059 + jQuery(function($){
1060 + if ( jQuery('#titlediv #title').val() == '' )
1061 + jQuery('#title-prompt-text').removeClass('screen-reader-text');
1062 +
1063 + jQuery('#titlediv #title').focus(function() {
1064 + jQuery('#title-prompt-text').addClass('screen-reader-text');
1065 + });
1066 + jQuery('#titlediv #title').blur(function() {
1067 + if ( jQuery('#titlediv #title').val() == '' )
1068 + jQuery('#title-prompt-text').removeClass('screen-reader-text');
1069 + });
1070 + });
1071 + </script>
1072 +</div>
1073 + <div id="accua_tabs">
1074 + <div id="save_settings_top" class="accua_forms_save_settings_top">
1075 + <form id="delete_form" action="admin.php?page=accua_forms_list" method="POST" onsubmit="return confirm(<?php print htmlspecialchars(_accua_forms_json_encode(__('Do you really want to delete this form?', 'contact-forms')), ENT_QUOTES); ?>);">
1076 + <input type="hidden" name="accua-form-edit-action" value="delete" />
1077 + <input type="hidden" name="form-id" value="<?php echo $fid_esc; ?>" />
1078 + <input type="submit" value="<?php _e( 'Delete this form', 'contact-forms'); ?>" />
1079 + <?php wp_nonce_field( 'contact-forms-delete_'.$fid ); ?>
1080 + </form>
1081 + <?php /*<input class="button button-primary button-large accua_form_save_settings_button" id="accua_form_save_settings" type="button" value="<?php echo htmlspecialchars(__( 'Save settings', 'contact-forms'), ENT_QUOTES); ?>" /> */ ?>
1082 + </div>
1083 + <ul id="ul_accua_tabs">
1084 + <li class="tabs"><a href="#accua_tab_fields"><?php _e( 'Fields', 'contact-forms'); ?></a></li>
1085 + <li class="tabs"><a href="#accua_tab_messages"><?php _e( 'Messages', 'contact-forms'); ?></a></li>
1086 + <?php /*<li class="tabs"><a href="#accua_tab_preview"><?php _e( 'Preview/Test', 'contact-forms'); ?></a></li> */ ?>
1087 + </ul>
1088 + <div id="accua_tab_fields" class="content_tab">
1089 + <div style="width:50%; float:left;background: #f4f4f4;">
1090 + <div style="padding: 20px;">
1091 + <input class="button button-primary button-large accua_form_save_settings_button" id="accua_form_save_settings_inside" type="button" value="<?php echo htmlspecialchars(__( 'Save', 'contact-forms'), ENT_QUOTES); ?>" />
1092 + <div id="accua_tabs2">
1093 + <ul>
1094 + <li class="tabs"><a href="#accua_tab_fields2"><?php _e( 'Fields', 'contact-forms'); ?></a></li>
1095 + <li class="tabs"><a href="#accua_tab_customise"><?php _e( 'Appearance', 'contact-forms'); ?></a></li>
1096 + </ul>
1097 + <div id="accua_tab_fields2">
1098 + <h2><?php _e( 'Drag & Drop Form Fields', 'contact-forms'); ?></h2>
1099 + <?php /*<a href="admin.php?page=accua_forms_fields" target="_blank"><strong><?php _e( 'Create new fields here', 'contact-forms'); ?></strong></a></p> */ ?>
1100 + <div style="width:30%; float:left;">
1101 + <!-- Begin available fields -->
1102 +
1103 + <div class="widget-liquid-left" style="margin-right:0">
1104 + <!-- <div id="widgets-left"> -->
1105 + <div id="widgets-left" style="margin-right:5px;">
1106 + <div id="available-widgets" class="widgets-holder-wrap">
1107 + <div class="widget-holder">
1108 + <div id="widget-list">
1109 + <!-- begin fields list -->
1110 +
1111 + <?php
1112 +
1113 + //This block must be executed before the output of available fields so accua_forms_field_text_settings_form() can initialize $html_multi_number for further html and fieldset fields
1114 + $form_fields_html = '';
1115 + foreach ($form_data['fields'] as $field) {
1116 + if (empty($avail_fields[$field['ref']])) {
1117 + $ref = array();
1118 + if (!empty($field['ref'])) {
1119 + if ($field['ref'] == '__fieldset-begin') {
1120 + $ref = array(
1121 + 'id' => '__fieldset-begin',
1122 + 'name' => __('Fieldset begin', 'contact-forms'),
1123 + 'type' => 'fieldset-begin',
1124 + 'description' => '',
1125 + );
1126 + } else if ($field['ref'] == '__fieldset-end') {
1127 + $ref = array(
1128 + 'id' => '__fieldset-end',
1129 + 'name' => __('Fieldset end', 'contact-forms'),
1130 + 'type' => 'fieldset-end',
1131 + 'description' => '',
1132 + );
1133 + }
1134 + }
1135 + } else {
1136 + $ref = $avail_fields[$field['ref']];
1137 + }
1138 +
1139 + //print_r($ref);
1140 + $form_fields_html .= accua_forms_field_text_settings_form($fid, $ref, $field);
1141 + }
1142 +
1143 +
1144 + foreach ($avail_fields as $avail_field) {
1145 + $hidden = (empty($form_data['fields'][$avail_field['id']])) ? false : 'hidden';
1146 + echo accua_forms_field_text_settings_form($fid, $avail_field, $hidden);
1147 + }
1148 + //Custom HTML field
1149 + echo accua_forms_field_text_settings_form($fid);
1150 + //Fieldset begin
1151 + echo accua_forms_field_text_settings_form($fid, array(
1152 + 'id' => '__fieldset-begin',
1153 + 'name' => __( 'Fieldset begin', 'contact-forms'),
1154 + 'type' => 'fieldset-begin',
1155 + 'description' => __('You can use this field multiple times.', 'contact-forms'),
1156 + 'default_value' => '',
1157 + 'allowed_values' => '',
1158 + ));
1159 + //Fieldset end
1160 + echo accua_forms_field_text_settings_form($fid, array(
1161 + 'id' => '__fieldset-end',
1162 + 'name' => __( 'Fieldset end', 'contact-forms'),
1163 + 'type' => 'fieldset-end',
1164 + 'description' => __('You can use this field multiple times.', 'contact-forms'),
1165 + 'default_value' => '',
1166 + 'allowed_values' => '',
1167 + ));
1168 + ?>
1169 +
1170 + <!-- end fields list -->
1171 + </div>
1172 +
1173 + <br class='clear' />
1174 + </div>
1175 + <br class="clear" />
1176 + </div>
1177 +
1178 + </div>
1179 + </div>
1180 + <!-- End available fields -->
1181 + </div>
1182 +
1183 + <div style="width:70%; float:left;" class="container">
1184 + <!--
1185 + <h3>Form Fields</h3>
1186 + <div id="form_fields_container">
1187 + </div>
1188 + -->
1189 +
1190 + <div class="widget-liquid-right" style="width:100%">
1191 + <div id="widgets-right" style="width:100%">
1192 + <div class="widgets-holder-wrap dashed">
1193 + <div class="sidebar-name">
1194 + <div class="sidebar-name-arrow"><br></div>
1195 + <h3><?php _e( 'Drop fields here', 'contact-forms'); ?> <span><img alt="" title="" class="ajax-feedback" src="<?php echo $adminurl;?>images/wpspin_light.gif"></span></h3>
1196 + </div>
1197 + <div class="widgets-sortables ui-sortable" id="cimatti-accua-fields-form-area-<?php echo $fid_esc ?>">
1198 + <?php echo $form_fields_html; ?>
1199 + </div>
1200 + </div>
1201 + </div>
1202 + </div>
1203 +
1204 + </div>
1205 + </div>
1206 + <div id="accua_tab_customise">
1207 + <div style="width: 48%; float:left;">
1208 + <h3><?php _e( 'General', 'contact-forms'); ?></h3>
1209 + <p id="accua_form_use_ajax"><input class="accua_form_value" type="checkbox" value="1" <?php if (!empty($form_data['use_ajax'])) {echo 'checked="checked" ';} ?>/><?php _e('Do not reload the page on form submission', 'contact-forms'); ?></p>
1210 +
1211 + <p id="accua_form_layout"><?php _e( 'Labels', 'contact-forms'); ?> <select name="layout" class="accua_form_value">
1212 + <option value="" <?php if (isset($form_overrided_data['layout'])) { echo 'selected="selected"'; } ?>>default (<?php if($default_form_data['layout']=='sidebyside') _e( 'Labels on the left of the fields', 'contact-forms'); else _e( 'Labels on top of the fields', 'contact-forms'); ?>)</option><option value="sidebyside" <?php if ((isset($form_overrided_data['layout'])) && ($form_data['layout'] == 'sidebyside')) { echo 'selected="selected"'; } ?>><?php _e( 'Labels on the left of the fields', 'contact-forms'); ?></option><option value="toplabel" <?php if ((isset($form_overrided_data['layout'])) && ($form_data['layout'] == 'toplabel')) { echo 'selected="selected"'; } ?>><?php _e( 'Labels on top of the fields', 'contact-forms'); ?></option></select>
1213 + </p>
1214 +
1215 + <div id="accua_form_style_margin" class="label_input" class="label_container">
1216 + <input name="accua_form_style_margin" class="accua_form_check_override" type="checkbox" value="1" <?php if (isset($form_overrided_data['style_margin'])) {echo 'checked="checked" ';} ?>/><strong><?php _e( 'Margin', 'contact-forms'); ?></strong>
1217 + <div class="default_value"><?php echo htmlspecialchars($default_form_data['style_margin']); ?></div>
1218 + <input class="accua_form_value" type="text" value="<?php echo htmlspecialchars($form_data['style_margin'], ENT_QUOTES) ?>" />
1219 +
1220 + </div>
1221 +
1222 + <div class="label_input">
1223 + <div id="accua_form_style_border_color" class="label_container">
1224 + <input name="accua_form_style_border_color" class="accua_form_check_override" type="checkbox" value="1" <?php if (isset($form_overrided_data['style_border_color'])) {echo 'checked="checked" ';} ?>/><strong><?php _e( 'Border color', 'contact-forms'); ?></strong>
1225 + <div class="default_value"><?php echo htmlspecialchars($default_form_data['style_border_color']); ?></div>
1226 + <input class="accua_form_value" type="text" value="<?php echo htmlspecialchars($form_data['style_border_color'], ENT_QUOTES) ?>" />
1227 + </div>
1228 + <div id="accua_form_style_border_width" class="label_container">
1229 + <input name="accua_form_style_border_width" class="accua_form_check_override" type="checkbox" value="1" <?php if (isset($form_overrided_data['style_border_width'])) {echo 'checked="checked" ';} ?>/><?php _e( 'Width', 'contact-forms'); ?>
1230 + <div class="default_value"><?php echo htmlspecialchars($default_form_data['style_border_width']); ?></div>
1231 + <input class="accua_form_value" type="text" value="<?php echo htmlspecialchars($form_data['style_border_width'], ENT_QUOTES) ?>" />
1232 + </div>
1233 + <div id="accua_form_style_border_radius" class="label_container">
1234 + <input name="accua_form_style_border_radius" class="accua_form_check_override" type="checkbox" value="1" <?php if (isset($form_overrided_data['style_border_radius'])) {echo 'checked="checked" ';} ?>/><?php _e( 'Radius', 'contact-forms'); ?>
1235 + <div class="default_value"><?php echo htmlspecialchars($default_form_data['style_border_radius']); ?></div>
1236 + <input class="accua_form_value" type="text" value="<?php echo htmlspecialchars($form_data['style_border_radius'], ENT_QUOTES) ?>" />
1237 + </div>
1238 + </div>
1239 +
1240 + <div class="label_input">
1241 + <div id="accua_form_style_background_color" class="label_container">
1242 + <input name="accua_form_style_background_color" class="accua_form_check_override" type="checkbox" value="1" <?php if (isset($form_overrided_data['style_background_color'])) {echo 'checked="checked" ';} ?>/><strong><?php _e( 'Background', 'contact-forms'); ?></strong>
1243 + <div class="default_value"><?php echo htmlspecialchars($default_form_data['style_background_color']); ?></div>
1244 + <input class="accua_form_value" type="text" value="<?php echo htmlspecialchars($form_data['style_background_color'], ENT_QUOTES) ?>" />
1245 + </div>
1246 +
1247 + <div id="accua_form_style_padding" class="label_container">
1248 + <input name="accua_form_style_padding" class="accua_form_check_override" type="checkbox" value="1" <?php if (isset($form_overrided_data['style_padding'])) {echo 'checked="checked" ';} ?>/><strong><?php _e( 'Padding', 'contact-forms'); ?></strong>
1249 + <div class="default_value"><?php echo htmlspecialchars($default_form_data['style_padding']); ?></div>
1250 + <input class="accua_form_value" type="text" value="<?php echo htmlspecialchars($form_data['style_padding'], ENT_QUOTES) ?>" />
1251 + </div>
1252 + </div>
1253 + <div class="label_input">
1254 + <div id="accua_form_style_color" class="label_container">
1255 + <input name="accua_form_style_color" class="accua_form_check_override" type="checkbox" value="1" <?php if (isset($form_overrided_data['style_color'])) {echo 'checked="checked" ';} ?>/><strong><?php _e( 'Font', 'contact-forms'); ?></strong>
1256 + <div class="default_value"><?php echo htmlspecialchars($default_form_data['style_color']); ?></div>
1257 + <input class="accua_form_value" type="text" value="<?php echo htmlspecialchars($form_data['style_color'], ENT_QUOTES) ?>" />
1258 + </div>
1259 +
1260 + <div id="accua_form_style_font_size" class="label_container">
1261 + <input name="accua_form_style_font_size" class="accua_form_check_override" type="checkbox" value="1" <?php if (isset($form_overrided_data['style_font_size'])) {echo 'checked="checked" ';} ?>/><?php _e( 'Size', 'contact-forms'); ?>
1262 + <div class="default_value"><?php echo htmlspecialchars($default_form_data['style_font_size']); ?></div>
1263 + <input class="accua_form_value" type="text" value="<?php echo htmlspecialchars($form_data['style_font_size'], ENT_QUOTES) ?>" />
1264 + </div>
1265 + </div>
1266 + </div>
1267 + <div style="width: 48%; float:left;">
1268 +
1269 + <h3><?php _e( 'Fields', 'contact-forms'); ?></h3>
1270 +
1271 + <div id="accua_form_style_field_spacing" class="label_input">
1272 + <input name="accua_form_style_field_spacing" class="accua_form_check_override" type="checkbox" value="1" <?php if (isset($form_overrided_data['style_field_spacing'])) {echo 'checked="checked" ';} ?>/><?php _e( 'Spacing', 'contact-forms'); ?>
1273 + <div class="default_value"><?php echo htmlspecialchars($default_form_data['style_field_spacing']); ?></div>
1274 + <input class="accua_form_value" type="text" value="<?php echo htmlspecialchars($form_data['style_field_spacing'], ENT_QUOTES) ?>" />
1275 + </div>
1276 +
1277 + <div id="accua_form_style_field_border_color" class="label_input">
1278 + <input name="accua_form_style_field_border_color" class="accua_form_check_override" type="checkbox" value="1" <?php if (isset($form_overrided_data['style_field_border_color'])) {echo 'checked="checked" ';} ?>/><?php _e( 'Border color', 'contact-forms'); ?>
1279 + <div class="default_value"><?php echo htmlspecialchars($default_form_data['style_field_border_color']); ?></div>
1280 + <input class="accua_form_value" type="text" value="<?php echo htmlspecialchars($form_data['style_field_border_color'], ENT_QUOTES) ?>" />
1281 + </div>
1282 +
1283 + <div id="accua_form_style_field_border_width" class="label_input">
1284 + <input name="accua_form_style_field_border_width" class="accua_form_check_override" type="checkbox" value="1" <?php if (isset($form_overrided_data['style_field_border_width'])) {echo 'checked="checked" ';} ?>/><?php _e( 'Border width', 'contact-forms'); ?>
1285 + <div class="default_value"><?php echo htmlspecialchars($default_form_data['style_field_border_width']); ?></div>
1286 + <input class="accua_form_value" type="text" value="<?php echo htmlspecialchars($form_data['style_field_border_width'], ENT_QUOTES) ?>" />
1287 + </div>
1288 +
1289 + <div id="accua_form_style_field_border_radius" class="label_input">
1290 + <input name="accua_form_style_field_border_radius" class="accua_form_check_override" type="checkbox" value="1" <?php if (isset($form_overrided_data['style_field_border_radius'])) {echo 'checked="checked" ';} ?>/><?php _e( 'Rounded corner radius', 'contact-forms'); ?>
1291 + <div class="default_value"><?php echo htmlspecialchars($default_form_data['style_field_border_radius']); ?></div>
1292 + <input class="accua_form_value" type="text" value="<?php echo htmlspecialchars($form_data['style_field_border_radius'], ENT_QUOTES) ?>" />
1293 + </div>
1294 +
1295 + <div id="accua_form_style_field_background_color" class="label_input">
1296 + <input name="accua_form_style_field_background_color" class="accua_form_check_override" type="checkbox" value="1" <?php if (isset($form_overrided_data['style_field_background_color'])) {echo 'checked="checked" ';} ?>/><?php _e( 'Background color', 'contact-forms'); ?>
1297 + <div class="default_value"><?php echo htmlspecialchars($default_form_data['style_field_background_color']); ?></div>
1298 + <input class="accua_form_value" type="text" value="<?php echo htmlspecialchars($form_data['style_field_background_color'], ENT_QUOTES) ?>" />
1299 + </div>
1300 +
1301 + <div id="accua_form_style_field_padding" class="label_input">
1302 + <input name="accua_form_style_field_padding" class="accua_form_check_override" type="checkbox" value="1" <?php if (isset($form_overrided_data['style_field_padding'])) {echo 'checked="checked" ';} ?>/><?php _e( 'Padding', 'contact-forms'); ?>
1303 + <div class="default_value"><?php echo htmlspecialchars($default_form_data['style_field_padding']); ?></div>
1304 + <input class="accua_form_value" type="text" value="<?php echo htmlspecialchars($form_data['style_field_padding'], ENT_QUOTES) ?>" />
1305 + </div>
1306 +
1307 + <div id="accua_form_style_field_color" class="label_input">
1308 + <input name="accua_form_style_field_color" class="accua_form_check_override" type="checkbox" value="1" <?php if (isset($form_overrided_data['style_field_color'])) {echo 'checked="checked" ';} ?>/><?php _e( 'Text color', 'contact-forms'); ?>
1309 + <div class="default_value"><?php echo htmlspecialchars($default_form_data['style_field_color']); ?></div>
1310 + <input class="accua_form_value" type="text" value="<?php echo htmlspecialchars($form_data['style_field_color'], ENT_QUOTES) ?>" />
1311 + </div>
1312 +
1313 +
1314 + <h3><?php _e( 'Submit button', 'contact-forms'); ?></h3>
1315 +
1316 + <div id="accua_form_style_submit_border_color" class="label_input">
1317 + <input name="accua_form_style_submit_border_color" class="accua_form_check_override" type="checkbox" value="1" <?php if (isset($form_overrided_data['style_submit_border_color'])) {echo 'checked="checked" ';} ?>/><?php _e( 'Border color', 'contact-forms'); ?>
1318 + <div class="default_value"><?php echo htmlspecialchars($default_form_data['style_submit_border_color']); ?></div>
1319 + <input class="accua_form_value" type="text" value="<?php echo htmlspecialchars($form_data['style_submit_border_color'], ENT_QUOTES) ?>" />
1320 + <?php _e( 'Customize', 'contact-forms'); ?>
1321 + </div>
1322 +
1323 + <div id="accua_form_style_submit_border_width" class="label_input">
1324 + <input name="accua_form_style_submit_border_width" class="accua_form_check_override" type="checkbox" value="1" <?php if (isset($form_overrided_data['style_submit_border_width'])) {echo 'checked="checked" ';} ?>/><?php _e( 'Border width', 'contact-forms'); ?>
1325 + <div class="default_value"><?php echo htmlspecialchars($default_form_data['style_submit_border_width']); ?></div>
1326 + <input class="accua_form_value" type="text" value="<?php echo htmlspecialchars($form_data['style_submit_border_width'], ENT_QUOTES) ?>" />
1327 + </div>
1328 +
1329 + <div id="accua_form_style_submit_border_radius" class="label_input">
1330 + <input name="accua_form_style_submit_border_radius" class="accua_form_check_override" type="checkbox" value="1" <?php if (isset($form_overrided_data['style_submit_border_radius'])) {echo 'checked="checked" ';} ?>/><?php _e( 'Rounded corner radius', 'contact-forms'); ?>
1331 + <div class="default_value"><?php echo htmlspecialchars($default_form_data['style_submit_border_radius']); ?></div>
1332 + <input class="accua_form_value" type="text" value="<?php echo htmlspecialchars($form_data['style_submit_border_radius'], ENT_QUOTES) ?>" />
1333 + </div>
1334 +
1335 + <div id="accua_form_style_submit_background_color" class="label_input">
1336 + <input name="accua_form_style_submit_background_color" class="accua_form_check_override" type="checkbox" value="1" <?php if (isset($form_overrided_data['style_submit_background_color'])) {echo 'checked="checked" ';} ?>/><?php _e( 'Background color', 'contact-forms'); ?>
1337 + <div class="default_value"><?php echo htmlspecialchars($default_form_data['style_submit_background_color']); ?></div>
1338 + <input class="accua_form_value" type="text" value="<?php echo htmlspecialchars($form_data['style_submit_background_color'], ENT_QUOTES) ?>" />
1339 + </div>
1340 +
1341 + <div id="accua_form_style_submit_padding" class="label_input">
1342 + <input name="accua_form_style_submit_padding" class="accua_form_check_override" type="checkbox" value="1" <?php if (isset($form_overrided_data['style_submit_padding'])) {echo 'checked="checked" ';} ?>/><?php _e( 'Padding', 'contact-forms'); ?>
1343 + <div class="default_value"><?php echo htmlspecialchars($default_form_data['style_submit_padding']); ?></div>
1344 + <input class="accua_form_value" type="text" value="<?php echo htmlspecialchars($form_data['style_submit_padding'], ENT_QUOTES) ?>" />
1345 + </div>
1346 +
1347 + <div id="accua_form_style_submit_color" class="label_input">
1348 + <input name="accua_form_style_submit_color" class="accua_form_check_override" type="checkbox" value="1" <?php if (isset($form_overrided_data['style_submit_color'])) {echo 'checked="checked" ';} ?>/><?php _e( 'Text color', 'contact-forms'); ?>
1349 + <div class="default_value"><?php echo htmlspecialchars($default_form_data['style_submit_color']); ?></div>
1350 + <input class="accua_form_value" type="text" value="<?php echo htmlspecialchars($form_data['style_submit_color'], ENT_QUOTES) ?>" />
1351 + </div>
1352 +
1353 + <div id="accua_form_style_submit_font_size" class="label_input">
1354 + <input name="accua_form_style_submit_font_size" class="accua_form_check_override" type="checkbox" value="1" <?php if (isset($form_overrided_data['style_submit_font_size'])) {echo 'checked="checked" ';} ?>/><?php _e( 'Font size', 'contact-forms'); ?>
1355 + <div class="default_value"><?php echo htmlspecialchars($default_form_data['style_submit_font_size']); ?></div>
1356 + <input class="accua_form_value" type="text" value="<?php echo htmlspecialchars($form_data['style_submit_font_size'], ENT_QUOTES) ?>" />
1357 + </div>
1358 +
1359 + <br clear="all"/>
1360 + </div>
1361 + </div>
1362 + </div>
1363 +
1364 +
1365 +
1366 + </div>
1367 + </div>
1368 + <div style="width:50%; float:right;">
1369 + <div style="padding: 15px;">
1370 + <h2><?php _e('Preview', 'contact-forms'); ?>
1371 + <?php echo $accuaHelp->add_pointer('form_edit_preview'); ?>
1372 + </h2>
1373 + <div id="accua_form_preview_area_wrapper">
1374 + <?php
1375 + echo "<script>
1376 + function resizeIframe(obj) {
1377 + altezza = obj.contentWindow.document.documentElement.scrollHeight + 200;
1378 + obj.style.height = altezza + 'px';
1379 + }
1380 + </script>";
1381 +
1382 + ?>
1383 + <iframe id="accua_form_preview_area" src="admin-ajax.php?action=accua_forms_preview&fid=<?php echo htmlspecialchars($fid,ENT_QUOTES);?>" frameborder="0" scrolling="no" onload="resizeIframe(this)" ></iframe>
1384 + <?php //todo: posso usare lo stile del sito? font ecc ?>
1385 + </div>
1386 +
1387 + </div>
1388 + </div>
1389 +
1390 + <div style="clear:both;">&nbsp;</div>
1391 +
1392 + <?php /* * / ?>
1393 + <pre>
1394 + accua_forms_form_fields_order_post: <?php echo htmlspecialchars(print_r(get_option('accua_forms_form_fields_order_post'), true)); ?>
1395 +
1396 + accua_forms_save_form_field_post: <?php echo htmlspecialchars(print_r(get_option('accua_forms_save_form_field_post'), true)); ?>
1397 +
1398 + accua_forms_saved_form_data: <?php echo htmlspecialchars(print_r($form_data, true)); ?>
1399 +
1400 + </pre>
1401 + <?php /* */ ?>
1402 +</div>
1403 + <div id="accua_tab_messages" class="content_tab">
1404 + <?php
1405 + $settings_editor = array(
1406 + 'teeny' => true,
1407 + 'editor_class' => 'accua_form_value',
1408 + 'tinymce' => array(
1409 + 'theme_advanced_buttons1' => 'bold,italic,underline,|,bullist,numlist,'));
1410 + ?>
1411 +
1412 + <div class="metabox-holder accua-forms-metabox-holder">
1413 + <div class="postbox ">
1414 + <h3 class="hndle"><span><?php _e('1. On-screen success message', 'contact-forms'); ?></span></h3>
1415 + <div class="inside" id="dashboard_right_now">
1416 + <div id="accua_form_success_message">
1417 + <input class="accua_form_check_override" name="accua_form_success_message" type="radio" value="0" <?php if (!isset($form_overrided_data['success_message'])) {echo ' checked ';} ?>> <?php _e( 'Use the default message', 'contact-forms'); ?>
1418 + <input class="accua_form_check_override" name="accua_form_success_message" type="radio" value="1" <?php if (isset($form_overrided_data['success_message']) && !isset($form_overrided_data['success_message_no_message'])) {echo ' checked ';} ?>/> <?php _e( 'Customize', 'contact-forms'); ?>
1419 + <input class="accua_form_check_override" name="accua_form_success_message" type="radio" value="-1" <?php if (isset($form_overrided_data['success_message_no_message'])) {echo ' checked ';} ?>/> <?php _e( 'Don\'t show any messages', 'contact-forms'); ?><br />
1420 + <div class="defalut_message">
1421 + <?php _e( 'Default Success message', 'contact-forms'); ?>
1422 + <div class="defalut_content_message"><?php echo wpautop($default_form_data['success_message']); ?></div>
1423 + </div>
1424 + <?php wp_editor( $form_data['success_message'] , 'accua_form_success_message_textarea' , $settings_editor); ?>
1425 + <!-- <textarea class="accua_form_value" style="width:95%"; cols="80" rows="8"><?php echo htmlspecialchars($form_data['success_message'], ENT_QUOTES) ?></textarea> -->
1426 + </div>
1427 + </div>
1428 + </div>
1429 + </div>
1430 +
1431 + <div class="metabox-holder accua-forms-metabox-holder">
1432 + <div class="postbox ">
1433 + <h3 class="hndle"><span><?php _e('2. On-screen error message', 'contact-forms'); ?></span></h3>
1434 + <div class="inside" id="dashboard_right_now">
1435 + <div id="accua_form_error_message">
1436 + <input class="accua_form_check_override" name="accua_form_error_message" type="radio" value="0" <?php if (!isset($form_overrided_data['error_message'])) {echo ' checked ';} ?>> <?php _e( 'Use the default message', 'contact-forms'); ?>
1437 + <input class="accua_form_check_override" name="accua_form_error_message" type="radio" value="1" <?php if (isset($form_overrided_data['error_message']) && !isset($form_overrided_data['error_message_no_message'])) {echo ' checked ';} ?>/> <?php _e( 'Customize', 'contact-forms'); ?>
1438 + <input class="accua_form_check_override" name="accua_form_error_message" type="radio" value="-1" <?php if (isset($form_overrided_data['error_message_no_message'])) {echo ' checked ';} ?>/> <?php _e( 'Don\'t show any messages', 'contact-forms'); ?><br />
1439 + <div class="defalut_message">
1440 + <?php _e( 'Default error message', 'contact-forms'); ?> <br />
1441 + <div class="defalut_content_message" ><?php echo wpautop($default_form_data['error_message']); ?></div>
1442 + </div>
1443 + <?php wp_editor( $form_data['error_message'] , 'accua_form_error_message_textarea' , $settings_editor); ?>
1444 + </div>
1445 + </div>
1446 + </div>
1447 + </div>
1448 + <br clear="all"/>
1449 + <div class="metabox-holder accua-forms-metabox-holder">
1450 + <div class="postbox ">
1451 + <h3 class="hndle"><span><?php _e('3. Email to notify administrator', 'contact-forms'); ?></span></h3>
1452 + <div class="inside" id="dashboard_right_now">
1453 + <div id="accua_form_admin_emails_to" class="label_input">
1454 + <label><?php _e('To', 'contact-forms'); ?></label>
1455 + <div class="default_value"><?php echo htmlspecialchars($default_form_data['admin_emails_to']); ?></div>
1456 + <input class="accua_form_value" type="text" value="<?php echo htmlspecialchars($form_data['admin_emails_to'], ENT_QUOTES) ?>" />
1457 + <input name="accua_form_admin_emails_to" class="accua_form_check_override" type="checkbox" value="1" <?php if (isset($form_overrided_data['admin_emails_to'])) {echo 'checked="checked" ';} ?>/><?php _e( 'Customize', 'contact-forms'); ?>
1458 + </div>
1459 + <div id="accua_form_emails_bcc" class="label_input">
1460 + <label><?php _e('Bcc', 'contact-forms'); ?></label>
1461 + <div class="default_value"><?php echo htmlspecialchars($default_form_data['emails_bcc']); ?></div>
1462 + <input class="accua_form_value" type="text" value="<?php echo htmlspecialchars($form_data['emails_bcc'], ENT_QUOTES) ?>" />
1463 + <input name ="accua_form_emails_bcc" class="accua_form_check_override" type="checkbox" value="1" <?php if (isset($form_overrided_data['emails_bcc'])) {echo 'checked="checked" ';} ?>/><?php _e( 'Customize', 'contact-forms'); ?>
1464 + </div>
1465 +
1466 + <div id="accua_form_admin_emails_subject" class="label_input">
1467 + <label><?php _e( 'Subject', 'contact-forms'); ?></label>
1468 + <div class="default_value"><?php echo htmlspecialchars($default_form_data['admin_emails_subject']); ?></div>
1469 + <input class="accua_form_value" type="text" value="<?php echo htmlspecialchars($form_data['admin_emails_subject'], ENT_QUOTES) ?>" />
1470 + <input name="accua_form_admin_emails_subject" class="accua_form_check_override" type="checkbox" value="1" <?php if (isset($form_overrided_data['admin_emails_subject'])) {echo 'checked="checked" ';} ?>/><?php _e( 'Customize', 'contact-forms'); ?>
1471 + </div>
1472 +
1473 + <div id="accua_form_admin_emails_message">
1474 + <input class="accua_form_check_override" name="accua_form_admin_emails_message" type="radio" value="0" <?php if (!isset($form_overrided_data['admin_emails_message'])) {echo ' checked ';} ?>> <?php _e( 'Use the default message', 'contact-forms'); ?>
1475 + <input class="accua_form_check_override" name="accua_form_admin_emails_message" type="radio" value="1" <?php if (isset($form_overrided_data['admin_emails_message']) && !isset($form_overrided_data['admin_emails_message_no_message'])) {echo ' checked ';} ?>/> <?php _e( 'Customize', 'contact-forms'); ?>
1476 + <input class="accua_form_check_override" name="accua_form_admin_emails_message" type="radio" value="-1" <?php if (isset($form_overrided_data['admin_emails_message_no_message'])) {echo ' checked ';} ?>/> <?php _e( 'Don\'t show any messages', 'contact-forms'); ?><br />
1477 + <div class="defalut_message">
1478 + <?php _e( 'Default message', 'contact-forms'); ?>
1479 + <div class="defalut_content_message"><?php echo wpautop($default_form_data['admin_emails_message']); ?></div>
1480 + </div>
1481 + <?php wp_editor( $form_data['admin_emails_message'] , 'accua_form_admin_emails_message_textarea' , $settings_editor); ?>
1482 + </div>
1483 +
1484 + </div>
1485 + </div>
1486 + </div>
1487 +
1488 + <div class="metabox-holder accua-forms-metabox-holder">
1489 + <div class="postbox ">
1490 + <h3 class="hndle"><span><?php _e('4. Email confirmation to the person who completed the form', 'contact-forms'); ?></span></h3>
1491 + <div class="inside" id="dashboard_right_now">
1492 + <div id="accua_form_emails_from_name" class="label_input">
1493 + <label><?php _e( 'From name', 'contact-forms'); ?></label>
1494 + <div class="default_value"><?php echo htmlspecialchars($default_form_data['emails_from_name']); ?></div>
1495 + <input class="accua_form_value" type="text" value="<?php echo htmlspecialchars($form_data['emails_from_name'], ENT_QUOTES) ?>" />
1496 + <input name="accua_form_emails_from_name" class="accua_form_check_override" type="checkbox" value="1" <?php if (isset($form_overrided_data['emails_from_name'])) {echo 'checked="checked" ';} ?>/><?php _e( 'Customize', 'contact-forms'); ?>
1497 + </div>
1498 + <div id="accua_form_emails_from" class="label_input">
1499 + <label><?php _e( 'From email', 'contact-forms'); ?></label>
1500 + <div class="default_value"><?php echo htmlspecialchars($default_form_data['emails_from']); ?></div>
1501 + <input class="accua_form_value" type="text" value="<?php echo htmlspecialchars($form_data['emails_from'], ENT_QUOTES) ?>" />
1502 + <input name="accua_form_emails_from" class="accua_form_check_override" type="checkbox" value="1" <?php if (isset($form_overrided_data['emails_from'])) {echo 'checked="checked" ';} ?>/><?php _e( 'Customize', 'contact-forms'); ?>
1503 + </div>
1504 + <div id="accua_form_confirmation_emails_subject" class="label_input">
1505 + <label><?php _e( 'Subject', 'contact-forms'); ?></label>
1506 + <div class="default_value"><?php echo htmlspecialchars($default_form_data['confirmation_emails_subject']); ?></div>
1507 + <input class="accua_form_value" type="text" value="<?php echo htmlspecialchars($form_data['confirmation_emails_subject'], ENT_QUOTES) ?>" />
1508 + <input name="accua_form_confirmation_emails_subject" class="accua_form_check_override" type="checkbox" value="1" <?php if (isset($form_overrided_data['confirmation_emails_subject'])) {echo 'checked="checked" ';} ?>/><?php _e( 'Customize', 'contact-forms'); ?>
1509 + </div>
1510 +
1511 + <div id="accua_form_confirmation_emails_message">
1512 + <input class="accua_form_check_override" name="accua_form_confirmation_emails_message" type="radio" value="0" <?php if (!isset($form_overrided_data['confirmation_emails_message'])) {echo ' checked ';} ?>> <?php _e( 'Use the default message', 'contact-forms'); ?>
1513 + <input class="accua_form_check_override" name="accua_form_confirmation_emails_message" type="radio" value="1" <?php if (isset($form_overrided_data['confirmation_emails_message']) && !isset($form_overrided_data['confirmation_emails_message_no_message'])) {echo ' checked ';} ?>/> <?php _e( 'Customize', 'contact-forms'); ?>
1514 + <input class="accua_form_check_override" name="accua_form_confirmation_emails_message" type="radio" value="-1" <?php if (isset($form_overrided_data['confirmation_emails_message_no_message'])) {echo ' checked ';} ?>/> <?php _e( 'Don\'t show any messages', 'contact-forms'); ?><br />
1515 + <div class="defalut_message">
1516 + <?php _e( 'Default message', 'contact-forms'); ?>
1517 + <div class="defalut_content_message"><?php echo wpautop($default_form_data['confirmation_emails_message']); ?></div>
1518 + </div>
1519 + <?php wp_editor( $form_data['confirmation_emails_message'] , 'accua_form_confirmation_emails_message_textarea' , $settings_editor); ?>
1520 + </div>
1521 + </div>
1522 + </div>
1523 + </div>
1524 + <br clear="all"/>
1525 +
1526 +<?php accua_forms_print_tokens(); ?>
1527 +
1528 +<input type="hidden" id="accua_form_save_settings_id" value="<?php echo $fid_esc; ?>" />
1529 +</div>
1530 +<?php /*
1531 +<div id="accua_tab_preview" class="content_tab">
1532 +</div> */?>
1533 +<p></p>
1534 +<input class="button button-primary button-large accua_form_save_settings_button" id="accua_form_save_settings_2" type="button" value="<?php _e( 'Save settings', 'contact-forms'); ?>" /> <span class="accua_form_save_settings_status"></span>
1535 +
1536 +</div>
1537 +<script>
1538 +jQuery('input[type=radio]').change(function() {
1539 + var name = jQuery(this).attr('name');
1540 + if (jQuery(this).val() == '1') {
1541 + jQuery('#'+name+' .defalut_message').hide();
1542 + jQuery('#'+name+' .wp-editor-wrap').show();
1543 + }
1544 + else {
1545 + if(jQuery(this).val() != '-1')
1546 + jQuery('#'+name+' .defalut_message').show();
1547 + else
1548 + jQuery('#'+name+' .defalut_message').hide();
1549 + jQuery('#'+name+' .wp-editor-wrap').hide();
1550 + }
1551 +});
1552 +
1553 +jQuery('input[type=checkbox]').click(function() {
1554 + var name = jQuery(this).attr('name');
1555 + if (!this.checked) {
1556 + jQuery('#'+name+' .default_value').show();
1557 + jQuery('#'+name+' .accua_form_value, #'+name+' .cp-color-picker').hide();
1558 + }
1559 + else {
1560 + jQuery('#'+name+' .default_value').hide();
1561 + jQuery('#'+name+' .accua_form_value, #'+name+' .cp-color-picker').show();
1562 + //cp-color-picker
1563 + }
1564 +});
1565 +
1566 +jQuery(".token_link").click(function() {
1567 + jQuery("#dialog_token").dialog("open");
1568 + return false;
1569 +});
1570 +
1571 +//inizializzazione
1572 +jQuery(document).ready(function($){
1573 + $('#accua_form_preview_area_wrapper').resizable({handles: 's'});
1574 + $('#accua_form_preview_area').css({
1575 + 'width': '100%',
1576 + 'height': '100%'
1577 + });
1578 + $.each(
1579 + ['success_message','error_message','admin_emails_message','confirmation_emails_message'],
1580 + function(i,key){
1581 + var value = $('#accua_form_'+key+' .accua_form_check_override:checked').val();
1582 + if(value!=undefined && value!=0) {
1583 + if(value!=-1)
1584 + jQuery('#accua_form_'+key+' .wp-editor-wrap').show();
1585 + else
1586 + jQuery('#accua_form_'+key+' .wp-editor-wrap').hide();
1587 + jQuery('#accua_form_'+key+' .defalut_message').hide();
1588 +
1589 + }
1590 + else {
1591 + jQuery('#accua_form_'+key+' .wp-editor-wrap').hide();
1592 + jQuery('#accua_form_'+key+' .defalut_message').show();
1593 + }
1594 + }
1595 + );
1596 + $.each(
1597 + ['emails_from_name','emails_from','admin_emails_to','emails_bcc','admin_emails_subject','confirmation_emails_subject','style_margin','style_border_color','style_border_width','style_border_radius','style_background_color','style_padding','style_color','style_font_size','style_field_spacing','style_field_border_color','style_field_border_width','style_field_border_radius','style_field_background_color','style_field_padding','style_field_color','style_submit_border_color','style_submit_border_width','style_submit_border_radius','style_submit_background_color','style_submit_padding','style_submit_color','style_submit_font_size'],
1598 + function(i,key){
1599 + if(!$('#accua_form_'+key+' .accua_form_check_override').is(':checked')) {
1600 + jQuery('#accua_form_'+key+' .default_value').show();
1601 + jQuery('#accua_form_'+key+' .accua_form_value, #accua_form_'+key+' .wp-picker-container').hide();
1602 + }
1603 + else {
1604 + jQuery('#accua_form_'+key+' .default_value').hide();
1605 + jQuery('#accua_form_'+key+' .accua_form_value, #accua_form_'+key+' .wp-picker-container').show();
1606 + }
1607 + });
1608 + $("#dialog_token").dialog({ dialogClass:'wp-dialog' ,autoOpen : false, modal : true, show : "blind", hide : "blind"});
1609 +
1610 + $('#accua_token a').appendTo('.wp-media-buttons');
1611 +
1612 +});
1613 +
1614 +jQuery(document).ready(function($){
1615 +
1616 + var originalWidth = $(document).width();
1617 + if(originalWidth <= 883) { //iphone
1618 + $(".metabox-holder").width('98%');
1619 + }
1620 +
1621 + $(window).resize(function (e) {
1622 + var newWidth = $(document).width();
1623 + if(newWidth <= 883) {
1624 + if (originalWidth > 883) {
1625 + $(".metabox-holder").width('98%');
1626 + }
1627 + } else if (originalWidth<=883) {
1628 + $(".metabox-holder").width('47%');
1629 + }
1630 + originalWidth = newWidth;
1631 + });
1632 +});
1633 +
1634 +</script>
1635 +
1636 +<?php
1637 + $accuaHelp->finished();
1638 +}
1639 +
1640 +function accua_forms_fields_page_head() {
1641 +/*
1642 + $baseurl = WP_PLUGIN_URL.'/'.substr(plugin_basename(__FILE__),0,-strlen(basename(__FILE__)));
1643 +?>
1644 + <script type="text/javascript" src="<?php echo $baseurl.'/qtip/jquery.qtip-1.0.0-rc3.js'; ?>"></script>
1645 + <script type="text/javascript">
1646 + var avail_fields = {
1647 + first_name: {
1648 + id: "first_name",
1649 + name: "First Name",
1650 + type: "textfield"
1651 + },
1652 + last_name: {
1653 + id: "last_name",
1654 + name: "Last Name",
1655 + type: "textfield"
1656 + },
1657 + email: {
1658 + id: "email",
1659 + name: "Email",
1660 + type: "email"
1661 + }
1662 + };
1663 +
1664 + jQuery(function($){
1665 + $avail = $('#available_fields_container');
1666 + for(var id in avail_fields) {
1667 + var field = avail_fields[id];
1668 + var el = $('<div></div>').text(field.name);
1669 + el.prepend('<input type="checkbox" />');
1670 + var content = $('<div><span>Id: </span></div>');
1671 + content.append($('<input type="text" />').val(field.id));
1672 + content.append($('<br /><span>Name: </span>'));
1673 + content.append($('<input type="text" />').val(field.name));
1674 + content.append($('<br /><span>Type: </span>'));
1675 + content.append($('<select><option value="textfield">Textfield</option><option value="textarea">Textarea</option><option value="email">Email</option></select>').val(field.type));
1676 + el.qtip({
1677 + content: {
1678 + text: content
1679 + },
1680 + position: {
1681 + target: 'mouse',
1682 + corner: {
1683 + target: 'bottomRight',
1684 + tooltip: 'topLeft'
1685 + },
1686 + adjust: {
1687 + mouse: false
1688 + }
1689 + },
1690 + show: {
1691 + when: {
1692 + event: 'mouseover'
1693 + },
1694 + solo: true
1695 + },
1696 + hide: {
1697 + when: {
1698 + event: 'unfocus'
1699 + }
1700 + }
1701 + });
1702 + $avail.append(el);
1703 + }
1704 + });
1705 + </script>
1706 + <style type="text/css">
1707 + .container > div {
1708 + padding: 0px;
1709 + margin-bottom: 6px;
1710 + }
1711 + </style>
1712 +<?php
1713 +*/
1714 +}
1715 +
1716 +function accua_forms_fields_get_types() {
1717 + return array(
1718 + 'textfield' => __( 'Text Field', 'contact-forms'),
1719 + 'textarea' => __( 'Text Area', 'contact-forms'),
1720 + 'email' => __( 'Email', 'contact-forms'),
1721 + 'autoreply_email' => __( 'Autoreply Email', 'contact-forms'),
1722 + 'checkbox' => __( 'Checkbox','contact-forms'),
1723 + 'select' => __('Select', 'contact-forms'),
1724 + 'radio' => __( 'Radio buttons', 'contact-forms'),
1725 + 'multiselect' => __( 'Multiple selections area', 'contact-forms'),
1726 + 'multicheckbox' => __( 'Multiple checkboxes', 'contact-forms'),
1727 + 'post-select' => __( 'Post select', 'contact-forms'),
1728 + 'post-multicheckbox' => __( 'Multiple post checkboxes', 'contact-forms'),
1729 + 'colorpicker' => __( 'Color picker', 'contact-forms'),
1730 + 'hidden' => __('Hidden value', 'contact-forms'),
1731 + 'file' => __('File upload', 'contact-forms'),
1732 + 'submit' => __( 'Submit button', 'contact-forms'),
1733 + 'html' => __( 'Custom HTML', 'contact-forms'),
1734 + 'captcha' => __( 'Captcha', 'contact-forms'),
1735 + 'password' => 'Password',
1736 + 'password-and-confirm' => __( 'Password and password confirmation','contact-forms'),
1737 + 'date' => __( 'Date','contact-forms'),
1738 + );
1739 +}
1740 +
1741 +function accua_forms_filter_date($value){
1742 + if (($value !== '') && preg_match('/^\d{4}-\d{2}-\d{2}$/', $value)) {
1743 + try {
1744 + $date = new DateTime($value);
1745 + if ($date) {
1746 + return $value;
1747 + }
1748 + } catch (Exception $e) {
1749 + }
1750 + }
1751 + return '';
1752 +}
1753 +
1754 +function accua_forms_fields_filter_values($post, $old_data = array()) {
1755 + //TODO: funzione di validazione dei field
1756 + $data = array(
1757 + 'version' => 2,
1758 + 'id' => $post['form-field-id'],
1759 + 'name' => $post['form-field-name'],
1760 + 'type' => $post['form-field-type'],
1761 + 'description' => $post['form-field-description'],
1762 + 'default_value' => $post['form-field-default-value'],
1763 + 'default_date_value' => $post['form-field-default-date-value'],
1764 + 'allowed_values' => $post['form-field-allowed-values'],
1765 + 'allowed_extensions' => '',
1766 + 'min_date' => $post['form-field-min-of-date'],
1767 + 'max_date' => $post['form-field-max-of-date'],
1768 + );
1769 + $valid = true;
1770 + $message = '';
1771 +
1772 + $types = accua_forms_fields_get_types();
1773 + if (!isset($types[$data['type']])) {
1774 + $message .= "<p>".__('Invalid type', 'contact-forms')."</p>";
1775 + $valid = false;
1776 + $data['type'] = 'textfield';
1777 + }
1778 +
1779 + if (!current_user_can('unfiltered_html')) {
1780 + $filter_fields = array('name', 'description', 'default_value', 'allowed_values');
1781 + foreach ($filter_fields as $k) {
1782 + $data[$k] = wp_kses($data[$k], 'post');
1783 + }
1784 + }
1785 +
1786 + if ($data['type'] == 'file') {
1787 + $data['allowed_extensions'] = accua_forms_filter_extensions($data['allowed_values']);
1788 + }
1789 +
1790 + $dates = array(
1791 + 'default_date_value' => __('Invalid default date', 'contact-forms'),
1792 + 'min_date' => __('Invalid min date', 'contact-forms'),
1793 + 'max_date' => __('Invalid max date', 'contact-forms'),
1794 + );
1795 + foreach ($dates as $k => $errormsg) {
1796 + if ($data[$k] !== '') {
1797 + $data[$k] = accua_forms_filter_date($data[$k]);
1798 + if ($data[$k] === '') {
1799 + $message .= "<p>".$errormsg."</p>";
1800 + $valid = false;
1801 + }
1802 + }
1803 + }
1804 +
1805 + return array(
1806 + 'data' => $data,
1807 + 'valid' => $valid,
1808 + 'message' => $message,
1809 + );
1810 +}
1811 +
1812 +function accua_forms_fields_page() {
1813 +/*
1814 +?>
1815 +<div class="wrap"><h2>Edit Form Fields</h2>
1816 + <div id="available_fields_container" class="container"></div>
1817 +</div>
1818 +<?php
1819 +*/
1820 + $message = '';
1821 + $taxonomy = '';
1822 + $post_type = '';
1823 +
1824 + /*
1825 + $avail_fields = array(
1826 + 'first_name' => array (
1827 + 'id' => "first_name",
1828 + 'name' => "First Name",
1829 + 'type' => "textfield",
1830 + 'description' => 'This is the first name',
1831 + ),
1832 + 'last_name' => array (
1833 + 'id' => "last_name",
1834 + 'name' => "Last Name",
1835 + 'type' => "textfield",
1836 + 'description' => 'This is the last name',
1837 + ),
1838 + 'email' => array (
1839 + 'id' => "email",
1840 + 'name' => "Email",
1841 + 'type' => "email",
1842 + 'description' => 'This is the email',
1843 + ),
1844 + );
1845 + */
1846 +
1847 + $avail_fields = get_option('accua_forms_avail_fields', array());
1848 +
1849 + $default_form_values = array(
1850 + 'version' => 1,
1851 + 'id' => '',
1852 + 'name' => '',
1853 + 'type' => 'textfield',
1854 + 'description' => '',
1855 + 'default_value' => '',
1856 + 'default_date_value' => '',
1857 + 'allowed_values' => '',
1858 + 'allowed_extensions' => '',
1859 + 'min_date' => '',
1860 + 'max_date' => '',
1861 + );
1862 +
1863 + $editing = false;
1864 + $adding = true;
1865 +
1866 + if (!empty($_POST['action'])) {
1867 + check_admin_referer('edit_form_field', '_wpnonce_edit_form_field');
1868 + $post = stripslashes_deep($_POST) + $default_form_values;
1869 + switch($post['action']) {
1870 + case 'edit-form-field':
1871 + if (empty($avail_fields[$post['form-field-id']])) {
1872 + $message .= 'Field "'.htmlspecialchars(sanitize_text_field($post['form-field-id'])).'" doesn\'t exists';
1873 + } else {
1874 + if (empty($post['delete-field'])) {
1875 + $filtered_data = accua_forms_fields_filter_values($post, $avail_fields[$post['form-field-id']]);
1876 + $avail_fields[$post['form-field-id']] = $filtered_data['data'];
1877 + $message .= sprintf( __( 'Field "%s" updated', 'contact-forms'), htmlspecialchars($post['form-field-id']) );
1878 + do_action('accua_forms_field_updated', $avail_fields[$post['form-field-id']]);
1879 + } else {
1880 + $deleting_field = $avail_fields[$post['form-field-id']];
1881 + unset ($avail_fields[$post['form-field-id']]);
1882 + $message .= sprintf( __( 'Field "%s" deleted', 'contact-forms'), htmlspecialchars($post['form-field-id']) );
1883 + do_action('accua_forms_field_deleted', $deleting_field);
1884 + }
1885 + update_option('accua_forms_avail_fields', $avail_fields);
1886 + }
1887 + break;
1888 + case 'add-form-field':
1889 + $fill_form_fields = true;
1890 + $valid = true;
1891 + if (empty($post['form-field-id']) || !preg_match('/^[a-z0-9_-]+$/i', $post['form-field-id'])) {
1892 + $message .= "<p>".__( 'Only letters, numbers, hyphen and underscores allowed in field identificative slug', 'contact-forms')."</p>";
1893 + $valid = false;
1894 + }
1895 + if(substr($post['form-field-id'], 0, 2) == '__') {
1896 + $message .= "<p>".__( 'The field identificative slug can\'t start with two underscores (__)', 'contact-forms')."</p>";
1897 + $valid = false;
1898 + }
1899 + if (!empty($avail_fields[$post['form-field-id']])) {
1900 + $message .= sprintf( __( '<p>A field with identificative slug "%s" already exists</p> Field "%s" deleted', 'contact-forms'), htmlspecialchars($post['form-field-id']) );
1901 + $valid = false;
1902 + }
1903 + if (strlen($post['form-field-id']) > 70) {
1904 + $message .= "<p>".__( 'The identificative slug cannot be longer than 70 characters', 'contact-forms')."</p>";
1905 + $valid = false;
1906 + }
1907 + $filtered_data = accua_forms_fields_filter_values($post);
1908 + $message .= $filtered_data['message'];
1909 + $valid = $valid && $filtered_data['valid'];
1910 + if ($valid) {
1911 + $fill_form_fields = false;
1912 + $avail_fields[$post['form-field-id']] = $filtered_data['data'];
1913 + update_option('accua_forms_avail_fields', $avail_fields);
1914 + $message .= sprintf( __( 'Field "%s" created', 'contact-forms'), htmlspecialchars($post['form-field-id']) );
1915 + do_action('accua_forms_field_added', $avail_fields[$post['form-field-id']]);
1916 + }
1917 + if ($fill_form_fields) {
1918 + $editing = true;
1919 + $default_form_values = $filtered_data['data'];
1920 + }
1921 + break;
1922 + }
1923 + } else if (!empty($_GET['edit-fid'])) {
1924 + $fid = stripslashes($_GET['edit-fid']);
1925 + if (empty($avail_fields[$fid])) {
1926 + $message .= sprintf( __( 'Field "%s" doesn\'t exists', 'contact-forms'), htmlspecialchars($fid) );
1927 + } else {
1928 + $adding = false;
1929 + $editing = true;
1930 + $default_form_values = $avail_fields[$fid] + $default_form_values;
1931 + }
1932 + }
1933 + if ($default_form_values['version'] >= 2 && $default_form_values['type'] == 'file') {
1934 + //Show allowed_extensions value in allowed_values field
1935 + $default_form_values['allowed_values'] = $default_form_values['allowed_extensions'];
1936 + }
1937 +
1938 +?>
1939 +<div id="accua_forms_fields_page" class="accua_forms_admin_page wrap nosubsub">
1940 +<h2><img src="<?php echo ACCUA_FORMS_DIR_URL.'img/cimatti-icon-20.png'; ?>"/> <?php _e('Contact Forms - Fields', 'contact-forms'); ?></h2>
1941 +<?php /* screen_icon(); ?>
1942 +<h2><?php echo esc_html( $title );
1943 +if ( !empty($_REQUEST['s']) )
1944 + printf( '<span class="subtitle">' . __('Search results for &#8220;%s&#8221;') . '</span>', esc_html( stripslashes($_REQUEST['s']) ) ); ?>
1945 +</h2>
1946 +
1947 +<?php if ( isset($_REQUEST['message']) && ( $msg = (int) $_REQUEST['message'] ) ) : ?>
1948 +<div id="message" class="updated"><p><?php echo $messages[$msg]; ?></p></div>
1949 +<?php $_SERVER['REQUEST_URI'] = remove_query_arg(array('message'), $_SERVER['REQUEST_URI']);
1950 +endif; */ ?>
1951 +<div id="ajax-response"><?php echo $message?></div>
1952 +
1953 +<?php /*
1954 +<form class="search-form" action="" method="get">
1955 +<input type="hidden" name="taxonomy" value="<?php echo esc_attr($taxonomy); ?>" />
1956 +<input type="hidden" name="post_type" value="<?php echo esc_attr($post_type); ?>" />
1957 +
1958 +<?php $wp_list_table->search_box( $tax->labels->search_items, 'tag' ); ?>
1959 +
1960 +</form>
1961 +*/ ?>
1962 +
1963 +<br class="clear" />
1964 +
1965 +<div id="col-container">
1966 +
1967 +<div id="col-right">
1968 +<div class="col-wrap">
1969 +<?php if (!$editing) { ?>
1970 +<form id="posts-filter" action="" method="post">
1971 +<input type="hidden" name="taxonomy" value="<?php echo esc_attr($taxonomy); /* TODO: Is this needed? */ ?>" />
1972 +<input type="hidden" name="post_type" value="<?php echo esc_attr($post_type); /* TODO: Is this needed? */ ?>" />
1973 +
1974 +<?php /* $wp_list_table->display(); */ ?>
1975 +
1976 +<table cellspacing="0" class="wp-list-table widefat fixed tags">
1977 + <thead>
1978 + <tr>
1979 + <th style="" class="manage-column column-cb check-column" id="cb" scope="col"><input type="checkbox" /></th>
1980 + <th style="" class="manage-column column-name" id="name" scope="col"><?php _e( 'Label', 'contact-forms'); ?></th>
1981 + <th style="" class="manage-column column-description" id="description" scope="col"><?php _e( 'Description', 'contact-forms'); ?></th>
1982 + <th style="" class="manage-column column-slug" id="slug" scope="col"><?php _e( 'Slug', 'contact-forms'); ?></th>
1983 + <th style="" class="manage-column column-type" id="type" scope="col"><?php _e( 'Type', 'contact-forms'); ?></th>
1984 + </tr>
1985 + </thead>
1986 +
1987 + <tfoot>
1988 + <tr>
1989 + <th style="" class="manage-column column-cb check-column" scope="col"><input type="checkbox" /></th>
1990 + <th style="" class="manage-column column-name" scope="col"><?php _e( 'Label', 'contact-forms'); ?></th>
1991 + <th style="" class="manage-column column-description" scope="col"><?php _e( 'Description', 'contact-forms'); ?></th>
1992 + <th style="" class="manage-column column-slug" scope="col"><?php _e( 'Slug', 'contact-forms'); ?></th>
1993 + <th style="" class="manage-column column-type" scope="col"><?php _e( 'Type', 'contact-forms'); ?></th>
1994 + </tr>
1995 + </tfoot>
1996 +
1997 + <tbody class="list:tag" id="the-list">
1998 +<?php
1999 + foreach ($avail_fields as $id => $field) {
2000 + foreach (array('id', 'name', 'type', 'description') as $i) {
2001 + $field[$i] = htmlspecialchars($field[$i], ENT_QUOTES);
2002 + $field[$i] = sanitize_text_field($field[$i]);
2003 + }
2004 + echo <<<END_OF_ROW
2005 + <tr id="field-{$field['id']}">
2006 + <th class="check-column" scope="row"><input type="checkbox" /></th>
2007 + <td class="name column-name"><strong><a title="Edit “{$field['name']}”" href="admin.php?page=accua_forms_fields&amp;edit-fid={$field['id']}" class="row-title">{$field['name']}</a></strong><br><div class="row-actions"><span class="edit"><a href="admin.php?page=accua_forms_fields&amp;edit-fid={$field['id']}">Edit</a></span></div></td>
2008 + <td class="description column-description">{$field['description']}</td>
2009 + <td class="slug column-slug">{$field['id']}</td>
2010 + <td class="type column-type">{$field['type']}</td>
2011 + </tr>
2012 +END_OF_ROW;
2013 + }
2014 +?>
2015 + </tbody>
2016 +</table>
2017 +
2018 +<br class="clear" />
2019 +</form>
2020 +<?php } ?>
2021 +<?php /* if ( 'category' == $taxonomy ) : ?>
2022 +<div class="form-wrap">
2023 +<p><?php printf(__('<strong>Note:</strong><br />Deleting a category does not delete the posts in that category. Instead, posts that were only assigned to the deleted category are set to the category <strong>%s</strong>.'), apply_filters('the_category', get_cat_name(get_option('default_category')))) ?></p>
2024 +<?php if ( current_user_can( 'import' ) ) : ?>
2025 +<p><?php printf(__('Categories can be selectively converted to tags using the <a href="%s">category to tag converter</a>.'), 'import.php') ?></p>
2026 +<?php endif; ?>
2027 +</div>
2028 +<?php elseif ( 'post_tag' == $taxonomy && current_user_can( 'import' ) ) : ?>
2029 +<div class="form-wrap">
2030 +<p><?php printf(__('Tags can be selectively converted to categories using the <a href="%s">tag to category converter</a>'), 'import.php') ;?>.</p>
2031 +</div>
2032 +<?php endif;
2033 +do_action('after-' . $taxonomy . '-table', $taxonomy);
2034 +*/ ?>
2035 +
2036 +</div>
2037 +</div><!-- /col-right -->
2038 +
2039 +<div id="col-left">
2040 +<div class="col-wrap">
2041 +
2042 +<?php
2043 +/*
2044 +if ( !is_null( $tax->labels->popular_items ) ) {
2045 + if ( current_user_can( $tax->cap->edit_terms ) )
2046 + $tag_cloud = wp_tag_cloud( array( 'taxonomy' => $taxonomy, 'echo' => false, 'link' => 'edit' ) );
2047 + else
2048 + $tag_cloud = wp_tag_cloud( array( 'taxonomy' => $taxonomy, 'echo' => false ) );
2049 +
2050 + if ( $tag_cloud ) :
2051 + ?>
2052 +<div class="tagcloud">
2053 +<h3><?php echo $tax->labels->popular_items; ?></h3>
2054 +<?php echo $tag_cloud; unset( $tag_cloud ); ?>
2055 +</div>
2056 +<?php
2057 +endif;
2058 +}
2059 +*/
2060 +
2061 +/*
2062 +if ( current_user_can($tax->cap->edit_terms) ) {
2063 + // Back compat hooks. Deprecated in preference to {$taxonomy}_pre_add_form
2064 + if ( 'category' == $taxonomy )
2065 + do_action('add_category_form_pre', (object)array('parent' => 0) );
2066 + elseif ( 'link_category' == $taxonomy )
2067 + do_action('add_link_category_form_pre', (object)array('parent' => 0) );
2068 + else
2069 + do_action('add_tag_form_pre', $taxonomy);
2070 +
2071 + do_action($taxonomy . '_pre_add_form', $taxonomy);
2072 +*/
2073 +
2074 +$types = accua_forms_fields_get_types();
2075 +?>
2076 +<div class="form-wrap">
2077 +<h3><?php echo $adding? __( 'Add new field','contact-forms'): __( 'Edit field','contact-forms') ; ?></h3>
2078 +<form id="addtag" method="post" action="admin.php?page=accua_forms_fields" class="validate">
2079 +<input type="hidden" name="action" value="<?php echo $adding?'add':'edit'; ?>-form-field" />
2080 +<?php /*
2081 +<input type="hidden" name="screen" value="<?php echo esc_attr($current_screen->id); ?>" />
2082 +<input type="hidden" name="taxonomy" value="<?php echo esc_attr($taxonomy); ?>" />
2083 +<input type="hidden" name="post_type" value="<?php echo esc_attr($post_type); ?>" />
2084 +*/ ?>
2085 +<?php wp_nonce_field('edit_form_field', '_wpnonce_edit_form_field'); ?>
2086 +
2087 +<div class="form-field form-required">
2088 + <label for="tag-name"><?php _e( 'Field label', 'contact-forms'); ?></label>
2089 + <input name="form-field-name" id="tag-name" type="text" value="<?php echo htmlspecialchars($default_form_values['name'], ENT_QUOTES) ?>" size="40" aria-required="true" />
2090 + <p><?php _e('The name is how it appears on your site.', 'contact-forms'); ?></p>
2091 +</div>
2092 +<?php /* if ( ! global_terms_enabled() ) : */ ?>
2093 +<div class="form-field">
2094 + <label for="tag-slug"><?php _e( 'Field slug (identificative)', 'contact-forms'); ?></label>
2095 + <input name="form-field-id" id="tag-slug" type="text" value="<?php echo htmlspecialchars($default_form_values['id'], ENT_QUOTES) ?>" <?php if (!$adding) { echo 'disabled="disabled"'; } ?> size="40" />
2096 + <?php if (!$adding) { echo '<input type="hidden" name="form-field-id" value="'.htmlspecialchars($default_form_values['id'], ENT_QUOTES).'" />'; } ?>
2097 + <p><?php _e('The &#8220;slug&#8221; is the URL-friendly version of the name. It is used as an identificator, and is unchangeable. It is usually all lowercase and it must contains only letters, numbers, and underscores.', 'contact-forms'); ?></p>
2098 +</div>
2099 +<div class="form-field">
2100 + <label for="parent"><?php _e( 'Field type', 'contact-forms'); ?></label>
2101 + <select class="postform" id="parent" name="form-field-type">
2102 + <?php /*
2103 + <option value="textfield" class="level-0" <?php echo ($default_form_values['type'] == 'textfield')?'selected="selected"':'';?> >Text Field</option>
2104 + <option value="textarea" class="level-0" <?php echo ($default_form_values['type'] == 'textarea')?'selected="selected"':'';?> >Text Area</option>
2105 + <option value="email" class="level-0" <?php echo ($default_form_values['type'] == 'email')?'selected="selected"':'';?> >Email</option>
2106 + <option value="checkbox" class="level-0" <?php echo ($default_form_values['type'] == 'checkbox')?'selected="selected"':'';?> >Checkbox</option>
2107 + <option value="select" class="level-0" <?php echo ($default_form_values['type'] == 'select')?'selected="selected"':'';?> >Select</option>
2108 + */
2109 + foreach ($types as $typeid => $typename) {
2110 + $selected = ($default_form_values['type'] == $typeid)?'selected="selected"':'';
2111 + echo <<<EOT
2112 +<option value="{$typeid}" class="level-0" {$selected} >{$typename}</option>
2113 +EOT;
2114 + }
2115 +
2116 + ?>
2117 + </select>
2118 +</div>
2119 +<?php /* endif; // global_terms_enabled() */ ?>
2120 +<?php /* if ( is_taxonomy_hierarchical($taxonomy) ) : ?>
2121 +<div class="form-field">
2122 + <label for="parent"><?php _ex('Parent', 'Taxonomy Parent'); ?></label>
2123 + <?php wp_dropdown_categories(array('hide_empty' => 0, 'hide_if_empty' => false, 'taxonomy' => $taxonomy, 'name' => 'parent', 'orderby' => 'name', 'hierarchical' => true, 'show_option_none' => __('None'))); ?>
2124 + <?php if ( 'category' == $taxonomy ) : // @todo: Generic text for hierarchical taxonomies ?>
2125 + <p><?php _e('Categories, unlike tags, can have a hierarchy. You might have a Jazz category, and under that have children categories for Bebop and Big Band. Totally optional.'); ?></p>
2126 + <?php endif; ?>
2127 +</div>
2128 +<?php endif; // is_taxonomy_hierarchical() */ ?>
2129 +<div class="form-field">
2130 + <label for="tag-description"><?php _e( 'Field description', 'contact-forms'); ?></label>
2131 + <textarea name="form-field-description" id="tag-description" rows="5" cols="40"><?php echo htmlspecialchars($default_form_values['description'], ENT_QUOTES) ?></textarea>
2132 + <p><?php _e('The description is not prominent by default; however, some themes may show it.', 'contact-forms'); ?></p>
2133 +</div>
2134 +
2135 +<div class="form-field">
2136 + <label for="form-field-default-value"><?php _e( 'Default value(s)', 'contact-forms'); ?>:</label>
2137 + <textarea name="form-field-default-value" id="form-field-default-value" rows="5" cols="40"><?php echo htmlspecialchars($default_form_values['default_value'], ENT_QUOTES) ?></textarea>
2138 + <p><?php _e( 'For multiple default values in multiple select and multiple checkboxes, use | as separator.', 'contact-forms'); ?></p>
2139 +</div>
2140 +
2141 +<div class="form-field">
2142 + <label for="form-field-allowed-values"><?php _e( 'Allowed values', 'contact-forms'); ?>:</label>
2143 + <textarea rows="5" cols="40" name="form-field-allowed-values" id=form-field-allowed-values"><?php echo htmlspecialchars($default_form_values['allowed_values'], ENT_QUOTES) ?></textarea>
2144 + <p><?php _e( 'Options used in select, radio and multiple checkboxes. Enter one value per line, in the format key|label. The key is the value that will be stored in the database. The label is optional, and the key will be used as the label if no label is specified. For file fields, this indicates allowed extensions (one per line without dot)', 'contact-forms'); ?></p>
2145 +</div>
2146 +
2147 +<div class="form-field">
2148 +<?php _e( 'Settings for date fields', 'contact-forms'); ?>
2149 +<div class="form-field">
2150 + <label for="form-field-default-date-value"><?php _e( 'Default value', 'contact-forms'); ?>:</label>
2151 + <input type="date" name="form-field-default-date-value" id="form-field-default-date-value" value="<?php echo htmlspecialchars($default_form_values['default_date_value'], ENT_QUOTES) ?>">
2152 +</div>
2153 +
2154 +
2155 +<label for="form-field-min-of-date"><?php _e( 'Min date', 'contact-forms'); ?>:</label>
2156 +<input type="date" id="form-field-min-of-date" name="form-field-min-of-date" value="<?php echo htmlspecialchars($default_form_values['min_date'], ENT_QUOTES) ?>">
2157 +
2158 +<label for="form-field-max-of-date"><?php _e( 'Max date', 'contact-forms'); ?>:</label>
2159 +<input type="date" id="form-field-max-of-date" name="form-field-max-of-date" value="<?php echo htmlspecialchars($default_form_values['max_date'], ENT_QUOTES) ?>">
2160 +
2161 +</div>
2162 +
2163 +
2164 +<?php
2165 +/*
2166 +if ( ! is_taxonomy_hierarchical($taxonomy) )
2167 + do_action('add_tag_form_fields', $taxonomy);
2168 +do_action($taxonomy . '_add_form_fields', $taxonomy);
2169 +*/
2170 +
2171 +if ($adding) {
2172 + submit_button( __( 'Add new field', 'contact-forms'), 'button' );
2173 +} else {
2174 + submit_button( __( 'Save changes', 'contact-forms'), 'button' );
2175 + submit_button( __( 'Delete field', 'contact-forms'), 'button', 'delete-field');
2176 +}
2177 +
2178 +/*
2179 +// Back compat hooks. Deprecated in preference to {$taxonomy}_add_form
2180 +if ( 'category' == $taxonomy )
2181 + do_action('edit_category_form', (object)array('parent' => 0) );
2182 +elseif ( 'link_category' == $taxonomy )
2183 + do_action('edit_link_category_form', (object)array('parent' => 0) );
2184 +else
2185 + do_action('add_tag_form', $taxonomy);
2186 +
2187 +do_action($taxonomy . '_add_form', $taxonomy);
2188 +*/
2189 +?>
2190 +</form></div>
2191 +<?php /* } */ ?>
2192 +
2193 +</div>
2194 +</div><!-- /col-left -->
2195 +
2196 +</div><!-- /col-container -->
2197 +</div><!-- /wrap -->
2198 +<?php
2199 + /* echo '<pre>accua_forms_avail_fields:', htmlspecialchars(print_r($avail_fields, true)), '</pre>'; */
2200 +}
2201 +
2202 +function accua_forms_settings_page() {
2203 +?>
2204 +<div id="accua_forms_settings_page" class="accua_forms_admin_page wrap">
2205 +<h2><img src="<?php echo ACCUA_FORMS_DIR_URL.'img/cimatti-icon-20.png'; ?>"/> <?php _e('Contact Forms - Default Settings', 'contact-forms'); ?></h2>
2206 +<?php
2207 + $empty_form_data = array(
2208 + 'success_message' => '',
2209 + 'error_message' => '',
2210 + 'emails_from_name' => '',
2211 + 'emails_from' => '',
2212 + 'admin_emails_to' => '',
2213 + 'emails_bcc' => '',
2214 + 'admin_emails_subject' => '',
2215 + 'admin_emails_message' => '',
2216 + 'confirmation_emails_subject' => '',
2217 + 'confirmation_emails_message' => '',
2218 + 'layout' => 'sidebyside',
2219 + 'style_margin' => '',
2220 + 'style_border_color' => '',
2221 + 'style_border_width' => '',
2222 + 'style_border_radius' => '',
2223 + 'style_background_color' => '',
2224 + 'style_padding' => '',
2225 + 'style_color' => '',
2226 + 'style_font_size' => '',
2227 + 'style_field_spacing' => '',
2228 + 'style_field_border_color' => '',
2229 + 'style_field_border_width' => '',
2230 + 'style_field_border_radius' => '',
2231 + 'style_field_background_color' => '',
2232 + 'style_field_padding' => '',
2233 + 'style_field_color' => '',
2234 + 'style_submit_border_color' => '',
2235 + 'style_submit_border_width' => '',
2236 + 'style_submit_border_radius' => '',
2237 + 'style_submit_background_color' => '',
2238 + 'style_submit_padding' => '',
2239 + 'style_submit_color' => '',
2240 + 'style_submit_font_size' => '',
2241 + );
2242 +
2243 + $empty_file_data = array(
2244 + 'valid_extensions' => '',
2245 + 'max_size' => '',
2246 + 'dest_path' => '',
2247 + );
2248 +
2249 + $empty_captcha_data = array(
2250 + 'recaptcha_force_v1' => '',
2251 + 'recaptcha_public_key' => '',
2252 + 'recaptcha_private_key' => '',
2253 + );
2254 +
2255 + $empty_analytics_data = array(
2256 + 'analytics_track_submit' => false,
2257 + 'analytics_track_fields' => false,
2258 + );
2259 +
2260 + $empty_anonymize_ip_data = array(
2261 + 'anonymize_ip_bytes' => 0,
2262 + );
2263 +
2264 + if($_SERVER['REQUEST_METHOD'] == 'POST' && !empty($_POST['accua_form_save_form_settings'])) {
2265 + check_admin_referer('accua_form_save_settings', '_nonce_accua_form_save_settings');
2266 + $post = stripslashes_deep($_POST);
2267 + $post += $empty_form_data;
2268 + $post += $empty_file_data;
2269 + $post += $empty_captcha_data;
2270 + $post += $empty_analytics_data;
2271 + $post += $empty_anonymize_ip_data;
2272 + $form_data = array();
2273 + $file_data = array();
2274 + $captcha_data = array();
2275 + $analytics_data = array();
2276 + $anonymize_ip_data = array();
2277 + foreach($empty_form_data as $key=>$val){
2278 + $form_data[$key] = $post[$key];
2279 + }
2280 + $form_data = accua_forms_filter_settings($form_data);
2281 +
2282 + $file_data['valid_extensions'] = accua_forms_filter_extensions($post['valid_extensions']);
2283 + $file_data['max_size'] = $post['max_size'];
2284 + if (current_user_can('edit_files') || current_user_can('install_plugins')) {
2285 + $file_data['dest_path'] = $post['dest_path'];
2286 + } else {
2287 + $old_file_data = get_option('accua_forms_default_file_field_data',array());
2288 + $file_data['dest_path'] = isset($old_file_data['dest_path']) ? $old_file_data['dest_path'] : '';
2289 + }
2290 +
2291 + $captcha_data['recaptcha_force_v1'] = (bool) $post['recaptcha_force_v1'];
2292 + $captcha_data['recaptcha_public_key'] = sanitize_text_field($post['recaptcha_public_key']);
2293 + $captcha_data['recaptcha_private_key'] = sanitize_text_field($post['recaptcha_private_key']);
2294 +
2295 + foreach($empty_analytics_data as $key=>$val){
2296 + $analytics_data[$key] = (bool) $post[$key];
2297 + }
2298 +
2299 + /* foreach($empty_anonymize_ip_data as $key=>$val){
2300 + $anonymize_ip_data[$key] = $post[$key];
2301 + } */
2302 + $anonymize_ip_bytes = (int) $post['anonymize_ip_bytes'];
2303 + if ($anonymize_ip_bytes < 0) {
2304 + $anonymize_ip_bytes = 0;
2305 + } else if ($anonymize_ip_bytes > 4) {
2306 + $anonymize_ip_bytes = 4;
2307 + }
2308 + $anonymize_ip_data['anonymize_ip_bytes'] = $anonymize_ip_bytes;
2309 +
2310 + update_option('accua_forms_default_form_data', $form_data);
2311 + update_option('accua_forms_default_file_field_data', $file_data);
2312 + update_option('accua_forms_default_captcha_field_data', $captcha_data);
2313 + update_option('accua_forms_default_analytics_data', $analytics_data);
2314 + update_option('accua_forms_anonymize_ip_data', $anonymize_ip_data);
2315 +
2316 + if (!empty($post['delete_previous_ip_values'])) {
2317 + global $wpdb;
2318 + $wpdb->query("UPDATE `{$wpdb->prefix}accua_forms_submissions` SET afs_ip = ''");
2319 + }
2320 + } else {
2321 + $form_data = get_option('accua_forms_default_form_data',array()) + $empty_form_data;
2322 + $file_data = get_option('accua_forms_default_file_field_data',array()) + $empty_file_data;
2323 + $captcha_data = get_option('accua_forms_default_captcha_field_data',array()) + $empty_captcha_data;
2324 + $analytics_data = get_option('accua_forms_default_analytics_data',array()) + $empty_analytics_data;
2325 + $anonymize_ip_data = get_option('accua_forms_anonymize_ip_data',array()) + $empty_anonymize_ip_data;
2326 + }
2327 + if ($captcha_data['recaptcha_force_v1']) {
2328 + $captcha_data = $empty_captcha_data;
2329 + }
2330 +?>
2331 +<form method="post">
2332 +<?php wp_nonce_field('accua_form_save_settings', '_nonce_accua_form_save_settings'); ?>
2333 +<input type="hidden" name="accua_form_save_form_settings" value="1" />
2334 +<?php /*
2335 +<p id="accua_form_layout"><?php _e( 'Layout', 'contact-forms'); ?>: <select name="layout" class="accua_form_value"><option value="sidebyside" <?php if ($form_data['layout'] == 'sidebyside') { echo 'selected="selected"'; } ?>>Labels on the left of the fields</option><option value="toplabel" <?php if ($form_data['layout'] == 'toplabel') { echo 'selected="selected"'; } ?>>Labels on top of the fields</option></select></p>
2336 +<p id="accua_form_success_message"><?php _e( 'Success message', 'contact-forms'); ?>:<br /><textarea name="success_message" class="accua_form_value" style="width:95%"; cols="80" rows="8"><?php echo htmlspecialchars($form_data['success_message'], ENT_QUOTES) ?></textarea></p>
2337 +<p id="accua_form_error_message"><?php _e( 'Error message', 'contact-forms'); ?>:<br /><textarea name="error_message" class="accua_form_value" style="width:95%"; cols="80" rows="8"><?php echo htmlspecialchars($form_data['error_message'], ENT_QUOTES) ?></textarea></p>
2338 +<p id="accua_form_emails_from"><?php _e( 'Emails from', 'contact-forms'); ?>: <input name="emails_from" class="accua_form_value" type="text" value="<?php echo htmlspecialchars($form_data['emails_from'], ENT_QUOTES) ?>" /></p>
2339 +<p id="accua_form_admin_emails_to"><?php _e( 'Admin emails to', 'contact-forms'); ?>: <input name="admin_emails_to" class="accua_form_value" type="text" value="<?php echo htmlspecialchars($form_data['admin_emails_to'], ENT_QUOTES) ?>" /></p>
2340 +<p id="accua_form_emails_bcc"><?php _e( 'Emails bcc', 'contact-forms'); ?>: <input name="emails_bcc" class="accua_form_value" type="text" value="<?php echo htmlspecialchars($form_data['emails_bcc'], ENT_QUOTES) ?>" /></p>
2341 +<p id="accua_form_admin_emails_subject"><?php _e( 'Admin email subject', 'contact-forms'); ?>: <input name="admin_emails_subject" class="accua_form_value" type="text" value="<?php echo htmlspecialchars($form_data['admin_emails_subject'], ENT_QUOTES) ?>" /></p>
2342 +<p id="accua_form_admin_emails_message"><?php _e( 'Admin email message', 'contact-forms'); ?>:<br /><textarea name="admin_emails_message" class="accua_form_value" style="width:95%"; cols="80" rows="8"><?php echo htmlspecialchars($form_data['admin_emails_message'], ENT_QUOTES) ?></textarea></p>
2343 +<p id="accua_form_confirmation_emails_subject"><?php _e( 'Confirmation email subject', 'contact-forms'); ?>: <input name="confirmation_emails_subject" class="accua_form_value" type="text" value="<?php echo htmlspecialchars($form_data['confirmation_emails_subject'], ENT_QUOTES) ?>" /></p>
2344 +<p id="accua_form_confirmation_emails_message"><?php _e( 'Confirmation email message', 'contact-forms'); ?>:<br /><textarea name="confirmation_emails_message" class="accua_form_value" style="width:95%"; cols="80" rows="8"><?php echo htmlspecialchars($form_data['confirmation_emails_message'], ENT_QUOTES) ?></textarea></p>
2345 +*/ ?>
2346 +<div id="accua_tab_messages" class="content_tab">
2347 + <?php
2348 + $settings_editor = array(
2349 + 'teeny' => true,
2350 + 'editor_class' => 'accua_form_value',
2351 + 'tinymce' => array(
2352 + 'theme_advanced_buttons1' => 'bold,italic,underline,|,bullist,numlist,'));
2353 + ?>
2354 + <div class="metabox-holder accua-forms-metabox-holder">
2355 + <div class="postbox ">
2356 + <h3 class="hndle"><span><?php _e('1. On-screen success message', 'contact-forms'); ?></span></h3>
2357 + <div class="inside" id="dashboard_right_now">
2358 + <div id="accua_form_success_message">
2359 + <?php wp_editor( $form_data['success_message'] , 'success_message' , $settings_editor); ?>
2360 + </div>
2361 + </div>
2362 + </div>
2363 + </div>
2364 +
2365 + <div class="metabox-holder accua-forms-metabox-holder">
2366 + <div class="postbox ">
2367 + <h3 class="hndle"><span><?php _e('2. On-screen error message', 'contact-forms'); ?></span></h3>
2368 + <div class="inside" id="dashboard_right_now">
2369 + <div id="accua_form_error_message">
2370 + <?php wp_editor( $form_data['error_message'] , 'error_message' , $settings_editor); ?>
2371 + </div>
2372 + </div>
2373 + </div>
2374 + </div>
2375 + <br clear="all"/>
2376 + <div class="metabox-holder accua-forms-metabox-holder">
2377 + <div class="postbox ">
2378 + <h3 class="hndle"><span><?php _e('3. Email to notify administrator', 'contact-forms'); ?></span></h3>
2379 + <div class="inside" id="dashboard_right_now">
2380 + <div id="accua_form_admin_emails_to" class="label_input">
2381 + <label><?php _e( 'To', 'contact-forms'); ?></label>
2382 + <input name="admin_emails_to" class="accua_form_value" type="text" value="<?php echo htmlspecialchars($form_data['admin_emails_to'], ENT_QUOTES) ?>" />
2383 + </div>
2384 + <br clear="all" />
2385 + <div id="accua_form_emails_bcc" class="label_input">
2386 + <label><?php _e( 'Bcc', 'contact-forms'); ?></label>
2387 + <input name="emails_bcc" class="accua_form_value" type="text" value="<?php echo htmlspecialchars($form_data['emails_bcc'], ENT_QUOTES) ?>" />
2388 + </div>
2389 + <br clear="all" />
2390 + <div id="accua_form_admin_emails_subject" class="label_input">
2391 + <label><?php _e( 'Subject', 'contact-forms'); ?></label>
2392 + <input name="admin_emails_subject" class="accua_form_value" type="text" value="<?php echo htmlspecialchars($form_data['admin_emails_subject'], ENT_QUOTES) ?>" />
2393 + </div>
2394 + <br clear="all" />
2395 + <div id="accua_form_admin_emails_message">
2396 + <?php wp_editor( $form_data['admin_emails_message'] , 'admin_emails_message' , $settings_editor); ?>
2397 + </div>
2398 +
2399 + </div>
2400 + </div>
2401 + </div>
2402 +
2403 + <div class="metabox-holder accua-forms-metabox-holder">
2404 + <div class="postbox ">
2405 + <h3 class="hndle"><span><?php _e('4. Email confirmation to the person who completed the form', 'contact-forms'); ?></span></h3>
2406 + <div class="inside" id="dashboard_right_now">
2407 + <div id="accua_form_emails_from_name" class="label_input">
2408 + <label><?php _e( 'From name', 'contact-forms'); ?></label>
2409 + <input class="accua_form_value" name="emails_from_name" type="text" value="<?php echo htmlspecialchars($form_data['emails_from_name'], ENT_QUOTES) ?>" />
2410 + </div>
2411 + <div id="accua_form_emails_from" class="label_input">
2412 + <label><?php _e( 'From email', 'contact-forms'); ?></label>
2413 + <input class="accua_form_value" name="emails_from" type="text" value="<?php echo htmlspecialchars($form_data['emails_from'], ENT_QUOTES) ?>" />
2414 + </div>
2415 + <br clear="all" />
2416 + <div id="accua_form_confirmation_emails_subject" class="label_input">
2417 + <label><?php _e( 'Subject', 'contact-forms'); ?></label>
2418 + <input class="accua_form_value" type="text" name="confirmation_emails_subject" value="<?php echo htmlspecialchars($form_data['confirmation_emails_subject'], ENT_QUOTES) ?>" />
2419 + </div>
2420 + <br clear="all" />
2421 + <div id="accua_form_confirmation_emails_message">
2422 + <?php wp_editor( $form_data['confirmation_emails_message'] , 'confirmation_emails_message' , $settings_editor); ?>
2423 + </div>
2424 + </div>
2425 + </div>
2426 + </div>
2427 + <br clear="all"/>
2428 +
2429 + <div class="metabox-holder accua-forms-metabox-holder">
2430 + <div class="postbox ">
2431 + <h3 class="hndle"><span><?php _e( 'File upload default settings', 'contact-forms'); ?></span></h3>
2432 + <div class="inside" id="dashboard_right_now">
2433 + <div id="accua_form_valid_extensions"><?php _e( 'Valid extensions', 'contact-forms'); ?> <br /><textarea name="valid_extensions" class="accua_form_value" style="width:95%"; cols="80" rows="8"><?php echo htmlspecialchars($file_data['valid_extensions'], ENT_QUOTES) ?></textarea>
2434 + <small><?php _e( 'List of valid extensions, without dot, one per line.', 'contact-forms'); ?></small>
2435 + </div>
2436 + <div id="accua_form_max_size"><?php _e( 'Maximum file size:', 'contact-forms'); ?> <input name="max_size" class="accua_form_value" type="text" value="<?php echo htmlspecialchars($file_data['max_size'], ENT_QUOTES) ?>" /><br />
2437 + <small><?php _e( 'You can use suffix K, M or G for kilobyte, megabyte or gigabyte.', 'contact-forms'); ?>
2438 + <?php
2439 + $server_max_size = AccuaForm_Element_File::file_upload_max_size();
2440 + if ($server_max_size > 0) {
2441 + _e( 'This value is limited by server upload limits of ', 'contact-forms');
2442 + echo AccuaForm_Element_File::format_size($server_max_size).". ";
2443 + _e( 'If you need a greater limit you should ask to the server administrator.', 'contact-forms');
2444 + }
2445 + ?>
2446 + </small>
2447 + </div>
2448 + <?php if (current_user_can('edit_files') || current_user_can('install_plugins')) { ?>
2449 + <div id="accua_form_dest_path"><?php _e( 'Upload path', 'contact-forms');?> : <input name="dest_path" class="accua_form_value" type="text" value="<?php echo htmlspecialchars($file_data['dest_path'], ENT_QUOTES) ?>" />
2450 + <small><?php _e( 'If it stars with \'/\' an absolute path is used, otherwise a path relative to the WordPress installation directory. Default value is "wp-content/uploads/accua-forms"', 'contact-forms');?>.</small>
2451 + </div>
2452 + <?php } ?>
2453 + </div>
2454 + </div>
2455 +
2456 + <div class="postbox ">
2457 + <h3 class="hndle"><span><?php _e( 'reCaptcha settings', 'contact-forms'); ?></span></h3>
2458 + <div class="inside" id="dashboard_right_now">
2459 + <p><?php _e( 'As reCAPTCHA v1 is discontinued, only reCAPTCHA v2 is supported', 'contact-forms');?></p>
2460 + <p><?php echo strtr(__('Please register this site for reCAPTCHA v2 on %REGISTERURL%, then enter the keys for this site in the following fields', 'contact-forms'), array('%REGISTERURL%' => '<a href="https://www.google.com/recaptcha" target="_blank">google.com/recaptcha</a>'));?></p>
2461 + <div id="accua_form_recaptcha_public_key"><?php _e('Site key', 'contact-forms');?> : <input name="recaptcha_public_key" class="accua_form_value" type="text" value="<?php echo htmlspecialchars($captcha_data['recaptcha_public_key'], ENT_QUOTES) ?>" />
2462 + </div>
2463 + <div id="accua_form_recaptcha_private_key"><?php _e('Secret key', 'contact-forms');?> : <input name="recaptcha_private_key" class="accua_form_value" type="text" value="<?php echo htmlspecialchars($captcha_data['recaptcha_private_key'], ENT_QUOTES) ?>" />
2464 + </div>
2465 + </div>
2466 + </div>
2467 +
2468 + <div class="postbox ">
2469 + <h3 class="hndle"><span><?php _e( 'IP address tracking', 'contact-forms'); ?></span></h3>
2470 + <div class="inside" id="dashboard_accua_form_anonymize_ip_addresses">
2471 + <p>
2472 + <?php _e("Select how many bytes of the visitor's IPs should be masked.", 'contact-forms');?>
2473 + </p>
2474 + <p>
2475 + <input type="radio" name="anonymize_ip_bytes" id="anonymize_ip_bytes_0" value="0" <?php if($anonymize_ip_data['anonymize_ip_bytes'] == 0) { echo 'checked="checked"'; } ?> />
2476 + <label for="anonymize_ip_bytes_0"><?php _e('No mask - e.g. 192.168.1.1', 'contact-forms');?></label><br />
2477 + </p>
2478 + <p>
2479 + <input type="radio" name="anonymize_ip_bytes" id="anonymize_ip_bytes_1" value="1" <?php if($anonymize_ip_data['anonymize_ip_bytes'] == 1) { echo 'checked="checked"'; } ?> />
2480 + <label for="anonymize_ip_bytes_1"><?php _e('1 byte - e.g. 192.168.1.xxx', 'contact-forms');?></label><br />
2481 + </p>
2482 + <p>
2483 + <input type="radio" name="anonymize_ip_bytes" id="anonymize_ip_bytes_2" value="2" <?php if($anonymize_ip_data['anonymize_ip_bytes'] == 2) { echo 'checked="checked"'; } ?> />
2484 + <label for="anonymize_ip_bytes_2"><?php _e('2 byte - e.g. 192.168.xxx.xxx', 'contact-forms');?></label><br />
2485 + </p>
2486 + <p>
2487 + <input type="radio" name="anonymize_ip_bytes" id="anonymize_ip_bytes_3" value="3" <?php if($anonymize_ip_data['anonymize_ip_bytes'] == 3) { echo 'checked="checked"'; } ?> />
2488 + <label for="anonymize_ip_bytes_3"><?php _e('3 byte - e.g. 192.xxx.xxx.xxx', 'contact-forms');?></label><br />
2489 + </p>
2490 + <p>
2491 + <input type="radio" name="anonymize_ip_bytes" id="anonymize_ip_bytes_4" value="4" <?php if($anonymize_ip_data['anonymize_ip_bytes'] == 4) { echo 'checked="checked"'; } ?> />
2492 + <label for="anonymize_ip_bytes_4"><?php _e('Fully mask IP address', 'contact-forms');?></label><br />
2493 + </p>
2494 + <h4><?php _e( 'Delete IP addresses', 'contact-forms'); ?></h4>
2495 + <p>
2496 + <input type="checkbox" id="delete_previous_ip_values" name="delete_previous_ip_values" class="accua_form_value" value="1" />
2497 + <label for="delete_previous_ip_values"><?php _e('Delete all previous IP values', 'contact-forms');?></label><br />
2498 + </p>
2499 + <br clear="all">
2500 + </div>
2501 + </div>
2502 +
2503 + <div class="postbox ">
2504 + <h3 class="hndle"><span><?php _e( 'Track actions with Google Analytics', 'contact-forms'); ?></span></h3>
2505 + <div class="inside" id="dashboard_right_now">
2506 + <p>
2507 + <input type="checkbox" id="accua_form_analytics_track_submit" name="analytics_track_submit" class="accua_form_value" value="1" <?php if($analytics_data['analytics_track_submit']) { echo 'checked="checked"'; } ?> />
2508 + <label for="accua_form_analytics_track_submit"><?php _e('Track submissions', 'contact-forms');?></label>
2509 + </p>
2510 + <p>
2511 + <input type="checkbox" id="accua_form_analytics_track_fields" name="analytics_track_fields" class="accua_form_value" value="1" <?php if($analytics_data['analytics_track_fields']) { echo 'checked="checked"'; } ?> />
2512 + <label for="accua_form_analytics_track_fields"><?php _e('Track fields filled in', 'contact-forms');?></label>
2513 + </p>
2514 + </div>
2515 + </div>
2516 +
2517 + </div>
2518 +
2519 + <div class="metabox-holder accua-forms-metabox-holder">
2520 + <div class="postbox ">
2521 + <h3 class="hndle"><span><?php _e( 'Layout &amp; Styling', 'contact-forms'); ?></span></h3>
2522 + <div class="inside" id="dashboard_right_now">
2523 + <p><?php _e( 'Customize the look and feel of your forms. Leave fields empty if you wish to use the native styles of your WordPress Theme.', 'contact-forms'); ?><p>
2524 + <h4><?php _e( 'Forms', 'contact-forms'); ?></h4>
2525 + <div id="accua_form_layout"> <?php _e( 'Layout', 'contact-forms'); ?>
2526 + <select name="layout" class="accua_form_value"><option value="sidebyside" <?php if ($form_data['layout'] == 'sidebyside') { echo 'selected="selected"'; } ?>>Labels on the left of the fields</option><option value="toplabel" <?php if ($form_data['layout'] == 'toplabel') { echo 'selected="selected"'; } ?>>Labels on top of the fields</option></select>
2527 + </div>
2528 + <div id="accua_form_style_margin" class="label_input">
2529 + <label><?php _e( 'Margin', 'contact-forms'); ?></label>
2530 + <input name="style_margin" class="accua_form_value" type="text" value="<?php echo htmlspecialchars($form_data['style_margin'], ENT_QUOTES) ?>" />
2531 + </div>
2532 + <div id="accua_form_style_border_color" class="label_input">
2533 + <label><?php _e( 'Border color', 'contact-forms'); ?></label>
2534 + <input name="style_border_color" class="accua_form_value" type="text" value="<?php echo htmlspecialchars($form_data['style_border_color'], ENT_QUOTES) ?>" />
2535 + </div>
2536 + <div id="accua_form_style_border_width" class="label_input">
2537 + <label><?php _e( 'Border width', 'contact-forms'); ?></label>
2538 + <input name="style_border_width" class="accua_form_value" type="text" value="<?php echo htmlspecialchars($form_data['style_border_width'], ENT_QUOTES) ?>" />
2539 + </div>
2540 + <div id="accua_form_style_border_radius" class="label_input">
2541 + <label><?php _e( 'Rounded corner radius', 'contact-forms'); ?></label>
2542 + <input name="style_border_radius" class="accua_form_value" type="text" value="<?php echo htmlspecialchars($form_data['style_border_radius'], ENT_QUOTES) ?>" />
2543 + </div>
2544 + <div id="accua_form_style_background_color" class="label_input">
2545 + <label><?php _e( 'Background color', 'contact-forms'); ?></label>
2546 + <input name="style_background_color" class="accua_form_value" type="text" value="<?php echo htmlspecialchars($form_data['style_background_color'], ENT_QUOTES) ?>" />
2547 + </div>
2548 + <div id="accua_form_style_padding" class="label_input">
2549 + <label><?php _e( 'Padding', 'contact-forms'); ?></label>
2550 + <input name="style_padding" class="accua_form_value" type="text" value="<?php echo htmlspecialchars($form_data['style_padding'], ENT_QUOTES) ?>" />
2551 + </div>
2552 + <div id="accua_form_style_color" class="label_input">
2553 + <label><?php _e( 'Text color', 'contact-forms'); ?></label>
2554 + <input name="style_color" class="accua_form_value" type="text" value="<?php echo htmlspecialchars($form_data['style_color'], ENT_QUOTES) ?>" />
2555 + </div>
2556 + <div id="accua_form_style_font_size" class="label_input">
2557 + <label><?php _e( 'Font size', 'contact-forms'); ?></label>
2558 + <input name="style_font_size" class="accua_form_value" type="text" value="<?php echo htmlspecialchars($form_data['style_font_size'], ENT_QUOTES) ?>" />
2559 + </div>
2560 +
2561 + <h4><?php _e( 'Fields', 'contact-forms'); ?></h4>
2562 + <div id="accua_form_style_field_spacing" class="label_input">
2563 + <label><?php _e( 'Spacing', 'contact-forms'); ?></label>
2564 + <input name="style_field_spacing" class="accua_form_value" type="text" value="<?php echo htmlspecialchars($form_data['style_field_spacing'], ENT_QUOTES) ?>" />
2565 + </div>
2566 + <div id="accua_form_style_field_border_color" class="label_input">
2567 + <label><?php _e( 'Border color', 'contact-forms'); ?></label>
2568 + <input name="style_field_border_color" class="accua_form_value" type="text" value="<?php echo htmlspecialchars($form_data['style_field_border_color'], ENT_QUOTES) ?>" />
2569 + </div>
2570 + <div id="accua_form_style_field_border_width" class="label_input">
2571 + <label><?php _e( 'Border width', 'contact-forms'); ?></label>
2572 + <input name="style_field_border_width" class="accua_form_value" type="text" value="<?php echo htmlspecialchars($form_data['style_field_border_width'], ENT_QUOTES) ?>" />
2573 + </div>
2574 + <div id="accua_form_style_field_border_radius" class="label_input">
2575 + <label><?php _e( 'Rounded corner radius', 'contact-forms'); ?></label>
2576 + <input name="style_field_border_radius" class="accua_form_value" type="text" value="<?php echo htmlspecialchars($form_data['style_field_border_radius'], ENT_QUOTES) ?>" />
2577 + </div>
2578 + <div id="accua_form_style_field_background_color" class="label_input">
2579 + <label><?php _e( 'Background color', 'contact-forms'); ?></label>
2580 + <input name="style_field_background_color" class="accua_form_value" type="text" value="<?php echo htmlspecialchars($form_data['style_field_background_color'], ENT_QUOTES) ?>" />
2581 + </div>
2582 + <div id="accua_form_style_field_padding" class="label_input">
2583 + <label><?php _e( 'Padding', 'contact-forms'); ?></label>
2584 + <input name="style_field_padding" class="accua_form_value" type="text" value="<?php echo htmlspecialchars($form_data['style_field_padding'], ENT_QUOTES) ?>" />
2585 + </div>
2586 + <div id="accua_form_style_field_color" class="label_input">
2587 + <label><?php _e( 'Text color', 'contact-forms'); ?></label>
2588 + <input name="style_field_color" class="accua_form_value" type="text" value="<?php echo htmlspecialchars($form_data['style_field_color'], ENT_QUOTES) ?>" />
2589 + </div>
2590 +
2591 + <h4><?php _e( 'Submit button', 'contact-forms'); ?></h4>
2592 + <div id="accua_form_style_submit_border_color" class="label_input">
2593 + <label><?php _e( 'Border color', 'contact-forms'); ?></label>
2594 + <input name="style_submit_border_color" class="accua_form_value" type="text" value="<?php echo htmlspecialchars($form_data['style_submit_border_color'], ENT_QUOTES) ?>" />
2595 + </div>
2596 + <div id="accua_form_style_submit_border_width" class="label_input">
2597 + <label><?php _e( 'Border width', 'contact-forms'); ?></label>
2598 + <input name="style_submit_border_width" class="accua_form_value" type="text" value="<?php echo htmlspecialchars($form_data['style_submit_border_width'], ENT_QUOTES) ?>" />
2599 + </div>
2600 + <div id="accua_form_style_submit_border_radius" class="label_input">
2601 + <label><?php _e( 'Rounded corner radius', 'contact-forms'); ?></label>
2602 + <input name="style_submit_border_radius" class="accua_form_value" type="text" value="<?php echo htmlspecialchars($form_data['style_submit_border_radius'], ENT_QUOTES) ?>" />
2603 + </div>
2604 + <div id="accua_form_style_submit_background_color" class="label_input">
2605 + <label><?php _e( 'Background color', 'contact-forms'); ?></label>
2606 + <input name="style_submit_background_color" class="accua_form_value" type="text" value="<?php echo htmlspecialchars($form_data['style_submit_background_color'], ENT_QUOTES) ?>" />
2607 + </div>
2608 + <div id="accua_form_style_submit_padding" class="label_input">
2609 + <label><?php _e( 'Padding', 'contact-forms'); ?></label>
2610 + <input name="style_submit_padding" class="accua_form_value" type="text" value="<?php echo htmlspecialchars($form_data['style_submit_padding'], ENT_QUOTES) ?>" />
2611 + </div>
2612 + <div id="accua_form_style_submit_color" class="label_input">
2613 + <label><?php _e( 'Text color', 'contact-forms'); ?></label>
2614 + <input name="style_submit_color" class="accua_form_value" type="text" value="<?php echo htmlspecialchars($form_data['style_submit_color'], ENT_QUOTES) ?>" />
2615 + </div>
2616 + <div id="accua_form_style_submit_font_size" class="label_input">
2617 + <label><?php _e( 'Font size', 'contact-forms'); ?></label>
2618 + <input name="style_submit_font_size" class="accua_form_value" type="text" value="<?php echo htmlspecialchars($form_data['style_submit_font_size'], ENT_QUOTES) ?>" />
2619 + </div>
2620 + <br clear="all" />
2621 + </div>
2622 + </div>
2623 + </div>
2624 +
2625 +
2626 + <br clear="all"/>
2627 +
2628 +</div>
2629 +
2630 +<?php /*
2631 +<h3><?php _e( 'File upload default settings', 'contact-forms'); ?></h3>
2632 +<p id="accua_form_valid_extensions"><?php _e( 'Valid extensions', 'contact-forms'); ?> <br /><textarea name="valid_extensions" class="accua_form_value" style="width:95%"; cols="80" rows="8"><?php echo htmlspecialchars($file_data['valid_extensions'], ENT_QUOTES) ?></textarea>
2633 + <small><?php _e( 'List of valid extensions, without dot, one per line.', 'contact-forms'); ?></small>
2634 +</p>
2635 +<p id="accua_form_max_size"><?php _e( 'Maximum file size:', 'contact-forms'); ?> <input name="max_size" class="accua_form_value" type="text" value="<?php echo htmlspecialchars($file_data['max_size'], ENT_QUOTES) ?>" /><br />
2636 + <small><?php _e( 'You can use suffix K, M or G for kilobyte, megabyte or gigabyte.', 'contact-forms'); ?>
2637 +<?php
2638 + $server_max_size = AccuaForm_Element_File::file_upload_max_size();
2639 + if ($server_max_size > 0) {
2640 + _e( 'This value is limited by server upload limits of ', 'contact-forms');
2641 + echo AccuaForm_Element_File::format_size($server_max_size).". ";
2642 + _e( 'If you need a greater limit you should ask to the server administrator.', 'contact-forms');
2643 + }
2644 +?>
2645 + </small></p>
2646 +<p id="accua_form_dest_path"><?php _e( 'Upload path', 'contact-forms');?> : <input name="dest_path" class="accua_form_value" type="text" value="<?php echo htmlspecialchars($file_data['dest_path'], ENT_QUOTES) ?>" />
2647 + <small><?php _e( 'If it stars with \'/\' an absolute path is used, otherwise a path relative to the WordPress installation directory. Default value is "wp-content/uploads/accua-forms"', 'contact-forms');?>.</small>
2648 +</p> */ ?>
2649 +<p><input class="button button-primary button-large" id="accua_form_save_settings" type="submit" value="Save settings" /></p>
2650 +
2651 +<?php accua_forms_print_tokens(); ?>
2652 +
2653 +</form>
2654 +</div>
2655 +
2656 +<script type='text/javascript'>
2657 +jQuery(function($) {
2658 + $('#accua_form_style_border_color .accua_form_value').colorPicker();
2659 + $('#accua_form_style_background_color .accua_form_value').colorPicker();
2660 + $('#accua_form_style_color .accua_form_value').colorPicker();
2661 + $('#accua_form_style_field_border_color .accua_form_value').colorPicker();
2662 + $('#accua_form_style_field_background_color .accua_form_value').colorPicker();
2663 + $('#accua_form_style_field_color .accua_form_value').colorPicker();
2664 + $('#accua_form_style_submit_border_color .accua_form_value').colorPicker();
2665 + $('#accua_form_style_submit_background_color .accua_form_value').colorPicker();
2666 + $('#accua_form_style_submit_color .accua_form_value').colorPicker();
2667 +});
2668 +</script>
2669 +
2670 +<?php
2671 +}
2672 +
2673 +function _accua_forms_get_abs_dest_path($dest_path = '') {
2674 + if ($dest_path === '') {
2675 + return realpath(ABSPATH) . '/wp-content/uploads/accua-forms';
2676 + } else if (substr($dest_path,0,1) === '/') {
2677 + return $dest_path;
2678 + } else {
2679 + return realpath(ABSPATH) . '/' . $dest_path;
2680 + }
2681 +}
2682 +
1517 2683 function _accua_forms_get_form_data($fid = false, $return_empty = true, $restore_trash = false){
1518 2684 $empty_form_data = array(
1519 2685 'fields' => array(),
1520 2686 'title' => '',
@@ -1528,9 +2694,8 @@
1528 2694 'admin_emails_message' => '',
1529 2695 'confirmation_emails_subject' => '',
1530 2696 'confirmation_emails_message' => '',
1531 2697 'use_ajax' => true,
1532 - 'gads_conversion_tracking_code' => '',
1533 2698 'layout' => 'sidebyside',
1534 2699 'style_margin' => '',
1535 2700 'style_border_color' => '',
1536 2701 'style_border_width' => '',
@@ -1552,12 +2717,8 @@
1552 2717 'style_submit_background_color' => '',
1553 2718 'style_submit_padding' => '',
1554 2719 'style_submit_color' => '',
1555 2720 'style_submit_font_size' => '',
1556 - 'submission_retention_override' => false,
1557 - 'submission_retention_value' => 0,
1558 - 'submission_retention_unit' => 'months',
1559 - 'submission_retention_mode' => 'anonymize',
1560 2721 );
1561 2722
1562 2723 if ($fid === false) {
1563 2724 return $empty_form_data;
@@ -1583,10 +2744,17 @@
1583 2744 if (isset($forms_data[$fid])) {
1584 2745 $form_data = array(
1585 2746 '_overrided' => $forms_data[$fid]
1586 2747 ) + $forms_data[$fid] + $default_form_data + $empty_form_data;
2748 + /*
2749 + if ($form_data['fields']) {
2750 + foreach ($form_data['fields'] as $i => $istance_data) {
2751 + // TODO: popuplate default fields data?
2752 + }
2753 + }
2754 + */
1587 2755 return $form_data;
1588 - } elseif ($return_empty) {
2756 + } else if ($return_empty) {
1589 2757 return array(
1590 2758 '_overrided' => array()
1591 2759 ) + $default_form_data + $empty_form_data;
1592 2760 } else {
@@ -1594,149 +2762,8 @@
1594 2762 }
1595 2763
1596 2764 }
1597 2765
1598 -/**
1599 - * Draft System Functions
1600 - *
1601 - * The draft system allows users to make changes to forms in the admin editor
1602 - * without immediately affecting the live/published form. Changes are stored in
1603 - * a transient until the user clicks Save, which publishes the draft.
1604 - *
1605 - * Pattern follows WordPress auto-draft system.
1606 - */
1607 -
1608 -/**
1609 - * Get the transient key for a form's draft data.
1610 - *
1611 - * @param string|int $fid Form ID.
1612 - * @return string Transient key.
1613 - */
1614 -// phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedFunctionFound -- Internal helper function
1615 -function _accua_forms_get_draft_key( $fid ) {
1616 - return 'accua_forms_draft_' . $fid;
1617 -}
1618 -
1619 -/**
1620 - * Initialize or get existing draft for a form.
1621 - * Called when the form editor is loaded.
1622 - *
1623 - * If a draft exists, returns it.
1624 - * If no draft exists, creates one from published data.
1625 - *
1626 - * @param string|int $fid Form ID.
1627 - * @return array Draft data array.
1628 - */
1629 -// phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedFunctionFound -- Internal helper function
1630 -function _accua_forms_init_draft( $fid ) {
1631 - $draft_key = _accua_forms_get_draft_key( $fid );
1632 -
1633 - // Check for existing draft
1634 - $draft_data = get_transient( $draft_key );
1635 -
1636 - if ( $draft_data !== false ) {
1637 - // Draft exists - return it
1638 - return $draft_data;
1639 - }
1640 -
1641 - // No draft - create from published data
1642 - $forms_data = get_option( 'accua_forms_saved_forms', array() );
1643 -
1644 - if ( isset( $forms_data[ $fid ] ) ) {
1645 - $draft_data = $forms_data[ $fid ];
1646 - } else {
1647 - // New form - initialize empty structure
1648 - $draft_data = array( 'fields' => array() );
1649 - }
1650 -
1651 - // Store as draft with 24 hour expiry
1652 - set_transient( $draft_key, $draft_data, DAY_IN_SECONDS );
1653 -
1654 - return $draft_data;
1655 -}
1656 -
1657 -/**
1658 - * Get draft data for a form (creating if necessary).
1659 - * Used by AJAX handlers to read current draft state.
1660 - *
1661 - * @param string|int $fid Form ID.
1662 - * @return array Draft data array.
1663 - */
1664 -// phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedFunctionFound -- Internal helper function
1665 -function _accua_forms_get_draft_data( $fid ) {
1666 - $draft_key = _accua_forms_get_draft_key( $fid );
1667 - $draft_data = get_transient( $draft_key );
1668 -
1669 - if ( $draft_data === false ) {
1670 - // Initialize draft from published data
1671 - $draft_data = _accua_forms_init_draft( $fid );
1672 - }
1673 -
1674 - return $draft_data;
1675 -}
1676 -
1677 -/**
1678 - * Save data to draft transient.
1679 - * Called by AJAX handlers when fields are edited.
1680 - *
1681 - * @param string|int $fid Form ID.
1682 - * @param array $draft_data Complete draft data to save.
1683 - * @return bool True on success.
1684 - */
1685 -// phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedFunctionFound -- Internal helper function
1686 -function _accua_forms_save_draft( $fid, $draft_data ) {
1687 - $draft_key = _accua_forms_get_draft_key( $fid );
1688 - return set_transient( $draft_key, $draft_data, DAY_IN_SECONDS );
1689 -}
1690 -
1691 -/**
1692 - * Publish draft to live data.
1693 - * Called when user clicks Save button.
1694 - *
1695 - * @param string|int $fid Form ID.
1696 - * @return bool True on success.
1697 - */
1698 -// phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedFunctionFound -- Internal helper function
1699 -function _accua_forms_publish_draft( $fid ) {
1700 - $draft_key = _accua_forms_get_draft_key( $fid );
1701 - $draft_data = get_transient( $draft_key );
1702 -
1703 - if ( $draft_data === false ) {
1704 - // No draft to publish - shouldn't happen normally
1705 - return false;
1706 - }
1707 -
1708 - // Get current published data
1709 - $forms_data = get_option( 'accua_forms_saved_forms', array() );
1710 -
1711 - // Update with draft
1712 - $forms_data[ $fid ] = $draft_data;
1713 -
1714 - // Save to database
1715 - $result = update_option( 'accua_forms_saved_forms', $forms_data );
1716 -
1717 - if ( $result ) {
1718 - // Clear draft after successful publish
1719 - delete_transient( $draft_key );
1720 - }
1721 -
1722 - return $result;
1723 -}
1724 -
1725 -/**
1726 - * Delete draft for a form.
1727 - * Called when discarding changes or after successful publish.
1728 - *
1729 - * @param string|int $fid Form ID.
1730 - * @return bool True on success.
1731 - */
1732 -// phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedFunctionFound -- Internal helper function
1733 -function _accua_forms_delete_draft( $fid ) {
1734 - $draft_key = _accua_forms_get_draft_key( $fid );
1735 - return delete_transient( $draft_key );
1736 -}
1737 -
1738 -// phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedFunctionFound -- Internal helper function, underscore prefix indicates private
1739 2766 function _accua_forms_style_parameters($params) {
1740 2767 $ret = '';
1741 2768 foreach ($params as $key => $value) {
1742 2769 $value = trim($value);
@@ -1760,23 +2787,9 @@
1760 2787 add_action('accua_form_alter', 'accua_forms_form_generate', -999, 2);
1761 2788 function accua_forms_form_generate($baseid, $form) {
1762 2789 if (substr($baseid, 0, 14) == '__accua-form__') {
1763 2790 $fid = substr($baseid,14);
1764 -
1765 - // Check if we're in admin preview mode - if so, read from draft
1766 - $use_draft = apply_filters('accua_forms_use_draft_for_preview', false);
1767 - if ($use_draft) {
1768 - // Get draft data and merge with defaults
1769 - $draft_data = _accua_forms_get_draft_data($fid);
1770 - $default_form_data = get_option('accua_forms_default_form_data', array());
1771 - $empty_form_data = _accua_forms_get_form_data(false); // Get empty structure
1772 - $form_data = array(
1773 - '_overrided' => $draft_data
1774 - ) + $draft_data + $default_form_data + $empty_form_data;
1775 - } else {
1776 - // Frontend: read from published data
1777 - $form_data = _accua_forms_get_form_data($fid, false);
1778 - }
2791 + $form_data = _accua_forms_get_form_data($fid, false);
1779 2792 /*
1780 2793 echo '<!-- fid = ';
1781 2794 print_r($fid);
1782 2795 echo "\n\nform_data = ";
@@ -1783,45 +2796,14 @@
1783 2796 print_r($form_data);
1784 2797 echo "\n-->";
1785 2798 */
1786 2799 if ($form_data) {
1787 - // Check for preview order override (allows live preview of field reorder before save)
1788 - $preview_order_override = apply_filters('accua_forms_preview_order_override', null);
1789 - if ($preview_order_override && !empty($form_data['fields'])) {
1790 - // Find the sidebar key for this form (format: cimatti-accua-fields-form-area-{fid})
1791 - $sidebar_key = 'cimatti-accua-fields-form-area-' . $fid;
1792 - if (isset($preview_order_override[$sidebar_key])) {
1793 - $order_string = $preview_order_override[$sidebar_key];
1794 - $order_array = explode(',', $order_string);
1795 -
1796 - // Reorder fields according to preview order
1797 - $old_fields = $form_data['fields'];
1798 - $new_fields = array();;
1799 -
1800 - foreach ($order_array as $widget_id) {
1801 - // Extract instance ID from widget ID (format: widget-{type}_{instance_id})
1802 - $instance_id = preg_replace('/^(new-)?widget-\\d+_/', '', $widget_id);
1803 - if (isset($old_fields[$instance_id])) {
1804 - $new_fields[$instance_id] = $old_fields[$instance_id];
1805 - unset($old_fields[$instance_id]);
1806 - }
1807 - }
1808 -
1809 - // Append any remaining fields not in order
1810 - if ($old_fields) {
1811 - $new_fields += $old_fields;
1812 - }
1813 -
1814 - $form_data['fields'] = $new_fields;
1815 - }
1816 - }
1817 -
1818 2800 $form_style = _accua_forms_style_parameters(array(
1819 2801 'margin' => $form_data['style_margin'],
1820 2802 'border-color' => $form_data['style_border_color'],
1821 2803 'border-width' => $form_data['style_border_width'],
1822 2804 'border-radius' => $form_data['style_border_radius'],
1823 - 'background-color' => $form_data['style_background_color'],
2805 + 'background' => $form_data['style_background_color'],
1824 2806 'padding' => $form_data['style_padding'],
1825 2807 'color' => $form_data['style_color'],
1826 2808 'font-size' => $form_data['style_font_size'],
1827 2809 ));
@@ -1830,9 +2812,9 @@
1830 2812 'margin-bottom' => $form_data['style_field_spacing'],
1831 2813 'border-color' => $form_data['style_field_border_color'],
1832 2814 'border-width' => $form_data['style_field_border_width'],
1833 2815 'border-radius' => $form_data['style_field_border_radius'],
1834 - 'background-color' => $form_data['style_field_background_color'],
2816 + 'background' => (trim($form_data['style_field_background_color']) === '')?'transparent':$form_data['style_field_background_color'],
1835 2817 'padding' => $form_data['style_field_padding'],
1836 2818 'color' => (trim($form_data['style_field_color']) === '')?$form_data['style_color']:$form_data['style_field_color'],
1837 2819 'font-size' => $form_data['style_font_size'],
1838 2820 ));
@@ -1839,17 +2821,14 @@
1839 2821 $field_properties = array();
1840 2822 if ($field_style !== '') {
1841 2823 $field_properties['style'] = $field_style;
1842 2824 }
1843 - // These will be set per-field in the loop below, initialized empty here
1844 - $field_properties['wrapperCssClass'] = '';
1845 - $field_properties['wrapperCssId'] = '';
1846 2825
1847 2826 $submit_style = _accua_forms_style_parameters(array(
1848 2827 'border-color' => $form_data['style_submit_border_color'],
1849 2828 'border-width' => $form_data['style_submit_border_width'],
1850 2829 'border-radius' => $form_data['style_submit_border_radius'],
1851 - 'background-color' => $form_data['style_submit_background_color'],
2830 + 'background' => $form_data['style_submit_background_color'],
1852 2831 'padding' => $form_data['style_submit_padding'],
1853 2832 'color' => $form_data['style_submit_color'],
1854 2833 'font-size' => $form_data['style_submit_font_size'],
1855 2834 ));
@@ -1882,9 +2861,9 @@
1882 2861 'name' => __('Fieldset begin', 'contact-forms'),
1883 2862 'type' => 'fieldset-begin',
1884 2863 'description' => '',
1885 2864 );
1886 - } elseif ($istance_data['ref'] == '__fieldset-end') {
2865 + } else if ($istance_data['ref'] == '__fieldset-end') {
1887 2866 $field_data = array(
1888 2867 'id' => '__fieldset-end',
1889 2868 'name' => __('Fieldset end', 'contact-forms'),
1890 2869 'type' => 'fieldset-end',
@@ -1904,10 +2883,8 @@
1904 2883 'description' => __('Use this special field to inject raw HTML in the form. You can use this multiple times.', 'contact-forms'),
1905 2884 'default_value' => '',
1906 2885 'allowed_values' => '',
1907 2886 'allowed_extensions' => '',
1908 - 'custom_required_message' => '',
1909 - 'custom_format_message' => '',
1910 2887 );
1911 2888
1912 2889 $istance_data += array(
1913 2890 'version' => 1,
@@ -1941,13 +2918,8 @@
1941 2918 'label' => $field_data['name'],
1942 2919 'default_value' => $field_data['default_value'], /* viene impostato il valore di defualt se non è un campo data */
1943 2920 'allowed_values' => $field_data['allowed_values'],
1944 2921 'allowed_extensions' => $field_data['allowed_extensions'],
1945 - 'post_type' => 'page', // Default for post-select fields
1946 - 'css_class' => '',
1947 - 'css_id' => '',
1948 - 'custom_required_message' => '',
1949 - 'custom_format_message' => '',
1950 2922 );
1951 2923
1952 2924 $element = NULL;
1953 2925 $element_conf = NULL;
@@ -1953,45 +2925,15 @@
1953 2925 $element_conf = NULL;
1954 2926
1955 2927 $allowed_val = trim($istance_data['allowed_values']);
1956 2928
1957 - // For post-select fields, we use lazy loading via AJAX, so don't pre-load posts here
1958 - if ($field_data['type'] == 'post-multicheckbox') {
1959 - // Post-multicheckbox still needs pre-loaded options for checkbox rendering
1960 - $post_type = isset($istance_data['post_type']) ? $istance_data['post_type'] : 'page';
1961 - $query_args = array();
1962 - if (!empty($allowed_val)) {
1963 - wp_parse_str($allowed_val, $query_args);
1964 - }
1965 - // Let a post_type in the query parameters override the field's
1966 - // post-type setting, matching post-select. The value comes from the
1967 - // saved field configuration (not a client request) and is validated
1968 - // against public post types.
1969 - if (!empty($query_args['post_type'])) {
1970 - $mc_public_types = get_post_types(array('public' => true));
1971 - $mc_override = sanitize_text_field($query_args['post_type']);
1972 - if (isset($mc_public_types[$mc_override])) {
1973 - $post_type = $mc_override;
1974 - }
1975 - }
1976 - $query_args['post_type'] = $post_type;
1977 - // Only publish/private may be exposed, even if the admin configured other statuses.
1978 - if (!empty($query_args['post_status'])) {
1979 - $mc_statuses = accua_forms_filter_field_post_status($query_args['post_status']);
1980 - if (!empty($mc_statuses)) {
1981 - $query_args['post_status'] = $mc_statuses;
1982 - } else {
1983 - unset($query_args['post_status']);
1984 - }
1985 - }
1986 - $posts = accua_get_pages($query_args);
2929 + if ($field_data['type'] == 'post-multicheckbox' || $field_data['type'] == 'post-select') {
2930 + $posts = accua_get_pages($allowed_val);
1987 2931 $allowed_values = array();
1988 2932 foreach ($posts as $p) {
2933 + //$allowed_values[$p->ID] = apply_filters( 'the_title', $p->post_title, $p->ID );
1989 2934 $allowed_values[$p->ID] = $p->post_title;
1990 2935 }
1991 - } elseif ($field_data['type'] == 'post-select') {
1992 - // Post-select uses lazy loading - just set empty options, JS will fetch
1993 - $allowed_values = array();
1994 2936 } else {
1995 2937 if ($field_data['type'] == 'file') {
1996 2938 $filedata = get_option('accua_forms_default_file_field_data',array());
1997 2939 $filedata += array(
@@ -2025,60 +2967,14 @@
2025 2967 $allowed_values[$val[0]] = $val[1];
2026 2968 }
2027 2969 }
2028 2970
2029 - // Set per-field wrapper CSS class and ID
2030 - $field_properties['wrapperCssClass'] = isset($istance_data['css_class']) ? $istance_data['css_class'] : '';
2031 - $field_properties['wrapperCssId'] = isset($istance_data['css_id']) ? $istance_data['css_id'] : '';
2032 -
2033 - // Captcha fields hide their title by default: the wrapper class makes
2034 - // the label screen-reader only (frontend.css), keeping it available to
2035 - // assistive tech and to the error summary JS label lookup.
2036 - if (in_array($field_data['type'], array('captcha', 'captcha_v3', 'cap'), true)
2037 - && accua_forms_captcha_hide_title($istance_data)) {
2038 - $field_properties['wrapperCssClass'] = trim($field_properties['wrapperCssClass'] . ' accua-captcha-title-hidden');
2039 - }
2040 -
2041 - // Resolve per-field custom validation messages (per-form instance → field definition → default)
2042 - $resolved_required_msg = '';
2043 - if (!empty($istance_data['custom_required_message'])) {
2044 - $resolved_required_msg = $istance_data['custom_required_message'];
2045 - } elseif (!empty($field_data['custom_required_message'])) {
2046 - $resolved_required_msg = $field_data['custom_required_message'];
2047 - }
2048 -
2049 - $resolved_format_msg = '';
2050 - if (!empty($istance_data['custom_format_message'])) {
2051 - $resolved_format_msg = $istance_data['custom_format_message'];
2052 - } elseif (!empty($field_data['custom_format_message'])) {
2053 - $resolved_format_msg = $field_data['custom_format_message'];
2054 - }
2055 -
2056 - // Add data attributes for client-side custom messages (reset each iteration)
2057 - unset($field_properties['data-custom-required-msg']);
2058 - unset($field_properties['data-custom-format-msg']);
2059 - if ($resolved_required_msg !== '') {
2060 - $field_properties['data-custom-required-msg'] = $resolved_required_msg;
2061 - }
2062 - if ($resolved_format_msg !== '') {
2063 - $field_properties['data-custom-format-msg'] = $resolved_format_msg;
2064 - }
2065 -
2066 2971 switch ($field_data['type']) {
2067 2972 case 'textarea':
2068 2973 $element = new Element_Textarea($istance_data['label'], $istance_data['istance_id'], $field_properties+array('cols' => '50', 'value'=>$istance_data['default_value']));
2069 2974 break;
2070 2975 case 'hidden':
2071 - // Hidden inputs render without the .pfbc-element wrapper, so the
2072 - // editor's CSS Class / CSS ID land on the input itself.
2073 - $hidden_props = array();
2074 - if ( !empty($field_properties['wrapperCssId']) ) {
2075 - $hidden_props['id'] = $field_properties['wrapperCssId'];
2076 - }
2077 - if ( !empty($field_properties['wrapperCssClass']) ) {
2078 - $hidden_props['class'] = $field_properties['wrapperCssClass'];
2079 - }
2080 - $element = new Element_Hidden($istance_data['istance_id'], $istance_data['default_value'], !empty($hidden_props) ? $hidden_props : null);
2976 + $element = new Element_Hidden($istance_data['istance_id'], $istance_data['default_value']);
2081 2977 break;
2082 2978 case 'checkbox':
2083 2979 $lab = $istance_data['label'];
2084 2980 if (!empty($istance_data['required'])) {
@@ -2087,17 +2983,18 @@
2087 2983 if ($allowed_values) {
2088 2984 reset($allowed_values);
2089 2985 $val = (string) key($allowed_values);
2090 2986 $defval = trim($istance_data['default_value']);
2091 - } elseif ($istance_data['default_value'] == '1') {
2987 + } else if ($istance_data['default_value'] == '1') {
2092 2988 $defval = $val = '1';
2093 2989 } else {
2094 2990 $val = empty($istance_data['default_value'])?'1':$istance_data['default_value'];
2095 2991 $defval = '';
2096 2992 }
2097 - $element = new AccuaForm_Element_Checkbox('', $istance_data['istance_id'], array($val => $lab), $field_properties+array('value' => $defval));
2993 + $element = new AccuaForm_Element_Checkbox('', $istance_data['istance_id'], array($val => $lab), array('value' => $defval));
2098 2994 break;
2099 2995 case 'select':
2996 + case 'post-select':
2100 2997 if (!isset($allowed_values[''])) {
2101 2998 $allowed_values = array('' => '') + $allowed_values;
2102 2999 }
2103 3000 $defval = trim($istance_data['default_value']);
@@ -2102,17 +2999,11 @@
2102 2999 }
2103 3000 $defval = trim($istance_data['default_value']);
2104 3001 $element = new AccuaForm_Element_Select($istance_data['label'], $istance_data['istance_id'], $allowed_values, $field_properties+array('value'=>$defval));
2105 3002 break;
2106 - case 'post-select':
2107 - $post_type = isset($istance_data['post_type']) ? $istance_data['post_type'] : 'page';
2108 - $extra_args = trim($istance_data['allowed_values']);
2109 - $defval = trim($istance_data['default_value']);
2110 - $element = new AccuaForm_Element_PostSelect($istance_data['label'], $istance_data['istance_id'], $post_type, $extra_args, $field_properties+array('value'=>$defval));
2111 - break;
2112 3003 case 'radio':
2113 3004 $defval = trim($istance_data['default_value']);
2114 - $element = new AccuaForm_Element_Radio($istance_data['label'], $istance_data['istance_id'], $allowed_values, $field_properties+array('value'=>$defval));
3005 + $element = new AccuaForm_Element_Radio($istance_data['label'], $istance_data['istance_id'], $allowed_values, array('value'=>$defval));
2115 3006 break;
2116 3007 case 'multiselect':
2117 3008 $defval = explode('|', $istance_data['default_value']);
2118 3009 foreach ($defval as $k => $v) {
@@ -2125,9 +3016,9 @@
2125 3016 $defval = explode('|', $istance_data['default_value']);
2126 3017 foreach ($defval as $k => $v) {
2127 3018 $defval[$k] = trim($v);
2128 3019 }
2129 - $element = new AccuaForm_Element_Checkbox($istance_data['label'], $istance_data['istance_id'], $allowed_values, $field_properties+array('value'=>$defval));
3020 + $element = new AccuaForm_Element_Checkbox($istance_data['label'], $istance_data['istance_id'], $allowed_values, array('value'=>$defval));
2130 3021 break;
2131 3022 case 'file':
2132 3023 $fdata = array();
2133 3024
@@ -2143,17 +3034,17 @@
2143 3034
2144 3035 $element = new AccuaForm_Element_File($istance_data['label'], $istance_data['istance_id'], $field_properties+$fdata);
2145 3036 break;
2146 3037 case 'html':
2147 - $element = new Element_HTML($istance_data['default_value'], $field_properties);
3038 + $element = new Element_HTML($istance_data['default_value']);
2148 3039 break;
2149 3040 case 'email':
2150 3041 case 'autoreply_email':
2151 - $email_props = $field_properties+array('value'=>$istance_data['default_value']);
2152 - if ($resolved_format_msg !== '') {
2153 - $email_props['custom_format_message'] = $resolved_format_msg;
2154 - }
2155 - $element = new AccuaForm_Element_Email($istance_data['label'], $istance_data['istance_id'], $email_props);
3042 + $element = new AccuaForm_Element_Email($istance_data['label'], $istance_data['istance_id'], $field_properties+array('value'=>$istance_data['default_value']));
3043 + $element->setValidation(new Validation_Email(
3044 + str_replace('%element%', $istance_data['label'], __("Attention: '%element%' must contain an email address.", 'contact-forms'))
3045 + ));
3046 + //"Errore: '{$istance_data['label']}' deve contenere un indirizzo email valido."
2156 3047 break;
2157 3048 case 'colorpicker':
2158 3049 $element = new AccuaForm_Element_ColorPicker($istance_data['label'], $istance_data['istance_id'], $field_properties+array('value'=>$istance_data['default_value']));
2159 3050 break;
@@ -2162,11 +3053,9 @@
2162 3053 $form->addElement(new AccuaForm_Element_FieldsetEnd());
2163 3054 } else {
2164 3055 $fieldset_open = true;
2165 3056 }
2166 - $fs_props = $field_properties;
2167 - $fs_props['fieldset_style'] = isset($istance_data['fieldset_style']) ? $istance_data['fieldset_style'] : 'border-off-title-off';
2168 - $element = new AccuaForm_Element_FieldsetBegin($istance_data['label'], $istance_data['istance_id'], $fs_props);
3057 + $element = new AccuaForm_Element_FieldsetBegin($istance_data['label'], $istance_data['istance_id']);
2169 3058 break;
2170 3059 case 'fieldset-end':
2171 3060 if ($fieldset_open) {
2172 3061 $element = new AccuaForm_Element_FieldsetEnd();
@@ -2174,19 +3063,9 @@
2174 3063 }
2175 3064 break;
2176 3065 case 'submit':
2177 3066 $add_submit = false;
2178 - $submit_extra = array('name' => $istance_data['istance_id'], 'value' => $istance_data['default_value']);
2179 - // Buttons render inside the shared .pfbc-buttons group without a
2180 - // per-element wrapper, so the editor's CSS Class / CSS ID are
2181 - // applied to the button element itself.
2182 - if (!empty($field_properties['wrapperCssClass'])) {
2183 - $submit_extra['class'] = $field_properties['wrapperCssClass'];
2184 - }
2185 - if (!empty($field_properties['wrapperCssId'])) {
2186 - $submit_extra['id'] = $field_properties['wrapperCssId'];
2187 - }
2188 - $element = new Element_Button($istance_data['label'], 'submit', $submit_properties+$submit_extra);
3067 + $element = new Element_Button($istance_data['label'], 'submit', $submit_properties+array('name' => $istance_data['istance_id'], 'value' => $istance_data['default_value']));
2189 3068 break;
2190 3069 case 'captcha':
2191 3070 $empty_captcha_data = array(
2192 3071 'recaptcha_force_v1' => '',
@@ -2193,16 +3072,9 @@
2193 3072 'recaptcha_public_key' => '',
2194 3073 'recaptcha_private_key' => '',
2195 3074 );
2196 3075 $captcha_data = get_option('accua_forms_default_captcha_field_data',array()) + $empty_captcha_data;
2197 - $captcha_properties = array(
2198 - "description" => "",
2199 - // Same accuaform_{fid} key format as v3: it identifies this
2200 - // form in the request-scoped spam-flag registry shared by the
2201 - // captcha validators (AccuaForm_Validation_CaptchaSpam).
2202 - 'captchaAction' => 'accuaform_' . preg_replace('/[^A-Za-z0-9_]/', '_', $fid),
2203 - 'spamAction' => accua_forms_captcha_spam_action($istance_data, 'captcha'),
2204 - );
3076 + $captcha_properties = array("description" => "");
2205 3077 $captcha_use_v1 = true;
2206 3078 if (($captcha_data['recaptcha_public_key'] !== '') && ($captcha_data['recaptcha_private_key'] !== '')) {
2207 3079 $captcha_properties['privateKey'] = $captcha_data['recaptcha_private_key'];
2208 3080 $captcha_properties['publicKey'] = $captcha_data['recaptcha_public_key'];
@@ -2210,60 +3082,17 @@
2210 3082 }
2211 3083 if ($captcha_use_v1) {
2212 3084 $element = new Element_HTML("\n\n<!-- ReCaptcha 1 is discontinued, please go to Contact Forms settings page and set reCaptcha v2 keys -->\n\n");
2213 3085 } else {
2214 - $element = new AccuaForm_Element_Captcha2 ($istance_data['label'], '', $field_properties+$captcha_properties);
3086 + $element = new AccuaForm_Element_Captcha2 ($istance_data['label'], '', $captcha_properties);
2215 3087 }
2216 3088 break;
2217 - case 'captcha_v3':
2218 - $captcha3_empty_data = array(
2219 - 'recaptcha_v3_public_key' => '',
2220 - 'recaptcha_v3_private_key' => '',
2221 - );
2222 - $captcha3_data = get_option('accua_forms_default_captcha_field_data',array()) + $captcha3_empty_data;
2223 - if (($captcha3_data['recaptcha_v3_public_key'] !== '') && ($captcha3_data['recaptcha_v3_private_key'] !== '')) {
2224 - $captcha3_properties = array(
2225 - 'description' => '',
2226 - 'privateKey' => $captcha3_data['recaptcha_v3_private_key'],
2227 - 'publicKey' => $captcha3_data['recaptcha_v3_public_key'],
2228 - // Distinct action per form, restricted to the characters Google allows
2229 - 'captchaAction' => 'accuaform_' . preg_replace('/[^A-Za-z0-9_]/', '_', $fid),
2230 - 'spamAction' => accua_forms_captcha_spam_action($istance_data, 'captcha_v3'),
2231 - 'scoreThreshold' => accua_forms_recaptcha3_score_threshold($istance_data),
2232 - );
2233 - $element = new AccuaForm_Element_Captcha3($istance_data['label'], '', $field_properties+$captcha3_properties);
2234 - } else {
2235 - $element = new Element_HTML("\n\n<!-- reCAPTCHA v3 keys are not configured, please go to Contact Forms settings page and set the reCAPTCHA v3 keys -->\n\n");
2236 - }
2237 - break;
2238 - case 'turnstile':
2239 - $element = new AccuaForm_Element_Turnstile($istance_data['label'], $istance_data['istance_id'], $field_properties+array("description" => ""));
2240 - break;
2241 - case 'cap':
2242 - $cap_empty_data = array(
2243 - 'cap_instance_url' => '',
2244 - 'cap_site_key' => '',
2245 - 'cap_secret_key' => '',
2246 - );
2247 - $cap_data = get_option('accua_forms_default_captcha_field_data',array()) + $cap_empty_data;
2248 - if (($cap_data['cap_instance_url'] !== '') && ($cap_data['cap_site_key'] !== '') && ($cap_data['cap_secret_key'] !== '')) {
2249 - $cap_properties = array(
2250 - 'description' => '',
2251 - 'instanceUrl' => $cap_data['cap_instance_url'],
2252 - 'siteKey' => $cap_data['cap_site_key'],
2253 - 'secretKey' => $cap_data['cap_secret_key'],
2254 - );
2255 - $element = new AccuaForm_Element_Cap($istance_data['label'], '', $field_properties+$cap_properties);
2256 - } else {
2257 - $element = new Element_HTML("\n\n<!-- Cap captcha is not configured, please go to Contact Forms settings page and set the Cap server URL, site key and secret key -->\n\n");
2258 - }
2259 - break;
2260 3089 case 'password':
2261 3090 $element = new Element_Password($istance_data['label'], $istance_data['istance_id'], $field_properties+array('value'=>$istance_data['default_value']));
2262 3091 break;
2263 3092 case 'password-and-confirm':
2264 3093 $id_2 = "___{$istance_data['istance_id']}___confirmpass";
2265 - $element = new Element_Password($istance_data['label'], $istance_data['istance_id'], $field_properties+array('value'=>$istance_data['default_value']));
3094 + $element = new Element_Password(__("Password", 'contact-forms'), $istance_data['istance_id'], $field_properties+array('value'=>$istance_data['default_value']));
2266 3095 $element_conf = new Element_Password(__("Confirm password", 'contact-forms'), $id_2, $field_properties+array('value'=>$istance_data['default_value']));
2267 3096 $element_conf_validator = new AccuaForm_Validation_Password();
2268 3097 $element_conf_validator->configure(array('otherPasswordFieldName'=>$istance_data['istance_id']));
2269 3098 $element_conf->setValidation($element_conf_validator);
@@ -2270,65 +3099,26 @@
2270 3099 break;
2271 3100 case 'date':
2272 3101 $element = new AccuaForm_Element_Date($istance_data['label'], $istance_data['istance_id'], $field_properties+array('value'=>$istance_data['default_value'], 'minDate'=>$istance_data['min_date'], 'maxDate'=>$istance_data['max_date']));
2273 3102 break;
2274 - case 'telephone':
2275 - $phone_country = isset($istance_data['country_code']) ? $istance_data['country_code'] : 'IT';
2276 - $phone_props = $field_properties+array('value'=>$istance_data['default_value'], 'country_code'=>$phone_country);
2277 - if ($resolved_format_msg !== '') {
2278 - $phone_props['custom_format_message'] = $resolved_format_msg;
2279 - }
2280 - $element = new AccuaForm_Element_Telephone($istance_data['label'], $istance_data['istance_id'], $phone_props);
2281 - break;
2282 3103 //case 'textfield':
2283 3104 default:
2284 - /**
2285 - * Filter to create a custom Element for an external field type.
2286 - *
2287 - * @param Element|null $element Null by default; return an Element to override.
2288 - * @param string $field_type The field type identifier.
2289 - * @param array $field_data The field definition from avail_fields.
2290 - * @param array $istance_data The field instance data (label, required, etc.).
2291 - * @param array $field_properties Common properties (description, shortDesc, etc.).
2292 - */
2293 - $element = apply_filters( 'accua_forms_render_field_element', null, $field_data['type'], $field_data, $istance_data, $field_properties );
2294 - if ( ! $element ) {
2295 - $element = new Element_Textbox($istance_data['label'], $istance_data['istance_id'], $field_properties+array('value'=>$istance_data['default_value']));
2296 - }
3105 + $element = new Element_Textbox($istance_data['label'], $istance_data['istance_id'], $field_properties+array('value'=>$istance_data['default_value']));
2297 3106 break;
2298 3107 }
2299 3108 if ($element) {
2300 3109 if (!empty($istance_data['required'])) {
2301 - if (!in_array($field_data['type'], array('captcha_v3', 'cap'), true)) {
2302 - // captcha_v3 and cap must not get this class: the client-side required check
2303 - // would inspect their hidden token input, which is empty until solved
2304 - $element->setClass('accuaforms-field-required');
2305 - }
2306 - if ($field_data['type'] === 'captcha' && empty($captcha_use_v1)) {
3110 + $element->setClass('accuaforms-field-required');
3111 + if($field_data['type'] == 'captcha' && empty($captcha_use_v1)) {
2307 3112 //nothing
2308 - } elseif ($field_data['type'] === 'captcha_v3') {
2309 - //nothing - v3 has its own validation set in the Element constructor
2310 - } elseif ($field_data['type'] === 'turnstile') {
2311 - //nothing - turnstile has its own validation set in the Element constructor
2312 - } elseif ($field_data['type'] === 'cap') {
2313 - //nothing - cap has its own validation set in the Element constructor
2314 - } elseif ($field_data['type'] === 'password-and-confirm') {
2315 - if ($resolved_required_msg !== '') {
2316 - $req_msg = str_replace(array('%s', '%element%'), $istance_data['label'], $resolved_required_msg);
2317 - } else {
2318 - /* translators: Password field required error */
2319 - $req_msg = __( 'Password is required', 'contact-forms' );
2320 - }
2321 - $element->setValidation(new Validation_Required($req_msg));
3113 + } else if($field_data['type'] == 'password-and-confirm') {
3114 + $element->setValidation(new Validation_Required(
3115 + str_replace('%element%', $istance_data['label'], __("Attention: Passwords are required fields.", 'contact-forms'))
3116 + ));
2322 3117 } else {
2323 - if ($resolved_required_msg !== '') {
2324 - $req_msg = str_replace(array('%s', '%element%'), $istance_data['label'], $resolved_required_msg);
2325 - } else {
2326 - /* translators: %element% is the field label, replaced with str_replace() */
2327 - // phpcs:ignore WordPress.WP.I18n.MissingTranslatorsComment -- Translators comment is above
2328 - $req_msg = str_replace('%element%', $istance_data['label'], __( '%element% is required', 'contact-forms' ));
2329 - }
2330 - $element->setValidation(new Validation_Required($req_msg));
3118 + $element->setValidation(new Validation_Required(
3119 + str_replace('%element%', $istance_data['label'], __("Attention: '%element%' is a required field.", 'contact-forms'))
3120 + ));
2331 3121 }
2332 3122 }
2333 3123
2334 3124 if ($elementName = $element->getName()) {
@@ -2349,18 +3139,9 @@
2349 3139 if ($fieldset_open) {
2350 3140 $form->addElement(new AccuaForm_Element_FieldsetEnd());
2351 3141 $fieldset_open = false;
2352 3142 }
2353 - /**
2354 - * Filter to suppress the automatically added submit button.
2355 - *
2356 - * Used by the Fields page live preview, which renders a single field
2357 - * with no use for a submit button. An explicit submit field in the
2358 - * form is unaffected.
2359 - *
2360 - * @param bool $suppress False by default.
2361 - */
2362 - if ($add_submit && !apply_filters('accua_forms_preview_suppress_auto_submit', false)) {
3143 + if ($add_submit) {
2363 3144 $form->addElement(new Element_Button(__('Submit', 'contact-forms'), 'submit', $submit_properties));
2364 3145 }
2365 3146 }
2366 3147
@@ -2380,9 +3161,9 @@
2380 3161 if (!empty($params['txt'])) {
2381 3162 $replace_map['__submitted_txt'] = implode("\n",$replace_map['__submitted_txt_raw']);
2382 3163 }
2383 3164 if (!empty($params['html'])) {
2384 - $replace_map['__submitted_html'] = implode("</td></tr>\n<tr>\n<td style='white-space:nowrap;vertical-align:top;padding:4px 10px 4px 0;'>",$replace_map['__submitted_html_raw']);
3165 + $replace_map['__submitted_html'] = implode('</td></tr><tr><td>',$replace_map['__submitted_html_raw']);
2385 3166 }
2386 3167 if (!empty($params['json'])) {
2387 3168 $replace_map['__submitted_json'] = _accua_forms_json_encode($replace_map['__submitted_json_raw']);
2388 3169 }
@@ -2403,240 +3184,8 @@
2403 3184 }
2404 3185 return $valid;
2405 3186 }
2406 3187
2407 -/**
2408 - * Sanitize a submissions-list column key.
2409 - *
2410 - * The case-preserving counterpart of sanitize_key(): column keys embed the
2411 - * field slug verbatim (`_field_{slug}`), and slugs are case-sensitive, so
2412 - * lowercasing would silently merge two fields whose slugs differ only in case.
2413 - * Allows the same character set the Fields page accepts for a slug.
2414 - *
2415 - * @since 2.3.0
2416 - * @param string $key Raw column key.
2417 - * @return string Sanitized column key.
2418 - */
2419 -function accua_forms_sanitize_column_key($key) {
2420 - return preg_replace('/[^A-Za-z0-9_\-]/', '', (string) $key);
2421 -}
2422 -
2423 -/**
2424 - * Allowed captcha spam actions (reCAPTCHA v2 and v3) and their form-editor
2425 - * labels.
2426 - *
2427 - * 'spam' accepts a submission that fails the captcha check silently (the
2428 - * visitor sees the normal success message, no emails are sent) and marks it
2429 - * with the Spam lead status; 'trash' and 'delete' are the other two silent
2430 - * modes. 'reject' blocks the submission with a visible error - the only
2431 - * behavior before 2.2.38, and the reCAPTCHA v2 default again since 2.3.0.
2432 - *
2433 - * @return array<string, string> action key => translated label.
2434 - */
2435 -function accua_forms_captcha_spam_action_options() {
2436 - return array(
2437 - 'spam' => __('Accept silently and mark as Spam', 'contact-forms'),
2438 - 'trash' => __('Accept silently and move to Trash', 'contact-forms'),
2439 - 'delete' => __('Accept silently and delete immediately', 'contact-forms'),
2440 - 'reject' => __('Reject with an error message', 'contact-forms'),
2441 - );
2442 -}
2443 -
2444 -/**
2445 - * The site-wide default spam action for a captcha type, from the settings page.
2446 - *
2447 - * reCAPTCHA v2 and v3 keep separate defaults because their checks fail for
2448 - * different reasons. A v3 failure is a low score computed invisibly, so
2449 - * absorbing it silently is the sensible default. A v2 failure most often means
2450 - * the visitor did not solve the checkbox they were shown - or took longer than
2451 - * the two minutes a token stays valid, or retried with a token Google had
2452 - * already consumed - and Google's guidance for that case is to surface the
2453 - * error and let them solve it again (the AJAX handler resets the widget, so a
2454 - * retry always carries a fresh token). Accepting those silently would file a
2455 - * real visitor's message as spam and send no notification, so v2 defaults to
2456 - * 'reject'.
2457 - *
2458 - * @since 2.3.0 The $type parameter, and the separate v2 default.
2459 - * @param string $type Field type: 'captcha' (reCAPTCHA v2) or 'captcha_v3'.
2460 - * @return string 'spam', 'trash', 'delete' or 'reject'.
2461 - */
2462 -function accua_forms_captcha_default_spam_action($type = 'captcha_v3') {
2463 - $captcha_data = get_option('accua_forms_default_captcha_field_data', array());
2464 - $is_v2 = ('captcha' === $type);
2465 - $option_key = $is_v2 ? 'captcha_spam_action_v2' : 'captcha_spam_action';
2466 - $fallback = $is_v2 ? 'reject' : 'spam';
2467 - $action = isset($captcha_data[$option_key]) ? $captcha_data[$option_key] : '';
2468 - return isset(accua_forms_captcha_spam_action_options()[$action]) ? $action : $fallback;
2469 -}
2470 -
2471 -/**
2472 - * Resolve the spam action configured on a captcha (v2) or captcha_v3 field
2473 - * instance: instance override, then the site-wide default for its type.
2474 - *
2475 - * @param array $istance_data The field instance data from the saved form.
2476 - * @param string $type Field type: 'captcha' (v2) or 'captcha_v3'.
2477 - * Defaults to the v3 resolution for backward
2478 - * compatibility with pre-2.3.0 callers.
2479 - * @return string 'spam', 'trash', 'delete' or 'reject'.
2480 - */
2481 -function accua_forms_captcha_spam_action($istance_data, $type = 'captcha_v3') {
2482 - $action = isset($istance_data['spam_action']) ? $istance_data['spam_action'] : '';
2483 - return isset(accua_forms_captcha_spam_action_options()[$action]) ? $action : accua_forms_captcha_default_spam_action($type);
2484 -}
2485 -
2486 -/**
2487 - * Find the spam action of the first captcha (v2) or captcha_v3 field of a
2488 - * form, if any.
2489 - *
2490 - * Note: when a submission was actually flagged, the handler follows the action
2491 - * recorded by the validator that failed (AccuaForm_Validation_CaptchaSpam), not
2492 - * this helper - a form can carry both a v2 and a v3 field with different
2493 - * actions. This remains for callers that need a form-level answer up front.
2494 - *
2495 - * @param array $form_data The saved form data (with 'fields').
2496 - * @return string The configured spam action, or the site-wide default if the
2497 - * form has no captcha field or no explicit setting.
2498 - */
2499 -function accua_forms_captcha_form_spam_action($form_data) {
2500 - if (!empty($form_data['fields']) && is_array($form_data['fields'])) {
2501 - $avail_fields = get_option('accua_forms_avail_fields', array());
2502 - foreach ($form_data['fields'] as $istance_data) {
2503 - if (isset($istance_data['ref'], $avail_fields[$istance_data['ref']]['type'])
2504 - && in_array($avail_fields[$istance_data['ref']]['type'], array('captcha', 'captcha_v3'), true)) {
2505 - return accua_forms_captcha_spam_action($istance_data, $avail_fields[$istance_data['ref']]['type']);
2506 - }
2507 - }
2508 - }
2509 - return accua_forms_captcha_default_spam_action();
2510 -}
2511 -
2512 -/**
2513 - * The site-wide default for the captcha "Hide field title" option.
2514 - *
2515 - * @return bool True when captcha titles are hidden by default (ships true).
2516 - */
2517 -function accua_forms_captcha_default_hide_title() {
2518 - $captcha_data = get_option('accua_forms_default_captcha_field_data', array());
2519 - if (!isset($captcha_data['captcha_hide_title'])) {
2520 - return true;
2521 - }
2522 - return !empty($captcha_data['captcha_hide_title']);
2523 -}
2524 -
2525 -/**
2526 - * Whether the title of a captcha field instance (captcha, captcha_v3 or cap)
2527 - * is hidden on the rendered form. Instance override, then the site-wide
2528 - * default (hidden unless the administrator changed it). The label stays in
2529 - * the markup visually hidden (screen-reader only), so error summary links and
2530 - * assistive tech keep working.
2531 - *
2532 - * @param array $istance_data The field instance data from the saved form.
2533 - * @return bool
2534 - */
2535 -function accua_forms_captcha_hide_title($istance_data) {
2536 - if (!isset($istance_data['hide_title'])) {
2537 - return accua_forms_captcha_default_hide_title();
2538 - }
2539 - return !empty($istance_data['hide_title']);
2540 -}
2541 -
2542 -/**
2543 - * Normalize a reCAPTCHA v3 score threshold to the 0.0 - 1.0 range Google
2544 - * uses, rounded to two decimals.
2545 - *
2546 - * @param mixed $value The raw value (string from a form field, float, ...).
2547 - * @param float $fallback Returned when $value is not numeric.
2548 - * @return float
2549 - */
2550 -function accua_forms_recaptcha3_clamp_score($value, $fallback = 0.5) {
2551 - if (!is_numeric($value)) {
2552 - return (float) $fallback;
2553 - }
2554 - $score = round((float) $value, 2);
2555 - if ($score < 0) {
2556 - return 0.0;
2557 - }
2558 - if ($score > 1) {
2559 - return 1.0;
2560 - }
2561 - return $score;
2562 -}
2563 -
2564 -/**
2565 - * The site-wide default minimum reCAPTCHA v3 score, from the settings page.
2566 - *
2567 - * @return float 0.0 - 1.0 (ships 0.5, the value Google suggests).
2568 - */
2569 -function accua_forms_recaptcha3_default_score_threshold() {
2570 - $captcha_data = get_option('accua_forms_default_captcha_field_data', array());
2571 - $stored = isset($captcha_data['recaptcha_v3_score_threshold']) ? $captcha_data['recaptcha_v3_score_threshold'] : null;
2572 - return accua_forms_recaptcha3_clamp_score($stored, 0.5);
2573 -}
2574 -
2575 -/**
2576 - * Resolve the minimum reCAPTCHA v3 score a submission must reach on a given
2577 - * field instance: instance override, then the site-wide default.
2578 - *
2579 - * The accua_forms_recaptcha3_score_threshold filter still runs last, inside
2580 - * the validator, and receives this value as its default.
2581 - *
2582 - * @param array $istance_data The field instance data from the saved form.
2583 - * @return float 0.0 - 1.0.
2584 - */
2585 -function accua_forms_recaptcha3_score_threshold($istance_data) {
2586 - $default = accua_forms_recaptcha3_default_score_threshold();
2587 - if (isset($istance_data['score_threshold']) && is_numeric($istance_data['score_threshold'])) {
2588 - return accua_forms_recaptcha3_clamp_score($istance_data['score_threshold'], $default);
2589 - }
2590 - return $default;
2591 -}
2592 -
2593 -/**
2594 - * Placement options for the floating reCAPTCHA v3 badge.
2595 - *
2596 - * Google allows hiding the badge only if the reCAPTCHA branding is shown
2597 - * elsewhere in the user flow - with 'hidden' the field prints the required
2598 - * notice text under the form itself.
2599 - *
2600 - * @return array<string, string> badge key => translated label.
2601 - */
2602 -function accua_forms_recaptcha3_badge_options() {
2603 - return array(
2604 - 'bottomright' => __('Bottom right', 'contact-forms'),
2605 - 'bottomleft' => __('Bottom left', 'contact-forms'),
2606 - 'hidden' => __('Hidden (the required reCAPTCHA notice is shown in the form instead)', 'contact-forms'),
2607 - );
2608 -}
2609 -
2610 -/**
2611 - * The configured reCAPTCHA v3 badge placement.
2612 - *
2613 - * Site-wide, not per field: the badge is a single floating element shared by
2614 - * every reCAPTCHA on the page.
2615 - *
2616 - * @return string 'bottomright' (default), 'bottomleft' or 'hidden'.
2617 - */
2618 -function accua_forms_recaptcha3_badge() {
2619 - $captcha_data = get_option('accua_forms_default_captcha_field_data', array());
2620 - $badge = isset($captcha_data['recaptcha_v3_badge']) ? $captcha_data['recaptcha_v3_badge'] : '';
2621 - return isset(accua_forms_recaptcha3_badge_options()[$badge]) ? $badge : 'bottomright';
2622 -}
2623 -
2624 -/** @deprecated 2.2.40 Use accua_forms_captcha_spam_action_options(). */
2625 -function accua_forms_recaptcha3_spam_action_options() {
2626 - return accua_forms_captcha_spam_action_options();
2627 -}
2628 -
2629 -/** @deprecated 2.2.40 Use accua_forms_captcha_spam_action(). */
2630 -function accua_forms_recaptcha3_spam_action($istance_data) {
2631 - return accua_forms_captcha_spam_action($istance_data);
2632 -}
2633 -
2634 -/** @deprecated 2.2.40 Use accua_forms_captcha_form_spam_action(). */
2635 -function accua_forms_recaptcha3_form_spam_action($form_data) {
2636 - return accua_forms_captcha_form_spam_action($form_data);
2637 -}
2638 -
2639 3188 function accua_forms_anonymize_ip($ip) {
2640 3189 $ip = (string) $ip;
2641 3190 $anonymize_ip_data = get_option('accua_forms_anonymize_ip_data',array());
2642 3191 if (empty($anonymize_ip_data['anonymize_ip_bytes'])) {
@@ -2675,90 +3224,30 @@
2675 3224 global $wpdb;
2676 3225
2677 3226 $time = time();
2678 3227
2679 - $captcha_flag_key = 'accuaform_' . preg_replace('/[^A-Za-z0-9_]/', '_', $fid);
2680 -
2681 - $stats_data = array(
3228 + $afs_stats = _accua_forms_json_encode(array(
2682 3229 'user_agent' => $form->stats['user_agent'],
2683 3230 'platform' => $form->stats['platform'],
2684 3231 'tentatives' => $form->stats['tentatives'],
2685 3232 'submit_method' => $form->stats['submit_method'],
2686 - );
3233 + ));
2687 3234
2688 - // reCAPTCHA v3 returned a score for this submission: keep it so the
2689 - // administrator can see what the form actually scores and tune the
2690 - // threshold accordingly. Recorded whether the check passed or not.
2691 - if (class_exists('AccuaForm_Validation_Captcha3', false)) {
2692 - $recaptcha3_score = AccuaForm_Validation_Captcha3::getScore($captcha_flag_key);
2693 - if ($recaptcha3_score !== null) {
2694 - $stats_data['recaptcha3_score'] = $recaptcha3_score;
2695 - }
2696 - }
2697 -
2698 - // Auto mark as spam: an email field carrying an address from the
2699 - // site-wide blocklist (settings page, Other settings tab). Recorded in
2700 - // the stats so the single submission page can say why it was classified;
2701 - // only the reason, never the address itself - afs_stats survives every
2702 - // read of the submission and is cleared on anonymization, so nothing
2703 - // personal belongs in it.
2704 - $has_blocklisted_email = accua_forms_submission_has_blocklisted_email($submittedData, $form_data);
2705 - if ($has_blocklisted_email) {
2706 - $stats_data['spam_reason'] = 'email_blocklist';
2707 - }
2708 -
2709 - $afs_stats = _accua_forms_json_encode($stats_data);
2710 -
2711 3235 $anonymized_ip = accua_forms_anonymize_ip($form->stats['ip']);
2712 3236
2713 - // Silent captcha classification: when the captcha (v2) or captcha_v3
2714 - // field of this form is configured with a silent spam action, a failed
2715 - // check passed validation but flagged the submission (see
2716 - // Validation/CaptchaSpam.php). The action comes from the validator that
2717 - // actually failed - since 2.3.0 v2 and v3 have different defaults, so a
2718 - // form carrying both must not follow whichever field happens to come
2719 - // first. A 'reject' action never flags, so a flagged key is always one
2720 - // of the three silent actions.
2721 - $captcha_spam_action = class_exists('AccuaForm_Validation_CaptchaSpam', false)
2722 - ? AccuaForm_Validation_CaptchaSpam::getSpamAction($captcha_flag_key)
2723 - : '';
2724 - $captcha_flagged = in_array($captcha_spam_action, array('spam', 'trash', 'delete'), true);
2725 - $spam_action = $captcha_spam_action;
2726 - $is_spam = $captcha_flagged;
2727 -
2728 - // The blocklist marks the submission as Spam whatever the captcha
2729 - // decided: a captcha judges how the form was filled in, not who filled
2730 - // it in. It never overrides a captcha classification that is already
2731 - // stricter (trash, delete) - only a submission the captcha let through
2732 - // is reclassified here.
2733 - if ($has_blocklisted_email && !$is_spam) {
2734 - $spam_action = 'spam';
2735 - $is_spam = true;
2736 - }
2737 -
2738 - $insert_data = array (
2739 - 'afs_form_id' => (string) $fid,
2740 - 'afs_post_id' => (string) $form->stats['pid'],
2741 - 'afs_ip' => $anonymized_ip,
2742 - 'afs_uri' => (string) $form->stats['uri'],
2743 - 'afs_referrer' => (string) $form->stats['referrer'],
2744 - 'afs_lang' => (string) $form->stats['lang'],
2745 - 'afs_created' => (string) gmdate('Y-m-d H:i:s', $form->stats['created']),
2746 - 'afs_submitted' => (string) gmdate('Y-m-d H:i:s', $time),
2747 - 'afs_stats' => (string) $afs_stats,
2748 - );
2749 - if ($is_spam) {
2750 - if ($spam_action === 'trash') {
2751 - $insert_data['afs_status'] = -1;
2752 - } elseif ($spam_action === 'spam') {
2753 - $insert_data['afs_lead_status'] = -1;
2754 - }
2755 - }
2756 -
2757 - // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery -- Form submission insert requires direct query
2758 3237 $insert_ret = $wpdb->insert(
2759 3238 $wpdb->prefix . 'accua_forms_submissions',
2760 - $insert_data
3239 + array (
3240 + 'afs_form_id' => (string) $fid,
3241 + 'afs_post_id' => (string) $form->stats['pid'],
3242 + 'afs_ip' => $anonymized_ip,
3243 + 'afs_uri' => (string) $form->stats['uri'],
3244 + 'afs_referrer' => (string) $form->stats['referrer'],
3245 + 'afs_lang' => (string) $form->stats['lang'],
3246 + 'afs_created' => (string) gmdate('Y-m-d H:i:s', $form->stats['created']),
3247 + 'afs_submitted' => (string) gmdate('Y-m-d H:i:s', $time),
3248 + 'afs_stats' => (string) $afs_stats,
3249 + )
2761 3250 );
2762 3251
2763 3252 if ($insert_ret) {
2764 3253 $submission_id = $form->stats['submission_id'] = $wpdb->insert_id;
@@ -2763,10 +3252,9 @@
2763 3252 if ($insert_ret) {
2764 3253 $submission_id = $form->stats['submission_id'] = $wpdb->insert_id;
2765 3254 } else {
2766 3255 $submission_id = $form->stats['submission_id'] = 0;
2767 - // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log -- Legitimate error logging for failed DB insert
2768 - error_log("[Contact Forms] unable to save submitted form data");
3256 + error_log("[WordPress Contact Forms] unable to save submitted form data");
2769 3257 }
2770 3258
2771 3259 $review_submission_url = admin_url('admin.php').'?page=accua_forms_submissions_list&sid='.$submission_id;
2772 3260
@@ -2781,15 +3269,15 @@
2781 3269 '__referrer' => $form->stats['referrer'],
2782 3270 '__lang' => $form->stats['lang'],
2783 3271 '__locale' => $form->stats['locale'],
2784 3272 '__created' => $form->stats['created'],
2785 - '__created_day' => wp_date('l j F Y', $form->stats['created']),
2786 - '__created_day_month_year' => wp_date('j F Y', $form->stats['created']),
2787 - '__created_hour' => wp_date('G:i', $form->stats['created']),
3273 + '__created_day' => date('l j F Y', $form->stats['created']),
3274 + '__created_day_month_year' => date('j F Y', $form->stats['created']),
3275 + '__created_hour' => date('G:i', $form->stats['created']),
2788 3276 '__submitted' => $time,
2789 - '__submitted_day' => wp_date('l j F Y', $time),
2790 - '__submitted_day_month_year' => wp_date('j F Y', $time),
2791 - '__submitted_hour' => wp_date('G:i', $time),
3277 + '__submitted_day' => date('l j F Y', $time),
3278 + '__submitted_day_month_year' => date('j F Y', $time),
3279 + '__submitted_hour' => date('G:i', $time),
2792 3280 '__confirmation_emails_message' => $form_data['confirmation_emails_message'],
2793 3281 '__user_agent' => $form->stats['user_agent'],
2794 3282 '__platform' => $form->stats['platform'],
2795 3283 '__tentatives' => $form->stats['tentatives'],
@@ -2823,9 +3311,9 @@
2823 3311 'name' => __('Fieldset begin', 'contact-forms'),
2824 3312 'type' => 'fieldset-begin',
2825 3313 'description' => '',
2826 3314 );
2827 - } elseif ($istance_data['ref'] == '__fieldset-end') {
3315 + } else if ($istance_data['ref'] == '__fieldset-end') {
2828 3316 $field_data = array(
2829 3317 'id' => '__fieldset-end',
2830 3318 'name' => __('Fieldset end', 'contact-forms'),
2831 3319 'type' => 'fieldset-end',
@@ -2911,10 +3399,10 @@
2911 3399 $urls = array();
2912 3400 foreach ($value as $val) {
2913 3401 if (isset($opts[$val])) {
2914 3402 $titles[] = $opts[$val];
2915 - $ids[] = $val;
2916 - $urls[] = get_permalink($val);
3403 + $ids[] = $value;
3404 + $urls[] = get_permalink($value);
2917 3405 $value2[] = $val . ': ' . trim(preg_replace('/[\s\n\r]+/', ' ', $opts[$val]));
2918 3406 }
2919 3407 }
2920 3408 $replace_map['__label_'.$istance_data['istance_id']] = $replace_map['__post_title_'.$istance_data['istance_id']] = implode("\n", $titles);
@@ -2929,26 +3417,15 @@
2929 3417 }
2930 3418 break;
2931 3419 case 'post-select':
2932 3420 if ($value !== '') {
2933 - $post = get_post(absint($value));
2934 - // The submitted ID must belong to the post type the field is
2935 - // configured for and have a status the field may expose (publish,
2936 - // plus private when explicitly configured); otherwise any post ID
2937 - // would be accepted.
2938 - $expected_post_type = isset($istance_data['post_type']) ? $istance_data['post_type'] : 'page';
2939 - $ps_allowed_statuses = array('publish');
2940 - $ps_element = $form->getElementByName($istance_id);
2941 - if ($ps_element instanceof AccuaForm_Element_PostSelect) {
2942 - $expected_post_type = $ps_element->getEffectivePostType();
2943 - $ps_allowed_statuses = $ps_element->getAllowedPostStatuses();
2944 - }
2945 - if ($post && in_array($post->post_status, $ps_allowed_statuses, true) && $post->post_type === $expected_post_type) {
2946 - $title = $post->post_title;
2947 - $replace_map['__label_'.$istance_data['istance_id']] = $replace_map['__post_title_'.$istance_data['istance_id']] = $title;
3421 + $el = $form->getElementByName($istance_id);
3422 + $opts = $el->getOptions();
3423 + if (isset($opts[$value])) {
3424 + $replace_map['__label_'.$istance_data['istance_id']] = $replace_map['__post_title_'.$istance_data['istance_id']] = $opts[$value];
2948 3425 $replace_map['__post_id_'.$istance_data['istance_id']] = $value;
2949 3426 $replace_map['__post_url_'.$istance_data['istance_id']] = get_permalink($value);
2950 - $value = $value . ': ' . trim(preg_replace('/[\s\n\r]+/', ' ', $title));
3427 + $value = $value . ': ' . trim(preg_replace('/[\s\n\r]+/', ' ', $opts[$value]));
2951 3428 } else {
2952 3429 $replace_map['__label_'.$istance_data['istance_id']] = $replace_map['__post_title_'.$istance_data['istance_id']] = '';
2953 3430 $replace_map['__post_id_'.$istance_data['istance_id']] = '';
2954 3431 $replace_map['__post_url_'.$istance_data['istance_id']] = '';
@@ -2970,10 +3447,9 @@
2970 3447 if ($value !== null && $value !== '' && $file) {
2971 3448 if ($form->renameFile($istance_id, "{$submission_id}_{$field_data['id']}_{$file['name']}")) {
2972 3449 $urlfield = rawurlencode($istance_data['istance_id']);
2973 3450 $urlfile = rawurlencode($value);
2974 - $token = accua_forms_generate_download_token($submission_id);
2975 - $file_download_url = admin_url('admin-ajax.php') . "?action=accua_forms_download_submitted_file&subid={$submission_id}&field={$urlfield}&file={$urlfile}&nonce=" . wp_create_nonce('accua_forms_download_nonce')."&token={$token}&_wpnonce=" . wp_create_nonce('download_file_' . $submission_id . '_' . $urlfield);
3451 + $file_download_url = admin_url('admin-ajax.php') . "?action=accua_forms_download_submitted_file&subid={$submission_id}&field={$urlfield}&file={$urlfile}";
2976 3452 }
2977 3453 }
2978 3454 $replace_map[$istance_data['istance_id']] = $value;
2979 3455 $replace_map['__download_'.$istance_data['istance_id']] = $file_download_url;
@@ -2992,20 +3468,12 @@
2992 3468 $replace_map[$istance_data['istance_id']] = $value;
2993 3469 }
2994 3470
2995 3471 switch ($field_data['type']) {
2996 - case 'fieldset-begin':
2997 - $fieldset_label = !empty($istance_data['label']) ? esc_html($istance_data['label']) : esc_html($istance_data['istance_id']);
2998 - $replace_map['__submitted_txt_raw'][$istance_data['istance_id']] = "\n--- {$istance_data['label']} ---";
2999 - $replace_map['__submitted_json_raw'][$istance_data['istance_id']] = $value;
3000 - $replace_map['__submitted_html_raw'][$istance_data['istance_id']] = "<strong style='font-size:14px;'>{$fieldset_label}</strong></td><td class='valori_submitted'>";
3001 - break;
3002 - case 'fieldset-end':
3003 - break;
3004 3472 case 'file':
3005 3473 $replace_map['__submitted_txt_raw'][$istance_data['istance_id']] = "{$istance_data['istance_id']}\t$value\t$file_download_url";
3006 3474 $replace_map['__submitted_json_raw'][$istance_data['istance_id']] = "$value\t$file_download_url";
3007 - $replace_map['__submitted_html_raw'][$istance_data['istance_id']] = "<strong>{$istance_data['istance_id']}</strong></td><td class='valori_submitted'><a href='".esc_url($file_download_url)."'>".esc_html($value)."</a>";
3475 + $replace_map['__submitted_html_raw'][$istance_data['istance_id']] = "<strong>{$istance_data['istance_id']}</strong></td><td class='valori_submitted'><a href='".htmlspecialchars($file_download_url,ENT_QUOTES)."'>".htmlspecialchars($value)."</a>";
3008 3476 break;
3009 3477
3010 3478 case 'email':
3011 3479 case 'autoreply_email':
@@ -3010,9 +3478,9 @@
3010 3478 case 'email':
3011 3479 case 'autoreply_email':
3012 3480 $replace_map['__submitted_txt_raw'][$istance_data['istance_id']] = "{$istance_data['istance_id']}\t$value";
3013 3481 $replace_map['__submitted_json_raw'][$istance_data['istance_id']] = $value;
3014 - $replace_map['__submitted_html_raw'][$istance_data['istance_id']] = "<strong>{$istance_data['istance_id']}</strong></td><td class='valori_submitted'><a href='mailto:".esc_attr($value)."'>".esc_html($value)."</a>";
3482 + $replace_map['__submitted_html_raw'][$istance_data['istance_id']] = "<strong>{$istance_data['istance_id']}</strong></td><td class='valori_submitted'><a href='mailto:".htmlspecialchars($value,ENT_QUOTES)."'>".htmlspecialchars($value)."</a>";
3015 3483 break;
3016 3484 case 'submit':
3017 3485 break;
3018 3486 case 'colorpicker':
@@ -3020,9 +3488,9 @@
3020 3488 $replace_map['__submitted_json_raw'][$istance_data['istance_id']] = $value;
3021 3489 if ($value === '') {
3022 3490 $value_html = '';
3023 3491 } else {
3024 - $value_esc = esc_attr($value);
3492 + $value_esc = htmlspecialchars($value, ENT_QUOTES);
3025 3493 $value_html = "<span style='color: $value_esc'><font color='$value_esc'>&#9608;</font></span> $value_esc";
3026 3494 }
3027 3495 $replace_map['__submitted_html_raw'][$istance_data['istance_id']] = "<strong>{$istance_data['istance_id']}</strong></td><td class='valori_submitted'>$value_html";
3028 3496 break;
@@ -3031,14 +3499,12 @@
3031 3499 break;
3032 3500 default:
3033 3501 $replace_map['__submitted_txt_raw'][$istance_data['istance_id']] = "{$istance_data['istance_id']}\t$value";
3034 3502 $replace_map['__submitted_json_raw'][$istance_data['istance_id']] = $value;
3035 - $replace_map['__submitted_html_raw'][$istance_data['istance_id']] = "<strong>{$istance_data['istance_id']}</strong></td><td class='valori_submitted'>".esc_html($value);
3036 - } if ($submission_id) {
3037 - // Ensure value is never NULL to prevent database errors
3038 - $safe_value = $value === null ? '' : $value;
3039 -
3040 - // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery -- Form field values insert requires direct query
3503 + $replace_map['__submitted_html_raw'][$istance_data['istance_id']] = "<strong>{$istance_data['istance_id']}</strong></td><td class='valori_submitted'>".htmlspecialchars($value);
3504 + }
3505 +
3506 + if ($submission_id) {
3041 3507 $wpdb->insert(
3042 3508 $wpdb->prefix . 'accua_forms_submissions_values',
3043 3509 array (
3044 3510 'afsv_sub_id' => $submission_id,
@@ -3043,9 +3509,9 @@
3043 3509 array (
3044 3510 'afsv_sub_id' => $submission_id,
3045 3511 'afsv_field_id' => $istance_data['istance_id'],
3046 3512 'afsv_type' => $type,
3047 - 'afsv_value' => $safe_value,
3513 + 'afsv_value' => $value,
3048 3514 ),
3049 3515 array('%d','%s','%s','%s')
3050 3516 );
3051 3517 }
@@ -3066,10 +3532,9 @@
3066 3532
3067 3533 //Newer filter, with an easier name
3068 3534 $replace_map = apply_filters('accua_forms_submission', $replace_map, $fid, $submittedData, $form, $_field_data, $_istance_data);
3069 3535
3070 - $submitted_html = "<table style='width:100%;border-collapse:collapse;'>\n<tr>\n<td style='white-space:nowrap;vertical-align:top;padding:4px 10px 4px 0;'>" . $replace_map['__submitted_html'] . "</td></tr></table>";
3071 - $submitted_html = str_replace("class='valori_submitted'", "class='valori_submitted' style='vertical-align:top;padding:4px 0;overflow-wrap:break-word;word-break:break-word;'", $submitted_html);
3536 + $submitted_html = '<table><tr><td>' . $replace_map['__submitted_html'] . '</td></tr></table>';
3072 3537 $confirmation_emails_message = $replace_map['__confirmation_emails_message'];
3073 3538 unset($replace_map['__submitted_html'], $replace_map['__confirmation_emails_message'], $replace_map['__submitted_txt_raw'], $replace_map['__submitted_html_raw'], $replace_map['__submitted_json_raw'], $replace_map['__autoreply_email_raw']);
3074 3539
3075 3540 $replace_map_html = array();
@@ -3074,9 +3539,9 @@
3074 3539
3075 3540 $replace_map_html = array();
3076 3541 foreach($replace_map as $key => $value) {
3077 3542 $replace_map_html["!$key"] = wp_kses($value, 'post');
3078 - $replace_map_html[$key] = esc_attr($value);
3543 + $replace_map_html[$key] = htmlspecialchars($value, ENT_QUOTES);
3079 3544 }
3080 3545
3081 3546 $replace_map['__submitted_html'] = $replace_map_html['__submitted_html'] = $replace_map_html['!__submitted_html'] = $submitted_html;
3082 3547 $replacer_html = new AccuaConditionalReplacer($replace_map_html);
@@ -3101,9 +3566,8 @@
3101 3566 }
3102 3567
3103 3568 $settings_html = array(
3104 3569 'success_message',
3105 - 'error_message',
3106 3570 'admin_emails_message',
3107 3571 );
3108 3572
3109 3573 foreach($settings_html as $i) {
@@ -3109,12 +3573,9 @@
3109 3573 foreach($settings_html as $i) {
3110 3574 $form_data_replaced[$i] = $replacer_html->doReplace($form_data[$i]);
3111 3575 }
3112 3576
3113 - // Track mail sending success for showing appropriate message
3114 - $mail_success = true;
3115 - $mail1 = true;
3116 - $mail2 = true;
3577 + AccuaForm::appendSubmittedMessages(wpautop($form_data_replaced['success_message']));
3117 3578
3118 3579 $header = array("Content-Type: text/html; charset=".get_option('blog_charset'));
3119 3580
3120 3581 $emails_from = trim($form_data_replaced['emails_from']);
@@ -3131,10 +3592,9 @@
3131 3592 if ($form_data_replaced['emails_bcc']) {
3132 3593 $header[] = 'Bcc: '.$form_data_replaced['emails_bcc'];
3133 3594 }
3134 3595
3135 - if (!$is_spam
3136 - && $form_data_replaced['admin_emails_to']
3596 + if ($form_data_replaced['admin_emails_to']
3137 3597 && $form_data_replaced['admin_emails_subject']) {
3138 3598 /*
3139 3599 $admin_tos = explode(',', strtr($form_data_replaced['admin_emails_to'], "\n\t\r;", ',,,,'));
3140 3600 foreach ($admin_tos as $admin_to) {
@@ -3140,98 +3600,17 @@
3140 3600 foreach ($admin_tos as $admin_to) {
3141 3601 $mail1 = wp_mail(trim($admin_to), $form_data_replaced['admin_emails_subject'], $form_data_replaced['admin_emails_message'], $header);
3142 3602 }
3143 3603 */
3144 - $mail1 = wp_mail($form_data_replaced['admin_emails_to'], $form_data_replaced['admin_emails_subject'],'<html><head></head><body style="background:#f9f8f8;font-size: 12px;font-family: &quot;Lucida Sans&quot;,&quot;Lucida Grande&quot;, Verdana, Arial, Sans-Serif;">'.wpautop($form_data_replaced['admin_emails_message']).'</body></html>', $header);
3145 - if (!$mail1) {
3146 - $mail_success = false;
3147 - }
3604 + $mail1 = wp_mail($form_data_replaced['admin_emails_to'], $form_data_replaced['admin_emails_subject'],'<html><head></head><body style="background:#f9f8f8;font-size: 12px;font-family: "Lucida Sans","Lucida Grande", Verdana, Arial, Sans-Serif;"">'.wpautop($form_data_replaced['admin_emails_message']).'</body></html>', $header);
3148 3605 }
3149 3606
3150 - if (!$is_spam
3151 - && $replace_map['__autoreply'] && $replace_map['__autoreply_email']
3607 + if ($replace_map['__autoreply'] && $replace_map['__autoreply_email']
3152 3608 && $form_data_replaced['confirmation_emails_subject']
3153 3609 && $confirmation_emails_message) {
3154 3610 $mail2 = wp_mail($replace_map['__autoreply_email'], $form_data_replaced['confirmation_emails_subject'], '<html><head></head><body>'.wpautop($confirmation_emails_message).'</body></html>', $header);
3155 - if (!$mail2) {
3156 - $mail_success = false;
3157 - }
3158 3611 }
3159 3612
3160 - // Determine which message to show based on mail success and user settings
3161 - if ($mail_success) {
3162 - // Show success message unless "Don't show any messages" is selected
3163 - if (empty($form_data['success_message_no_message'])) {
3164 - $message_content = trim($form_data_replaced['success_message']);
3165 - if ($message_content !== '') {
3166 - AccuaForm::appendSubmittedMessages(wpautop($message_content));
3167 - }
3168 - }
3169 - } else {
3170 - // Mail failed - show error message unless "Don't show any messages" is selected
3171 - if (empty($form_data['error_message_no_message'])) {
3172 - $error_content = trim($form_data_replaced['error_message']);
3173 - if ($error_content !== '') {
3174 - AccuaForm::appendSubmittedMessages(wpautop($error_content));
3175 - }
3176 - }
3177 - }
3178 -
3179 - if ($is_spam) {
3180 - if ($spam_action === 'delete' && $submission_id) {
3181 - // Remove the stored rows and any uploaded files; the visitor still
3182 - // saw the normal success message.
3183 - accua_forms_erase_submission($submission_id, 'delete');
3184 - $submission_id = $form->stats['submission_id'] = 0;
3185 - }
3186 -
3187 - // The two captcha hooks keep firing only for captcha classifications:
3188 - // they are documented as such, and a listener acting on them (feeding
3189 - // a captcha's own reporting API, tuning a score threshold) would be
3190 - // misled by a submission no captcha ever looked at. The blocklist has
3191 - // the type-agnostic accua_forms_spam_submission below instead.
3192 - if ($captcha_flagged) {
3193 - /**
3194 - * Fires when a submission was silently classified as spam by a
3195 - * captcha field (reCAPTCHA v2 or v3).
3196 - *
3197 - * @param int $submission_id The stored submission id (0 when the spam action is 'delete').
3198 - * @param string $spam_action The configured action: 'spam', 'trash' or 'delete'.
3199 - * @param string $fid The form id.
3200 - */
3201 - do_action('accua_forms_captcha_spam_submission', $submission_id, $captcha_spam_action, $fid);
3202 -
3203 - /**
3204 - * Deprecated alias of accua_forms_captcha_spam_submission, kept for
3205 - * backward compatibility. Since 2.2.40 it also fires for reCAPTCHA v2
3206 - * classifications, not only v3.
3207 - *
3208 - * @param int $submission_id The stored submission id (0 when the spam action is 'delete').
3209 - * @param string $spam_action The configured action: 'spam', 'trash' or 'delete'.
3210 - * @param string $fid The form id.
3211 - */
3212 - do_action('accua_forms_recaptcha3_spam_submission', $submission_id, $captcha_spam_action, $fid);
3213 - }
3214 -
3215 - /**
3216 - * Fires when a submission was silently classified as spam by any of
3217 - * the plugin's spam checks.
3218 - *
3219 - * @since 2.3.1
3220 - * @param int $submission_id The stored submission id (0 when the spam action is 'delete').
3221 - * @param string $spam_action The action applied: 'spam', 'trash' or 'delete'.
3222 - * @param string $fid The form id.
3223 - * @param string $spam_reason What classified it: 'captcha' or 'email_blocklist'.
3224 - */
3225 - do_action(
3226 - 'accua_forms_spam_submission',
3227 - $submission_id,
3228 - $spam_action,
3229 - $fid,
3230 - $captcha_flagged ? 'captcha' : 'email_blocklist'
3231 - );
3232 - }
3233 -
3234 3613 /*
3235 3614 echo "<!-- replace_map: "
3236 3615 , print_r($replace_map, true)
3237 3616 , "\nreplace_map: "
@@ -3259,16 +3638,11 @@
3259 3638 'file_format' => 'name',
3260 3639 );
3261 3640 $ret = array();
3262 3641 if ($options['extra']) {
3263 - // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- Submission data lookup requires direct query
3264 - $query1 = $wpdb->prepare(
3265 - "SELECT *
3642 + $query1 = "SELECT *
3266 3643 FROM `{$wpdb->prefix}accua_forms_submissions`
3267 - WHERE afs_id = %d",
3268 - $subid
3269 - );
3270 - // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- $query1 is prepared above, submission lookup requires direct query
3644 + WHERE afs_id = $subid";
3271 3645 $data = $wpdb->get_row($query1);
3272 3646 if (!empty($data)) {
3273 3647 $created = $data->afs_created;
3274 3648 $created[10] = 'T';
@@ -3290,10 +3664,8 @@
3290 3664 'user_agent' => '',
3291 3665 'platform' => '',
3292 3666 'tentatives' => '',
3293 3667 'submit_method' => '',
3294 - // Only present on submissions verified by a reCAPTCHA v3 field.
3295 - 'recaptcha3_score' => '',
3296 3668 );
3297 3669 $ret += array(
3298 3670 '__fid' => $data->afs_form_id,
3299 3671 '__subid' => $subid,
@@ -3303,31 +3675,25 @@
3303 3675 '__uri' => $data->afs_uri,
3304 3676 '__referrer' => $data->afs_referrer,
3305 3677 '__lang' => $data->afs_lang,
3306 3678 '__created' => $created,
3307 - '__created_day' => wp_date('l j F Y', $created),
3308 - '__created_hour' => wp_date('G:i', $created),
3679 + '__created_day' => date('l j F Y', $created),
3680 + '__created_hour' => date('G:i', $created),
3309 3681 '__submitted' => $submitted,
3310 - '__submitted_day' => wp_date('l j F Y', $submitted),
3311 - '__submitted_hour' => wp_date('G:i', $submitted),
3682 + '__submitted_day' => date('l j F Y', $submitted),
3683 + '__submitted_hour' => date('G:i', $submitted),
3312 3684 '__user_agent' => $stats['user_agent'],
3313 3685 '__platform' => $stats['platform'],
3314 3686 '__tentatives' => $stats['tentatives'],
3315 3687 '__submit_method' => $stats['submit_method'],
3316 - '__recaptcha3_score' => $stats['recaptcha3_score'],
3317 3688 );
3318 3689 }
3319 3690 }
3320 3691
3321 - // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- Submission values lookup requires direct query
3322 - $query2 = $wpdb->prepare(
3323 - "SELECT *
3324 - FROM `{$wpdb->prefix}accua_forms_submissions_values`
3325 - WHERE afsv_sub_id = %d",
3326 - $subid
3327 - );
3692 + $query2 = "SELECT *
3693 + FROM `{$wpdb->prefix}accua_forms_submissions_values`
3694 + WHERE afsv_sub_id = $subid";
3328 3695
3329 - // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- $query2 is prepared above, submission values lookup requires direct query
3330 3696 $data2 = $wpdb->get_results($query2, OBJECT);
3331 3697
3332 3698 foreach ($data2 as $row) {
3333 3699 switch ($row->afsv_type) {
@@ -3334,15 +3700,12 @@
3334 3700 case 'file' :
3335 3701 if ($options['file_format'] == 'url' || $options['file_format'] == 'link') {
3336 3702 $fieldid = rawurlencode($row->afsv_field_id);
3337 3703 $filename = rawurlencode($row->afsv_value);
3338 - $url = admin_url('admin-ajax.php') . "?action=accua_forms_download_submitted_file&subid={$row->afsv_sub_id}&field={$fieldid}&file={$filename}&nonce=" . wp_create_nonce('accua_forms_download_nonce') . "&_wpnonce=" . wp_create_nonce('download_file_' . $row->afsv_sub_id . '_' . $fieldid);
3339 - if(isset($options['token'])){
3340 - $url .= '&token='.$options['token'];
3341 - }
3704 + $url = admin_url('admin-ajax.php') . "?action=accua_forms_download_submitted_file&subid={$row->afsv_sub_id}&field={$fieldid}&file={$filename}";
3342 3705 if ($options['file_format'] == 'link'){
3343 - $url = esc_url($url);
3344 - $filename = esc_html($row->afsv_value);
3706 + $url = htmlspecialchars($url,ENT_QUOTES);
3707 + $filename = htmlspecialchars($row->afsv_value,ENT_QUOTES);
3345 3708 $fielddata = "<a href='{$url}' target='_blank'>{$filename}</a>";
3346 3709 } else {
3347 3710 $fielddata = $url;
3348 3711 }
@@ -3367,20 +3730,11 @@
3367 3730 $fid = $atts['fid'];
3368 3731 $form_data = _accua_forms_get_form_data($fid, false);
3369 3732
3370 3733 if (! $form_data) {
3371 - // In preview mode, allow unsaved (new) forms to render using draft + defaults
3372 - if (! apply_filters('accua_forms_use_draft_for_preview', false)) {
3373 - return '';
3374 - }
3375 - $default_form_data = get_option('accua_forms_default_form_data', array());
3376 - $empty_form_data = _accua_forms_get_form_data(false);
3377 - $form_data = array('_overrided' => array()) + $default_form_data + $empty_form_data;
3734 + return '';
3378 3735 }
3379 3736
3380 - // Note: Preview field order override is handled in accua_forms_form_generate()
3381 - // which applies the filter there for live preview
3382 -
3383 3737 $fid = '__accua-form__'.$fid;
3384 3738
3385 3739 $out = '';
3386 3740
@@ -3385,26 +3739,12 @@
3385 3739 $out = '';
3386 3740
3387 3741 if (AccuaForm::getSubmittedID() == $fid) {
3388 3742 /* return "<pre>Form submitted.\n\nData: " . print_r(AccuaForm::getSubmittedData(), true) . '</pre>'; */
3389 - // Get per-form messages (supports multiple forms on same page)
3390 - $messages = AccuaForm::getSubmittedMessages($fid);
3391 - if ($messages && trim($messages) !== '') {
3743 + $messages = AccuaForm::getSubmittedMessages();
3744 + if ($messages) {
3392 3745 $out .= '<div id="_response_messages_'.$fid.'" class="accua-form-messages">'.$messages.'</div>';
3393 3746 }
3394 -
3395 - // Non-AJAX fallback: set URL hash and scroll to result messages on page load.
3396 - // The anchor elements are only created by the AJAX JS block (which is not output for
3397 - // non-AJAX forms), so we scroll to the messages div by class instead.
3398 - $anchor_suffix = preg_replace('/[^a-zA-Z0-9]+/', '_', str_replace('__accua-form__', '', $fid));
3399 - $hash_type = AccuaForm::isValid() ? 'formSubmitSuccess' : 'formSubmitInvalid';
3400 - $anchor_full = esc_js($hash_type . '-' . $anchor_suffix);
3401 - $out .= '<script>document.addEventListener("DOMContentLoaded",function(){'
3402 - . 'if(history.replaceState)history.replaceState(null,"","#' . $anchor_full . '");'
3403 - . 'var m=document.querySelector(".accua-form-messages");'
3404 - . 'if(m)m.scrollIntoView({behavior:"smooth",block:"start"})'
3405 - . '});</script>';
3406 -
3407 3747 if (AccuaForm::isValid()) {
3408 3748 return $out;
3409 3749 }
3410 3750 $form = AccuaForm::getSubmittedForm();
@@ -3409,28 +3749,13 @@
3409 3749 }
3410 3750 $form = AccuaForm::getSubmittedForm();
3411 3751 } else {
3412 3752 $analytics_data = get_option('accua_forms_default_analytics_data',array());
3413 -
3414 - // Check for preview layout override (allows live preview of layout changes before save)
3415 - $layout = $form_data['layout'];
3416 - $preview_layout_override = apply_filters('accua_forms_preview_layout_override', '');
3417 - if ($preview_layout_override) {
3418 - $layout = $preview_layout_override;
3419 - }
3420 -
3421 - // If layout is empty (meaning "use default"), resolve to the global default layout
3422 - if (empty($layout)) {
3423 - $default_form_data = get_option('accua_forms_default_form_data', array());
3424 - $layout = !empty($default_form_data['layout']) ? $default_form_data['layout'] : 'sidebyside';
3425 - }
3426 -
3427 3753 $params = array(
3428 - 'layout' => $layout,
3754 + 'layout' => $form_data['layout'],
3429 3755 'title' => $form_data['title'],
3430 3756 'track_submit' => !empty($analytics_data['analytics_track_submit']),
3431 3757 'track_fields' => !empty($analytics_data['analytics_track_fields']),
3432 - 'gads_conversion_tracking_code' => $form_data['gads_conversion_tracking_code'],
3433 3758 );
3434 3759 $form = AccuaForm::create($fid, $params);
3435 3760 }
3436 3761
@@ -3436,10 +3761,9 @@
3436 3761
3437 3762 $out .= $form->render(true);
3438 3763
3439 3764 $doing_ajax = function_exists('wp_doing_ajax') ? wp_doing_ajax() : (defined( 'DOING_AJAX' ) && DOING_AJAX);
3440 - // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Read-only check for Yoast SEO compatibility, strips HTML for preview
3441 - if ($doing_ajax && isset($_REQUEST['action']) && ($_REQUEST['action'] === 'wpseo_filter_shortcodes')) {
3765 + if ($doing_ajax && ($_REQUEST['action'] === 'wpseo_filter_shortcodes')) {
3442 3766 $strip_regexp = '/(<iframe[^>]*>(.*?)<\/iframe>|<script[^>]*>(.*?)<\/script>|<input([^>]*)type="hidden"[^>]*>)/is';
3443 3767 $out = preg_replace($strip_regexp, '', $out);
3444 3768 }
3445 3769
@@ -3448,15 +3772,12 @@
3448 3772 }
3449 3773
3450 3774 function accua_forms_include($fid, $atts=array(), $content = '', $code = '') {
3451 3775 $atts['fid'] = $fid;
3452 - // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Shortcode handler manages its own escaping
3453 3776 echo accua_forms_shortcode_handler($atts, $content, $code);
3454 3777 }
3455 3778
3456 -// phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedFunctionFound -- Internal helper function, double underscore prefix indicates private
3457 3779 function __accua_forms_submissions_list_page(){
3458 - // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Read-only routing, actual actions have nonce checks
3459 3780 if(isset($_GET['sid'])) {
3460 3781 accua_forms_single_submission();
3461 3782 } else {
3462 3783 accua_forms_submissions_list_page();
@@ -3461,272 +3782,32 @@
3461 3782 } else {
3462 3783 accua_forms_submissions_list_page();
3463 3784 }
3464 3785 }
3465 -function accua_forms_submissions_list_page_load(){
3466 - // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Read-only routing for screen option registration
3467 - if(isset($_GET['sid'])) {
3468 - // Handle GET-based trash/restore actions here (before any output is sent)
3469 - require_once __DIR__ . '/admin/single-submission.php';
3470 - $sid = (int) $_GET['sid'];
3471 - // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Nonce verified below before processing
3472 - if ( $sid && isset( $_GET['action'] ) ) {
3473 - if ( $_GET['action'] === 'trash' ) {
3474 - check_admin_referer( 'del_sub_form_' . $sid );
3475 - accua_forms_trash_submission( $sid );
3476 - wp_safe_redirect( admin_url( 'admin.php?page=accua_forms_submissions_list&trashed=1' ) );
3477 - exit;
3478 - }
3479 - if ( $_GET['action'] === 'restore' ) {
3480 - check_admin_referer( 'restore_sub_form_' . $sid );
3481 - accua_forms_restore_submission( $sid );
3482 - wp_safe_redirect( admin_url( 'admin.php?page=accua_forms_submissions_list&restored=1' ) );
3483 - exit;
3484 - }
3485 - }
3486 - return;
3487 - }
3488 - add_screen_option('per_page', array(
3489 - 'default' => 100,
3490 - 'option' => 'accua_forms_submissions_per_page',
3491 - ));
3492 -
3493 - // Set default hidden columns for first-time users: hide the field columns
3494 - // not flagged "Show in essential columns" on the Fields page (plus the
3495 - // technical main columns).
3496 - add_filter( 'default_hidden_columns', function( $hidden ) {
3497 - $non_essential = [ 'form_id', 'pid', 'created', 'lead_status' ];
3498 - $avail_fields = get_option( 'accua_forms_avail_fields', [] );
3499 - foreach ( (array) $avail_fields as $slug => $field_data ) {
3500 - if ( empty( $field_data['essential_column'] ) ) {
3501 - $non_essential[] = '_field_' . $slug;
3502 - }
3503 - }
3504 - return array_unique( array_merge( $hidden, $non_essential ) );
3505 - } );
3506 -
3507 - $screen = get_current_screen();
3508 - $screen->add_help_tab( array(
3509 - 'id' => 'accua_forms_lead_statuses',
3510 - 'title' => __( 'Lead Statuses', 'contact-forms' ),
3511 - 'content' => '<p>' . accua_forms_get_lead_statuses_help() . '</p>',
3512 - ) );
3513 -
3514 - // Last, so that the export reads the hidden columns through the
3515 - // default_hidden_columns filter registered above.
3516 - accua_forms_submissions_maybe_bulk_export();
3517 -}
3518 -add_filter('set_screen_option_accua_forms_submissions_per_page', function($status, $option, $value) {
3519 - return (int) $value;
3520 -}, 10, 3);
3521 -/**
3522 - * Stream the ticked submissions as Excel, for the two export bulk actions.
3523 - *
3524 - * The other bulk actions are handled by the list table's process_bulk_action(),
3525 - * which the page calls from admin_head, where the response has already started;
3526 - * a download has to send its own headers, so this one runs on the load hook
3527 - * instead. The file itself is written by the same code the two buttons above
3528 - * the table use, over the same view: the rows are narrowed to the ticked ids,
3529 - * everything else (filters, search, sort order) comes from the request the
3530 - * form submitted, so the file is ordered like the screen it was asked for on.
3531 - *
3532 - * The current action is read the way WP_List_Table::current_action() reads it
3533 - * rather than by asking a list table, so nothing is built until an export is
3534 - * actually being asked for.
3535 - *
3536 - * @return void Dies with the file when rows were ticked. Returns otherwise,
3537 - * leaving process_bulk_action() to report the empty selection.
3538 - */
3539 -function accua_forms_submissions_maybe_bulk_export() {
3540 - // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Nonce verified below, once the action is known to be ours
3541 - if ( ! empty( $_GET['filter_action'] ) ) {
3542 - return;
3543 - }
3544 -
3545 - $action = '';
3546 - foreach ( array( 'action', 'action2' ) as $key ) {
3547 - // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Nonce verified below
3548 - if ( ! isset( $_GET[ $key ] ) || ! is_string( $_GET[ $key ] ) ) {
3549 - continue;
3550 - }
3551 - // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Nonce verified below
3552 - if ( '-1' !== $_GET[ $key ] ) {
3553 - // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Nonce verified below
3554 - $action = sanitize_key( wp_unslash( $_GET[ $key ] ) );
3555 - break;
3556 - }
3557 - }
3558 - if ( 'export_visible' !== $action && 'export_all' !== $action ) {
3559 - return;
3560 - }
3561 -
3562 - if ( ! current_user_can( 'manage_options' ) ) {
3563 - wp_die( esc_html__( 'You do not have sufficient permissions to access this page.', 'contact-forms' ), 403 );
3564 - }
3565 - check_admin_referer( 'bulk-submissions' );
3566 -
3567 - $ids = array();
3568 - // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized, WordPress.Security.ValidatedSanitizedInput.MissingUnslash -- Values are cast to int
3569 - if ( ! empty( $_GET['submission'] ) && is_array( $_GET['submission'] ) ) {
3570 - // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized, WordPress.Security.ValidatedSanitizedInput.MissingUnslash -- Value cast to int
3571 - foreach ( $_GET['submission'] as $i ) {
3572 - $i = (int) $i;
3573 - if ( $i > 0 ) {
3574 - $ids[ $i ] = $i;
3575 - }
3576 - }
3577 - }
3578 - if ( ! $ids ) {
3579 - // Nothing ticked: let the page render and say so.
3580 - return;
3581 - }
3582 -
3583 - require_once __DIR__ . '/admin/submissions-list-page.php';
3584 - $listTable = new Accua_Forms_Submissions_List_Table();
3585 - $listTable->export_xls = true;
3586 - // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Nonce verified above
3587 - $get = stripslashes_deep( $_GET );
3588 - $get['accua_export_ids'] = array_values( $ids );
3589 - $listTable->prepare_items( true, $get );
3590 -
3591 - $show_col = $listTable->export_column_keys( 'export_visible' === $action );
3592 -
3593 - header( 'Content-disposition: attachment; filename=downloads-report.xls' );
3594 - header( 'Content-type: application/vnd.ms-excel' );
3595 - accua_forms_submission_page_save_excel_general( $listTable, $show_col );
3596 - die( '' );
3597 -}
3598 3786 function accua_forms_submissions_list_page_head(){
3599 - // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Read-only routing, actual actions have nonce checks
3600 3787 if(isset($_GET['sid'])) {
3601 - require_once __DIR__ . '/admin/single-submission.php';
3788 + require_once('accua-forms-single-submission.php');
3602 3789 accua_forms_single_submission(true);
3603 3790 } else {
3604 - require_once __DIR__ . '/admin/submissions-list-page.php';
3791 + require_once('accua-forms-submissions-page.php');
3605 3792 accua_forms_submissions_list_page(true);
3606 3793 }
3607 3794
3608 3795 }
3609 3796
3610 -/* Generiamo token di sicurezza per poter accedere anche da anonimo - email */
3611 -function accua_forms_generate_download_token($subid) {
3612 - global $wpdb;
3613 - $token = wp_generate_password(32, false); // Token casuale di 32 caratteri
3614 -
3615 - // Controlla se esiste già un token per questo sub_id
3616 - // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- Token lookup requires direct query
3617 - $existing_token = $wpdb->get_var($wpdb->prepare(
3618 - "SELECT afsv_value FROM `{$wpdb->prefix}accua_forms_submissions_values` WHERE afsv_sub_id = %d AND afsv_field_id = '_accua_download_token'",
3619 - $subid
3620 - ));
3621 - if ($existing_token) {
3622 - return $existing_token;
3623 - } else{
3624 - // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery -- Token insert requires direct query
3625 - $wpdb->insert(
3626 - $wpdb->prefix . 'accua_forms_submissions_values',
3627 - [
3628 - 'afsv_sub_id' => $subid,
3629 - 'afsv_field_id' => '_accua_download_token',
3630 - 'afsv_type' => 'token',
3631 - 'afsv_value' => $token
3632 - ],
3633 - ['%d', '%s', '%s', '%s']
3634 - );
3635 - return $token;
3636 - }
3637 -}
3638 -
3639 -function accua_forms_check_download_token($subid, $get_token) {
3640 - global $wpdb;
3641 -
3642 - $subid = (int) $subid; // Cast to integer for security
3643 -
3644 - // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- Token verification requires direct query
3645 - $saved_token = $wpdb->get_var($wpdb->prepare(
3646 - "SELECT afsv_value FROM `{$wpdb->prefix}accua_forms_submissions_values` WHERE afsv_sub_id = %d AND afsv_field_id = '_accua_download_token'",
3647 - $subid
3648 - ));
3649 -
3650 - // Debug logging for token verification (comment out in production)
3651 - // error_log("Token check: Submission ID: $subid, Provided token: $get_token, Saved token: $saved_token");
3652 -
3653 - return isset($get_token) && $get_token === $saved_token;
3654 -}
3655 -
3656 -/**
3657 - * Gestisce il download di un file inviato tramite un modulo.
3658 - *
3659 - * Questa funzione viene eseguita tramite una richiesta AJAX e permette agli utenti di scaricare
3660 - * un file precedentemente caricato con un modulo. Controlla i parametri della richiesta per verificare
3661 - * la presenza di un file associato a un determinato ID di invio e campo del modulo.
3662 - *
3663 - * - Se il parametro "html" è presente, genera una pagina HTML con un link di reindirizzamento automatico.
3664 - * - Recupera le informazioni del file dal database per verificarne l'esistenza.
3665 - * - Se il file esiste e può essere letto, restituisce il contenuto con gli appropriati header HTTP.
3666 - * - Se il file non viene trovato, restituisce un errore 404.
3667 - *
3668 - * Sicurezza:
3669 - * - Nonce
3670 - * - Utilizza `stripslashes_deep` per sanificare i dati in ingresso.
3671 - * - Protegge il database utilizzando `wpdb->prepare` per prevenire SQL Injection.
3672 - * - Determina il tipo MIME del file per un download sicuro.
3673 - * - Aggiunto token di verifica per utenti
3674 - */
3675 -
3676 3797 add_action('wp_ajax_accua_forms_download_submitted_file', 'accua_forms_download_submitted_file');
3677 3798 add_action('wp_ajax_nopriv_accua_forms_download_submitted_file', 'accua_forms_download_submitted_file');
3678 3799 function accua_forms_download_submitted_file(){
3679 3800 $get = stripslashes_deep($_GET);
3680 - $token_valid = false;
3681 - $nonce_valid = false;
3682 - $subid = '';
3683 -
3684 - if(isset($get['subid'])){
3685 - $subid = rawurlencode($get['subid']);
3686 - }
3687 -
3688 - // First verify WordPress nonce for CSRF protection (for logged-in users)
3689 - if (isset($get['_wpnonce']) && wp_verify_nonce($get['_wpnonce'], 'download_file_' . $subid . '_' . $get['field'])) {
3690 - $nonce_valid = true;
3691 - }
3692 -
3693 - // For backward compatibility with older URL format that use 'nonce' instead of '_wpnonce'
3694 - if (!$nonce_valid && isset($get['nonce']) && check_ajax_referer('accua_forms_download_nonce', 'nonce', false)) {
3695 - $nonce_valid = true;
3696 - }
3697 -
3698 - // Check for token-based authentication (for email links and unauthenticated users)
3699 - if (isset($get['token']) && $subid != '') {
3700 - if (accua_forms_check_download_token($subid, $get['token']) == 1) {
3701 - $token_valid = true;
3702 - }
3703 - }
3704 -
3705 - // If both authentication methods fail, deny access
3706 - if (!$nonce_valid && !$token_valid) {
3707 - wp_die(esc_html__('Security check failed.', 'contact-forms'), 403);
3708 - }
3709 - // Additional permission check for admin users
3710 - if(!$token_valid && !$nonce_valid && $subid != ''){
3711 - // If neither token nor nonce is valid, check for logged-in admin permissions
3712 - if (!is_user_logged_in() || !current_user_can('manage_options')) {
3713 - wp_die(esc_html__('You do not have sufficient permissions to access this page.', 'contact-forms'));
3714 - }
3715 - }
3716 3801 if (isset($get['subid'],$get['field'],$get['file'])) {
3717 - if (!empty($get['html'])) { /* export xls*/
3802 + if (!empty($get['html'])) {
3718 3803 header("Content-type: text/html");
3719 3804 $subid = rawurlencode($get['subid']);
3720 3805 $fieldid = rawurlencode($get['field']);
3721 3806 $filename = rawurlencode($get['file']);
3722 - $url = admin_url('admin-ajax.php') . "?action=accua_forms_download_submitted_file&subid={$subid}&field={$fieldid}&file={$filename}&nonce=" . wp_create_nonce('accua_forms_download_nonce') . "&_wpnonce=" . wp_create_nonce('download_file_' . $subid . '_' . $fieldid);
3723 - if(isset($get['token'])){
3724 - $url .= '&token='.$get['token'];
3725 - }
3726 - $url = esc_url($url);
3727 - $filename = esc_html($get['file']);
3728 - // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- $filename and $url are pre-escaped above
3807 + $url = admin_url('admin-ajax.php') . "?action=accua_forms_download_submitted_file&subid={$subid}&field={$fieldid}&file={$filename}";
3808 + $url = htmlspecialchars($url,ENT_QUOTES);
3809 + $filename = htmlspecialchars($get['file'],ENT_QUOTES);
3729 3810 die("<html><head><title>{$filename}</title><meta http-equiv='refresh' content='0;URL={$url}'></head><body><a href='{$url}'>{$filename}</a></body></html>");
3730 3811 }
3731 3812 global $wpdb;
3732 3813 $subid = (int) $get['subid'];
@@ -3731,19 +3812,15 @@
3731 3812 global $wpdb;
3732 3813 $subid = (int) $get['subid'];
3733 3814 $field = $get['field'];
3734 3815 $file = $get['file'];
3735 - $query = $wpdb->prepare(
3736 - "SELECT *
3737 - FROM `{$wpdb->prefix}accua_forms_submissions_values`
3738 - WHERE afsv_sub_id = %d
3739 - AND afsv_field_id = %s
3740 - AND afsv_value = %s",
3741 - $subid,
3742 - $field,
3743 - $file
3744 - );
3745 - // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- $query is prepared above, file download verification requires direct query
3816 + $query = "SELECT *
3817 + FROM `{$wpdb->prefix}accua_forms_submissions_values`
3818 + WHERE afsv_sub_id = %d
3819 + AND afsv_field_id = %s
3820 + AND afsv_value = %s
3821 + ";
3822 + $query = $wpdb->prepare($query, $subid, $field, $file);
3746 3823 $subval = $wpdb->get_results($query, OBJECT);
3747 3824 if ($subval) {
3748 3825 $file_data = get_option('accua_forms_default_file_field_data',array()) + array('dest_path' => '');
3749 3826 $dest_path = _accua_forms_get_abs_dest_path($file_data['dest_path']);
@@ -3749,9 +3826,9 @@
3749 3826 $dest_path = _accua_forms_get_abs_dest_path($file_data['dest_path']);
3750 3827 $filename = "{$dest_path}/{$subid}_{$field}_{$file}";
3751 3828 if (is_file($filename) && is_readable($filename)){
3752 3829 if (function_exists('finfo_open')){
3753 - @ $finfo = finfo_open(FILEINFO_MIME_TYPE);
3830 + @ $finfo = finfo_open(FILEINFO_MIME);
3754 3831 if ($finfo) {
3755 3832 @ $filetype = finfo_file($finfo, $filename);
3756 3833 @ finfo_close($finfo);
3757 3834 }
@@ -3761,23 +3838,15 @@
3761 3838 }
3762 3839 if (empty($filetype)) {
3763 3840 $filetype = "application/octet-stream";
3764 3841 }
3765 - // Clean any output buffers to prevent stale content from being sent before the file
3766 - while (ob_get_level()) {
3767 - ob_end_clean();
3768 - }
3769 - // Remove all pre-set headers (admin-ajax.php sets Content-Type: text/html early)
3770 - header_remove();
3771 - nocache_headers();
3772 - header("Content-Type: $filetype");
3773 - header("Content-Length: ".filesize($filename));
3842 + header("Content-type: $filetype");
3843 + header("Content-length: ".filesize($filename));
3774 3844 if (empty($_GET['view'])) {
3775 - header("Content-Disposition: attachment; filename=\"$file\"");
3845 + header("Content-disposition: attachment; filename=\"$file\"");
3776 3846 }
3777 - // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_readfile -- WP_Filesystem not suitable for binary file streaming
3778 3847 readfile($filename);
3779 - exit;
3848 + die('');
3780 3849 }
3781 3850 }
3782 3851 }
3783 3852 header("HTTP/1.0 404 Not Found");
@@ -3792,117 +3861,22 @@
3792 3861 return new AccuaConditionalReplacer($map);
3793 3862 }
3794 3863
3795 3864
3796 -/**
3797 - * Prepare the emoji styles for a standalone document built outside the normal
3798 - * page lifecycle, such as the preview iframes.
3799 - *
3800 - * Those render by calling wp_print_styles() directly, which fires the
3801 - * 'wp_print_styles' action. WordPress 6.4 and later still keep the deprecated
3802 - * print_emoji_styles() on that action for backward compatibility, and retire it
3803 - * inside wp_enqueue_emoji_styles(), which runs on wp_enqueue_scripts or
3804 - * admin_enqueue_scripts. Neither of those runs in an AJAX request, so the
3805 - * deprecated printer was still attached and every preview refresh logged a
3806 - * deprecation notice. Doing here what a normal page load would have done keeps
3807 - * the emoji styles the preview had before and drops the notice.
3808 - *
3809 - * A no-op on WordPress 5.9 to 6.3, our declared minimum, where
3810 - * print_emoji_styles() is current and there is nothing to replace.
3811 - */
3812 -function accua_forms_prepare_emoji_styles_for_preview() {
3813 - if ( ! function_exists( 'wp_enqueue_emoji_styles' ) ) {
3814 - return;
3815 - }
3816 - remove_action( 'wp_print_styles', 'print_emoji_styles' );
3817 - wp_enqueue_emoji_styles();
3818 -}
3819 -
3820 3865 add_action('wp_ajax_accua_forms_preview', 'accua_forms_preview');
3821 3866 function accua_forms_preview() {
3822 3867 if (!current_user_can('manage_options')){
3823 3868 die ('');
3824 3869 }
3825 -
3826 - // Check nonce for CSRF protection
3827 - $nonce = isset( $_REQUEST['_wpnonce'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['_wpnonce'] ) ) : '';
3828 - if ( ! wp_verify_nonce( $nonce, 'accua_forms_preview' ) ) {
3829 - wp_die( esc_html__( 'Security check failed.', 'contact-forms' ), 403 );
3830 - }
3831 3870
3832 - // Enqueue form styles before printing them
3833 - accua_form_enqueue_scripts_and_styles();
3834 -
3835 - // Accept temporary layout override for live preview (before save)
3836 - // This allows real-time preview when user changes layout dropdown
3837 - $preview_layout = '';
3838 - if ( ! empty( $_REQUEST['preview_layout'] ) ) {
3839 - $layout_input = sanitize_text_field( wp_unslash( $_REQUEST['preview_layout'] ) );
3840 - $allowed_layouts = array( 'toplabel', 'sidebyside', 'inlinelabel' );
3841 - if ( in_array( $layout_input, $allowed_layouts, true ) ) {
3842 - $preview_layout = $layout_input;
3843 - } elseif ( 'default' === $layout_input ) {
3844 - // 'default' means use the global default layout
3845 - $default_form_data = get_option( 'accua_forms_default_form_data', array() );
3846 - $preview_layout = ! empty( $default_form_data['layout'] ) ? $default_form_data['layout'] : 'sidebyside';
3847 - }
3848 - }
3849 -
3850 - // Accept temporary field order for live preview (before save)
3851 - // This allows preview to show reordered fields without saving to database
3852 - $preview_order = null;
3853 - if ( ! empty( $_REQUEST['preview_order'] ) ) {
3854 - // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- JSON decoded and validated below
3855 - $order_json = wp_unslash( $_REQUEST['preview_order'] );
3856 - $preview_order = json_decode( $order_json, true );
3857 - if ( json_last_error() !== JSON_ERROR_NONE ) {
3858 - $preview_order = null;
3859 - }
3860 - }
3861 -
3862 - // Store the preview layout override in a filter so shortcode handler can use it
3863 - if ($preview_layout) {
3864 - add_filter('accua_forms_preview_layout_override', function() use ($preview_layout) {
3865 - return $preview_layout;
3866 - });
3867 - }
3868 -
3869 - // Store the preview order override in a filter so shortcode handler can use it
3870 - if ($preview_order) {
3871 - add_filter('accua_forms_preview_order_override', function() use ($preview_order) {
3872 - return $preview_order;
3873 - });
3874 - }
3875 -
3876 - // Signal that we're in admin preview mode - form generator should read from draft
3877 - add_filter('accua_forms_use_draft_for_preview', '__return_true');
3878 -
3879 3871 echo '<html><head>
3880 3872 <style>
3881 - *, *::before, *::after { box-sizing: border-box; }
3882 - body {
3883 - font-family: -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif;
3884 - margin: 0;
3885 - padding: 16px;
3886 - background: #fff;
3887 - font-size: 14px;
3888 - line-height: 1.5;
3889 - }
3873 + body {font-family: -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif;}
3890 3874 </style>';
3891 - accua_forms_prepare_emoji_styles_for_preview();
3892 3875 wp_print_styles();
3893 3876 wp_print_head_scripts();
3894 3877 echo '</head><body>';
3895 - $preview_fid = isset($_REQUEST['fid']) ? sanitize_text_field(wp_unslash($_REQUEST['fid'])) : '';
3896 -
3897 - // Check if the form has any fields - show placeholder if empty
3898 - $draft_data = _accua_forms_get_draft_data($preview_fid);
3899 - if (empty($draft_data['fields'])) {
3900 - echo '<p style="color:#50575e;text-align:center;margin-top:40px;">' . esc_html__('Add fields to the form to see the preview.', 'contact-forms') . '</p>';
3901 - } else {
3902 - // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Shortcode handler manages its own escaping
3903 - echo accua_forms_shortcode_handler(array('fid' => $preview_fid));
3904 - }
3878 + echo accua_forms_shortcode_handler(array('fid'=>$_REQUEST['fid']));
3905 3879 wp_print_footer_scripts();
3906 3880 echo '</body></html>';
3907 3881 die('');
3908 3882 }
@@ -3916,27 +3890,17 @@
3916 3890 header("HTTP/1.0 401 Access Denied");
3917 3891 //header("Status: 401 Access Denied");
3918 3892 die('You are not authorized to access this page.');
3919 3893 }
3920 -
3921 - // Check nonce for CSRF protection
3922 - if (!isset($_REQUEST['_wpnonce']) || !wp_verify_nonce(sanitize_text_field(wp_unslash($_REQUEST['_wpnonce'])), 'accua_forms_export_excel')) {
3923 - wp_die(esc_html__('Security check failed.', 'contact-forms'), 403);
3924 - }
3925 3894
3926 - require_once __DIR__ . '/admin/submissions-list-page.php';
3895 + require_once('accua-forms-submissions-page.php');
3927 3896 $listTable = new Accua_Forms_Submissions_List_Table();
3928 3897 $listTable->export_xls = true;
3929 3898 $listTable->prepare_items(true);
3930 - // Sanitize column selection input. Not sanitize_key(): it lowercases, and
3931 - // column keys carry the field slug verbatim (_field_{slug}), which is
3932 - // case-sensitive - two fields may differ only in case, so lowercasing here
3933 - // dropped one of them from the export.
3934 - $show_col_input = isset($_GET['accua_show_field']) ? sanitize_text_field(wp_unslash($_GET['accua_show_field'])) : '';
3935 - $show_col = array_map('accua_forms_sanitize_column_key', explode(',', $show_col_input));
3899 + $show_col = explode( ',', $_GET['accua_show_field']);
3936 3900 $show_col = array_diff($show_col, array('singlesub'));
3937 - header('Content-disposition: attachment; filename=downloads-report.xls');
3938 - header('Content-type: application/vnd.ms-excel');
3901 + header("Content-disposition: attachment; filename=downloads-report.xls");
3902 + header("Content-type: application/vnd.ms-excel");
3939 3903 accua_forms_submission_page_save_excel_general($listTable,$show_col);
3940 3904 die('');
3941 3905 }
3942 3906
@@ -3951,9 +3915,9 @@
3951 3915 ?><html xmlns:o="urn:schemas-microsoft-com:office:office"
3952 3916 xmlns:x="urn:schemas-microsoft-com:office:excel"
3953 3917 xmlns="http://www.w3.org/TR/REC-html40">
3954 3918 <head>
3955 - <meta http-equiv=Content-Type content="<?php echo esc_attr( $content_type ); ?>" />
3919 + <meta http-equiv=Content-Type content="<?php echo $content_type; ?>" />
3956 3920 <meta name=ProgId content=Excel.Sheet />
3957 3921 <style>
3958 3922 <!--
3959 3923 td {vertical-align:top;}
@@ -3992,9 +3956,9 @@
3992 3956 <?php
3993 3957 $cols = $listTable->get_columns();
3994 3958 foreach($cols as $col_key=>$col_value) {
3995 3959 if(in_array($col_key, $show_col)) { ?>
3996 - <td x:autofilter="all"><?php echo esc_html( $col_value ); ?></td>
3960 + <td x:autofilter="all"><?php echo $col_value; ?></td>
3997 3961 <?php }
3998 3962 } ?>
3999 3963 </tr>
4000 3964
@@ -4001,24 +3965,22 @@
4001 3965 <?php
4002 3966 $lead_statuses = accua_forms_get_lead_statuses();
4003 3967
4004 3968 foreach($listTable->items as $id_submission=>$single_submission) {
4005 - // phpcs:ignore Squiz.PHP.DiscouragedFunctions.Discouraged -- Required to prevent timeout during large exports
4006 3969 @ set_time_limit(10);
4007 3970 echo "<tr>";
4008 3971 foreach($cols as $col_key=>$col_value) {
4009 3972 if(in_array($col_key, $show_col)) {
4010 - echo '<td class="' . esc_attr($col_key) . '">';
3973 + echo "<td class='.$col_key.'>";
4011 3974 if ($col_key == 'lead_status') {
4012 3975 if (isset($lead_statuses[$single_submission['lead_status']])) {
4013 - echo esc_html($lead_statuses[$single_submission['lead_status']]);
3976 + echo htmlspecialchars($lead_statuses[$single_submission['lead_status']]);
4014 3977 }
4015 - } elseif(isset($single_submission[$col_key])) {
3978 + } else if(isset($single_submission[$col_key])) {
4016 3979 if ( method_exists( $listTable, 'column_' . $col_key ) ) {
4017 - // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- List table column methods handle their own escaping
4018 3980 echo call_user_func( array( &$listTable, 'column_' . $col_key ), $single_submission );
4019 - } else {
4020 - // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- List table column_default handles escaping
3981 + }
3982 + else {
4021 3983 echo $listTable->column_default( $single_submission, $col_key );
4022 3984 }
4023 3985 }
4024 3986 echo "</td>";
@@ -4038,36 +4000,34 @@
4038 4000 function accua_forms_print_tokens() {
4039 4001 $avail_fields = get_option('accua_forms_avail_fields', array());
4040 4002 $tokens = '';
4041 4003 foreach($avail_fields as $key=>$value) {
4042 - $field_name = $value['name'] ?? $value['label'] ?? $key;
4043 - $tokens .= $field_name . ": {" . $key . "}\n";
4004 + $tokens .= $value['name'] . ": {" . $key . "}\n";
4044 4005 switch ($value['type']) {
4045 4006 case 'file':
4046 - $tokens .= $field_name . " (download link): {__download_" . $key . "}\n";
4007 + $tokens .= $value['name'] . " (download link): {__download_" . $key . "}\n";
4047 4008 break;
4048 4009 case 'multiselect':
4049 4010 case 'multicheckbox':
4050 - $tokens .= $field_name . " (labels): {__label_" . $key . "}\n";
4011 + $tokens .= $value['name'] . " (labels): {__label_" . $key . "}\n";
4051 4012 break;
4052 4013 case 'select':
4053 4014 case 'radio':
4054 - $tokens .= $field_name . " (label): {__label_" . $key . "}\n";
4015 + $tokens .= $value['name'] . " (label): {__label_" . $key . "}\n";
4055 4016 break;
4056 4017 case 'post-multicheckbox':
4057 - $tokens .= $field_name . " (posts titles): {__label_" . $key . "}\n";
4058 - $tokens .= $field_name . " (posts ids): {__post_id_" . $key . "}\n";
4059 - $tokens .= $field_name . " (posts urls): {__post_url_" . $key . "}\n";
4018 + $tokens .= $value['name'] . " (posts titles): {__label_" . $key . "}\n";
4019 + $tokens .= $value['name'] . " (posts ids): {__post_id_" . $key . "}\n";
4020 + $tokens .= $value['name'] . " (posts urls): {__post_url_" . $key . "}\n";
4060 4021 break;
4061 4022 case 'post-select':
4062 - $tokens .= $field_name . " (post title): {__label_" . $key . "}\n";
4063 - $tokens .= $field_name . " (post id): {__post_id_" . $key . "}\n";
4064 - $tokens .= $field_name . " (post url): {__post_url_" . $key . "}\n";
4023 + $tokens .= $value['name'] . " (post title): {__label_" . $key . "}\n";
4024 + $tokens .= $value['name'] . " (post id): {__post_id_" . $key . "}\n";
4025 + $tokens .= $value['name'] . " (post url): {__post_url_" . $key . "}\n";
4065 4026 break;
4066 4027 }
4067 4028 }
4068 4029
4069 - // phpcs:disable PluginCheck.CodeAnalysis.Heredoc.NotAllowed, WordPress.Security.EscapeOutput.HeredocOutputNotEscaped -- Heredoc for tokens help HTML
4070 4030 echo <<<EOT
4071 4031 <div class="accua_forms_token_list">
4072 4032 <h2>Tokens</h2>
4073 4033 <em>In HTML text, use {!token_name} to insert unfiltered token value</em>
@@ -4096,9 +4056,8 @@
4096 4056 {__user_agent}
4097 4057 {__platform}
4098 4058 {__tentatives}
4099 4059 {__submit_method}
4100 -{__recaptcha3_score}
4101 4060 {__submitted_txt}
4102 4061 {__submitted_html}
4103 4062 {__submitted_json}
4104 4063 {__autoreply}
@@ -4106,432 +4065,356 @@
4106 4065 {__confirmation_emails_message}
4107 4066 {__review_submission_url}</pre>
4108 4067 </div>
4109 4068 EOT;
4110 - // phpcs:enable PluginCheck.CodeAnalysis.Heredoc.NotAllowed, WordPress.Security.EscapeOutput.HeredocOutputNotEscaped
4111 4069 do_action('accua_forms_print_tokens');
4112 4070 }
4113 4071
4114 -/**
4115 - * Get posts/pages for post-select fields using get_posts() for WPML compatibility.
4116 - *
4117 - * Uses WordPress get_posts() instead of direct SQL to ensure WPML and other
4118 - * language plugins can filter results to current language automatically.
4119 - *
4120 - * Performance considerations:
4121 - * - Results are cached using transients (5 minute TTL) to reduce database queries
4122 - * - meta_key/meta_value queries are necessary for filtering by custom fields
4123 - * - post__not_in is used only when exclude is explicitly requested by admin
4124 - * - Default limit of 500 posts prevents runaway queries
4125 - *
4126 - * Hierarchy handling:
4127 - * - child_of returns all descendants of the given post; exclude_tree removes a
4128 - * post and all its descendants. Both are resolved to explicit ID lists via
4129 - * accua_forms_get_post_descendant_ids() before querying, so they remain
4130 - * correct with pagination and search.
4131 - * - hierarchical only affects ordering (parents before children) and only when
4132 - * the result set is complete and title-sorted; it never drops posts whose
4133 - * parent is unavailable (e.g. published children of draft parents).
4134 - *
4135 - * @since 2.0.0-beta.29
4136 - * @param string|array $args Query arguments (backward compatible with old function).
4137 - * @return array Array of post objects.
4138 - */
4139 4072 function accua_get_pages($args = '') {
4140 - // phpcs:disable WordPressVIPMinimum.Performance.WPQueryParams.PostNotIn_exclude, WordPress.DB.SlowDBQuery.slow_db_query_meta_key, WordPress.DB.SlowDBQuery.slow_db_query_meta_value -- These are function parameter defaults, not actual query execution.
4073 + global $wpdb;
4074 +
4141 4075 $defaults = array(
4142 - 'child_of' => 0,
4143 - 'sort_order' => 'ASC',
4144 - 'sort_column' => 'post_title',
4145 - 'hierarchical' => 1,
4146 - 'exclude' => array(),
4147 - 'include' => array(),
4148 - 'meta_key' => '',
4149 - 'meta_value' => '',
4150 - 'meta_value_lt' => '',
4151 - 'meta_value_gt' => '',
4152 - 'meta_value_le' => '',
4153 - 'meta_value_ge' => '',
4154 - 'meta_value_like' => '',
4155 - 'meta_value_format' => 'string',
4156 - 'authors' => '',
4157 - 'parent' => -1,
4158 - 'exclude_tree' => '',
4159 - 'number' => 500, // Default limit for performance
4160 - 'offset' => 0,
4161 - 'post_type' => 'page',
4162 - 'post_status' => 'publish',
4163 - 'suppress_filters' => false, // IMPORTANT: Allow WPML to filter by language
4164 - 's' => '', // Search term (new parameter for AJAX search)
4076 + 'child_of' => 0,
4077 + 'sort_order' => 'ASC',
4078 + 'sort_column' => 'post_title',
4079 + 'hierarchical' => 1,
4080 + 'exclude' => array(),
4081 + 'include' => array(),
4082 + 'meta_key' => '',
4083 + 'meta_value' => '',
4084 + 'meta_value_lt' => '',
4085 + 'meta_value_gt' => '',
4086 + 'meta_value_le' => '',
4087 + 'meta_value_ge' => '',
4088 + 'meta_value_like' => '',
4089 + 'meta_value_format' => 'string',
4090 + 'authors' => '',
4091 + 'parent' => -1,
4092 + 'exclude_tree' => '',
4093 + 'number' => '',
4094 + 'offset' => 0,
4095 + 'post_type' => 'page',
4096 + 'post_status' => 'publish',
4165 4097 );
4166 - // phpcs:enable WordPressVIPMinimum.Performance.WPQueryParams.PostNotIn_exclude, WordPress.DB.SlowDBQuery.slow_db_query_meta_key, WordPress.DB.SlowDBQuery.slow_db_query_meta_value
4167 4098
4168 - $r = wp_parse_args($args, $defaults);
4099 + $r = wp_parse_args( $args, $defaults );
4100 + $child_of = (int) $r['child_of'];
4101 + $sort_order = $r['sort_order'];
4102 + $sort_column = $r['sort_column'];
4103 + $hierarchical = $r['hierarchical'];
4104 + $exclude = $r['exclude'];
4105 + $include = $r['include'];
4106 + $meta_key = $r['meta_key'];
4107 + $meta_value = $r['meta_value'];
4108 + $meta_value_lt = $r['meta_value_lt'];
4109 + $meta_value_gt = $r['meta_value_gt'];
4110 + $meta_value_le = $r['meta_value_le'];
4111 + $meta_value_ge = $r['meta_value_ge'];
4112 + $meta_value_like = $r['meta_value_like'];
4113 + $meta_value_format = $r['meta_value_format'];
4114 + $authors = $r['authors'];
4115 + $parent = $r['parent'];
4116 + $exclude_tree = $r['exclude_tree'];
4117 + $number = (int) $r['number'];
4118 + $offset = (int) $r['offset'];
4119 + $post_type = $r['post_type'];
4120 + $post_status = $r['post_status'];
4169 4121
4170 - // Generate cache key based on arguments and current language
4171 - $cache_key_data = $r;
4172 - // Add current language to cache key for WPML/Polylang compatibility
4173 - if (function_exists('pll_current_language')) {
4174 - $cache_key_data['_lang'] = pll_current_language();
4175 - } elseif (defined('ICL_LANGUAGE_CODE')) {
4176 - $cache_key_data['_lang'] = ICL_LANGUAGE_CODE;
4177 - }
4178 - $cache_key = 'accua_pages_' . md5(wp_json_encode($cache_key_data));
4122 + /*
4123 + // Make sure the post type is hierarchical
4124 + $hierarchical_post_types = get_post_types( array( 'hierarchical' => true ) );
4125 + if ( !in_array( $post_type, $hierarchical_post_types ) )
4126 + return false;
4127 + */
4179 4128
4180 - // Check transient cache first (skip for search queries and random ordering)
4181 - $use_cache = empty($r['s']) && $r['sort_column'] !== 'rand';
4182 - if ($use_cache) {
4183 - $cached = get_transient($cache_key);
4184 - if ($cached !== false) {
4185 - return $cached;
4186 - }
4187 - }
4129 + // Make sure we have a valid post type
4130 + if ( !is_array( $post_type ) )
4131 + $post_type = explode( ',', $post_type );
4132 + if ( array_diff( $post_type, get_post_types() ) )
4133 + return false;
4188 4134
4189 - // Validate post type
4190 - $post_type = $r['post_type'];
4191 - if (!is_array($post_type)) {
4192 - $post_type = array_map('trim', explode(',', $post_type));
4193 - }
4194 - $valid_post_types = get_post_types();
4195 - $post_type = array_filter($post_type, function($pt) use ($valid_post_types) {
4196 - return in_array($pt, $valid_post_types, true);
4197 - });
4198 - if (empty($post_type)) {
4199 - return array();
4200 - }
4135 + // Make sure we have a valid post status
4136 + if ( !is_array( $post_status ) )
4137 + $post_status = explode( ',', $post_status );
4138 + if ( array_diff( $post_status, get_post_stati() ) )
4139 + return false;
4201 4140
4202 - // Validate post status
4203 - $post_status = $r['post_status'];
4204 - if (!is_array($post_status)) {
4205 - $post_status = array_map('trim', explode(',', $post_status));
4141 + /*
4142 + $cache = array();
4143 + $key = md5( serialize( compact(array_keys($defaults)) ) );
4144 + if ( $cache = wp_cache_get( 'get_pages', 'posts' ) ) {
4145 + if ( is_array($cache) && isset( $cache[ $key ] ) ) {
4146 + $pages = apply_filters('get_pages', $cache[ $key ], $r );
4147 + return $pages;
4206 4148 }
4207 - $valid_statuses = get_post_stati();
4208 - $post_status = array_filter($post_status, function($ps) use ($valid_statuses) {
4209 - return in_array($ps, $valid_statuses, true);
4210 - });
4211 - if (empty($post_status)) {
4212 - $post_status = array('publish');
4213 4149 }
4214 4150
4215 - // Map sort_column to orderby
4216 - $orderby_map = array(
4217 - 'post_title' => 'title',
4218 - 'title' => 'title',
4219 - 'post_date' => 'date',
4220 - 'date' => 'date',
4221 - 'post_modified' => 'modified',
4222 - 'modified' => 'modified',
4223 - 'menu_order' => 'menu_order',
4224 - 'post_name' => 'name',
4225 - 'name' => 'name',
4226 - 'post_parent' => 'parent',
4227 - 'parent' => 'parent',
4228 - 'ID' => 'ID',
4229 - 'rand' => 'rand',
4230 - 'comment_count' => 'comment_count',
4231 - 'post_author' => 'author',
4232 - 'author' => 'author',
4233 - );
4234 - $sort_column = $r['sort_column'];
4235 - $orderby = isset($orderby_map[$sort_column]) ? $orderby_map[$sort_column] : 'title';
4151 + if ( !is_array($cache) )
4152 + $cache = array();
4153 + */
4236 4154
4237 - // Build get_posts arguments
4238 - $query_args = array(
4239 - 'post_type' => $post_type,
4240 - 'post_status' => $post_status,
4241 - 'orderby' => $orderby,
4242 - 'order' => strtoupper($r['sort_order']) === 'DESC' ? 'DESC' : 'ASC',
4243 - 'posts_per_page' => !empty($r['number']) ? (int) $r['number'] : 500,
4244 - 'offset' => (int) $r['offset'],
4245 - 'suppress_filters' => (bool) $r['suppress_filters'],
4246 - );
4247 -
4248 - // Search term
4249 - if (!empty($r['s'])) {
4250 - $query_args['s'] = sanitize_text_field($r['s']);
4155 + $inclusions = '';
4156 + if ( !empty($include) ) {
4157 + $child_of = 0; //ignore child_of, parent, exclude, meta_key, and meta_value params if using include
4158 + $parent = -1;
4159 + $exclude = '';
4160 + $meta_key = '';
4161 + $meta_value = '';
4162 + $meta_value_lt = '';
4163 + $meta_value_gt = '';
4164 + $meta_value_le = '';
4165 + $meta_value_ge = '';
4166 + $meta_value_like = '';
4167 + $hierarchical = false;
4168 + $incpages = wp_parse_id_list( $include );
4169 + if ( ! empty( $incpages ) ) {
4170 + foreach ( $incpages as $incpage ) {
4171 + if (empty($inclusions))
4172 + $inclusions = $wpdb->prepare(' AND ( ID = %d ', $incpage);
4173 + else
4174 + $inclusions .= $wpdb->prepare(' OR ID = %d ', $incpage);
4175 + }
4176 + }
4251 4177 }
4178 + if (!empty($inclusions))
4179 + $inclusions .= ')';
4252 4180
4253 - // Include specific posts (overrides other filters)
4254 - if (!empty($r['include'])) {
4255 - $include = wp_parse_id_list($r['include']);
4256 - if (!empty($include)) {
4257 - $query_args['post__in'] = $include;
4258 - $query_args['orderby'] = 'post__in'; // Preserve include order
4181 + $exclusions = '';
4182 + if ( !empty($exclude) ) {
4183 + $expages = wp_parse_id_list( $exclude );
4184 + if ( ! empty( $expages ) ) {
4185 + foreach ( $expages as $expage ) {
4186 + if (empty($exclusions))
4187 + $exclusions = $wpdb->prepare(' AND ( ID <> %d ', $expage);
4188 + else
4189 + $exclusions .= $wpdb->prepare(' AND ID <> %d ', $expage);
4190 + }
4259 4191 }
4260 - } else {
4261 - // Exclude posts - only used when admin explicitly configures exclusions.
4262 - // exclude_tree also removes all descendants of the given post, resolved
4263 - // against the full tree so it works with pagination and search.
4264 - $exclude_ids = array();
4265 - if (!empty($r['exclude'])) {
4266 - $exclude_ids = wp_parse_id_list($r['exclude']);
4267 - }
4268 - if (!empty($r['exclude_tree'])) {
4269 - $exclude_tree = (int) $r['exclude_tree'];
4270 - $exclude_ids = array_merge($exclude_ids, array($exclude_tree), accua_forms_get_post_descendant_ids($exclude_tree, $post_type));
4271 - }
4192 + }
4193 + if (!empty($exclusions))
4194 + $exclusions .= ')';
4272 4195
4273 - // Child of: restrict to all descendants of the given post, like core get_pages().
4274 - // Resolved to an explicit ID list so it stays correct with pagination and search.
4275 - if (!empty($r['child_of'])) {
4276 - $descendant_ids = accua_forms_get_post_descendant_ids((int) $r['child_of'], $post_type);
4277 - // post__in cannot be combined with post__not_in, so exclusions are applied to the list itself.
4278 - $descendant_ids = array_values(array_diff($descendant_ids, $exclude_ids));
4279 - $query_args['post__in'] = !empty($descendant_ids) ? $descendant_ids : array(0);
4280 - } elseif (!empty($exclude_ids)) {
4281 - // phpcs:ignore WordPressVIPMinimum.Performance.WPQueryParams.PostNotIn_post__not_in -- Exclusion is an optional admin-configured feature, not default behavior.
4282 - $query_args['post__not_in'] = $exclude_ids;
4283 - }
4196 + $author_query = '';
4197 + if (!empty($authors)) {
4198 + $post_authors = preg_split('/[\s,]+/',$authors);
4284 4199
4285 - // Parent filter (direct children only)
4286 - if ((int) $r['parent'] >= 0) {
4287 - $query_args['post_parent'] = (int) $r['parent'];
4288 - }
4200 + if ( ! empty( $post_authors ) ) {
4201 + foreach ( $post_authors as $post_author ) {
4202 + //Do we have an author id or an author login?
4203 + if ( 0 == intval($post_author) ) {
4204 + $post_author = get_user_by('login', $post_author);
4205 + if ( empty($post_author) )
4206 + continue;
4207 + if ( empty($post_author->ID) )
4208 + continue;
4209 + $post_author = $post_author->ID;
4210 + }
4289 4211
4290 - // Authors filter
4291 - if (!empty($r['authors'])) {
4292 - $author_ids = array();
4293 - $post_authors = preg_split('/[\s,]+/', $r['authors']);
4294 - foreach ($post_authors as $post_author) {
4295 - $post_author = trim($post_author);
4296 - if (empty($post_author)) {
4297 - continue;
4298 - }
4299 - if (is_numeric($post_author)) {
4300 - $author_ids[] = (int) $post_author;
4301 - } else {
4302 - $user = get_user_by('login', $post_author);
4303 - if ($user && !empty($user->ID)) {
4304 - $author_ids[] = $user->ID;
4305 - }
4306 - }
4212 + if ( '' == $author_query )
4213 + $author_query = $wpdb->prepare(' post_author = %d ', $post_author);
4214 + else
4215 + $author_query .= $wpdb->prepare(' OR post_author = %d ', $post_author);
4307 4216 }
4308 - if (!empty($author_ids)) {
4309 - $query_args['author__in'] = $author_ids;
4310 - }
4217 + if ( '' != $author_query )
4218 + $author_query = " AND ($author_query)";
4311 4219 }
4220 + }
4312 4221
4313 - // Build meta_query for advanced meta comparisons
4314 - $meta_query = array();
4222 + $allowed_keys = array('author', 'post_author', 'date', 'post_date', 'title', 'post_title', 'name', 'post_name', 'modified',
4223 + 'post_modified', 'modified_gmt', 'post_modified_gmt', 'menu_order', 'parent', 'post_parent',
4224 + 'ID', 'rand', 'comment_count');
4315 4225
4316 - // Standard meta_key/meta_value - used for filtering posts by custom field.
4317 - // This is an optional admin-configured feature for advanced post filtering.
4318 - if (!empty($r['meta_key'])) {
4319 - // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_key -- Required for custom field filtering feature.
4320 - $query_args['meta_key'] = stripslashes($r['meta_key']);
4321 - if (!empty($r['meta_value'])) {
4322 - // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_value -- Required for custom field filtering feature.
4323 - $query_args['meta_value'] = stripslashes($r['meta_value']);
4324 - }
4226 + $join = '';
4227 + $where = "$exclusions $inclusions ";
4228 + if ( ! ( empty( $meta_key ) && empty( $meta_value )
4229 + && empty( $meta_value_lt ) && empty( $meta_value_gt )
4230 + && empty( $meta_value_le ) && empty( $meta_value_ge )
4231 + && empty( $meta_value_like ) ) ) {
4232 + $join = " LEFT JOIN $wpdb->postmeta ON ( $wpdb->posts.ID = $wpdb->postmeta.post_id )";
4233 + $allowed_keys[] = 'meta_key';
4234 + $allowed_keys[] = 'meta_value';
4235 +
4236 + // meta_key and meta_value might be slashed
4237 + $meta_key = stripslashes($meta_key);
4238 + $meta_value = stripslashes($meta_value);
4239 + $meta_value_lt = stripslashes($meta_value_lt);
4240 + $meta_value_gt = stripslashes($meta_value_gt);
4241 + $meta_value_le = stripslashes($meta_value_le);
4242 + $meta_value_ge = stripslashes($meta_value_ge);
4243 + $meta_value_like = stripslashes($meta_value_like);
4244 +
4245 + if ( ! empty( $meta_key ) ) {
4246 + $where .= $wpdb->prepare(" AND $wpdb->postmeta.meta_key = %s", $meta_key);
4325 4247 }
4326 4248
4327 - // Advanced meta comparisons (lt, gt, le, ge, like)
4328 - if (!empty($r['meta_key']) && (
4329 - !empty($r['meta_value_lt']) || !empty($r['meta_value_gt']) ||
4330 - !empty($r['meta_value_le']) || !empty($r['meta_value_ge']) ||
4331 - !empty($r['meta_value_like'])
4332 - )) {
4333 - $meta_key = stripslashes($r['meta_key']);
4334 - $meta_type = 'CHAR';
4335 - switch ($r['meta_value_format']) {
4336 - case 'int':
4337 - $meta_type = 'NUMERIC';
4338 - break;
4339 - case 'float':
4340 - $meta_type = 'DECIMAL';
4341 - break;
4342 - case 'timestamp':
4343 - $meta_type = 'DATETIME';
4344 - break;
4345 - }
4249 + $meta_value_field = "$wpdb->postmeta.meta_value";
4250 + $meta_value_timestamp = false;
4251 + switch($meta_value_format) {
4252 + case 'timestamp':
4253 + $meta_value_field = "TIMESTAMP( $meta_value_field )";
4254 + $meta_value_param = "FROM_UNIXTIME( %s )";
4255 + $meta_value_timestamp = true;
4256 + break;
4257 + case 'int':
4258 + $meta_value_param = "%d";
4259 + break;
4260 + case 'float':
4261 + $meta_value_param = "%f";
4262 + break;
4263 + //case 'string':
4264 + default:
4265 + $meta_value_param = "%s";
4266 + }
4346 4267
4347 - if (!empty($r['meta_value_lt'])) {
4348 - $value = stripslashes($r['meta_value_lt']);
4349 - if ($r['meta_value_format'] === 'timestamp') {
4350 - $value = gmdate('Y-m-d H:i:s', strtotime($value));
4351 - }
4352 - $meta_query[] = array(
4353 - 'key' => $meta_key,
4354 - 'value' => $value,
4355 - 'compare' => '<',
4356 - 'type' => $meta_type,
4357 - );
4268 + if ( ! empty( $meta_value ) ) {
4269 + if ($meta_value_timestamp) {
4270 + $meta_value = strtotime($meta_value);
4358 4271 }
4359 - if (!empty($r['meta_value_gt'])) {
4360 - $value = stripslashes($r['meta_value_gt']);
4361 - if ($r['meta_value_format'] === 'timestamp') {
4362 - $value = gmdate('Y-m-d H:i:s', strtotime($value));
4363 - }
4364 - $meta_query[] = array(
4365 - 'key' => $meta_key,
4366 - 'value' => $value,
4367 - 'compare' => '>',
4368 - 'type' => $meta_type,
4369 - );
4272 + $where .= $wpdb->prepare(" AND $meta_value_field = $meta_value_param", $meta_value);
4273 + }
4274 + if ( ! empty( $meta_value_lt ) ) {
4275 + if ($meta_value_timestamp) {
4276 + $meta_value_lt = strtotime($meta_value_lt);
4370 4277 }
4371 - if (!empty($r['meta_value_le'])) {
4372 - $value = stripslashes($r['meta_value_le']);
4373 - if ($r['meta_value_format'] === 'timestamp') {
4374 - $value = gmdate('Y-m-d H:i:s', strtotime($value));
4375 - }
4376 - $meta_query[] = array(
4377 - 'key' => $meta_key,
4378 - 'value' => $value,
4379 - 'compare' => '<=',
4380 - 'type' => $meta_type,
4381 - );
4278 + $where .= $wpdb->prepare(" AND $meta_value_field < $meta_value_param", $meta_value_lt);
4279 + }
4280 + if ( ! empty( $meta_value_gt ) ) {
4281 + if ($meta_value_timestamp) {
4282 + $meta_value_gt = strtotime($meta_value_gt);
4382 4283 }
4383 - if (!empty($r['meta_value_ge'])) {
4384 - $value = stripslashes($r['meta_value_ge']);
4385 - if ($r['meta_value_format'] === 'timestamp') {
4386 - $value = gmdate('Y-m-d H:i:s', strtotime($value));
4387 - }
4388 - $meta_query[] = array(
4389 - 'key' => $meta_key,
4390 - 'value' => $value,
4391 - 'compare' => '>=',
4392 - 'type' => $meta_type,
4393 - );
4284 + $where .= $wpdb->prepare(" AND $meta_value_field > $meta_value_param", $meta_value_gt);
4285 + }
4286 + if ( ! empty( $meta_value_le ) ) {
4287 + if ($meta_value_timestamp) {
4288 + $meta_value_le = strtotime($meta_value_le);
4394 4289 }
4395 - if (!empty($r['meta_value_like'])) {
4396 - $meta_query[] = array(
4397 - 'key' => $meta_key,
4398 - 'value' => stripslashes($r['meta_value_like']),
4399 - 'compare' => 'LIKE',
4400 - );
4290 + $where .= $wpdb->prepare(" AND $meta_value_field <= $meta_value_param", $meta_value_le);
4291 + }
4292 + if ( ! empty( $meta_value_ge ) ) {
4293 + if ($meta_value_timestamp) {
4294 + $meta_value_ge = strtotime($meta_value_ge);
4401 4295 }
4402 -
4403 - if (!empty($meta_query)) {
4404 - // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query -- Required for advanced meta comparison operators (lt, gt, like, etc.).
4405 - $query_args['meta_query'] = $meta_query;
4406 - // Remove simple meta_value if we're using meta_query
4407 - unset($query_args['meta_value']);
4296 + $where .= $wpdb->prepare(" AND $meta_value_field >= $meta_value_param", $meta_value_ge);
4297 + }
4298 + if ( ! empty( $meta_value_like ) ) {
4299 + if ($meta_value_timestamp) {
4300 + $meta_value_like = strtotime($meta_value_like);
4408 4301 }
4302 + $where .= $wpdb->prepare(" AND $meta_value_field like $meta_value_param", $meta_value_like);
4409 4303 }
4410 4304 }
4411 4305
4412 - // Get posts using WordPress function (WPML automatically filters by current language)
4413 - $pages = get_posts($query_args);
4306 + if ( $parent >= 0 )
4307 + $where .= $wpdb->prepare(' AND post_parent = %d ', $parent);
4414 4308
4415 - if (empty($pages)) {
4416 - // Cache empty results too (5 minutes)
4417 - if ($use_cache) {
4418 - set_transient($cache_key, array(), 5 * MINUTE_IN_SECONDS);
4309 +
4310 + if ( 1 == count ( $post_type ) ) {
4311 + $where_post_type = $wpdb->prepare( "post_type = %s", array_shift( $post_type ) );
4312 + } else {
4313 + $post_type = implode( "', '", $post_type );
4314 + $where_post_type = "post_type IN ('$post_type')";
4315 + }
4316 +
4317 + if ( 1 == count( $post_status ) ) {
4318 + $where_post_type .= $wpdb->prepare( " AND post_status = %s", array_shift( $post_status ) );
4319 + } else {
4320 + $post_status = implode( "', '", $post_status );
4321 + $where_post_type .= " AND post_status IN ('$post_status')";
4322 + }
4323 +
4324 + $orderby_array = array();
4325 + foreach ( explode( ',', $sort_column ) as $orderby ) {
4326 + $orderby = trim( $orderby );
4327 + if ( !in_array( $orderby, $allowed_keys ) )
4328 + continue;
4329 +
4330 + switch ( $orderby ) {
4331 + case 'menu_order':
4332 + break;
4333 + case 'ID':
4334 + $orderby = "$wpdb->posts.ID";
4335 + break;
4336 + case 'rand':
4337 + $orderby = 'RAND()';
4338 + break;
4339 + case 'comment_count':
4340 + $orderby = "$wpdb->posts.comment_count";
4341 + break;
4342 + case 'meta_key':
4343 + case 'meta_value':
4344 + $orderby = "$wpdb->postmeta.$orderby";
4345 + break;
4346 + default:
4347 + if ( 0 === strpos( $orderby, 'post_' ) )
4348 + $orderby = "$wpdb->posts." . $orderby;
4349 + else
4350 + $orderby = "$wpdb->posts.post_" . $orderby;
4419 4351 }
4420 - /**
4421 - * Filters the list of pages retrieved from accua_get_pages.
4422 - *
4423 - * @since 2.0.0-beta.29
4424 - *
4425 - * @param array $pages List of page objects.
4426 - * @param array $r Arguments passed to accua_get_pages.
4427 - */
4428 - return apply_filters('accua_forms_get_pages', array(), $r);
4352 +
4353 + $orderby_array[] = $orderby;
4354 +
4429 4355 }
4356 + $sort_column = ! empty( $orderby_array ) ? implode( ',', $orderby_array ) : "$wpdb->posts.post_title";
4430 4357
4431 - // Hierarchical (tree) ordering: list parents before their children, like core
4432 - // get_pages(). Only applied when the result set is complete (no search, no
4433 - // offset, not truncated by the limit) and title-sorted - reordering a paginated
4434 - // or filtered slice would drop children whose parent is not in the same slice.
4435 - if ($r['hierarchical'] && empty($r['s']) && (int) $r['offset'] === 0
4436 - && count($pages) < (int) $query_args['posts_per_page']
4437 - && $orderby === 'title'
4438 - && function_exists('get_page_children')) {
4439 - $tree_ordered = get_page_children((int) $r['child_of'], $pages);
4440 - if (count($tree_ordered) < count($pages)) {
4441 - // Posts whose ancestors are not part of the result set (e.g. published
4442 - // children of a draft parent) go at the end instead of being dropped.
4443 - $tree_ids = array();
4444 - foreach ($tree_ordered as $page) {
4445 - $tree_ids[$page->ID] = true;
4446 - }
4447 - foreach ($pages as $page) {
4448 - if (!isset($tree_ids[$page->ID])) {
4449 - $tree_ordered[] = $page;
4450 - }
4451 - }
4452 - }
4453 - $pages = $tree_ordered;
4358 + $sort_order = strtoupper( $sort_order );
4359 + if ( '' !== $sort_order && !in_array( $sort_order, array( 'ASC', 'DESC' ) ) )
4360 + $sort_order = 'ASC';
4361 +
4362 + $query = "SELECT * FROM $wpdb->posts $join WHERE ($where_post_type) $where ";
4363 + $query .= $author_query;
4364 + $query .= " ORDER BY " . $sort_column . " " . $sort_order ;
4365 +
4366 + if ( !empty($number) && !empty($offset) ) {
4367 + $query .= $wpdb->prepare(' LIMIT %d, %d', $offset, $number);
4454 4368 }
4455 4369
4456 - // Cache results for 5 minutes to improve performance
4457 - if ($use_cache) {
4458 - set_transient($cache_key, $pages, 5 * MINUTE_IN_SECONDS);
4370 + //echo "<!-- accua_forms_query:\n$query\n-->";
4371 +
4372 + $pages = $wpdb->get_results($query);
4373 +
4374 + if ( empty($pages) ) {
4375 + $pages = apply_filters('get_pages', array(), $r);
4376 + return $pages;
4459 4377 }
4460 4378
4461 - /** This filter is documented above */
4462 - return apply_filters('accua_forms_get_pages', $pages, $r);
4463 -}
4379 + // Sanitize before caching so it'll only get done once
4380 + $num_pages = count($pages);
4381 + for ($i = 0; $i < $num_pages; $i++) {
4382 + $pages[$i] = sanitize_post($pages[$i], 'raw');
4383 + }
4464 4384
4465 -/**
4466 - * Get the IDs of all descendants of a post by traversing the post_parent tree.
4467 - *
4468 - * Used to resolve the child_of and exclude_tree arguments of accua_get_pages()
4469 - * to an explicit ID list, so the main query stays correct with pagination and
4470 - * search. Traverses posts of any status so that e.g. a published grandchild of
4471 - * a draft child is still found (the main query applies its own status filter).
4472 - *
4473 - * @since 2.2.27
4474 - * @param int $parent_id Root post ID (not included in the result).
4475 - * @param string|array $post_type Post type(s) to traverse.
4476 - * @return int[] Descendant post IDs.
4477 - */
4478 -function accua_forms_get_post_descendant_ids($parent_id, $post_type) {
4479 - $descendant_ids = array();
4480 - $level = array((int) $parent_id);
4481 - // Depth guard: hierarchies deeper than 25 levels are treated as data corruption (parent loops).
4482 - for ($depth = 0; $depth < 25 && !empty($level); $depth++) {
4483 - $children = get_posts(array(
4484 - 'post_type' => $post_type,
4485 - 'post_status' => 'any',
4486 - 'post_parent__in' => $level,
4487 - 'posts_per_page' => -1,
4488 - 'fields' => 'ids',
4489 - // phpcs:ignore WordPressVIPMinimum.Performance.WPQueryParams.SuppressFilters_suppress_filters -- Structural traversal: do not let language plugins hide ancestors (also get_posts()'s default).
4490 - 'suppress_filters' => true,
4491 - 'orderby' => 'ID',
4492 - 'order' => 'ASC',
4493 - ));
4494 - $children = array_map('intval', array_diff($children, $descendant_ids, array((int) $parent_id)));
4495 - $descendant_ids = array_merge($descendant_ids, $children);
4496 - $level = $children;
4385 + /*
4386 + // Update cache.
4387 + update_post_cache( $pages );
4388 + */
4389 +
4390 + if ( $child_of || $hierarchical )
4391 + $pages = get_page_children($child_of, $pages);
4392 +
4393 + if ( !empty($exclude_tree) ) {
4394 + $exclude = (int) $exclude_tree;
4395 + $children = get_page_children($exclude, $pages);
4396 + $excludes = array();
4397 + foreach ( $children as $child )
4398 + $excludes[] = $child->ID;
4399 + $excludes[] = $exclude;
4400 + $num_pages = count($pages);
4401 + for ( $i = 0; $i < $num_pages; $i++ ) {
4402 + if ( in_array($pages[$i]->ID, $excludes) )
4403 + unset($pages[$i]);
4404 + }
4497 4405 }
4498 - return $descendant_ids;
4406 +
4407 + $pages = apply_filters('get_pages', $pages, $r);
4408 +
4409 + return $pages;
4499 4410 }
4500 4411
4501 -// phpcs:disable WordPress.DB.DirectDatabaseQuery
4502 4412 function accua_forms_trash_submission($id_sub){
4503 4413 global $wpdb;
4504 4414 return $wpdb->query($wpdb->prepare("UPDATE `{$wpdb->prefix}accua_forms_submissions` SET afs_status = -1 WHERE afs_id = %d", $id_sub)) !== FALSE;
4505 4415 }
4506 4416
4507 -function accua_forms_restore_submission($id_sub){
4508 - global $wpdb;
4509 - return $wpdb->query($wpdb->prepare("UPDATE `{$wpdb->prefix}accua_forms_submissions` SET afs_status = 0 WHERE afs_id = %d", $id_sub)) !== FALSE;
4510 -}
4511 -// phpcs:enable WordPress.DB.DirectDatabaseQuery
4512 -
4513 -/**
4514 - * Clear accua_get_pages cache when posts are modified.
4515 - *
4516 - * Called when posts are created, updated, deleted, or have status changed.
4517 - * This ensures that post-select dropdowns always show fresh data.
4518 - *
4519 - * @since 2.0.0-beta.29
4520 - * @param int $post_id Post ID that was modified.
4521 - */
4522 -function accua_forms_clear_pages_cache($post_id = 0) {
4523 - global $wpdb;
4524 - // Delete all transients that start with 'accua_pages_'
4525 - // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- Direct query required to delete transients by prefix, and we're clearing cache not reading data.
4526 - $wpdb->query("DELETE FROM {$wpdb->options} WHERE option_name LIKE '_transient_accua_pages_%' OR option_name LIKE '_transient_timeout_accua_pages_%'");
4527 -}
4528 -// Clear cache when posts are modified
4529 -add_action('save_post', 'accua_forms_clear_pages_cache');
4530 -add_action('delete_post', 'accua_forms_clear_pages_cache');
4531 -add_action('trash_post', 'accua_forms_clear_pages_cache');
4532 -add_action('untrash_post', 'accua_forms_clear_pages_cache');
4533 -
4534 4417 function accua_forms_get_lead_statuses() {
4535 4418 static $statuses = NULL;
4536 4419 if ($statuses === NULL) {
4537 4420 $statuses = array(
@@ -4548,34 +4431,24 @@
4548 4431 }
4549 4432 return $statuses;
4550 4433 }
4551 4434
4552 -/**
4553 - * Get lead statuses help text (used in toggletip and Help Tab).
4554 - */
4555 -function accua_forms_get_lead_statuses_help() {
4556 - return '<strong>' . esc_html__( 'Spam', 'contact-forms' ) . '</strong> - ' . esc_html__( 'All submissions that can be discarded immediately, including submission tests', 'contact-forms' ) . '<br>'
4557 - . '<strong>' . esc_html__( 'Job Candidate', 'contact-forms' ) . '</strong> - ' . esc_html__( 'Includes spontaneous and specific job applications', 'contact-forms' ) . '<br>'
4558 - . '<strong>' . esc_html__( 'Lead', 'contact-forms' ) . '</strong> - ' . esc_html__( 'Unclear (general info request)', 'contact-forms' ) . '<br>'
4559 - . '<strong>' . esc_html__( 'Prospect', 'contact-forms' ) . '</strong> - ' . esc_html__( 'A qualified lead passed to Sales', 'contact-forms' ) . '<br>'
4560 - . '<strong>' . esc_html__( 'Opportunity', 'contact-forms' ) . '</strong> - ' . esc_html__( 'Quote / Pricing request that must be followed up', 'contact-forms' ) . '<br>'
4561 - . '<strong>' . esc_html__( 'Customer', 'contact-forms' ) . '</strong> - ' . esc_html__( 'Has already purchased', 'contact-forms' ) . '<br>'
4562 - . '<strong>' . esc_html__( 'Supplier', 'contact-forms' ) . '</strong> - ' . esc_html__( 'Contact whose role is or can only be supplier of goods and services', 'contact-forms' ) . '<br>'
4563 - . '<strong>' . esc_html__( 'Other', 'contact-forms' ) . '</strong> - ' . esc_html__( 'Contact is valid but not within lead generation', 'contact-forms' );
4564 -}
4565 -
4566 4435 function accua_forms_select_lead_status($subid, $original_lead_status) {
4567 - $subid = absint( $subid );
4568 - // (int), not absint(): -1 is the Spam lead status and must not collapse onto 1.
4569 - $original_lead_status = (int) $original_lead_status;
4570 - $nonce = esc_attr( wp_json_encode( wp_create_nonce( "set_lead_status_$subid" ) ) );
4571 - $ret = '<select onchange="accua_forms_set_lead_status(this, ' . $subid . ', ' . $nonce . ', ' . $original_lead_status . ')">';
4436 + static $accuaHelp = NULL;
4437 + if ($accuaHelp === NULL) {
4438 + if (!class_exists('AccuaFormsHelp')) {
4439 + require_once('accua-forms-help.php');
4440 + }
4441 + $accuaHelp = AccuaFormsHelp::getInstance();
4442 + }
4443 + $nonce = htmlspecialchars(_accua_forms_json_encode(wp_create_nonce( "set_lead_status_$subid" )),ENT_QUOTES);
4444 + $ret = "<select onchange=\"accua_forms_set_lead_status(this, $subid, $nonce, $original_lead_status)\">";
4572 4445 $statuses = accua_forms_get_lead_statuses();
4573 4446 foreach ($statuses as $k => $l) {
4574 - $selected = ( (int) $k === $original_lead_status ) ? ' selected="selected" ' : '';
4575 - $ret .= '<option value="' . esc_attr( $k ) . '"' . $selected . '>' . esc_html( $l ) . '</option>';
4447 + $selected = ($k == $original_lead_status) ? ' selected="selected" ' : '';
4448 + $ret .= "<option value=\"$k\"$selected>" . htmlspecialchars($l) . "</option>";
4576 4449 }
4577 - $ret .= '</select>';
4450 + $ret .= "</select>" . $accuaHelp->add_pointer('contact_forms_lead_statuses') . "<span class='accua-forms-select-lead-status-progress'></span>";
4578 4451 return $ret;
4579 4452 }
4580 4453
4581 4454 add_action( 'wp_ajax_accua-forms-set-lead-status' , 'accua_forms_set_lead_status');
@@ -4582,9 +4455,8 @@
4582 4455 function accua_forms_set_lead_status() {
4583 4456 if (!current_user_can('manage_options')){
4584 4457 wp_die(0, 403);
4585 4458 }
4586 - // phpcs:ignore WordPress.Security.NonceVerification.Missing -- Nonce verification happens after subid is extracted via check_ajax_referer()
4587 4459 $post = $_POST + array(
4588 4460 'subid' => 0,
4589 4461 'lead_status' => 0,
4590 4462 );
@@ -4595,62 +4467,16 @@
4595 4467 $lead_status = (int) $post['lead_status'];
4596 4468 $statuses = accua_forms_get_lead_statuses();
4597 4469 if (isset($statuses[$lead_status])) {
4598 4470 global $wpdb;
4599 - // phpcs:disable WordPress.DB.DirectDatabaseQuery
4600 - $ret = $wpdb->update(
4601 - "{$wpdb->prefix}accua_forms_submissions",
4471 + $ret = $wpdb->update("{$wpdb->prefix}accua_forms_submissions",
4602 4472 array('afs_lead_status' => $lead_status),
4603 4473 array('afs_id' => $subid),
4604 - array('%d'),
4605 - array('%d')
4474 + '%d', '%d'
4606 4475 );
4607 - // phpcs:enable WordPress.DB.DirectDatabaseQuery
4608 4476 if ($ret !== FALSE) {
4609 - wp_die(1);
4477 + wp_die(1, 200);
4610 4478 }
4611 4479 }
4612 4480 }
4613 4481 wp_die(0, 500);
4614 4482 }
4615 -
4616 -add_action( 'wp_ajax_accua-forms-add-note', 'accua_forms_ajax_add_note' );
4617 -function accua_forms_ajax_add_note() {
4618 - $sub_id = isset( $_POST['subid'] ) ? (int) $_POST['subid'] : 0;
4619 - $text = isset( $_POST['text'] ) ? sanitize_textarea_field( wp_unslash( $_POST['text'] ) ) : '';
4620 -
4621 - if ( ! $sub_id || ! $text ) {
4622 - wp_send_json_error();
4623 - }
4624 - check_ajax_referer( "submission_{$sub_id}_note_add", '_nonce' );
4625 - if ( ! current_user_can( 'manage_options' ) ) {
4626 - wp_send_json_error();
4627 - }
4628 -
4629 - require_once __DIR__ . '/admin/single-submission.php';
4630 - $result = accua_forms_add_submission_note( $sub_id, $text );
4631 - if ( ! $result ) {
4632 - wp_send_json_error();
4633 - }
4634 - $result['del_nonce'] = wp_create_nonce( "submission_{$sub_id}_note_del" );
4635 - wp_send_json_success( $result );
4636 -}
4637 -
4638 -add_action( 'wp_ajax_accua-forms-delete-note', 'accua_forms_ajax_delete_note' );
4639 -function accua_forms_ajax_delete_note() {
4640 - $sub_id = isset( $_POST['subid'] ) ? (int) $_POST['subid'] : 0;
4641 - $date = isset( $_POST['date'] ) ? sanitize_text_field( wp_unslash( $_POST['date'] ) ) : '';
4642 -
4643 - if ( ! $sub_id || ! $date ) {
4644 - wp_send_json_error();
4645 - }
4646 - check_ajax_referer( "submission_{$sub_id}_note_del", '_nonce' );
4647 - if ( ! current_user_can( 'manage_options' ) ) {
4648 - wp_send_json_error();
4649 - }
4650 -
4651 - require_once __DIR__ . '/admin/single-submission.php';
4652 - if ( ! accua_forms_delete_submission_note( $sub_id, $date ) ) {
4653 - wp_send_json_error();
4654 - }
4655 - wp_send_json_success();
4656 -}