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

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