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

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