Passed
Push — master ( fecf8d...919089 )
by Stiofan
01:09 queued 10s
created

WP_Super_Duper::siteorigin_js()   B

Complexity

Conditions 1
Paths 1

Size

Total Lines 91

Duplication

Lines 91
Ratio 100 %

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 0
dl 91
loc 91
rs 8.1963
c 0
b 0
f 0

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
if ( ! defined( 'ABSPATH' ) ) {
3
	exit;
4
}
5
6
if ( ! class_exists( 'WP_Super_Duper' ) ) {
7
8
9
	/**
10
	 * A Class to be able to create a Widget, Shortcode or Block to be able to output content for WordPress.
11
	 *
12
	 * Should not be called direct but extended instead.
13
	 *
14
	 * Class WP_Super_Duper
15
	 * @since 1.0.3 is_block_content_call() method added.
16
	 * @since 1.0.3 Placeholder text will be shown for widget that return no block content.
17
	 * @since 1.0.4 is_elementor_widget_output() method added.
18
	 * @since 1.0.4 is_elementor_preview() method added.
19
	 * @since 1.0.5 Block checkbox options are set as true by default even when set as false - FIXED
20
	 * @since 1.0.6 Some refactoring for page builders - CHANGED
21
	 * @ver 1.0.6
22
	 */
23
	class WP_Super_Duper extends WP_Widget {
24
25
		public $version = "1.0.6";
26
		public $block_code;
27
		public $options;
28
		public $base_id;
29
		public $arguments = array();
30
		public $instance = array();
31
		private $class_name;
32
33
		/**
34
		 * Take the array options and use them to build.
35
		 */
36
		public function __construct( $options ) {
37
			global $sd_widgets;
38
39
			$sd_widgets[ $options['base_id'] ] = array(
40
				'name'       => $options['name'],
41
				'class_name' => $options['class_name']
42
			);
43
			$this->base_id                     = $options['base_id'];
44
			// lets filter the options before we do anything
45
			$options       = apply_filters( "wp_super_duper_options", $options );
46
			$options       = apply_filters( "wp_super_duper_options_{$this->base_id}", $options );
47
			$options       = $this->add_name_from_key( $options );
48
			$this->options = $options;
49
50
			$this->base_id   = $options['base_id'];
51
			$this->arguments = isset( $options['arguments'] ) ? $options['arguments'] : array();
52
53
			// init parent
54
			parent::__construct( $options['base_id'], $options['name'], $options['widget_ops'] );
55
56
			if ( isset( $options['class_name'] ) ) {
57
				// register widget
58
				$this->class_name = $options['class_name'];
59
60
				// register shortcode
61
				$this->register_shortcode();
62
63
				// register block
64
				add_action( 'admin_enqueue_scripts', array( $this, 'register_block' ) );
65
			}
66
67
			// add the CSS and JS we need ONCE
68
			global $sd_widget_scripts;
69
70
			if ( ! $sd_widget_scripts ) {
71
				wp_add_inline_script( 'admin-widgets', $this->widget_js() );
72
				wp_add_inline_script( 'customize-controls', $this->widget_js() );
73
				wp_add_inline_style( 'widgets', $this->widget_css() );
74
75
				$sd_widget_scripts = true;
76
77
				// add shortcode insert button once
78
				add_action( 'media_buttons', array( $this, 'shortcode_insert_button' ) );
79
				if ( $this->is_preview() ) {
80
					add_action( 'wp_footer', array( $this, 'shortcode_insert_button_script' ) );
81
				}
82
				add_action( 'wp_ajax_super_duper_get_widget_settings', array( __CLASS__, 'get_widget_settings' ) );
83
			}
84
85
			do_action( 'wp_super_duper_widget_init', $options, $this );
86
		}
87
88
		/**
89
		 * Get widget settings.
90
		 *
91
		 * @since 1.0.0
92
		 */
93
		public static function get_widget_settings() {
94
			global $sd_widgets;
95
96
			$shortcode = isset( $_REQUEST['shortcode'] ) && $_REQUEST['shortcode'] ? sanitize_title_with_dashes( $_REQUEST['shortcode'] ) : '';
97
			if ( ! $shortcode ) {
98
				wp_die();
99
			}
100
			$widget_args = isset( $sd_widgets[ $shortcode ] ) ? $sd_widgets[ $shortcode ] : '';
101
			if ( ! $widget_args ) {
102
				wp_die();
103
			}
104
			$class_name = isset( $widget_args['class_name'] ) && $widget_args['class_name'] ? $widget_args['class_name'] : '';
105
			if ( ! $class_name ) {
106
				wp_die();
107
			}
108
109
			// invoke an instance method
110
			$widget = new $class_name;
111
112
			ob_start();
113
			$widget->form( array() );
114
			$form = ob_get_clean();
115
			echo "<form id='$shortcode'>" . $form . "<div class=\"widget-control-save\"></div></form>";
116
			echo "<style>" . $widget->widget_css() . "</style>";
117
			echo "<script>" . $widget->widget_js() . "</script>";
118
			?>
119
			<?php
120
			wp_die();
121
		}
122
123
		/**
124
		 * Insert shortcode builder button to classic editor (not inside Gutenberg, not needed).
125
		 *
126
		 * @since 1.0.0
127
		 *
128
		 * @param string $editor_id Optional. Shortcode editor id. Default null.
129
		 * @param string $insert_shortcode_function Optional. Insert shotcode function. Default null.
130
		 */
131
		public static function shortcode_insert_button( $editor_id = '', $insert_shortcode_function = '' ) {
132
			global $sd_widgets, $shortcode_insert_button_once;
133
			if ( $shortcode_insert_button_once ) {
134
				return;
135
			}
136
			add_thickbox();
137
			?>
138
			<div id="super-duper-content" style="display:none;">
139
140
				<div class="sd-shortcode-left-wrap">
141
					<?php
142
					asort( $sd_widgets );
143
					if ( ! empty( $sd_widgets ) ) {
144
						echo '<select class="widefat" onchange="sd_get_shortcode_options(this);">';
145
						echo "<option>" . __( 'Select shortcode' ) . "</option>";
146
						foreach ( $sd_widgets as $shortcode => $class ) {
147
							echo "<option value='" . esc_attr( $shortcode ) . "'>" . esc_attr( $shortcode ) . " (" . esc_attr( $class['name'] ) . ")</option>";
148
						}
149
						echo "</select>";
150
151
					}
152
					?>
153
					<div class="sd-shortcode-settings"></div>
154
155
				</div>
156
157
				<div class="sd-shortcode-right-wrap">
158
					<textarea id='sd-shortcode-output' disabled></textarea>
159
					<div id='sd-shortcode-output-actions'>
160
						<button class="button"
161
						        onclick="sd_insert_shortcode(<?php if ( ! empty( $editor_id ) ) {
162
							        echo "'" . $editor_id . "'";
163
						        } ?>)"><?php _e( 'Insert shortcode' ); ?></button>
164
						<button class="button"
165
						        onclick="sd_copy_to_clipboard()"><?php _e( 'Copy shortcode' ); ?></button>
166
					</div>
167
				</div>
168
169
			</div>
170
171
			<?php
172
			// if Font Awesome is available then show a icon if not show a WP icon.
173
			$button_string = wp_style_is( 'font-awesome', 'enqueued' ) && 1 == 2 ? '<i class="fas fa-cubes" aria-hidden="true"></i>' : '<span style="vertical-align: middle;line-height: 18px;font-size: 20px;" class="dashicons dashicons-screenoptions"></span>';
174
			?>
175
176
			<a href="#TB_inline?width=100%&height=550&inlineId=super-duper-content"
177
			   class="thickbox button super-duper-content-open"
178
			   title="<?php _e( 'Add Shortcode' ); ?>"><?php echo $button_string; ?></a>
179
180
			<?php
181
			self::shortcode_insert_button_script( $editor_id, $insert_shortcode_function );
182
			$shortcode_insert_button_once = true;
183
		}
184
185
		/**
186
		 * Makes SD work with the siteOrigin page builder.
187
		 *
188
		 * @since 1.0.6
189
		 * @return mixed
190
		 */
191 View Code Duplication
		public static function siteorigin_js() {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
192
			ob_start();
193
			?>
194
			<script>
195
				/**
196
				 * Check a form to see what items shoudl be shown or hidden.
197
				 */
198
				function sd_so_show_hide(form) {
199
					jQuery(form).find(".sd-argument").each(function () {
200
201
						var $element_require = jQuery(this).data('element_require');
202
203
						if ($element_require) {
204
205
							$element_require = $element_require.replace("&#039;", "'"); // replace single quotes
206
							$element_require = $element_require.replace("&quot;", '"'); // replace double quotes
207
208
							if (eval($element_require)) {
209
								jQuery(this).removeClass('sd-require-hide');
210
							} else {
211
								jQuery(this).addClass('sd-require-hide');
212
							}
213
						}
214
					});
215
				}
216
217
				/**
218
				 * Toggle advanced settings visibility.
219
				 */
220
				function sd_so_toggle_advanced($this) {
221
					var form = jQuery($this).parents('form,.form,.so-content');
222
					form.find('.sd-advanced-setting').toggleClass('sd-adv-show');
223
					return false;// prevent form submit
224
				}
225
226
				/**
227
				 * Initialise a individual widget.
228
				 */
229
				function sd_so_init_widget($this, $selector) {
230
					if (!$selector) {
231
						$selector = 'form';
232
					}
233
					// only run once.
234
					if (jQuery($this).data('sd-widget-enabled')) {
235
						return;
236
					} else {
237
						jQuery($this).data('sd-widget-enabled', true);
238
					}
239
240
					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>';
241
					var form = jQuery($this).parents('' + $selector + '');
242
243
					if (jQuery($this).val() == '1' && jQuery(form).find('.sd-advanced-button').length == 0) {
244
						jQuery(form).append($button);
245
					}
246
247
					// show hide on form change
248
					jQuery(form).change(function () {
249
						sd_so_show_hide(form);
250
					});
251
252
					// show hide on load
253
					sd_so_show_hide(form);
254
				}
255
256
				jQuery(function () {
257
					jQuery(document).on('open_dialog', function (w, e) {
258
						setTimeout(function () {
259
							if (jQuery('.so-panels-dialog-wrapper:visible .so-content.panel-dialog .sd-show-advanced').length) {
260
								console.log('exists');
261
								if (jQuery('.so-panels-dialog-wrapper:visible .so-content.panel-dialog .sd-show-advanced').val() == '1') {
262
									console.log('true');
263
									sd_so_init_widget('.so-panels-dialog-wrapper:visible .so-content.panel-dialog .sd-show-advanced', 'div');
264
								}
265
							}
266
						}, 200);
267
					});
268
				});
269
			</script>
270
			<?php
271
			$output = ob_get_clean();
272
273
			/*
274
			 * We only add the <script> tags for code highlighting, so we strip them from the output.
275
			 */
276
277
			return str_replace( array(
278
				'<script>',
279
				'</script>'
280
			), '', $output );
281
		}
282
283
		/**
284
		 * Output the JS and CSS for the shortcode insert button.
285
		 *
286
		 * @since 1.0.6
287
		 *
288
		 * @param string $editor_id
289
		 * @param string $insert_shortcode_function
290
		 */
291
		public static function shortcode_insert_button_script( $editor_id = '', $insert_shortcode_function = '' ) {
292
			?>
293
			<style>
294
				.sd-shortcode-left-wrap {
295
					float: left;
296
					width: 60%;
297
				}
298
299
				.sd-shortcode-left-wrap .gd-help-tip {
300
					float: none;
301
				}
302
303
				.sd-shortcode-left-wrap .widefat {
304
					border-spacing: 0;
305
					width: 100%;
306
					clear: both;
307
					margin: 0;
308
					border: 1px solid #ddd;
309
					box-shadow: inset 0 1px 2px rgba(0, 0, 0, .07);
310
					background-color: #fff;
311
					color: #32373c;
312
					outline: 0;
313
					transition: 50ms border-color ease-in-out;
314
					padding: 3px 5px;
315
				}
316
317
				.sd-shortcode-left-wrap input[type=checkbox].widefat {
318
					border: 1px solid #b4b9be;
319
					background: #fff;
320
					color: #555;
321
					clear: none;
322
					cursor: pointer;
323
					display: inline-block;
324
					line-height: 0;
325
					height: 16px;
326
					margin: -4px 4px 0 0;
327
					margin-top: 0;
328
					outline: 0;
329
					padding: 0 !important;
330
					text-align: center;
331
					vertical-align: middle;
332
					width: 16px;
333
					min-width: 16px;
334
					-webkit-appearance: none;
335
					box-shadow: inset 0 1px 2px rgba(0, 0, 0, .1);
336
					transition: .05s border-color ease-in-out;
337
				}
338
339
				.sd-shortcode-left-wrap input[type=checkbox]:checked:before {
340
					content: "\f147";
341
					margin: -3px 0 0 -4px;
342
					color: #1e8cbe;
343
					float: left;
344
					display: inline-block;
345
					vertical-align: middle;
346
					width: 16px;
347
					font: normal 21px/1 dashicons;
348
					speak: none;
349
					-webkit-font-smoothing: antialiased;
350
					-moz-osx-font-smoothing: grayscale;
351
				}
352
353
				#sd-shortcode-output-actions button,
354
				.sd-advanced-button {
355
					color: #555;
356
					border-color: #ccc;
357
					background: #f7f7f7;
358
					box-shadow: 0 1px 0 #ccc;
359
					vertical-align: top;
360
					display: inline-block;
361
					text-decoration: none;
362
					font-size: 13px;
363
					line-height: 26px;
364
					height: 28px;
365
					margin: 0;
366
					padding: 0 10px 1px;
367
					cursor: pointer;
368
					border-width: 1px;
369
					border-style: solid;
370
					-webkit-appearance: none;
371
					border-radius: 3px;
372
					white-space: nowrap;
373
					box-sizing: border-box;
374
				}
375
376
				button.sd-advanced-button {
377
					background: #0073aa;
378
					border-color: #006799;
379
					box-shadow: inset 0 2px 0 #006799;
380
					vertical-align: top;
381
					color: #fff;
382
					text-decoration: none;
383
					text-shadow: 0 -1px 1px #006799, 1px 0 1px #006799, 0 1px 1px #006799, -1px 0 1px #006799;
384
					float: right;
385
					margin-right: 3px !important;
386
					font-size: 20px !important;
387
				}
388
389
				.sd-shortcode-right-wrap {
390
					float: right;
391
					width: 35%;
392
				}
393
394
				#sd-shortcode-output {
395
					background: rgba(255, 255, 255, .5);
396
					border-color: rgba(222, 222, 222, .75);
397
					box-shadow: inset 0 1px 2px rgba(0, 0, 0, .04);
398
					color: rgba(51, 51, 51, .5);
399
					overflow: auto;
400
					padding: 2px 6px;
401
					line-height: 1.4;
402
					resize: vertical;
403
				}
404
405
				#sd-shortcode-output {
406
					height: 250px;
407
					width: 100%;
408
				}
409
			</style>
410
			<?php
411
			if ( class_exists( 'SiteOrigin_Panels' ) ) {
412
				echo "<script>" . self::siteorigin_js() . "</script>";
413
			}
414
			?>
415
			<script>
416
				<?php
417
				if(! empty( $insert_shortcode_function )){
418
					echo $insert_shortcode_function;
419
				}else{
420
421
				/**
422
				 * Function for super duper insert shortcode.
423
				 *
424
				 * @since 1.0.0
425
				 */
426
				?>
427
				function sd_insert_shortcode($editor_id) {
428
					$shortcode = jQuery('#sd-shortcode-output').val();
429
					if ($shortcode) {
430
431
						if (!$editor_id) {
432
							$editor_id = "<?php if ( isset( $_REQUEST['et_fb'] ) ) {
433
								echo "#main_content_content_vb_tiny_mce";
434
							} else {
435
								echo "#wp-content-editor-container textarea";
436
							} ?>";
437
						}
438
439
						if (tinyMCE && tinyMCE.activeEditor && jQuery($editor_id).attr("aria-hidden") == "true") {
440
							tinyMCE.execCommand('mceInsertContent', false, $shortcode);
441
						} else {
442
							var $txt = jQuery($editor_id);
443
							var caretPos = $txt[0].selectionStart;
444
							var textAreaTxt = $txt.val();
445
							var txtToAdd = $shortcode;
446
							var textareaValue = textAreaTxt.substring(0, caretPos) + txtToAdd + textAreaTxt.substring(caretPos);
447
							$txt.val(textareaValue).change().keydown().blur().keyup().keypress();
448
449
							// set Divi react input value
450
							var input = document.getElementById("main_content_content_vb_tiny_mce");
451
							if (input) {
452
								sd_setNativeValue(input, textareaValue);
453
							}
454
455
						}
456
						tb_remove();
457
					}
458
				}
459
460
				function sd_setNativeValue(element, value) {
461
					let lastValue = element.value;
462
					element.value = value;
463
					let event = new Event("input", {target: element, bubbles: true});
464
					// React 15
465
					event.simulated = true;
466
					// React 16
467
					let tracker = element._valueTracker;
468
					if (tracker) {
469
						tracker.setValue(lastValue);
470
					}
471
					element.dispatchEvent(event);
472
				}
473
				<?php }?>
474
475
				function sd_copy_to_clipboard() {
476
					/* Get the text field */
477
					var copyText = document.getElementById("sd-shortcode-output");
478
					//un-disable the field
479
					copyText.disabled = false;
480
					/* Select the text field */
481
					copyText.select();
482
					/* Copy the text inside the text field */
483
					document.execCommand("Copy");
484
					//re-disable the field
485
					copyText.disabled = true;
486
					/* Alert the copied text */
487
					alert("Copied the text: " + copyText.value);
488
				}
489
				function sd_get_shortcode_options($this) {
490
491
					$short_code = jQuery($this).val();
492
					if ($short_code) {
493
494
						var data = {
495
							'action': 'super_duper_get_widget_settings',
496
							'shortcode': $short_code,
497
							'attributes': 123,
498
							'post_id': 321,
499
							'_ajax_nonce': '<?php echo wp_create_nonce( 'super_duper_output_shortcode' );?>'
500
						};
501
502
						if (typeof ajaxurl === 'undefined') {
503
							var ajaxurl = "<?php echo admin_url( 'admin-ajax.php' );?>";
504
						}
505
506
						jQuery.post(ajaxurl, data, function (response) {
507
							jQuery('.sd-shortcode-settings').html(response);
508
509
							jQuery('#' + $short_code).on('change', 'select', function () {
510
								sd_build_shortcode($short_code);
511
							}); // take care of select tags
512
513
							jQuery('#' + $short_code).on('change keypress keyup', 'input', function () {
514
								sd_build_shortcode($short_code);
515
							});
516
517
							sd_build_shortcode($short_code);
518
519
							// resize the window to fit
520
							setTimeout(function () {
521
								jQuery('#TB_ajaxContent').css('width', 'auto').css('height', '75vh');
522
							}, 200);
523
524
525
							return response;
526
						});
527
					}
528
529
				}
530
531
				function sd_build_shortcode($id) {
532
533
					var multiSelects = {};
534
					var multiSelectsRemove = [];
535
536
					$output = "[" + $id;
537
538
					$form_data = jQuery("#" + $id).serializeArray();
539
540
					// run checks for multiselects
541
					jQuery.each($form_data, function (index, element) {
542
						if (element && element.value) {
543
							$field_name = element.name.substr(element.name.indexOf("][") + 2);
544
							$field_name = $field_name.replace("]", "");
545
							// check if its a multiple
546
							if ($field_name.includes("[]")) {
547
								multiSelectsRemove[multiSelectsRemove.length] = index;
548
								$field_name = $field_name.replace("[]", "");
549
								if ($field_name in multiSelects) {
550
									multiSelects[$field_name] = multiSelects[$field_name] + "," + element.value;
551
								} else {
552
									multiSelects[$field_name] = element.value;
553
								}
554
							}
555
						}
556
					});
557
558
					// fix multiselects if any are found
559
					if (multiSelectsRemove.length) {
560
561
						// remove all multiselects
562
						multiSelectsRemove.reverse();
563
						multiSelectsRemove.forEach(function (index) {
564
							$form_data.splice(index, 1);
565
						});
566
567
						$ms_arr = [];
568
						// add multiselets back
569
						jQuery.each(multiSelects, function (index, value) {
570
							$ms_arr[$ms_arr.length] = {"name": "[][" + index + "]", "value": value};
571
						});
572
						$form_data = $form_data.concat($ms_arr);
573
					}
574
575
576
					if ($form_data) {
577
						$form_data.forEach(function (element) {
578
579
							if (element.value) {
580
								$field_name = element.name.substr(element.name.indexOf("][") + 2);
581
								$field_name = $field_name.replace("]", "");
582
								$output = $output + " " + $field_name + '="' + element.value + '"';
583
							}
584
585
						});
586
					}
587
					$output = $output + "]";
588
					jQuery('#sd-shortcode-output').html($output);
589
				}
590
591
			</script>
592
593
			<?php
594
		}
595
596 View Code Duplication
		public function widget_css() {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
597
			ob_start();
598
			?>
599
			<style>
600
				.sd-advanced-setting {
601
					display: none;
602
				}
603
604
				.sd-advanced-setting.sd-adv-show {
605
					display: block;
606
				}
607
608
				.sd-argument.sd-require-hide,
609
				.sd-advanced-setting.sd-require-hide {
610
					display: none;
611
				}
612
613
				button.sd-advanced-button {
614
					margin-right: 3px !important;
615
					font-size: 20px !important;
616
				}
617
			</style>
618
			<?php
619
			$output = ob_get_clean();
620
621
			/*
622
			 * We only add the <script> tags for code highlighting, so we strip them from the output.
623
			 */
624
625
			return str_replace( array(
626
				'<style>',
627
				'</style>'
628
			), '', $output );
629
		}
630
631 View Code Duplication
		public function widget_js() {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
632
			ob_start();
633
			?>
634
			<script>
635
636
				/**
637
				 * Toggle advanced settings visibility.
638
				 */
639
				function sd_toggle_advanced($this) {
640
					var form = jQuery($this).parents('form,.form');
641
					form.find('.sd-advanced-setting').toggleClass('sd-adv-show');
642
					return false;// prevent form submit
643
				}
644
645
				/**
646
				 * Check a form to see what items shoudl be shown or hidden.
647
				 */
648
				function sd_show_hide(form) {
649
					console.log('show/hide');
650
					jQuery(form).find(".sd-argument").each(function () {
651
652
						var $element_require = jQuery(this).data('element_require');
653
654
						if ($element_require) {
655
656
							$element_require = $element_require.replace("&#039;", "'"); // replace single quotes
657
							$element_require = $element_require.replace("&quot;", '"'); // replace double quotes
658
659
							if (eval($element_require)) {
660
								jQuery(this).removeClass('sd-require-hide');
661
							} else {
662
								jQuery(this).addClass('sd-require-hide');
663
							}
664
						}
665
					});
666
				}
667
668
				/**
669
				 * Initialise widgets from the widgets screen.
670
				 */
671
				function sd_init_widgets($selector) {
672
					jQuery(".sd-show-advanced").each(function (index) {
673
						sd_init_widget(this, $selector);
674
					});
675
				}
676
677
				/**
678
				 * Initialise a individual widget.
679
				 */
680
				function sd_init_widget($this, $selector) {
681
					console.log($selector);
682
683
					if (!$selector) {
684
						$selector = 'form';
685
					}
686
					// only run once.
687
					if (jQuery($this).data('sd-widget-enabled')) {
688
						return;
689
					} else {
690
						jQuery($this).data('sd-widget-enabled', true);
691
					}
692
693
					var $button = '<button title="<?php _e( 'Advanced Settings' );?>" class="button button-primary right sd-advanced-button" onclick="sd_toggle_advanced(this);return false;"><i class="fas fa-sliders-h" aria-hidden="true"></i></button>';
694
					var form = jQuery($this).parents('' + $selector + '');
695
696
					if (jQuery($this).val() == '1' && jQuery(form).find('.sd-advanced-button').length == 0) {
697
						console.log('add advanced button');
698
699
						jQuery(form).find('.widget-control-save').after($button);
700
					} else {
701
						console.log('no advanced button');
702
						console.log(jQuery($this).val());
703
						console.log(jQuery(form).find('.sd-advanced-button').length);
704
705
					}
706
707
					// show hide on form change
708
					jQuery(form).change(function () {
709
						sd_show_hide(form);
710
					});
711
712
					// show hide on load
713
					sd_show_hide(form);
714
				}
715
716
				/**
717
				 * Init a customizer widget.
718
				 */
719
				function sd_init_customizer_widget(section) {
720
					if (section.expanded) {
721
						section.expanded.bind(function (isExpanding) {
722
							if (isExpanding) {
723
								// is it a SD widget?
724
								if (jQuery(section.container).find('.sd-show-advanced').length) {
725
									// init the widget
726
									sd_init_widget(jQuery(section.container).find('.sd-show-advanced'), ".form");
727
								}
728
							}
729
						});
730
					}
731
				}
732
733
				/**
734
				 * If on widgets screen.
735
				 */
736
				jQuery(function () {
737
					// if not in customizer.
738
					if (!wp.customize) {
739
						sd_init_widgets("form");
740
					}
741
742
					// init on widget added
743
					jQuery(document).on('widget-added', function (e, widget) {
744
						console.log('widget added');
745
						// is it a SD widget?
746
						if (jQuery(widget).find('.sd-show-advanced').length) {
747
							// init the widget
748
							sd_init_widget(jQuery(widget).find('.sd-show-advanced'), "form");
749
						}
750
					});
751
752
					// inint on widget updated
753
					jQuery(document).on('widget-updated', function (e, widget) {
754
						console.log('widget updated');
755
756
						// is it a SD widget?
757
						if (jQuery(widget).find('.sd-show-advanced').length) {
758
							// init the widget
759
							sd_init_widget(jQuery(widget).find('.sd-show-advanced'), "form");
760
						}
761
					});
762
763
				});
764
765
766
				/**
767
				 * We need to run this before jQuery is ready
768
				 */
769
				if (wp.customize) {
770
					wp.customize.bind('ready', function () {
771
772
						// init widgets on load
773
						wp.customize.control.each(function (section) {
774
							sd_init_customizer_widget(section);
775
						});
776
777
						// init widgets on add
778
						wp.customize.control.bind('add', function (section) {
779
							sd_init_customizer_widget(section);
780
						});
781
782
					});
783
784
				}
785
				<?php do_action( 'wp_super_duper_widget_js', $this ); ?>
786
			</script>
787
			<?php
788
			$output = ob_get_clean();
789
790
			/*
791
			 * We only add the <script> tags for code highlighting, so we strip them from the output.
792
			 */
793
794
			return str_replace( array(
795
				'<script>',
796
				'</script>'
797
			), '', $output );
798
		}
799
800
801
		/**
802
		 * Set the name from the argument key.
803
		 *
804
		 * @param $options
805
		 *
806
		 * @return mixed
807
		 */
808
		private function add_name_from_key( $options, $arguments = false ) {
809
			if ( ! empty( $options['arguments'] ) ) {
810
				foreach ( $options['arguments'] as $key => $val ) {
811
					$options['arguments'][ $key ]['name'] = $key;
812
				}
813
			} elseif ( $arguments && is_array( $options ) && ! empty( $options ) ) {
814
				foreach ( $options as $key => $val ) {
815
					$options[ $key ]['name'] = $key;
816
				}
817
			}
818
819
			return $options;
820
		}
821
822
		/**
823
		 * Register the parent shortcode.
824
		 *
825
		 * @since 1.0.0
826
		 */
827
		public function register_shortcode() {
828
			add_shortcode( $this->base_id, array( $this, 'shortcode_output' ) );
829
			add_action( 'wp_ajax_super_duper_output_shortcode', array( __CLASS__, 'render_shortcode' ) );
830
		}
831
832
		/**
833
		 * Render the shortcode via ajax so we can return it to Gutenberg.
834
		 *
835
		 * @since 1.0.0
836
		 */
837
		public static function render_shortcode() {
838
839
			check_ajax_referer( 'super_duper_output_shortcode', '_ajax_nonce', true );
840
			if ( ! current_user_can( 'manage_options' ) ) {
841
				wp_die();
842
			}
843
844
			// we might need the $post value here so lets set it.
845
			if ( isset( $_POST['post_id'] ) && $_POST['post_id'] ) {
846
				$post_obj = get_post( absint( $_POST['post_id'] ) );
847
				if ( ! empty( $post_obj ) && empty( $post ) ) {
0 ignored issues
show
Bug introduced by
The variable $post seems only to be defined at a later point. As such the call to empty() seems to always evaluate to true.

This check marks calls to isset(...) or empty(...) that are found before the variable itself is defined. These will always have the same result.

This is likely the result of code being shifted around. Consider removing these calls.

Loading history...
848
					global $post;
849
					$post = $post_obj;
850
				}
851
			}
852
853
			if ( isset( $_POST['shortcode'] ) && $_POST['shortcode'] ) {
854
				$shortcode_name   = sanitize_title_with_dashes( $_POST['shortcode'] );
855
				$attributes_array = isset( $_POST['attributes'] ) && $_POST['attributes'] ? $_POST['attributes'] : array();
856
				$attributes       = '';
857
				if ( ! empty( $attributes_array ) ) {
858
					foreach ( $attributes_array as $key => $value ) {
859
						$attributes .= " " . sanitize_title_with_dashes( $key ) . "='" . wp_slash( $value ) . "' ";
860
					}
861
				}
862
863
				$shortcode = "[" . $shortcode_name . " " . $attributes . "]";
864
865
				echo do_shortcode( $shortcode );
866
867
			}
868
			wp_die();
869
		}
870
871
		/**
872
		 * Output the shortcode.
873
		 *
874
		 * @param array $args
875
		 * @param string $content
876
		 *
877
		 * @return string
878
		 */
879
		public function shortcode_output( $args = array(), $content = '' ) {
880
			$args = self::argument_values( $args );
881
882
			// add extra argument so we know its a output to gutenberg
883
			//$args
884
			$args = $this->string_to_bool( $args );
885
886
887
			$calss = isset( $this->options['widget_ops']['classname'] ) ? esc_attr( $this->options['widget_ops']['classname'] ) : '';
888
889
			$calss = apply_filters( 'wp_super_duper_div_classname', $calss, $args, $this );
890
			$calss = apply_filters( 'wp_super_duper_div_classname_' . $this->base_id, $calss, $args, $this );
891
892
			$attrs = apply_filters( 'wp_super_duper_div_attrs', '', $args, $this );
0 ignored issues
show
Unused Code introduced by
$attrs is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
893
			$attrs = apply_filters( 'wp_super_duper_div_attrs_' . $this->base_id, '', $args, $this );
894
895
			$shortcode_args = array();
896
			$output         = '';
897
			$no_wrap        = isset( $this->options['no_wrap'] ) && $this->options['no_wrap'] ? true : false;
898
			$main_content   = $this->output( $args, $shortcode_args, $content );
0 ignored issues
show
Bug introduced by
Are you sure the assignment to $main_content is correct as $this->output($args, $shortcode_args, $content) (which targets WP_Super_Duper::output()) seems to always return null.

This check looks for function or method calls that always return null and whose return value is assigned to a variable.

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

}

$a = new A();
$object = $a->getObject();

The method getObject() can return nothing but null, so it makes no sense to assign that value to a variable.

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

Loading history...
899
			if ( $main_content && ! $no_wrap ) {
900
				// wrap the shortcode in a dive with the same class as the widget
901
				$output .= '<div class="' . $calss . '" ' . $attrs . '>';
902
				if ( ! empty( $args['title'] ) ) {
903
					// if its a shortcode and there is a title try to grab the title wrappers
904
					$shortcode_args = array( 'before_title' => '', 'after_title' => '' );
905
					if ( empty( $instance ) ) {
0 ignored issues
show
Bug introduced by
The variable $instance seems to never exist, and therefore empty should always return true. Did you maybe rename this variable?

This check looks for calls to isset(...) or empty() on variables that are yet undefined. These calls will always produce the same result and can be removed.

This is most likely caused by the renaming of a variable or the removal of a function/method parameter.

Loading history...
906
						global $wp_registered_sidebars;
907
						if ( ! empty( $wp_registered_sidebars ) ) {
908
							foreach ( $wp_registered_sidebars as $sidebar ) {
909
								if ( ! empty( $sidebar['before_title'] ) ) {
910
									$shortcode_args['before_title'] = $sidebar['before_title'];
911
									$shortcode_args['after_title']  = $sidebar['after_title'];
912
									break;
913
								}
914
							}
915
						}
916
					}
917
					$output .= $this->output_title( $shortcode_args, $args );
918
				}
919
				$output .= $main_content;
920
				$output .= '</div>';
921
			} elseif ( $main_content && $no_wrap ) {
922
				$output .= $main_content;
923
			}
924
925
			// if preview show a placeholder if empty
926 View Code Duplication
			if ( $this->is_preview() && $output == '' ) {
927
				$output = $this->preview_placeholder_text( "[{" . $this->base_id . "}]" );
928
			}
929
930
			return $output;
931
		}
932
933
		/**
934
		 * Placeholder text to show if output is empty and we are on a preview/builder page.
935
		 *
936
		 * @param string $name
937
		 *
938
		 * @return string
939
		 */
940
		public function preview_placeholder_text( $name = '' ) {
941
			return "<div style='background:#0185ba33;padding: 10px;border: 4px #ccc dashed;'>" . sprintf( __( 'Placeholder for: %s' ), $name ) . "</div>";
942
		}
943
944
		/**
945
		 * Sometimes booleans values can be turned to strings, so we fix that.
946
		 *
947
		 * @param $options
948
		 *
949
		 * @return mixed
950
		 */
951
		public function string_to_bool( $options ) {
952
			// convert bool strings to booleans
953
			foreach ( $options as $key => $val ) {
954
				if ( $val == 'false' ) {
955
					$options[ $key ] = false;
956
				} elseif ( $val == 'true' ) {
957
					$options[ $key ] = true;
958
				}
959
			}
960
961
			return $options;
962
		}
963
964
		/**
965
		 * Get the argument values that are also filterable.
966
		 *
967
		 * @param $instance
968
		 *
969
		 * @return array
970
		 */
971
		public function argument_values( $instance ) {
972
			$argument_values = array();
973
974
			// set widget instance
975
			$this->instance = $instance;
976
977
			if ( empty( $this->arguments ) ) {
978
				$this->arguments = $this->get_arguments();
979
			}
980
981
			if ( ! empty( $this->arguments ) ) {
982
				foreach ( $this->arguments as $key => $args ) {
983
					// set the input name from the key
984
					$args['name'] = $key;
985
					//
986
					$argument_values[ $key ] = isset( $instance[ $key ] ) ? $instance[ $key ] : '';
987
					if ( $argument_values[ $key ] == '' && isset( $args['default'] ) ) {
988
						$argument_values[ $key ] = $args['default'];
989
					}
990
				}
991
			}
992
993
			return $argument_values;
994
		}
995
996
		/**
997
		 * Set arguments in super duper.
998
		 *
999
		 * @since 1.0.0
1000
		 *
1001
		 * @return array Set arguments.
1002
		 */
1003
		public function set_arguments() {
1004
			return $this->arguments;
1005
		}
1006
1007
		/**
1008
		 * Get arguments in super duper.
1009
		 *
1010
		 * @since 1.0.0
1011
		 *
1012
		 * @return array Get arguments.
1013
		 */
1014
		public function get_arguments() {
1015
			if ( empty( $this->arguments ) ) {
1016
				$this->arguments = $this->set_arguments();
1017
			}
1018
1019
			$this->arguments = apply_filters( 'wp_super_duper_arguments', $this->arguments, $this->options, $this->instance );
1020
			$this->arguments = $this->add_name_from_key( $this->arguments, true );
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->add_name_from_key($this->arguments, true) of type * is incompatible with the declared type array of property $arguments.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
1021
1022
			return $this->arguments;
1023
		}
1024
1025
		/**
1026
		 * This is the main output class for all 3 items, widget, shortcode and block, it is extended in the calling class.
1027
		 *
1028
		 * @param array $args
1029
		 * @param array $widget_args
1030
		 * @param string $content
1031
		 */
1032
		public function output( $args = array(), $widget_args = array(), $content = '' ) {
1033
1034
		}
1035
1036
		/**
1037
		 * Add the dynamic block code inline when the wp-block in enqueued.
1038
		 */
1039
		public function register_block() {
1040
			wp_add_inline_script( 'wp-blocks', $this->block() );
1041
			if ( class_exists( 'SiteOrigin_Panels' ) ) {
1042
1043
				wp_add_inline_script( 'wp-blocks', $this->siteorigin_js() );
1044
1045
			}
1046
		}
1047
1048
		/**
1049
		 * Check if we need to show advanced options.
1050
		 *
1051
		 * @return bool
1052
		 */
1053
		public function block_show_advanced() {
1054
1055
			$show      = false;
1056
			$arguments = $this->arguments;
1057
1058
			if ( empty( $arguments ) ) {
1059
				$arguments = $this->get_arguments();
1060
			}
1061
1062
			if ( ! empty( $arguments ) ) {
1063
				foreach ( $arguments as $argument ) {
1064
					if ( isset( $argument['advanced'] ) && $argument['advanced'] ) {
1065
						$show = true;
1066
					}
1067
				}
1068
			}
1069
1070
			return $show;
1071
		}
1072
1073
1074
		/**
1075
		 * Output the JS for building the dynamic Guntenberg block.
1076
		 *
1077
		 * @since 1.0.4 Added block_wrap property which will set the block wrapping output element ie: div, span, p or empty for no wrap.
1078
		 * @return mixed
1079
		 */
1080
		public function block() {
1081
			ob_start();
1082
			?>
1083
			<script>
1084
				/**
1085
				 * BLOCK: Basic
1086
				 *
1087
				 * Registering a basic block with Gutenberg.
1088
				 * Simple block, renders and saves the same content without any interactivity.
1089
				 *
1090
				 * Styles:
1091
				 *        editor.css — Editor styles for the block.
1092
				 *        style.css  — Editor & Front end styles for the block.
1093
				 */
1094
				(function () {
1095
					var __ = wp.i18n.__; // The __() for internationalization.
1096
					var el = wp.element.createElement; // The wp.element.createElement() function to create elements.
1097
					var editable = wp.blocks.Editable;
1098
					var blocks = wp.blocks;
1099
					var registerBlockType = wp.blocks.registerBlockType; // The registerBlockType() to register blocks.
1100
					var is_fetching = false;
1101
					var prev_attributes = [];
1102
1103
					/**
1104
					 * Register Basic Block.
1105
					 *
1106
					 * Registers a new block provided a unique name and an object defining its
1107
					 * behavior. Once registered, the block is made available as an option to any
1108
					 * editor interface where blocks are implemented.
1109
					 *
1110
					 * @param  {string}   name     Block name.
1111
					 * @param  {Object}   settings Block settings.
1112
					 * @return {?WPBlock}          The block, if it has been successfully
1113
					 *                             registered; otherwise `undefined`.
1114
					 */
1115
					registerBlockType('<?php echo str_replace( "_", "-", sanitize_title_with_dashes( $this->options['textdomain'] ) . '/' . sanitize_title_with_dashes( $this->options['class_name'] ) );  ?>', { // Block name. Block names must be string that contains a namespace prefix. Example: my-plugin/my-custom-block.
1116
						title: '<?php echo $this->options['name'];?>', // Block title.
1117
						description: '<?php echo esc_attr( $this->options['widget_ops']['description'] )?>', // Block title.
1118
						icon: '<?php echo isset( $this->options['block-icon'] ) ? esc_attr( $this->options['block-icon'] ) : 'shield-alt';?>', // Block icon from Dashicons → https://developer.wordpress.org/resource/dashicons/.
1119
						category: '<?php echo isset( $this->options['block-category'] ) ? esc_attr( $this->options['block-category'] ) : 'common';?>', // Block category — Group blocks together based on common traits E.g. common, formatting, layout widgets, embed.
1120
						<?php if ( isset( $this->options['block-keywords'] ) ) {
1121
						echo "keywords : " . $this->options['block-keywords'] . ",";
1122
					}?>
1123
1124
						<?php
1125
1126
						$show_advanced = $this->block_show_advanced();
1127
1128
						$show_alignment = false;
1129
1130
						if ( ! empty( $this->arguments ) ) {
1131
							echo "attributes : {";
1132
1133
							if ( $show_advanced ) {
1134
								echo "show_advanced: {";
1135
								echo "	type: 'boolean',";
1136
								echo "  default: false,";
1137
								echo "},";
1138
							}
1139
1140
							// block wrap element
1141
							if ( isset( $this->options['block-wrap'] ) ) { //@todo we should validate this?
1142
								echo "block_wrap: {";
1143
								echo "	type: 'string',";
1144
								echo "  default: '" . esc_attr( $this->options['block-wrap'] ) . "',";
1145
								echo "},";
1146
							}
1147
1148
1149
							foreach ( $this->arguments as $key => $args ) {
1150
1151
								// set if we should show alignment
1152
								if ( $key == 'alignment' ) {
1153
									$show_alignment = true;
1154
								}
1155
1156
								$extra = '';
0 ignored issues
show
Unused Code introduced by
$extra is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
1157
1158
								if ( $args['type'] == 'checkbox' ) {
1159
									$type    = 'boolean';
1160
									$default = isset( $args['default'] ) && $args['default'] ? 'true' : 'false';
1161
								} elseif ( $args['type'] == 'number' ) {
1162
									$type    = 'number';
1163
									$default = isset( $args['default'] ) ? "'" . $args['default'] . "'" : "''";
1164
								} elseif ( $args['type'] == 'select' && ! empty( $args['multiple'] ) ) {
1165
									$type = 'array';
1166
									if ( is_array( $args['default'] ) ) {
1167
										$default = isset( $args['default'] ) ? "['" . implode( "','", $args['default'] ) . "']" : "[]";
1168 View Code Duplication
									} else {
1169
										$default = isset( $args['default'] ) ? "'" . $args['default'] . "'" : "''";
1170
									}
1171
								} elseif ( $args['type'] == 'multiselect' ) {
1172
									$type    = 'array';
1173
									$default = isset( $args['default'] ) ? "'" . $args['default'] . "'" : "''";
1174 View Code Duplication
								} else {
1175
									$type    = 'string';
1176
									$default = isset( $args['default'] ) ? "'" . $args['default'] . "'" : "''";
1177
								}
1178
								echo $key . " : {";
1179
								echo "type : '$type',";
1180
								echo "default : $default,";
1181
								echo "},";
1182
							}
1183
1184
							echo "content : {type : 'string',default: 'Please select the attributes in the block settings'},";
1185
1186
							echo "},";
1187
1188
						}
1189
1190
						?>
1191
1192
						// The "edit" property must be a valid function.
1193
						edit: function (props) {
1194
1195
							var content = props.attributes.content;
1196
1197
							function onChangeContent() {
1198
1199
								if (!is_fetching && prev_attributes[props.id] != props.attributes) {
1200
1201
									//console.log(props);
1202
1203
									is_fetching = true;
1204
									var data = {
1205
										'action': 'super_duper_output_shortcode',
1206
										'shortcode': '<?php echo $this->options['base_id'];?>',
1207
										'attributes': props.attributes,
1208
										'post_id': <?php global $post; if ( isset( $post->ID ) ) {
1209
										echo $post->ID;
1210
									}?>,
1211
										'_ajax_nonce': '<?php echo wp_create_nonce( 'super_duper_output_shortcode' );?>'
1212
									};
1213
1214
									jQuery.post(ajaxurl, data, function (response) {
1215
										return response;
1216
									}).then(function (env) {
1217
1218
										// if the content is empty then we place some placeholder text
1219
										if (env == '') {
1220
											env = "<div style='background:#0185ba33;padding: 10px;border: 4px #ccc dashed;'>" + "<?php _e( 'Placeholder for: ' );?>" + props.name + "</div>";
1221
										}
1222
1223
										props.setAttributes({content: env});
1224
										is_fetching = false;
1225
										prev_attributes[props.id] = props.attributes;
1226
									});
1227
1228
1229
								}
1230
1231
								return props.attributes.content;
1232
1233
							}
1234
1235
							return [
1236
1237
								el(wp.editor.BlockControls, {key: 'controls'},
1238
1239
									<?php if($show_alignment){?>
1240
									el(
1241
										wp.editor.AlignmentToolbar,
1242
										{
1243
											value: props.attributes.alignment,
1244
											onChange: function (alignment) {
1245
												props.setAttributes({alignment: alignment})
1246
											}
1247
										}
1248
									)
1249
									<?php }?>
1250
1251
								),
1252
1253
								el(wp.editor.InspectorControls, {key: 'inspector'},
1254
1255
									<?php
1256
1257
									if(! empty( $this->arguments )){
1258
1259
									if ( $show_advanced ) {
1260
									?>
1261
									el(
1262
										wp.components.ToggleControl,
1263
										{
1264
											label: 'Show Advanced Settings?',
1265
											checked: props.attributes.show_advanced,
1266
											onChange: function (show_advanced) {
1267
												props.setAttributes({show_advanced: !props.attributes.show_advanced})
1268
											}
1269
										}
1270
									),
1271
									<?php
1272
1273
									}
1274
1275
									foreach($this->arguments as $key => $args){
1276
									$custom_attributes = ! empty( $args['custom_attributes'] ) ? $this->array_to_attributes( $args['custom_attributes'] ) : '';
1277
									$options = '';
1278
									$extra = '';
1279
									$require = '';
0 ignored issues
show
Unused Code introduced by
$require is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
1280
									$onchange = "props.setAttributes({ $key: $key } )";
1281
									$value = "props.attributes.$key";
1282
									$text_type = array( 'text', 'password', 'number', 'email', 'tel', 'url', 'color' );
1283
									if ( in_array( $args['type'], $text_type ) ) {
1284
										$type = 'TextControl';
1285
									} elseif ( $args['type'] == 'checkbox' ) {
1286
										$type = 'CheckboxControl';
1287
										$extra .= "checked: props.attributes.$key,";
1288
										$onchange = "props.setAttributes({ $key: ! props.attributes.$key } )";
1289
									} elseif ( $args['type'] == 'select' || $args['type'] == 'multiselect' ) {
1290
										$type = 'SelectControl';
1291
										if ( ! empty( $args['options'] ) ) {
1292
											$options .= "options  : [";
1293
											foreach ( $args['options'] as $option_val => $option_label ) {
1294
												$options .= "{ value : '" . esc_attr( $option_val ) . "',     label : '" . esc_attr( $option_label ) . "'     },";
1295
											}
1296
											$options .= "],";
1297
										}
1298
										if ( isset( $args['multiple'] ) && $args['multiple'] ) { //@todo multiselect does not work at the moment: https://github.com/WordPress/gutenberg/issues/5550
1299
											$extra .= ' multiple: true, ';
1300
											//$onchange = "props.setAttributes({ $key: ['edit'] } )";
1301
											//$value = "['edit', 'delete']";
1302
										}
1303
									} elseif ( $args['type'] == 'alignment' ) {
1304
										$type = 'AlignmentToolbar'; // @todo this does not seem to work but cant find a example
1305
									} else {
1306
										continue;// if we have not implemented the control then don't break the JS.
1307
									}
1308
1309
									// add show only if advanced
1310
									if ( ! empty( $args['advanced'] ) ) {
1311
										echo "props.attributes.show_advanced && ";
1312
									}
1313
									// add setting require if defined
1314
									if ( ! empty( $args['element_require'] ) ) {
1315
										echo $this->block_props_replace( $args['element_require'], true ) . " && ";
1316
									}
1317
									?>
1318
									el(
1319
										wp.components.<?php echo esc_attr( $type );?>,
1320
										{
1321
											label: '<?php echo esc_attr( $args['title'] );?>',
1322
											help: '<?php if ( isset( $args['desc'] ) ) {
1323
												echo esc_attr( $args['desc'] );
1324
											}?>',
1325
											value: <?php echo $value;?>,
1326
											<?php if ( $type == 'TextControl' && $args['type'] != 'text' ) {
1327
											echo "type: '" . esc_attr( $args['type'] ) . "',";
1328
										}?>
1329
											<?php if ( ! empty( $args['placeholder'] ) ) {
1330
											echo "placeholder: '" . esc_attr( $args['placeholder'] ) . "',";
1331
										}?>
1332
											<?php echo $options;?>
1333
											<?php echo $extra;?>
1334
											<?php echo $custom_attributes;?>
1335
											onChange: function ( <?php echo $key;?> ) {
1336
												<?php echo $onchange;?>
1337
											}
1338
										}
1339
									),
1340
									<?php
1341
									}
1342
									}
1343
									?>
1344
1345
								),
1346
1347
								<?php
1348
								// If the user sets block-output array then build it
1349
								if ( ! empty( $this->options['block-output'] ) ) {
1350
								$this->block_element( $this->options['block-output'] );
1351
							}else{
1352
								// if no block-output is set then we try and get the shortcode html output via ajax.
1353
								?>
1354
								el('div', {
1355
									dangerouslySetInnerHTML: {__html: onChangeContent()},
1356
									className: props.className,
1357
									style: {'min-height': '30px'}
1358
								})
1359
								<?php
1360
								}
1361
								?>
1362
							]; // end return
1363
						},
1364
1365
						// The "save" property must be specified and must be a valid function.
1366
						save: function (props) {
1367
1368
							//console.log(props);
1369
1370
1371
							var attr = props.attributes;
1372
							var align = '';
1373
1374
							// build the shortcode.
1375
							var content = "[<?php echo $this->options['base_id'];?>";
1376
							<?php
1377
1378
							if(! empty( $this->arguments )){
1379
							foreach($this->arguments as $key => $args){
1380
							?>
1381
							if (attr.hasOwnProperty("<?php echo esc_attr( $key );?>")) {
1382
								content += " <?php echo esc_attr( $key );?>='" + attr.<?php echo esc_attr( $key );?>+ "' ";
1383
							}
1384
							<?php
1385
							}
1386
							}
1387
1388
							?>
1389
							content += "]";
1390
1391
1392
							// @todo should we add inline style here or just css classes?
1393
							if (attr.alignment) {
1394
								if (attr.alignment == 'left') {
1395
									align = 'alignleft';
1396
								}
1397
								if (attr.alignment == 'center') {
1398
									align = 'aligncenter';
1399
								}
1400
								if (attr.alignment == 'right') {
1401
									align = 'alignright';
1402
								}
1403
							}
1404
1405
							//console.log(content);
1406
							var block_wrap = 'div';
1407
							if (attr.hasOwnProperty("block_wrap")) {
1408
								block_wrap = attr.block_wrap;
1409
							}
1410
							return el(block_wrap, {dangerouslySetInnerHTML: {__html: content}, className: align});
1411
1412
						}
1413
					});
1414
				})();
1415
			</script>
1416
			<?php
1417
			$output = ob_get_clean();
1418
1419
			/*
1420
			 * We only add the <script> tags for code highlighting, so we strip them from the output.
1421
			 */
1422
1423
			return str_replace( array(
1424
				'<script>',
1425
				'</script>'
1426
			), '', $output );
1427
		}
1428
1429
		/**
1430
		 * Convert an array of attributes to block string.
1431
		 *
1432
		 * @todo there is prob a faster way to do this, also we could add some validation here.
1433
		 *
1434
		 * @param $custom_attributes
1435
		 *
1436
		 * @return string
1437
		 */
1438
		public function array_to_attributes( $custom_attributes, $html = false ) {
1439
			$attributes = '';
1440
			if ( ! empty( $custom_attributes ) ) {
1441
1442
				if ( $html ) {
1443
					foreach ( $custom_attributes as $key => $val ) {
1444
						$attributes .= " $key='$val' ";
1445
					}
1446
				} else {
1447
					foreach ( $custom_attributes as $key => $val ) {
1448
						$attributes .= "'$key': '$val',";
1449
					}
1450
				}
1451
			}
1452
1453
			return $attributes;
1454
		}
1455
1456
		/**
1457
		 * A self looping function to create the output for JS block elements.
1458
		 *
1459
		 * This is what is output in the WP Editor visual view.
1460
		 *
1461
		 * @param $args
1462
		 */
1463
		public function block_element( $args ) {
1464
1465
1466
			if ( ! empty( $args ) ) {
1467
				foreach ( $args as $element => $new_args ) {
1468
1469
					if ( is_array( $new_args ) ) { // its an element
1470
1471
1472
						if ( isset( $new_args['element'] ) ) {
1473
1474 View Code Duplication
							if ( isset( $new_args['element_require'] ) ) {
1475
								echo str_replace( array(
1476
										"'+",
1477
										"+'"
1478
									), '', $this->block_props_replace( $new_args['element_require'] ) ) . " &&  ";
1479
								unset( $new_args['element_require'] );
1480
							}
1481
1482
							echo "\n el( '" . $new_args['element'] . "', {";
1483
1484
							// get the attributes
1485
							foreach ( $new_args as $new_key => $new_value ) {
1486
1487
1488
								if ( $new_key == 'element' || $new_key == 'content' || $new_key == 'element_require' || $new_key == 'element_repeat' || is_array( $new_value ) ) {
1489
									// do nothing
1490
								} else {
1491
									echo $this->block_element( array( $new_key => $new_value ) );
1492
								}
1493
							}
1494
1495
							echo "},";// end attributes
1496
1497
							// get the content
1498
							$first_item = 0;
1499
							foreach ( $new_args as $new_key => $new_value ) {
1500
								if ( $new_key === 'content' || is_array( $new_value ) ) {
1501
1502
									if ( $new_key === 'content' ) {
1503
										echo "'" . $this->block_props_replace( $new_value ) . "'";
1504
									}
1505
1506
									if ( is_array( $new_value ) ) {
1507
1508 View Code Duplication
										if ( isset( $new_value['element_require'] ) ) {
1509
											echo str_replace( array(
1510
													"'+",
1511
													"+'"
1512
												), '', $this->block_props_replace( $new_value['element_require'] ) ) . " &&  ";
1513
											unset( $new_value['element_require'] );
1514
										}
1515
1516
										if ( isset( $new_value['element_repeat'] ) ) {
1517
											$x = 1;
1518
											while ( $x <= absint( $new_value['element_repeat'] ) ) {
1519
												$this->block_element( array( '' => $new_value ) );
1520
												$x ++;
1521
											}
1522
										} else {
1523
											$this->block_element( array( '' => $new_value ) );
1524
										}
1525
									}
1526
									$first_item ++;
1527
								}
1528
							}
1529
1530
							echo ")";// end content
1531
1532
							echo ", \n";
1533
1534
						}
1535
					} else {
1536
1537
						if ( substr( $element, 0, 3 ) === "if_" ) {
1538
							echo str_replace( "if_", "", $element ) . ": " . $this->block_props_replace( $new_args, true ) . ",";
1539
						} elseif ( $element == 'style' ) {
1540
							echo $element . ": " . $this->block_props_replace( $new_args ) . ",";
1541
						} else {
1542
							echo $element . ": '" . $this->block_props_replace( $new_args ) . "',";
1543
						}
1544
1545
					}
1546
				}
1547
			}
1548
		}
1549
1550
		/**
1551
		 * Replace block attributes placeholders with the proper naming.
1552
		 *
1553
		 * @param $string
1554
		 *
1555
		 * @return mixed
1556
		 */
1557
		public function block_props_replace( $string, $no_wrap = false ) {
1558
1559
			if ( $no_wrap ) {
1560
				$string = str_replace( array( "[%", "%]" ), array( "props.attributes.", "" ), $string );
1561
			} else {
1562
				$string = str_replace( array( "[%", "%]" ), array( "'+props.attributes.", "+'" ), $string );
1563
			}
1564
1565
			return $string;
1566
		}
1567
1568
		/**
1569
		 * Outputs the content of the widget
1570
		 *
1571
		 * @param array $args
1572
		 * @param array $instance
1573
		 */
1574
		public function widget( $args, $instance ) {
1575
1576
			// get the filtered values
1577
			$argument_values = $this->argument_values( $instance );
1578
			$argument_values = $this->string_to_bool( $argument_values );
1579
			$output          = $this->output( $argument_values, $args );
0 ignored issues
show
Bug introduced by
Are you sure the assignment to $output is correct as $this->output($argument_values, $args) (which targets WP_Super_Duper::output()) seems to always return null.

This check looks for function or method calls that always return null and whose return value is assigned to a variable.

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

}

$a = new A();
$object = $a->getObject();

The method getObject() can return nothing but null, so it makes no sense to assign that value to a variable.

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

Loading history...
1580
1581
			if ( $output ) {
1582
				// Before widget
1583
				$before_widget = $args['before_widget'];
1584
				$before_widget = apply_filters( 'wp_super_duper_before_widget', $before_widget, $args, $instance, $this );
1585
				$before_widget = apply_filters( 'wp_super_duper_before_widget_' . $this->base_id, $before_widget, $args, $instance, $this );
1586
1587
				// After widget
1588
				$after_widget = $args['after_widget'];
1589
				$after_widget = apply_filters( 'wp_super_duper_after_widget', $after_widget, $args, $instance, $this );
1590
				$after_widget = apply_filters( 'wp_super_duper_after_widget_' . $this->base_id, $after_widget, $args, $instance, $this );
1591
1592
				echo $before_widget;
1593
				// elementor strips the widget wrapping div so we check for and add it back if needed
1594
				if ( $this->is_elementor_widget_output() ) {
1595
					echo ! empty( $this->options['widget_ops']['classname'] ) ? "<span class='" . esc_attr( $this->options['widget_ops']['classname'] ) . "'>" : '';
1596
				}
1597
				echo $this->output_title( $args, $instance );
1598
				echo $output;
1599
				if ( $this->is_elementor_widget_output() ) {
1600
					echo ! empty( $this->options['widget_ops']['classname'] ) ? "</span>" : '';
1601
				}
1602
				echo $after_widget;
1603 View Code Duplication
			} elseif ( $this->is_preview() && $output == '' ) {// if preview show a placeholder if empty
1604
				$output = $this->preview_placeholder_text( "{{" . $this->base_id . "}}" );
1605
				echo $output;
1606
			}
1607
		}
1608
1609
		/**
1610
		 * Tests if the current output is inside a elementor container.
1611
		 *
1612
		 * @since 1.0.4
1613
		 * @return bool
1614
		 */
1615
		public function is_elementor_widget_output() {
1616
			$result = false;
1617
			if ( defined( 'ELEMENTOR_VERSION' ) && isset( $this->number ) && $this->number == 'REPLACE_TO_ID' ) {
1618
				$result = true;
1619
			}
1620
1621
			return $result;
1622
		}
1623
1624
		/**
1625
		 * Tests if the current output is inside a elementor preview.
1626
		 *
1627
		 * @since 1.0.4
1628
		 * @return bool
1629
		 */
1630
		public function is_elementor_preview() {
1631
			$result = false;
1632
			if ( isset( $_REQUEST['elementor-preview'] ) || ( is_admin() && isset( $_REQUEST['action'] ) && $_REQUEST['action'] == 'elementor' ) ) {
1633
				$result = true;
1634
			}
1635
1636
			return $result;
1637
		}
1638
1639
		/**
1640
		 * Tests if the current output is inside a Divi preview.
1641
		 *
1642
		 * @since 1.0.6
1643
		 * @return bool
1644
		 */
1645
		public function is_divi_preview() {
1646
			$result = false;
1647
			if ( isset( $_REQUEST['et_fb'] ) || isset( $_REQUEST['et_pb_preview'] ) || ( is_admin() && isset( $_REQUEST['action'] ) && $_REQUEST['action'] == 'elementor' ) ) {
1648
				$result = true;
1649
			}
1650
1651
			return $result;
1652
		}
1653
1654
		/**
1655
		 * Tests if the current output is inside a Beaver builder preview.
1656
		 *
1657
		 * @since 1.0.6
1658
		 * @return bool
1659
		 */
1660
		public function is_beaver_preview() {
1661
			$result = false;
1662
			if ( isset( $_REQUEST['fl_builder'] ) ) {
1663
				$result = true;
1664
			}
1665
1666
			return $result;
1667
		}
1668
1669
		/**
1670
		 * Tests if the current output is inside a siteorigin builder preview.
1671
		 *
1672
		 * @since 1.0.6
1673
		 * @return bool
1674
		 */
1675
		public function is_siteorigin_preview() {
1676
			$result = false;
1677
			if ( !empty( $_REQUEST['siteorigin_panels_live_editor'] )) {
1678
				$result = true;
1679
			}
1680
1681
			return $result;
1682
		}
1683
1684
		/**
1685
		 * General function to check if we are in a preview situation.
1686
		 *
1687
		 * @since 1.0.6
1688
		 * @return bool
1689
		 */
1690
		public function is_preview() {
1691
			$preview = false;
1692
			if ( $this->is_divi_preview() ) {
1693
				$preview = true;
1694
			} elseif ( $this->is_elementor_preview() ) {
1695
				$preview = true;
1696
			} elseif ( $this->is_beaver_preview() ) {
1697
				$preview = true;
1698
			} elseif ( $this->is_siteorigin_preview() ) {
1699
				$preview = true;
1700
			}
1701
1702
			return $preview;
1703
		}
1704
1705
		/**
1706
		 * Output the super title.
1707
		 *
1708
		 * @param $args
1709
		 * @param array $instance
1710
		 *
1711
		 * @return string
1712
		 */
1713
		public function output_title( $args, $instance = array() ) {
1714
			$output = '';
1715
			if ( ! empty( $instance['title'] ) ) {
1716
				/** This filter is documented in wp-includes/widgets/class-wp-widget-pages.php */
1717
				$title  = apply_filters( 'widget_title', $instance['title'], $instance, $this->id_base );
1718
				$output = $args['before_title'] . $title . $args['after_title'];
1719
			}
1720
1721
			return $output;
1722
		}
1723
1724
		/**
1725
		 * Outputs the options form inputs for the widget.
1726
		 *
1727
		 * @param array $instance The widget options.
1728
		 */
1729
		public function form( $instance ) {
1730
1731
			// set widget instance
1732
			$this->instance = $instance;
1733
1734
			// set it as a SD widget
1735
			echo $this->widget_advanced_toggle();
1736
1737
			echo "<p>" . esc_attr( $this->options['widget_ops']['description'] ) . "</p>";
1738
			$arguments = $this->get_arguments();
1739
1740
			if ( is_array( $arguments ) ) {
1741
				foreach ( $arguments as $key => $args ) {
1742
					$this->widget_inputs( $args, $instance );
1743
				}
1744
			}
1745
		}
1746
1747
		/**
1748
		 * Get the hidden input that when added makes the advanced button show on widget settings.
1749
		 *
1750
		 * @return string
1751
		 */
1752
		public function widget_advanced_toggle() {
1753
1754
			$output = '';
1755
			if ( $this->block_show_advanced() ) {
1756
				$val = 1;
1757
			} else {
1758
				$val = 0;
1759
			}
1760
1761
			$output .= "<input type='hidden'  class='sd-show-advanced' value='$val' />";
1762
1763
			return $output;
1764
		}
1765
1766
		/**
1767
		 * Convert require element.
1768
		 *
1769
		 * @since 1.0.0
1770
		 *
1771
		 * @param string $input Input element.
1772
		 *
1773
		 * @return string $output
1774
		 */
1775
		public function convert_element_require( $input ) {
1776
1777
			$input = str_replace( "'", '"', $input );// we only want double quotes
1778
1779
			$output = esc_attr( str_replace( array( "[%", "%]" ), array(
1780
				"jQuery(form).find('[data-argument=\"",
1781
				"\"]').find('input,select').val()"
1782
			), $input ) );
1783
1784
			return $output;
1785
		}
1786
1787
		/**
1788
		 * Builds the inputs for the widget options.
1789
		 *
1790
		 * @param $args
1791
		 * @param $instance
1792
		 */
1793
		public function widget_inputs( $args, $instance ) {
1794
1795
			$class             = "";
1796
			$element_require   = "";
1797
			$custom_attributes = "";
1798
1799
			// get value
1800
			if ( isset( $instance[ $args['name'] ] ) ) {
1801
				$value = $instance[ $args['name'] ];
1802
			} elseif ( ! isset( $instance[ $args['name'] ] ) && ! empty( $args['default'] ) ) {
1803
				$value = is_array( $args['default'] ) ? array_map( "esc_html", $args['default'] ) : esc_html( $args['default'] );
1804
			} else {
1805
				$value = '';
1806
			}
1807
1808
			// get placeholder
1809 View Code Duplication
			if ( ! empty( $args['placeholder'] ) ) {
1810
				$placeholder = "placeholder='" . esc_html( $args['placeholder'] ) . "'";
1811
			} else {
1812
				$placeholder = '';
1813
			}
1814
1815
			// get if advanced
1816
			if ( isset( $args['advanced'] ) && $args['advanced'] ) {
1817
				$class .= " sd-advanced-setting ";
1818
			}
1819
1820
			// element_require
1821
			if ( isset( $args['element_require'] ) && $args['element_require'] ) {
1822
				$element_require = $args['element_require'];
1823
			}
1824
1825
			// custom_attributes
1826
			if ( isset( $args['custom_attributes'] ) && $args['custom_attributes'] ) {
1827
				$custom_attributes = $this->array_to_attributes( $args['custom_attributes'], true );
1828
			}
1829
1830
			// before wrapper
1831
			?>
1832
			<p class="sd-argument <?php echo esc_attr( $class ); ?>"
1833
			   data-argument='<?php echo esc_attr( $args['name'] ); ?>'
1834
			   data-element_require='<?php if ( $element_require ) {
1835
				   echo $this->convert_element_require( $element_require );
1836
			   } ?>'
1837
			>
1838
				<?php
1839
1840
				switch ( $args['type'] ) {
1841
					//array('text','password','number','email','tel','url','color')
1842
					case "text":
1843
					case "password":
1844
					case "number":
1845
					case "email":
1846
					case "tel":
1847
					case "url":
1848 View Code Duplication
					case "color":
1849
						?>
1850
						<label
1851
							for="<?php echo esc_attr( $this->get_field_id( $args['name'] ) ); ?>"><?php echo esc_attr( $args['title'] ); ?><?php echo $this->widget_field_desc( $args ); ?></label>
1852
						<input <?php echo $placeholder; ?> class="widefat"
1853
							<?php echo $custom_attributes; ?>
1854
							                               id="<?php echo esc_attr( $this->get_field_id( $args['name'] ) ); ?>"
1855
							                               name="<?php echo esc_attr( $this->get_field_name( $args['name'] ) ); ?>"
1856
							                               type="<?php echo esc_attr( $args['type'] ); ?>"
1857
							                               value="<?php echo esc_attr( $value ); ?>">
1858
						<?php
1859
1860
						break;
1861
					case "select":
1862
						$multiple = isset( $args['multiple'] ) && $args['multiple'] ? true : false;
1863
						if ( $multiple ) {
1864
							if ( empty( $value ) ) {
1865
								$value = array();
1866
							}
1867
						}
1868
						?>
1869
						<label
1870
							for="<?php echo esc_attr( $this->get_field_id( $args['name'] ) ); ?>"><?php echo esc_attr( $args['title'] ); ?><?php echo $this->widget_field_desc( $args ); ?></label>
1871
						<select <?php echo $placeholder; ?> class="widefat"
1872
							<?php echo $custom_attributes; ?>
1873
							                                id="<?php echo esc_attr( $this->get_field_id( $args['name'] ) ); ?>"
1874
							                                name="<?php echo esc_attr( $this->get_field_name( $args['name'] ) );
1875
							                                if ( $multiple ) {
1876
								                                echo "[]";
1877
							                                } ?>"
1878
							<?php if ( $multiple ) {
1879
								echo "multiple";
1880
							} //@todo not implemented yet due to gutenberg not supporting it
1881
							?>
1882
						>
1883
							<?php
1884
1885
							if ( ! empty( $args['options'] ) ) {
1886
								foreach ( $args['options'] as $val => $label ) {
1887
									if ( $multiple ) {
1888
										$selected = in_array( $val, $value ) ? 'selected="selected"' : '';
1889
									} else {
1890
										$selected = selected( $value, $val, false );
1891
									}
1892
									echo "<option value='$val' " . $selected . ">$label</option>";
1893
								}
1894
							}
1895
							?>
1896
						</select>
1897
						<?php
1898
						break;
1899 View Code Duplication
					case "checkbox":
1900
						?>
1901
						<input <?php echo $placeholder; ?>
1902
							<?php checked( 1, $value, true ) ?>
1903
							<?php echo $custom_attributes; ?>
1904
							class="widefat" id="<?php echo esc_attr( $this->get_field_id( $args['name'] ) ); ?>"
1905
							name="<?php echo esc_attr( $this->get_field_name( $args['name'] ) ); ?>" type="checkbox"
1906
							value="1">
1907
						<label
1908
							for="<?php echo esc_attr( $this->get_field_id( $args['name'] ) ); ?>"><?php echo esc_attr( $args['title'] ); ?><?php echo $this->widget_field_desc( $args ); ?></label>
1909
						<?php
1910
						break;
1911
					case "hidden":
1912
						?>
1913
						<input id="<?php echo esc_attr( $this->get_field_id( $args['name'] ) ); ?>"
1914
						       name="<?php echo esc_attr( $this->get_field_name( $args['name'] ) ); ?>" type="hidden"
1915
						       value="<?php echo esc_attr( $value ); ?>">
1916
						<?php
1917
						break;
1918
					default:
1919
						echo "No input type found!"; // @todo we need to add more input types.
1920
				}
1921
1922
				// after wrapper
1923
				?>
1924
			</p>
1925
			<?php
1926
1927
		}
1928
1929
		/**
1930
		 * Get the widget input description html.
1931
		 *
1932
		 * @param $args
1933
		 *
1934
		 * @return string
1935
		 * @todo, need to make its own tooltip script
1936
		 */
1937
		public function widget_field_desc( $args ) {
1938
1939
			$description = '';
1940
			if ( isset( $args['desc'] ) && $args['desc'] ) {
1941
				if ( isset( $args['desc_tip'] ) && $args['desc_tip'] ) {
1942
					$description = $this->desc_tip( $args['desc'] );
1943
				} else {
1944
					$description = '<span class="description">' . wp_kses_post( $args['desc'] ) . '</span>';
1945
				}
1946
			}
1947
1948
			return $description;
1949
		}
1950
1951
		/**
1952
		 * Get the tool tip html.
1953
		 *
1954
		 * @param $tip
1955
		 * @param bool $allow_html
1956
		 *
1957
		 * @return string
1958
		 */
1959
		function desc_tip( $tip, $allow_html = false ) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
1960
			if ( $allow_html ) {
1961
				$tip = $this->sanitize_tooltip( $tip );
1962
			} else {
1963
				$tip = esc_attr( $tip );
1964
			}
1965
1966
			return '<span class="gd-help-tip dashicons dashicons-editor-help" title="' . $tip . '"></span>';
1967
		}
1968
1969
		/**
1970
		 * Sanitize a string destined to be a tooltip.
1971
		 *
1972
		 * @param string $var
1973
		 *
1974
		 * @return string
1975
		 */
1976
		public function sanitize_tooltip( $var ) {
1977
			return htmlspecialchars( wp_kses( html_entity_decode( $var ), array(
1978
				'br'     => array(),
1979
				'em'     => array(),
1980
				'strong' => array(),
1981
				'small'  => array(),
1982
				'span'   => array(),
1983
				'ul'     => array(),
1984
				'li'     => array(),
1985
				'ol'     => array(),
1986
				'p'      => array(),
1987
			) ) );
1988
		}
1989
1990
		/**
1991
		 * Processing widget options on save
1992
		 *
1993
		 * @param array $new_instance The new options
1994
		 * @param array $old_instance The previous options
1995
		 *
1996
		 * @return array
1997
		 * @todo we should add some sanitation here.
1998
		 */
1999
		public function update( $new_instance, $old_instance ) {
2000
2001
			//save the widget
2002
			$instance = array_merge( (array) $old_instance, (array) $new_instance );
2003
2004
			// set widget instance
2005
			$this->instance = $instance;
2006
2007
			if ( empty( $this->arguments ) ) {
2008
				$this->get_arguments();
2009
			}
2010
2011
			// check for checkboxes
2012
			if ( ! empty( $this->arguments ) ) {
2013
				foreach ( $this->arguments as $argument ) {
2014
					if ( isset( $argument['type'] ) && $argument['type'] == 'checkbox' && ! isset( $new_instance[ $argument['name'] ] ) ) {
2015
						$instance[ $argument['name'] ] = '0';
2016
					}
2017
				}
2018
			}
2019
2020
			return $instance;
2021
		}
2022
2023
		/**
2024
		 * Checks if the current call is a ajax call to get the block content.
2025
		 *
2026
		 * This can be used in your widget to return different content as the block content.
2027
		 *
2028
		 * @since 1.0.3
2029
		 * @return bool
2030
		 */
2031
		public function is_block_content_call() {
2032
			$result = false;
2033
			if ( wp_doing_ajax() && isset( $_REQUEST['action'] ) && $_REQUEST['action'] == 'super_duper_output_shortcode' ) {
2034
				$result = true;
2035
			}
2036
2037
			return $result;
2038
		}
2039
2040
	}
2041
2042
}