PluginProbe
Contact Forms by Cimatti / 2.3.5
Contact Forms by Cimatti v2.3.5
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
contact-forms / admin / list-page.php

list-page.php in Contact Forms by Cimatti 2.3.5, at admin/list-page.php

408 lines 15.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 if ( ! defined( 'ABSPATH' ) ) exit;
3
4 if (!class_exists('WP_List_Table')) {
5 require_once(ABSPATH . 'wp-admin/includes/class-wp-list-table.php');
6 }
7
8 class Accua_Forms_List_Table extends WP_List_Table {
9 var $message = NULL;
10 var $active_items = 0;
11 var $del_items = 0;
12 var $accua_orderby = null;
13 var $accua_order_asc = null;
14
15 function __construct(){
16 global $status, $page;
17 $this->message = '';
18 parent::__construct(array(
19 'singular' => 'form',
20 'plural' => 'forms',
21 'ajax' => false
22 ));
23 }
24
25 function get_num_of_active_items(){
26 return $this->active_items;
27 }
28
29 function get_num_of_del_items(){
30 return $this->del_items;
31 }
32
33 function column_default($item, $column_name){
34 if (isset($item[$column_name])) {
35 return esc_attr($item[$column_name]);
36 } else {
37 return '';
38 }
39 }
40
41 function column_cb($item){
42 return sprintf(
43 '<input type="checkbox" name="%1$s[]" value="%2$s" />',
44 /*$1%s*/ $this->_args['singular'],
45 /*$2%s*/ $item['ID']
46 );
47 }
48
49 function column_title($item){
50 if ($item['deleted']) {
51 if (isset($item['title'])) {
52 $item_name = esc_html($item['title']);
53 } else {
54 $item_name = $item['ID'];
55 }
56 $nonced_edit = wp_nonce_url('admin.php?page=accua_forms_list&amp;fid=' . $item['ID'] . '&amp;restore=1', 'edit_posts');
57 $actions = array(
58 'edit' => "<a href='" . $nonced_edit . "'>" . __("Restore", 'contact-forms') . "</a>",
59 );
60 return "<strong>" . $item_name . "</strong>" . $this->row_actions($actions);
61 } else {
62 $nonced_edit = wp_nonce_url('admin.php?page=accua_forms_list&amp;fid=' . $item['ID'], 'edit_posts');
63 $nonced_clone = wp_nonce_url('admin.php?page=accua_forms_add&amp;clonefrom=' . $item['ID'], 'clone_posts');
64 $nonced_del = wp_nonce_url('admin.php?page=accua_forms_list&amp;fid_del=' . $item['ID'], 'trash_posts');
65 $actions = array(
66 'edit' => "<a href='{$nonced_edit}'>" . __("Edit", 'contact-forms') . "</a>"
67 . " &middot; <a href='{$nonced_clone}'>" . __("Clone", 'contact-forms') . "</a>"
68 . " &middot; <a href='admin.php?page=accua_forms_submissions_list&amp;fid={$item['ID']}'>" . __("Report", 'contact-forms') . "</a>"
69 . " &middot; <a href='{$nonced_del}'>" . __("Trash", 'contact-forms') . "</a>",
70 );
71 return "<strong><a class='row-title' href='{$nonced_edit}'>" . esc_html($item['title']) . "</a></strong>" . $this->row_actions($actions);
72 }
73 }
74
75 function column_submissions($item){
76 if ($item['submissions'] != 0)
77 return sprintf(
78 '<a href="admin.php?page=accua_forms_submissions_list&amp;fid=%1$s">%2$s</a>',
79 /*$1%s*/ $item['ID'],
80 /*$2%s*/ $item['submissions']
81 );
82 else
83 return "0";
84 }
85
86 function get_columns(){
87 $columns = array(
88 'cb' => '<input type="checkbox" />', //Render a checkbox instead of text
89 'title' => __('Title', 'contact-forms'),
90 'ID' => 'ID',
91 'shortcode' => __('Shortcode', 'contact-forms'),
92 'phpcode' => __('PHP code', 'contact-forms'),
93 'fromemail' => __('From Email', 'contact-forms'),
94 'fromname' => __('From Name', 'contact-forms'),
95 'adminemail' => __('Admin Email', 'contact-forms'),
96 'bccemail' => __('BCC Email', 'contact-forms'),
97 'retention' => __('Data Retention', 'contact-forms'),
98 'submissions' => __('Submissions', 'contact-forms'),
99 );
100 return $columns;
101 }
102
103 function column_retention( $item ) {
104 return isset( $item['retention'] ) ? esc_html( $item['retention'] ) : '';
105 }
106
107 function get_sortable_columns(){
108 return array(
109 'title' => array('title', false),
110 'ID' => array('ID', false),
111 'shortcode' => array('ID', false),
112 'phpcode' => array('ID', false),
113 'fromemail' => array('fromemail', false),
114 'fromname' => array('fromname', false),
115 'adminemail' => array('adminemail', false),
116 'bccemail' => array('bccemail', false),
117 'retention' => array('retention_seconds', false),
118 'submissions' => array('submissions', false),
119 );
120 }
121
122 function get_bulk_actions(){
123 // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Display logic only, no data processing
124 if (isset($_GET['del']) && absint($_GET['del']) === 1) {
125 $actions = array();
126 } else {
127 $actions = array(
128 'delete' => __('Move to trash', 'contact-forms')
129 );
130 }
131 return $actions;
132 }
133
134 function set_message($single_message){
135 $this->message = $single_message;
136 }
137
138 function get_message(){
139 if ($this->message != NULL)
140 return $this->message;
141 else
142 return NULL;
143 }
144
145 function accua_usort_numeric($a, $b){
146 $result = ((int)$a[$this->accua_orderby]) - ((int)$b[$this->accua_orderby]);
147 if (!$result) {
148 $result = ((int)$a['ID']) - ((int)$b['ID']);
149 }
150 return ($this->accua_order_asc) ? $result : -$result;
151 }
152
153 function accua_usort_string($a, $b){
154 $result = strcasecmp($a[$this->accua_orderby], $b[$this->accua_orderby]);
155 if (!$result) {
156 $result = ((int)$a['ID']) - ((int)$b['ID']);
157 }
158 return ($this->accua_order_asc) ? $result : -$result;
159 }
160
161 function process_bulk_action(){
162 $current_action = $this->current_action();
163 if ($current_action) {
164 check_admin_referer('bulk-forms'); //check nonce generated for 'bulk-'.$this->_args['plural']
165 // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized, WordPress.Security.ValidatedSanitizedInput.MissingUnslash -- Values sanitized in array_map below
166 $forms_raw = (isset($_GET['form']) && is_array($_GET['form'])) ? wp_unslash($_GET['form']) : array();
167 $forms = array_map('sanitize_text_field', $forms_raw);
168 if ('delete' === $current_action) {
169 $forms_deleted = false;
170 $forms_data = get_option('accua_forms_saved_forms', array());
171 $trash_data = get_option('accua_forms_trash_forms', array());
172
173 foreach ($forms as $single_form) {
174 if (isset($forms_data[$single_form])) {
175 $trash_data[$single_form] = $forms_data[$single_form];
176 unset($forms_data[$single_form]);
177 $forms_deleted = true;
178 ?>
179 <script type="text/javascript">
180 jQuery(function($){
181 // Match the checkbox cell by class, not by tag: WordPress 7.1
182 // renders it as a td where every earlier version rendered a th.
183 jQuery("#the-list tr:has(.check-column input[type='checkbox'][value='<?php echo esc_js( $single_form ); ?>'])").fadeOut();
184 });
185 </script>
186 <?php
187 }
188 }
189 if ($forms_deleted) {
190 update_option('accua_forms_trash_forms', $trash_data);
191 update_option('accua_forms_saved_forms', $forms_data);
192 $this->set_message(__("Forms deleted", 'contact-forms'));
193 }
194
195 }
196 }
197 }
198
199 function prepare_items(){
200 global $wpdb, $hook_suffix;
201 $per_page = 50;
202 $del = isset($_GET['del']) && $_GET['del'] == 1;
203
204 $columns = $this->get_columns();
205 $hidden = get_hidden_columns($hook_suffix);
206 $sortable = $this->get_sortable_columns();
207
208 $this->_column_headers = array($columns, $hidden, $sortable);
209
210 $current_page = $this->get_pagenum();
211
212 $limit = ($current_page - 1) * $per_page;
213
214 $forms_data = get_option('accua_forms_saved_forms', array());
215 $forms_trash = get_option('accua_forms_trash_forms', array());
216 $forms_default = get_option('accua_forms_default_form_data', array());
217
218 $this->active_items = count($forms_data);
219 $this->del_items = count($forms_trash);
220
221 $data = array();
222 $global_retention = get_option( 'accua_forms_retention_data', array() );
223
224 if ($del) {
225 check_admin_referer('deleted_forms');
226 $start = $forms_trash;
227 } else {
228 $start = $forms_data;
229 }
230
231 foreach ($start as $id => $form) {
232 if (isset($form['title']) && (trim($form['title']) !== '')) {
233 $title = $form['title'];
234 } else {
235 $title = __('(no title)', 'contact-forms');
236 }
237
238 $data[$id] = array(
239 'ID' => $id,
240 'title' => $title,
241 'submissions' => 0,
242 'shortcode' => $del ? '' : '[accua-form fid="' . $id . '"]',
243 'phpcode' => $del ? '' : "<?php accua_forms_include('$id'); ?>",
244 'deleted' => $del,
245 );
246
247 $forminfos = array(
248 'fromemail' => 'emails_from',
249 'fromname' => 'emails_from_name',
250 'adminemail' => 'admin_emails_to',
251 'bccemail' => 'emails_bcc',
252 );
253
254 foreach ($forminfos as $infodest => $infoid) {
255 if (isset($form[$infoid])) {
256 $data[$id][$infodest] = $form[$infoid];
257 } else {
258 $data[$id][$infodest] = $forms_default[$infoid] . " (default)";
259 }
260 }
261
262 // Compute effective data retention column
263 $config = accua_forms_get_retention_config( $id );
264 $has_override = ! empty( $form['submission_retention_override'] );
265 $unit_labels = array( 'days' => __( 'days', 'contact-forms' ), 'months' => __( 'months', 'contact-forms' ), 'years' => __( 'years', 'contact-forms' ) );
266 $mode_labels = array( 'anonymize' => __( 'Anonymize', 'contact-forms' ), 'delete' => __( 'Delete', 'contact-forms' ) );
267 $data[$id]['retention_seconds'] = $config['seconds'];
268 if ( $config['seconds'] > 0 ) {
269 // Reverse-engineer the display value from the form or global settings
270 if ( $has_override ) {
271 $r_val = isset( $form['submission_retention_value'] ) ? (int) $form['submission_retention_value'] : 0;
272 $r_unit = isset( $form['submission_retention_unit'] ) ? $form['submission_retention_unit'] : 'months';
273 } else {
274 $r_val = isset( $global_retention['retention_value'] ) ? (int) $global_retention['retention_value'] : 0;
275 $r_unit = isset( $global_retention['retention_unit'] ) ? $global_retention['retention_unit'] : 'months';
276 }
277 $r_unit_label = $unit_labels[ $r_unit ] ?? $r_unit;
278 $r_mode_label = $mode_labels[ $config['mode'] ] ?? $config['mode'];
279 $data[$id]['retention'] = sprintf( '%d %s / %s', $r_val, $r_unit_label, $r_mode_label );
280 } else {
281 $data[$id]['retention'] = __( 'Keep indefinitely', 'contact-forms' );
282 }
283
284 }
285
286 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- Custom table query for form submissions count
287 $submissions = $wpdb->get_results(
288 $wpdb->prepare(
289 "SELECT afs_form_id AS fid, count(*) AS submissions
290 FROM `{$wpdb->prefix}accua_forms_submissions`
291 WHERE afs_status >= %d
292 GROUP BY afs_form_id",
293 0
294 ),
295 OBJECT
296 );
297 foreach ($submissions as $fsub) {
298 if (isset($data[$fsub->fid])) {
299 $data[$fsub->fid]['submissions'] = $fsub->submissions;
300 } else if ($del) {
301 if (!isset($forms_data[$fsub->fid])) {
302 $data[$fsub->fid] = array(
303 'ID' => $fsub->fid,
304 'submissions' => $fsub->submissions,
305 'deleted' => true,
306 'shortcode' => '',
307 'phpcode' => '',
308 'fromemail' => '',
309 'fromname' => '',
310 'adminemail' => '',
311 'bccemail' => '',
312 );
313 $this->del_items++;
314 }
315 } else if (!isset($forms_trash[$fsub->fid])) {
316 $this->del_items++;
317 }
318 }
319
320 $numeric_keys = array( 'ID', 'submissions', 'retention_seconds' );
321 $string_keys = array( 'title', 'fromemail', 'fromname', 'adminemail', 'bccemail' );
322 $allowed_keys = array_merge( $numeric_keys, $string_keys );
323
324 // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Read-only sort parameter
325 $this->accua_orderby = isset($_GET['orderby']) ? sanitize_key(wp_unslash($_GET['orderby'])) : 'ID';
326 if ( ! in_array( $this->accua_orderby, $allowed_keys, true ) ) {
327 $this->accua_orderby = 'ID';
328 }
329 // Default order: ascending for string columns, descending for numeric columns
330 // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Read-only sort direction
331 if (empty($_GET['order'])) {
332 $this->accua_order_asc = in_array( $this->accua_orderby, $string_keys, true );
333 } else {
334 // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Read-only sort direction
335 $this->accua_order_asc = (sanitize_key(wp_unslash($_GET['order'])) !== 'desc');
336 }
337 if ( in_array( $this->accua_orderby, $numeric_keys, true ) ) {
338 usort($data, array(&$this, 'accua_usort_numeric'));
339 } else {
340 usort($data, array(&$this, 'accua_usort_string'));
341 }
342
343 $total_items = count($data);
344
345 $this->items = array_slice($data, $limit, $per_page);
346
347 $this->set_pagination_args(array(
348 'total_items' => $total_items,
349 'per_page' => $per_page,
350 'total_pages' => ceil($total_items / $per_page)
351 ));
352 }
353 }
354
355 function accua_forms_list_page_table($head = false){
356 static $listTable = null;
357 //var_dump($_REQUEST);
358
359 if (isset($_GET['fid_del'])) {
360 check_admin_referer('trash_posts');
361 $fid = sanitize_text_field( wp_unslash( $_GET['fid_del'] ) );
362 $forms_data = get_option('accua_forms_saved_forms', array());
363 if (isset($forms_data[$fid])) {
364 $trash_data = get_option('accua_forms_trash_forms', array());
365 $trash_data[$fid] = $forms_data[$fid];
366 update_option('accua_forms_trash_forms', $trash_data);
367 unset($forms_data[$fid]);
368 update_option('accua_forms_saved_forms', $forms_data);
369 }
370 }
371
372 if ($listTable === null) {
373 $listTable = new Accua_Forms_List_Table();
374 $listTable->process_bulk_action();
375 $listTable->prepare_items();
376 }
377
378 if ($head === true) {
379 return;
380 }
381
382 if ($listTable->get_message() != NULL) { ?>
383 <div class="updated"><p><?php echo esc_html( $listTable->get_message() ); ?></p></div>
384 <?php } ?>
385 <ul class="subsubsub">
386 <li>
387 <?php $nonced_url = wp_nonce_url('admin.php?page=accua_forms_list', 'home_forms') ?>
388 <a <?php if (!isset($_GET['del']) || ($_GET['del'] != 1)) { echo " class='current' "; } ?> href="<?php echo esc_url($nonced_url) ?>">
389 <?php esc_html_e("Active", 'contact-forms'); ?></a> (<?php echo esc_html($listTable->get_num_of_active_items()); ?>) |
390 </li>
391 <li>
392 <?php $nonced_url = wp_nonce_url('admin.php?page=accua_forms_list&del=1', 'deleted_forms'); ?>
393 <a <?php if (isset($_GET['del']) && ($_GET['del'] == 1)) { echo " class='current' "; } ?> href="<?php echo esc_url($nonced_url) ?>">
394 <?php esc_html_e("Trash", 'contact-forms'); ?></a> (<?php echo esc_html($listTable->get_num_of_del_items()); ?>)
395 </li>
396 </ul>
397
398 <form id="accua-forms-list-filter" method="get">
399 <input type="hidden" name="page" value="<?php echo esc_attr( isset( $_REQUEST['page'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['page'] ) ) : '' ); ?>" />
400 <?php
401 // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- WP_List_Table display() outputs safe HTML
402 $listTable->display();
403 ?>
404 </form>
405 <?php /* echo '<pre>$listTable = ' htmlspecialchars(print_r($listTable, true)); ?></pre> */ ?>
406 <?php
407 }
408