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 +820 -50 1.1.0 → 3.1.14 View file →
@@ -1,12 +1,12 @@
1 1 <?php
2 2 /**
3 3 * @package FireBox
4 - * @version 1.1.0 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 © 2022 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,48 +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 - new Media();
61 -
62 - $this->library = firebox()->library;
83 + if (!isset($_POST['post_type']) || $_POST['post_type'] !== 'firebox')
84 + {
85 + return;
86 + }
63 87
64 - // Update Notice
65 - $valid_pages = [
66 - 'firebox',
67 - 'firebox-analytics',
68 - 'firebox-import',
69 - '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'
70 261 ];
71 - $updateNotice = new \FPFramework\Admin\Includes\UpdateNotice(
72 - firebox()->plugin_slug,
73 - 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 + [],
74 438 FBOX_VERSION,
75 - $valid_pages
439 + false
76 440 );
77 - $updateNotice->init();
441 + wp_enqueue_style('firebox-admin-lite');
442 + }
443 +
78 444
79 - // Top Bar Navigation
80 - 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);
81 449
82 - // Review Reminder
83 - new \FPFramework\Admin\Includes\ReviewReminder(
84 - firebox()->plugin_slug,
85 - firebox()->plugin_name,
86 - 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
87 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);
88 571 }
89 572
90 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 + /**
91 617 * Runs all Admin Actions
92 618 *
93 619 * @return void
94 620 */
@@ -93,15 +619,31 @@
93 619 * @return void
94 620 */
95 621 private function handleActions()
96 622 {
97 - add_action('admin_enqueue_scripts', [$this, 'registerMedia'], 20);
623 + add_action('admin_enqueue_scripts', [$this, 'registerGlobalMedia'], 20);
98 624
99 625
100 - 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 + }
101 629
102 - add_action('fpframework/admin/template/footer/nav_links', [$this, 'add_admin_page_template_footer_nav_links']);
103 -
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);
104 646 }
105 647
106 648
107 649 /**
@@ -114,35 +656,45 @@
114 656 */
115 657 public function plugin_action_links($links)
116 658 {
117 659 $links = array_merge( $links, array(
118 - '<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>'
119 661 ) );
120 662
121 663 return $links;
122 664 }
665 +
123 666
124 667 /**
125 - * Adds links to the admin template footer nav links
668 + * Runs all Admin Filters
126 669 *
127 670 * @return void
128 671 */
129 - public function add_admin_page_template_footer_nav_links()
672 + private function handleFilters()
130 673 {
131 - ?>
132 - <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>
133 - <?php
674 + add_filter('admin_body_class', [$this, 'setPluginPageBodyClass']);
675 + add_filter('plugin_row_meta' , [$this, 'addPluginMetaLinks'], 10, 4);
134 676 }
135 -
136 677
137 678 /**
138 - * Runs all Admin Filters
679 + * Adds extra links to the plugins page.
139 680 *
140 - * @return void
681 + * @param array $links
682 + * @param string $file
683 + * @param array $plugin_data
684 + * @param string $status
685 + *
686 + * @return array
141 687 */
142 - private function handleFilters()
688 + public function addPluginMetaLinks($links, $file, $plugin_data, $status)
143 689 {
144 - 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;
145 697 }
146 698
147 699 /**
148 700 * Sets a class to the body of the FireBox Admin Pages
@@ -162,8 +714,16 @@
162 714 {
163 715 $classes .= ' fpf-controller-page';
164 716 }
165 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 +
166 726 return $classes;
167 727 }
168 728
169 729 /**
@@ -172,9 +732,9 @@
172 732 * @return boolean
173 733 */
174 734 private function isPluginPage()
175 735 {
176 - 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
177 737 {
178 738 return true;
179 739 }
180 740
@@ -187,13 +747,8 @@
187 747 {
188 748 return true;
189 749 }
190 750
191 - if (current_user_can('manage_options'))
192 - {
193 - return true;
194 - }
195 -
196 751 return false;
197 752 }
198 753
199 754 /**
@@ -230,9 +785,9 @@
230 785 * Registers CSS and JS files
231 786 *
232 787 * @return void
233 788 */
234 - public function registerMedia()
789 + public function registerMediaAdminPages()
235 790 {
236 791 $this->registerStyles();
237 792 $this->registerScripts();
238 793 }
@@ -256,8 +811,18 @@
256 811 false
257 812 );
258 813 wp_enqueue_style('firebox-admin');
259 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 +
260 825 $css = '
261 826 :root {
262 827 --fpf-templates-library-header-logo: url(' . FBOX_MEDIA_ADMIN_URL . 'images/logo.svg);
263 828 }
@@ -274,12 +839,217 @@
274 839 {
275 840 wp_register_script('firebox-admin', false);
276 841 wp_enqueue_script('firebox-admin');
277 842
843 +
844 +
278 845 $data = array(
279 - 'media_url' => FBOX_MEDIA_URL,
280 - 'admin_url' => get_admin_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 + ]
281 1001 );
282 1002
283 1003 wp_localize_script('firebox-admin', 'fbox_admin_js_object', $data);
284 1004 }
285 -}
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 +}