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

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