PluginProbe
FireBox – WooCommerce Popup Builder, Exit Intent Popup, Email Optin & Cart Abandonment / 3.1.5
FireBox – WooCommerce Popup Builder, Exit Intent Popup, Email Optin & Cart Abandonment v3.1.5
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 3.1.5, at Inc/Core/Admin/Admin.php

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