PluginProbe
FireBox – WooCommerce Popup Builder, Exit Intent Popup, Email Optin & Cart Abandonment / trunk
FireBox – WooCommerce Popup Builder, Exit Intent Popup, Email Optin & Cart Abandonment vtrunk
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 / Analytics / Metrics / Metric.php

Metric.php in FireBox – WooCommerce Popup Builder, Exit Intent Popup, Email Optin & Cart Abandonment trunk, at Inc/Core/Analytics/Metrics/Metric.php

230 lines 5.7 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 3.1.13 Free
5 *
6 * @author FirePlugins <info@fireplugins.com>
7 * @link https://www.fireplugins.com
8 * @copyright Copyright © 2026 FirePlugins All Rights Reserved
9 * @license GNU GPLv3 <http://www.gnu.org/licenses/gpl.html> or later
10 */
11
12 namespace FireBox\Core\Analytics\Metrics;
13
14 if (!defined('ABSPATH'))
15 {
16 exit; // Exit if accessed directly.
17 }
18
19 abstract class Metric
20 {
21 protected $start_date = null;
22 protected $end_date = null;
23 protected $filters = [];
24 protected $offset = null;
25 protected $limit = null;
26 protected $type = 'list';
27 protected $query_placeholders = [];
28 protected $sql_filters = '';
29 protected $wpdb;
30 protected $options = [];
31 protected $is_single_day = false;
32 protected $table_logs;
33 protected $table_details;
34
35 // Simple timezone offset cache for request duration
36 protected static $timezone_offset_cache = null;
37
38 // Query strategy pattern support
39 protected $queryStrategy = null;
40
41 /**
42 * @param string $start_date
43 * @param string $end_date
44 * @param string $type Can be "list" or "count"
45 * @param array $options
46 */
47 public function __construct($start_date = null, $end_date = null, $type = 'list', $options = [])
48 {
49 global $wpdb;
50 $this->wpdb = $wpdb;
51
52 // Initialize table names
53 $this->table_logs = $wpdb->prefix . 'firebox_logs';
54 $this->table_details = $wpdb->prefix . 'firebox_logs_details';
55
56 $this->start_date = $start_date;
57 $this->end_date = $end_date;
58 $this->type = $type;
59 $this->query_placeholders = [$this->start_date, $this->end_date];
60 $this->options = $options;
61 $this->is_single_day = \FireBox\Core\Analytics\Helpers\Date::isSingleDay($this->start_date, $this->end_date);
62 }
63
64 protected function applyFilters()
65 {
66 $filter_builder = new \FireBox\Core\Analytics\Filters\FilterBuilder($this->query_placeholders);
67 $result = $filter_builder->build($this->filters);
68
69 $this->sql_filters = $result['sql'];
70 $this->query_placeholders = $result['placeholders'];
71 }
72
73 abstract public function getData();
74
75 public function onAfterGetData(&$data = [])
76 {
77 if (empty($data)) {
78 return;
79 }
80
81 // Use transformer system for data processing
82 \FireBox\Core\Analytics\Transformers\TransformerRegistry::transformData(
83 $data,
84 $this->type,
85 [
86 'is_single_day' => $this->isSingleDay(),
87 'options' => $this->options
88 ]
89 );
90 }
91
92 /**
93 * Get timezone offset string for SQL CONVERT_TZ function (cached)
94 * Returns offset in format '+05:30' or '-08:00'
95 *
96 * @return string Timezone offset string
97 */
98 protected function getTimezoneOffsetString()
99 {
100 // Cache timezone offset since it doesn't change during request
101 if (self::$timezone_offset_cache === null) {
102 $timezone_offset = get_option('gmt_offset');
103 $hours = (int) $timezone_offset;
104 $minutes = abs(($timezone_offset - (int) $timezone_offset) * 60);
105 self::$timezone_offset_cache = sprintf('%+03d:%02d', $hours, $minutes);
106 }
107
108 return self::$timezone_offset_cache;
109 }
110
111 public function filters(array $filters)
112 {
113 $this->filters = $filters;
114 return $this;
115 }
116
117 public function offset(int $offset)
118 {
119 $this->offset = $offset;
120 return $this;
121 }
122
123 public function limit(int $limit)
124 {
125 $this->limit = $limit;
126 return $this;
127 }
128
129 public function isSingleDay()
130 {
131 return $this->is_single_day;
132 }
133
134 /**
135 * Accessor methods for query strategies
136 */
137 public function getWpdb()
138 {
139 return $this->wpdb;
140 }
141
142 public function getOptions()
143 {
144 return array_merge($this->options, [
145 'start_date' => $this->start_date,
146 'end_date' => $this->end_date,
147 'limit' => $this->limit,
148 'offset' => $this->offset,
149 'type' => $this->type,
150 'is_single_day' => $this->is_single_day
151 ]);
152 }
153
154 public function getFilters()
155 {
156 return $this->filters;
157 }
158
159 public function getType()
160 {
161 return $this->type;
162 }
163
164 public function getTableLogs()
165 {
166 return $this->table_logs;
167 }
168
169 public function getTableDetails()
170 {
171 return $this->table_details;
172 }
173
174 /**
175 * Smart timezone-aware SQL date function wrapper
176 * Automatically applies timezone conversion to any SQL date function
177 *
178 * @param string $function SQL date function (e.g., 'DAYNAME', 'DATE_FORMAT', 'YEAR', 'MONTH')
179 * @param string $date_column Database date column (e.g., 'bld.date', 'l.date')
180 * @param string $format_args Additional format arguments for functions like DATE_FORMAT
181 * @return string Complete SQL expression with timezone conversion
182 */
183 public function getTimezoneDateSQL($function, $date_column, $format_args = '')
184 {
185 $offset_string = $this->getTimezoneOffsetString();
186 $timezone_converted_date = "CONVERT_TZ($date_column, '+00:00', '$offset_string')";
187
188 if (!empty($format_args))
189 {
190 return "$function($timezone_converted_date, $format_args)";
191 }
192
193 return "$function($timezone_converted_date)";
194 }
195
196 /**
197 * Execute query with optimized result processing
198 */
199 protected function executeQuery(string $sql)
200 {
201 if ($this->type === 'count') {
202 $column_value = $this->wpdb->get_col($sql); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
203 return array_sum(array_map('intval', $column_value));
204 }
205
206 return $this->wpdb->get_results($sql); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
207 }
208
209 /**
210 * Get the query strategy instance (lazy initialization)
211 * Can be overridden by subclasses to provide custom strategy factories
212 */
213 protected function getQueryStrategy()
214 {
215 if ($this->queryStrategy === null) {
216 $this->queryStrategy = $this->createQueryStrategy();
217 }
218 return $this->queryStrategy;
219 }
220
221 /**
222 * Create the appropriate query strategy for this metric type
223 * Must be implemented by subclasses that use the strategy pattern
224 */
225 protected function createQueryStrategy()
226 {
227 // Default implementation returns null - subclasses should override if they use strategies
228 return null;
229 }
230 }