PluginProbe
FireBox – WooCommerce Popup Builder, Exit Intent Popup, Email Optin & Cart Abandonment / trunk
FireBox – WooCommerce Popup Builder, Exit Intent Popup, Email Optin & Cart Abandonment vtrunk
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 / Admin / Admin.php

Admin.php in FireBox – WooCommerce Popup Builder, Exit Intent Popup, Email Optin & Cart Abandonment trunk, at Inc/Core/Admin/Admin.php

1,056 lines 30.7 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 3.1.13 Free
5 *
6 * @author FirePlugins <info@fireplugins.com>
7 * @link https://www.fireplugins.com
8 * @copyright Copyright © 2026 FirePlugins All Rights Reserved
9 * @license GNU GPLv3 <http://www.gnu.org/licenses/gpl.html> or later
10 */
11
12 namespace FireBox\Core\Admin;
13
14 if (!defined('ABSPATH'))
15 {
16 exit; // Exit if accessed directly.
17 }
18
19 class Admin
20 {
21 /**
22 * Admin Page Settings
23 *
24 * @var AdminPageSettings
25 */
26 private $pageSettings;
27
28 /**
29 * Library
30 *
31 * @var Library
32 */
33 public $library;
34
35 /**
36 * Admin constructor
37 */
38 public function __construct()
39 {
40 new \FireBox\Core\Notices\Ajax();
41
42 add_action('admin_init', [$this, 'maybeExportSubmsissions']);
43
44 add_action('admin_head', [$this, 'set_gutenberg_editor_logo']);
45
46 add_action('wp_trash_post', [$this, 'on_campaign_trash'], 10, 2);
47 add_action('untrash_post', [$this, 'on_campaign_untrash'], 10, 2);
48
49
50 add_action('admin_enqueue_scripts', [$this, 'global_backend_assets'], 20);
51
52
53 add_action('current_screen', [$this, 'current_screen']);
54
55 add_action('firebox/admin/content', [$this, 'showNotices'], -5);
56
57 add_action('admin_init', [$this, 'redirectAfterActivation']);
58
59 // init dependencies
60 $this->initDependencies();
61
62 // Admin Page Settings
63 $this->pageSettings = new AdminPageSettings();
64
65 // run actions
66 $this->handleActions();
67
68 // run filters
69 $this->handleFilters();
70
71 add_action('save_post', [$this, 'onSave'], 20);
72 }
73
74 /**
75 * On Save, clear the campaign cookie if closing behavior > when closed is set to "never".
76 *
77 * @param string $post_id
78 *
79 * @return void
80 */
81 public function onSave($post_id)
82 {
83 if (!isset($_POST['post_type']) || $_POST['post_type'] !== 'firebox')
84 {
85 return;
86 }
87
88 if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE)
89 {
90 return;
91 }
92
93 if ($parent_id = wp_is_post_revision($post_id))
94 {
95 $post_id = $parent_id;
96 }
97
98 $meta = get_post_meta($post_id, 'firebox_meta');
99
100 $assign_cookietype = isset($meta[0]['assign_cookietype']) ? $meta[0]['assign_cookietype'] : '';
101
102 if ($assign_cookietype === 'never')
103 {
104 $cookie = \FireBox\Core\Helpers\BoxHelper::cookiePrefix() . $post_id;
105
106 foreach (\FireBox\Core\Helpers\BoxHelper::cookiePathsToClear() as $path)
107 {
108 setcookie($cookie, '', time() - 3600, $path, \FireBox\Core\Helpers\BoxHelper::cookieDomain());
109 }
110 }
111 }
112
113 /**
114 * Set the FireBox logo in the Gutenberg editor.
115 *
116 * @return void
117 */
118 public function set_gutenberg_editor_logo()
119 {
120 if (get_post_type() !== 'firebox')
121 {
122 return;
123 }
124
125 ?>
126 <style>
127 @media screen and (min-width: 782px) {
128 .editor-header {
129 grid-template: auto / auto minmax(0, max-content) minmax(min-content, 1fr) 60px;
130 }
131
132 .editor-header:has(>.editor-header__center) {
133 grid-template: auto / auto minmax(min-content, 1fr) 2fr minmax(min-content, 1fr) 60px;
134 }
135 }
136 .editor-header__back-button .edit-post-fullscreen-mode-close,
137 .editor-header__back-button a.components-button.has-icon {
138 background: transparent !important;
139 background-image: url("<?php echo esc_url(FBOX_MEDIA_ADMIN_URL); ?>images/logo_full.svg") !important;
140 background-size: 105px !important;
141 margin-right: 0 !important;
142 margin-left: 17px !important;
143 background-repeat: no-repeat !important;
144 background-position: center center !important;
145 width: 120px !important;
146 }
147 .editor-header__back-button .edit-post-fullscreen-mode-close:before,
148 .editor-header__back-button .edit-post-fullscreen-mode-close:after,
149 .editor-header__back-button img,
150 .editor-header__back-button svg {
151 display: none !important;
152 }
153 </style>
154 <?php
155 }
156
157 public function maybeExportSubmsissions()
158 {
159 if (!isset($_GET['task']) || $_GET['task'] !== 'export')
160 {
161 return;
162 }
163
164 if (!isset($_GET['form_id']))
165 {
166 return;
167 }
168
169 if (!isset($_GET['page']) || $_GET['page'] !== 'firebox-submissions')
170 {
171 return;
172 }
173
174 // Authorization: only users who can view submissions may export them.
175 if (!current_user_can('read_fireboxes'))
176 {
177 return;
178 }
179
180 // CSRF: verify the nonce generated on the submissions list page.
181 check_admin_referer('firebox-export-submissions');
182
183 $form_id = sanitize_text_field(wp_unslash($_GET['form_id']));
184
185 $export = $this->getSubmissionsForExport($form_id);
186
187 if (!$export)
188 {
189 return;
190 }
191
192 /**
193 * The export holds every submission for the form, so it must not sit at a
194 * guessable path in the shared temp directory while it is being served.
195 * wp_tempnam() creates a unique file with restrictive permissions.
196 */
197 $name = sanitize_file_name($export['name']);
198 $download_name = 'submissions_' . $name . '_' . gmdate('Y-m-d_H-i-s') . '.csv';
199
200 $filename = wp_tempnam('firebox-export-' . $name);
201
202 if (!$filename)
203 {
204 return;
205 }
206
207 try
208 {
209 self::toCSV($export['rows'], $filename);
210
211 // Send the appropriate headers to force the download in the browser
212 header('Content-Description: File Transfer');
213 header('Content-Type: text/csv; charset=UTF-8');
214 header('Content-Disposition: attachment; filename="' . $download_name . '"');
215 header('X-Content-Type-Options: nosniff');
216 header('Expires: 0');
217 header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
218 header('Pragma: public');
219 header('Content-Length: ' . filesize($filename));
220
221 // Clear any buffered output so it doesn't corrupt the download
222 while (ob_get_level())
223 {
224 ob_end_clean();
225 }
226
227 flush();
228
229 readfile($filename);
230 }
231 finally
232 {
233 // Runs even if writing or streaming failed, so the PII never lingers on disk.
234 if (file_exists($filename))
235 {
236 unlink($filename);
237 }
238 }
239
240 exit;
241 }
242
243 /**
244 * Collects and prepares submission rows for CSV export.
245 * Returns the prepared rows (with the resolved form attached) or false.
246 *
247 * @param string $form_id
248 *
249 * @return array|false
250 */
251 protected function getSubmissionsForExport($form_id)
252 {
253 $payload = [
254 'where' => [
255 'form_id' => " = '" . sanitize_key($form_id) . "'",
256 'state' => ' = 1'
257 ],
258 'offset' => 0,
259 'limit' => 99999,
260 'orderby' => 'created_at ASC'
261 ];
262
263 if (!$submissions = firebox()->tables->submission->getResults($payload))
264 {
265 return false;
266 }
267
268 if (!$form = \FireBox\Core\Helpers\Form\Form::getFormByID($form_id, true))
269 {
270 return false;
271 }
272
273 // Fetch all submission meta in chunked IN() queries instead of one query per submission.
274 $submission_ids = wp_list_pluck($submissions, 'id');
275 $meta_by_submission = [];
276
277 foreach (array_chunk($submission_ids, 500) as $id_chunk)
278 {
279 $ids_in = implode(',', array_map('absint', $id_chunk));
280
281 $chunk_meta = firebox()->tables->submissionmeta->getResults([
282 'where' => [
283 'submission_id' => " IN (" . $ids_in . ")"
284 ]
285 ]);
286
287 foreach ($chunk_meta as $meta_item)
288 {
289 $meta_by_submission[$meta_item->submission_id][] = $meta_item;
290 }
291 }
292
293 $prepared = [];
294
295 foreach ($submissions as $item)
296 {
297 $prepared_payload = [
298 'id' => $item->id,
299 'created' => get_date_from_gmt($item->created_at),
300 'state' => $item->state === '1' ? 'Published' : 'Unpublished'
301 ];
302
303 $meta = isset($meta_by_submission[$item->id]) ? $meta_by_submission[$item->id] : [];
304
305 if ($meta && $form['fields'])
306 {
307 foreach ($form['fields'] as $field)
308 {
309 foreach ($meta as $meta_item)
310 {
311 if ($field->getOptionValue('id') === $meta_item->meta_key)
312 {
313 $prepared_payload[$field->getOptionValue('name')] = $field->prepareValue($meta_item->meta_value);
314 }
315 }
316 }
317 }
318
319 $prepared[] = $prepared_payload;
320 }
321
322 return ['name' => $form['name'], 'rows' => $prepared];
323 }
324
325 /**
326 * Create a CSV file with given data
327 *
328 * @param array $data The data to populate the file
329 * @param string $destination The path where the store the CSV file
330 * @param bool $append If true, given data will be appended to the end of the file.
331 * @param boolean $excel_security If enabled, certain row values will be prefixed by a tab to avoid any CSV injection.
332 *
333 * @return void
334 */
335 private static function toCSV($data, $destination, $append = false, $excel_security = true, $check_for_duplicates = true)
336 {
337 $resource = fopen($destination, $append ? 'a+' : 'w');
338
339 if (!$append)
340 {
341 // Support UTF-8 on Microsoft Excel
342 fputs($resource, "\xEF\xBB\xBF");
343
344 // Add column names in the first line
345 fputcsv($resource, array_keys($data[0]), ',', '"', '\\');
346 }
347
348 // Get CSV content
349 $existingRows = [];
350 if ($append && $check_for_duplicates)
351 {
352 while (($existingData = fgetcsv($resource)) !== false)
353 {
354 $existingRows[(int) $existingData[0]] = $existingData;
355 }
356 }
357
358 foreach ($data as $row)
359 {
360 if (!empty($existingRows) && isset($row['id']) && array_key_exists($row['id'], $existingRows))
361 {
362 continue;
363 }
364
365 // Prevent CSV Injection: https://vel.joomla.org/articles/2140-introducing-csv-injection
366 if ($excel_security)
367 {
368 foreach ($row as &$value)
369 {
370 $value = is_array($value) ? implode(', ', $value) : $value;
371
372 $firstChar = substr($value, 0, 1);
373
374 // Prefixe values starting with a =, +, - or @ by a tab character
375 if (in_array($firstChar, array('=', '+', '-', '@')))
376 {
377 $value = ' ' . $value;
378 }
379 }
380 }
381
382 fputcsv($resource, $row, ',', '"', '\\');
383 }
384
385 fclose($resource);
386 }
387
388 /**
389 * Fires when a campaign is trashed.
390 *
391 * @param int $post_id
392 * @param string $previous_status
393 *
394 * @return void
395 */
396 public function on_campaign_trash($post_id, $previous_status)
397 {
398 $post_type = get_post_type($post_id);
399 $post_status = get_post_status($post_id);
400
401 if ($post_type === 'firebox' && $post_status === 'draft')
402 {
403 \FPFramework\Libs\AdminNotice::displaySuccess(firebox()->_('FB_CAMPAIGN_HAS_BEEN_TRASHED'));
404 }
405 }
406
407 /**
408 * Fires when a campaign is untrashed.
409 *
410 * @param int $post_id
411 * @param string $previous_status
412 *
413 * @return void
414 */
415 public function on_campaign_untrash($post_id, $previous_status)
416 {
417 $post_type = get_post_type($post_id);
418 $post_status = get_post_status($post_id);
419
420 if ($post_type === 'firebox' && $post_status === 'trash')
421 {
422 \FPFramework\Libs\AdminNotice::displaySuccess(firebox()->_('FB_CAMPAIGN_HAS_BEEN_RESTORED'));
423 }
424 }
425
426 public function showNotices()
427 {
428 \FireBox\Core\Notices\Notices::getInstance()->show();
429 }
430
431
432 public function global_backend_assets()
433 {
434 wp_register_style(
435 'firebox-admin-lite',
436 FBOX_MEDIA_ADMIN_URL . 'css/lite.css',
437 [],
438 FBOX_VERSION,
439 false
440 );
441 wp_enqueue_style('firebox-admin-lite');
442 }
443
444
445 public function current_screen($screen)
446 {
447 add_action('admin_enqueue_scripts', [$this, 'registerEditorMedia'], 11);
448 add_action('enqueue_block_assets', [$this, 'registerCampaignEditorAssets'], 12);
449
450 // Check for classic editor with firebox post type
451 if (isset($screen->id) && $screen->id === 'firebox' && !$screen->is_block_editor) {
452 add_action('admin_notices', [$this, 'showClassicEditorNotice']);
453 }
454
455 $allowed_pages = [
456 'toplevel_page_firebox',
457 'firebox_page_firebox-campaigns',
458 'firebox_page_firebox-analytics',
459 'firebox_page_firebox-submissions',
460 'firebox_page_firebox-settings',
461 'firebox_page_firebox-import'
462 ];
463
464 if (isset($screen->id) && in_array($screen->id, $allowed_pages))
465 {
466 add_action('admin_enqueue_scripts', [$this, 'registerMediaAdminPages'], 20);
467
468 add_filter('admin_footer_text', [$this, 'admin_footer_text']);
469 }
470 }
471
472 /**
473 * Shows a notice when using classic editor with firebox post type
474 *
475 * @return void
476 */
477 public function showClassicEditorNotice()
478 {
479 ?>
480 <div class="notice notice-warning">
481 <p><?php echo esc_html(firebox()->_('FB_CLASSIC_EDITOR_NOT_SUPPORTED')); ?></p>
482 </div>
483 <?php
484 }
485
486 public function registerEditorMedia()
487 {
488 wp_register_script('firebox-admin-editor', false);
489 wp_enqueue_script('firebox-admin-editor');
490
491 $data = [
492 'media_url' => FBOX_MEDIA_URL,
493 'timezone' => $this->getTimezone(),
494 'license_type' => FBOX_LICENSE_TYPE,
495 'license_plan' => FBOX_LICENSE_PLAN,
496 'langs' => [
497 'LITE' => fpframework()->_('FPF_LITE'),
498 ]
499 ];
500
501 wp_localize_script('firebox-admin-editor', 'fbox_admin_editor_js_object', $data);
502 }
503
504 public function registerCampaignEditorAssets()
505 {
506 if (!is_admin())
507 {
508 return;
509 }
510
511 // Enqueue block editor style only in Gutenberg editor
512 if (!function_exists('get_current_screen'))
513 {
514 return;
515 }
516
517 $screen = get_current_screen();
518 if (!$screen->is_block_editor)
519 {
520 return;
521 }
522
523 wp_enqueue_script(
524 'firebox-helper-store',
525 FBOX_MEDIA_ADMIN_URL . 'js/blocks/helper_store.js',
526 ['wp-data'],
527 FBOX_VERSION,
528 false
529 );
530
531 wp_enqueue_style(
532 'firebox-blocks',
533 FBOX_MEDIA_PUBLIC_URL . 'css/blocks.css',
534 [],
535 FBOX_VERSION
536 );
537
538 $css = '
539 :root {
540 --firebox-editor-background-image: url(' . FBOX_MEDIA_ADMIN_URL . 'images/browser-bg.png);
541 }
542 ';
543 wp_add_inline_style('firebox-blocks', $css);
544
545 if (get_post_type() !== 'firebox')
546 {
547 return;
548 }
549
550 wp_register_script('firebox-campaign-editor', false);
551 wp_enqueue_script('firebox-campaign-editor');
552
553 $data = [
554 'plugins' => [
555 'wpml_active' => \is_plugin_active('sitepress-multilingual-cms/sitepress.php'),
556 'edd_active' => \is_plugin_active('easy-digital-downloads/easy-digital-downloads.php') || \is_plugin_active('easy-digital-downloads-pro/easy-digital-downloads.php'),
557 'woo_active' => \is_plugin_active('woocommerce/woocommerce.php')
558 ],
559 'geolocation_updated' => !\FPFramework\Helpers\Geolocation::geoNeedsUpdate(),
560 'geolocation_update_url' => admin_url('admin.php?page=firebox-settings#geolocation'),
561 'geolocation_city_notice' => (new \FPFramework\Base\Conditions\Conditions\Geo\City())->getValueHint(),
562 'geolocation_country_notice' => (new \FPFramework\Base\Conditions\Conditions\Geo\Country())->getValueHint(),
563 'geolocation_region_notice' => (new \FPFramework\Base\Conditions\Conditions\Geo\Region())->getValueHint(),
564 'geolocation_continent_notice' => (new \FPFramework\Base\Conditions\Conditions\Geo\Continent())->getValueHint(),
565 'countries_list' => \FPFramework\Helpers\CountriesHelper::getCountriesList(),
566 'user_ip' => \FPFramework\Base\User::getIP(),
567 'currency' => $this->getCurrency()
568 ];
569
570 wp_localize_script('firebox-campaign-editor', 'firebox_campaign_editor', $data);
571 }
572
573 /**
574 * Returns the current eCommerce solution's currency.
575 *
576 * @return string
577 */
578 private function getCurrency()
579 {
580 $output = '';
581
582 $eddActive = \is_plugin_active('easy-digital-downloads/easy-digital-downloads.php') || \is_plugin_active('easy-digital-downloads-pro/easy-digital-downloads.php');
583 if ($eddActive)
584 {
585 $output = \edd_get_currency();
586 }
587 else
588 {
589 $wooActive = \is_plugin_active('woocommerce/woocommerce.php');
590 if ($wooActive)
591 {
592 $output = \get_woocommerce_currency();
593 }
594 }
595
596 return $output;
597 }
598
599 public function admin_footer_text()
600 {
601 return;
602 }
603
604 /**
605 * Load admin dependencies.
606 *
607 * @return void
608 */
609 private function initDependencies()
610 {
611 new Media();
612
613 $this->library = firebox()->library;
614 }
615
616 /**
617 * Runs all Admin Actions
618 *
619 * @return void
620 */
621 private function handleActions()
622 {
623 add_action('admin_enqueue_scripts', [$this, 'registerGlobalMedia'], 20);
624
625
626 add_filter('plugin_action_links_' . plugin_basename(FBOX_PLUGIN_BASE_FILE), [$this, 'plugin_action_links']);
627
628 }
629
630 public function registerGlobalMedia()
631 {
632 wp_register_style('firebox-global-admin', false);
633 wp_enqueue_style('firebox-global-admin');
634 $css = '
635 #adminmenu li.toplevel_page_firebox .wp-menu-image {
636 padding: 4px 0 0 0;
637 height: auto;
638 }
639 #adminmenu li.toplevel_page_firebox img {
640 width: 20px !important;
641 padding: 0;
642 padding-top: 3px !important;
643 }
644 ';
645 wp_add_inline_style('firebox-global-admin', $css);
646 }
647
648
649 /**
650 * Adds extra links to the Plugins page in the free version.
651 * - Upgrade to Pro button
652 *
653 * @param array $links
654 *
655 * @return array
656 */
657 public function plugin_action_links($links)
658 {
659 $links = array_merge( $links, array(
660 '<a href="' . sprintf(FBOX_GO_PRO_URL, 'pro') . '" class="firebox-go-pro-link" title="' . fpframework()->_('FPF_UNLOCK_MORE_FEATURES_WITH_PRO_READ_MORE') . '">' . firebox()->_('FB_UPGRADE_20_OFF') . '</a>'
661 ) );
662
663 return $links;
664 }
665
666
667 /**
668 * Runs all Admin Filters
669 *
670 * @return void
671 */
672 private function handleFilters()
673 {
674 add_filter('admin_body_class', [$this, 'setPluginPageBodyClass']);
675 add_filter('plugin_row_meta' , [$this, 'addPluginMetaLinks'], 10, 4);
676 }
677
678 /**
679 * Adds extra links to the plugins page.
680 *
681 * @param array $links
682 * @param string $file
683 * @param array $plugin_data
684 * @param string $status
685 *
686 * @return array
687 */
688 public function addPluginMetaLinks($links, $file, $plugin_data, $status)
689 {
690 if ($file === FBOX_PLUGIN_BASENAME)
691 {
692 $links['rate'] = '<a href="https://wordpress.org/support/plugin/firebox/reviews/#new-post" aria-label="' . esc_attr(firebox()->_('FB_RATE_FIREBOX')) . '" target="_blank">' . esc_html(firebox()->_('FB_RATE_FIREBOX')) . '</a>';
693 $links['support'] = '<a href="' . \FPFramework\Base\Functions::getUTMURL('https://www.fireplugins.com/contact/', '', 'misc', 'support') . '" aria-label="' . esc_attr(fpframework()->_('FPF_SUPPORT')) . '" target="_blank">' . esc_html(fpframework()->_('FPF_SUPPORT')) . '</a>';
694 }
695
696 return $links;
697 }
698
699 /**
700 * Sets a class to the body of the FireBox Admin Pages
701 *
702 * @return string
703 */
704 public function setPluginPageBodyClass($classes)
705 {
706 if (!$this->isPluginPage())
707 {
708 return $classes;
709 }
710
711 $classes .= ' fpf-admin-page fpf-firebox-page';
712
713 if ($this->isControllerPage())
714 {
715 $classes .= ' fpf-controller-page';
716 }
717
718 // Set admin template theme class
719 $fireplugins_theme = isset($_COOKIE['fireplugins_theme']) ? sanitize_key($_COOKIE['fireplugins_theme']) : 'light';
720 $classes .= ' ' . $fireplugins_theme;
721
722 // Set admin template sidebar toggle class
723 $sidebar_state = isset($_COOKIE['fireplugins_sidebar_state']) ? sanitize_key($_COOKIE['fireplugins_sidebar_state']) : 'expand';
724 $classes .= ' ' . ($sidebar_state === 'expand' ? 'fpf-admin-sidebar-expand' : 'fpf-admin-sidebar-shrink');
725
726 return $classes;
727 }
728
729 /**
730 * Checks if we are in a plugin page
731 *
732 * @return boolean
733 */
734 private function isPluginPage()
735 {
736 if (in_array($this->getPageNow(), ['edit.php', 'post-new.php']) && isset($_GET['post_type']) && $_GET['post_type'] == 'firebox') //phpcs:ignore WordPress.Security.NonceVerification.Recommended
737 {
738 return true;
739 }
740
741 if ($this->getPageNow() == 'post.php')
742 {
743 return true;
744 }
745
746 if ($this->isControllerPage())
747 {
748 return true;
749 }
750
751 return false;
752 }
753
754 /**
755 * Whether we are browsing a plugin page from the plugin's menu
756 *
757 * @return boolean
758 */
759 private function isControllerPage()
760 {
761 if (!firebox()->menu)
762 {
763 return false;
764 }
765
766 $current_plugin_page = fpframework()->getPluginPage();
767 $plugin_menu_items = firebox()->menu->getPluginMenuItems();
768
769 // Only set the class to the plugin pages
770 return $this->getPageNow() == 'admin.php' && in_array($current_plugin_page, $plugin_menu_items);
771 }
772
773 /**
774 * Returns page now
775 *
776 * @return string
777 */
778 protected function getPageNow()
779 {
780 global $pagenow;
781 return $pagenow;
782 }
783
784 /**
785 * Registers CSS and JS files
786 *
787 * @return void
788 */
789 public function registerMediaAdminPages()
790 {
791 $this->registerStyles();
792 $this->registerScripts();
793 }
794
795 /**
796 * Register admin styles.
797 *
798 * @return void
799 */
800 public function registerStyles()
801 {
802 // load dashicons
803 wp_enqueue_style('dashicons');
804
805 // firebox main admin css
806 wp_register_style(
807 'firebox-admin',
808 FBOX_MEDIA_ADMIN_URL . 'css/firebox.css',
809 [],
810 FBOX_VERSION,
811 false
812 );
813 wp_enqueue_style('firebox-admin');
814
815 // firebox admin design
816 wp_register_style(
817 'firebox-design-admin',
818 FBOX_MEDIA_ADMIN_URL . 'css/firebox_design.css',
819 [],
820 FBOX_VERSION,
821 false
822 );
823 wp_enqueue_style('firebox-design-admin');
824
825 $css = '
826 :root {
827 --fpf-templates-library-header-logo: url(' . FBOX_MEDIA_ADMIN_URL . 'images/logo.svg);
828 }
829 ';
830 wp_add_inline_style('firebox-admin', $css);
831 }
832
833 /**
834 * Registers admin scripts.
835 *
836 * @return void
837 */
838 public function registerScripts()
839 {
840 wp_register_script('firebox-admin', false);
841 wp_enqueue_script('firebox-admin');
842
843
844
845 $data = array(
846 'campaigns_item_new_url' => admin_url('post-new.php?post_type=firebox'),
847 'campaigns_list_url' => admin_url('admin.php?page=firebox-campaigns'),
848 'campaigns_item_edit_url' => admin_url('post.php?post={{ID}}&action=edit'),
849 'campaigns_item_analytics_url' => admin_url('admin.php?page=firebox-analytics&campaign={{ID}}'),
850 'campaigns_analytics_url' => admin_url('admin.php?page=firebox-analytics'),
851 'submissions_page' => admin_url('admin.php?page=firebox-submissions'),
852 'flags_url' => FBOX_PLUGIN_URL . 'Inc/Framework/media/admin/images/flags/{{FLAG}}.png',
853 'license_type' => FBOX_LICENSE_TYPE,
854 'license_plan' => FBOX_LICENSE_PLAN,
855
856
857 'langs' => [
858 'CAMPAIGN_INFO' => firebox()->_('FB_CAMPAIGN_INFO'),
859 'EDIT_CAMPAIGN' => firebox()->_('FB_EDIT_CAMPAIGN'),
860 'STATUS' => fpframework()->_('FPF_STATUS'),
861 'CREATED' => fpframework()->_('FPF_CREATED'),
862 'LAST_VIEWED' => firebox()->_('FB_LAST_VIEWED'),
863 'ACTIVE' => firebox()->_('FB_ACTIVE'),
864 'DISABLED' => fpframework()->_('FPF_DISABLED'),
865 'ID' => fpframework()->_('FPF_ID'),
866 'CAMPAIGN' => firebox()->_('FB_CAMPAIGN'),
867 'VIEW' => firebox()->_('FB_VIEW'),
868 'VIEWS' => firebox()->_('FB_VIEWS'),
869 'CLICK' => firebox()->_('FB_CLICK'),
870 'CLICKS' => firebox()->_('FB_CLICKS'),
871 'ACTIONS' => firebox()->_('FB_ACTIONS'),
872 'CONVERSION' => firebox()->_('FB_CONVERSION'),
873 'CONVERSIONS' => firebox()->_('FB_CONVERSIONS'),
874 'CONVERSION_RATE' => firebox()->_('FB_CONVERSION_RATE'),
875 'NO_DATA_AVAILABLE' => firebox()->_('FB_NO_DATA_AVAILABLE'),
876 'COULDNT_LOAD_DATA' => firebox()->_('FB_COULDNT_LOAD_DATA'),
877 'TRY_AGAIN' => firebox()->_('FB_TRY_AGAIN'),
878 'DISMISS' => firebox()->_('FB_DISMISS'),
879 'ERROR_OCCURRED_PLEASE_TRY_AGAIN' => fpframework()->_('FPF_ERROR_OCCURRED_PLEASE_TRY_AGAIN'),
880 'COUNTRIES' => fpframework()->_('FPF_COUNTRIES'),
881 'FLAG' => fpframework()->_('FPF_FLAG'),
882 'DEVICES' => fpframework()->_('FPF_DEVICES'),
883 'EVENTS' => fpframework()->_('FPF_EVENTS'),
884 'PERCENTAGE_DIFFERENCE_AGAINST_PREVIOUS_PERIOD' => firebox()->_('FB_PERCENTAGE_DIFFERENCE_AGAINST_PREVIOUS_PERIOD'),
885 'NO_CAMPAIGN_DATA_FOUND' => firebox()->_('FB_NO_CAMPAIGN_DATA_FOUND'),
886 'MOST_POPULAR_CAMPAIGNS' => firebox()->_('FB_MOST_POPULAR_CAMPAIGNS'),
887 'TOP_CAMPAIGNS' => firebox()->_('FB_TOP_CAMPAIGNS'),
888 'N/A' => fpframework()->_('FPF_N/A'),
889 'ALL_DAYS' => firebox()->_('FB_ALL_DAYS'),
890 'MONDAY' => firebox()->_('FB_MONDAY'),
891 'TUESDAY' => firebox()->_('FB_TUESDAY'),
892 'WEDNESDAY' => firebox()->_('FB_WEDNESDAY'),
893 'THURSDAY' => firebox()->_('FB_THURSDAY'),
894 'FRIDAY' => firebox()->_('FB_FRIDAY'),
895 'SATURDAY' => firebox()->_('FB_SATURDAY'),
896 'SUNDAY' => firebox()->_('FB_SUNDAY'),
897 'VIEW_HOURS' => firebox()->_('FB_VIEW_HOURS'),
898 'PATHS' => fpframework()->_('FPF_PATHS'),
899 'REFERRERS' => fpframework()->_('FPF_REFERRERS'),
900 'S' => fpframework()->_('FPF_S'),
901 'VIEW_CAMPAIGN_ANALYTICS' => firebox()->_('FB_VIEW_CAMPAIGN_ANALYTICS'),
902 'ACTIVATE' => fpframework()->_('FPF_ACTIVATE'),
903 'DEACTIVATE' => fpframework()->_('FPF_DEACTIVATE'),
904 'EDIT' => fpframework()->_('FPF_EDIT'),
905 'DELETE' => fpframework()->_('FPF_DELETE'),
906 'DUPLICATE' => fpframework()->_('FPF_DUPLICATE'),
907 'ARE_YOU_SURE_YOU_WANT_TO_DELETE_THIS_CAMPAIGN' => firebox()->_('FB_ARE_YOU_SURE_YOU_WANT_TO_DELETE_THIS_CAMPAIGN'),
908 'RECENT_CAMPAIGNS' => firebox()->_('FB_RECENT_CAMPAIGNS'),
909 'VIEW_ALL' => firebox()->_('FB_VIEW_ALL'),
910 'YOU_HAVENT_CREATED_ANY_CAMPAIGNS_YET' => firebox()->_('FB_YOU_HAVENT_CREATED_ANY_CAMPAIGNS_YET'),
911 'NEW_CAMPAIGN' => firebox()->_('FB_NEW_CAMPAIGN'),
912 'NUMBER_OF_VIEWS_IN_THE_LAST_30_DAYS' => firebox()->_('FB_NUMBER_OF_VIEWS_IN_THE_LAST_30_DAYS'),
913 'NUMBER_OF_CONVERSIONS_IN_THE_LAST_30_DAYS' => firebox()->_('FB_NUMBER_OF_CONVERSIONS_IN_THE_LAST_30_DAYS'),
914 'CONVERSION_RATE_IN_THE_LAST_30_DAYS' => firebox()->_('FB_CONVERSION_RATE_IN_THE_LAST_30_DAYS'),
915 'LOADING_CAMPAIGNS' => firebox()->_('FB_LOADING_CAMPAIGNS'),
916 'NO_CAMPAIGNS_FOUND' => firebox()->_('FB_NO_CAMPAIGNS_FOUND'),
917 'SEARCH_DOTS' => firebox()->_('FB_SEARCH_DOTS'),
918 'TODAY' => firebox()->_('FB_TODAY'),
919 'YESTERDAY' => firebox()->_('FB_YESTERDAY'),
920 'LAST_7_DAYS' => firebox()->_('FB_LAST_7_DAYS'),
921 'LAST_30_DAYS' => firebox()->_('FB_LAST_30_DAYS'),
922 'LAST_WEEK' => firebox()->_('FB_LAST_WEEK'),
923 'MONTH_TO_DATE' => firebox()->_('FB_MONTH_TO_DATE'),
924 'LAST_MONTH' => firebox()->_('FB_LAST_MONTH'),
925 'YEAR_TO_DATE' => firebox()->_('FB_YEAR_TO_DATE'),
926 'CUSTOM' => firebox()->_('FB_CUSTOM'),
927 'READ_MORE' => firebox()->_('FB_READ_MORE'),
928 'AVG_TIME_OPEN' => firebox()->_('FB_AVG_TIME_OPEN'),
929 'CONVERSION_RATE_TOOLTIP_DESC' => firebox()->_('FB_CONVERSION_RATE_TOOLTIP_DESC'),
930 'CONVERSIONS_TOOLTIP_DESC' => firebox()->_('FB_CONVERSIONS_TOOLTIP_DESC'),
931 'VS_PREVIOUS_PERIOD' => firebox()->_('FB_VS_PREVIOUS_PERIOD'),
932 'VIEWS_TOOLTIP_DESC' => firebox()->_('FB_VIEWS_TOOLTIP_DESC'),
933 'NO' => firebox()->_('FB_NO'),
934 'DATA_AVAILABLE' => firebox()->_('FB_DATA_AVAILABLE'),
935 'PERFORMANCE' => firebox()->_('FB_PERFORMANCE'),
936 'TRENDING_TEMPLATES' => firebox()->_('FB_TRENDING_TEMPLATES'),
937 'THERE_ARE_NO_TRENDING_TEMPLATES_TO_SHOW' => firebox()->_('FB_THERE_ARE_NO_TRENDING_TEMPLATES_TO_SHOW'),
938 'INSERT_TEMPLATE' => firebox()->_('FB_INSERT_TEMPLATE'),
939 'INSERT' => firebox()->_('FB_INSERT'),
940 'VIEW_ALL_ANALYTICS' => firebox()->_('FB_VIEW_ALL_ANALYTICS'),
941 'DAILY' => firebox()->_('FB_DAILY'),
942 'WEEKLY' => firebox()->_('FB_WEEKLY'),
943 'MONTHLY' => firebox()->_('FB_MONTHLY'),
944 'UPGRADE_TO_PRO' => fpframework()->_('FPF_UPGRADE_TO_PRO'),
945 'ALL_CAMPAIGNS' => firebox()->_('FB_ALL_CAMPAIGNS'),
946 'OVERVIEW' => fpframework()->_('FPF_OVERVIEW'),
947 'TO' => fpframework()->_('FPF_TO'),
948 'SHOWING_TOP_30_RESULTS' => firebox()->_('FB_SHOWING_TOP_30_RESULTS'),
949 'DAY_OF_THE_WEEK' => firebox()->_('FB_DAY_OF_THE_WEEK'),
950 'ANALYTICS' => fpframework()->_('FPF_ANALYTICS'),
951 'SALES_FUNNEL' => firebox()->_('FB_SALES_FUNNEL'),
952 'SALES_FUNNEL_LOCKED_COPY' => firebox()->_('FB_SALES_FUNNEL_LOCKED_COPY'),
953 'PURCHASE' => firebox()->_('FB_PURCHASE'),
954 'PURCHASES' => firebox()->_('FB_PURCHASES'),
955 'INTERACTIONS' => firebox()->_('FB_INTERACTIONS'),
956 'FUNNEL_VISUALIZATION' => firebox()->_('FB_FUNNEL_VISUALIZATION'),
957 'OVERALL_CONVERSION_RATE' => firebox()->_('FB_OVERALL_CONVERSION_RATE'),
958 'REVENUE_CONVERSIONS' => firebox()->_('FB_REVENUE_CONVERSIONS'),
959 'LITE' => fpframework()->_('FPF_LITE'),
960 'FREE' => fpframework()->_('FPF_FREE'),
961 'FROM' => firebox()->_('FB_FROM'),
962 'OF' => firebox()->_('FB_OF'),
963 'USERS' => firebox()->_('FB_USERS'),
964 'TOTAL' => firebox()->_('FB_TOTAL'),
965 'TOTAL_POPUP_IMPRESSIONS' => firebox()->_('FB_TOTAL_POPUP_IMPRESSIONS'),
966 'REVENUE' => firebox()->_('FB_REVENUE'),
967 'REVENUE_TOOLTIP_DESC' => firebox()->_('FB_REVENUE_TOOLTIP_DESC'),
968 'VIEW_THROUGH_REVENUE' => firebox()->_('FB_VIEW_THROUGH_REVENUE'),
969 'VIEW_THROUGH_REVENUE_TOOLTIP_DESC' => firebox()->_('FB_VIEW_THROUGH_REVENUE_TOOLTIP_DESC'),
970 'CONVERSION_THROUGH_REVENUE' => firebox()->_('FB_CONVERSION_THROUGH_REVENUE'),
971 'CONVERSION_THROUGH_REVENUE_TOOLTIP_DESC' => firebox()->_('FB_CONVERSION_THROUGH_REVENUE_TOOLTIP_DESC'),
972 'REVENUE_ROI' => firebox()->_('FB_REVENUE_ROI'),
973 'REVENUE_ROI_TOOLTIP_TITLE' => firebox()->_('FB_REVENUE_ROI_TOOLTIP_TITLE'),
974 'REVENUE_ROI_TOTAL_REVENUE_GENERATED' => firebox()->_('FB_REVENUE_ROI_TOTAL_REVENUE_GENERATED'),
975 'REVENUE_ROI_LITE_MESSAGE' => firebox()->_('FB_REVENUE_ROI_LITE_MESSAGE'),
976 'REVENUE_ROI_PRO_MESSAGE' => firebox()->_('FB_REVENUE_ROI_PRO_MESSAGE'),
977 'LAST_4_WEEKS' => firebox()->_('FB_LAST_4_WEEKS'),
978 'LAST_6_MONTHS' => firebox()->_('FB_LAST_6_MONTHS'),
979 'LAST_12_MONTHS' => firebox()->_('FB_LAST_12_MONTHS'),
980 'QUARTER_TO_DATE' => firebox()->_('FB_QUARTER_TO_DATE'),
981 'AVAILABLE_IN_PRO' => firebox()->_('FB_AVAILABLE_IN_PRO'),
982 'PLAN_COST' => firebox()->_('FB_PLAN_COST'),
983 'LIFETIME_REVENUE' => firebox()->_('FB_LIFETIME_REVENUE'),
984 'YOUR_ROI' => firebox()->_('FB_YOUR_ROI'),
985 'UNLOCK_REVENUE_ROI' => firebox()->_('FB_UNLOCK_REVENUE_ROI'),
986 'GROWTH' => firebox()->_('FB_GROWTH'),
987 'AVAILABLE_IN' => firebox()->_('FB_AVAILABLE_IN'),
988 'PRO' => firebox()->_('FB_PRO'),
989 'BASIC' => firebox()->_('FB_BASIC'),
990 'UPGRADE_TO_X' => fpframework()->_('FPF_UPGRADE_TO_X'),
991 'UPGRADE_TO_X_PLAN' => fpframework()->_('FPF_UPGRADE_TO_X_PLAN'),
992 'FEATURE_AVAILABLE_IN_X_PLAN' => firebox()->_('FB_FEATURE_AVAILABLE_IN_X_PLAN'),
993 'SORRY_FEATURE_NOT_AVAILABLE_IN_YOUR_PLAN' => fpframework()->_('FPF_SORRY_FEATURE_NOT_AVAILABLE_IN_YOUR_PLAN'),
994 'PRO_MODAL_IS_PRO_FEATURE' => fpframework()->_('FPF_PRO_MODAL_IS_PRO_FEATURE'),
995 'PRO_MODAL_WERE_SORRY' => fpframework()->_('FPF_PRO_MODAL_WERE_SORRY'),
996 'PRO_MODAL_PERCENTAGE_OFF' => fpframework()->_('FPF_PRO_MODAL_PERCENTAGE_OFF'),
997 'CLICKS_TOOLTIP_DESC' => firebox()->_('FB_CLICKS_TOOLTIP_DESC'),
998 'VIEW_REVENUE' => firebox()->_('FB_VIEW_REVENUE'),
999 'CONVERSION_REVENUE' => firebox()->_('FB_CONVERSION_REVENUE'),
1000 ]
1001 );
1002
1003 wp_localize_script('firebox-admin', 'fbox_admin_js_object', $data);
1004 }
1005
1006 /**
1007 * Returns the timezone in format: +-XX:XX
1008 *
1009 * @return string
1010 */
1011 private function getTimezone()
1012 {
1013 $offset = get_option('gmt_offset');
1014 $hours = (int) $offset;
1015 $minutes = abs(($offset - (int) $offset) * 60);
1016 return sprintf('%+03d:%02d', $hours, $minutes);
1017 }
1018
1019
1020
1021
1022
1023 /**
1024 * Redirect to FireBox dashboard after plugin activation
1025 *
1026 * @return void
1027 */
1028 public function redirectAfterActivation()
1029 {
1030 // Check if activation redirect option exists
1031 if (!get_option('firebox_activation_redirect'))
1032 {
1033 return;
1034 }
1035
1036 // Clear the option
1037 delete_option('firebox_activation_redirect');
1038
1039 // Only redirect on the plugins page
1040 if (!isset($_GET['activate'])) //phpcs:ignore WordPress.Security.NonceVerification.Recommended
1041 {
1042 return;
1043 }
1044
1045 // Prevent redirect if activating multiple plugins
1046 if (is_network_admin() || isset($_GET['activate-multi'])) //phpcs:ignore WordPress.Security.NonceVerification.Recommended
1047 {
1048 return;
1049 }
1050
1051 // Redirect to FireBox dashboard
1052 wp_safe_redirect(admin_url('admin.php?page=firebox'));
1053 exit;
1054 }
1055 }
1056