# firebox/1.0.13/Inc/Core/FB/Box.php

FireBox – WooCommerce Popup Builder, Exit Intent Popup, Email Optin &amp; Cart Abandonment, version 1.0.13. 962 lines.

- Page: https://pluginprobe.com/plugins/firebox/1.0.13/code/Inc/Core/FB/Box.php
- Raw: https://pluginprobe.com/plugins/firebox/1.0.13/raw/Inc/Core/FB/Box.php
- Modified: 2022-05-16T15:27:10+00:00

Line numbers below start at 1. Link to a line or a range by appending a fragment to the
page URL, for example `https://pluginprobe.com/plugins/firebox/1.0.13/code/Inc/Core/FB/Box.php#L10-L20`.

```php
<?php
/**
 * @package         FireBox
 * @version         1.0.13 Free
 * 
 * @author          FirePlugins <info@fireplugins.com>
 * @link            https://www.fireplugins.com
 * @copyright       Copyright © 2022 FirePlugins All Rights Reserved
 * @license         GNU GPLv3 <http://www.gnu.org/licenses/gpl.html> or later
*/

namespace FireBox\Core\FB;

if (!defined('ABSPATH'))
{
	exit; // Exit if accessed directly.
}

use FireBox\Core\Helpers\BoxHelper;
use FPFramework\Libs\Registry;
use FPFramework\Helpers\Fields\DimensionsHelper;

class Box
{
	/**
	 * Send useful JS snippet once in first box
	 * 
	 * @var  boolean
	 */
	static $loadedLocalizedScript = false;

	/**
	 * The box settings
	 */
	private $boxSettings;

	/**
	 * The factory
	 * 
	 * @var  Factory
	 */
	protected $factory;

	public function __construct($boxSettings = null, $factory = null)
	{
		$this->init($boxSettings, $factory);
	}

	public function init($boxSettings = null, $factory = null)
	{
		if (!$factory)
		{
			$factory = new \FPFramework\Base\Factory();
		}
		
		$this->boxSettings = $boxSettings;
		$this->factory = $factory;
	}

	/**
	 * Gets published box.
	 * 
	 * @param   integer  $id
	 * @param   string   $status
	 * 
	 * @return  array
	 */
	public function get($id, $status = null)
	{
		$payload = [
			'where' => [
				'ID' => ' = ' . esc_sql($id),
				'post_type' => " = 'firebox'"
			]
		];

		// apply status if given
		if ($status)
		{
			$payload['where']['post_status'] = ' = \'' . esc_sql($status) . '\'';
		}
		
		if (!$box = firebox()->tables->box->getResults($payload))
		{
			return [];
		}

		if (!isset($box[0]))
		{
			return [];
		}
		
		$box = $box[0];

		// get meta options for box
		$meta = self::getMeta($id);
		$box->params = new Registry($meta);

		return $box;
	}

	/**
	 * Get box meta
	 * 
	 * @param   int  $id
	 * 
	 * @return  array
	 */
	public static function getMeta($id)
	{
		return get_post_meta($id, 'fpframework_meta_settings', true);
	}

	/**
	 * Render box
	 * 
	 * @return  string
	 */
	public function render($box = null)
	{
		// we do not have a passed box or box settings from constructor, abort
		// as we cannot render a box without any box parameters
		if (!$box && !$this->boxSettings)
		{
			return;
		}

		// if a box was given to the function, use these settings instead
		if ($box)
		{
			$this->boxSettings = $box;
		}

		// if we have box settings, then set up our box with these settings
		if ($this->boxSettings)
		{
			$box = $this->boxSettings;
		}

        // Check Publishing Assignments
        if (!$this->pass($box))
        {
			return;
		}

		// get settings params
		$params = BoxHelper::getParams();

		if (!did_action('wp_enqueue_scripts'))
		{
			/**
			 * Loads all media files.
			 */
			add_action('wp_enqueue_scripts', function() use ($box, $params) {
				// load box media
				$this->loadBoxMedia($box, $params);
			});
		}
		else
		{
			// load box media
			$this->loadBoxMedia($box, $params);
		}

		self::prepare($box);

		if (!did_action('wp_head'))
		{
			/**
			 * Custom CSS
			 */
			add_action('wp_head', function() use ($box) {
				if ($css = $this->getCustomCSS($box))
				{
					echo '<style type="text/css" class="fb-' . esc_attr($box->ID) . '-style fb-responsive-style">' . $css . '</style>';
				}
			});
		}
		else
		{
			if ($css = $this->getCustomCSS($box))
			{
				echo '<style type="text/css" class="fb-' . esc_attr($box->ID) . '-style fb-responsive-style">' . $css . '</style>';
			}
		}
		
		/**
		 * Runs before rendering the box.
		 */
		do_action('firebox/box/before_render', $box);

		// after we prepare it, update box settings
		$this->boxSettings = $box;

		// payload
		$payload = [
			'box' => $box,
			'params' => $params,
		];
		
		// return box template
		add_action('wp_footer', function() use ($box, $payload) {
			echo firebox()->renderer->public->render('box', $payload, true);
		});
	}

	/**
	 * Gets the Custom CSS of the popup.
	 * 
	 * @param   object  $box
	 * 
	 * @return  string
	 */
	private function getCustomCSS($box)
	{
		$css = is_string($box->params->get('customcss')) ? $box->params->get('customcss') : '';

		// add responsive CSS
		if ($responsive_css = (array) $box->params->get('responsive_css', []))
		{
			if (isset($responsive_css['tablet']) && !empty($responsive_css['tablet']))
			{
				$css .= '
@media only screen and (max-width: 768px) {
	.fb-' . esc_attr($box->ID) . ' .fb-dialog { ' . esc_html($responsive_css['tablet']) . ' }
}';
			}
			if (isset($responsive_css['mobile']) && !empty($responsive_css['mobile']))
			{
				$css .= '
@media only screen and (max-width: 468px) {
	.fb-' . esc_attr($box->ID) . ' .fb-dialog { ' . esc_html($responsive_css['mobile']) . ' }
}';
			}
		}

		return $css;
	}
    
	/**
	 * Send a helpful object to JavaScript files
	 *
	 * @return  void
	 */
	public static function setJSObject()
	{
		if (self::$loadedLocalizedScript)
		{
			return;
		}
		self::$loadedLocalizedScript = true;
		
		$data = array(
			'ajax_url' => admin_url('admin-ajax.php'),
			'nonce'    => wp_create_nonce('fbox_js_nonce'),
			'site_url' => site_url('/'),
			'referrer' => isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : ''
		);

		wp_localize_script('firebox', 'fbox_js_object', $data);
	}

	/**
	 * Load Box Media
	 * 
	 * @param   array  $box
	 * @param   array  $params
	 * 
	 * @return  void
	 */
	public function loadBoxMedia($box, $params)
	{
		$box = new Registry($box);
		$params = new Registry($params);

		/**
		 * We require a CSS handle to register inline styles.
		 * 
		 * For this case, we use this dummy style to add inline CSS for our popups
		 * even though the FireBox CSS file may not appear in the page.
		 */
		wp_register_style('firebox-custom-styles', false);
		wp_enqueue_style('firebox-custom-styles');

		// Add polyfills for Internet Explorer
		$browser = $this->factory->getBrowser();
		if ($browser && is_array($browser) && array_key_exists('name', $browser) && $browser['name'] == 'ie')
		{
			wp_enqueue_script(
				'firebox-ie11-polyfill',
				'https://polyfill.io/v3/polyfill.min.js?features=NodeList.prototype.forEach%2CElement.prototype.closest%2CArray.prototype.forEach%2CArray.prototype.find%2CIntersectionObserver%2CIntersectionObserverEntry',
				[],
				FBOX_VERSION,
				false
			);
		}

		/**
		 * Velocity
		 */
		if ($params->get('loadVelocity', true))
		{
			wp_enqueue_script(
				'firebox-velocity',
				FBOX_MEDIA_PUBLIC_URL . 'js/vendor/velocity.js',
				[],
				FBOX_VERSION,
				false
			);
			wp_enqueue_script(
				'firebox-velocity-ui',
				FBOX_MEDIA_PUBLIC_URL . 'js/vendor/velocity.ui.js',
				[],
				FBOX_VERSION,
				false
			);

			/**
			 * Animations
			 */
			if (strpos($box->get('params.data.animationin'), 'firebox') !== false || strpos($box->get('params.data.animationout'), 'firebox') !== false)
			{
				wp_enqueue_script(
					'firebox-animations',
					FBOX_MEDIA_PUBLIC_URL . 'js/animations.js',
					[],
					FBOX_VERSION,
					false
				);
			}
		}

		/**
		 * FireBox JS
		 */
		wp_enqueue_script(
			'firebox',
			FBOX_MEDIA_PUBLIC_URL . 'js/firebox.js',
			[],
			FBOX_VERSION,
			false
		);

		// run above the main JS script to run only once
        self::setJSObject();
		
		/**
		 * FireBox CSS
		 */
		if ($params->get('loadCSS', true))
		{
			wp_enqueue_style(
				'firebox',
				FBOX_MEDIA_PUBLIC_URL . 'css/firebox.css',
				[],
				FBOX_VERSION,
				false
			);
		}

		/**
		 * Page Slide mode JS
		 */
		if ($box->get('params.data.mode') == 'pageslide')
		{
			wp_enqueue_script(
				'firebox-pageslide-mode',
				FBOX_MEDIA_PUBLIC_URL . 'js/pageslide_mode.js',
				[],
				FBOX_VERSION,
				false
			);
		}

		

		$this->loadThemeCSSOverrides();
	}

	/**
	 * Some themes require overrides to preserve as much as we can the styling of the popups.
	 * 
	 * @return  void
	 */
	private function loadThemeCSSOverrides()
	{
		$active_theme = wp_get_theme();
		$theme = $active_theme->template;

		/**
		 * This is the listed of the themes that we have created overrides
		 */
		$themes = [
			'twentytwentyone'
		];

		if (!in_array($theme, $themes))
		{
			return;
		}

		wp_enqueue_style(
			'firebox-theme-' . $theme . '-override',
			FBOX_MEDIA_PUBLIC_URL . 'css/themes/' . $theme . '.css',
			[],
			FBOX_VERSION,
			false
		);
	}

	/**
	 * Prepares the box before rendering
	 * 
	 * @param   array  $box
	 * 
	 * @return  void
	 */
	public static function prepare(&$box)
	{
		global $post;
		$original_post = $post;

		$GLOBALS['post'] = $box;
		setup_postdata($GLOBALS['post']);

		$cParam = BoxHelper::getParams();
		$cParam = new Registry($cParam);

		$box->post_content = apply_filters('the_content', $box->post_content);

		$css_class_prefix = 'fb-';
		
		$position = $box->params->get('position', '');
		$position = !is_string($position) ? '' : $position;
		
        /* Classes */
        $css_class = [
            $box->ID,
            $position
		];
		
        $rtl = $box->params->get('rtl', '0');
        if ($rtl == '1')
        {
            $css_class[] = 'rtl';
		}

		self::prefixCSSClasses($css_class);
		
		// class suffix
		$classSuffix = $box->params->get('classsuffix', '');
		$classSuffix = is_string($classSuffix) ? $classSuffix : '';
		
        $css_class[] = $classSuffix;
		
		$box->classes = $css_class;
		
		// box shadow
		$boxshadow = (is_string($box->params->get('boxshadow', '1')) || is_int($box->params->get('boxshadow', '1'))) ? $box->params->get('boxshadow', '1') : '0';

        $dialog_css_classes = [
            $boxshadow != '0' ? 'shd' . $boxshadow : null
		];

		// Align Content
		$aligncontent = is_string($box->params->get('aligncontent')) ? explode(' ', $box->params->get('aligncontent')) : [];
        $dialog_css_classes = array_merge($dialog_css_classes, $aligncontent);
		
        self::prefixCSSClasses($dialog_css_classes);
		$box->dialog_classes = $dialog_css_classes;
		
		/* CSS */
		// border
		$border	= is_string($box->params->get('bordertype', 'none')) ? $box->params->get('bordertype', 'none') : 'none';
		$border_width = $box->params->get('borderwidth.value', 0) ? $box->params->get('borderwidth.value', 0) : 0;
		$border_unit = is_string($box->params->get('borderwidth.unit', 'px')) ? $box->params->get('borderwidth.unit', 'px') : 0;
		$border_color = is_string($box->params->get('bordercolor')) ? $box->params->get('bordercolor') : '';

        $style = [
            'background'  		=> $box->params->get('backgroundcolor'),
            'color'				=> $box->params->get('textcolor'),
            'border'			=> $border == 'none' ? null : $border . ' ' . $border_width . $border_unit . ' ' . $border_color,
		];

		// add shared properties
		$shared_properties = [
			'width' => [
				'prefix_only' => true
			],
			'height' => [
				'prefix_only' => true
			],
			'padding' => [],
			'margin' => []
		];
		foreach ($shared_properties as $prop => $prop_data)
		{
			// add dekstop property
			$value = (array) $box->params->get($prop . '_control.' . $prop, []);
			if (isset($value['desktop']))
			{
				$prefix_only = isset($prop_data['prefix_only']) ? (bool) $prop_data['prefix_only'] : false;
				
				$desktop_value = DimensionsHelper::parseDimensionsData($value['desktop'], $prop, false, $prefix_only);
				$style = array_merge($style, $desktop_value);
			}
		}
		
		// add dekstop border_radius
		$border_radius = (array) $box->params->get('borderradius_control.borderradius', []);
		if (isset($border_radius['desktop']))
		{
			$desktop_border_radius = DimensionsHelper::parseDimensionsBorderRadiusData($border_radius['desktop']);
			$style = array_merge($style, $desktop_border_radius);
		}
		
        // Background Image
        if ($box->params->get('bgimage', false))
        {
			$bgrepeat = is_string($box->params->get('bgrepeat')) ? $box->params->get('bgrepeat') : '';
			$bgsize = is_string($box->params->get('bgsize')) ? $box->params->get('bgsize') : '';
			$bgposition = is_string($box->params->get('bgposition')) ? $box->params->get('bgposition') : '';
			
			$style['background-image']  = 'url(\'' . esc_url($box->params->get('bgimagefile')) . '\')';
			$style['background-repeat'] = strtolower($bgrepeat);
			$style['background-size'] = strtolower($bgsize);
			$style['background-position'] = strtolower($bgposition);
		}

		$box->style = BoxHelper::arrayToCSSS($style);

        $trigger_point_methods = [
            'pageheight'   => 'onScrollDepth',
            'element'      => 'onElementVisibility',
            'pageready'    => 'onPageReady',
            'pageload'     => 'onPageLoad',
            'userleave'    => 'onExit',
            'onclick'      => 'onClick',
            'elementHover' => 'onHover',
            'ondemand'     => 'onDemand'
		];

		/* Other Settings */
		$scroll_depth = $box->params->get('scroll_depth', 'percentage');
		$scroll_depth = is_string($scroll_depth) ? $scroll_depth : '';

		$animation_duration = $box->params->get('duration') ? (float) $box->params->get('duration') : 0;
		
        // Use Namespaced classes for each trigger point and let them manipulate the settings dynamicaly.
        $box->settings = [
            'trigger'              => (is_string($box->params->get('triggermethod'))) && array_key_exists($box->params->get('triggermethod'), $trigger_point_methods) ? $trigger_point_methods[$box->params->get('triggermethod')] : $box->params->get('triggermethod'),
            'trigger_selector'     => $box->params->get('triggerelement'),
            'delay'                => (int) $box->params->get('triggerdelay') * 1000,
            'scroll_depth'         => $scroll_depth,
			'scroll_depth_value'   => $scroll_depth == 'percentage' ? (int) $box->params->get('triggerpercentage') : (int) $box->params->get('scroll_pixel'),
			'firing_frequency'     => (int) $box->params->get('firing_frequency', 1),
            'reverse_scroll_close' => (bool) $box->params->get('autohide'),
			'threshold'            => (float) $box->params->get('threshold', 0) / 100,
			'close_out_viewport'   => (bool) $box->params->get('close_out_viewport', false),
            'exit_timer'           => (int) $box->params->get('exittimer') * 1000,
            'idle_time'            => (int) $box->params->get('idle_time') * 1000,
            'animation_open'       => $box->params->get('animationin'),
            'animation_close'      => $box->params->get('animationout'),
			'animation_duration'   => (float) $animation_duration * 1000,
			'prevent_default'      => (bool) $box->params->get('preventdefault', true),
            'backdrop'             => (bool) $box->params->get('overlay'),
            'backdrop_color'       => $box->params->get('overlay_color'),
            'backdrop_click'       => (bool) $box->params->get('overlayclick'),
            'disable_page_scroll'  => (bool) $box->params->get('preventpagescroll'),
            'test_mode'            => (bool) $box->params->get('testmode'),
            'debug'                => (bool) $cParam->get('debug', false),
            'ga_tracking'          => (bool) $cParam->get('gaTrack', 0),
            'ga_tracking_id'       => $cParam->get('gaID', 0),
            'ga_tracking_label'    => $cParam->get('gaCategory'),
			'auto_focus'		   => (bool) $box->params->get('autofocus', false)
		];

		$box->styles_container = BoxHelper::arrayToCSSS([
            'z-index' => $box->params->get('zindex', 99999) != 99999 ? $box->params->get('zindex') : null
		]);

		// Let's start using CSS vars for each box settings.
		$cssVars = [
			'animation_duration' => (float) $animation_duration . 's'
		];
		
		// Enqueue firebox custom inline CSS
		$cssVarsForm = self::cssVarsToString($cssVars, '.fb-' . $box->ID);
		if (!did_action('wp_enqueue_scripts'))
		{
			add_action('wp_enqueue_scripts', function() use ($cssVarsForm) {
				wp_add_inline_style('firebox-custom-styles', $cssVarsForm);
			});
		}
		else
		{
			wp_add_inline_style('firebox-custom-styles', $cssVarsForm);
		}

		// set padding and margin for other devices as well
		self::setResponsiveCSS($box);

		self::replaceBoxSmartTags($box);

		$GLOBALS['post'] = $original_post;
		wp_reset_postdata();
	}

	/**
	 * Converts an array of CSS variables to its corresponding strings.
	 * 
	 * @param   array   $cssVars
	 * @param   string  $namespace
	 * 
	 * @return  string
	 */
	private static function cssVarsToString($cssVars, $namespace)
    {
        $output = '';

        foreach ($cssVars as $key => $value)
        {
            $output .= '--' . $key . ': ' . $value . ';' . "\n";
        }

        return $namespace . ' {
                ' . $output . '
            }
        ';
    }

	/**
	 * Sets all responsive CSS to use in box view
	 * 
	 * @param   object  $box
	 * 
	 * @return  void
	 */
	private static function setResponsiveCSS(&$box)
	{
		$tablet = '';
		$mobile = '';

		/**
		 * Handle width, height, padding, margin the same way.
		 */
		$shared_properties = [
			'width' => [
				'prefix_only' => true
			],
			'height' => [
				'prefix_only' => true
			],
			'padding' => [],
			'margin' => []
		];

		foreach ($shared_properties as $prop => $prop_settings)
		{
			$prop_data = (array) $box->params->get($prop . '_control.' . $prop, []);

			$prefix_only = isset($prop_settings['prefix_only']) ? $prop_settings['prefix_only'] : false;

			// assign each device CSS
			if (isset($prop_data['tablet']))
			{
				$tablet .= BoxHelper::arrayToCSSS(DimensionsHelper::parseDimensionsData($prop_data['tablet'], $prop, true, $prefix_only));
			}
			if (isset($prop_data['mobile']))
			{
				$mobile .= BoxHelper::arrayToCSSS(DimensionsHelper::parseDimensionsData($prop_data['mobile'], $prop, true, $prefix_only));
			}
		}

		// border radius requires a special method
		$border_radius = (array) $box->params->get('borderradius_control.borderradius', []);
		if (isset($border_radius['tablet']))
		{
			$tablet .= BoxHelper::arrayToCSSS(DimensionsHelper::parseDimensionsBorderRadiusData($border_radius['tablet'], true));
		}
		if (isset($border_radius['mobile']))
		{
			$mobile .= BoxHelper::arrayToCSSS(DimensionsHelper::parseDimensionsBorderRadiusData($border_radius['mobile'], true));
		}

		$responsive_css = [
			'tablet' => $tablet,
			'mobile' => $mobile
		];
		$box->params->set('responsive_css', $responsive_css);
	}
	
	/**
	 * Replaces all box smart tags
	 * 
	 * @param   object  $box
	 * 
	 * @return  object
	 */
	public static function replaceBoxSmartTags(&$box)
	{
		$tags = new \FPFramework\Base\SmartTags\SmartTags();

		// register FB Smart Tags
		$tags->register('\FireBox\Core\SmartTags', FBOX_BASE_FOLDER . '/Inc/Core/SmartTags', $box);

		$box = $tags->replace($box);
	}

	/**
	 * Checks if a box passes assignments
	 * 
	 * @param   object  $box
	 * 
	 * @return  boolean
	 */
	public function pass($box)
    {
        if (!$box || !is_object($box))
        {
            return false;
		}

		// set box settings if empty
		if (empty($this->boxSettings))
		{
			$this->boxSettings = $box;
		}

        // Prepare boxes that mirror other boxes assignments
        if ($box->params->get('mirror', false) && $mirror_box_id = $box->params->get('mirror_box'))
        {
			$box->params->merge(self::getAssignmentsForMirroring($mirror_box_id));
        }

        // Check first local assignments
        if (!$this->passLocalAssignments($box))
        {
            return false;
        }

		// If testmode is enabled disable the User Groups assignment
        if ($box->params->get('testmode'))
        {
            $box->params->set('assignments.assign_grouplevel.selection', '0');
		}
		
		$globalAssignments = $this->passGlobalAssignments($box);
		
        // Check framework based assignments
        return $globalAssignments;
	}

	/**
	 * Passes framework based global assignments
	 * 
	 * @param   object  $box
	 * 
	 * @return  boolean
	 */
    private function passGlobalAssignments($box)
    {
        $assignments = new \FPFramework\Base\Assignments($this->factory);
		$pass = $assignments->passAll($box, $box->params->get('assignmentMatchingMethod', 'and'));
		return $pass;
    }

    /**
     * Check if a box passes local assignments
     *
	 * @param   object  $box
	 * 
     * @return  boolean
     */
    private function passLocalAssignments($box)
    {
        $localAssignments = new \FireBox\Core\FB\Assignments($this, $this->factory);
        return $localAssignments->passAll();
    }
	
	/**
	 * Gets assignments of mirrored box
	 * 
	 * @param   int  $box_id
	 * 
	 * @return  object
	 */
	private static function getAssignmentsForMirroring($box_id)
    {   
		$payload = [
			'where' => [
				'ID' => ' = ' . intval($box_id),
				'post_status' => " = 'publish'",
				'post_type' => " = 'firebox'"
			]
		];
		
        // Load box
		if (!$box = firebox()->tables->box->getResults($payload))
		{
            return;
		}
		
		$box = $box[0];
		
		// get meta options for box
		$meta = get_post_meta($box_id, 'fpframework_meta_settings', true);
		$box->params = $meta;

        // To prevent user frustration, we ignore the following assignments because they are not displayed in the Publishing Assignments.
        $params_to_ignore = [
            'assign_impressions'
        ];

        $assignments = [];

        // Gather params to merge
        foreach ($box->params as $param_key => $param_value)
        {
            if (strpos($param_key, 'assign') === false || in_array($param_key, $params_to_ignore))
            {
                continue;
            }

            $assignments[$param_key] = $param_value;
		}
		
        return new Registry($assignments);
    }

	/**
	 * Prefixes the CSS classes
	 * 
	 * @param   array   $classes
	 * @param   string  $prefix
	 * 
	 * @return  void
	 */
    private static function prefixCSSClasses(&$classes, $prefix = 'fb-')
    {
		$classes = array_filter($classes);
		
		if (empty($classes))
		{
			return;
		}

        foreach ($classes as &$class)
        {
            $class = $prefix . $class;
        }
    }

	/**
	 * Track box open
	 * 
	 * @param   integer  $box_id
	 * @param   string   $page
	 * @param   string   $referrer
	 * 
	 * @return  void
	 */
    public function logOpenEvent($box_id, $page = null, $referrer = null)
    {
        $box = $this->get($box_id);

        // Do not track if statistics option is disabled
		$track_open_event = (bool) (is_null($box->params->get('stats', null)) ? BoxHelper::getParams()->get('stats', 1) : $box->params->get('stats'));
        if (!$track_open_event)
        {
            return;
        }

        return firebox()->log->track($box_id, 1, null, $page, $referrer);
    }

	/**
	 * Track box close
	 * 
	 * @param   integer  $box_id
	 * @param   integer  $box_log_id
	 * 
	 * @return  void
	 */
    public function logCloseEvent($box_id, $box_log_id)
    {
        $box = $this->get($box_id);

        // Do not track if statistics option is disabled
		$track_open_event = (bool) (is_null($box->params->get('stats', null)) ? BoxHelper::getParams()->get('stats', 1) : $box->params->get('stats'));
        if (!$track_open_event)
        {
            return null;
        }

        firebox()->log->track($box_id, 2, $box_log_id);
	}
	
	/**
	 * Get box impressions
	 * 
	 * @param   array  $payload
	 * 
	 * @return  array
	 */
	public function getImpressions($payload)
	{
		return firebox()->tables->boxlog->getResults($payload);
	}
	
	/**
	 * Get total box impressions
	 * 
	 * @param   array  $payload
	 * 
	 * @return  array
	 */
	public function getTotalImpressions($payload)
	{
		return count($this->getImpressions($payload));
	}

	/**
	 * Return the box settings
	 * 
	 * @return  object
	 */
	public function getBoxSettings()
	{
		return $this->boxSettings;
	}

	/**
	 * Sets the box settings
	 * 
	 * @param   object  $settings
	 * 
	 * @return  object
	 */
	public function setBoxSettings($settings)
	{
		$this->boxSettings = $settings;
	}

	/**
	 * Returns the box cookie
	 * 
	 * @param   string  $cookie
	 * 
	 * @return  mixed
	 */
	public function getCookie($cookie = null)
	{
		$cookie = $cookie ? $cookie : (isset($this->boxSettings->ID) ? $this->boxSettings->ID : null);
		if (!isset($cookie))
		{
			return;
		}
		
		return new Cookie($cookie);
	}
}
```
