PluginProbe ʕ •ᴥ•ʔ
PixelYourSite – Your smart PIXEL (TAG) & API Manager / 11.1.4.2
PixelYourSite – Your smart PIXEL (TAG) & API Manager v11.1.4.2
11.2.0.6 trunk 1.0 1.01 1.02 1.03 1.04 1.05 1.05.1 10.0.0 10.0.1 10.0.1.1 10.0.1.2 10.0.2 10.0.3 10.0.3.1 10.0.4 10.1.0 10.1.1 10.1.1.1 10.1.1.2 10.1.2.1 10.1.3 10.2.0 10.2.0.1 10.2.0.2 10.2.1 11.0.0 11.0.0.1 11.0.0.2 11.0.0.3 11.0.0.4 11.0.1 11.0.1.1 11.0.1.2 11.0.2 11.1.0 11.1.1 11.1.2 11.1.3 11.1.4 11.1.4.1 11.1.4.2 11.1.5 11.1.5.1 11.1.5.2 11.2.0 11.2.0.1 11.2.0.2 11.2.0.3 11.2.0.4 11.2.0.5 2.0 2.1 2.2 2.2.1 2.2.2 2.2.3 2.2.4 2.2.5 2.2.7 2.8.10 2.8.9 3.0 3.0.1 3.0.2 3.0.3 3.1.0 4.0.0 4.0.1 4.0.2 4.0.3 5.0.0 5.0.1 5.0.2 5.0.3 5.0.4 5.0.5.2 5.0.6 5.0.7 5.0.8 5.0.9 5.1.0 5.2.0 5.2.1 5.3.0 5.3.1 5.3.2 5.3.3 5.3.4 7.0.0 7.0.1 7.0.2 7.0.3 7.0.4 7.0.5 7.1.0 7.1.1 7.1.10 7.1.11 7.1.12 7.1.13 7.1.14 7.1.2 7.1.3 7.1.4 7.1.5 7.1.6 7.1.7 7.1.8 7.1.9 7.2.0 7.2.1 7.2.1.1 7.3.0 8.0.0 8.0.1 8.0.2 8.0.3 8.0.4 8.0.5 8.0.6 8.0.7 8.0.8 8.0.9 8.1.0 8.1.1 8.2.0 8.2.1 8.2.10 8.2.11 8.2.12 8.2.13 8.2.14 8.2.15 8.2.16 8.2.17 8.2.18 8.2.2 8.2.3 8.2.4 8.2.5 8.2.6 8.2.7 8.2.8 9.0.0 9.1.0 9.1.1 9.2.0 9.2.1 9.2.2 9.3.0 9.3.1 9.3.2 9.3.3 9.3.4 9.3.5 9.3.6 9.3.7 9.3.8 9.3.8.1 9.3.9 9.4.0 9.4.0.1 9.4.1 9.4.2 9.4.3 9.4.5 9.4.5.1 9.4.6 9.4.7 9.4.7.1 9.5.0 9.5.0.1 9.5.1 9.5.1.1 9.5.3 9.5.4 9.5.5 9.6.0 9.6.0.1 9.6.1 9.6.1.1 9.6.2 9.7.0 9.7.0.1 9.7.1 9.7.2
pixelyoursite / includes / class-settings.php
pixelyoursite / includes Last commit date
enrich 9 months ago events 5 months ago formEvents 1 year ago logger 1 year ago views 5 months ago class-consent.php 5 months ago class-custom-event-factory.php 1 year ago class-custom-event.php 5 months ago class-event-id-generator.php 5 years ago class-events-manager-ajax_hook.php 5 months ago class-events-manager.php 5 months ago class-fixed-notices.php 1 year ago class-optin-notices.php 1 year ago class-pixel.php 7 years ago class-plugin-updater.php 9 months ago class-plugin.php 7 years ago class-pys.php 5 months ago class-settings.php 5 months ago functions-admin.php 1 year ago functions-buttons.php 1 year ago functions-common.php 5 months ago functions-custom-event.php 10 months ago functions-edd.php 2 years ago functions-gdpr.php 11 months ago functions-license.php 10 months ago functions-migrate.php 9 months ago functions-promo-notices.php 1 year ago functions-system-report.php 7 years ago functions-update-plugin.php 6 years ago functions-woo.php 11 months ago options_defaults.json 8 months ago options_fields.json 8 months ago
class-settings.php
1385 lines
1 <?php
2
3 namespace PixelYourSite;
4
5 if ( ! defined( 'ABSPATH' ) ) {
6 exit; // Exit if accessed directly.
7 }
8
9 abstract class Settings {
10
11 /**
12 * Options section slug
13 *
14 * @var string
15 */
16 private $slug;
17
18 /**
19 * Options values
20 *
21 * @var array
22 */
23 private $values = array();
24
25 /**
26 * Database option key
27 *
28 * @var string
29 */
30 private $option_key = '';
31
32 /**
33 * Default options values
34 *
35 * @var array
36 */
37 private $defaults = array();
38
39 /**
40 * List of all options
41 *
42 * @var array
43 */
44 private $options = array();
45
46 private $defaults_json_path;
47 private static ?bool $table_exists = null;
48
49 public static function storage_table(): string {
50 global $wpdb;
51 return $wpdb->prefix . 'pys_options';
52 }
53
54 private static function table_exists(): bool {
55 if (self::$table_exists !== null) {
56 return self::$table_exists;
57 }
58
59 // Try object cache first
60 $cached = wp_cache_get('pys_options_table_exists', 'pys');
61 if ($cached !== false) {
62 return self::$table_exists = (bool) $cached;
63 }
64
65 global $wpdb;
66 $table = self::storage_table();
67 $exists = (bool) $wpdb->get_var(
68 $wpdb->prepare("SHOW TABLES LIKE %s", $table)
69 );
70 if (!$exists) {
71 // Create table
72 $charset_collate = $wpdb->get_charset_collate();
73 $sql = "CREATE TABLE IF NOT EXISTS $table (
74 id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
75 option_name VARCHAR(191) NOT NULL,
76 option_value LONGTEXT NOT NULL,
77 migrated TINYINT(1) NOT NULL DEFAULT 1,
78 updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
79 PRIMARY KEY (id),
80 UNIQUE KEY option_name (option_name)
81 ) $charset_collate;";
82 require_once ABSPATH . 'wp-admin/includes/upgrade.php';
83 dbDelta($sql);
84
85 // After dbDelta table exists
86 $exists = true;
87 }
88 // Cache for 12h; adjust as you like
89 wp_cache_set('pys_options_table_exists', $exists, 'pys', 12 * HOUR_IN_SECONDS);
90 return self::$table_exists = $exists;
91 }
92 /**
93 * Constructor
94 *
95 * @param string $slug
96 */
97 public function __construct( $slug ) {
98 $this->slug = $slug;
99 $this->option_key = 'pys_' . $slug;
100 }
101
102 public function getSlug() {
103 return $this->slug;
104 }
105
106 /**
107 * Load options fields and options defaults from specified files
108 *
109 * @param string $fields Path to options fields file
110 * @param string $defaults Path to options defaults file
111 */
112 public function locateOptions( $fields, $defaults ) {
113
114 $this->loadJSON( $fields, false );
115 $this->loadJSON( $defaults, true );
116
117 $this->defaults_json_path = $defaults;
118 self::table_exists();
119 }
120
121 public function resetToDefaults() {
122
123 if ( ! file_exists( $this->defaults_json_path ) ) {
124 return;
125 }
126
127 // List of fields to preserve
128 $preserve_fields = [
129 'enabled',
130
131 'tracking_id',
132 'enable_server_container',
133 'server_container_url',
134 'transport_url',
135
136 'pixel_id',
137 'use_server_api',
138 'advanced_matching_enabled',
139 'server_access_api_token',
140 'use_server_api',
141 'verify_meta_tag',
142
143 'gtm_id',
144 'gtm_just_data_layer',
145 ];
146
147 // Load current values
148 $this->maybeLoad();
149 $current_values = $this->values;
150
151 // Preserve the values of specified fields
152 $preserved_values = [];
153 foreach ( $preserve_fields as $field ) {
154 if ( isset( $current_values[ $field ] ) ) {
155 $preserved_values[ $field ] = $current_values[ $field ];
156 }
157 }
158
159 // Load default values
160 $content = file_get_contents( $this->defaults_json_path );
161 $default_values = json_decode( $content, true );
162
163 // Merge preserved values with default values
164 $merged_values = array_merge( $default_values, $preserved_values );
165
166 // Update options with the merged values
167 $this->updateOptions( $merged_values );
168 }
169
170 /**
171 * Load options fields or options defaults from specified file
172 *
173 * @param string $file
174 * @param bool $is_defaults
175 */
176 private function loadJSON( $file, $is_defaults ) {
177
178 if ( ! file_exists( $file ) ) {
179 return;
180 }
181
182 $content = file_get_contents( $file );
183 $values = json_decode( $content, true );
184
185 if ( null === $values ) {
186 return;
187 }
188
189 if ( $is_defaults ) {
190 $this->defaults = $values;
191 } else {
192 $this->options = $values;
193 }
194
195 }
196
197 /**
198 * Reading from a new table.
199 *
200 * @return array|null array of values or null if there is no entry
201 */
202 private function pys_get_from_storage( $option_key ) {
203 global $wpdb;
204 if (!self::$table_exists) {
205 return null;
206 }
207
208 $table = self::storage_table();
209
210 // Safe to query the table
211 $row = $wpdb->get_row(
212 $wpdb->prepare(
213 "SELECT option_value FROM $table WHERE option_name = %s LIMIT 1",
214 $option_key
215 ),
216 ARRAY_A
217 );
218
219 if ( ! $row ) {
220 return null;
221 }
222
223 $val = maybe_unserialize( $row['option_value'] );
224 return is_array( $val ) ? $val : [];
225 }
226 /**
227 * Write to a new table.
228 *
229 * @return bool
230 */
231 private function pys_set_in_storage( $option_key, $value, $migrated = 1 ) {
232 global $wpdb;
233 if (!self::$table_exists) {
234 return null;
235 }
236 $table = self::storage_table();
237 $data = [
238 'option_value' => maybe_serialize( $value ),
239 'migrated' => (int) $migrated,
240 ];
241 $format = [ '%s', '%d' ];
242 // Checking if there is a record
243 $exists = $wpdb->get_var(
244 $wpdb->prepare(
245 "SELECT COUNT(*) FROM {$table} WHERE option_name = %s",
246 $option_key
247 )
248 );
249
250 if ( $exists ) {
251 // We are updating
252 $result = $wpdb->update(
253 $table,
254 $data,
255 [ 'option_name' => $option_key ],
256 $format,
257 [ '%s' ]
258 );
259 } else {
260 // Insert a new one
261 $result = $wpdb->insert(
262 $table,
263 array_merge( [ 'option_name' => $option_key ], $data ),
264 array_merge( [ '%s' ], $format )
265 );
266 }
267
268 return $result !== false;
269 }
270 /**
271 * Add new option field
272 *
273 * @param string $key
274 * @param string $field_type
275 * @param mixed $default
276 */
277 public function addOption( $key, $field_type, $default ) {
278 $this->options[ $key ] = $field_type;
279 $this->defaults[ $key ] = $default;
280 }
281
282 /**
283 * Gets an option value or its default value
284 *
285 * @param string $key Option key
286 * @param mixed $fallback Option fallback value if no default is set
287 *
288 * @return mixed The value specified for the option or a default value for the option.
289 */
290 public function getOption( $key, $fallback = null ) {
291
292 $this->maybeLoad();
293
294 // get option default if unset
295 if ( ! isset( $this->values[ $key ] ) ) {
296 $this->values[ $key ] = isset( $this->defaults[ $key ] )
297 ? $this->defaults[ $key ] : null;
298 }
299
300 // use fall back value if default is not set
301 if ( null === $this->values[ $key ] && ! is_null( $fallback ) ) {
302 $this->values[ $key ] = $fallback;
303 }
304
305 return $this->values[ $key ];
306
307 }
308 public function setOption($key, $value){
309 $this->maybeLoad();
310 if (isset($value) ) {
311 $this->values[ $key ] = $value;
312 }
313 }
314 /**
315 * Load values from database
316 *
317 * @param bool $force Force options load
318 */
319 private function maybeLoad( $force = false ) {
320
321 if ( ! $force && ! empty( $this->values ) ) {
322 return; // already loaded
323 }
324
325 // 1) Let's try a new table
326 $stored = $this->pys_get_from_storage( $this->option_key );
327 if ( is_array( $stored ) ) {
328 $this->values = wp_parse_args( $stored, $this->defaults );
329 return;
330 }
331
332 // 2) Let's try the old way (wp_options)
333 $legacy = get_option( $this->option_key, null );
334 if ( is_array( $legacy ) ) {
335 // Migration to a new table
336 $this->pys_set_in_storage( $this->option_key, $legacy, 1 );
337 $this->values = wp_parse_args( $legacy, $this->defaults );
338 return;
339 }
340
341 // 3) If nothing, we take defaults
342 $this->values = $this->defaults;
343
344 }
345
346 public function reloadOptions() {
347 $this->maybeLoad( true );
348 }
349
350 /**
351 * Sanitize and save options
352 *
353 * @param null|array $values Optional. If set, options values will be received from param instead of $_POST.
354 */
355 public function updateOptions( $values = null ) {
356
357 $this->maybeLoad();
358
359 if ( is_array( $values ) ) {
360 $form_data = $values;
361 } else {
362 if ( isset( $_POST['pys'][ $this->slug ] ) && is_array( $_POST['pys'][ $this->slug ] ) ) {
363 $form_data = $_POST['pys'][ $this->slug ];
364 } else {
365 $form_data = [];
366 }
367 }
368
369 // We only apply valid fields and sanitize them
370 foreach ( $form_data as $key => $value ) {
371 if ( isset( $this->options[ $key ] ) ) {
372 $this->values[ $key ] = $this->sanitize_form_field( $key, $value );
373 }
374 }
375
376 // We write to a new table (primarily)
377 $written = $this->pys_set_in_storage( $this->option_key, $this->values, 1 );
378
379 if ( ! $written ) {
380 // Fallback: if we couldn't write to our table, we save it in wp_options
381 update_option( $this->option_key, $this->values, false );
382 }
383
384 }
385
386 /**
387 * Sanitize form field
388 *
389 * @param string $key Field key
390 * @param array $value Field value
391 *
392 * @return mixed Sanitized field value
393 */
394 private function sanitize_form_field( $key, $value ) {
395
396 $type = $this->options[ $key ];
397
398 // look for very specific sanitization filter
399 $filter_name = "{$this->option_key}_settings_sanitize_{$key}_field";
400 if ( has_filter( $filter_name ) ) {
401 return apply_filters( $filter_name, $value );
402 }
403
404 // look for a sanitize_FIELDTYPE_field method
405 if ( is_callable( array( $this, 'sanitize_' . $type . '_field' ) ) ) {
406 return $this->{'sanitize_' . $type . '_field'}( $value );
407 }
408
409 // fallback to text
410 return $this->sanitize_text_field( $value );
411
412 }
413
414 /**
415 * Output text input
416 *
417 * @param $key
418 * @param string $placeholder
419 * @param bool $disabled
420 * @param bool $hidden
421 * @param bool $empty
422 */
423 public function render_text_input( $key, $placeholder = '', $disabled = false, $hidden = false, $empty = false, $type = 'standard' ) {
424
425 $attr_name = "pys[$this->slug][$key]";
426 $attr_id = 'pys_' . $this->slug . '_' . $key;
427 $attr_value = $empty == false ? $this->getOption( $key ) : "";
428
429 $classes = array(
430 "input-$type"
431 );
432
433 if ( $hidden ) {
434 $classes[] = 'form-control-hidden';
435 }
436
437 $classes = implode( ' ', $classes );
438 ?>
439
440 <input <?php disabled( $disabled ); ?>
441 type="text"
442 name="<?php echo esc_attr( $attr_name ); ?>"
443 id="<?php echo esc_attr( $attr_id ); ?>"
444 value="<?php echo esc_attr( $attr_value ); ?>"
445 placeholder="<?php echo esc_attr( $placeholder ); ?>"
446 class="<?php echo esc_attr( $classes ); ?>">
447 <?php
448 }
449
450 /**
451 * Output text input
452 *
453 * @param $key
454 * @param string $placeholder
455 * @param bool $disabled
456 * @param bool $hidden
457 * @param bool $empty
458 */
459 public function render_password_input( $key, $placeholder = '', $disabled = false, $hidden = false, $empty = false, $type = 'standard' ) {
460
461 $attr_name = "pys[$this->slug][$key]";
462 $attr_id = 'pys_' . $this->slug . '_' . $key;
463 $attr_value = $empty == false ? $this->getOption( $key ) : "";
464
465 $classes = array(
466 "input-$type",
467 "passwordInput"
468 );
469
470 if ( $hidden ) {
471 $classes[] = 'form-control-hidden';
472 }
473
474 $classes = implode( ' ', $classes );
475 ?>
476 <div class="password-block">
477 <input <?php disabled( $disabled ); ?>
478 type="text"
479 name="<?php echo esc_attr( $attr_name ); ?>"
480 id="<?php echo esc_attr( $attr_id ); ?>"
481 value="<?php echo esc_attr( $attr_value ); ?>"
482 placeholder="<?php echo esc_attr( $placeholder ); ?>"
483 class="<?php echo esc_attr( $classes ); ?>"
484 style="display:none;"
485 >
486
487 <input type="text" class="maskedInput input-<?php echo esc_attr( $type ); ?>" data-value="<?php echo esc_attr( $attr_value ); ?>">
488 </div>
489 <?php
490 }
491 /**
492 * Output pixel ID input (text)
493 *
494 * @param $key
495 * @param string $placeholder
496 * @param int $index
497 */
498 public function render_pixel_id( $key, $placeholder = '', $index = 0 ) {
499
500 $attr_name = "pys[$this->slug][$key][]";
501 $attr_id = 'pys_' . $this->slug . '_' . $key . '_' . $index;
502
503 $values = (array) $this->getOption( $key );
504 $attr_value = isset( $values[ $index ] ) ? $values[ $index ] : null;
505
506 ?>
507
508 <input type="text" name="<?php echo esc_attr( $attr_name ); ?>"
509 id="<?php echo esc_attr( $attr_id ); ?>"
510 value="<?php echo esc_attr( $attr_value ); ?>"
511 placeholder="<?php echo esc_attr( $placeholder ); ?>"
512 class="input-standard">
513
514 <?php
515
516 }
517
518 /**
519 * Output text area input array item
520 *
521 * @param $key
522 * @param string $placeholder
523 * @param int $index
524 */
525 public function render_text_area_array_item( $key, $placeholder = '', $index = 0, $enabled = true ) {
526
527 $attr_name = "pys[$this->slug][$key][]";
528 $attr_id = 'pys_' . $this->slug . '_' . $key . '_' . $index;
529
530 $values = (array) $this->getOption( $key );
531 $attr_value = isset( $values[ $index ] ) ? $values[ $index ] : null;
532
533 ?>
534
535 <textarea type="text" name="<?php echo esc_attr( $attr_name ); ?>"
536 id="<?php echo esc_attr( $attr_id ); ?>"
537 placeholder="<?php echo esc_attr( $placeholder ); ?>"
538 class="textarea-standard" <?= !$enabled ? 'disabled' : ''; ?>><?php echo esc_attr( $attr_value ); ?></textarea>
539
540 <?php
541 }
542
543 /**
544 * Output text input array item
545 *
546 * @param $key
547 * @param string $placeholder
548 * @param int $index
549 */
550 public function render_text_input_array_item( $key, $placeholder = '', $index = 0,$hidden = false ) {
551
552 $attr_name = "pys[$this->slug][$key][]";
553 $attr_id = 'pys_' . $this->slug . '_' . $key . '_' . $index;
554
555 $values = (array) $this->getOption( $key );
556 $attr_value = isset( $values[ $index ] ) ? $values[ $index ] : null;
557
558 ?>
559
560 <input type=<?=$hidden? "hidden": "text"?> name="<?php echo esc_attr( $attr_name ); ?>"
561 id="<?php echo esc_attr( $attr_id ); ?>"
562 value="<?php echo esc_attr( $attr_value ); ?>"
563 placeholder="<?php echo esc_attr( $placeholder ); ?>"
564 class="input-standard">
565 <?php
566 }
567
568 /**
569 * Output text area input
570 *
571 * @param $key
572 * @param string $placeholder
573 * @param bool $disabled
574 * @param bool $hidden
575 */
576 public function render_text_area_input( $key, $placeholder = '', $disabled = false, $hidden = false ) {
577
578 $attr_name = "pys[$this->slug][$key]";
579 $attr_id = 'pys_' . $this->slug . '_' . $key;
580 $attr_value = $this->getOption( $key );
581
582 $classes = array( 'form-control' );
583
584 if( $hidden ) {
585 $classes[] = 'form-control-hidden';
586 }
587
588 $classes = implode( ' ', $classes );
589
590 ?>
591
592 <textarea <?php disabled( $disabled ); ?> name="<?php echo esc_attr( $attr_name ); ?>"
593 id="<?php echo esc_attr( $attr_id ); ?>" rows="5"
594 placeholder="<?php echo esc_attr( $placeholder ); ?>"
595 class="<?php echo esc_attr( $classes ); ?>"><?php esc_html_e( $attr_value ); ?></textarea>
596
597 <?php
598
599 }
600
601 /**
602 * Output checkbox input stylized as switcher
603 *
604 * @param $key
605 * @param bool $collapse
606 * @param bool $disabled
607 */
608 public function render_switcher_input( $key, $collapse = false, $disabled = false, $default = false, $type = 'secondary') {
609 $attr_name = "pys[$this->slug][$key]";
610 $attr_id = 'pys_' . $this->slug . '_' . $key;
611 $attr_value = $this->getOption( $key );
612 $input_class = $label_class = '';
613
614 $classes = array( "$type-switch" );
615
616 if ( $collapse ) {
617 $classes[] = 'collapse-control';
618 }
619
620 if ( $disabled ) {
621 $classes[] = 'disabled';
622 $attr_name = "";
623 $attr_value = $default;
624 }
625
626 if ( $type === 'primary' ) {
627 $input_class = 'primary-switch-input';
628 $label_class = 'primary-switch-btn';
629 } elseif ( $type === 'secondary' ) {
630 $input_class = 'custom-switch-input';
631 $label_class = 'custom-switch-btn';
632 }
633
634 $classes = implode( ' ', $classes );
635
636 ?>
637
638 <div class="<?php echo esc_attr( $classes ); ?>">
639
640 <?php if ( !$disabled ) : ?>
641 <input type="hidden" name="<?php echo esc_attr( $attr_name ); ?>" value="0">
642 <?php endif; ?>
643
644 <?php if ( $collapse ) : ?>
645 <input type="checkbox" name="<?php echo esc_attr( $attr_name ); ?>"
646 value="1" <?php disabled( $disabled, true ); ?> <?php checked( $attr_value, true ); ?>
647 id="<?php echo esc_attr( $attr_id ); ?>"
648 class="<?php echo esc_attr( $input_class ); ?>"
649 data-target="pys_<?php echo esc_attr( $this->slug ); ?>_<?php echo esc_attr( $key ); ?>_panel">
650 <?php else : ?>
651 <input type="checkbox" name="<?php echo esc_attr( $attr_name ); ?>"
652 value="1" <?php disabled( $disabled, true ); ?> <?php checked( $attr_value, true ); ?>
653 id="<?php echo esc_attr( $attr_id ); ?>"
654 class="<?php echo esc_attr( $input_class ); ?>">
655 <?php endif; ?>
656
657 <label class="<?php echo esc_attr( $label_class ); ?>" for="<?php echo esc_attr( $attr_id ); ?>">
658 <?php if ( $type === 'primary' ) : ?>
659 <span class="<?php echo esc_attr( $label_class ); ?>-slider"></span>
660 <?php endif; ?>
661 </label>
662 </div>
663
664 <?php
665 }
666
667 public function render_switcher_input_array( $key, $index = 0 ) {
668
669 $attr_name = "pys[$this->slug][$key][]";
670 $attr_id = 'pys_' . $this->slug . '_' . $key . "_" . $index;
671 $attr_values = (array) $this->getOption( $key );
672 $value = "index_" . $index;
673 $valueIndex = array_search( $value, $attr_values );
674
675 $classes = array( 'secondary-switch' );
676 $classes = implode( ' ', $classes );
677
678 ?>
679
680 <div class="<?php echo esc_attr( $classes ); ?>">
681 <input type="checkbox"
682 name="<?php echo esc_attr( $attr_name ); ?>"
683 value="<?php echo esc_attr( $value ); ?>"
684 <?php echo $valueIndex !== false ? "checked" : "" ?>
685 id="<?php echo esc_attr( $attr_id ); ?>"
686 class="custom-switch-input <?php echo esc_attr( $key ); ?>">
687
688 <label class="custom-switch-btn" for="<?php echo esc_attr( $attr_id ); ?>"></label>
689 </div>
690
691 <?php
692
693 }
694
695 /**
696 * Output checkbox input
697 *
698 * @param $key
699 * @param $label
700 * @param bool $disabled
701 */
702 public function render_checkbox_input( $key, $label, $disabled = false ) {
703
704 $attr_name = "pys[$this->slug][$key]";
705 $attr_value = $this->getOption( $key );
706 $id = $key . "_" . random_int( 1, 1000000 );
707
708 ?>
709
710 <div class="small-checkbox">
711 <input type="hidden" name="<?php echo esc_attr( $attr_name ); ?>" value="0">
712 <input type="checkbox" id="<?php echo esc_attr( $id ); ?>" name="<?php echo esc_attr( $attr_name ); ?>"
713 value="1"
714 class="small-control-input" <?php disabled( $disabled, true ); ?> <?php checked( $attr_value, true ); ?>>
715 <label class="small-control small-checkbox-label" for="<?php echo esc_attr( $id ); ?>">
716 <span class="small-control-indicator"><i class="icon-check"></i></span>
717 <span class="small-control-description"><?php echo wp_kses_post( $label ); ?></span>
718 </label>
719 </div>
720
721 <?php
722 }
723
724 /**
725 * Output checkbox input array
726 *
727 * @param $key
728 * @param $label
729 * @param bool $disabled
730 */
731 public function render_checkbox_input_revert_array( $key, $label, $value, $disabled = false ) {
732
733 $attr_name = "pys[$this->slug][$key][]";
734 $attr_values = (array) $this->getOption( $key );
735
736 $isChecked = !in_array( $value, $attr_values );
737 $id = $key . "_" . random_int( 1, 1000000 );
738 ?>
739 <div class="small-checkbox">
740 <input type="hidden" name="<?php echo esc_attr( $attr_name ); ?>" value="<?= $value ?>">
741 <input type="checkbox" id="<?php echo esc_attr( $id ); ?>" name="<?php echo esc_attr( $attr_name ); ?>"
742 value="<?= "revert_" . $value ?>"
743 class="small-control-input" <?php disabled( $disabled, true ); ?>
744 <?php echo $isChecked ? "checked" : "" ?>>
745 <label class="small-control small-checkbox-label" for="<?php echo esc_attr( $id ); ?>">
746 <span class="small-control-indicator"><i class="icon-check"></i></span>
747 <span class="small-control-description"><?php echo wp_kses_post( $label ); ?></span>
748 </label>
749 </div>
750
751 <?php
752 }
753
754
755 /**
756 * @throws RandomException
757 */
758 public function render_checkbox_blacklist_input_array($key, $label, $value, $disabled = false ) {
759
760 $attr_name = "pys[$this->slug][$key][]";
761 $attr_values = (array) $this->getOption( $key );
762 $id = $key . "_" . random_int( 1, 1000000 );
763 $isChecked = in_array($value, $attr_values, true);
764 ?>
765 <div class="small-checkbox">
766 <input type="checkbox" id="<?php echo esc_attr( $id ); ?>" name="<?php echo esc_attr( $attr_name ); ?>"
767 value="<?= $value ?>"
768 class="small-control-input" <?php disabled( $disabled, true ); ?> <?php echo $isChecked ? "checked" : "" ?>>
769 <label class="small-control small-checkbox-label" for="<?php echo esc_attr( $id ); ?>">
770 <span class="small-control-indicator"><i class="icon-check"></i></span>
771 <span class="small-control-description"><?php echo wp_kses_post( $label ); ?></span>
772 </label>
773 </div>
774
775 <?php
776
777 }
778
779 /**
780 * Output radio input
781 *
782 * @param $key
783 * @param $value
784 * @param $label
785 * @param bool $disabled
786 * @param bool $with_pro_badge
787 */
788 public function render_radio_input( $key, $value, $label, $disabled = false, $with_pro_badge = false ) {
789
790 $id = $key . "_" . rand( 1, 1000000 );
791 $attr_name = "pys[$this->slug][$key]";
792 ?>
793
794 <div class="radio-standard">
795 <input type="radio"
796 name="<?php echo esc_attr( $attr_name ); ?>"
797 <?php disabled( $disabled, true ); ?>
798 class="custom-control-input"
799 id="<?php echo esc_attr( $id ); ?>"
800 <?php checked( $this->getOption( $key ), $value ); ?>
801 value="<?php echo esc_attr( $value ); ?>">
802 <label class="standard-control radio-checkbox-label" for="<?php echo esc_attr( $id ); ?>">
803 <span class="standard-control-indicator"></span>
804 <span class="standard-control-description"><?php echo wp_kses_post( $label ); ?></span>
805 <?php if ( $with_pro_badge ) {
806 renderCogBadge();
807 } ?>
808 </label>
809 </div>
810
811 <?php
812
813 }
814
815 /**
816 * Output number input
817 *
818 * @param $key
819 * @param null $placeholder
820 * @param bool $disabled
821 */
822 public function render_number_input( $key, $placeholder = '', $disabled = false, $max = null, $min = 0, $step = 'any', $suffix = '' ) {
823
824 $attr_name = "pys[$this->slug][$key]";
825 $attr_id = 'pys_' . $this->slug . '_' . $key;
826 $attr_value = $this->getOption( $key );
827
828 ?>
829 <div class="input-number-wrapper">
830 <button class="decrease"><i class="icon-minus"></i></button>
831 <input <?php disabled( $disabled ); ?> type="number" name="<?php echo esc_attr( $attr_name ); ?>"
832 id="<?php echo esc_attr( $attr_id ); ?>"
833 value="<?php echo esc_attr( $attr_value ); ?>"
834 placeholder="<?php echo esc_attr( $placeholder ); ?>"
835 min="<?= $min ?>"
836 <?php if ( $max != null ) : ?> max="<?= $max ?>" <?php endif; ?>
837 step="<?= $step ?>"
838 >
839 <button class="increase"><i class="icon-plus"></i></button>
840 </div>
841
842 <?php
843
844 }
845
846
847 /**
848 * Output number input
849 *
850 * @param $key
851 * @param null $placeholder
852 * @param bool $disabled
853 */
854 public function render_number_input_percent( $key, $placeholder = '', $disabled = false, $max = null, $min = 0, $step = 'any' ) {
855
856 $attr_name = "pys[$this->slug][$key]";
857 $attr_id = 'pys_' . $this->slug . '_' . $key;
858 $attr_value = $this->getOption( $key );
859
860 ?>
861 <div class="input-number-wrapper input-number-wrapper-percent">
862 <button class="decrease"><i class="icon-minus"></i></button>
863 <input <?php disabled( $disabled ); ?> type="number" name="<?php echo esc_attr( $attr_name ); ?>"
864 id="<?php echo esc_attr( $attr_id ); ?>"
865 value="<?php echo esc_attr( $attr_value ); ?>"
866 placeholder="<?php echo esc_attr( $placeholder ); ?>"
867 min="<?= $min ?>"
868 <?php if ( $max != null ) : ?> max="<?= $max ?>" <?php endif; ?>
869 step="<?= $step ?>"
870 >
871 <button class="increase"><i class="icon-plus"></i></button>
872 </div>
873
874 <?php
875
876 }
877 /**
878 * Output select input
879 *
880 * @param $key
881 * @param $options
882 * @param bool $disabled
883 * @param null $visibility_target
884 * @param null $visibility_value
885 */
886 public function render_select_input( $key, $options, $disabled = false, $visibility_target = null, $visibility_value = null, $searchable = false ) {
887
888 $attr_name = "pys[$this->slug][$key]";
889 $attr_id = 'pys_' . $this->slug . '_' . $key;
890
891 $classes = array( 'select-standard' );
892
893 if ( $visibility_target ) {
894 $classes[] = 'controls-visibility';
895 }
896 if($searchable){
897 $classes[] = 'pys-pysselect2';
898 }
899
900 $classes = implode( ' ', $classes );
901
902 ?>
903 <div class="select-standard-wrap">
904 <select class="<?php echo esc_attr( $classes ); ?>" id="<?php echo esc_attr( $attr_id ); ?>"
905 name="<?php echo esc_attr( $attr_name ); ?>" <?php disabled( $disabled ); ?>
906 data-target="<?php echo esc_attr( $visibility_target ); ?>"
907 data-value="<?php echo esc_attr( $visibility_value ); ?>" autocomplete="off">
908
909 <option value="" disabled selected>Please, select...</option>
910
911 <?php foreach ( $options as $option_key => $option_value ) : ?>
912 <option value="<?php echo esc_attr( $option_key ); ?>" <?php selected( $option_key, esc_attr( $this->getOption( $key ) ) ); ?> <?php disabled( $option_key, 'disabled' ); ?>><?php echo esc_attr( $option_value ); ?></option>
913 <?php endforeach; ?>
914 </select>
915 </div>
916 <?php
917 }
918
919 /**
920 * Output multi select input
921 *
922 * @param $key
923 * @param $values
924 * @param bool $disabled
925 */
926 public function render_multi_select_input( $key, $values, $disabled = false, $placeholder = "" ) {
927
928 $attr_name = "pys[$this->slug][$key][]";
929 $attr_id = 'pys_' . $this->slug . '_' . $key;
930
931 $selected = $this->getOption( $key ) ? $this->getOption( $key ) : array();
932 ?>
933
934 <input type="hidden" name="<?php echo esc_attr( $attr_name ); ?>" value="">
935 <select class="pys-pysselect2"
936 data-placeholder="<?= $placeholder ?>"
937 name="<?php echo esc_attr( $attr_name ); ?>"
938 id="<?php echo esc_attr( $attr_id ); ?>" <?php disabled( $disabled ); ?> style="width: 100%;"
939 multiple>
940 <?php foreach ( $values as $option_key => $option_value ) : ?>
941 <option value="<?php echo esc_attr( $option_key ); ?>"
942 <?php selected( in_array( $option_key, $selected ) ); ?>
943 <?php disabled( $option_key, 'disabled' ); ?>
944 >
945 <?php echo esc_attr( $option_value ); ?>
946 </option>
947 <?php endforeach; ?>
948
949 </select>
950
951 <?php
952 }
953
954 /**
955 * Output tags select input
956 *
957 * @param $key
958 * @param bool $disabled
959 */
960 public function render_tags_select_input( $key, $disabled = false ,$default = []) {
961
962 $attr_name = "pys[$this->slug][$key][]";
963 $attr_id = 'pys_' . $this->slug . '_' . $key;
964
965 $tags = $this->getOption( $key );
966 $tags = is_array( $tags ) ? array_filter( $tags ) : array();
967 $tags = array_diff($tags,$default);
968 ?>
969
970 <input type="hidden" name="<?php echo esc_attr( $attr_name ); ?>" value="">
971 <select class="pys-tags-pysselect2" name="<?php echo esc_attr( $attr_name ); ?>"
972 id="<?php echo esc_attr( $attr_id ); ?>" <?php disabled( $disabled ); ?> style="width: 100%;"
973 multiple>
974
975 <?php foreach ( $default as $tag ) : ?>
976 <option value="<?php echo esc_attr( $tag ); ?>" selected locked="locked">
977 <?php echo esc_attr( $tag ); ?>
978 </option>
979 <?php endforeach; ?>
980
981 <?php foreach ( $tags as $tag ) : ?>
982 <option value="<?php echo esc_attr( $tag ); ?>" selected>
983 <?php echo esc_attr( $tag ); ?>
984 </option>
985 <?php endforeach; ?>
986
987 </select>
988
989 <?php
990 }
991
992
993 /**
994 * Sanitize text field value
995 *
996 * @param $value
997 *
998 * @return string
999 */
1000 public function sanitize_text_field( $value ) {
1001
1002 $value = is_null( $value ) ? '' : $value;
1003
1004 return wp_kses_post( trim( stripslashes( $value ) ) );
1005
1006 }
1007
1008 /**
1009 * Sanitize textarea field value
1010 *
1011 * @param $value
1012 *
1013 * @return string
1014 */
1015 public function sanitize_textarea_field( $value ){
1016
1017 $value = is_null( $value ) ? '' : $value;
1018
1019 return trim( stripslashes( $value ) );
1020
1021 }
1022
1023 /**
1024 * Sanitize number field value
1025 *
1026 * @param $value
1027 *
1028 * @return int
1029 */
1030 public function sanitize_number_field( $value ) {
1031 return (int) $value;
1032 }
1033
1034 /**
1035 * Sanitize checkbox field value
1036 *
1037 * @param $value
1038 *
1039 * @return bool
1040 */
1041 public function sanitize_checkbox_field( $value ) {
1042
1043 if ( is_bool( $value ) || is_numeric( $value ) ) {
1044 return (bool) $value;
1045 } else {
1046 return false;
1047 }
1048
1049 }
1050
1051 /**
1052 * Sanitize radio field value
1053 *
1054 * @param $value
1055 *
1056 * @return null|string
1057 */
1058 public function sanitize_radio_field( $value ) {
1059 return ! is_null( $value ) ? trim( stripslashes( $value ) ) : null;
1060 }
1061
1062 /**
1063 * Sanitize select field value
1064 *
1065 * @see deepSanitizeTextField()
1066 *
1067 * @param $value
1068 *
1069 * @return array|string
1070 */
1071 public function sanitize_select_field( $value ) {
1072
1073 $value = is_null( $value ) ? '' : $value;
1074
1075 return deepSanitizeTextField( stripslashes( $value ) );
1076
1077 }
1078
1079 /**
1080 * Sanitize tags select value
1081 *
1082 * @see deepSanitizeTextField()
1083 *
1084 * @param $value
1085 *
1086 * @return array
1087 */
1088 public function sanitize_multi_select_field( $value ) {
1089 return is_array( $value ) ? array_map( 'PixelYourSite\deepSanitizeTextField', $value ) : array();
1090 }
1091
1092 /**
1093 * @param $value
1094 *
1095 * @return array
1096 */
1097 public function sanitize_tag_select_field( $value ) {
1098 return is_array( $value ) ? array_map( 'PixelYourSite\deepSanitizeTextField', $value ) : array();
1099 }
1100
1101 /**
1102 * Sanitize array field value
1103 *
1104 * @param $values
1105 *
1106 * @return array
1107 */
1108 public function sanitize_array_field( $values ) {
1109
1110 $values = is_array( $values ) ? $values : array();
1111 $sanitized = array();
1112
1113 foreach ( $values as $key => $value ) {
1114
1115 $new_value = $this->sanitize_text_field( $value );
1116
1117 if ( ! empty( $new_value ) && ! in_array( $new_value, $sanitized ) ) {
1118 $sanitized[ $key ] = $new_value;
1119 }
1120
1121 }
1122
1123 return $sanitized;
1124
1125 }
1126
1127 /**
1128 * Sanitize array field value
1129 *
1130 * @param $values
1131 *
1132 * @return array
1133 */
1134 public function sanitize_array_textarea_field( $values ) {
1135
1136 $values = is_array( $values ) ? $values : array();
1137 $sanitized = array();
1138
1139 foreach ( $values as $key => $value ) {
1140
1141 $new_value = $this->sanitize_textarea_field( $value );
1142
1143 if ( ! empty( $new_value ) && ! in_array( $new_value, $sanitized ) ) {
1144 $sanitized[ $key ] = $new_value;
1145 }
1146
1147 }
1148
1149 return $sanitized;
1150 }
1151 /**
1152 * Sanitize array field value with duplicates value
1153 *
1154 * @param $values
1155 *
1156 * @return array
1157 */
1158 public function sanitize_array_v_field( $values ) {
1159
1160 $values = is_array( $values ) ? $values : array();
1161 $sanitized = array();
1162
1163 foreach ( $values as $key => $value ) {
1164
1165 $new_value = $this->sanitize_text_field( $value );
1166
1167 if ( ! empty( $new_value ) ) {
1168 $sanitized[ $key ] = $new_value;
1169 }
1170
1171 }
1172
1173 return $sanitized;
1174
1175 }
1176 public function render_checkbox_input_array( $key, $label, $index = 0, $disabled = false ) {
1177
1178 $attr_name = "pys[$this->slug][$key][]";
1179 $attr_values = (array) $this->getOption( $key );
1180 $value = "index_" . $index;
1181 $valueIndex = array_search( $value, $attr_values );
1182 $id = $key . "_" . rand( 1, 1000000 );
1183 ?>
1184 <div class="small-checkbox">
1185 <input type="hidden" name="<?php echo esc_attr( $attr_name ); ?>" value="0">
1186 <input type="checkbox" id="<?php echo esc_attr( $id ); ?>" name="<?php echo esc_attr( $attr_name ); ?>"
1187 value="<?= $value ?>"
1188 class="small-control-input" <?php disabled( $disabled, true ); ?>
1189 <?php echo $valueIndex !== false ? "checked" : "" ?>>
1190 <label class="small-control small-checkbox-label" for="<?php echo esc_attr( $id ); ?>">
1191 <span class="small-control-indicator"><i class="icon-check"></i></span>
1192 <span class="small-control-description"><?php echo wp_kses_post( $label ); ?></span>
1193 </label>
1194 </div>
1195
1196 <?php
1197
1198 }
1199 function renderDummyTextInput( $placeholder = '' ) {
1200 ?>
1201
1202 <input type="text" disabled="disabled" placeholder="<?php esc_html_e( $placeholder ); ?>" class="form-control">
1203
1204 <?php
1205 }
1206 function renderDummyNumberInput($default = 0) {
1207 ?>
1208
1209 <input type="number" disabled="disabled" min="0" max="100" class="form-control" value="<?=$default?>">
1210
1211 <?php
1212 }
1213
1214 function renderDummySwitcher($isEnable = false) {
1215 $attr = $isEnable ? " checked='checked'" : "";
1216 ?>
1217
1218 <div class="custom-switch disabled">
1219 <input type="checkbox" value="1" <?=$attr?> disabled="disabled" class="custom-switch-input">
1220 <label class="custom-switch-btn"></label>
1221 </div>
1222
1223 <?php
1224 }
1225
1226 function renderDummyCheckbox( $label, $with_pro_badge = false ) {
1227 ?>
1228
1229 <label class="custom-control custom-checkbox <?php echo $with_pro_badge ? 'custom-checkbox-badge' : ''; ?>">
1230 <input type="checkbox" value="1"
1231 class="custom-control-input" disabled="disabled">
1232 <span class="custom-control-indicator"></span>
1233 <span class="custom-control-description">
1234 <?php echo wp_kses_post( $label ); ?>
1235 <?php if ( $with_pro_badge ) {
1236 renderProBadge();
1237 } ?>
1238 </span>
1239 </label>
1240
1241 <?php
1242 }
1243
1244 function renderDummyRadioInput( $label, $checked = false ) {
1245 ?>
1246
1247 <label class="custom-control custom-radio">
1248 <input type="radio" disabled="disabled"
1249 class="custom-control-input" <?php checked( $checked ); ?>>
1250 <span class="custom-control-indicator"></span>
1251 <span class="custom-control-description"><?php echo wp_kses_post( $label ); ?></span>
1252 </label>
1253
1254 <?php
1255 }
1256
1257 function renderDummyTagsFields( $tags = array() ) {
1258 ?>
1259
1260 <select class="form-control pys-tags-pysselect2" disabled="disabled" style="width: 100%;" multiple>
1261
1262 <?php if(!empty($tags)){
1263 foreach ( $tags as $tag ) : ?>
1264 <option value="<?php echo esc_attr( $tag ); ?>" selected>
1265 <?php echo esc_attr( $tag ); ?>
1266 </option>
1267 <?php endforeach;
1268 }
1269 ?>
1270
1271 </select>
1272
1273 <?php
1274 }
1275
1276 function renderDummySelectInput( $value, $full_width = false ) {
1277
1278 $attr_width = $full_width ? 'width: 100%;' : '';
1279
1280 ?>
1281
1282 <select class="form-control form-control-sm" disabled="disabled" autocomplete="off" style="<?php echo esc_attr( $attr_width ); ?>">
1283 <option value="" disabled selected><?php esc_html_e( $value ); ?></option>
1284 </select>
1285
1286 <?php
1287 }
1288
1289 function renderProBadge( $url = null,$label = "PRO Feature" ) {
1290
1291 if ( ! $url ) {
1292 $url = 'https://www.pixelyoursite.com/';
1293 }
1294
1295 $url = untrailingslashit( $url ) . '/?utm_source=pys-free-plugin&utm_medium=pro-badge&utm_campaign=pro-feature';
1296
1297 echo '&nbsp;<a href="' . esc_url( $url ) . '" target="_blank" class="badge badge-pill badge-pro">'.$label.'</a>';
1298 }
1299 public function convertTimeToSeconds($timeValue = 24, $type = 'hours')
1300 {
1301 switch ($type){
1302 case 'hours':
1303 $time = $timeValue * 60 * 60;
1304 break;
1305 case 'minute':
1306 $time = $timeValue * 60;
1307 break;
1308 case 'seconds':
1309 $time = $timeValue;
1310 break;
1311 }
1312 return $time;
1313 }
1314
1315
1316 public function renderValueOptionsBlock($context, $useEnable = true, $usePopover = true, $useBorder = true, $title = '', $disabled = false) {
1317 if ( empty( $context ) ) {
1318 return;
1319 }
1320
1321 if ( empty( $title ) ) {
1322 $title = 'Value parameter settings:';
1323 }
1324
1325 $prefixes = [
1326 'purchase',
1327 'initiate_checkout',
1328 'complete_registration'
1329 ];
1330 if ( count( array_filter( $prefixes, function ( $prefix ) use ( $context ) {
1331 return strpos( $context, $prefix ) !== false;
1332 } ) ) > 0 ) {
1333 $priceText = 'Order\'s total';
1334 $percentText = 'Percent of the order\'s total';
1335 } else {
1336 $priceText = 'Product price';
1337 $percentText = 'Percent of the product price';
1338 }
1339 ?>
1340 <div class="gap-24">
1341 <div class="d-flex align-items-center">
1342 <?php if ( !is_null( $this->getOption( $context . '_value_enabled' ) ) || $useEnable ) : ?>
1343 <div class="mr-16">
1344 <?php !$disabled ? $this->render_switcher_input( $context . '_value_enabled', true ) : renderDummySwitcher(); ?>
1345 </div>
1346 <?php endif; ?>
1347 <h4 class="secondary_heading"><?php echo esc_html( $title ); ?></h4>
1348 <?php
1349 if ( $usePopover ) {
1350 renderPopoverButton( $context . '_event_value' );
1351 } ?>
1352 </div>
1353
1354 <div <?php if ( !is_null( $this->getOption( $context . '_value_enabled' ) ) && !$disabled) {
1355 renderCollapseTargetAttributes( $context . '_value_enabled', PYS() );
1356 } ?>>
1357 <div class="radio-inputs-wrap-big woo-settings-block">
1358 <?php !$disabled ? $this->render_radio_input( $context . '_value_option', 'price', $priceText ) : renderDummyRadioInput($priceText); ?>
1359
1360 <?php if ( strpos( $context, 'edd_' ) !== 0 ) { ?>
1361 <?php if ( !isPixelCogActive() ) { ?>
1362 <?php !$disabled ? $this->render_radio_input( $context . '_value_option', 'cog', 'Price minus Cost of Goods.', true, true ): renderDummyRadioInput('Price minus Cost of Goods'); ?>
1363 <?php } else { ?>
1364 <?php !$disabled ? $this->render_radio_input( $context . '_value_option', 'cog', 'Price minus Cost of Goods', false ): renderDummyRadioInput('Price minus Cost of Goods'); ?>
1365 <?php } ?>
1366 <?php } ?>
1367
1368 <div class="grid-table">
1369 <?php renderDummyRadioInput( $percentText ); ?>
1370 <?php renderDummyNumberInput( 0 ); ?>
1371
1372 <?php !$disabled ? $this->render_radio_input( $context . '_value_option', 'global', 'Use global value' ) : renderDummyRadioInput('Use global value') ; ?>
1373 <?php !$disabled ? $this->render_number_input( $context . '_value_global' ) : renderDummyNumberInput(0); ?>
1374 </div>
1375 </div>
1376
1377 <?php if ( $useBorder ) : ?>
1378 <div class="line mt-24"></div>
1379 <?php endif; ?>
1380 </div>
1381 </div>
1382
1383 <?php
1384 }
1385 }