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

708 lines 16.3 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.0.6 Free
5 *
6 * @author FirePlugins <info@fireplugins.com>
7 * @link https://www.fireplugins.com
8 * @copyright Copyright © 2023 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;
161 }
162
163 $fbox = $this->box;
164
165 $this->prepare();
166
167 $css = $this->getCustomCSS();
168
169 add_action('wp_enqueue_scripts', function() use ($fbox, $css) {
170 // Loads all media files.
171 $this->loadBoxMedia($fbox);
172
173 // Load CSS
174 if ($css)
175 {
176 wp_add_inline_style('firebox', $css);
177 }
178
179
180 });
181
182 /**
183 * Runs before rendering the box.
184 */
185 do_action('firebox/box/before_render', $this->box);
186
187 // payload
188 $payload = [
189 'box' => $this->box,
190 'params' => $this->params,
191 ];
192
193 // return box template
194 add_action('wp_footer', function() use ($payload) {
195 echo firebox()->renderer->public->render('box', $payload, true);
196 });
197 }
198
199 /**
200 * Gets the Custom CSS of the popup.
201 *
202 * @return string
203 */
204 private function getCustomCSS()
205 {
206 return $this->box->params->get('customcss', '');
207 }
208
209 /**
210 * Send a helpful object to JavaScript files
211 *
212 * @return void
213 */
214 public static function setJSObject()
215 {
216 if (self::$loadedLocalizedScript)
217 {
218 return;
219 }
220 self::$loadedLocalizedScript = true;
221
222 $data = array(
223 'ajax_url' => admin_url('admin-ajax.php'),
224 'nonce' => wp_create_nonce('fbox_js_nonce'),
225 'site_url' => site_url('/'),
226 'referrer' => isset($_SERVER['HTTP_REFERER']) ? sanitize_text_field($_SERVER['HTTP_REFERER']) : ''
227 );
228
229 wp_localize_script('firebox', 'fbox_js_object', $data);
230 }
231
232 /**
233 * Load Box Media
234 *
235 * @return void
236 */
237 public function loadBoxMedia($box)
238 {
239 $box = new Registry($box);
240
241 // Add polyfills for Internet Explorer
242 $browser = $this->factory->getBrowser();
243 if ($browser && is_array($browser) && array_key_exists('name', $browser) && $browser['name'] === 'ie')
244 {
245 wp_enqueue_script(
246 'firebox-ie11-polyfill',
247 'https://polyfill.io/v3/polyfill.min.js?features=NodeList.prototype.forEach%2CElement.prototype.closest%2CArray.prototype.forEach%2CArray.prototype.find%2CIntersectionObserver%2CIntersectionObserverEntry',
248 [],
249 FBOX_VERSION,
250 true
251 );
252 }
253
254 /**
255 * Velocity
256 */
257 if ($this->params->get('loadVelocity', true))
258 {
259 wp_enqueue_script(
260 'firebox-velocity',
261 FBOX_MEDIA_PUBLIC_URL . 'js/vendor/velocity.js',
262 [],
263 FBOX_VERSION,
264 true
265 );
266 wp_enqueue_script(
267 'firebox-velocity-ui',
268 FBOX_MEDIA_PUBLIC_URL . 'js/vendor/velocity.ui.js',
269 [],
270 FBOX_VERSION,
271 true
272 );
273
274 /**
275 * Animations
276 */
277 if (strpos($box->get('params.data.animationin'), 'firebox') !== false || strpos($box->get('params.data.animationout'), 'firebox') !== false)
278 {
279 wp_enqueue_script(
280 'firebox-animations',
281 FBOX_MEDIA_PUBLIC_URL . 'js/animations.js',
282 [],
283 FBOX_VERSION,
284 true
285 );
286 }
287 }
288
289 /**
290 * FireBox JS
291 */
292 wp_enqueue_script(
293 'firebox',
294 FBOX_MEDIA_PUBLIC_URL . 'js/firebox.js',
295 [],
296 FBOX_VERSION,
297 true
298 );
299
300 // run above the main JS script to run only once
301 self::setJSObject();
302
303 /**
304 * FireBox CSS
305 */
306 if ($this->params->get('loadCSS', true))
307 {
308 wp_enqueue_style(
309 'firebox',
310 FBOX_MEDIA_PUBLIC_URL . 'css/firebox.css',
311 [],
312 FBOX_VERSION
313 );
314 }
315
316 /**
317 * Page Slide mode JS
318 */
319 if ($box->get('params.data.mode') == 'pageslide')
320 {
321 wp_enqueue_script(
322 'firebox-pageslide-mode',
323 FBOX_MEDIA_PUBLIC_URL . 'js/pageslide_mode.js',
324 [],
325 FBOX_VERSION,
326 true
327 );
328 }
329
330
331
332 $this->loadThemeCSSOverrides();
333 }
334
335 /**
336 * Some themes require overrides to preserve as much as we can the styling of the popups.
337 *
338 * @return void
339 */
340 private function loadThemeCSSOverrides()
341 {
342 $active_theme = wp_get_theme();
343 $theme = $active_theme->template;
344
345 /**
346 * This is the listed of the themes that we have created overrides
347 */
348 $themes = [
349 'twentytwentyone'
350 ];
351
352 if (!in_array($theme, $themes))
353 {
354 return;
355 }
356
357 wp_enqueue_style(
358 'firebox-theme-' . $theme . '-override',
359 FBOX_MEDIA_PUBLIC_URL . 'css/themes/' . $theme . '.css',
360 [],
361 FBOX_VERSION
362 );
363 }
364
365 /**
366 * Prepares the box before rendering
367 *
368 * @return void
369 */
370 public function prepare()
371 {
372 $this->css = new Styling\CSS($this->box);
373
374 $cParam = BoxHelper::getParams();
375 $cParam = new Registry($cParam);
376
377 $this->box->post_content = apply_filters('the_content', $this->box->post_content);
378
379 $position = $this->box->params->get('position', '');
380 $position = !is_string($position) ? '' : $position;
381
382 /* Classes */
383 $css_class = [
384 $this->box->ID,
385 $position
386 ];
387
388 $rtl = $this->box->params->get('rtl', '0');
389 if ($rtl == '1')
390 {
391 $css_class[] = 'rtl';
392 }
393
394 self::prefixCSSClasses($css_class);
395
396 // Class suffix
397 $classSuffix = $this->box->params->get('classsuffix', '');
398 $classSuffix = is_string($classSuffix) ? $classSuffix : '';
399
400 $css_class[] = $classSuffix;
401
402 $this->box->classes = $css_class;
403
404 // Box shadow
405 $boxshadow = (is_string($this->box->params->get('boxshadow', '1')) || is_int($this->box->params->get('boxshadow', '1'))) ? $this->box->params->get('boxshadow', '1') : '0';
406
407 $dialog_css_classes = [
408 $boxshadow != '0' ? 'shd' . $boxshadow : null
409 ];
410
411 // Align Content
412 $aligncontent = is_string($this->box->params->get('aligncontent')) ? explode(' ', $this->box->params->get('aligncontent')) : [];
413 $dialog_css_classes = array_merge($dialog_css_classes, $aligncontent);
414
415 self::prefixCSSClasses($dialog_css_classes);
416 $this->box->dialog_classes = $dialog_css_classes;
417
418 $trigger_point_methods = [
419 'pageheight' => 'onScrollDepth',
420 'element' => 'onElementVisibility',
421 'pageready' => 'onPageReady',
422 'pageload' => 'onPageLoad',
423 'userleave' => 'onExit',
424 'onclick' => 'onClick',
425 'onexternallink' => 'onExternalLink',
426 'elementHover' => 'onHover',
427 'ondemand' => 'onDemand'
428 ];
429
430 /* Other Settings */
431 $scroll_depth = $this->box->params->get('scroll_depth', 'percentage');
432 $scroll_depth = is_string($scroll_depth) ? $scroll_depth : '';
433
434 $animation_duration = $this->box->params->get('duration') ? (float) $this->box->params->get('duration') : 0;
435
436 // Use Namespaced classes for each trigger point and let them manipulate the settings dynamicaly.
437 $this->box->settings = [
438 'trigger' => (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'),
439 'trigger_selector' => $this->box->params->get('triggerelement'),
440 'delay' => (int) $this->box->params->get('triggerdelay') * 1000,
441 'scroll_depth' => $scroll_depth,
442 'scroll_depth_value' => $scroll_depth == 'percentage' ? (int) $this->box->params->get('triggerpercentage') : (int) $this->box->params->get('scroll_pixel'),
443 'firing_frequency' => (int) $this->box->params->get('firing_frequency', 1),
444 'reverse_scroll_close' => (bool) $this->box->params->get('autohide'),
445 'threshold' => (float) $this->box->params->get('threshold', 0) / 100,
446 'close_out_viewport' => (bool) $this->box->params->get('close_out_viewport', false),
447 'exit_timer' => (int) $this->box->params->get('exittimer') * 1000,
448 'idle_time' => (int) $this->box->params->get('idle_time') * 1000,
449 'animation_open' => $this->box->params->get('animationin'),
450 'animation_close' => $this->box->params->get('animationout'),
451 'animation_duration' => (float) $animation_duration * 1000,
452 'prevent_default' => (bool) $this->box->params->get('preventdefault', true),
453 'backdrop' => (bool) $this->box->params->get('overlay'),
454 'backdrop_color' => $this->box->params->get('overlay_color'),
455 'backdrop_click' => (bool) $this->box->params->get('overlayclick'),
456 'disable_page_scroll' => (bool) $this->box->params->get('preventpagescroll'),
457 'test_mode' => (bool) $this->box->params->get('testmode'),
458 'debug' => (bool) $cParam->get('debug', false),
459 'ga_tracking' => (bool) $cParam->get('gaTrack', 0),
460 'ga_tracking_id' => $cParam->get('gaID', 0),
461 'ga_tracking_label' => $cParam->get('gaCategory'),
462 'auto_focus' => (bool) $this->box->params->get('autofocus', false)
463 ];
464
465 // Apply Popup CSS
466 $this->box->params->set('customcss', $this->box->params->get('customcss') . $this->css->getCSS());
467
468 $this->replaceBoxSmartTags();
469 }
470
471 /**
472 * Replaces all box smart tags
473 *
474 * @return object
475 */
476 public function replaceBoxSmartTags()
477 {
478 $tags = new \FPFramework\Base\SmartTags\SmartTags();
479
480 // register FB Smart Tags
481 $tags->register('\FireBox\Core\SmartTags', FBOX_BASE_FOLDER . '/Inc/Core/SmartTags', $this->box);
482
483 $this->box = $tags->replace($this->box);
484 }
485
486 /**
487 * Checks if a box passes assignments
488 *
489 * @return boolean
490 */
491 public function pass()
492 {
493 if (!$this->box || !is_object($this->box))
494 {
495 return false;
496 }
497
498 // Check first local assignments
499 if (!$this->passLocalAssignments())
500 {
501 return false;
502 }
503
504 $displayConditionsType = $this->box->params->get('display_conditions_type', '');
505
506 // If empty, display popup sitewide
507 if (empty($displayConditionsType) || $displayConditionsType === 'all')
508 {
509 return true;
510 }
511
512 // Mirror Display Conditions of another popup.
513 if ($displayConditionsType == 'mirror' && $mirror_box_id = $this->box->params->get('mirror_box'))
514 {
515 $this->box->params->merge(self::getAssignmentsForMirroring($mirror_box_id));
516 }
517
518 // Get a recursive array of all rules
519 $rules = json_decode(json_encode($this->box->params->get('rules', [])), true);
520
521 // If testmode is enabled disable the User Groups assignment
522 if ($this->box->params->get('testmode'))
523 {
524 foreach ($rules as $key => &$group)
525 {
526 foreach ($group['rules'] as $_key => &$rule)
527 {
528 if (!isset($rule['name']) || empty($rule['name']))
529 {
530 continue;
531 }
532
533 if ($rule['name'] === 'WP\UserGroup')
534 {
535 unset($group['rules'][$_key]);
536 }
537 }
538 }
539 }
540
541 // Check framework based assignments
542 return \FPFramework\Base\Conditions\ConditionBuilder::pass($rules, $this->factory);
543 }
544
545 /**
546 * Check if a box passes local assignments
547 *
548 * @return boolean
549 */
550 private function passLocalAssignments()
551 {
552 $localAssignments = new \FireBox\Core\FB\Assignments($this, $this->factory);
553 return $localAssignments->passAll();
554 }
555
556 /**
557 * Gets assignments of mirrored box
558 *
559 * @param int $box_id
560 *
561 * @return object
562 */
563 private function getAssignmentsForMirroring($box_id)
564 {
565 $payload = [
566 'where' => [
567 'ID' => ' = ' . intval($box_id),
568 'post_status' => " = 'publish'",
569 'post_type' => " = 'firebox'"
570 ]
571 ];
572
573 // Load box
574 if (!$box = firebox()->tables->box->getResults($payload))
575 {
576 return;
577 }
578
579 $box = $box[0];
580
581 // get meta options for box
582 $meta = get_post_meta($box_id, 'fpframework_meta_settings', true);
583 $box->params = new Registry($meta);
584
585 return new Registry(['rules' => $box->params->get('rules')]);
586 }
587
588 /**
589 * Prefixes the CSS classes
590 *
591 * @param array $classes
592 * @param string $prefix
593 *
594 * @return void
595 */
596 private static function prefixCSSClasses(&$classes, $prefix = 'fb-')
597 {
598 $classes = array_filter($classes);
599
600 if (empty($classes))
601 {
602 return;
603 }
604
605 foreach ($classes as &$class)
606 {
607 $class = $prefix . $class;
608 }
609 }
610
611 /**
612 * Track box open
613 *
614 * @param integer $box_id
615 * @param string $page
616 * @param string $referrer
617 *
618 * @return void
619 */
620 public function logOpenEvent($box_id, $page = null, $referrer = null)
621 {
622 $box = $this->get($box_id);
623
624 // Do not track if statistics option is disabled
625 $track_open_event = (bool) (is_null($box->params->get('stats', null)) ? BoxHelper::getParams()->get('stats', 1) : $box->params->get('stats'));
626 if (!$track_open_event)
627 {
628 return;
629 }
630
631 return firebox()->log->track($box_id, 1, null, $page, $referrer);
632 }
633
634 /**
635 * Track box close
636 *
637 * @param integer $box_id
638 * @param integer $box_log_id
639 *
640 * @return void
641 */
642 public function logCloseEvent($box_id, $box_log_id)
643 {
644 $box = $this->get($box_id);
645
646 // Do not track if statistics option is disabled
647 $track_open_event = (bool) (is_null($box->params->get('stats', null)) ? BoxHelper::getParams()->get('stats', 1) : $box->params->get('stats'));
648 if (!$track_open_event)
649 {
650 return null;
651 }
652
653 firebox()->log->track($box_id, 2, $box_log_id);
654 }
655
656 /**
657 * Get total box impressions
658 *
659 * @param array $payload
660 *
661 * @return array
662 */
663 public function getTotalImpressions($payload)
664 {
665 $impressions = firebox()->tables->boxlog->getResults($payload);
666
667 return count($impressions);
668 }
669
670 /**
671 * Returns the cookie instance.
672 *
673 * @return mixed
674 */
675 public function getCookie()
676 {
677 if (!$this->box)
678 {
679 return;
680 }
681
682 return new Cookie($this->box->id);
683 }
684
685 /**
686 * Returns the box.
687 *
688 * @return object
689 */
690 public function getBox()
691 {
692 return $this->box;
693 }
694
695 /**
696 * Sets the box.
697 *
698 * @param object $box
699 *
700 * @return Box
701 */
702 public function setBox($box)
703 {
704 $this->box = $box;
705
706 return $this;
707 }
708 }