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.14 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 All 123 releases
firebox / Inc / Framework / Inc / Base / FieldsParser.php

FieldsParser.php in FireBox – WooCommerce Popup Builder, Exit Intent Popup, Email Optin & Cart Abandonment 3.1.12, at Inc/Framework/Inc/Base/FieldsParser.php

457 lines 9.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * @package FirePlugins Framework
4 * @version 1.2.3
5 *
6 * @author FirePlugins <[email protected]>
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 FPFramework\Base;
13
14 if (!defined('ABSPATH'))
15 {
16 exit; // Exit if accessed directly.
17 }
18
19 use FPFramework\Helpers\HTML;
20 use FPFramework\Helpers\StringHelper;
21
22 class FieldsParser
23 {
24 /**
25 * The Bind Data
26 *
27 * @var array
28 */
29 protected $bind_data;
30
31 /**
32 * The fields path of plugin.
33 *
34 * @var string
35 */
36 protected $fields_path;
37
38 /**
39 * The fields name prefix.
40 * This is used to prefix our field names.
41 *
42 * @var string
43 */
44 protected $fields_name_prefix;
45
46 public function __construct($data = [])
47 {
48 $this->bind_data = isset($data['bind_data']) ? (array) $data['bind_data'] : [];
49 $this->fields_path = isset($data['fields_path']) ? (array) $data['fields_path'] : null;
50 $this->fields_name_prefix = isset($data['fields_name_prefix']) ? $data['fields_name_prefix'] : \FPFramework\Helpers\FieldsHelper::$fields_prefix;
51 }
52
53 /**
54 * Renders the sections, in left, plain or right orientation
55 *
56 * @param array $section
57 *
58 * @return void
59 */
60 public function renderContentFields($section)
61 {
62 if (!isset($section['content']) && !is_array($section['content']) && !count($section['content']))
63 {
64 return;
65 }
66
67 // loop sections
68 foreach ($section['content'] as $_section)
69 {
70 // render section fields
71 $this->renderSectionFields($_section);
72 }
73 }
74
75 /**
76 * Renders all fields within a section
77 *
78 * @param array $section
79 *
80 * @return void
81 */
82 public function renderSectionFields($section)
83 {
84 // Hide section if set
85 if (isset($section['hide']))
86 {
87 return;
88 }
89
90 if (!isset($section['fields']))
91 {
92 return;
93 }
94
95 // wrap section title and fields - start
96 $this->wrapFieldsSectionStart($section);
97
98 // Render title of this set of fields
99 $this->renderSectionTitle($section);
100
101 // start - wrap the fields in a parent div
102 $this->checkAndStartWrapSectionFieldsInDiv($section);
103
104 // render all fields
105 $this->renderFields($section['fields']);
106
107 // end - wrap the fields in a parent div
108 $this->checkAndEndWrapSectionFieldsInDiv($section);
109
110 // wrap section title and fields - end
111 $this->wrapFieldsSectionEnd($section);
112 }
113
114 /**
115 * Renders given fields
116 *
117 * @param string $fields
118 *
119 * @return void
120 */
121 public function renderFields($fields)
122 {
123 if (!is_array($fields) || !count($fields))
124 {
125 return;
126 }
127
128 foreach ($fields as $key => $field)
129 {
130 $this->loadField($field);
131 }
132 }
133
134 /**
135 * Loads the field
136 *
137 * @param array $field
138 *
139 * @return mixed
140 */
141 public function loadField($field)
142 {
143 if (!isset($field['type']))
144 {
145 return;
146 }
147
148 if (!$field_path = $this->getFieldPath($field))
149 {
150 return;
151 }
152
153 // check if we need this field to have a name without prepending the prefix
154 $name_clean = isset($field['name_clean']) ? (bool) $field['name_clean'] : false;
155
156 // set field name prefix
157 if (isset($field['name']) && !$name_clean)
158 {
159 $field['name_key'] = $field['name'];
160 }
161
162 // set name prefix for the field
163 if ($this->fields_name_prefix)
164 {
165 $field['name_prefix'] = $this->fields_name_prefix;
166 }
167
168 // set field path
169 $field['field_path'] = $field_path;
170
171 // full field class name
172 $field_class = $field_path . $field['type'];
173
174 // bind data
175 if ($this->bind_data && isset($field['name_key']))
176 {
177 // get binded value
178 $binded_value = $this->getBindDataFieldValue($field['name_key']);
179
180 // set field value
181 if($binded_value || $binded_value == '0')
182 {
183 $field['value'] = $binded_value;
184 }
185 }
186
187 // initialize field
188 $field_class = new $field_class($field);
189
190 $field_class->render();
191 }
192
193 /**
194 * Returns the field path. Whether this field exists in the framework or in a plugin.
195 *
196 * @param array $field
197 *
198 * @return mixed
199 */
200 private function getFieldPath($field)
201 {
202 static $resolved = [];
203
204 $field_type = $field['type'];
205 $cache_key = $field_type . '|' . implode(',', (array) $this->fields_path);
206
207 if (array_key_exists($cache_key, $resolved))
208 {
209 return $resolved[$cache_key];
210 }
211
212 if ($this->fields_path && is_array($this->fields_path))
213 {
214 foreach ($this->fields_path as $fields_path)
215 {
216 // ensure field exists in field path
217 if (!class_exists($fields_path . $field_type))
218 {
219 continue;
220 }
221
222 return $resolved[$cache_key] = $fields_path;
223 }
224 }
225
226 // check framework
227 $framework_fields_path = '\\FPFramework\\Base\\Fields\\';
228 if (class_exists($framework_fields_path . $field_type))
229 {
230 return $resolved[$cache_key] = $framework_fields_path;
231 }
232
233 return $resolved[$cache_key] = false;
234 }
235
236 /**
237 * Gets the value from bind data based on field name
238 *
239 * @param string $name
240 *
241 * @return mixed
242 */
243 protected function getBindDataFieldValue($name)
244 {
245 if (!$name)
246 {
247 return null;
248 }
249
250 $value = '';
251 $found = true;
252
253 // make sure bind data are set
254 if (!isset($this->bind_data))
255 {
256 return null;
257 }
258
259 // split name as format is key.key2.key3
260 $splitted_name = explode('.', $name);
261
262 // make sure we splitted the name and have data to use
263 if (!count($splitted_name))
264 {
265 // check if it exists
266 if (!isset($this->bind_data[$name]))
267 {
268 return null;
269 }
270
271 return $this->bind_data[$name];
272 }
273
274 // get first name item
275 $key = $splitted_name[0];
276
277 // if we have 1 name key only
278 if (count($splitted_name) == 1)
279 {
280 // make sure it exists
281 if (!isset($this->bind_data[$key]))
282 {
283 return null;
284 }
285
286 return $this->bind_data[$key];
287 }
288
289 // get the bind data to use and find the value
290 $value = $this->bind_data;
291
292 // loop given name keys to find value
293 foreach ($splitted_name as $n)
294 {
295 $value = is_object($value) ? (array) $value : $value;
296
297 if (!isset($value[$n]))
298 {
299 $found = null;
300 break;
301 }
302
303 $value = $value[$n];
304 }
305
306 if (!$found)
307 {
308 return null;
309 }
310
311 return $value;
312 }
313
314 /**
315 * Wraps the section title and fields.
316 *
317 * @param array $section
318 *
319 * @return void
320 */
321 private function wrapFieldsSectionStart($section)
322 {
323 if (!isset($section['fields']) && !is_array($section['fields']) && count($section['fields']) < 2 && !isset($section['wrapper']))
324 {
325 return;
326 }
327
328 $showon = isset($section['wrapper']['showon']) ? $section['wrapper']['showon'] : '';
329
330 // outer classes
331 $default_outer_classes = ['fpf-fields-wrapper'];
332 $outer_classes = (isset($section['wrapper']) && isset($section['wrapper']['outer_class'])) ? $section['wrapper']['outer_class'] : $default_outer_classes;
333
334 // inner classes
335 $default_classes = ['grid-x', 'grid-margin-x', 'grid-margin-y'];
336 $inner_classes = isset($section['wrapper']) && isset($section['wrapper']['class']) ? $section['wrapper']['class'] : $default_classes;
337
338 // render div openings
339 if ($outer_classes)
340 {
341 echo HTML::renderStartDiv(['showon' => $showon, 'class' => $outer_classes]); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
342 }
343
344 if ($inner_classes)
345 {
346 echo HTML::renderStartDiv(['class' => $inner_classes]); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
347 }
348 }
349
350 /**
351 * Ends the wrap of section title and fields.
352 *
353 * @param array $section
354 *
355 * @return void
356 */
357 private function wrapFieldsSectionEnd($section)
358 {
359 if (!isset($section['fields']) && !is_array($section['fields']) && count($section['fields']) < 2 && !isset($section['wrapper']))
360 {
361 return;
362 }
363
364 // outer classes
365 $default_outer_classes = ['fpf-fields-wrapper'];
366 $outer_classes = (isset($section['wrapper']) && isset($section['wrapper']['outer_class'])) ? $section['wrapper']['outer_class'] : $default_outer_classes;
367
368 // inner classes
369 $default_classes = ['grid-x', 'grid-margin-x', 'grid-margin-y'];
370 $inner_classes = isset($section['wrapper']) && isset($section['wrapper']['class']) ? $section['wrapper']['class'] : $default_classes;
371
372 // render div openings
373 if ($outer_classes)
374 {
375 echo HTML::renderEndDiv(); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
376 }
377
378 if ($inner_classes)
379 {
380 echo HTML::renderEndDiv(); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
381 }
382 }
383
384 /**
385 * Renders the title of the fields section
386 *
387 * @param array $section
388 *
389 * @return string
390 */
391 protected function renderSectionTitle($section)
392 {
393 if (!isset($section['title']))
394 {
395 return;
396 }
397
398 // set default heading type
399 if (!isset($section['title']['heading_type']))
400 {
401 $section['title']['heading_type'] = 'h4';
402 }
403
404 $section['title']['input_class'][] = 'cell large-3 fpf-section-heading';
405
406 echo HTML::renderHeading($section['title']); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
407 }
408
409 /**
410 * Checks if we have a section title and wraps the fields with a div
411 *
412 * @param array $section
413 *
414 * @return string
415 */
416 protected function checkAndStartWrapSectionFieldsInDiv($section)
417 {
418 if (!isset($section['title']))
419 {
420 return;
421 }
422
423 echo HTML::renderStartDiv(['class' => ['cell', 'large-auto', 'fpf-section-content']]); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
424
425 echo HTML::renderStartDiv(['class' => ['grid-x', 'grid-margin-x', 'grid-margin-y']]); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
426 }
427
428 /**
429 * Checks if we have a section title and close the div that wrapped the fields
430 *
431 * @param array $section
432 *
433 * @return string
434 */
435 protected function checkAndEndWrapSectionFieldsInDiv($section)
436 {
437 if (!isset($section['title']))
438 {
439 return;
440 }
441
442 echo HTML::renderEndDiv(); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
443 echo HTML::renderEndDiv(); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
444 }
445
446 /**
447 * Set form bind data
448 *
449 * @param array $bind_data
450 *
451 * @return void
452 */
453 public function setBindData($bind_data)
454 {
455 $this->bind_data = $bind_data;
456 }
457 }