Passed
Pull Request — master (#191)
by
unknown
02:57
created

WP_Super_Duper::shortcode_insert_button()   C

Complexity

Conditions 11
Paths 65

Size

Total Lines 69

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 11
nc 65
nop 2
dl 0
loc 69
rs 6.5296
c 0
b 0
f 0

How to fix   Long Method    Complexity   

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
	 * @since 1.0.7 Some refactoring for page builders - CHANGED
22
	 * @since 1.0.8 Some refactoring for page builders ( cornerstone builder now supported ) - CHANGED
23
	 * @ver 1.0.8
24
	 */
25
	class WP_Super_Duper extends WP_Widget {
26
27
		public $version = "1.0.8";
28
		public $block_code;
29
		public $options;
30
		public $base_id;
31
		public $arguments = array();
32
		public $instance = array();
33
		private $class_name;
34
35
		/**
36
		 * Take the array options and use them to build.
37
		 */
38
		public function __construct( $options ) {
39
			global $sd_widgets;
40
41
			$sd_widgets[ $options['base_id'] ] = array(
42
				'name'       => $options['name'],
43
				'class_name' => $options['class_name']
44
			);
45
			$this->base_id                     = $options['base_id'];
46
			// lets filter the options before we do anything
47
			$options       = apply_filters( "wp_super_duper_options", $options );
48
			$options       = apply_filters( "wp_super_duper_options_{$this->base_id}", $options );
49
			$options       = $this->add_name_from_key( $options );
50
			$this->options = $options;
51
52
			$this->base_id   = $options['base_id'];
53
			$this->arguments = isset( $options['arguments'] ) ? $options['arguments'] : array();
54
55
			// init parent
56
			parent::__construct( $options['base_id'], $options['name'], $options['widget_ops'] );
57
58
			if ( isset( $options['class_name'] ) ) {
59
				// register widget
60
				$this->class_name = $options['class_name'];
61
62
				// register shortcode
63
				$this->register_shortcode();
64
65
				// register block
66
				add_action( 'admin_enqueue_scripts', array( $this, 'register_block' ) );
67
			}
68
69
			// add the CSS and JS we need ONCE
70
			global $sd_widget_scripts;
71
72
			if ( ! $sd_widget_scripts ) {
73
				wp_add_inline_script( 'admin-widgets', $this->widget_js() );
74
				wp_add_inline_script( 'customize-controls', $this->widget_js() );
75
				wp_add_inline_style( 'widgets', $this->widget_css() );
76
77
				$sd_widget_scripts = true;
78
79
				// add shortcode insert button once
80
				add_action( 'media_buttons', array( $this, 'shortcode_insert_button' ) );
81
				if ( $this->is_preview() ) {
82
					add_action( 'wp_footer', array( $this, 'shortcode_insert_button_script' ) );
83
					add_action( 'elementor/editor/after_enqueue_scripts', array( $this, 'shortcode_insert_button_script' ) ); // for elementor
84
				}
85
				add_action( 'cornerstone_load_builder', array( $this, 'shortcode_insert_button_script' ) ); // for cornerstone builder (this is the preview)
86
87
				add_action( 'wp_ajax_super_duper_get_widget_settings', array( __CLASS__, 'get_widget_settings' ) );
88
			}
89
90
			do_action( 'wp_super_duper_widget_init', $options, $this );
91
		}
92
93
		/**
94
		 * Get widget settings.
95
		 *
96
		 * @since 1.0.0
97
		 */
98
		public static function get_widget_settings() {
99
			global $sd_widgets;
100
101
			$shortcode = isset( $_REQUEST['shortcode'] ) && $_REQUEST['shortcode'] ? sanitize_title_with_dashes( $_REQUEST['shortcode'] ) : '';
102
			if ( ! $shortcode ) {
103
				wp_die();
104
			}
105
			$widget_args = isset( $sd_widgets[ $shortcode ] ) ? $sd_widgets[ $shortcode ] : '';
106
			if ( ! $widget_args ) {
107
				wp_die();
108
			}
109
			$class_name = isset( $widget_args['class_name'] ) && $widget_args['class_name'] ? $widget_args['class_name'] : '';
110
			if ( ! $class_name ) {
111
				wp_die();
112
			}
113
114
			// invoke an instance method
115
			$widget = new $class_name;
116
117
			ob_start();
118
			$widget->form( array() );
119
			$form = ob_get_clean();
120
			echo "<form id='$shortcode'>" . $form . "<div class=\"widget-control-save\"></div></form>";
121
			echo "<style>" . $widget->widget_css() . "</style>";
122
			echo "<script>" . $widget->widget_js() . "</script>";
123
			?>
124
			<?php
125
			wp_die();
126
		}
127
128
		/**
129
		 * Insert shortcode builder button to classic editor (not inside Gutenberg, not needed).
130
		 *
131
		 * @since 1.0.0
132
		 *
133
		 * @param string $editor_id Optional. Shortcode editor id. Default null.
134
		 * @param string $insert_shortcode_function Optional. Insert shotcode function. Default null.
135
		 */
136
		public static function shortcode_insert_button( $editor_id = '', $insert_shortcode_function = '' ) {
137
			global $sd_widgets, $shortcode_insert_button_once;
138
			if ( $shortcode_insert_button_once ) {
139
				return;
140
			}
141
			add_thickbox();
142
143
144
			/**
145
			 * Cornerstone makes us play dirty tricks :/
146
			 * All media_buttons are removed via JS unless they are two specific id's so we wrap our content in this ID so it is not removed.
147
			 */
148
			if(function_exists('cornerstone_plugin_init') && !is_admin()){
149
				echo '<span id="insert-media-button">';
150
			}
151
152
			?>
153
			<div id="super-duper-content" style="display:none;">
154
155
				<div class="sd-shortcode-left-wrap">
156
					<?php
157
					asort( $sd_widgets );
158
					if ( ! empty( $sd_widgets ) ) {
159
						echo '<select class="widefat" onchange="sd_get_shortcode_options(this);">';
160
						echo "<option>" . __( 'Select shortcode' ) . "</option>";
161
						foreach ( $sd_widgets as $shortcode => $class ) {
162
							echo "<option value='" . esc_attr( $shortcode ) . "'>" . esc_attr( $shortcode ) . " (" . esc_attr( $class['name'] ) . ")</option>";
163
						}
164
						echo "</select>";
165
166
					}
167
					?>
168
					<div class="sd-shortcode-settings"></div>
169
170
				</div>
171
172
				<div class="sd-shortcode-right-wrap">
173
					<textarea id='sd-shortcode-output' disabled></textarea>
174
					<div id='sd-shortcode-output-actions'>
175
						<button class="button"
176
						        onclick="sd_insert_shortcode(<?php if ( ! empty( $editor_id ) ) {
177
							        echo "'" . $editor_id . "'";
178
						        } ?>)"><?php _e( 'Insert shortcode' ); ?></button>
179
						<button class="button"
180
						        onclick="sd_copy_to_clipboard()"><?php _e( 'Copy shortcode' ); ?></button>
181
					</div>
182
				</div>
183
184
			</div>
185
186
			<?php
187
			// if Font Awesome is available then show a icon if not show a WP icon.
188
			$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>';
189
			?>
190
191
			<a href="#TB_inline?width=100%&height=550&inlineId=super-duper-content"
192
			   class="thickbox button super-duper-content-open"
193
			   title="<?php _e( 'Add Shortcode' ); ?>"><?php echo $button_string; ?></a>
194
195
			<?php
196
197
			// see opening note
198
			if(function_exists('cornerstone_plugin_init') && !is_admin()){
199
				echo '</span>'; // end #insert-media-button
200
			}
201
202
			self::shortcode_insert_button_script( $editor_id, $insert_shortcode_function );
203
			$shortcode_insert_button_once = true;
204
		}
205
206
		/**
207
		 * Makes SD work with the siteOrigin page builder.
208
		 *
209
		 * @since 1.0.6
210
		 * @return mixed
211
		 */
212 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...
213
			ob_start();
214
			?>
215
			<script>
216
				/**
217
				 * Check a form to see what items shoudl be shown or hidden.
218
				 */
219
				function sd_so_show_hide(form) {
220
					jQuery(form).find(".sd-argument").each(function () {
221
222
						var $element_require = jQuery(this).data('element_require');
223
224
						if ($element_require) {
225
226
							$element_require = $element_require.replace("&#039;", "'"); // replace single quotes
227
							$element_require = $element_require.replace("&quot;", '"'); // replace double quotes
228
229
							if (eval($element_require)) {
230
								jQuery(this).removeClass('sd-require-hide');
231
							} else {
232
								jQuery(this).addClass('sd-require-hide');
233
							}
234
						}
235
					});
236
				}
237
238
				/**
239
				 * Toggle advanced settings visibility.
240
				 */
241
				function sd_so_toggle_advanced($this) {
242
					var form = jQuery($this).parents('form,.form,.so-content');
243
					form.find('.sd-advanced-setting').toggleClass('sd-adv-show');
244
					return false;// prevent form submit
245
				}
246
247
				/**
248
				 * Initialise a individual widget.
249
				 */
250
				function sd_so_init_widget($this, $selector) {
251
					if (!$selector) {
252
						$selector = 'form';
253
					}
254
					// only run once.
255
					if (jQuery($this).data('sd-widget-enabled')) {
256
						return;
257
					} else {
258
						jQuery($this).data('sd-widget-enabled', true);
259
					}
260
261
					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>';
262
					var form = jQuery($this).parents('' + $selector + '');
263
264
					if (jQuery($this).val() == '1' && jQuery(form).find('.sd-advanced-button').length == 0) {
265
						jQuery(form).append($button);
266
					}
267
268
					// show hide on form change
269
					jQuery(form).change(function () {
270
						sd_so_show_hide(form);
271
					});
272
273
					// show hide on load
274
					sd_so_show_hide(form);
275
				}
276
277
				jQuery(function () {
278
					jQuery(document).on('open_dialog', function (w, e) {
279
						setTimeout(function () {
280
							if (jQuery('.so-panels-dialog-wrapper:visible .so-content.panel-dialog .sd-show-advanced').length) {
281
								console.log('exists');
282
								if (jQuery('.so-panels-dialog-wrapper:visible .so-content.panel-dialog .sd-show-advanced').val() == '1') {
283
									console.log('true');
284
									sd_so_init_widget('.so-panels-dialog-wrapper:visible .so-content.panel-dialog .sd-show-advanced', 'div');
285
								}
286
							}
287
						}, 200);
288
					});
289
				});
290
			</script>
291
			<?php
292
			$output = ob_get_clean();
293
294
			/*
295
			 * We only add the <script> tags for code highlighting, so we strip them from the output.
296
			 */
297
298
			return str_replace( array(
299
				'<script>',
300
				'</script>'
301
			), '', $output );
302
		}
303
304
		/**
305
		 * Output the JS and CSS for the shortcode insert button.
306
		 *
307
		 * @since 1.0.6
308
		 *
309
		 * @param string $editor_id
310
		 * @param string $insert_shortcode_function
311
		 */
312
		public static function shortcode_insert_button_script( $editor_id = '', $insert_shortcode_function = '' ) {
313
			?>
314
			<style>
315
				.sd-shortcode-left-wrap {
316
					float: left;
317
					width: 60%;
318
				}
319
320
				.sd-shortcode-left-wrap .gd-help-tip {
321
					float: none;
322
				}
323
324
				.sd-shortcode-left-wrap .widefat {
325
					border-spacing: 0;
326
					width: 100%;
327
					clear: both;
328
					margin: 0;
329
					border: 1px solid #ddd;
330
					box-shadow: inset 0 1px 2px rgba(0, 0, 0, .07);
331
					background-color: #fff;
332
					color: #32373c;
333
					outline: 0;
334
					transition: 50ms border-color ease-in-out;
335
					padding: 3px 5px;
336
				}
337
338
				.sd-shortcode-left-wrap input[type=checkbox].widefat {
339
					border: 1px solid #b4b9be;
340
					background: #fff;
341
					color: #555;
342
					clear: none;
343
					cursor: pointer;
344
					display: inline-block;
345
					line-height: 0;
346
					height: 16px;
347
					margin: -4px 4px 0 0;
348
					margin-top: 0;
349
					outline: 0;
350
					padding: 0 !important;
351
					text-align: center;
352
					vertical-align: middle;
353
					width: 16px;
354
					min-width: 16px;
355
					-webkit-appearance: none;
356
					box-shadow: inset 0 1px 2px rgba(0, 0, 0, .1);
357
					transition: .05s border-color ease-in-out;
358
				}
359
360
				.sd-shortcode-left-wrap input[type=checkbox]:checked:before {
361
					content: "\f147";
362
					margin: -3px 0 0 -4px;
363
					color: #1e8cbe;
364
					float: left;
365
					display: inline-block;
366
					vertical-align: middle;
367
					width: 16px;
368
					font: normal 21px/1 dashicons;
369
					speak: none;
370
					-webkit-font-smoothing: antialiased;
371
					-moz-osx-font-smoothing: grayscale;
372
				}
373
374
				#sd-shortcode-output-actions button,
375
				.sd-advanced-button {
376
					color: #555;
377
					border-color: #ccc;
378
					background: #f7f7f7;
379
					box-shadow: 0 1px 0 #ccc;
380
					vertical-align: top;
381
					display: inline-block;
382
					text-decoration: none;
383
					font-size: 13px;
384
					line-height: 26px;
385
					height: 28px;
386
					margin: 0;
387
					padding: 0 10px 1px;
388
					cursor: pointer;
389
					border-width: 1px;
390
					border-style: solid;
391
					-webkit-appearance: none;
392
					border-radius: 3px;
393
					white-space: nowrap;
394
					box-sizing: border-box;
395
				}
396
397
				button.sd-advanced-button {
398
					background: #0073aa;
399
					border-color: #006799;
400
					box-shadow: inset 0 2px 0 #006799;
401
					vertical-align: top;
402
					color: #fff;
403
					text-decoration: none;
404
					text-shadow: 0 -1px 1px #006799, 1px 0 1px #006799, 0 1px 1px #006799, -1px 0 1px #006799;
405
					float: right;
406
					margin-right: 3px !important;
407
					font-size: 20px !important;
408
				}
409
410
				.sd-shortcode-right-wrap {
411
					float: right;
412
					width: 35%;
413
				}
414
415
				#sd-shortcode-output {
416
					background: rgba(255, 255, 255, .5);
417
					border-color: rgba(222, 222, 222, .75);
418
					box-shadow: inset 0 1px 2px rgba(0, 0, 0, .04);
419
					color: rgba(51, 51, 51, .5);
420
					overflow: auto;
421
					padding: 2px 6px;
422
					line-height: 1.4;
423
					resize: vertical;
424
				}
425
426
				#sd-shortcode-output {
427
					height: 250px;
428
					width: 100%;
429
				}
430
			</style>
431
			<?php
432
			if ( class_exists( 'SiteOrigin_Panels' ) ) {
433
				echo "<script>" . self::siteorigin_js() . "</script>";
434
			}
435
			?>
436
			<script>
437
				<?php
438
				if(! empty( $insert_shortcode_function )){
439
					echo $insert_shortcode_function;
440
				}else{
441
442
				/**
443
				 * Function for super duper insert shortcode.
444
				 *
445
				 * @since 1.0.0
446
				 */
447
				?>
448
				function sd_insert_shortcode($editor_id) {
449
					$shortcode = jQuery('#sd-shortcode-output').val();
450
					if ($shortcode) {
451
452
						if (!$editor_id) {
453
454
							<?php
455
							if ( isset( $_REQUEST['et_fb'] ) ) {
456
								echo '$editor_id = "#main_content_content_vb_tiny_mce";';
457
							}elseif ( isset( $_REQUEST['action'] ) &&  $_REQUEST['action']=='elementor' ) {
458
								echo '$editor_id = "#elementor-controls .wp-editor-container textarea";';
459
							}else{
460
								echo '$editor_id = "#wp-content-editor-container textarea";';
461
							}
462
							?>
463
						}else{
464
							$editor_id = '#'+$editor_id;
465
						}
466
467
						if (tinyMCE && tinyMCE.activeEditor && jQuery($editor_id).attr("aria-hidden") == "true") {
468
							tinyMCE.execCommand('mceInsertContent', false, $shortcode);
469
						} else {
470
							var $txt = jQuery($editor_id);
471
							var caretPos = $txt[0].selectionStart;
472
							var textAreaTxt = $txt.val();
473
							var txtToAdd = $shortcode;
474
							var textareaValue = textAreaTxt.substring(0, caretPos) + txtToAdd + textAreaTxt.substring(caretPos);
475
							$txt.val(textareaValue).change().keydown().blur().keyup().keypress();
476
477
							// set Divi react input value
478
							var input = document.getElementById("main_content_content_vb_tiny_mce");
479
							if (input) {
480
								sd_setNativeValue(input, textareaValue);
481
							}
482
483
						}
484
						tb_remove();
485
					}
486
				}
487
488
				function sd_setNativeValue(element, value) {
489
					let lastValue = element.value;
490
					element.value = value;
491
					let event = new Event("input", {target: element, bubbles: true});
492
					// React 15
493
					event.simulated = true;
494
					// React 16
495
					let tracker = element._valueTracker;
496
					if (tracker) {
497
						tracker.setValue(lastValue);
498
					}
499
					element.dispatchEvent(event);
500
				}
501
				<?php }?>
502
503
				function sd_copy_to_clipboard() {
504
					/* Get the text field */
505
					var copyText = document.getElementById("sd-shortcode-output");
506
					//un-disable the field
507
					copyText.disabled = false;
508
					/* Select the text field */
509
					copyText.select();
510
					/* Copy the text inside the text field */
511
					document.execCommand("Copy");
512
					//re-disable the field
513
					copyText.disabled = true;
514
					/* Alert the copied text */
515
					alert("Copied the text: " + copyText.value);
516
				}
517
				function sd_get_shortcode_options($this) {
518
519
					$short_code = jQuery($this).val();
520
					if ($short_code) {
521
522
						var data = {
523
							'action': 'super_duper_get_widget_settings',
524
							'shortcode': $short_code,
525
							'attributes': 123,
526
							'post_id': 321,
527
							'_ajax_nonce': '<?php echo wp_create_nonce( 'super_duper_output_shortcode' );?>'
528
						};
529
530
						if (typeof ajaxurl === 'undefined') {
531
							var ajaxurl = "<?php echo admin_url( 'admin-ajax.php' );?>";
532
						}
533
534
						jQuery.post(ajaxurl, data, function (response) {
535
							jQuery('.sd-shortcode-settings').html(response);
536
537
							jQuery('#' + $short_code).on('change', 'select', function () {
538
								sd_build_shortcode($short_code);
539
							}); // take care of select tags
540
541
							jQuery('#' + $short_code).on('change keypress keyup', 'input', function () {
542
								sd_build_shortcode($short_code);
543
							});
544
545
							sd_build_shortcode($short_code);
546
547
							// resize the window to fit
548
							setTimeout(function () {
549
								jQuery('#TB_ajaxContent').css('width', 'auto').css('height', '75vh');
550
							}, 200);
551
552
553
							return response;
554
						});
555
					}
556
557
				}
558
559
				function sd_build_shortcode($id) {
560
561
					var multiSelects = {};
562
					var multiSelectsRemove = [];
563
564
					$output = "[" + $id;
565
566
					$form_data = jQuery("#" + $id).serializeArray();
567
568
					// run checks for multiselects
569
					jQuery.each($form_data, function (index, element) {
570
						if (element && element.value) {
571
							$field_name = element.name.substr(element.name.indexOf("][") + 2);
572
							$field_name = $field_name.replace("]", "");
573
							// check if its a multiple
574
							if ($field_name.includes("[]")) {
575
								multiSelectsRemove[multiSelectsRemove.length] = index;
576
								$field_name = $field_name.replace("[]", "");
577
								if ($field_name in multiSelects) {
578
									multiSelects[$field_name] = multiSelects[$field_name] + "," + element.value;
579
								} else {
580
									multiSelects[$field_name] = element.value;
581
								}
582
							}
583
						}
584
					});
585
586
					// fix multiselects if any are found
587
					if (multiSelectsRemove.length) {
588
589
						// remove all multiselects
590
						multiSelectsRemove.reverse();
591
						multiSelectsRemove.forEach(function (index) {
592
							$form_data.splice(index, 1);
593
						});
594
595
						$ms_arr = [];
596
						// add multiselets back
597
						jQuery.each(multiSelects, function (index, value) {
598
							$ms_arr[$ms_arr.length] = {"name": "[][" + index + "]", "value": value};
599
						});
600
						$form_data = $form_data.concat($ms_arr);
601
					}
602
603
604
					if ($form_data) {
605
						$form_data.forEach(function (element) {
606
607
							if (element.value) {
608
								$field_name = element.name.substr(element.name.indexOf("][") + 2);
609
								$field_name = $field_name.replace("]", "");
610
								$output = $output + " " + $field_name + '="' + element.value + '"';
611
							}
612
613
						});
614
					}
615
					$output = $output + "]";
616
					jQuery('#sd-shortcode-output').html($output);
617
				}
618
619
			</script>
620
621
			<?php
622
		}
623
624 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...
625
			ob_start();
626
			?>
627
			<style>
628
				.sd-advanced-setting {
629
					display: none;
630
				}
631
632
				.sd-advanced-setting.sd-adv-show {
633
					display: block;
634
				}
635
636
				.sd-argument.sd-require-hide,
637
				.sd-advanced-setting.sd-require-hide {
638
					display: none;
639
				}
640
641
				button.sd-advanced-button {
642
					margin-right: 3px !important;
643
					font-size: 20px !important;
644
				}
645
			</style>
646
			<?php
647
			$output = ob_get_clean();
648
649
			/*
650
			 * We only add the <script> tags for code highlighting, so we strip them from the output.
651
			 */
652
653
			return str_replace( array(
654
				'<style>',
655
				'</style>'
656
			), '', $output );
657
		}
658
659 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...
660
			ob_start();
661
			?>
662
			<script>
663
664
				/**
665
				 * Toggle advanced settings visibility.
666
				 */
667
				function sd_toggle_advanced($this) {
668
					var form = jQuery($this).parents('form,.form');
669
					form.find('.sd-advanced-setting').toggleClass('sd-adv-show');
670
					return false;// prevent form submit
671
				}
672
673
				/**
674
				 * Check a form to see what items shoudl be shown or hidden.
675
				 */
676
				function sd_show_hide(form) {
677
					console.log('show/hide');
678
					jQuery(form).find(".sd-argument").each(function () {
679
680
						var $element_require = jQuery(this).data('element_require');
681
682
						if ($element_require) {
683
684
							$element_require = $element_require.replace("&#039;", "'"); // replace single quotes
685
							$element_require = $element_require.replace("&quot;", '"'); // replace double quotes
686
687
							if (eval($element_require)) {
688
								jQuery(this).removeClass('sd-require-hide');
689
							} else {
690
								jQuery(this).addClass('sd-require-hide');
691
							}
692
						}
693
					});
694
				}
695
696
				/**
697
				 * Initialise widgets from the widgets screen.
698
				 */
699
				function sd_init_widgets($selector) {
700
					jQuery(".sd-show-advanced").each(function (index) {
701
						sd_init_widget(this, $selector);
702
					});
703
				}
704
705
				/**
706
				 * Initialise a individual widget.
707
				 */
708
				function sd_init_widget($this, $selector) {
709
					console.log($selector);
710
711
					if (!$selector) {
712
						$selector = 'form';
713
					}
714
					// only run once.
715
					if (jQuery($this).data('sd-widget-enabled')) {
716
						return;
717
					} else {
718
						jQuery($this).data('sd-widget-enabled', true);
719
					}
720
721
					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>';
722
					var form = jQuery($this).parents('' + $selector + '');
723
724
					if (jQuery($this).val() == '1' && jQuery(form).find('.sd-advanced-button').length == 0) {
725
						console.log('add advanced button');
726
727
						jQuery(form).find('.widget-control-save').after($button);
728
					} else {
729
						console.log('no advanced button');
730
						console.log(jQuery($this).val());
731
						console.log(jQuery(form).find('.sd-advanced-button').length);
732
733
					}
734
735
					// show hide on form change
736
					jQuery(form).change(function () {
737
						sd_show_hide(form);
738
					});
739
740
					// show hide on load
741
					sd_show_hide(form);
742
				}
743
744
				/**
745
				 * Init a customizer widget.
746
				 */
747
				function sd_init_customizer_widget(section) {
748
					if (section.expanded) {
749
						section.expanded.bind(function (isExpanding) {
750
							if (isExpanding) {
751
								// is it a SD widget?
752
								if (jQuery(section.container).find('.sd-show-advanced').length) {
753
									// init the widget
754
									sd_init_widget(jQuery(section.container).find('.sd-show-advanced'), ".form");
755
								}
756
							}
757
						});
758
					}
759
				}
760
761
				/**
762
				 * If on widgets screen.
763
				 */
764
				jQuery(function () {
765
					// if not in customizer.
766
					if (!wp.customize) {
767
						sd_init_widgets("form");
768
					}
769
770
					// init on widget added
771
					jQuery(document).on('widget-added', function (e, widget) {
772
						console.log('widget added');
773
						// is it a SD widget?
774
						if (jQuery(widget).find('.sd-show-advanced').length) {
775
							// init the widget
776
							sd_init_widget(jQuery(widget).find('.sd-show-advanced'), "form");
777
						}
778
					});
779
780
					// inint on widget updated
781
					jQuery(document).on('widget-updated', function (e, widget) {
782
						console.log('widget updated');
783
784
						// is it a SD widget?
785
						if (jQuery(widget).find('.sd-show-advanced').length) {
786
							// init the widget
787
							sd_init_widget(jQuery(widget).find('.sd-show-advanced'), "form");
788
						}
789
					});
790
791
				});
792
793
794
				/**
795
				 * We need to run this before jQuery is ready
796
				 */
797
				if (wp.customize) {
798
					wp.customize.bind('ready', function () {
799
800
						// init widgets on load
801
						wp.customize.control.each(function (section) {
802
							sd_init_customizer_widget(section);
803
						});
804
805
						// init widgets on add
806
						wp.customize.control.bind('add', function (section) {
807
							sd_init_customizer_widget(section);
808
						});
809
810
					});
811
812
				}
813
				<?php do_action( 'wp_super_duper_widget_js', $this ); ?>
814
			</script>
815
			<?php
816
			$output = ob_get_clean();
817
818
			/*
819
			 * We only add the <script> tags for code highlighting, so we strip them from the output.
820
			 */
821
822
			return str_replace( array(
823
				'<script>',
824
				'</script>'
825
			), '', $output );
826
		}
827
828
829
		/**
830
		 * Set the name from the argument key.
831
		 *
832
		 * @param $options
833
		 *
834
		 * @return mixed
835
		 */
836
		private function add_name_from_key( $options, $arguments = false ) {
837
			if ( ! empty( $options['arguments'] ) ) {
838
				foreach ( $options['arguments'] as $key => $val ) {
839
					$options['arguments'][ $key ]['name'] = $key;
840
				}
841
			} elseif ( $arguments && is_array( $options ) && ! empty( $options ) ) {
842
				foreach ( $options as $key => $val ) {
843
					$options[ $key ]['name'] = $key;
844
				}
845
			}
846
847
			return $options;
848
		}
849
850
		/**
851
		 * Register the parent shortcode.
852
		 *
853
		 * @since 1.0.0
854
		 */
855
		public function register_shortcode() {
856
			add_shortcode( $this->base_id, array( $this, 'shortcode_output' ) );
857
			add_action( 'wp_ajax_super_duper_output_shortcode', array( __CLASS__, 'render_shortcode' ) );
858
		}
859
860
		/**
861
		 * Render the shortcode via ajax so we can return it to Gutenberg.
862
		 *
863
		 * @since 1.0.0
864
		 */
865
		public static function render_shortcode() {
866
867
			check_ajax_referer( 'super_duper_output_shortcode', '_ajax_nonce', true );
868
			if ( ! current_user_can( 'manage_options' ) ) {
869
				wp_die();
870
			}
871
872
			// we might need the $post value here so lets set it.
873
			if ( isset( $_POST['post_id'] ) && $_POST['post_id'] ) {
874
				$post_obj = get_post( absint( $_POST['post_id'] ) );
875
				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...
876
					global $post;
877
					$post = $post_obj;
878
				}
879
			}
880
881
			if ( isset( $_POST['shortcode'] ) && $_POST['shortcode'] ) {
882
				$shortcode_name   = sanitize_title_with_dashes( $_POST['shortcode'] );
883
				$attributes_array = isset( $_POST['attributes'] ) && $_POST['attributes'] ? $_POST['attributes'] : array();
884
				$attributes       = '';
885
				if ( ! empty( $attributes_array ) ) {
886
					foreach ( $attributes_array as $key => $value ) {
887
						$attributes .= " " . sanitize_title_with_dashes( $key ) . "='" . wp_slash( $value ) . "' ";
888
					}
889
				}
890
891
				$shortcode = "[" . $shortcode_name . " " . $attributes . "]";
892
893
				echo do_shortcode( $shortcode );
894
895
			}
896
			wp_die();
897
		}
898
899
		/**
900
		 * Output the shortcode.
901
		 *
902
		 * @param array $args
903
		 * @param string $content
904
		 *
905
		 * @return string
906
		 */
907
		public function shortcode_output( $args = array(), $content = '' ) {
908
			$args = self::argument_values( $args );
909
910
			// add extra argument so we know its a output to gutenberg
911
			//$args
912
			$args = $this->string_to_bool( $args );
913
914
915
			$calss = isset( $this->options['widget_ops']['classname'] ) ? esc_attr( $this->options['widget_ops']['classname'] ) : '';
916
917
			$calss = apply_filters( 'wp_super_duper_div_classname', $calss, $args, $this );
918
			$calss = apply_filters( 'wp_super_duper_div_classname_' . $this->base_id, $calss, $args, $this );
919
920
			$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...
921
			$attrs = apply_filters( 'wp_super_duper_div_attrs_' . $this->base_id, '', $args, $this );
922
923
			$shortcode_args = array();
924
			$output         = '';
925
			$no_wrap        = isset( $this->options['no_wrap'] ) && $this->options['no_wrap'] ? true : false;
926
			$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...
927
			if ( $main_content && ! $no_wrap ) {
928
				// wrap the shortcode in a dive with the same class as the widget
929
				$output .= '<div class="' . $calss . '" ' . $attrs . '>';
930
				if ( ! empty( $args['title'] ) ) {
931
					// if its a shortcode and there is a title try to grab the title wrappers
932
					$shortcode_args = array( 'before_title' => '', 'after_title' => '' );
933
					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...
934
						global $wp_registered_sidebars;
935
						if ( ! empty( $wp_registered_sidebars ) ) {
936
							foreach ( $wp_registered_sidebars as $sidebar ) {
937
								if ( ! empty( $sidebar['before_title'] ) ) {
938
									$shortcode_args['before_title'] = $sidebar['before_title'];
939
									$shortcode_args['after_title']  = $sidebar['after_title'];
940
									break;
941
								}
942
							}
943
						}
944
					}
945
					$output .= $this->output_title( $shortcode_args, $args );
946
				}
947
				$output .= $main_content;
948
				$output .= '</div>';
949
			} elseif ( $main_content && $no_wrap ) {
950
				$output .= $main_content;
951
			}
952
953
			// if preview show a placeholder if empty
954 View Code Duplication
			if ( $this->is_preview() && $output == '' ) {
955
				$output = $this->preview_placeholder_text( "[{" . $this->base_id . "}]" );
956
			}
957
958
			return $output;
959
		}
960
961
		/**
962
		 * Placeholder text to show if output is empty and we are on a preview/builder page.
963
		 *
964
		 * @param string $name
965
		 *
966
		 * @return string
967
		 */
968
		public function preview_placeholder_text( $name = '' ) {
969
			return "<div style='background:#0185ba33;padding: 10px;border: 4px #ccc dashed;'>" . sprintf( __( 'Placeholder for: %s' ), $name ) . "</div>";
970
		}
971
972
		/**
973
		 * Sometimes booleans values can be turned to strings, so we fix that.
974
		 *
975
		 * @param $options
976
		 *
977
		 * @return mixed
978
		 */
979
		public function string_to_bool( $options ) {
980
			// convert bool strings to booleans
981
			foreach ( $options as $key => $val ) {
982
				if ( $val == 'false' ) {
983
					$options[ $key ] = false;
984
				} elseif ( $val == 'true' ) {
985
					$options[ $key ] = true;
986
				}
987
			}
988
989
			return $options;
990
		}
991
992
		/**
993
		 * Get the argument values that are also filterable.
994
		 *
995
		 * @param $instance
996
		 *
997
		 * @return array
998
		 */
999
		public function argument_values( $instance ) {
1000
			$argument_values = array();
1001
1002
			// set widget instance
1003
			$this->instance = $instance;
1004
1005
			if ( empty( $this->arguments ) ) {
1006
				$this->arguments = $this->get_arguments();
1007
			}
1008
1009
			if ( ! empty( $this->arguments ) ) {
1010
				foreach ( $this->arguments as $key => $args ) {
1011
					// set the input name from the key
1012
					$args['name'] = $key;
1013
					//
1014
					$argument_values[ $key ] = isset( $instance[ $key ] ) ? $instance[ $key ] : '';
1015
					if ( $argument_values[ $key ] == '' && isset( $args['default'] ) ) {
1016
						$argument_values[ $key ] = $args['default'];
1017
					}
1018
				}
1019
			}
1020
1021
			return $argument_values;
1022
		}
1023
1024
		/**
1025
		 * Set arguments in super duper.
1026
		 *
1027
		 * @since 1.0.0
1028
		 *
1029
		 * @return array Set arguments.
1030
		 */
1031
		public function set_arguments() {
1032
			return $this->arguments;
1033
		}
1034
1035
		/**
1036
		 * Get arguments in super duper.
1037
		 *
1038
		 * @since 1.0.0
1039
		 *
1040
		 * @return array Get arguments.
1041
		 */
1042
		public function get_arguments() {
1043
			if ( empty( $this->arguments ) ) {
1044
				$this->arguments = $this->set_arguments();
1045
			}
1046
1047
			$this->arguments = apply_filters( 'wp_super_duper_arguments', $this->arguments, $this->options, $this->instance );
1048
			$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...
1049
1050
			return $this->arguments;
1051
		}
1052
1053
		/**
1054
		 * This is the main output class for all 3 items, widget, shortcode and block, it is extended in the calling class.
1055
		 *
1056
		 * @param array $args
1057
		 * @param array $widget_args
1058
		 * @param string $content
1059
		 */
1060
		public function output( $args = array(), $widget_args = array(), $content = '' ) {
1061
1062
		}
1063
1064
		/**
1065
		 * Add the dynamic block code inline when the wp-block in enqueued.
1066
		 */
1067
		public function register_block() {
1068
			wp_add_inline_script( 'wp-blocks', $this->block() );
1069
			if ( class_exists( 'SiteOrigin_Panels' ) ) {
1070
1071
				wp_add_inline_script( 'wp-blocks', $this->siteorigin_js() );
1072
1073
			}
1074
		}
1075
1076
		/**
1077
		 * Check if we need to show advanced options.
1078
		 *
1079
		 * @return bool
1080
		 */
1081
		public function block_show_advanced() {
1082
1083
			$show      = false;
1084
			$arguments = $this->arguments;
1085
1086
			if ( empty( $arguments ) ) {
1087
				$arguments = $this->get_arguments();
1088
			}
1089
1090
			if ( ! empty( $arguments ) ) {
1091
				foreach ( $arguments as $argument ) {
1092
					if ( isset( $argument['advanced'] ) && $argument['advanced'] ) {
1093
						$show = true;
1094
					}
1095
				}
1096
			}
1097
1098
			return $show;
1099
		}
1100
1101
1102
		/**
1103
		 * Output the JS for building the dynamic Guntenberg block.
1104
		 *
1105
		 * @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.
1106
		 * @return mixed
1107
		 */
1108
		public function block() {
1109
			ob_start();
1110
			?>
1111
			<script>
1112
				/**
1113
				 * BLOCK: Basic
1114
				 *
1115
				 * Registering a basic block with Gutenberg.
1116
				 * Simple block, renders and saves the same content without any interactivity.
1117
				 *
1118
				 * Styles:
1119
				 *        editor.css — Editor styles for the block.
1120
				 *        style.css  — Editor & Front end styles for the block.
1121
				 */
1122
				(function () {
1123
					var __ = wp.i18n.__; // The __() for internationalization.
1124
					var el = wp.element.createElement; // The wp.element.createElement() function to create elements.
1125
					var editable = wp.blocks.Editable;
1126
					var blocks = wp.blocks;
1127
					var registerBlockType = wp.blocks.registerBlockType; // The registerBlockType() to register blocks.
1128
					var is_fetching = false;
1129
					var prev_attributes = [];
1130
1131
					/**
1132
					 * Register Basic Block.
1133
					 *
1134
					 * Registers a new block provided a unique name and an object defining its
1135
					 * behavior. Once registered, the block is made available as an option to any
1136
					 * editor interface where blocks are implemented.
1137
					 *
1138
					 * @param  {string}   name     Block name.
1139
					 * @param  {Object}   settings Block settings.
1140
					 * @return {?WPBlock}          The block, if it has been successfully
1141
					 *                             registered; otherwise `undefined`.
1142
					 */
1143
					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.
1144
						title: '<?php echo $this->options['name'];?>', // Block title.
1145
						description: '<?php echo esc_attr( $this->options['widget_ops']['description'] )?>', // Block title.
1146
						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/.
1147
						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.
1148
						<?php if ( isset( $this->options['block-keywords'] ) ) {
1149
						echo "keywords : " . $this->options['block-keywords'] . ",";
1150
					}?>
1151
1152
						<?php
1153
1154
						$show_advanced = $this->block_show_advanced();
1155
1156
						$show_alignment = false;
1157
1158
						if ( ! empty( $this->arguments ) ) {
1159
							echo "attributes : {";
1160
1161
							if ( $show_advanced ) {
1162
								echo "show_advanced: {";
1163
								echo "	type: 'boolean',";
1164
								echo "  default: false,";
1165
								echo "},";
1166
							}
1167
1168
							// block wrap element
1169
							if ( isset( $this->options['block-wrap'] ) ) { //@todo we should validate this?
1170
								echo "block_wrap: {";
1171
								echo "	type: 'string',";
1172
								echo "  default: '" . esc_attr( $this->options['block-wrap'] ) . "',";
1173
								echo "},";
1174
							}
1175
1176
1177
							foreach ( $this->arguments as $key => $args ) {
1178
1179
								// set if we should show alignment
1180
								if ( $key == 'alignment' ) {
1181
									$show_alignment = true;
1182
								}
1183
1184
								$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...
1185
1186
								if ( $args['type'] == 'checkbox' ) {
1187
									$type    = 'boolean';
1188
									$default = isset( $args['default'] ) && $args['default'] ? 'true' : 'false';
1189
								} elseif ( $args['type'] == 'number' ) {
1190
									$type    = 'number';
1191
									$default = isset( $args['default'] ) ? "'" . $args['default'] . "'" : "''";
1192
								} elseif ( $args['type'] == 'select' && ! empty( $args['multiple'] ) ) {
1193
									$type = 'array';
1194
									if ( is_array( $args['default'] ) ) {
1195
										$default = isset( $args['default'] ) ? "['" . implode( "','", $args['default'] ) . "']" : "[]";
1196 View Code Duplication
									} else {
1197
										$default = isset( $args['default'] ) ? "'" . $args['default'] . "'" : "''";
1198
									}
1199
								} elseif ( $args['type'] == 'multiselect' ) {
1200
									$type    = 'array';
1201
									$default = isset( $args['default'] ) ? "'" . $args['default'] . "'" : "''";
1202 View Code Duplication
								} else {
1203
									$type    = 'string';
1204
									$default = isset( $args['default'] ) ? "'" . $args['default'] . "'" : "''";
1205
								}
1206
								echo $key . " : {";
1207
								echo "type : '$type',";
1208
								echo "default : $default,";
1209
								echo "},";
1210
							}
1211
1212
							echo "content : {type : 'string',default: 'Please select the attributes in the block settings'},";
1213
1214
							echo "},";
1215
1216
						}
1217
1218
						?>
1219
1220
						// The "edit" property must be a valid function.
1221
						edit: function (props) {
1222
1223
							var content = props.attributes.content;
1224
1225
							function onChangeContent() {
1226
1227
								if (!is_fetching && prev_attributes[props.id] != props.attributes) {
1228
1229
									//console.log(props);
1230
1231
									is_fetching = true;
1232
									var data = {
1233
										'action': 'super_duper_output_shortcode',
1234
										'shortcode': '<?php echo $this->options['base_id'];?>',
1235
										'attributes': props.attributes,
1236
										'post_id': <?php global $post; if ( isset( $post->ID ) ) {
1237
										echo $post->ID;
1238
									}?>,
1239
										'_ajax_nonce': '<?php echo wp_create_nonce( 'super_duper_output_shortcode' );?>'
1240
									};
1241
1242
									jQuery.post(ajaxurl, data, function (response) {
1243
										return response;
1244
									}).then(function (env) {
1245
1246
										// if the content is empty then we place some placeholder text
1247
										if (env == '') {
1248
											env = "<div style='background:#0185ba33;padding: 10px;border: 4px #ccc dashed;'>" + "<?php _e( 'Placeholder for: ' );?>" + props.name + "</div>";
1249
										}
1250
1251
										props.setAttributes({content: env});
1252
										is_fetching = false;
1253
										prev_attributes[props.id] = props.attributes;
1254
									});
1255
1256
1257
								}
1258
1259
								return props.attributes.content;
1260
1261
							}
1262
1263
							return [
1264
1265
								el(wp.editor.BlockControls, {key: 'controls'},
1266
1267
									<?php if($show_alignment){?>
1268
									el(
1269
										wp.editor.AlignmentToolbar,
1270
										{
1271
											value: props.attributes.alignment,
1272
											onChange: function (alignment) {
1273
												props.setAttributes({alignment: alignment})
1274
											}
1275
										}
1276
									)
1277
									<?php }?>
1278
1279
								),
1280
1281
								el(wp.editor.InspectorControls, {key: 'inspector'},
1282
1283
									<?php
1284
1285
									if(! empty( $this->arguments )){
1286
1287
									if ( $show_advanced ) {
1288
									?>
1289
									el(
1290
										wp.components.ToggleControl,
1291
										{
1292
											label: 'Show Advanced Settings?',
1293
											checked: props.attributes.show_advanced,
1294
											onChange: function (show_advanced) {
1295
												props.setAttributes({show_advanced: !props.attributes.show_advanced})
1296
											}
1297
										}
1298
									),
1299
									<?php
1300
1301
									}
1302
1303
									foreach($this->arguments as $key => $args){
1304
									$custom_attributes = ! empty( $args['custom_attributes'] ) ? $this->array_to_attributes( $args['custom_attributes'] ) : '';
1305
									$options = '';
1306
									$extra = '';
1307
									$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...
1308
									$onchange = "props.setAttributes({ $key: $key } )";
1309
									$value = "props.attributes.$key";
1310
									$text_type = array( 'text', 'password', 'number', 'email', 'tel', 'url', 'color'  );
1311
									if ( in_array( $args['type'], $text_type ) ) {
1312
										$type = 'TextControl';
1313
									}
1314
//									elseif ( $args['type'] == 'color' ) { //@todo ColorPicker labels are not shown yet, we may have to add our own https://github.com/WordPress/gutenberg/issues/14378
1315
//										$type = 'ColorPicker';
1316
//									}
1317
									elseif ( $args['type'] == 'checkbox' ) {
1318
										$type = 'CheckboxControl';
1319
										$extra .= "checked: props.attributes.$key,";
1320
										$onchange = "props.setAttributes({ $key: ! props.attributes.$key } )";
1321
									} elseif ( $args['type'] == 'select' || $args['type'] == 'multiselect' ) {
1322
										$type = 'SelectControl';
1323
										if ( ! empty( $args['options'] ) ) {
1324
											$options .= "options  : [";
1325
											foreach ( $args['options'] as $option_val => $option_label ) {
1326
												$options .= "{ value : '" . esc_attr( $option_val ) . "',     label : '" . esc_attr( $option_label ) . "'     },";
1327
											}
1328
											$options .= "],";
1329
										}
1330
										if ( isset( $args['multiple'] ) && $args['multiple'] ) { //@todo multiselect does not work at the moment: https://github.com/WordPress/gutenberg/issues/5550
1331
											$extra .= ' multiple: true, ';
1332
											//$onchange = "props.setAttributes({ $key: ['edit'] } )";
1333
											//$value = "['edit', 'delete']";
1334
										}
1335
									} elseif ( $args['type'] == 'alignment' ) {
1336
										$type = 'AlignmentToolbar'; // @todo this does not seem to work but cant find a example
1337
									} else {
1338
										continue;// if we have not implemented the control then don't break the JS.
1339
									}
1340
1341
									// add show only if advanced
1342
									if ( ! empty( $args['advanced'] ) ) {
1343
										echo "props.attributes.show_advanced && ";
1344
									}
1345
									// add setting require if defined
1346
									if ( ! empty( $args['element_require'] ) ) {
1347
										echo $this->block_props_replace( $args['element_require'], true ) . " && ";
1348
									}
1349
									?>
1350
									el(
1351
										wp.components.<?php echo esc_attr( $type );?>,
1352
										{
1353
											label: '<?php echo esc_attr( $args['title'] );?>',
1354
											help: '<?php if ( isset( $args['desc'] ) ) {
1355
												echo esc_attr( $args['desc'] );
1356
											}?>',
1357
											value: <?php echo $value;?>,
1358
											<?php if ( $type == 'TextControl' && $args['type'] != 'text' ) {
1359
											echo "type: '" . esc_attr( $args['type'] ) . "',";
1360
										}?>
1361
											<?php if ( ! empty( $args['placeholder'] ) ) {
1362
											echo "placeholder: '" . esc_attr( $args['placeholder'] ) . "',";
1363
										}?>
1364
											<?php echo $options;?>
1365
											<?php echo $extra;?>
1366
											<?php echo $custom_attributes;?>
1367
											onChange: function ( <?php echo $key;?> ) {
1368
												<?php echo $onchange;?>
1369
											}
1370
										}
1371
									),
1372
									<?php
1373
									}
1374
									}
1375
									?>
1376
1377
								),
1378
1379
								<?php
1380
								// If the user sets block-output array then build it
1381
								if ( ! empty( $this->options['block-output'] ) ) {
1382
								$this->block_element( $this->options['block-output'] );
1383
							}else{
1384
								// if no block-output is set then we try and get the shortcode html output via ajax.
1385
								?>
1386
								el('div', {
1387
									dangerouslySetInnerHTML: {__html: onChangeContent()},
1388
									className: props.className,
1389
									style: {'min-height': '30px'}
1390
								})
1391
								<?php
1392
								}
1393
								?>
1394
							]; // end return
1395
						},
1396
1397
						// The "save" property must be specified and must be a valid function.
1398
						save: function (props) {
1399
1400
							//console.log(props);
1401
1402
1403
							var attr = props.attributes;
1404
							var align = '';
1405
1406
							// build the shortcode.
1407
							var content = "[<?php echo $this->options['base_id'];?>";
1408
							<?php
1409
1410
							if(! empty( $this->arguments )){
1411
							foreach($this->arguments as $key => $args){
1412
							?>
1413
							if (attr.hasOwnProperty("<?php echo esc_attr( $key );?>")) {
1414
								content += " <?php echo esc_attr( $key );?>='" + attr.<?php echo esc_attr( $key );?>+ "' ";
1415
							}
1416
							<?php
1417
							}
1418
							}
1419
1420
							?>
1421
							content += "]";
1422
1423
1424
							// @todo should we add inline style here or just css classes?
1425
							if (attr.alignment) {
1426
								if (attr.alignment == 'left') {
1427
									align = 'alignleft';
1428
								}
1429
								if (attr.alignment == 'center') {
1430
									align = 'aligncenter';
1431
								}
1432
								if (attr.alignment == 'right') {
1433
									align = 'alignright';
1434
								}
1435
							}
1436
1437
							//console.log(content);
1438
							var block_wrap = 'div';
1439
							if (attr.hasOwnProperty("block_wrap")) {
1440
								block_wrap = attr.block_wrap;
1441
							}
1442
							return el(block_wrap, {dangerouslySetInnerHTML: {__html: content}, className: align});
1443
1444
						}
1445
					});
1446
				})();
1447
			</script>
1448
			<?php
1449
			$output = ob_get_clean();
1450
1451
			/*
1452
			 * We only add the <script> tags for code highlighting, so we strip them from the output.
1453
			 */
1454
1455
			return str_replace( array(
1456
				'<script>',
1457
				'</script>'
1458
			), '', $output );
1459
		}
1460
1461
		/**
1462
		 * Convert an array of attributes to block string.
1463
		 *
1464
		 * @todo there is prob a faster way to do this, also we could add some validation here.
1465
		 *
1466
		 * @param $custom_attributes
1467
		 *
1468
		 * @return string
1469
		 */
1470
		public function array_to_attributes( $custom_attributes, $html = false ) {
1471
			$attributes = '';
1472
			if ( ! empty( $custom_attributes ) ) {
1473
1474
				if ( $html ) {
1475
					foreach ( $custom_attributes as $key => $val ) {
1476
						$attributes .= " $key='$val' ";
1477
					}
1478
				} else {
1479
					foreach ( $custom_attributes as $key => $val ) {
1480
						$attributes .= "'$key': '$val',";
1481
					}
1482
				}
1483
			}
1484
1485
			return $attributes;
1486
		}
1487
1488
		/**
1489
		 * A self looping function to create the output for JS block elements.
1490
		 *
1491
		 * This is what is output in the WP Editor visual view.
1492
		 *
1493
		 * @param $args
1494
		 */
1495
		public function block_element( $args ) {
1496
1497
1498
			if ( ! empty( $args ) ) {
1499
				foreach ( $args as $element => $new_args ) {
1500
1501
					if ( is_array( $new_args ) ) { // its an element
1502
1503
1504
						if ( isset( $new_args['element'] ) ) {
1505
1506 View Code Duplication
							if ( isset( $new_args['element_require'] ) ) {
1507
								echo str_replace( array(
1508
										"'+",
1509
										"+'"
1510
									), '', $this->block_props_replace( $new_args['element_require'] ) ) . " &&  ";
1511
								unset( $new_args['element_require'] );
1512
							}
1513
1514
							echo "\n el( '" . $new_args['element'] . "', {";
1515
1516
							// get the attributes
1517
							foreach ( $new_args as $new_key => $new_value ) {
1518
1519
1520
								if ( $new_key == 'element' || $new_key == 'content' || $new_key == 'element_require' || $new_key == 'element_repeat' || is_array( $new_value ) ) {
1521
									// do nothing
1522
								} else {
1523
									echo $this->block_element( array( $new_key => $new_value ) );
1524
								}
1525
							}
1526
1527
							echo "},";// end attributes
1528
1529
							// get the content
1530
							$first_item = 0;
1531
							foreach ( $new_args as $new_key => $new_value ) {
1532
								if ( $new_key === 'content' || is_array( $new_value ) ) {
1533
1534
									if ( $new_key === 'content' ) {
1535
										echo "'" . $this->block_props_replace( $new_value ) . "'";
1536
									}
1537
1538
									if ( is_array( $new_value ) ) {
1539
1540 View Code Duplication
										if ( isset( $new_value['element_require'] ) ) {
1541
											echo str_replace( array(
1542
													"'+",
1543
													"+'"
1544
												), '', $this->block_props_replace( $new_value['element_require'] ) ) . " &&  ";
1545
											unset( $new_value['element_require'] );
1546
										}
1547
1548
										if ( isset( $new_value['element_repeat'] ) ) {
1549
											$x = 1;
1550
											while ( $x <= absint( $new_value['element_repeat'] ) ) {
1551
												$this->block_element( array( '' => $new_value ) );
1552
												$x ++;
1553
											}
1554
										} else {
1555
											$this->block_element( array( '' => $new_value ) );
1556
										}
1557
									}
1558
									$first_item ++;
1559
								}
1560
							}
1561
1562
							echo ")";// end content
1563
1564
							echo ", \n";
1565
1566
						}
1567
					} else {
1568
1569
						if ( substr( $element, 0, 3 ) === "if_" ) {
1570
							echo str_replace( "if_", "", $element ) . ": " . $this->block_props_replace( $new_args, true ) . ",";
1571
						} elseif ( $element == 'style' ) {
1572
							echo $element . ": " . $this->block_props_replace( $new_args ) . ",";
1573
						} else {
1574
							echo $element . ": '" . $this->block_props_replace( $new_args ) . "',";
1575
						}
1576
1577
					}
1578
				}
1579
			}
1580
		}
1581
1582
		/**
1583
		 * Replace block attributes placeholders with the proper naming.
1584
		 *
1585
		 * @param $string
1586
		 *
1587
		 * @return mixed
1588
		 */
1589
		public function block_props_replace( $string, $no_wrap = false ) {
1590
1591
			if ( $no_wrap ) {
1592
				$string = str_replace( array( "[%", "%]" ), array( "props.attributes.", "" ), $string );
1593
			} else {
1594
				$string = str_replace( array( "[%", "%]" ), array( "'+props.attributes.", "+'" ), $string );
1595
			}
1596
1597
			return $string;
1598
		}
1599
1600
		/**
1601
		 * Outputs the content of the widget
1602
		 *
1603
		 * @param array $args
1604
		 * @param array $instance
1605
		 */
1606
		public function widget( $args, $instance ) {
1607
1608
			// get the filtered values
1609
			$argument_values = $this->argument_values( $instance );
1610
			$argument_values = $this->string_to_bool( $argument_values );
1611
			$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...
1612
1613
			if ( $output ) {
1614
				// Before widget
1615
				$before_widget = $args['before_widget'];
1616
				$before_widget = apply_filters( 'wp_super_duper_before_widget', $before_widget, $args, $instance, $this );
1617
				$before_widget = apply_filters( 'wp_super_duper_before_widget_' . $this->base_id, $before_widget, $args, $instance, $this );
1618
1619
				// After widget
1620
				$after_widget = $args['after_widget'];
1621
				$after_widget = apply_filters( 'wp_super_duper_after_widget', $after_widget, $args, $instance, $this );
1622
				$after_widget = apply_filters( 'wp_super_duper_after_widget_' . $this->base_id, $after_widget, $args, $instance, $this );
1623
1624
				echo $before_widget;
1625
				// elementor strips the widget wrapping div so we check for and add it back if needed
1626
				if ( $this->is_elementor_widget_output() ) {
1627
					echo ! empty( $this->options['widget_ops']['classname'] ) ? "<span class='" . esc_attr( $this->options['widget_ops']['classname'] ) . "'>" : '';
1628
				}
1629
				echo $this->output_title( $args, $instance );
1630
				echo $output;
1631
				if ( $this->is_elementor_widget_output() ) {
1632
					echo ! empty( $this->options['widget_ops']['classname'] ) ? "</span>" : '';
1633
				}
1634
				echo $after_widget;
1635 View Code Duplication
			} elseif ( $this->is_preview() && $output == '' ) {// if preview show a placeholder if empty
1636
				$output = $this->preview_placeholder_text( "{{" . $this->base_id . "}}" );
1637
				echo $output;
1638
			}
1639
		}
1640
1641
		/**
1642
		 * Tests if the current output is inside a elementor container.
1643
		 *
1644
		 * @since 1.0.4
1645
		 * @return bool
1646
		 */
1647
		public function is_elementor_widget_output() {
1648
			$result = false;
1649
			if ( defined( 'ELEMENTOR_VERSION' ) && isset( $this->number ) && $this->number == 'REPLACE_TO_ID' ) {
1650
				$result = true;
1651
			}
1652
1653
			return $result;
1654
		}
1655
1656
		/**
1657
		 * Tests if the current output is inside a elementor preview.
1658
		 *
1659
		 * @since 1.0.4
1660
		 * @return bool
1661
		 */
1662 View Code Duplication
		public function is_elementor_preview() {
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...
1663
			$result = false;
1664
			if ( isset( $_REQUEST['elementor-preview'] ) || ( is_admin() && isset( $_REQUEST['action'] ) && $_REQUEST['action'] == 'elementor' ) || (isset( $_REQUEST['action'] ) && $_REQUEST['action'] == 'elementor_ajax') ) {
1665
				$result = true;
1666
			}
1667
1668
			return $result;
1669
		}
1670
1671
		/**
1672
		 * Tests if the current output is inside a Divi preview.
1673
		 *
1674
		 * @since 1.0.6
1675
		 * @return bool
1676
		 */
1677 View Code Duplication
		public function is_divi_preview() {
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...
1678
			$result = false;
1679
			if ( isset( $_REQUEST['et_fb'] ) || isset( $_REQUEST['et_pb_preview'] ) || ( is_admin() && isset( $_REQUEST['action'] ) && $_REQUEST['action'] == 'elementor' ) ) {
1680
				$result = true;
1681
			}
1682
1683
			return $result;
1684
		}
1685
1686
		/**
1687
		 * Tests if the current output is inside a Beaver builder preview.
1688
		 *
1689
		 * @since 1.0.6
1690
		 * @return bool
1691
		 */
1692
		public function is_beaver_preview() {
1693
			$result = false;
1694
			if ( isset( $_REQUEST['fl_builder'] ) ) {
1695
				$result = true;
1696
			}
1697
1698
			return $result;
1699
		}
1700
1701
		/**
1702
		 * Tests if the current output is inside a siteorigin builder preview.
1703
		 *
1704
		 * @since 1.0.6
1705
		 * @return bool
1706
		 */
1707
		public function is_siteorigin_preview() {
1708
			$result = false;
1709
			if ( !empty( $_REQUEST['siteorigin_panels_live_editor'] )) {
1710
				$result = true;
1711
			}
1712
1713
			return $result;
1714
		}
1715
1716
		/**
1717
		 * Tests if the current output is inside a cornerstone builder preview.
1718
		 *
1719
		 * @since 1.0.8
1720
		 * @return bool
1721
		 */
1722
		public function is_cornerstone_preview() {
1723
			$result = false;
1724
			if ( !empty( $_REQUEST['cornerstone_preview'] ) || basename($_SERVER['REQUEST_URI'])=='cornerstone-endpoint') {
1725
				$result = true;
1726
			}
1727
1728
			return $result;
1729
		}
1730
1731
		/**
1732
		 * General function to check if we are in a preview situation.
1733
		 *
1734
		 * @since 1.0.6
1735
		 * @return bool
1736
		 */
1737
		public function is_preview() {
1738
			$preview = false;
1739
			if ( $this->is_divi_preview() ) {
1740
				$preview = true;
1741
			} elseif ( $this->is_elementor_preview() ) {
1742
				$preview = true;
1743
			} elseif ( $this->is_beaver_preview() ) {
1744
				$preview = true;
1745
			} elseif ( $this->is_siteorigin_preview() ) {
1746
				$preview = true;
1747
			}elseif ( $this->is_cornerstone_preview() ) {
1748
				$preview = true;
1749
			}
1750
1751
			return $preview;
1752
		}
1753
1754
		/**
1755
		 * Output the super title.
1756
		 *
1757
		 * @param $args
1758
		 * @param array $instance
1759
		 *
1760
		 * @return string
1761
		 */
1762
		public function output_title( $args, $instance = array() ) {
1763
			$output = '';
1764
			if ( ! empty( $instance['title'] ) ) {
1765
				/** This filter is documented in wp-includes/widgets/class-wp-widget-pages.php */
1766
				$title  = apply_filters( 'widget_title', $instance['title'], $instance, $this->id_base );
1767
				$output = $args['before_title'] . $title . $args['after_title'];
1768
			}
1769
1770
			return $output;
1771
		}
1772
1773
		/**
1774
		 * Outputs the options form inputs for the widget.
1775
		 *
1776
		 * @param array $instance The widget options.
1777
		 */
1778
		public function form( $instance ) {
1779
1780
			// set widget instance
1781
			$this->instance = $instance;
1782
1783
			// set it as a SD widget
1784
			echo $this->widget_advanced_toggle();
1785
1786
			echo "<p>" . esc_attr( $this->options['widget_ops']['description'] ) . "</p>";
1787
			$arguments = $this->get_arguments();
1788
1789
			if ( is_array( $arguments ) ) {
1790
				foreach ( $arguments as $key => $args ) {
1791
					$this->widget_inputs( $args, $instance );
1792
				}
1793
			}
1794
		}
1795
1796
		/**
1797
		 * Get the hidden input that when added makes the advanced button show on widget settings.
1798
		 *
1799
		 * @return string
1800
		 */
1801
		public function widget_advanced_toggle() {
1802
1803
			$output = '';
1804
			if ( $this->block_show_advanced() ) {
1805
				$val = 1;
1806
			} else {
1807
				$val = 0;
1808
			}
1809
1810
			$output .= "<input type='hidden'  class='sd-show-advanced' value='$val' />";
1811
1812
			return $output;
1813
		}
1814
1815
		/**
1816
		 * Convert require element.
1817
		 *
1818
		 * @since 1.0.0
1819
		 *
1820
		 * @param string $input Input element.
1821
		 *
1822
		 * @return string $output
1823
		 */
1824
		public function convert_element_require( $input ) {
1825
1826
			$input = str_replace( "'", '"', $input );// we only want double quotes
1827
1828
			$output = esc_attr( str_replace( array( "[%", "%]" ), array(
1829
				"jQuery(form).find('[data-argument=\"",
1830
				"\"]').find('input,select').val()"
1831
			), $input ) );
1832
1833
			return $output;
1834
		}
1835
1836
		/**
1837
		 * Builds the inputs for the widget options.
1838
		 *
1839
		 * @param $args
1840
		 * @param $instance
1841
		 */
1842
		public function widget_inputs( $args, $instance ) {
1843
1844
			$class             = "";
1845
			$element_require   = "";
1846
			$custom_attributes = "";
1847
1848
			// get value
1849
			if ( isset( $instance[ $args['name'] ] ) ) {
1850
				$value = $instance[ $args['name'] ];
1851
			} elseif ( ! isset( $instance[ $args['name'] ] ) && ! empty( $args['default'] ) ) {
1852
				$value = is_array( $args['default'] ) ? array_map( "esc_html", $args['default'] ) : esc_html( $args['default'] );
1853
			} else {
1854
				$value = '';
1855
			}
1856
1857
			// get placeholder
1858 View Code Duplication
			if ( ! empty( $args['placeholder'] ) ) {
1859
				$placeholder = "placeholder='" . esc_html( $args['placeholder'] ) . "'";
1860
			} else {
1861
				$placeholder = '';
1862
			}
1863
1864
			// get if advanced
1865
			if ( isset( $args['advanced'] ) && $args['advanced'] ) {
1866
				$class .= " sd-advanced-setting ";
1867
			}
1868
1869
			// element_require
1870
			if ( isset( $args['element_require'] ) && $args['element_require'] ) {
1871
				$element_require = $args['element_require'];
1872
			}
1873
1874
			// custom_attributes
1875
			if ( isset( $args['custom_attributes'] ) && $args['custom_attributes'] ) {
1876
				$custom_attributes = $this->array_to_attributes( $args['custom_attributes'], true );
1877
			}
1878
1879
			// before wrapper
1880
			?>
1881
			<p class="sd-argument <?php echo esc_attr( $class ); ?>"
1882
			   data-argument='<?php echo esc_attr( $args['name'] ); ?>'
1883
			   data-element_require='<?php if ( $element_require ) {
1884
				   echo $this->convert_element_require( $element_require );
1885
			   } ?>'
1886
			>
1887
				<?php
1888
1889
				switch ( $args['type'] ) {
1890
					//array('text','password','number','email','tel','url','color')
1891
					case "text":
1892
					case "password":
1893
					case "number":
1894
					case "email":
1895
					case "tel":
1896
					case "url":
1897 View Code Duplication
					case "color":
1898
						?>
1899
						<label
1900
							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>
1901
						<input <?php echo $placeholder; ?> class="widefat"
1902
							<?php echo $custom_attributes; ?>
1903
							                               id="<?php echo esc_attr( $this->get_field_id( $args['name'] ) ); ?>"
1904
							                               name="<?php echo esc_attr( $this->get_field_name( $args['name'] ) ); ?>"
1905
							                               type="<?php echo esc_attr( $args['type'] ); ?>"
1906
							                               value="<?php echo esc_attr( $value ); ?>">
1907
						<?php
1908
1909
						break;
1910
					case "select":
1911
						$multiple = isset( $args['multiple'] ) && $args['multiple'] ? true : false;
1912
						if ( $multiple ) {
1913
							if ( empty( $value ) ) {
1914
								$value = array();
1915
							}
1916
						}
1917
						?>
1918
						<label
1919
							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>
1920
						<select <?php echo $placeholder; ?> class="widefat"
1921
							<?php echo $custom_attributes; ?>
1922
							                                id="<?php echo esc_attr( $this->get_field_id( $args['name'] ) ); ?>"
1923
							                                name="<?php echo esc_attr( $this->get_field_name( $args['name'] ) );
1924
							                                if ( $multiple ) {
1925
								                                echo "[]";
1926
							                                } ?>"
1927
							<?php if ( $multiple ) {
1928
								echo "multiple";
1929
							} //@todo not implemented yet due to gutenberg not supporting it
1930
							?>
1931
						>
1932
							<?php
1933
1934
							if ( ! empty( $args['options'] ) ) {
1935
								foreach ( $args['options'] as $val => $label ) {
1936
									if ( $multiple ) {
1937
										$selected = in_array( $val, $value ) ? 'selected="selected"' : '';
1938
									} else {
1939
										$selected = selected( $value, $val, false );
1940
									}
1941
									echo "<option value='$val' " . $selected . ">$label</option>";
1942
								}
1943
							}
1944
							?>
1945
						</select>
1946
						<?php
1947
						break;
1948 View Code Duplication
					case "checkbox":
1949
						?>
1950
						<input <?php echo $placeholder; ?>
1951
							<?php checked( 1, $value, true ) ?>
1952
							<?php echo $custom_attributes; ?>
1953
							class="widefat" id="<?php echo esc_attr( $this->get_field_id( $args['name'] ) ); ?>"
1954
							name="<?php echo esc_attr( $this->get_field_name( $args['name'] ) ); ?>" type="checkbox"
1955
							value="1">
1956
						<label
1957
							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>
1958
						<?php
1959
						break;
1960
					case "hidden":
1961
						?>
1962
						<input id="<?php echo esc_attr( $this->get_field_id( $args['name'] ) ); ?>"
1963
						       name="<?php echo esc_attr( $this->get_field_name( $args['name'] ) ); ?>" type="hidden"
1964
						       value="<?php echo esc_attr( $value ); ?>">
1965
						<?php
1966
						break;
1967
					default:
1968
						echo "No input type found!"; // @todo we need to add more input types.
1969
				}
1970
1971
				// after wrapper
1972
				?>
1973
			</p>
1974
			<?php
1975
1976
		}
1977
1978
		/**
1979
		 * Get the widget input description html.
1980
		 *
1981
		 * @param $args
1982
		 *
1983
		 * @return string
1984
		 * @todo, need to make its own tooltip script
1985
		 */
1986
		public function widget_field_desc( $args ) {
1987
1988
			$description = '';
1989
			if ( isset( $args['desc'] ) && $args['desc'] ) {
1990
				if ( isset( $args['desc_tip'] ) && $args['desc_tip'] ) {
1991
					$description = $this->desc_tip( $args['desc'] );
1992
				} else {
1993
					$description = '<span class="description">' . wp_kses_post( $args['desc'] ) . '</span>';
1994
				}
1995
			}
1996
1997
			return $description;
1998
		}
1999
2000
		/**
2001
		 * Get the tool tip html.
2002
		 *
2003
		 * @param $tip
2004
		 * @param bool $allow_html
2005
		 *
2006
		 * @return string
2007
		 */
2008
		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...
2009
			if ( $allow_html ) {
2010
				$tip = $this->sanitize_tooltip( $tip );
2011
			} else {
2012
				$tip = esc_attr( $tip );
2013
			}
2014
2015
			return '<span class="gd-help-tip dashicons dashicons-editor-help" title="' . $tip . '"></span>';
2016
		}
2017
2018
		/**
2019
		 * Sanitize a string destined to be a tooltip.
2020
		 *
2021
		 * @param string $var
2022
		 *
2023
		 * @return string
2024
		 */
2025
		public function sanitize_tooltip( $var ) {
2026
			return htmlspecialchars( wp_kses( html_entity_decode( $var ), array(
2027
				'br'     => array(),
2028
				'em'     => array(),
2029
				'strong' => array(),
2030
				'small'  => array(),
2031
				'span'   => array(),
2032
				'ul'     => array(),
2033
				'li'     => array(),
2034
				'ol'     => array(),
2035
				'p'      => array(),
2036
			) ) );
2037
		}
2038
2039
		/**
2040
		 * Processing widget options on save
2041
		 *
2042
		 * @param array $new_instance The new options
2043
		 * @param array $old_instance The previous options
2044
		 *
2045
		 * @return array
2046
		 * @todo we should add some sanitation here.
2047
		 */
2048
		public function update( $new_instance, $old_instance ) {
2049
2050
			//save the widget
2051
			$instance = array_merge( (array) $old_instance, (array) $new_instance );
2052
2053
			// set widget instance
2054
			$this->instance = $instance;
2055
2056
			if ( empty( $this->arguments ) ) {
2057
				$this->get_arguments();
2058
			}
2059
2060
			// check for checkboxes
2061
			if ( ! empty( $this->arguments ) ) {
2062
				foreach ( $this->arguments as $argument ) {
2063
					if ( isset( $argument['type'] ) && $argument['type'] == 'checkbox' && ! isset( $new_instance[ $argument['name'] ] ) ) {
2064
						$instance[ $argument['name'] ] = '0';
2065
					}
2066
				}
2067
			}
2068
2069
			return $instance;
2070
		}
2071
2072
		/**
2073
		 * Checks if the current call is a ajax call to get the block content.
2074
		 *
2075
		 * This can be used in your widget to return different content as the block content.
2076
		 *
2077
		 * @since 1.0.3
2078
		 * @return bool
2079
		 */
2080
		public function is_block_content_call() {
2081
			$result = false;
2082
			if ( wp_doing_ajax() && isset( $_REQUEST['action'] ) && $_REQUEST['action'] == 'super_duper_output_shortcode' ) {
2083
				$result = true;
2084
			}
2085
2086
			return $result;
2087
		}
2088
2089
	}
2090
2091
}