PluginProbe
FireBox – WooCommerce Popup Builder, Exit Intent Popup, Email Optin & Cart Abandonment / 2.1.37
FireBox – WooCommerce Popup Builder, Exit Intent Popup, Email Optin & Cart Abandonment v2.1.37
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 / FB / Box.php

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

756 lines 16.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 2.1.37 Free
5 *
6 * @author FirePlugins <info@fireplugins.com>
7 * @link https://www.fireplugins.com
8 * @copyright Copyright © 2025 FirePlugins All Rights Reserved
9 * @license GNU GPLv3 <http://www.gnu.org/licenses/gpl.html> or later
10 */
11
12 namespace FireBox\Core\FB;
13
14 if (!defined('ABSPATH'))
15 {
16 exit; // Exit if accessed directly.
17 }
18
19 use FireBox\Core\Helpers\BoxHelper;
20 use FPFramework\Libs\Registry;
21 use FPFramework\Helpers\Fields\DimensionsHelper;
22 use FPFramework\Helpers\CSS;
23
24 class Box
25 {
26 /**
27 * Send useful JS snippet once in first box
28 *
29 * @var boolean
30 */
31 static $loadedLocalizedScript = false;
32
33 /**
34 * The box.
35 *
36 * @param object
37 */
38 private $box = null;
39
40 /**
41 * Factory
42 *
43 * @var Factory
44 */
45 private $factory = null;
46
47 /**
48 * FireBox settings.
49 *
50 * @var object
51 */
52 private $params = null;
53
54 /**
55 * Popup CSS.
56 *
57 * @var CSS
58 */
59 public $css = null;
60
61 /**
62 * Constructor.
63 *
64 * @param object $box
65 * @param object $factory
66 *
67 * @return void
68 */
69 public function __construct($box = null, $factory = null)
70 {
71 if ($box)
72 {
73 $this->box = $this->prepareConstructorBox($box);
74 }
75
76 if (!$factory)
77 {
78 $factory = new \FPFramework\Base\Factory();
79 }
80 $this->factory = $factory;
81
82 $this->params = new Registry(BoxHelper::getParams());
83 }
84
85 /**
86 * Allow to set either a box ID or box object
87 * and we then set the box object.
88 *
89 * @param mixed $box
90 *
91 * @return object
92 */
93 private function prepareConstructorBox($box)
94 {
95 if (!is_object($box))
96 {
97 $box = $this->get($box);
98 }
99
100 return $box;
101 }
102
103 /**
104 * Get a box.
105 *
106 * @param int $id
107 * @param string $status
108 *
109 * @return object
110 */
111 public function get($id = null, $status = null)
112 {
113 if (!$id)
114 {
115 return;
116 }
117
118 $payload = [
119 'where' => [
120 'ID' => ' = ' . esc_sql(intval($id)),
121 'post_type' => " = 'firebox'"
122 ]
123 ];
124
125 // apply status if given
126 if ($status)
127 {
128 $payload['where']['post_status'] = ' = \'' . esc_sql($status) . '\'';
129 }
130
131 if (!$box = firebox()->tables->box->getResults($payload))
132 {
133 return [];
134 }
135
136 if (!isset($box[0]))
137 {
138 return [];
139 }
140
141 $this->box = $box[0];
142
143 // get meta options for box
144 $meta = \FireBox\Core\Helpers\BoxHelper::getMeta($id);
145 $this->box->params = new Registry($meta);
146
147 return $this->box;
148 }
149
150 /**
151 * Renders the box.
152 *
153 * @return void
154 */
155 public function render()
156 {
157 // Check Publishing Assignments
158 if (!$this->pass())
159 {
160 return false;
161 }
162
163 $fbox = $this->box;
164
165 /**
166 * Runs before rendering the box.
167 */
168 do_action('firebox/box/before_render', $this->box);
169
170 $this->prepare();
171
172 $css = $this->getCustomCSS();
173
174 add_action('wp_enqueue_scripts', function() use ($fbox, $css) {
175 // Loads all media files.
176 $this->loadBoxMedia($fbox);
177
178 // Load CSS
179 if ($css)
180 {
181 wp_add_inline_style('firebox', $css);
182 }
183
184
185 });
186
187 // Allow to manipulate the box before rendering
188 $this->box = apply_filters('firebox/box/edit', $this->box);
189
190 // payload
191 $payload = [
192 'box' => $this->box,
193 'params' => $this->params,
194 ];
195
196 // print campaign HTML
197 add_action('wp_footer', function() use ($payload) {
198 echo $this->getFinalCampaignHTML($payload); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
199 });
200
201 return true;
202 }
203
204 public function renderEmbed()
205 {
206 // Check Publishing Assignments
207 if (!$this->pass())
208 {
209 return false;
210 }
211
212 /**
213 * Runs before rendering the box.
214 */
215 do_action('firebox/box/before_render', $this->box);
216
217 $this->prepare();
218
219 // Loads all media files.
220 $this->loadBoxMedia($this->box);
221
222 $css = $this->getCustomCSS();
223
224 wp_register_style('fireboxStyle', false);
225 wp_enqueue_style('fireboxStyle');
226
227 // Load CSS
228 if ($css)
229 {
230 wp_add_inline_style('fireboxStyle', $css);
231 }
232
233
234
235 // Allow to manipulate the box before rendering
236 $this->box = apply_filters('firebox/box/edit', $this->box);
237
238 // payload
239 $payload = [
240 'box' => $this->box,
241 'params' => $this->params,
242 ];
243
244 // return box template
245 return $this->getFinalCampaignHTML($payload);
246 }
247
248 public function getFinalCampaignHTML($payload)
249 {
250 $html = firebox()->renderer->public->render('box', $payload, true);
251
252 /**
253 * Runs after rendering the box.
254 */
255 return apply_filters('firebox/box/after_render', $html, $payload['box']);
256 }
257
258 /**
259 * Gets the Custom CSS of the popup.
260 *
261 * @return string
262 */
263 public function getCustomCSS()
264 {
265 return $this->box->params->get('customcss', '');
266 }
267
268 /**
269 * Send a helpful object to JavaScript files
270 *
271 * @return void
272 */
273 public static function setJSObject()
274 {
275 if (self::$loadedLocalizedScript)
276 {
277 return;
278 }
279 self::$loadedLocalizedScript = true;
280
281 $data = [
282 'ajax_url' => admin_url('admin-ajax.php'),
283 'nonce' => wp_create_nonce('fbox_js_nonce'),
284 'site_url' => site_url('/'),
285 'referrer' => isset($_SERVER['HTTP_REFERER']) ? sanitize_url(wp_unslash($_SERVER['HTTP_REFERER'])) : ''
286 ];
287
288 wp_add_inline_script('firebox-main', 'const fbox_js_object = ' . wp_json_encode($data), 'before');
289 }
290
291 /**
292 * Load Box Media
293 *
294 * @return void
295 */
296 public function loadBoxMedia($box)
297 {
298 $box = new Registry($box);
299
300 /**
301 * Velocity
302 */
303 if ($this->params->get('loadVelocity', true))
304 {
305 wp_enqueue_script(
306 'firebox-velocity',
307 FBOX_MEDIA_PUBLIC_URL . 'js/vendor/velocity.js',
308 [],
309 FBOX_VERSION,
310 true
311 );
312 wp_enqueue_script(
313 'firebox-velocity-ui',
314 FBOX_MEDIA_PUBLIC_URL . 'js/vendor/velocity.ui.js',
315 ['firebox-velocity'],
316 FBOX_VERSION,
317 true
318 );
319
320 /**
321 * Animations
322 */
323 if (strpos($box->get('params.data.animationin'), 'firebox') !== false || strpos($box->get('params.data.animationout'), 'firebox') !== false)
324 {
325 wp_enqueue_script(
326 'firebox-animations',
327 FBOX_MEDIA_PUBLIC_URL . 'js/animations.js',
328 ['firebox-velocity-ui'],
329 FBOX_VERSION,
330 true
331 );
332 }
333 }
334
335 /**
336 * FireBox JS
337 */
338 wp_enqueue_script(
339 'firebox-main',
340 FBOX_MEDIA_PUBLIC_URL . 'js/firebox.js',
341 [],
342 FBOX_VERSION,
343 true
344 );
345
346 // Add Custom Javascript
347 $custom_code = $box->get('params.data.customcode', '');
348 if (is_string($custom_code) && !empty($custom_code))
349 {
350 $custom_code = html_entity_decode(stripslashes($custom_code));
351 wp_add_inline_script('firebox-main', $custom_code, 'after');
352 }
353
354 // run above the main JS script to run only once
355 self::setJSObject();
356
357 /**
358 * FireBox CSS
359 */
360 if ($this->params->get('loadCSS', true))
361 {
362 wp_enqueue_style(
363 'firebox',
364 FBOX_MEDIA_PUBLIC_URL . 'css/firebox.css',
365 [],
366 FBOX_VERSION
367 );
368 }
369
370 /**
371 * Page Slide mode JS
372 */
373 if ($box->get('params.data.mode') == 'pageslide')
374 {
375 wp_enqueue_script(
376 'firebox-pageslide-mode',
377 FBOX_MEDIA_PUBLIC_URL . 'js/pageslide_mode.js',
378 ['firebox-main'],
379 FBOX_VERSION,
380 true
381 );
382 }
383
384
385 }
386
387 /**
388 * Prepares the box before rendering
389 *
390 * @return void
391 */
392 public function prepare()
393 {
394 $this->css = new Styling\CSS($this->box);
395
396 $cParam = BoxHelper::getParams();
397 $cParam = new Registry($cParam);
398
399 $this->box->post_content = apply_filters('the_content', $this->box->post_content);
400
401 /* Classes */
402 $css_class = [
403 $this->box->ID
404 ];
405
406 if ($this->box->params->get('mode') === 'popup')
407 {
408 $position = $this->box->params->get('position', '');
409 $position = !is_string($position) ? '' : $position;
410 if ($position)
411 {
412 $css_class[] = $position;
413 }
414 }
415
416 $rtl = $this->box->params->get('rtl', '0');
417 if ($rtl == '1')
418 {
419 $css_class[] = 'rtl';
420 }
421
422 self::prefixCSSClasses($css_class);
423
424 // Class suffix
425 $classSuffix = $this->box->params->get('classsuffix', '');
426 $classSuffix = is_string($classSuffix) ? $classSuffix : '';
427
428 $css_class[] = $classSuffix;
429
430 $this->box->classes = $css_class;
431
432 // Box shadow
433 $boxshadow = (is_string($this->box->params->get('boxshadow', '1')) || is_int($this->box->params->get('boxshadow', '1'))) ? $this->box->params->get('boxshadow', '1') : '0';
434
435 $dialog_css_classes = [
436 $boxshadow != '0' ? 'shd' . $boxshadow : null
437 ];
438
439 // Align Content
440 $aligncontent = is_string($this->box->params->get('aligncontent')) ? explode(' ', $this->box->params->get('aligncontent')) : [];
441 $dialog_css_classes = array_merge($dialog_css_classes, $aligncontent);
442
443 self::prefixCSSClasses($dialog_css_classes);
444 $this->box->dialog_classes = $dialog_css_classes;
445
446 $trigger_point_methods = [
447 'pageready' => 'onPageReady',
448 'pageload' => 'onPageLoad',
449 'onclick' => 'onClick',
450 'elementHover' => 'onHover',
451 'ondemand' => 'onDemand',
452
453 ];
454
455 /* Other Settings */
456 $animation_duration = $this->box->params->get('duration') ? (float) $this->box->params->get('duration') : 0;
457
458 $delay = in_array($this->box->params->get('triggermethod'), ['floatingbutton', 'onexternallink']) ? 0 : (int) $this->box->params->get('triggerdelay') * 1000;
459
460 $trigger_method = (is_string($this->box->params->get('triggermethod'))) && array_key_exists($this->box->params->get('triggermethod'), $trigger_point_methods) ? $trigger_point_methods[$this->box->params->get('triggermethod')] : $this->box->params->get('triggermethod');
461
462 $trigger_element = is_scalar($this->box->params->get('triggerelement', '')) ? $this->box->params->get('triggerelement', '') : '';
463
464 // Use Namespaced classes for each trigger point and let them manipulate the settings dynamicaly.
465 $this->box->settings = [
466 'name' => $this->box->post_title,
467 'trigger' => $trigger_method,
468 'trigger_selector' => $trigger_method === 'onExternalLink' ? '' : rtrim($trigger_element, ','),
469 'delay' => $delay,
470
471 'animation_open' => $this->box->params->get('animationin'),
472 'animation_close' => $this->box->params->get('animationout'),
473 'animation_duration' => (float) $animation_duration * 1000,
474 'prevent_default' => (bool) $this->box->params->get('preventdefault', true),
475 'backdrop' => (bool) $this->box->params->get('overlay'),
476 'backdrop_color' => $this->box->params->get('overlay_color'),
477 'backdrop_click' => (bool) $this->box->params->get('overlayclick'),
478 'disable_page_scroll' => (bool) $this->box->params->get('preventpagescroll'),
479 'test_mode' => (bool) $this->box->params->get('testmode'),
480 'debug' => (bool) $cParam->get('debug', false),
481 'auto_focus' => (bool) $this->box->params->get('autofocus', false),
482 'mode' => $this->box->params->get('mode')
483 ];
484
485 // Apply Popup CSS
486 $this->box->params->set('customcss', $this->box->params->get('customcss') . $this->css->getCSS());
487
488 $this->replaceBoxSmartTags();
489 }
490
491 /**
492 * Replaces all box smart tags
493 *
494 * @return object
495 */
496 public function replaceBoxSmartTags()
497 {
498 $tags = new \FPFramework\Base\SmartTags\SmartTags();
499
500 // register FB Smart Tags
501 $tags->register('\FireBox\Core\SmartTags', FBOX_BASE_FOLDER . '/Inc/Core/SmartTags', $this->box);
502
503 $this->box = $tags->replace($this->box);
504 }
505
506 /**
507 * Checks if a box passes assignments
508 *
509 * @return boolean
510 */
511 public function pass()
512 {
513 if (!$this->box || !is_object($this->box))
514 {
515 return false;
516 }
517
518 // Check first local assignments
519 if (!$this->passLocalAssignments())
520 {
521 return false;
522 }
523
524 $displayConditionsType = $this->box->params->get('display_conditions_type', '');
525
526 // If empty, display popup sitewide
527 if (empty($displayConditionsType) || $displayConditionsType === 'all')
528 {
529 return true;
530 }
531
532 // Mirror Display Conditions of another popup.
533 if ($displayConditionsType == 'mirror' && $mirror_box_id = $this->box->params->get('mirror_box'))
534 {
535 $this->box->params->merge(self::getAssignmentsForMirroring($mirror_box_id));
536 }
537
538 // Get a recursive array of all rules
539 $rules = $this->box->params->get('rules', []);
540 $rules = is_string($rules) ? json_decode($rules, true) : json_decode(wp_json_encode($rules), true);
541
542 // If testmode is enabled disable the User Groups condition
543 if ($this->box->params->get('testmode'))
544 {
545 foreach ($rules as $key => &$group)
546 {
547 foreach ($group['rules'] as $_key => &$rule)
548 {
549 if (!isset($rule['name']) || empty($rule['name']))
550 {
551 continue;
552 }
553
554 if ($rule['name'] === 'WP\UserGroup')
555 {
556 unset($group['rules'][$_key]);
557 }
558 }
559 }
560 }
561
562 // Check framework based conditions
563 return \FPFramework\Base\Conditions\ConditionBuilder::pass($rules, $this->factory);
564 }
565
566 /**
567 * Check if a box passes local conditions
568 *
569 * @return boolean
570 */
571 private function passLocalAssignments()
572 {
573 $localAssignments = new \FireBox\Core\FB\Assignments($this, $this->factory);
574 return $localAssignments->passAll();
575 }
576
577 /**
578 * Gets assignments of mirrored box
579 *
580 * @param int $box_id
581 *
582 * @return object
583 */
584 private function getAssignmentsForMirroring($box_id)
585 {
586 $payload = [
587 'where' => [
588 'ID' => ' = ' . intval($box_id),
589 'post_status' => " = 'publish'",
590 'post_type' => " = 'firebox'"
591 ]
592 ];
593
594 // Load box
595 if (!$box = firebox()->tables->box->getResults($payload))
596 {
597 return;
598 }
599
600 $box = $box[0];
601
602 // get meta options for box
603 $meta = get_post_meta($box_id, 'fpframework_meta_settings', true);
604 $box->params = new Registry($meta);
605
606 return new Registry(['rules' => $box->params->get('rules')]);
607 }
608
609 /**
610 * Prefixes the CSS classes
611 *
612 * @param array $classes
613 * @param string $prefix
614 *
615 * @return void
616 */
617 private static function prefixCSSClasses(&$classes, $prefix = 'fb-')
618 {
619 $classes = array_filter($classes);
620
621 if (empty($classes))
622 {
623 return;
624 }
625
626 foreach ($classes as &$class)
627 {
628 $class = $prefix . $class;
629 }
630 }
631
632 /**
633 * Track box open
634 *
635 * @param integer $box_id
636 * @param string $page
637 * @param string $referrer
638 *
639 * @return void
640 */
641 public function logOpenEvent($box_id, $page = null, $referrer = null)
642 {
643 $box = $this->get($box_id);
644
645 // Do not track if statistics option is disabled
646 $track_open_event = (bool) (is_null($box->params->get('stats', null)) ? BoxHelper::getParams()->get('stats', 1) : $box->params->get('stats'));
647 if (!$track_open_event)
648 {
649 return;
650 }
651
652 return firebox()->log->track($box_id, 1, null, $page, $referrer);
653 }
654
655 /**
656 * Track box close
657 *
658 * @param integer $box_id
659 * @param integer $box_log_id
660 *
661 * @return void
662 */
663 public function logCloseEvent($box_id, $box_log_id)
664 {
665 $box = $this->get($box_id);
666
667 // Do not track if statistics option is disabled
668 $track_open_event = (bool) (is_null($box->params->get('stats', null)) ? BoxHelper::getParams()->get('stats', 1) : $box->params->get('stats'));
669 if (!$track_open_event)
670 {
671 return null;
672 }
673
674 firebox()->log->track($box_id, 2, $box_log_id);
675 }
676
677 /**
678 * Get total box impressions
679 *
680 * @param array $payload
681 *
682 * @return array
683 */
684 public function getTotalImpressions($payload)
685 {
686 $impressions = firebox()->tables->boxlog->getResults($payload);
687
688 return count($impressions);
689 }
690
691 /**
692 * Returns the cookie instance.
693 *
694 * @return mixed
695 */
696 public function getCookie()
697 {
698 if (!$this->box)
699 {
700 return;
701 }
702
703 return new Cookie($this->box);
704 }
705
706 /**
707 * Returns the box.
708 *
709 * @return object
710 */
711 public function getBox()
712 {
713 return $this->box;
714 }
715
716 /**
717 * Sets the box.
718 *
719 * @param object $box
720 *
721 * @return Box
722 */
723 public function setBox($box)
724 {
725 $this->box = $box;
726
727 return $this;
728 }
729
730 public function getParams()
731 {
732 return $this->params;
733 }
734
735 public function setParams($params)
736 {
737 $this->params = $params;
738
739 return $this;
740 }
741
742 public function getCampaignParams()
743 {
744 return isset($this->box->params) ? $this->box->params : null;
745 }
746
747 public function setCampaignParams($params)
748 {
749 if (isset($this->box->params))
750 {
751 $this->box->params = $params;
752 }
753
754 return $this;
755 }
756 }