Passed
Push — master ( e9e8ae...991cb4 )
by Brian
11:14
created

WP_Super_Duper::is_fusion_preview()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 4
c 0
b 0
f 0
nc 2
nop 0
dl 0
loc 7
rs 10
1
<?php
2
/**
3
 * Contains the main class.
4
 *
5
 * @since 1.0.0
6
 */
7
8
defined( 'ABSPATH' ) || exit;
9
10
// Ensure the class is only loaded once.
11
if ( ! class_exists( 'WP_Super_Duper' ) ) {
12
13
	/**
14
	 *
15
	 * A Class to be able to create a Widget, Shortcode or Block to be able to output content for WordPress.
16
	 *
17
	 * View hello-world.php for example usage
18
	 *
19
	 * @since 1.0.0
20
	 * @since 1.0.16 change log moved to file change-log.txt - CHANGED
21
	 * @since 2.0.0 shortcode, widget and blocks moved into separate files - CHANGED
22
	 * @version 2.0.0
23
	 */
24
	abstract class WP_Super_Duper {
25
	
26
		public $version = "2.0.1";
27
		public $font_awesome_icon_version = "5.11.2";
28
		public $block_code;
29
		public $options;
30
		public $base_id;
31
		public $number;
32
		public $settings_hash;
33
		public $arguments = array();
34
		public $instance = array();
35
	
36
		// prevent SDv1 errors if register_widget() function used
37
		public $id_base;
38
	
39
		/**
40
		 * @var array Contains an array of output types instances.
41
		 */
42
		public $output_types = array();
43
	
44
		/**
45
		 * The relative url to the current folder.
46
		 *
47
		 * @var string
48
		 */
49
		public $url = '';
50
	
51
		/**
52
		 * Take the array options and use them to build.
53
		 */
54
		public function __construct( $options ) {
55
			global $sd_widgets;
56
	
57
			$sd_widgets[ $options['base_id'] ] = array(
58
				'name'       => $options['name'],
59
				'class_name' => $options['class_name']
60
			);
61
			$this->base_id   = $options['base_id'];
62
	
63
			// Lets filter the options before we do anything.
64
			$options = apply_filters( 'wp_super_duper_options', $options, $this );
65
			$options = apply_filters( "wp_super_duper_options_{$this->base_id}", $options, $this );
66
			$options = $this->add_name_from_key( $options );
67
	
68
			// Set args.
69
			$this->options   = $options;
70
			$this->base_id   = $options['base_id'];
71
			$this->arguments = isset( $options['arguments'] ) ? $options['arguments'] : array();
72
	
73
			// Load output types.
74
			$this->load_output_types();
75
	
76
			// add generator text to admin head
77
			add_action( 'admin_head', array( $this, 'generator' ) );
78
	
79
			add_action( 'admin_init', array( __CLASS__, 'load_widgets_setting' ) );
80
	
81
			add_action( 'wp_ajax_super_duper_get_picker', array( __CLASS__, 'get_picker' ) );
82
	
83
			do_action( 'wp_super_duper_widget_init', $options, $this );
84
	
85
		}
86
	
87
		/**
88
		 * Set the name from the argument key.
89
		 *
90
		 * @param array $options
91
		 * @param bool $arguments
92
		 *
93
		 * @return mixed
94
		 */
95
		protected function add_name_from_key( $options, $arguments = false ) {
96
			if ( ! empty( $options['arguments'] ) ) {
97
				foreach ( $options['arguments'] as $key => $val ) {
98
					$options['arguments'][ $key ]['name'] = $key;
99
				}
100
			} elseif ( $arguments && is_array( $options ) && ! empty( $options ) ) {
101
				foreach ( $options as $key => $val ) {
102
					$options[ $key ]['name'] = $key;
103
				}
104
			}
105
	
106
			return $options;
107
		}
108
	
109
		/**
110
		 * Output the version in the admin header.
111
		 */
112
		public function load_output_types() {
113
	
114
			$allowed_types = $this->get_output_types();
115
			$output_types  = array( 'block', 'shortcode', 'widget' );
116
	
117
			// Check if this is being overidden by the widget.
118
			$args = $this->get_arguments();
119
			if ( isset( $args['output_types'] ) && is_array( $args['output_types'] ) ) {
120
				$output_types  = $args['output_types'] ;
121
			}
122
	
123
			if ( isset( $this->options['output_types'] ) && is_array( $this->options['output_types'] ) ) {
124
				$output_types  = $this->options['output_types'] ;
125
			}
126
	
127
			// Load each output type.
128
			foreach ( $output_types as $output_type ) {
129
	
130
				// Ensure this is an allowed type.
131
				if ( ! isset( $allowed_types[ $output_type ] ) ) {
132
					continue;
133
				}
134
	
135
				// If the class does not exist, try loading it.
136
				if ( ! class_exists( $allowed_types[ $output_type ] ) ) {
137
	
138
					if ( file_exists( plugin_dir_path( __FILE__ ) . "type/$output_type.php" ) ) {
139
						require_once( plugin_dir_path( __FILE__ ) . "type/$output_type.php" );
140
					} else {
141
						continue;
142
					}
143
	
144
				}
145
	
146
				$output_class                       = $allowed_types[ $output_type ];
147
				$this->output_types[ $output_type ] = new $output_class( $this );
148
			}
149
	
150
		}
151
	
152
		/**
153
		 * Retrieves an array of available SD types.
154
		 *
155
		 * @return array
156
		 */
157
		protected function get_output_types() {
158
	
159
			// Output type id and class.
160
			$types = array(
161
				'block'     => 'WP_Super_Duper_Block',
162
				'shortcode' => 'WP_Super_Duper_Shortcode',
163
				'widget'    => 'WP_Super_Duper_Widget',
164
			);
165
	
166
			// Maybe disable widgets.
167
			$disable_widget   = get_option( 'sd_load_widgets', 'auto' );
168
	
169
			if ( 'auto' === $disable_widget ) {
170
				if ( !$this->widgets_required() ) {
171
					unset( $types['widget'] );
172
				}
173
			}
174
	
175
			if ( 'no' === $disable_widget ) {
176
				unset( $types['widget'] );
177
			}
178
	
179
			return apply_filters( 'super_duper_types', $types, $this );
180
		}
181
	
182
		/**
183
		 * Check if we are required to load widgets.
184
		 *
185
		 * @return mixed|void
186
		 */
187
		protected function widgets_required(){
188
			global $wp_version;
189
	
190
			$required = false;
191
	
192
	
193
			// check wp version
194
			if( version_compare( $wp_version, '5.8', '<' ) ){
195
				$required = true;
196
			}
197
	
198
			// Page builders that require widgets
199
			if(
200
			!$required && (
201
			defined( 'ELEMENTOR_VERSION' ) // elementor
202
			|| class_exists( 'Fusion_Element' ) // Fusion Builder (avada)
203
			|| class_exists( 'SiteOrigin_Panels' ) // SiteOrigin Page builder
204
			|| defined( 'WPB_VC_VERSION' ) // WPBakery page builder
205
			|| defined( 'CT_VERSION' ) // Oxygen Builder
206
			|| defined( 'FL_BUILDER_VERSION' ) // Beaver Builder
207
			|| defined( 'FL_THEME_BUILDER_VERSION' ) // Beaver Themer
208
			)
209
			){
210
				$required = true;
211
			}
212
	
213
			// Theme has active widgets
214
			if( !$required && !empty( $this->has_active_widgets() )  ){
215
				$required = true;
216
			}
217
	
218
	
219
			return apply_filters( 'sd_widgets_required' , $required );
220
		}
221
	
222
		/**
223
		 * Check if the current site has any active old style widgets.
224
		 *
225
		 * @return bool
226
		 */
227
		protected function has_active_widgets(){
228
			global $sd_has_active_widgets;
229
	
230
			// have we already done this?
231
			if(!is_null($sd_has_active_widgets)){
232
				return $sd_has_active_widgets;
233
			}
234
	
235
			$result = false;
236
			$sidebars_widgets = get_option('sidebars_widgets');
237
	
238
			if(is_array($sidebars_widgets)){
239
	
240
				foreach ($sidebars_widgets as $key => $value) {
241
	
242
	
243
	
244
					if( $key != 'wp_inactive_widgets' ) {
245
	
246
						if(!empty($value) && is_array($value)){
247
							foreach($value as $widget){
248
								if($widget && substr( $widget, 0, 6 ) !== "block-"){
249
									$result = true;
250
								}
251
							}
252
						}
253
	
254
					}
255
				}
256
			}
257
	
258
			$sd_has_active_widgets = $result;
259
	
260
			return $result;
261
		}
262
	
263
		/**
264
		 * Get arguments in super duper.
265
		 *
266
		 * @since 1.0.0
267
		 *
268
		 * @return array Get arguments.
269
		 */
270
		public function get_arguments() {
271
			if ( empty( $this->arguments ) ) {
272
				$this->arguments = $this->set_arguments();
273
			}
274
	
275
			$this->arguments = apply_filters( 'wp_super_duper_arguments', $this->arguments, $this->options, $this->instance );
276
			$this->arguments = $this->add_name_from_key( $this->arguments, true );
277
	
278
			return $this->arguments;
279
		}
280
	
281
		/**
282
		 * Set arguments in super duper.
283
		 *
284
		 * @since 1.0.0
285
		 *
286
		 * @return array Set arguments.
287
		 */
288
		public function set_arguments() {
289
			return $this->arguments;
290
		}
291
	
292
		/**
293
		 * Makes SD work with the siteOrigin page builder.
294
		 *
295
		 * @since 1.0.6
296
		 * @return mixed
297
		 */
298
		public static function siteorigin_js() {
299
			ob_start();
300
			?>
301
			<script>
302
				/**
303
				 * Check a form to see what items should be shown or hidden.
304
				 */
305
				function sd_so_show_hide(form) {
306
					jQuery(form).find(".sd-argument").each(function () {
307
	
308
						var $element_require = jQuery(this).data('element_require');
309
	
310
						if ($element_require) {
311
	
312
							$element_require = $element_require.replace("&#039;", "'"); // replace single quotes
313
							$element_require = $element_require.replace("&quot;", '"'); // replace double quotes
314
	
315
							if (eval($element_require)) {
316
								jQuery(this).removeClass('sd-require-hide');
317
							} else {
318
								jQuery(this).addClass('sd-require-hide');
319
							}
320
						}
321
					});
322
				}
323
	
324
				/**
325
				 * Toggle advanced settings visibility.
326
				 */
327
				function sd_so_toggle_advanced($this) {
328
					var form = jQuery($this).parents('form,.form,.so-content');
329
					form.find('.sd-advanced-setting').toggleClass('sd-adv-show');
330
					return false;// prevent form submit
331
				}
332
	
333
				/**
334
				 * Initialise a individual widget.
335
				 */
336
				function sd_so_init_widget($this, $selector) {
337
					if (!$selector) {
338
						$selector = 'form';
339
					}
340
					// only run once.
341
					if (jQuery($this).data('sd-widget-enabled')) {
342
						return;
343
					} else {
344
						jQuery($this).data('sd-widget-enabled', true);
345
					}
346
	
347
					var $button = '<button title="<?php _e( 'Advanced Settings' );?>" class="button button-primary right sd-advanced-button" onclick="sd_so_toggle_advanced(this);return false;"><i class="fas fa-sliders-h" aria-hidden="true"></i></button>';
348
					var form = jQuery($this).parents('' + $selector + '');
349
	
350
					if (jQuery($this).val() == '1' && jQuery(form).find('.sd-advanced-button').length == 0) {
351
						jQuery(form).append($button);
352
					}
353
	
354
					// show hide on form change
355
					jQuery(form).on("change", function () {
356
						sd_so_show_hide(form);
357
					});
358
	
359
					// show hide on load
360
					sd_so_show_hide(form);
361
				}
362
	
363
				jQuery(function () {
364
					jQuery(document).on('open_dialog', function (w, e) {
365
						setTimeout(function () {
366
							if (jQuery('.so-panels-dialog-wrapper:visible .so-content.panel-dialog .sd-show-advanced').length) {
367
								console.log('exists');
368
								if (jQuery('.so-panels-dialog-wrapper:visible .so-content.panel-dialog .sd-show-advanced').val() == '1') {
369
									console.log('true');
370
									sd_so_init_widget('.so-panels-dialog-wrapper:visible .so-content.panel-dialog .sd-show-advanced', 'div');
371
								}
372
							}
373
						}, 200);
374
					});
375
				});
376
			</script>
377
			<?php
378
			$output = ob_get_clean();
379
	
380
			/*
381
			 * We only add the <script> tags for code highlighting, so we strip them from the output.
382
			 */
383
			return str_replace( array(
384
				'<script>',
385
				'</script>'
386
			), '', $output );
387
		}
388
	
389
		/**
390
		 * A function to ge the shortcode builder picker html.
391
		 *
392
		 * @param string $editor_id
393
		 *
394
		 * @return string
395
		 */
396
		public static function get_picker( $editor_id = '' ) {
397
	
398
			ob_start();
399
			if ( isset( $_POST['editor_id'] ) ) {
400
				$editor_id = esc_attr( $_POST['editor_id'] );
401
			} elseif ( isset( $_REQUEST['et_fb'] ) ) {
402
				$editor_id = 'main_content_content_vb_tiny_mce';
403
			}
404
	
405
			global $sd_widgets;
406
			?>
407
	
408
			<div class="sd-shortcode-left-wrap">
409
				<?php
410
				ksort( $sd_widgets );
411
				//				print_r($sd_widgets);exit;
412
				if ( ! empty( $sd_widgets ) ) {
413
					echo '<select class="widefat" onchange="sd_get_shortcode_options(this);">';
414
					echo "<option>" . __( 'Select shortcode' ) . "</option>";
415
					foreach ( $sd_widgets as $shortcode => $class ) {
416
						echo "<option value='" . esc_attr( $shortcode ) . "'>" . esc_attr( $shortcode ) . " (" . esc_attr( $class['name'] ) . ")</option>";
417
					}
418
					echo "</select>";
419
	
420
				}
421
				?>
422
				<div class="sd-shortcode-settings"></div>
423
	
424
			</div>
425
	
426
			<div class="sd-shortcode-right-wrap">
427
				<textarea id='sd-shortcode-output' disabled></textarea>
428
				<div id='sd-shortcode-output-actions'>
429
					<?php if ( $editor_id != '' ) { ?>
430
						<button class="button sd-insert-shortcode-button"
431
								onclick="sd_insert_shortcode(<?php if ( ! empty( $editor_id ) ) {
432
									echo "'" . $editor_id . "'";
433
								} ?>)"><?php _e( 'Insert shortcode' ); ?></button>
434
					<?php } ?>
435
					<button class="button"
436
							onclick="sd_copy_to_clipboard()"><?php _e( 'Copy shortcode' ); ?></button>
437
				</div>
438
			</div>
439
			<?php
440
	
441
			$html = ob_get_clean();
442
	
443
			if ( wp_doing_ajax() ) {
444
				echo $html;
445
				$should_die = true;
446
	
447
				// some builder get the editor via ajax so we should not die on those occasions
448
				$dont_die = array(
449
					'parent_tag',// WP Bakery
450
					'avia_request' // enfold
451
				);
452
	
453
				foreach ( $dont_die as $request ) {
454
					if ( isset( $_REQUEST[ $request ] ) ) {
455
						$should_die = false;
456
					}
457
				}
458
	
459
				if ( $should_die ) {
460
					wp_die();
461
				}
462
	
463
			} else {
464
				return $html;
465
			}
466
	
467
			return '';
468
	
469
		}
470
	
471
		/**
472
		 * Returns the JS used to render the widget/shortcode settings form.
473
		 *
474
		 * @return string
475
		 */
476
		public static function widget_js() {
477
			ob_start();
478
			?>
479
			<script>
480
	
481
				/**
482
				 * Toggle advanced settings visibility.
483
				 */
484
				function sd_toggle_advanced($this) {
485
					var form = jQuery($this).parents('form,.form');
486
						form.find('.sd-advanced-setting').toggleClass('sd-adv-show');
487
						return false;// prevent form submit
488
				}
489
	
490
				/**
491
				 * Check a form to see what items should be shown or hidden.
492
				 */
493
				function sd_show_hide(form) {
494
					console.log('show/hide');
495
					jQuery(form).find(".sd-argument").each(function () {
496
	
497
						var $element_require = jQuery(this).data('element_require');
498
	
499
						if ($element_require) {
500
	
501
							$element_require = $element_require.replace("&#039;", "'"); // replace single quotes
502
							$element_require = $element_require.replace("&quot;", '"'); // replace double quotes
503
	
504
							if (eval($element_require)) {
505
								jQuery(this).removeClass('sd-require-hide');
506
							} else {
507
								jQuery(this).addClass('sd-require-hide');
508
							}
509
						}
510
					});
511
				}
512
	
513
				/**
514
				 * Initialise widgets from the widgets screen.
515
				 */
516
				function sd_init_widgets($selector) {
517
					jQuery(".sd-show-advanced").each(function (index) {
518
						sd_init_widget(this, $selector);
519
					});
520
				}
521
	
522
				/**
523
				 * Initialise a individual widget.
524
				 */
525
				function sd_init_widget($this, $selector) {
526
					console.log($selector);
527
	
528
					if (!$selector) {
529
						$selector = 'form';
530
					}
531
					// only run once.
532
					if (jQuery($this).data('sd-widget-enabled')) {
533
						return;
534
					} else {
535
						jQuery($this).data('sd-widget-enabled', true);
536
					}
537
	
538
					var $button = '<button title="<?php _e( 'Advanced Settings' );?>" style="line-height: 28px;" class="button button-primary right sd-advanced-button" onclick="sd_toggle_advanced(this);return false;"><span class="dashicons dashicons-admin-settings" style="width: 28px;font-size: 28px;"></span></button>';
539
					var form = jQuery($this).parents('' + $selector + '');
540
	
541
					if (jQuery($this).val() == '1' && jQuery(form).find('.sd-advanced-button').length == 0) {
542
						console.log('add advanced button');
543
						if(jQuery(form).find('.widget-control-save').length > 0){
544
							jQuery(form).find('.widget-control-save').after($button);
545
						}else{
546
							jQuery(form).find('.sd-show-advanced').after($button);
547
						}
548
					} else {
549
						console.log('no advanced button');
550
						console.log(jQuery($this).val());
551
						console.log(jQuery(form).find('.sd-advanced-button').length);
552
					}
553
	
554
					// show hide on form change
555
					jQuery(form).on("change", function () {
556
						sd_show_hide(form);
557
					});
558
	
559
					// show hide on load
560
					sd_show_hide(form);
561
					}
562
	
563
					/**
564
					 * Init a customizer widget.
565
					 */
566
					function sd_init_customizer_widget(section) {
567
						if (section.expanded) {
568
							section.expanded.bind(function (isExpanding) {
569
								if (isExpanding) {
570
									// is it a SD widget?
571
									if (jQuery(section.container).find('.sd-show-advanced').length) {
572
										// init the widget
573
										sd_init_widget(jQuery(section.container).find('.sd-show-advanced'), ".form");
574
									}
575
								}
576
							});
577
						}
578
					}
579
	
580
					/**
581
					 * If on widgets screen.
582
					 */
583
					jQuery(function () {
584
						// if not in customizer.
585
						if (!wp.customize) {
586
							sd_init_widgets("form");
587
						}
588
	
589
						// init on widget added
590
						jQuery(document).on('widget-added', function (e, widget) {
591
							console.log('widget added');
592
							// is it a SD widget?
593
							if (jQuery(widget).find('.sd-show-advanced').length) {
594
								// init the widget
595
								sd_init_widget(jQuery(widget).find('.sd-show-advanced'), "form");
596
							}
597
						});
598
	
599
						// init on widget updated
600
						jQuery(document).on('widget-updated', function (e, widget) {
601
							console.log('widget updated');
602
	
603
							// is it a SD widget?
604
							if (jQuery(widget).find('.sd-show-advanced').length) {
605
								// init the widget
606
								sd_init_widget(jQuery(widget).find('.sd-show-advanced'), "form");
607
							}
608
						});
609
	
610
					});
611
	
612
	
613
					/**
614
					 * We need to run this before jQuery is ready
615
					 */
616
					if (wp.customize) {
617
						wp.customize.bind('ready', function () {
618
	
619
							// init widgets on load
620
							wp.customize.control.each(function (section) {
621
								sd_init_customizer_widget(section);
622
							});
623
	
624
							// init widgets on add
625
							wp.customize.control.bind('add', function (section) {
626
								sd_init_customizer_widget(section);
627
							});
628
	
629
						});
630
	
631
					}
632
					<?php do_action( 'wp_super_duper_widget_js' ); ?>
633
			</script>
634
	
635
			<?php
636
				$output = ob_get_clean();
637
	
638
				/*
639
				* We only add the <script> tags for code highlighting, so we strip them from the output.
640
				*/
641
	
642
				return str_replace( array(
643
					'<script>',
644
					'</script>'
645
				), '', $output );
646
		}
647
	
648
		/**
649
		 * Returns the CSS used to render the widget/shortcode settings form.
650
		 *
651
		 * @param bool $advanced If we should include advanced CSS.
652
		 *
653
		 * @return mixed
654
		 */
655
		public static function widget_css( $advanced = true ) {
656
			ob_start();
657
			?>
658
	
659
			<style>
660
				<?php if ( $advanced ) : ?>
661
					.sd-advanced-setting {
662
						display: none;
663
					}
664
	
665
					.sd-advanced-setting.sd-adv-show {
666
						display: block;
667
					}
668
	
669
					.sd-argument.sd-require-hide,
670
					.sd-advanced-setting.sd-require-hide {
671
						display: none;
672
					}
673
	
674
					button.sd-advanced-button {
675
						margin-right: 3px !important;
676
						font-size: 20px !important;
677
					}
678
	
679
				<?php endif; ?>
680
	
681
				button.sd-toggle-group-button {
682
					background-color: #f3f3f3;
683
					color: #23282d;
684
					cursor: pointer;
685
					padding: 10px;
686
					width: 100%;
687
					border: none;
688
					text-align: left;
689
					outline: none;
690
					font-size: 13px;
691
					font-weight: bold;
692
					margin-bottom: 1px;
693
				}
694
	
695
			</style>
696
	
697
			<?php
698
				$output = ob_get_clean();
699
	
700
				/*
701
				* We only add the <script> tags for code highlighting, so we strip them from the output.
702
				*/
703
	
704
				return str_replace( array(
705
					'<style>',
706
					'</style>'
707
				), '', $output );
708
		}
709
	
710
		/**
711
		 * Registers the widgets loading settings.
712
		 */
713
		public static function load_widgets_setting() {
714
			register_setting( 'general', 'sd_load_widgets', 'esc_attr' );
0 ignored issues
show
Bug introduced by
'esc_attr' of type string is incompatible with the type array expected by parameter $args of register_setting(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

714
			register_setting( 'general', 'sd_load_widgets', /** @scrutinizer ignore-type */ 'esc_attr' );
Loading history...
715
	
716
			add_settings_field(
717
				'sd_load_widgets',
718
				'<label for="sd_load_widgets">' . __( 'Load Super Duper Widgets' ) . '</label>',
719
				'WP_Super_Duper::load_widgets_setting_html',
720
				'general'
721
			);
722
	
723
		}
724
	
725
		/**
726
		 * Displays the widgets settings HTML.
727
		 */
728
		public static function load_widgets_setting_html() {
729
			$available_options = array(
730
				'yes'  => __( 'Yes' ),
731
				'no'   => __( 'No' ),
732
				'auto' => __( 'Auto' ),
733
			);
734
			$selected_option   = get_option( 'sd_load_widgets', 'auto' );
735
	
736
			?>
737
				<select name="sd_load_widgets" id="sd_load_widgets">
738
					<?php foreach ( $available_options as $key => $label ) : ?>
739
						<option value="<?php echo esc_attr( $key ); ?>" <?php selected( $key, $selected_option ); ?>><?php echo esc_html( $label ); ?></option>
740
					<?php endforeach; ?>
741
				</select>
742
				<p class="description"><?php _e( 'This option allows you to disable Super Duper widgets and instead only load the blocks and shortcodes.' ); ?></p>
743
			<?php
744
		}
745
	
746
		/**
747
		 * prevent SDv1 errors if register_widget() function used
748
		 */
749
		public function _register(){
750
			// backwards compatibility
751
		}
752
	
753
		/**
754
		 * Output the version in the admin header.
755
		 */
756
		public function generator() {
757
	
758
			// We want to set this once.
759
			if ( empty( $GLOBALS['SD_SET_GENERATOR'] ) ) {
760
				echo '<meta name="generator" content="WP Super Duper v' . $this->version . '" />';
761
				$GLOBALS['SD_SET_GENERATOR'] = 1;
762
			}
763
	
764
		}
765
	
766
		/**
767
		 * This is the main output class for all 3 items, widget, shortcode and block, it is extended in the calling class.
768
		 *
769
		 * @param array $args
770
		 * @param array $widget_args
771
		 * @param string $content
772
		 */
773
		public function output( $args = array(), $widget_args = array(), $content = '' ) {
774
			echo call_user_func( $this->options['widget_ops']['output'], $args, $widget_args, $content );
775
		}
776
	
777
		/**
778
		 * Placeholder text to show if output is empty and we are on a preview/builder page.
779
		 *
780
		 * @param string $name
781
		 *
782
		 * @return string
783
		 */
784
		public function preview_placeholder_text( $name = '' ) {
785
			return "<div style='background:#0185ba33;padding: 10px;border: 4px #ccc dashed;'>" . sprintf( __( 'Placeholder for: %s' ), $name ) . "</div>";
786
		}
787
	
788
		/**
789
		 * Sometimes booleans values can be turned to strings, so we fix that.
790
		 *
791
		 * @param $options
792
		 *
793
		 * @return mixed
794
		 */
795
		public function string_to_bool( $options ) {
796
			// convert bool strings to booleans
797
			foreach ( $options as $key => $val ) {
798
				if ( $val == 'false' ) {
799
					$options[ $key ] = false;
800
				} elseif ( $val == 'true' ) {
801
					$options[ $key ] = true;
802
				}
803
			}
804
	
805
			return $options;
806
		}
807
	
808
		/**
809
		 * Get the argument values that are also filterable.
810
		 *
811
		 * @param $instance
812
		 *
813
		 * @since 1.0.12 Don't set checkbox default value if the value is empty.
814
		 *
815
		 * @return array
816
		 */
817
		public function argument_values( $instance ) {
818
			$argument_values = array();
819
	
820
			// set widget instance
821
			$this->instance = $instance;
822
	
823
			if ( empty( $this->arguments ) ) {
824
				$this->arguments = $this->get_arguments();
825
			}
826
	
827
			if ( ! empty( $this->arguments ) ) {
828
				foreach ( $this->arguments as $key => $args ) {
829
					// set the input name from the key
830
					$args['name'] = $key;
831
					//
832
					$argument_values[ $key ] = isset( $instance[ $key ] ) ? $instance[ $key ] : '';
833
					if ( $args['type'] == 'checkbox' && $argument_values[ $key ] == '' ) {
834
						// don't set default for an empty checkbox
835
					} elseif ( $argument_values[ $key ] == '' && isset( $args['default'] ) ) {
836
						$argument_values[ $key ] = $args['default'];
837
					}
838
				}
839
			}
840
	
841
			return $argument_values;
842
		}
843
	
844
		/**
845
		 * Get the url path to the current folder.
846
		 *
847
		 * @return string
848
		 */
849
		public function get_url() {
850
			$url = $this->url;
851
	
852
			if ( ! $url ) {
853
				// check if we are inside a plugin
854
				$file_dir = str_replace( "/includes", "", dirname( __FILE__ ) );
855
	
856
				$dir_parts = explode( "/wp-content/", $file_dir );
857
				$url_parts = explode( "/wp-content/", plugins_url() );
858
	
859
				if ( ! empty( $url_parts[0] ) && ! empty( $dir_parts[1] ) ) {
860
					$url       = trailingslashit( $url_parts[0] . "/wp-content/" . $dir_parts[1] );
861
					$this->url = $url;
862
				}
863
			}
864
	
865
			return $url;
866
		}
867
	
868
		/**
869
		 * General function to check if we are in a preview situation.
870
		 *
871
		 * @since 1.0.6
872
		 * @return bool
873
		 */
874
		public function is_preview() {
875
			return $this->is_divi_preview() || $this->is_elementor_preview() || $this->is_beaver_preview() || $this->is_siteorigin_preview() || $this->is_cornerstone_preview() || $this->is_fusion_preview() || $this->is_oxygen_preview() || $this->is_block_content_call();
876
		}
877
	
878
		/**
879
		 * Tests if the current output is inside a Divi preview.
880
		 *
881
		 * @since 1.0.6
882
		 * @return bool
883
		 */
884
		public function is_divi_preview() {
885
			$result = false;
886
			if ( isset( $_REQUEST['et_fb'] ) || isset( $_REQUEST['et_pb_preview'] ) || ( is_admin() && isset( $_REQUEST['action'] ) && $_REQUEST['action'] == 'elementor' ) ) {
887
				$result = true;
888
			}
889
	
890
			return $result;
891
		}
892
	
893
		/**
894
		 * Tests if the current output is inside a elementor preview.
895
		 *
896
		 * @since 1.0.4
897
		 * @return bool
898
		 */
899
		public function is_elementor_preview() {
900
			$result = false;
901
			if ( isset( $_REQUEST['elementor-preview'] ) || ( is_admin() && isset( $_REQUEST['action'] ) && $_REQUEST['action'] == 'elementor' ) || ( isset( $_REQUEST['action'] ) && $_REQUEST['action'] == 'elementor_ajax' ) ) {
902
				$result = true;
903
			}
904
	
905
			return $result;
906
		}
907
	
908
		/**
909
		 * Tests if the current output is inside a Beaver builder preview.
910
		 *
911
		 * @since 1.0.6
912
		 * @return bool
913
		 */
914
		public function is_beaver_preview() {
915
			$result = false;
916
			if ( isset( $_REQUEST['fl_builder'] ) ) {
917
				$result = true;
918
			}
919
	
920
			return $result;
921
		}
922
	
923
		/**
924
		 * Tests if the current output is inside a siteorigin builder preview.
925
		 *
926
		 * @since 1.0.6
927
		 * @return bool
928
		 */
929
		public function is_siteorigin_preview() {
930
			$result = false;
931
			if ( ! empty( $_REQUEST['siteorigin_panels_live_editor'] ) ) {
932
				$result = true;
933
			}
934
	
935
			return $result;
936
		}
937
	
938
		/**
939
		 * Tests if the current output is inside a cornerstone builder preview.
940
		 *
941
		 * @since 1.0.8
942
		 * @return bool
943
		 */
944
		public function is_cornerstone_preview() {
945
			$result = false;
946
			if ( ! empty( $_REQUEST['cornerstone_preview'] ) || basename( $_SERVER['REQUEST_URI'] ) == 'cornerstone-endpoint' ) {
947
				$result = true;
948
			}
949
	
950
			return $result;
951
		}
952
	
953
		/**
954
		 * Tests if the current output is inside a fusion builder preview.
955
		 *
956
		 * @since 1.1.0
957
		 * @return bool
958
		 */
959
		public function is_fusion_preview() {
960
			$result = false;
961
			if ( ! empty( $_REQUEST['fb-edit'] ) || ! empty( $_REQUEST['fusion_load_nonce'] ) ) {
962
				$result = true;
963
			}
964
	
965
			return $result;
966
		}
967
	
968
		/**
969
		 * Tests if the current output is inside a Oxygen builder preview.
970
		 *
971
		 * @since 1.0.18
972
		 * @return bool
973
		 */
974
		public function is_oxygen_preview() {
975
			$result = false;
976
			if ( ! empty( $_REQUEST['ct_builder'] ) || ( ! empty( $_REQUEST['action'] ) && ( substr( $_REQUEST['action'], 0, 11 ) === "oxy_render_" || substr( $_REQUEST['action'], 0, 10 ) === "ct_render_" ) ) ) {
977
				$result = true;
978
			}
979
	
980
			return $result;
981
		}
982
	
983
		/**
984
		* Checks if the current call is a ajax call to get the block content.
985
		*
986
		* This can be used in your widget to return different content as the block content.
987
		*
988
		* @since 1.0.3
989
		* @return bool
990
		*/
991
		public function is_block_content_call() {
992
			$result = false;
993
			if ( wp_doing_ajax() && isset( $_REQUEST['action'] ) && $_REQUEST['action'] == 'super_duper_output_shortcode' ) {
994
				$result = true;
995
			}
996
	
997
			return $result;
998
		}
999
	
1000
		/**
1001
		 * Outputs the options form inputs for the widget/shortcode.
1002
		 *
1003
		 * @param array $instance The widget options.
1004
		 */
1005
		public function form( $instance ) {
1006
	
1007
			// Set widget instance.
1008
			$this->instance = $instance;
1009
	
1010
			// Set it as a SD widget.
1011
			echo $this->widget_advanced_toggle();
1012
	
1013
			// Display description.
1014
			printf( '<p>%s</p>', esc_html( $this->options['widget_ops']['description'] ) );
1015
	
1016
			// Prepare arguments.
1017
			$arguments_raw = $this->get_arguments();
1018
	
1019
		if ( is_array( $arguments_raw ) ) {
0 ignored issues
show
introduced by
The condition is_array($arguments_raw) is always true.
Loading history...
1020
	
1021
			$arguments = $this->group_arguments( $arguments_raw );
1022
	
1023
			// Do we have sections?
1024
			if ( $arguments != $arguments_raw ) {
1025
	
1026
					$panel_count = 0;
1027
					foreach ( $arguments as $key => $args ) {
1028
	
1029
						$hide       = $panel_count ? ' style="display:none;" ' : '';
1030
						$icon_class = $panel_count ? 'fas fa-chevron-up' : 'fas fa-chevron-down';
1031
						echo "<button onclick='jQuery(this).find(\"i\").toggleClass(\"fas fa-chevron-up fas fa-chevron-down\");jQuery(this).next().slideToggle();' type='button' class='sd-toggle-group-button sd-input-group-toggle" . sanitize_title_with_dashes( $key ) . "'>" . esc_attr( $key ) . " <i style='float:right;' class='" . esc_attr( $icon_class ) . "'></i></button>";
1032
						echo "<div class='sd-toggle-group sd-input-group-" . sanitize_title_with_dashes( $key ) . "' $hide>";
1033
	
1034
						foreach ( $args as $k => $a ) {
1035
	
1036
							$this->widget_inputs_row_start($k, $a);
1037
							$this->widget_inputs( $a, $instance );
1038
							$this->widget_inputs_row_end($k, $a);
1039
	
1040
						}
1041
	
1042
						echo "</div>";
1043
	
1044
						$panel_count ++;
1045
	
1046
					}
1047
	
1048
				} else {
1049
	
1050
					foreach ( $arguments as $key => $args ) {
1051
						$this->widget_inputs_row_start($key, $args);
1052
						$this->widget_inputs( $args, $instance );
1053
						$this->widget_inputs_row_end($key, $args);
1054
					}
1055
	
1056
				}
1057
	
1058
			}
1059
		}
1060
	
1061
		/**
1062
		 * Get the hidden input that when added makes the advanced button show on widget settings.
1063
		 *
1064
		 * @return string
1065
		 */
1066
		public function widget_advanced_toggle() {
1067
	
1068
			return sprintf(
1069
				'<input type="hidden"  class="sd-show-advanced" value="%s" />',
1070
				(int) $this->block_show_advanced()
1071
			);
1072
	
1073
		}
1074
	
1075
		/**
1076
		 * Check if we need to show advanced options.
1077
		 *
1078
		 * @return bool
1079
		 */
1080
		public function block_show_advanced() {
1081
			$show      = false;
1082
			$arguments = $this->get_arguments();
1083
	
1084
			if ( ! empty( $arguments ) ) {
1085
				foreach ( $arguments as $argument ) {
1086
					if ( isset( $argument['advanced'] ) && $argument['advanced'] ) {
1087
						$show = true;
1088
						break; // no need to continue if we know we have it
1089
					}
1090
				}
1091
			}
1092
	
1093
			return $show;
1094
		}
1095
	
1096
		/**
1097
		 * Groups widget arguments.
1098
		 *
1099
		 * @param array $arguments
1100
		 *
1101
		 * @return array
1102
		 */
1103
		public function group_arguments( $arguments ) {
1104
	
1105
			if ( ! empty( $arguments ) ) {
1106
				$temp_arguments = array();
1107
				$general        = __( "General" );
1108
				$add_sections   = false;
1109
				foreach ( $arguments as $key => $args ) {
1110
					if ( isset( $args['group'] ) ) {
1111
						$temp_arguments[ $args['group'] ][ $key ] = $args;
1112
						$add_sections                             = true;
1113
					} else {
1114
						$temp_arguments[ $general ][ $key ] = $args;
1115
					}
1116
				}
1117
	
1118
				// only add sections if more than one
1119
				if ( $add_sections ) {
1120
					$arguments = $temp_arguments;
1121
				}
1122
			}
1123
	
1124
			return $arguments;
1125
		}
1126
	
1127
		public function widget_inputs_row_start($key, $args){
0 ignored issues
show
Unused Code introduced by
The parameter $key is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

1127
		public function widget_inputs_row_start(/** @scrutinizer ignore-unused */ $key, $args){

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
1128
			if(!empty($args['row'])){
1129
				// maybe open
1130
				if(!empty($args['row']['open'])){
1131
					?>
1132
					<div class='bsui sd-argument ' data-argument='<?php echo esc_attr( $args['row']['key'] ); ?>' data-element_require='<?php if ( !empty($args['row']['element_require'])) {
1133
						echo $this->convert_element_require( $args['row']['element_require'] );
1134
					} ?>'>
1135
					<?php if(!empty($args['row']['title'])){ ?>
1136
					<label class="mb-0 "><?php echo esc_attr( $args['row']['title'] ); ?><?php echo $this->widget_field_desc( $args['row'] ); ?></label>
1137
					<?php }?>
1138
					<div class='row <?php if(!empty($args['row']['class'])){ echo esc_attr($args['row']['class']);} ?>'>
1139
					<div class='col pr-2'>
1140
					<?php
1141
				}elseif(!empty($args['row']['close'])){
1142
					echo "<div class='col pl-0'>";
1143
				}else{
1144
					echo "<div class='col pl-0 pr-2'>";
1145
				}
1146
			}
1147
		}
1148
	
1149
		/**
1150
		 * Convert require element.
1151
		 *
1152
		 * @since 1.0.0
1153
		 *
1154
		 * @param string $input Input element.
1155
		 *
1156
		 * @return string $output
1157
		 */
1158
		public function convert_element_require( $input ) {
1159
	
1160
			$input = str_replace( "'", '"', $input );// we only want double quotes
1161
	
1162
			$output = esc_attr( str_replace( array( "[%", "%]" ), array(
1163
				"jQuery(form).find('[data-argument=\"",
1164
				"\"]').find('input,select,textarea').val()"
1165
			), $input ) );
1166
	
1167
			return $output;
1168
		}
1169
	
1170
		/**
1171
		 * Get the widget input description html.
1172
		 *
1173
		 * @param $args
1174
		 *
1175
		 * @return string
1176
		 * @todo, need to make its own tooltip script
1177
		 */
1178
		public function widget_field_desc( $args ) {
1179
	
1180
			$description = '';
1181
			if ( isset( $args['desc'] ) && $args['desc'] ) {
1182
				if ( isset( $args['desc_tip'] ) && $args['desc_tip'] ) {
1183
					$description = $this->desc_tip( $args['desc'] );
1184
				} else {
1185
					$description = '<span class="description">' . wp_kses_post( $args['desc'] ) . '</span>';
1186
				}
1187
			}
1188
	
1189
			return $description;
1190
		}
1191
	
1192
		/**
1193
		 * Get the tool tip html.
1194
		 *
1195
		 * @param $tip
1196
		 * @param bool $allow_html
1197
		 *
1198
		 * @return string
1199
		 */
1200
		public function desc_tip( $tip, $allow_html = false ) {
1201
			if ( $allow_html ) {
1202
				$tip = $this->sanitize_tooltip( $tip );
1203
			} else {
1204
				$tip = esc_attr( $tip );
1205
			}
1206
	
1207
			return '<span class="gd-help-tip dashicons dashicons-editor-help" title="' . $tip . '"></span>';
1208
		}
1209
	
1210
		/**
1211
		 * Sanitize a string destined to be a tooltip.
1212
		 *
1213
		 * @param string $var
1214
		 *
1215
		 * @return string
1216
		 */
1217
		public function sanitize_tooltip( $var ) {
1218
			return htmlspecialchars( wp_kses( html_entity_decode( $var ), array(
1219
				'br'     => array(),
1220
				'em'     => array(),
1221
				'strong' => array(),
1222
				'small'  => array(),
1223
				'span'   => array(),
1224
				'ul'     => array(),
1225
				'li'     => array(),
1226
				'ol'     => array(),
1227
				'p'      => array(),
1228
			) ) );
1229
		}
1230
	
1231
		/**
1232
		 * Builds the inputs for the widget options.
1233
		 *
1234
		 * @param $args
1235
		 * @param $instance
1236
		 */
1237
		public function widget_inputs( $args, $instance ) {
1238
	
1239
			$class             = "";
1240
			$element_require   = "";
1241
			$custom_attributes = "";
1242
	
1243
			// get value
1244
			if ( isset( $instance[ $args['name'] ] ) ) {
1245
				$value = $instance[ $args['name'] ];
1246
			} elseif ( ! isset( $instance[ $args['name'] ] ) && ! empty( $args['default'] ) ) {
1247
				$value = is_array( $args['default'] ) ? array_map( "esc_html", $args['default'] ) : esc_html( $args['default'] );
1248
			} else {
1249
				$value = '';
1250
			}
1251
	
1252
			// get placeholder
1253
			if ( ! empty( $args['placeholder'] ) ) {
1254
				$placeholder = "placeholder='" . esc_html( $args['placeholder'] ) . "'";
1255
			} else {
1256
				$placeholder = '';
1257
			}
1258
	
1259
			// get if advanced
1260
			if ( isset( $args['advanced'] ) && $args['advanced'] ) {
1261
				$class .= " sd-advanced-setting ";
1262
			}
1263
	
1264
			// element_require
1265
			if ( isset( $args['element_require'] ) && $args['element_require'] ) {
1266
				$element_require = $args['element_require'];
1267
			}
1268
	
1269
			// custom_attributes
1270
			if ( isset( $args['custom_attributes'] ) && $args['custom_attributes'] ) {
1271
				$custom_attributes = $this->array_to_attributes( $args['custom_attributes'], true );
1272
			}
1273
	
1274
	
1275
			// before wrapper
1276
			?>
1277
			<p class="sd-argument <?php echo esc_attr( $class ); ?>"
1278
			data-argument='<?php echo esc_attr( $args['name'] ); ?>'
1279
			data-element_require='<?php if ( $element_require ) {
1280
				echo $this->convert_element_require( $element_require );
1281
			} ?>'
1282
			>
1283
			<?php
1284
	
1285
	
1286
			switch ( $args['type'] ) {
1287
				//array('text','password','number','email','tel','url','color')
1288
				case "text":
1289
				case "password":
1290
				case "number":
1291
				case "email":
1292
				case "tel":
1293
				case "url":
1294
				case "color":
1295
					?>
1296
					<label
1297
						for="<?php echo esc_attr( $this->get_field_id( $args['name'] ) ); ?>"><?php echo $this->widget_field_title( $args );?><?php echo $this->widget_field_desc( $args ); ?></label>
1298
					<input <?php echo $placeholder; ?> class="widefat"
1299
						<?php echo $custom_attributes; ?>
1300
													   id="<?php echo esc_attr( $this->get_field_id( $args['name'] ) ); ?>"
1301
													   name="<?php echo esc_attr( $this->get_field_name( $args['name'] ) ); ?>"
1302
													   type="<?php echo esc_attr( $args['type'] ); ?>"
1303
													   value="<?php echo esc_attr( $value ); ?>">
1304
					<?php
1305
	
1306
					break;
1307
				case "select":
1308
					$multiple = isset( $args['multiple'] ) && $args['multiple'] ? true : false;
1309
					if ( $multiple ) {
1310
						if ( empty( $value ) ) {
1311
							$value = array();
1312
						}
1313
					}
1314
					?>
1315
					<label
1316
						for="<?php echo esc_attr( $this->get_field_id( $args['name'] ) ); ?>"><?php echo $this->widget_field_title( $args ); ?><?php echo $this->widget_field_desc( $args ); ?></label>
1317
					<select <?php echo $placeholder; ?> class="widefat"
1318
						<?php echo $custom_attributes; ?>
1319
														id="<?php echo esc_attr( $this->get_field_id( $args['name'] ) ); ?>"
1320
														name="<?php echo esc_attr( $this->get_field_name( $args['name'] ) );
1321
														if ( $multiple ) {
1322
															echo "[]";
1323
														} ?>"
1324
						<?php if ( $multiple ) {
1325
							echo "multiple";
1326
						} //@todo not implemented yet due to gutenberg not supporting it
1327
						?>
1328
					>
1329
						<?php
1330
	
1331
						if ( ! empty( $args['options'] ) ) {
1332
							foreach ( $args['options'] as $val => $label ) {
1333
								if ( $multiple ) {
1334
									$selected = in_array( $val, $value ) ? 'selected="selected"' : '';
1335
								} else {
1336
									$selected = selected( $value, $val, false );
1337
								}
1338
								echo "<option value='$val' " . $selected . ">$label</option>";
1339
							}
1340
						}
1341
						?>
1342
					</select>
1343
					<?php
1344
					break;
1345
				case "checkbox":
1346
					?>
1347
					<input <?php echo $placeholder; ?>
1348
						<?php checked( 1, $value, true ) ?>
1349
						<?php echo $custom_attributes; ?>
1350
						class="widefat" id="<?php echo esc_attr( $this->get_field_id( $args['name'] ) ); ?>"
1351
						name="<?php echo esc_attr( $this->get_field_name( $args['name'] ) ); ?>" type="checkbox"
1352
						value="1">
1353
					<label
1354
						for="<?php echo esc_attr( $this->get_field_id( $args['name'] ) ); ?>"><?php echo $this->widget_field_title( $args );?><?php echo $this->widget_field_desc( $args ); ?></label>
1355
					<?php
1356
					break;
1357
				case "textarea":
1358
					?>
1359
					<label
1360
						for="<?php echo esc_attr( $this->get_field_id( $args['name'] ) ); ?>"><?php echo $this->widget_field_title( $args ); ?><?php echo $this->widget_field_desc( $args ); ?></label>
1361
					<textarea <?php echo $placeholder; ?> class="widefat"
1362
						<?php echo $custom_attributes; ?>
1363
														  id="<?php echo esc_attr( $this->get_field_id( $args['name'] ) ); ?>"
1364
														  name="<?php echo esc_attr( $this->get_field_name( $args['name'] ) ); ?>"
1365
					><?php echo esc_attr( $value ); ?></textarea>
1366
					<?php
1367
	
1368
					break;
1369
				case "hidden":
1370
					?>
1371
					<input id="<?php echo esc_attr( $this->get_field_id( $args['name'] ) ); ?>"
1372
						   name="<?php echo esc_attr( $this->get_field_name( $args['name'] ) ); ?>" type="hidden"
1373
						   value="<?php echo esc_attr( $value ); ?>">
1374
					<?php
1375
					break;
1376
				default:
1377
					echo "No input type found!"; // @todo we need to add more input types.
1378
			}
1379
	
1380
			// after wrapper
1381
			?>
1382
			</p>
1383
			<?php
1384
		}
1385
	
1386
		/**
1387
		 * Convert an array of attributes to JS object or HTML attributes string.
1388
		 *
1389
		 * @todo there is prob a faster way to do this, also we could add some validation here.
1390
		 *
1391
		 * @param $attributes
1392
		 *
1393
		 * @return string
1394
		 */
1395
		public function array_to_attributes( $attributes, $html = false ) {
1396
	
1397
			if ( ! is_array( $attributes ) ) {
1398
				return '';
1399
			}
1400
	
1401
			$output = '';
1402
			foreach ( $attributes as $name => $value ) {
1403
	
1404
				if ( $html ) {
1405
	
1406
					if ( true === $value ) {
1407
						$output .= esc_html( $name ) . ' ';
1408
					} else if ( false !== $value ) {
1409
						$output .= sprintf( '%s="%s" ', esc_html( $name ), trim( esc_attr( $value ) ) );
1410
					}
1411
	
1412
				} else {
1413
					$output .= sprintf( "'%s': '%s',", esc_js( $name ), is_bool( $value ) ? $value : trim( esc_js( $value ) ) );
1414
				}
1415
	
1416
			}
1417
	
1418
			return $output;
1419
		}
1420
	
1421
		/**
1422
		 * Constructs id attributes for use in WP_Widget::form() fields.
1423
		 *
1424
		 * This function should be used in form() methods to create id attributes
1425
		 * for fields to be saved by WP_Widget::update().
1426
		 *
1427
		 * @since 2.8.0
1428
		 * @since 4.4.0 Array format field IDs are now accepted.
1429
		 *
1430
		 * @param string $field_name Field name.
1431
		 *
1432
		 * @return string ID attribute for `$field_name`.
1433
		 */
1434
		public function get_field_id( $field_name ) {
1435
	
1436
			$field_name = str_replace( array( '[]', '[', ']' ), array( '', '-', '' ), $field_name );
1437
			$field_name = trim( $field_name, '-' );
1438
	
1439
			return 'widget-' . $this->base_id . '-' . $this->get_number() . '-' . $field_name;
1440
		}
1441
	
1442
		/**
1443
		 * Returns the instance number.
1444
		 *
1445
		 * @return int
1446
		 */
1447
		public function get_number() {
1448
			static $number = 1;
1449
	
1450
			if ( isset( $this->output_types['widget'] ) ) {
1451
				return $this->output_types['widget']->number;
1452
			}
1453
	
1454
			if ( empty( $this->number ) ) {
1455
				$this->number = $number;
1456
				$number ++;
1457
			}
1458
	
1459
			return $this->number;
1460
		}
1461
	
1462
		/**
1463
		 * Get the widget input title html.
1464
		 *
1465
		 * @param $args
1466
		 *
1467
		 * @return string
1468
		 */
1469
		public function widget_field_title( $args ) {
1470
	
1471
			$title = '';
1472
			if ( isset( $args['title'] ) && $args['title'] ) {
1473
				if ( isset( $args['icon'] ) && $args['icon'] ) {
1474
					$title = $this->get_widget_icon( $args['icon'], $args['title']  );
1475
				} else {
1476
					$title = esc_attr($args['title']);
1477
				}
1478
			}
1479
	
1480
			return $title;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $title also could return the type array which is incompatible with the documented return type string.
Loading history...
1481
		}
1482
	
1483
		/**
1484
		 * Retrieves the icon to use for widgets / blocks.
1485
		 *
1486
		 * @return array
1487
		 */
1488
		public function get_widget_icon( $icon = 'box-top', $title = '' ) {
1489
			if($icon=='box-top'){
1490
				return '<svg title="'.esc_attr($title).'" width="20px" height="20px" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg" fill-rule="evenodd" clip-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" role="img" aria-hidden="true" focusable="false"><rect x="2.714" y="5.492" width="1.048" height="9.017" fill="#555D66"></rect><rect x="16.265" y="5.498" width="1.023" height="9.003" fill="#555D66"></rect><rect x="5.518" y="2.186" width="8.964" height="2.482" fill="#272B2F"></rect><rect x="5.487" y="16.261" width="9.026" height="1.037" fill="#555D66"></rect></svg>';
0 ignored issues
show
Bug Best Practice introduced by
The expression return '<svg title="' . ...#555D66"></rect></svg>' returns the type string which is incompatible with the documented return type array.
Loading history...
1491
			}elseif($icon=='box-right'){
1492
				return '<svg title="'.esc_attr($title).'" width="20px" height="20px" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg" fill-rule="evenodd" clip-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" role="img" aria-hidden="true" focusable="false"><rect x="2.714" y="5.492" width="1.046" height="9.017" fill="#555D66"></rect><rect x="15.244" y="5.498" width="2.518" height="9.003" fill="#272B2F"></rect><rect x="5.518" y="2.719" width="8.964" height="0.954" fill="#555D66"></rect><rect x="5.487" y="16.308" width="9.026" height="0.99" fill="#555D66"></rect></svg>';
0 ignored issues
show
Bug Best Practice introduced by
The expression return '<svg title="' . ...#555D66"></rect></svg>' returns the type string which is incompatible with the documented return type array.
Loading history...
1493
			}elseif($icon=='box-bottom'){
1494
				return '<svg title="'.esc_attr($title).'" width="20px" height="20px" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg" fill-rule="evenodd" clip-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" role="img" aria-hidden="true" focusable="false"><rect x="2.714" y="5.492" width="1" height="9.017" fill="#555D66"></rect><rect x="16.261" y="5.498" width="1.027" height="9.003" fill="#555D66"></rect><rect x="5.518" y="2.719" width="8.964" height="0.968" fill="#555D66"></rect><rect x="5.487" y="15.28" width="9.026" height="2.499" fill="#272B2F"></rect></svg>';
0 ignored issues
show
Bug Best Practice introduced by
The expression return '<svg title="' . ...#272B2F"></rect></svg>' returns the type string which is incompatible with the documented return type array.
Loading history...
1495
			}elseif($icon=='box-left'){
1496
				return '<svg title="'.esc_attr($title).'" width="20px" height="20px" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg" fill-rule="evenodd" clip-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" role="img" aria-hidden="true" focusable="false"><rect x="2.202" y="5.492" width="2.503" height="9.017" fill="#272B2F"></rect><rect x="16.276" y="5.498" width="1.012" height="9.003" fill="#555D66"></rect><rect x="5.518" y="2.719" width="8.964" height="0.966" fill="#555D66"></rect><rect x="5.487" y="16.303" width="9.026" height="0.995" fill="#555D66"></rect></svg>';
0 ignored issues
show
Bug Best Practice introduced by
The expression return '<svg title="' . ...#555D66"></rect></svg>' returns the type string which is incompatible with the documented return type array.
Loading history...
1497
			}
1498
		}
1499
	
1500
		/**
1501
		 * Constructs name attributes for use in form() fields
1502
		 *
1503
		 * This function should be used in form() methods to create name attributes for fields
1504
		 * to be saved by update()
1505
		 *
1506
		 * @since 2.8.0
1507
		 * @since 4.4.0 Array format field names are now accepted.
1508
		 *
1509
		 * @param string $field_name Field name.
1510
		 *
1511
		 * @return string Name attribute for `$field_name`.
1512
		 */
1513
		public function get_field_name( $field_name ) {
1514
			$pos = strpos( $field_name, '[' );
1515
	
1516
			if ( false !== $pos ) {
1517
				// Replace the first occurrence of '[' with ']['.
1518
				$field_name = '[' . substr_replace( $field_name, '][', $pos, strlen( '[' ) );
0 ignored issues
show
Bug introduced by
Are you sure substr_replace($field_na...][', $pos, strlen('[')) of type array|string can be used in concatenation? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1518
				$field_name = '[' . /** @scrutinizer ignore-type */ substr_replace( $field_name, '][', $pos, strlen( '[' ) );
Loading history...
1519
			} else {
1520
				$field_name = '[' . $field_name . ']';
1521
			}
1522
	
1523
			return 'widget-' . $this->base_id . '[' . $this->get_number() . ']' . $field_name;
1524
		}
1525
	
1526
		public function widget_inputs_row_end($key, $args){
0 ignored issues
show
Unused Code introduced by
The parameter $key is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

1526
		public function widget_inputs_row_end(/** @scrutinizer ignore-unused */ $key, $args){

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
1527
			if(!empty($args['row'])){
1528
				// maybe close
1529
				if(!empty($args['row']['close'])){
1530
					echo "</div></div>";
1531
				}
1532
	
1533
				echo "</div>";
1534
			}
1535
		}
1536
	
1537
		/**
1538
		 * Generate and return inline styles from CSS rules that will match the unique class of the instance.
1539
		 *
1540
		 * @param array $rules
1541
		 *
1542
		 * @since 1.0.20
1543
		 * @return string
1544
		 */
1545
		public function get_instance_style($rules = array()){
1546
			$css = '';
1547
	
1548
			if(!empty($rules)){
1549
				$rules = array_unique($rules);
1550
				$instance_hash = $this->get_instance_hash();
1551
				$css .= "<style>";
1552
				foreach($rules as $rule){
1553
					$css .= ".sdel-$instance_hash $rule";
1554
				}
1555
				$css .= "</style>";
1556
			}
1557
	
1558
			return $css;
1559
		}
1560
	
1561
		/**
1562
		 * Get an instance hash that will be unique to the type and settings.
1563
		 *
1564
		 * @since 1.0.20
1565
		 * @return string
1566
		 */
1567
		public function get_instance_hash(){
1568
			$instance_string = $this->base_id . serialize( $this->instance );
1569
			return hash( 'crc32b', $instance_string );
1570
		}
1571
	
1572
		/**
1573
		 * Get the conditional fields JavaScript.
1574
		 *
1575
		 * @return mixed
1576
		 */
1577
		public function conditional_fields_js() {
1578
			ob_start();
1579
			?>
1580
			<script>
1581
			/**
1582
			* Conditional Fields
1583
			*/
1584
			var sd_cf_field_rules = [], sd_cf_field_key_rules = {}, sd_cf_field_default_values = {};
1585
	
1586
			jQuery(function($) {
1587
				/* Init conditional fields */
1588
				sd_cf_field_init_rules($);
1589
			});
1590
	
1591
			/**
1592
			* Conditional fields init.
1593
			*/
1594
			function sd_cf_field_init_rules($) {
1595
				if (!$('[data-has-rule]').length) {
1596
					return;
1597
				}
1598
	
1599
				$('[data-rule-key]').on('change keypress keyup', 'input, textarea', function() {
1600
					sd_cf_field_apply_rules($(this));
1601
				});
1602
	
1603
				$('[data-rule-key]').on('change', 'select', function() {
1604
					sd_cf_field_apply_rules($(this));
1605
				});
1606
	
1607
				$('[data-rule-key]').on('change.select2', 'select', function() {
1608
					sd_cf_field_apply_rules($(this));
1609
				});
1610
	
1611
				/*jQuery(document).on('sd_cf_field_on_change', function() {
1612
					sd_cf_field_hide_child_elements();
1613
				});*/
1614
	
1615
				sd_cf_field_setup_rules($);
1616
			}
1617
	
1618
			/**
1619
			* Setup conditional field rules.
1620
			*/
1621
			function sd_cf_field_setup_rules($) {
1622
				var sd_cf_field_keys = [];
1623
	
1624
				$('[data-rule-key]').each(function() {
1625
					var key = jQuery(this).data('rule-key'),
1626
						irule = parseInt(jQuery(this).data('has-rule'));
1627
					if (key) {
1628
						sd_cf_field_keys.push(key);
1629
					}
1630
	
1631
					var parse_conds = {};
1632
					if ($(this).data('rule-fie-0')) {
1633
						for (var i = 0; i < irule; i++) {
1634
							var field = $(this).data('rule-fie-' + i);
1635
							if (typeof parse_conds[i] === 'undefined') {
1636
								parse_conds[i] = {};
1637
							}
1638
							parse_conds[i]['action'] = $(this).data('rule-act-' + i);
1639
							parse_conds[i]['field'] = $(this).data('rule-fie-' + i);
1640
							parse_conds[i]['condition'] = $(this).data('rule-con-' + i);
1641
							parse_conds[i]['value'] = $(this).data('rule-val-' + i);
1642
						}
1643
	
1644
						jQuery.each(parse_conds, function(j, data) {
1645
							var item = {
1646
								'field': {
1647
									key: key,
1648
									action: data.action,
1649
									field: data.field,
1650
									condition: data.condition,
1651
									value: data.value,
1652
									rule: {
1653
										key: key,
1654
										action: data.action,
1655
										condition: data.condition,
1656
										value: data.value
1657
									}
1658
								}
1659
							};
1660
							sd_cf_field_rules.push(item);
1661
						});
1662
					}
1663
					sd_cf_field_default_values[jQuery(this).data('rule-key')] = sd_cf_field_get_default_value(jQuery(this));
1664
				});
1665
	
1666
				jQuery.each(sd_cf_field_keys, function(i, fkey) {
1667
					sd_cf_field_key_rules[fkey] = sd_cf_field_get_children(fkey);
1668
				});
1669
	
1670
				jQuery('[data-rule-key]:visible').each(function() {
1671
					var conds = sd_cf_field_key_rules[jQuery(this).data('rule-key')];
1672
					if (conds && conds.length) {
1673
						var $main_el = jQuery(this), el = sd_cf_field_get_element($main_el);
1674
						if (jQuery(el).length) {
1675
							sd_cf_field_apply_rules(jQuery(el));
1676
						}
1677
					}
1678
				});
1679
			}
1680
	
1681
			/**
1682
			* Apply conditional field rules.
1683
			*/
1684
			function sd_cf_field_apply_rules($el) {
1685
				if (!$el.parents('[data-rule-key]').length) {
1686
					return;
1687
				}
1688
	
1689
				if ($el.data('no-rule')) {
1690
					return;
1691
				}
1692
	
1693
				var key = $el.parents('[data-rule-key]').data('rule-key');
1694
				var conditions = sd_cf_field_key_rules[key];
1695
				if (typeof conditions === 'undefined') {
1696
					return;
1697
				}
1698
				var field_type = sd_cf_field_get_type($el.parents('[data-rule-key]')),
1699
					current_value = sd_cf_field_get_value($el);
1700
	
1701
				var $keys = {},
1702
					$keys_values = {},
1703
					$key_rules = {};
1704
	
1705
				jQuery.each(conditions, function(index, condition) {
1706
					if (typeof $keys_values[condition.key] == 'undefined') {
1707
						$keys_values[condition.key] = [];
1708
						$key_rules[condition.key] = {}
1709
					}
1710
	
1711
					$keys_values[condition.key].push(condition.value);
1712
					$key_rules[condition.key] = condition;
1713
				});
1714
	
1715
				jQuery.each(conditions, function(index, condition) {
1716
					if (typeof $keys[condition.key] == 'undefined') {
1717
						$keys[condition.key] = {};
1718
					}
1719
	
1720
					if (condition.condition === 'empty') {
1721
						var field_value = Array.isArray(current_value) ? current_value.join('') : current_value;
1722
						if (!field_value || field_value === '') {
1723
							$keys[condition.key][index] = true;
1724
						} else {
1725
							$keys[condition.key][index] = false;
1726
						}
1727
					} else if (condition.condition === 'not empty') {
1728
						var field_value = Array.isArray(current_value) ? current_value.join('') : current_value;
1729
						if (field_value && field_value !== '') {
1730
							$keys[condition.key][index] = true;
1731
						} else {
1732
							$keys[condition.key][index] = false;
1733
						}
1734
					} else if (condition.condition === 'equals to') {
1735
						var field_value = (Array.isArray(current_value) && current_value.length === 1) ? current_value[0] : current_value;
1736
						if (((condition.value && condition.value == condition.value) || (condition.value === field_value)) && sd_cf_field_in_array(field_value, $keys_values[condition.key])) {
1737
							$keys[condition.key][index] = true;
1738
						} else {
1739
							$keys[condition.key][index] = false;
1740
						}
1741
					} else if (condition.condition === 'not equals') {
1742
						var field_value = (Array.isArray(current_value) && current_value.length === 1) ? current_value[0] : current_value;
1743
						if (jQuery.isNumeric(condition.value) && parseInt(field_value) !== parseInt(condition.value) && field_value && !sd_cf_field_in_array(field_value, $keys_values[condition.key])) {
1744
							$keys[condition.key][index] = true;
1745
						} else if (condition.value != field_value && !sd_cf_field_in_array(field_value, $keys_values[condition.key])) {
1746
							$keys[condition.key][index] = true;
1747
						} else {
1748
							$keys[condition.key][index] = false;
1749
						}
1750
					} else if (condition.condition === 'greater than') {
1751
						var field_value = (Array.isArray(current_value) && current_value.length === 1) ? current_value[0] : current_value;
1752
						if (jQuery.isNumeric(condition.value) && parseInt(field_value) > parseInt(condition.value)) {
1753
							$keys[condition.key][index] = true;
1754
						} else {
1755
							$keys[condition.key][index] = false;
1756
						}
1757
					} else if (condition.condition === 'less than') {
1758
						var field_value = (Array.isArray(current_value) && current_value.length === 1) ? current_value[0] : current_value;
1759
						if (jQuery.isNumeric(condition.value) && parseInt(field_value) < parseInt(condition.value)) {
1760
							$keys[condition.key][index] = true;
1761
						} else {
1762
							$keys[condition.key][index] = false;
1763
						}
1764
					} else if (condition.condition === 'contains') {
1765
						switch (field_type) {
1766
							case 'multiselect':
1767
								if (current_value && ((!Array.isArray(current_value) && current_value.indexOf(condition.value) >= 0) || (Array.isArray(current_value) && sd_cf_field_in_array(condition.value, current_value)))) { //
1768
									$keys[condition.key][index] = true;
1769
								} else {
1770
									$keys[condition.key][index] = false;
1771
								}
1772
								break;
1773
							case 'checkbox':
1774
								if (current_value && ((!Array.isArray(current_value) && current_value.indexOf(condition.value) >= 0) || (Array.isArray(current_value) && sd_cf_field_in_array(condition.value, current_value)))) { //
1775
									$keys[condition.key][index] = true;
1776
								} else {
1777
									$keys[condition.key][index] = false;
1778
								}
1779
								break;
1780
							default:
1781
								if (typeof $keys[condition.key][index] === 'undefined') {
1782
									if (current_value && current_value.indexOf(condition.value) >= 0 && sd_cf_field_in_array(current_value, $keys_values[condition.key])) {
1783
										$keys[condition.key][index] = true;
1784
									} else {
1785
										$keys[condition.key][index] = false;
1786
									}
1787
								}
1788
								break;
1789
						}
1790
					}
1791
				});
1792
	
1793
				jQuery.each($keys, function(index, field) {
1794
					if (sd_cf_field_in_array(true, field)) {
1795
						sd_cf_field_apply_action($el, $key_rules[index], true);
1796
					} else {
1797
						sd_cf_field_apply_action($el, $key_rules[index], false);
1798
					}
1799
				});
1800
	
1801
				/* Trigger field change */
1802
				if ($keys.length) {
1803
					$el.trigger('sd_cf_field_on_change');
1804
				}
1805
			}
1806
	
1807
			/**
1808
			* Get the field element.
1809
			*/
1810
			function sd_cf_field_get_element($el) {
1811
				var el = $el.find('input,textarea,select'),
1812
					type = sd_cf_field_get_type($el);
1813
				if (type && window._sd_cf_field_elements && typeof window._sd_cf_field_elements == 'object' && typeof window._sd_cf_field_elements[type] != 'undefined') {
1814
					el = window._sd_cf_field_elements[type];
1815
				}
1816
				return el;
1817
			}
1818
	
1819
			/**
1820
			* Get the field type.
1821
			*/
1822
			function sd_cf_field_get_type($el) {
1823
				return $el.data('rule-type');
1824
			}
1825
	
1826
			/**
1827
			* Get the field value.
1828
			*/
1829
			function sd_cf_field_get_value($el) {
1830
				var current_value = $el.val();
1831
	
1832
				if ($el.is(':checkbox')) {
1833
					current_value = '';
1834
					if ($el.parents('[data-rule-key]').find('input:checked').length > 1) {
1835
						$el.parents('[data-rule-key]').find('input:checked').each(function() {
1836
							current_value = current_value + jQuery(this).val() + ' ';
1837
						});
1838
					} else {
1839
						if ($el.parents('[data-rule-key]').find('input:checked').length >= 1) {
1840
							current_value = $el.parents('[data-rule-key]').find('input:checked').val();
1841
						}
1842
					}
1843
				}
1844
	
1845
				if ($el.is(':radio')) {
1846
					current_value = $el.parents('[data-rule-key]').find('input[type=radio]:checked').val();
1847
				}
1848
	
1849
				return current_value;
1850
			}
1851
	
1852
			/**
1853
			* Get the field default value.
1854
			*/
1855
			function sd_cf_field_get_default_value($el) {
1856
				var value = '',
1857
					type = sd_cf_field_get_type($el);
1858
	
1859
				switch (type) {
1860
					case 'text':
1861
					case 'number':
1862
					case 'date':
1863
					case 'textarea':
1864
					case 'select':
1865
						value = $el.find('input:text,input[type="number"],textarea,select').val();
1866
						break;
1867
					case 'phone':
1868
					case 'email':
1869
					case 'color':
1870
					case 'url':
1871
					case 'hidden':
1872
					case 'password':
1873
					case 'file':
1874
						value = $el.find('input[type="' + type + '"]').val();
1875
						break;
1876
					case 'multiselect':
1877
						value = $el.find('select').val();
1878
						break;
1879
					case 'radio':
1880
						if ($el.find('input[type="radio"]:checked').length >= 1) {
1881
							value = $el.find('input[type="radio"]:checked').val();
1882
						}
1883
						break;
1884
					case 'checkbox':
1885
						if ($el.find('input[type="checkbox"]:checked').length >= 1) {
1886
							if ($el.find('input[type="checkbox"]:checked').length > 1) {
1887
								var values = [];
1888
								values.push(value);
1889
								$el.find('input[type="checkbox"]:checked').each(function() {
1890
									values.push(jQuery(this).val());
1891
								});
1892
								value = values;
1893
							} else {
1894
								value = $el.find('input[type="checkbox"]:checked').val();
1895
							}
1896
						}
1897
						break;
1898
					default:
1899
						if (window._sd_cf_field_default_values && typeof window._sd_cf_field_default_values == 'object' && typeof window._sd_cf_field_default_values[type] != 'undefined') {
1900
							value = window._sd_cf_field_default_values[type];
1901
						}
1902
						break;
1903
				}
1904
				return {
1905
					type: type,
1906
					value: value
1907
				};
1908
			}
1909
	
1910
			/**
1911
			* Reset field default value.
1912
			*/
1913
			function sd_cf_field_reset_default_value($el) {
1914
				var type = sd_cf_field_get_type($el),
1915
					key = $el.data('rule-key'),
1916
					field = sd_cf_field_default_values[key];
1917
	
1918
				switch (type) {
1919
					case 'text':
1920
					case 'number':
1921
					case 'date':
1922
					case 'textarea':
1923
						$el.find('input:text,input[type="number"],textarea').val(field.value);
1924
						break;
1925
					case 'phone':
1926
					case 'email':
1927
					case 'color':
1928
					case 'url':
1929
					case 'hidden':
1930
					case 'password':
1931
					case 'file':
1932
						$el.find('input[type="' + type + '"]').val(field.value);
1933
						break;
1934
					case 'select':
1935
						$el.find('select').find('option').prop('selected', false);
1936
						$el.find('select').val(field.value);
1937
						$el.find('select').trigger('change');
1938
						break;
1939
					case 'multiselect':
1940
						$el.find('select').find('option').prop('selected', false);
1941
						if ((typeof field.value === 'object' || typeof field.value === 'array') && !field.value.length && $el.find('select option:first').text() == '') {
1942
							$el.find('select option:first').remove(); // Clear first option to show placeholder.
1943
						}
1944
						jQuery.each(field.value, function(i, v) {
1945
							$el.find('select').find('option[value="' + v + '"]').attr('selected', true);
1946
						});
1947
						$el.find('select').trigger('change');
1948
						break;
1949
					case 'checkbox':
1950
						if ($el.find('input[type="checkbox"]:checked').length >= 1) {
1951
							$el.find('input[type="checkbox"]:checked').prop('checked', false);
1952
							if (Array.isArray(field.value)) {
1953
								jQuery.each(field.value, function(i, v) {
1954
									$el.find('input[type="checkbox"][value="' + v + '"]').attr('checked', true);
1955
								});
1956
							} else {
1957
								$el.find('input[type="checkbox"][value="' + field.value + '"]').attr('checked', true);
1958
							}
1959
						}
1960
						break;
1961
					case 'radio':
1962
						if ($el.find('input[type="radio"]:checked').length >= 1) {
1963
							setTimeout(function() {
1964
								$el.find('input[type="radio"]:checked').prop('checked', false);
1965
								$el.find('input[type="radio"][value="' + field.value + '"]').attr('checked', true);
1966
							}, 100);
1967
						}
1968
						break;
1969
					default:
1970
						jQuery(document.body).trigger('sd_cf_field_reset_default_value', type, $el, field);
1971
						break;
1972
				}
1973
	
1974
				if (!$el.hasClass('sd-cf-field-has-changed')) {
1975
					var el = sd_cf_field_get_element($el);
1976
					if (type === 'radio' || type === 'checkbox') {
1977
						el = el.find(':checked');
1978
					}
1979
					if (el) {
1980
						el.trigger('change');
1981
						$el.addClass('sd-cf-field-has-changed');
1982
					}
1983
				}
1984
			}
1985
	
1986
			/**
1987
			* Get the field children.
1988
			*/
1989
			function sd_cf_field_get_children(field_key) {
1990
				var rules = [];
1991
				jQuery.each(sd_cf_field_rules, function(j, rule) {
1992
					if (rule.field.field === field_key) {
1993
						rules.push(rule.field.rule);
1994
					}
1995
				});
1996
				return rules;
1997
			}
1998
	
1999
			/**
2000
			* Check in array field value.
2001
			*/
2002
			function sd_cf_field_in_array(find, item, match) {
2003
				var found = false,
2004
					key;
2005
				match = !!match;
2006
	
2007
				for (key in item) {
2008
					if ((match && item[key] === find) || (!match && item[key] == find)) {
2009
						found = true;
2010
						break;
2011
					}
2012
				}
2013
				return found;
2014
			}
2015
	
2016
			/**
2017
			* App the field condition action.
2018
			*/
2019
			function sd_cf_field_apply_action($el, rule, isTrue) {
2020
				var $destEl = jQuery('[data-rule-key="' + rule.key + '"]');
2021
	
2022
				if (rule.action === 'show' && isTrue) {
2023
					if ($destEl.is(':hidden')) {
2024
						sd_cf_field_reset_default_value($destEl);
2025
					}
2026
					sd_cf_field_show_element($destEl);
2027
				} else if (rule.action === 'show' && !isTrue) {
2028
					sd_cf_field_hide_element($destEl);
2029
				} else if (rule.action === 'hide' && isTrue) {
2030
					sd_cf_field_hide_element($destEl);
2031
				} else if (rule.action === 'hide' && !isTrue) {
2032
					if ($destEl.is(':hidden')) {
2033
						sd_cf_field_reset_default_value($destEl);
2034
					}
2035
					sd_cf_field_show_element($destEl);
2036
				}
2037
				return $el.removeClass('sd-cf-field-has-changed');
2038
			}
2039
	
2040
			/**
2041
			* Show field element.
2042
			*/
2043
			function sd_cf_field_show_element($el) {
2044
				$el.removeClass('d-none').show();
2045
	
2046
				if (window && window.navigator.userAgent.indexOf("MSIE") !== -1) {
2047
					$el.css({
2048
						"visibility": "visible"
2049
					});
2050
				}
2051
			}
2052
	
2053
			/**
2054
			* Hide field element.
2055
			*/
2056
			function sd_cf_field_hide_element($el) {
2057
				$el.addClass('d-none').hide();
2058
	
2059
				if (window && window.navigator.userAgent.indexOf("MSIE") !== -1) {
2060
					$el.css({
2061
						"visibility": "hidden"
2062
					});
2063
				}
2064
			}
2065
	
2066
			/**
2067
			* Show field child elements.
2068
			*/
2069
			function sd_cf_field_hide_child_elements() {
2070
				jQuery.each(sd_cf_field_key_rules, function(i, conds) {
2071
					if (i && conds && conds.length && (jQuery('[data-rule-key="' + i + '"]:hidden').length >= 1 || jQuery('[data-rule-key="' + i + '"]').css('display') === 'none')) {
2072
						jQuery.each(conds, function(key, cond) {
2073
							jQuery('[data-rule-key="' + cond.key + '"]').addClass('d-none').hide();
2074
						});
2075
					}
2076
				});
2077
			}
2078
			<?php do_action( 'wp_super_duper_conditional_fields_js', $this ); ?>
2079
			</script>
2080
						<?php
2081
						$output = ob_get_clean();
2082
	
2083
						return str_replace( array( '<script>', '</script>' ), '', trim( $output ) );
2084
			}
2085
	
2086
		/**
2087
		 * Output the super title.
2088
		 *
2089
		 * @param $args
2090
		 * @param array $instance
2091
		 *
2092
		 * @return string
2093
		 */
2094
		public function output_title( $args, $instance = array() ) {
2095
			$output = '';
2096
	
2097
			if ( ! empty( $instance['title'] ) ) {
2098
				/** This filter is documented in wp-includes/widgets/class-wp-widget-pages.php */
2099
				$title  = apply_filters( 'widget_title', $instance['title'], $instance, $this->base_id );
2100
	
2101
				if ( empty( $instance['widget_title_tag'] ) ) {
2102
					$output = $args['before_title'] . $title . $args['after_title'];
2103
				} else {
2104
					$title_tag = esc_attr( $instance['widget_title_tag'] );
2105
	
2106
					// classes
2107
					$title_classes = array();
2108
					$title_classes[] = !empty( $instance['widget_title_size_class'] ) ? sanitize_html_class( $instance['widget_title_size_class'] ) : '';
2109
					$title_classes[] = !empty( $instance['widget_title_align_class'] ) ? sanitize_html_class( $instance['widget_title_align_class'] ) : '';
2110
					$title_classes[] = !empty( $instance['widget_title_color_class'] ) ? "text-".sanitize_html_class( $instance['widget_title_color_class'] ) : '';
2111
					$title_classes[] = !empty( $instance['widget_title_border_class'] ) ? sanitize_html_class( $instance['widget_title_border_class'] ) : '';
2112
					$title_classes[] = !empty( $instance['widget_title_border_color_class'] ) ? "border-".sanitize_html_class( $instance['widget_title_border_color_class'] ) : '';
2113
					$title_classes[] = !empty( $instance['widget_title_mt_class'] ) ? "mt-".absint( $instance['widget_title_mt_class'] ) : '';
2114
					$title_classes[] = !empty( $instance['widget_title_mr_class'] ) ? "mr-".absint( $instance['widget_title_mr_class'] ) : '';
2115
					$title_classes[] = !empty( $instance['widget_title_mb_class'] ) ? "mb-".absint( $instance['widget_title_mb_class'] ) : '';
2116
					$title_classes[] = !empty( $instance['widget_title_ml_class'] ) ? "ml-".absint( $instance['widget_title_ml_class'] ) : '';
2117
					$title_classes[] = !empty( $instance['widget_title_pt_class'] ) ? "pt-".absint( $instance['widget_title_pt_class'] ) : '';
2118
					$title_classes[] = !empty( $instance['widget_title_pr_class'] ) ? "pr-".absint( $instance['widget_title_pr_class'] ) : '';
2119
					$title_classes[] = !empty( $instance['widget_title_pb_class'] ) ? "pb-".absint( $instance['widget_title_pb_class'] ) : '';
2120
					$title_classes[] = !empty( $instance['widget_title_pl_class'] ) ? "pl-".absint( $instance['widget_title_pl_class'] ) : '';
2121
					$title_classes   = array_filter( $title_classes );
2122
	
2123
					$class  = ! empty( $title_classes ) ? implode( ' ', $title_classes ) : '';
2124
					$output = "<$title_tag class='$class' >$title</$title_tag>";
2125
				}
2126
	
2127
			}
2128
	
2129
			return $output;
2130
		}
2131
2132
		/**
2133
		 * Backwards compatibility for SDv1
2134
		 * 
2135
		 * @param string $editor_id
2136
		 * @param string $insert_shortcode_function
2137
		 * 
2138
		 * @return string|void
2139
		 */
2140
		public static function shortcode_insert_button( $editor_id = '', $insert_shortcode_function = '' ) {
2141
			return class_exists('WP_Super_Duper_Shortcode') ? WP_Super_Duper_Shortcode::shortcode_insert_button( $editor_id, $insert_shortcode_function ) : '';
0 ignored issues
show
Bug introduced by
Are you sure the usage of WP_Super_Duper_Shortcode...ert_shortcode_function) targeting WP_Super_Duper_Shortcode...ortcode_insert_button() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
2142
		}
2143
2144
		/**
2145
		 * Backwards compatibility for SDv1
2146
		 * 
2147
		 * @param string $id
2148
		 * @param string $search_for_id
2149
		 * 
2150
		 * @return mixed|string
2151
		 */
2152
		public static function shortcode_button( $id = '', $search_for_id = '') {
2153
			return class_exists('WP_Super_Duper_Shortcode') ? WP_Super_Duper_Shortcode::shortcode_button( $id, $search_for_id ) : '';
2154
		}
2155
	
2156
	}
2157
2158
}
2159