PluginProbe
FireBox – WooCommerce Popup Builder, Exit Intent Popup, Email Optin & Cart Abandonment / 2.0.12
FireBox – WooCommerce Popup Builder, Exit Intent Popup, Email Optin & Cart Abandonment v2.0.12
3.1.13 3.1.12 3.1.11 3.1.10 3.1.9 3.1.8 3.1.7 trunk 1.0.0 1.0.1 1.0.10 1.0.11 1.0.12 1.0.13 1.0.14 1.0.2 1.0.3 1.0.4 1.0.5 1.0.6 1.0.7 1.0.8 1.0.9 1.1.0 1.1.1 All 122 releases
firebox / Inc / Core / Form / Tables / Submissions.php

Submissions.php in FireBox – WooCommerce Popup Builder, Exit Intent Popup, Email Optin & Cart Abandonment 2.0.12, at Inc/Core/Form/Tables/Submissions.php

574 lines 12.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * @package FireBox
4 * @version 2.0.12 Free
5 *
6 * @author FirePlugins <info@fireplugins.com>
7 * @link https://www.fireplugins.com
8 * @copyright Copyright © 2023 FirePlugins All Rights Reserved
9 * @license GNU GPLv3 <http://www.gnu.org/licenses/gpl.html> or later
10 */
11
12 namespace FireBox\Core\Form\Tables;
13
14 if (!defined('ABSPATH'))
15 {
16 exit; // Exit if accessed directly.
17 }
18
19 // Load WP_List_Table if not loaded
20 if (!class_exists('WP_List_Table'))
21 {
22 require_once ABSPATH . 'wp-admin/includes/class-wp-list-table.php';
23 }
24
25 use \FireBox\Core\Helpers\Form\Form;
26
27 class Submissions extends \WP_List_Table
28 {
29 /**
30 * Total items.
31 *
32 * @var array
33 */
34 private $total_items;
35
36 /**
37 * Total items per page.
38 *
39 * @var int
40 */
41 private $per_page = 20;
42
43 /**
44 * All forms.
45 *
46 * @var array
47 */
48 private $forms = [];
49
50 /**
51 * The selected form id.
52 *
53 * @var string
54 */
55 private $selected_form_id = null;
56
57 /**
58 * The selected form.
59 *
60 * @var array
61 */
62 private $selected_form = null;
63
64 public function __construct($args = [])
65 {
66 parent::__construct($args);
67
68 $this->forms = Form::getForms();
69
70 $this->selected_form_id = isset($_GET['form_id']) ? sanitize_key($_GET['form_id']) : (isset($this->forms[0]['id']) ? $this->forms[0]['id'] : null);
71 $this->selected_form = $this->getForm($this->selected_form_id);
72 }
73
74 /**
75 * This is a default column renderer.
76 *
77 * @param Object $item
78 * @param string $column_name
79 *
80 * @return string
81 */
82 public function column_default($item, $column_name)
83 {
84 // Find field related values
85 if (strpos($column_name, 'field_') === 0)
86 {
87 foreach ($item->meta as $meta_item)
88 {
89 if ('field_' . $meta_item->meta_key !== $column_name)
90 {
91 continue;
92 }
93
94 return nl2br($meta_item->meta_value);
95 }
96
97 return '';
98 }
99
100 return $item->$column_name;
101 }
102
103 /**
104 * Returns the form fields.
105 *
106 * @return array
107 */
108 private function getFormFields()
109 {
110 return isset($this->selected_form['fields']) ? $this->selected_form['fields'] : [];
111 }
112
113 /**
114 * Column "state" output.
115 *
116 * @param object $item
117 *
118 * @return void
119 */
120 public function column_state($item)
121 {
122 echo \FPFramework\Helpers\HTML::renderFPToggle([
123 'input_class' => ['fb-toggle-form-state'],
124 'name' => 'fb_submission_state_' . $item->id,
125 'extra_atts' => [
126 'data-submission-id' => $item->id
127 ],
128 'value' => $item->state === '1' ? 1 : 0
129 ]);
130 }
131
132 /**
133 * Column "created at" output.
134 *
135 * @param object $item
136 *
137 * @return void
138 */
139 public function column_created_at($item)
140 {
141 return get_date_from_gmt($item->created_at);
142 }
143
144 /**
145 * Column "id" output.
146 *
147 * @param object $item
148 *
149 * @return void
150 */
151 public function column_id($item)
152 {
153 $url = admin_url('admin.php?page=firebox-submissions&task=edit&id=' . $item->id);
154
155 return '<a href="' . $url . '">' . $item->id . '</a>';
156 }
157
158 /**
159 * Column "user id" output.
160 *
161 * @param object $item
162 *
163 * @return void
164 */
165 public function column_user_id($item)
166 {
167 if ($item->user_id === '0')
168 {
169 return '';
170 }
171
172 return '<a href="' . get_edit_user_link($item->user_id) . '">' . $item->user_id . '</a>';
173 }
174
175 /**
176 * Column "user name" output.
177 *
178 * @param object $item
179 *
180 * @return void
181 */
182 public function column_user_name($item)
183 {
184 if ($item->user_id === '0')
185 {
186 return '';
187 }
188
189 $user = get_user_by('id', $item->user_id);
190
191 return '<a href="' . get_edit_user_link($item->user_id) . '">' . $user->display_name . '</a>';
192 }
193
194 /**
195 * Renders a checkbox.
196 *
197 * @param object $item
198 *
199 * @return string
200 */
201 public function column_cb($item)
202 {
203 return sprintf('<input type="checkbox" name="id[]" value="%s" />', esc_attr($item->id));
204 }
205
206 /**
207 * Returns all table columns.
208 *
209 * @return array
210 */
211 function get_columns()
212 {
213 $columns = [
214 'cb' => '<input type="checkbox" />',
215 'state' => fpframework()->_('FPF_STATUS'),
216 'id' => fpframework()->_('FPF_ID'),
217 'created_at' => firebox()->_('FB_DATE_SUBMITTED')
218 ];
219
220 if ($fields = $this->getFormFields())
221 {
222 foreach ($fields as $field)
223 {
224 $columns = array_merge($columns, [
225 'field_' . $field->getOptionValue('id') => !empty($field->getLabel()) ? $field->getLabel() : $field->getOptionValue('name')
226 ]);
227 }
228 }
229
230 $columns = array_merge($columns, [
231 'user_id' => fpframework()->_('FPF_USER_ID'),
232 'user_name' => fpframework()->_('FPF_USER_NAME'),
233 'visitor_id' => fpframework()->_('FPF_VISITOR_ID'),
234 ]);
235
236 return $columns;
237 }
238
239 /**
240 * [OPTIONAL] This method return columns that may be used to sort table
241 * all strings in array - is column names
242 * notice that true on name column means that its default sort
243 *
244 * @return array
245 */
246 public function get_sortable_columns()
247 {
248 return [
249 'state' => ['state', false],
250 'id' => ['id', true],
251 'created_at' => ['created_at', false],
252 'user_id' => ['user_id', false],
253 'visitor_id' => ['visitor_id', false],
254 ];
255 }
256
257 /**
258 * Returns the allowed sortable columns keys.
259 *
260 * @return array
261 */
262 private function getAllowedOrders()
263 {
264 return array_keys($this->get_sortable_columns());
265 }
266
267 /**
268 * Set bulk actions.
269 *
270 * @return array
271 */
272 public function get_bulk_actions()
273 {
274 return [
275 'publish' => fpframework()->_('FPF_PUBLISH'),
276 'unpublish' => fpframework()->_('FPF_UNPUBLISH'),
277 'delete' => fpframework()->_('FPF_DELETE')
278 ];
279 }
280
281 /**
282 * Processes the bulk actions.
283 *
284 * @return void
285 */
286 public function process_bulk_action()
287 {
288 if (!isset($_GET['form_id']))
289 {
290 return;
291 }
292
293 // Ensure we have an action
294 if (!$action = $this->current_action())
295 {
296 return;
297 }
298
299 // Ensure its a valid action
300 $allowed_actions = $this->get_bulk_actions();
301 if (!array_key_exists($action, $allowed_actions))
302 {
303 return;
304 }
305
306 // Get nonce
307 $nonce = isset($_GET['_wpnonce']) ? sanitize_text_field($_GET['_wpnonce']) : '';
308 if (!$nonce)
309 {
310 return;
311 }
312
313 // Validate nonce
314 if (!wp_verify_nonce($nonce, 'bulk-firebox_page_firebox-submissions'))
315 {
316 wp_die(fpframework()->_('FPF_CANNOT_VALIDATE_REQUEST'));
317 }
318
319 unset($_GET['fpframework_fields']);
320
321 // Ensure we have IDs
322 $ids = isset($_GET['id'] ) ? array_filter($_GET['id'], 'intval') : [];
323 if (!$ids)
324 {
325 return;
326 }
327
328 $redirect_url = admin_url('edit.php?post_type=firebox-submissions&form_id=' . $_GET['form_id']);
329
330 // Publish or Unpublish action
331 if (in_array($action, ['publish', 'unpublish']))
332 {
333 $new_state = $action === 'publish' ? 1 : 0;
334
335 foreach ($ids as $id)
336 {
337 if (!\FireBox\Core\Helpers\Form\Submission::updateState($id, $new_state))
338 {
339 wp_die(firebox()->_('FB_CANNOT_UPDATE_SUBMISSION'));
340 }
341 }
342
343 \FPFramework\Libs\AdminNotice::displaySuccess(firebox()->_('FB_SUBMISSIONS_UPDATED'));
344 }
345 // Delete action
346 else if ($action === 'delete')
347 {
348 $ids = implode(',', $ids);
349
350 global $wpdb;
351
352 // Delete submission
353 $s_table_name = firebox()->tables->submission->getFullTableName();
354 $wpdb->query("DELETE FROM $s_table_name WHERE id IN($ids)");
355
356 // Also delete all submission meta associated with this submission
357 $sm_table_name = firebox()->tables->submissionmeta->getFullTableName();
358 $wpdb->query("DELETE FROM $sm_table_name WHERE submission_id IN($ids)");
359
360 \FPFramework\Libs\AdminNotice::displaySuccess(firebox()->_('FB_SUBMISSIONS_UPDATED'));
361 }
362
363 return $redirect_url;
364 }
365
366 /**
367 * Returns the views.
368 *
369 * @return array
370 */
371 public function get_views()
372 {
373 $current = isset($_GET['status']) ? sanitize_key($_GET['status']) : '';
374 $base_url = $this->get_base_url();
375
376 // Base URL
377 $remove = ['status', 'paged', '_wpnonce'];
378 $url = remove_query_arg($remove, $base_url);
379
380 $count = '&nbsp;<span class="count">(%d)</span>';
381
382 // All
383 $all_class = in_array($current, ['', 'all'], true) ? ' class="current"' : '';
384 $all_count = sprintf($count, esc_attr(count($this->total_items)));
385 $all_label = fpframework()->_('FPF_ALL') . $all_count;
386
387 // Published
388 $p_class = in_array($current, ['published'], true) ? ' class="current"' : '';
389 $p_count = sprintf($count, esc_attr($this->getPublishedCount()));
390 $p_label = fpframework()->_('FPF_PUBLISHED') . $p_count;
391
392 // Unpublished
393 $t_class = in_array($current, ['unpublished'], true) ? ' class="current"' : '';
394 $t_count = sprintf($count, esc_attr($this->getUnpublishedCount()));
395 $t_label = fpframework()->_('FPF_UNPUBLISHED') . $t_count;
396
397 $views = [
398 'all' => sprintf('<a href="%s"%s>%s</a>', esc_url($url), $all_class, $all_label),
399 'published' => sprintf('<a href="%s"%s>%s</a>', esc_url(add_query_arg('status', 'published', $base_url)), $p_class, $p_label),
400 'unpublished' => sprintf('<a href="%s"%s>%s</a>', esc_url(add_query_arg('status', 'unpublished', $base_url)), $t_class, $t_label),
401 ];
402
403 return $views;
404 }
405
406 /**
407 * Returns how many published items we have.
408 *
409 * @return int
410 */
411 private function getPublishedCount()
412 {
413 return count(array_filter($this->total_items, function($submission) {
414 return $submission->state === '1';
415 }));
416 }
417
418 /**
419 * Returns how many unpublished items we have.
420 *
421 * @return int
422 */
423 private function getUnpublishedCount()
424 {
425 return count(array_filter($this->total_items, function($submission) {
426 return $submission->state === '0';
427 }));
428 }
429
430 /**
431 * When no items, display this message.
432 *
433 * @return void
434 */
435 public function no_items()
436 {
437 esc_html_e(firebox()->_('FB_NO_SUBMISSIONS_FOUND'));
438 }
439
440 /**
441 * Returns the form given its ID.
442 *
443 * @param int $id
444 *
445 * @return array
446 */
447 private function getForm($id = '')
448 {
449 if (!$id)
450 {
451 return;
452 }
453
454 $hash = md5('getForm_' . $id);
455
456 // check cache
457 if ($form = wp_cache_get($hash))
458 {
459 return $form;
460 }
461
462 $form = array_filter($this->forms, function($form_item) use ($id) {
463 return $id === $form_item['id'];
464 });
465 $form = reset($form);
466
467 wp_cache_set($hash, $form);
468
469 return $form;
470 }
471
472 /**
473 * Prepares items to be shown in table.
474 *
475 * @return void
476 */
477 function prepare_items()
478 {
479 $this->process_bulk_action();
480
481 $columns = $this->get_columns();
482
483 $sortable = $this->get_sortable_columns();
484
485 $this->_column_headers = [$columns, [], $sortable];
486
487 $offset = isset($_GET['paged']) ? max(0, intval($_GET['paged'] - 1) * $this->per_page) : 0;
488
489 $orderby = isset($_GET['orderby']) && in_array($_GET['orderby'], $this->getAllowedOrders()) ? sanitize_key($_GET['orderby']) : 'created_at';
490 $order = isset($_GET['order']) && in_array($_GET['order'], ['asc', 'desc']) ? sanitize_key($_GET['order']) : 'desc';
491 $orderby = $orderby . ' ' . $order;
492
493 $payload = [
494 'where' => [
495 'form_id' => " = '" . esc_sql($this->selected_form_id) . "'"
496 ],
497 'offset' => $offset,
498 'limit' => $this->per_page,
499 'orderby' => $orderby
500 ];
501
502 $status = isset($_GET['status']) ? sanitize_key($_GET['status']) : false;
503 if ($status)
504 {
505 $payload['where'] = array_merge($payload['where'], [
506 'state = ' => "'" . esc_sql($status === 'published' ? 1 : 0) . "'"
507 ]);
508 }
509
510 $this->total_items = firebox()->tables->submission->getResults([
511 'where' => [
512 'form_id' => " = '" . esc_sql($this->selected_form_id) . "'"
513 ]
514 ], true);
515
516 $total_items_count = count($this->total_items);
517
518 $this->items = $total_items_count ? firebox()->tables->submission->getResults($payload) : [];
519
520 if ($this->items)
521 {
522 // Set submission fields values
523 foreach ($this->items as &$item)
524 {
525 // Find field values
526 $meta = firebox()->tables->submissionmeta->getResults([
527 'where' => [
528 'submission_id' => " = " . esc_sql($item->id)
529 ]
530 ]);
531 $item->meta = $meta;
532 }
533
534 $this->set_pagination_args([
535 'total_items' => $total_items_count,
536 'per_page' => $this->per_page,
537 'total_pages' => ceil($total_items_count / $this->per_page),
538 ]);
539 }
540 }
541
542 /**
543 * Generates the table navigation above or below the table
544 *
545 * Overriden.
546 *
547 * @param string $which
548 *
549 * @return void
550 */
551 protected function display_tablenav($which)
552 {
553 if ('top' === $which)
554 {
555 wp_nonce_field('bulk-' . $this->_args['plural'], '_wpnonce', false, true);
556 }
557 ?>
558 <div class="tablenav <?php echo esc_attr($which); ?>">
559
560 <?php if ($this->has_items()): ?>
561 <div class="alignleft actions bulkactions">
562 <?php $this->bulk_actions($which); ?>
563 </div>
564 <?php
565 endif;
566 $this->extra_tablenav($which);
567 $this->pagination($which);
568 ?>
569
570 <br class="clear" />
571 </div>
572 <?php
573 }
574 }