PluginProbe
FireBox – WooCommerce Popup Builder, Exit Intent Popup, Email Optin & Cart Abandonment / 3.1.14
FireBox – WooCommerce Popup Builder, Exit Intent Popup, Email Optin & Cart Abandonment v3.1.14
3.1.14 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 All 123 releases
← All changes | Inc/Core/Admin/Admin.php +831 -48 1.0.4 → 3.1.14 View file →
@@ -1,12 +1,12 @@
1 1 <?php
2 2 /**
3 3 * @package FireBox
4 - * @version 1.0.4 Free
4 + * @version 3.1.14 Free
5 5 *
6 6 * @author FirePlugins <[email protected]>
7 7 * @link https://www.fireplugins.com
8 - * @copyright Copyright © 2021 FirePlugins All Rights Reserved
8 + * @copyright Copyright © 2026 FirePlugins All Rights Reserved
9 9 * @license GNU GPLv3 <http://www.gnu.org/licenses/gpl.html> or later
10 10 */
11 11
12 12 namespace FireBox\Core\Admin;
@@ -36,8 +36,27 @@
36 36 * Admin constructor
37 37 */
38 38 public function __construct()
39 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 +
40 59 // init dependencies
41 60 $this->initDependencies();
42 61
43 62 // Admin Page Settings
@@ -47,46 +66,555 @@
47 66 $this->handleActions();
48 67
49 68 // run filters
50 69 $this->handleFilters();
70 +
71 + add_action('save_post', [$this, 'onSave'], 20);
51 72 }
52 73
53 74 /**
54 - * Load admin dependencies.
75 + * On Save, clear the campaign cookie if closing behavior > when closed is set to "never".
55 76 *
77 + * @param string $post_id
78 + *
56 79 * @return void
57 80 */
58 - private function initDependencies()
81 + public function onSave($post_id)
59 82 {
60 - $this->library = firebox()->library;
83 + if (!isset($_POST['post_type']) || $_POST['post_type'] !== 'firebox')
84 + {
85 + return;
86 + }
61 87
62 - // Update Notice
63 - $valid_pages = [
64 - 'firebox',
65 - 'firebox-analytics',
66 - 'firebox-import',
67 - 'firebox-settings'
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'
68 261 ];
69 - $updateNotice = new \FPFramework\Admin\Includes\UpdateNotice(
70 - firebox()->plugin_slug,
71 - firebox()->plugin_name,
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 + [],
72 438 FBOX_VERSION,
73 - $valid_pages
439 + false
74 440 );
75 - $updateNotice->init();
441 + wp_enqueue_style('firebox-admin-lite');
442 + }
443 +
76 444
77 - // Top Bar Navigation
78 - new Includes\TopBarNavigation();
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);
79 449
80 - // Review Reminder
81 - new \FPFramework\Admin\Includes\ReviewReminder(
82 - firebox()->plugin_slug,
83 - firebox()->plugin_name,
84 - FBOX_MEDIA_ADMIN_URL
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
85 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);
86 571 }
87 572
88 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 + /**
89 617 * Runs all Admin Actions
90 618 *
91 619 * @return void
92 620 */
@@ -91,15 +619,31 @@
91 619 * @return void
92 620 */
93 621 private function handleActions()
94 622 {
95 - add_action('admin_enqueue_scripts', [$this, 'registerMedia'], 20);
623 + add_action('admin_enqueue_scripts', [$this, 'registerGlobalMedia'], 20);
96 624
97 625
98 - add_action('plugin_action_links_' . plugin_basename(FBOX_PLUGIN_BASE_FILE), [$this, 'plugin_action_links']);
626 + add_filter('plugin_action_links_' . plugin_basename(FBOX_PLUGIN_BASE_FILE), [$this, 'plugin_action_links']);
627 +
628 + }
99 629
100 - add_action('fpframework/admin/template/footer/nav_links', [$this, 'add_admin_page_template_footer_nav_links']);
101 -
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);
102 646 }
103 647
104 648
105 649 /**
@@ -112,35 +656,45 @@
112 656 */
113 657 public function plugin_action_links($links)
114 658 {
115 659 $links = array_merge( $links, array(
116 - '<a href="' . FBOX_GO_PRO_URL . '" class="firebox-go-pro-link" title="' . fpframework()->_('FPF_UNLOCK_MORE_FEATURES_WITH_PRO_READ_MORE') . '">' . fpframework()->_('FPF_GO_PRO') . '</a>'
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>'
117 661 ) );
118 662
119 663 return $links;
120 664 }
665 +
121 666
122 667 /**
123 - * Adds links to the admin template footer nav links
668 + * Runs all Admin Filters
124 669 *
125 670 * @return void
126 671 */
127 - public function add_admin_page_template_footer_nav_links()
672 + private function handleFilters()
128 673 {
129 - ?>
130 - <li><a href="https://www.fireplugins.com/<?php echo esc_attr(firebox()->plugin_slug); ?>" target="_blank"><?php echo esc_html(fpframework()->_('FPF_GET_PRO_FEATURES')); ?></a></li>
131 - <?php
674 + add_filter('admin_body_class', [$this, 'setPluginPageBodyClass']);
675 + add_filter('plugin_row_meta' , [$this, 'addPluginMetaLinks'], 10, 4);
132 676 }
133 -
134 677
135 678 /**
136 - * Runs all Admin Filters
679 + * Adds extra links to the plugins page.
137 680 *
138 - * @return void
681 + * @param array $links
682 + * @param string $file
683 + * @param array $plugin_data
684 + * @param string $status
685 + *
686 + * @return array
139 687 */
140 - private function handleFilters()
688 + public function addPluginMetaLinks($links, $file, $plugin_data, $status)
141 689 {
142 - add_filter('admin_body_class', [$this, 'setPluginPageBodyClass']);
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;
143 697 }
144 698
145 699 /**
146 700 * Sets a class to the body of the FireBox Admin Pages
@@ -160,8 +714,16 @@
160 714 {
161 715 $classes .= ' fpf-controller-page';
162 716 }
163 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 +
164 726 return $classes;
165 727 }
166 728
167 729 /**
@@ -170,9 +732,9 @@
170 732 * @return boolean
171 733 */
172 734 private function isPluginPage()
173 735 {
174 - if ($this->getPageNow() == 'edit.php' && isset($_GET['post_type']) && $_GET['post_type'] == 'firebox')
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
175 737 {
176 738 return true;
177 739 }
178 740
@@ -185,13 +747,8 @@
185 747 {
186 748 return true;
187 749 }
188 750
189 - if (current_user_can('manage_options'))
190 - {
191 - return true;
192 - }
193 -
194 751 return false;
195 752 }
196 753
197 754 /**
@@ -228,9 +785,9 @@
228 785 * Registers CSS and JS files
229 786 *
230 787 * @return void
231 788 */
232 - public function registerMedia()
789 + public function registerMediaAdminPages()
233 790 {
234 791 $this->registerStyles();
235 792 $this->registerScripts();
236 793 }
@@ -253,8 +810,25 @@
253 810 FBOX_VERSION,
254 811 false
255 812 );
256 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);
257 831 }
258 832
259 833 /**
260 834 * Registers admin scripts.
@@ -262,11 +836,220 @@
262 836 * @return void
263 837 */
264 838 public function registerScripts()
265 839 {
840 + wp_register_script('firebox-admin', false);
841 + wp_enqueue_script('firebox-admin');
842 +
843 +
844 +
266 845 $data = array(
267 - 'media_url' => FBOX_MEDIA_URL
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 + ]
268 1001 );
269 1002
270 - wp_localize_script('fpframework-admin', 'fbox_admin_js_object', $data);
1003 + wp_localize_script('firebox-admin', 'fbox_admin_js_object', $data);
271 1004 }
272 -}
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 +}