PluginProbe
FireBox – WooCommerce Popup Builder, Exit Intent Popup, Email Optin & Cart Abandonment / 3.1.12
FireBox – WooCommerce Popup Builder, Exit Intent Popup, Email Optin & Cart Abandonment v3.1.12
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 / Meta.php

Meta.php in FireBox – WooCommerce Popup Builder, Exit Intent Popup, Email Optin & Cart Abandonment 3.1.12, at Inc/Core/FB/Meta.php

426 lines 14.1 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.12 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\FB;
13
14 if (!defined('ABSPATH'))
15 {
16 exit; // Exit if accessed directly.
17 }
18
19 class Meta
20 {
21 private $is_running = false;
22
23 public function __construct()
24 {
25 add_filter('get_post_metadata', [$this, 'get_legacy_meta'], 10, 4);
26
27 $this->register();
28 }
29
30 public function get_legacy_meta($value, $post_id, $meta_key, $single)
31 {
32 if ($this->is_running || $meta_key !== 'firebox_meta')
33 {
34 return $value;
35 }
36
37 $this->is_running = true;
38
39 // Get new format meta
40 $new_meta = get_post_meta($post_id, 'firebox_meta', true) ?: [];
41
42 // If we have new meta data, return it
43 if (is_array($new_meta) && count($new_meta))
44 {
45 $this->is_running = false;
46 return $value;
47 }
48
49 $defaults = $this->getDefaults();
50
51 // Get legacy meta
52 $legacy_meta = get_post_meta($post_id, 'fpframework_meta_settings', true);
53
54 // Merge legacy values if not already in new format
55 if (!empty($legacy_meta))
56 {
57 $map = [
58 // Campaign Format
59 'mode' => [],
60
61 // Trigger
62 'triggermethod' => [
63 'transform' => 'triggermethod_migration'
64 ],
65 'triggerelement' => [],
66 'close_out_viewport' => [],
67 'threshold' => [],
68 'exittimer' => [],
69 'idle_time' => [],
70 'triggerdelay' => [],
71 'scroll_depth' => [
72 'rename' => 'scroll_amount',
73 'transform' => 'scroll_depth_migration'
74 ],
75 'autohide' => [],
76 'firing_frequency' => [
77 'transform' => 'firing_frequency_toggle_migration'
78 ],
79 'floating_button_show_on_close' => [],
80 'floatingbutton_message' => [
81 'transform' => 'floatingbutton_message_migration'
82 ],
83 'floating_button_position' => [],
84 'assign_impressions_param_type' => [],
85 'assign_impressions_param_custom_period_times' => [],
86 'assign_impressions_param_custom_period' => [],
87 'opening_sound' => [],
88 'assign_cookietype' => [],
89 'assign_cookietype_param_custom_period_times' => [],
90 'assign_cookietype_param_custom_period' => [],
91 'box_auto_close' => [
92 'transform' => 'box_auto_close_migration'
93 ],
94 'box_auto_close_seconds' => [],
95 'autofocus' => [],
96 'close_on_esc' => [],
97
98 // Actions
99 'actions' => [
100 'transform' => 'actions_migration'
101 ],
102
103 // Display Conditions
104 'display_conditions_type' => [],
105 'mirror_box' => [],
106 'rules' => [
107 'transform' => 'rules_migration'
108 ],
109
110 // Position
111 'position' => [],
112
113 // Design
114 'width_control.width' => [
115 'rename' => 'width',
116 'transform' => 'migrate_unitvalue'
117 ],
118 'height_control.height' => [
119 'rename' => 'height',
120 'transform' => 'migrate_unitvalue'
121 ],
122 'fontsize_control.fontsize' => [
123 'rename' => 'fontsize',
124 'transform' => 'migrate_unitvalue'
125 ],
126 'padding_control.padding' => [
127 'rename' => 'padding',
128 'transform' => 'dimension'
129 ],
130 'margin_control.margin' => [
131 'rename' => 'margin',
132 'transform' => 'dimension'
133 ],
134 'textcolor' => [],
135 'backgroundcolor' => [],
136 'aligncontent' => [],
137 'boxshadow' => [
138 'transform' => 'shadow_migration'
139 ],
140 'animationin' => [
141 'transform' => 'animation_migration'
142 ],
143 'animationout' => [
144 'transform' => 'animation_migration'
145 ],
146 'duration' => [],
147 'border' => [
148 'transform' => 'border_migration'
149 ],
150 'borderradius_control.borderradius' => [
151 'rename' => 'borderradius',
152 'transform' => 'borderradius_migration'
153 ],
154 // Background Overlay
155 'overlay' => [
156 'transform' => 'overlay_enabled_migration'
157 ],
158 'overlay_color' => [],
159 'overlayblurradius' => [
160 'transform' => 'overlayblurradius_migration'
161 ],
162 'overlayclick' => [],
163 // Background Image
164 'bgimage' => [],
165 'bgimagefile' => [],
166 'bgrepeat' => [],
167 'bgsize' => [],
168 'bgposition' => [],
169
170 // Close Button
171 'closebutton' => [],
172
173 // Advanced
174 'customcode' => [],
175 'customcss' => [],
176 'testmode' => [],
177 'preventpagescroll' => [],
178 'stats' => [],
179 'classsuffix' => [],
180 'zindex' => [],
181
182
183 ];
184
185 foreach ($map as $key => $value)
186 {
187 $legacyValue = $this->getValueFromLegacyMeta($key, $value, $new_meta, $legacy_meta);
188
189 // Renames
190 if (isset($value['rename']))
191 {
192 $key = $value['rename'];
193 }
194
195 // Does the new meta value exist?
196 $valueExistsInNewMeta = isset($new_meta[$key]);
197
198 // Set new meta value from legacy meta value. Always assign (even when
199 // $legacyValue is null, i.e. no legacy counterpart exists) so the key
200 // exists throughout the transform stage below — direct array access on
201 // an existing-but-null key doesn't warn, whereas leaving the key entirely
202 // absent does. Null placeholders are stripped before the final defaults
203 // backfill so they don't clobber a field's documented default.
204 if (!isset($new_meta[$key]))
205 {
206 $new_meta[$key] = $legacyValue;
207 }
208
209 // Transforms
210 if (isset($value['transform']))
211 {
212 $migrator = new MetaMigrator();
213 $migrator->applyTransform($value['transform'], $key, $new_meta, $legacy_meta, $defaults, $valueExistsInNewMeta);
214 }
215 }
216 }
217
218 // Drop null placeholders (keys with no legacy counterpart, kept in the array
219 // only so the transform stage above could access them without warnings), then
220 // backfill any key still missing — including every key, if there was no legacy
221 // meta at all, i.e. a brand new campaign — with its documented default, without
222 // clobbering keys that were actually migrated from legacy data.
223 $new_meta = array_filter($new_meta, function ($v) { return $v !== null; });
224 $new_meta = array_merge($defaults, $new_meta);
225
226 $this->is_running = false;
227
228 // WP always expects filters on `get_post_metadata` to return the value
229 // wrapped in an array; it unwraps to $value[0] itself when $single is true.
230 return [$new_meta];
231 }
232
233 /**
234 * Returns null (not '') when no legacy counterpart exists, so the caller can tell
235 * "no legacy value" apart from "legacy value is an empty string" and fall back to
236 * the field's documented default instead of persisting an empty string.
237 */
238 private function getValueFromLegacyMeta($key, $value, $new_meta, $legacy_meta)
239 {
240 $_value = null;
241
242 if (strpos($key, '.') !== false)
243 {
244 list($first_part, $second_part) = explode('.', $key, 2);
245 if (!isset($new_meta[$value['rename']]) && isset($legacy_meta[$first_part][$second_part]))
246 {
247 $_value = $legacy_meta[$first_part][$second_part];
248 }
249 }
250 else
251 {
252 if (!isset($new_meta[$key]) && isset($legacy_meta[$key]))
253 {
254 $_value = $legacy_meta[$key];
255 }
256 }
257
258 return $_value;
259 }
260
261 private function getDefaults()
262 {
263 return [
264 'mode' => 'popup',
265
266 // For fullscreen
267 'center_content' => false,
268
269 'triggermethod' => 'pageload',
270 'triggerelement' => '',
271 'close_out_viewport' => false,
272 'threshold' => 25,
273 'exittimer' => 1,
274 'idle_time' => 10,
275 'triggerdelay' => 0,
276 'scroll_amount' => '80%',
277 'autohide' => false,
278 'firing_frequency' => '1',
279 'floating_button_show_on_close' => false,
280 'floatingbutton_message' => [
281 'text' => 'Open Popup',
282 'bgcolor' => '#4285F4',
283 'textcolor' => '#fff',
284 'fontsize' => '15px'
285 ],
286 'floating_button_position' => 'bottom-right',
287 'assign_impressions_param_type' => 'always',
288 'assign_impressions_param_custom_period_times' => 1,
289 'assign_impressions_param_custom_period' => 'session',
290 'opening_sound' => [
291 'source' => 'none',
292 'file' => '',
293 'url' => '',
294 ],
295 'assign_cookietype' => 'never',
296 'assign_cookietype_param_custom_period_times' => 1,
297 'assign_cookietype_param_custom_period' => 'days',
298 'box_auto_close' => false,
299 'box_auto_close_seconds' => 5,
300 'autofocus' => false,
301 'close_on_esc' => false,
302
303 // Actions
304 'actions' => [],
305
306 // Display Conditions
307 'display_conditions_type' => 'all',
308 'mirror_box' => '',
309 'rules' => [
310 [
311 'matching_method' => 'all',
312 'enabled' => true,
313 'rules' => [
314 [
315 'enabled' => true,
316 'name' => '',
317 'operator' => '',
318 'value' => ''
319 ]
320 ]
321 ]
322 ],
323
324 'position' => 'center',
325
326 'width' => [
327 'desktop' => '500px'
328 ],
329 'height' => [
330 'desktop' => 'auto'
331 ],
332 'padding' => [
333 'desktop' => [
334 'top' => '30px',
335 'right' => '30px',
336 'bottom' => '30px',
337 'left' => '30px'
338 ]
339 ],
340 'margin' => [
341 'desktop' => [
342 'top' => '',
343 'right' => '',
344 'bottom' => '',
345 'left' => ''
346 ]
347 ],
348 'closebutton' => [
349 'show' => '1',
350 'source' => 'icon',
351 'color' => 'rgba(136, 136, 136, 1)',
352 'hover' => 'rgba(85, 85, 85, 1)',
353 'size' => 30,
354 'image' => '',
355 'mediaId' => false,
356 'delay' => 0
357 ],
358 'backgroundcolor' => '#ffffff',
359 'boxshadow' => true,
360 'animationin' => 'fadeIn',
361 'animationout' => 'fadeOut',
362 'animation_type' => 'slide',
363 'duration' => 0.3,
364 'border' => [
365 'width' => '0',
366 'style' => 'solid',
367 'color' => 'rgba(0, 0, 0, 0.4)'
368 ],
369 'borderradius' => [
370 'desktop' => [
371 'topLeft' => '0px',
372 'topRight' => '0px',
373 'bottomLeft' => '0px',
374 'bottomRight' => '0px'
375 ]
376 ],
377 // Background Overlay
378 'overlay' => true,
379 'overlay_color' => 'rgba(0, 0, 0, 0.2)',
380 'overlayblurradius' => 0,
381 'overlayclick' => true,
382 // Background Image
383 'bgimage' => false,
384 'bgimagefile' => '',
385 'bgrepeat' => 'Repeat',
386 'bgsize' => 'Auto',
387 'bgposition' => 'Left Top',
388
389 // Advanced
390 'customcode' => '',
391 'customcss' => '',
392 'testmode' => false,
393 'preventpagescroll' => false,
394 'stats' => true,
395 'classsuffix' => '',
396 'zindex' => 99999,
397
398
399
400 // Deprecated
401 'fontsize' => [
402 'desktop' => '16px'
403 ],
404 'textcolor' => '#444444',
405 'aligncontent' => ''
406 ];
407 }
408
409 public function register()
410 {
411 register_meta('post', 'firebox_meta', [
412 'object_subtype' => 'firebox',
413 'show_in_rest' => [
414 'schema' => [
415 'type' => 'object',
416 'additionalProperties' => true
417 ]
418 ],
419 'type' => 'object',
420 'single' => true,
421 'auth_callback' => function($allowed, $meta_key, $post_id, $user_id, $cap, $caps) {
422 return current_user_can('edit_fireboxes');
423 }
424 ]);
425 }
426 }