Passed
Push — master ( 1d60eb...03dff3 )
by Stiofan
06:44 queued 03:02
created

WP_Super_Duper::shortcode_insert_button()   B

Complexity

Conditions 5
Paths 5

Size

Total Lines 209

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 5
nc 5
nop 2
dl 0
loc 209
rs 7.6888
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
	 * @ver 1.0.2
16
	 */
17
	class WP_Super_Duper extends WP_Widget {
18
19
20
		public $version = "1.0.2";
21
		public $block_code;
22
		public $options;
23
		public $base_id;
24
		public $arguments = array();
25
		public $instance = array();
26
		private $class_name;
27
28
		/**
29
		 * Take the array options and use them to build.
30
		 */
31
		public function __construct( $options ) {
32
			global $sd_widgets;
33
34
35
36
			//print_r($options);exit;
37
			$sd_widgets[$options['base_id']] = array('name'=> $options['name'],'class_name'=>$options['class_name']);
38
			$this->base_id = $options['base_id'];
39
			// lets filter the options before we do anything
40
			$options       = apply_filters( "wp_super_duper_options", $options );
41
			$options       = apply_filters( "wp_super_duper_options_{$this->base_id}", $options );
42
			$options       = $this->add_name_from_key( $options );
43
			$this->options = $options;
44
45
			$this->base_id   = $options['base_id'];
46
			$this->arguments = isset( $options['arguments'] ) ? $options['arguments'] : array();
47
48
49
			// init parent
50
			parent::__construct( $options['base_id'], $options['name'], $options['widget_ops'] );
51
52
53
			if ( isset( $options['class_name'] ) ) {
54
				// register widget
55
				$this->class_name = $options['class_name'];
56
57
				// register shortcode
58
				$this->register_shortcode();
59
60
				// register block
61
				//$this->register_block();
62
				add_action( 'admin_enqueue_scripts', array( $this, 'register_block' ) );
63
			}
64
65
			// add the CSS and JS we need ONCE
66
			global $sd_widget_scripts;
67
68
			if ( ! $sd_widget_scripts ) {
69
				wp_add_inline_script( 'admin-widgets', $this->widget_js() );
70
				wp_add_inline_script( 'customize-controls', $this->widget_js() );
71
				wp_add_inline_style( 'widgets', $this->widget_css() );
72
73
				// seems ashame to add this for one icon but i love it :(
74
				//wp_register_script('font-awesome', 'https://use.fontawesome.com/releases/v5.4.1/js/all.js', array('font-awesome-shim'), $this->version);
75
				//wp_register_script('font-awesome-shim', 'https://use.fontawesome.com/releases/v5.4.1/js/v4-shims.js', array(), $this->version);
76
77
				//echo '###';
78
				$sd_widget_scripts = true;
79
80
				// add shortcode insert button once
81
				add_action( 'media_buttons',array( $this, 'shortcode_insert_button' ) );
82
				//if( !wp_doing_ajax() ){
83
				add_action( 'wp_ajax_super_duper_get_widget_settings', array( __CLASS__, 'get_widget_settings' ) );
84
				//}
85
86
			}
87
88
			do_action( 'wp_super_duper_widget_init', $options, $this );
89
90
		}
91
92
		/**
93
		 * Get widget settings.
94
		 *
95
		 * @since 2.0.0
96
		 */
97
		public static function get_widget_settings(){
98
			global $sd_widgets;
99
//			print_r($_REQUEST);
100
//			echo '####';
101
102
			$shortcode = isset($_REQUEST['shortcode']) && $_REQUEST['shortcode'] ? sanitize_title_with_dashes($_REQUEST['shortcode']) : '';
103
			if(!$shortcode){wp_die();}
104
			$widget_args = isset($sd_widgets[$shortcode]) ? $sd_widgets[$shortcode] :'';
105
			if(!$widget_args){wp_die();}
106
			$class_name = isset($widget_args['class_name']) && $widget_args['class_name'] ? $widget_args['class_name'] : '';
107
			if(!$class_name){wp_die();}
108
109
110
111
			//print_r( $sd_widgets );
112
113
114
			// invoke an instance method
115
//			$instance = new Instance();
116
//			call_user_func( array( $instance, 'method' ) );
117
			$widget = new $class_name;
118
119
//			print_r($widget->form(array()));
120
			ob_start();
121
			$widget->form(array());
122
			$form = ob_get_clean();
123
			echo "<form id='$shortcode'>".$form."<div class=\"widget-control-save\"></div></form>";
124
//			echo "<div id='sd-shortcode-output'></div>";
125
126
			echo "<style>".$widget->widget_css()."</style>";
127
			echo "<script>".$widget->widget_js()."</script>";
128
			?>
129
			<?php
130
			wp_die();
131
		}
132
133
		/**
134
		 * Insert button in shortcode.
135
		 *
136
		 * @since 2.0.0
137
		 *
138
		 * @param string $editor_id Optional. Shortcode editor id. Default null.
139
		 * @param string $insert_shortcode_function Optional. Insert shotcode function. Default null.
140
		 */
141
		public static function shortcode_insert_button($editor_id = '',$insert_shortcode_function=''){
142
			global $sd_widgets,$shortcode_insert_button_once;
143
			if($shortcode_insert_button_once){return;}
144
			add_thickbox();
145
			?>
146
			<div id="super-duper-content" style="display:none;">
147
148
				<div class="sd-shortcode-left-wrap">
149
					<?php
150
					//print_r( $sd_widgets );
151
					asort($sd_widgets );
152
					if(!empty($sd_widgets)){
153
						echo '<select onchange="sd_get_shortcode_options(this);">';
154
						echo "<option>".__('Select shortcode')."</option>";
155
						foreach($sd_widgets as $shortcode => $class){
156
							echo "<option value='".esc_attr($shortcode)."'>".esc_attr($shortcode)." (".esc_attr($class['name']).")</option>";
157
						}
158
						echo "</select>";
159
160
					}
161
					?>
162
					<div class="sd-shortcode-settings"></div>
163
164
				</div>
165
166
				<div  class="sd-shortcode-right-wrap">
167
					<textarea id='sd-shortcode-output' disabled></textarea>
168
					<div id='sd-shortcode-output-actions'>
169
						<button class="button" onclick="sd_insert_shortcode()"><?php _e('Insert shortcode');?></button>
170
						<button class="button" onclick="sd_copy_to_clipboard()"><?php _e('Copy shortcode');?></button>
171
					</div>
172
				</div>
173
174
			</div>
175
176
177
			<a href="#TB_inline?width=100%&height=550&inlineId=super-duper-content" class="thickbox button super-duper-content-open" title="<?php _e('Add Shortcode');?>"><i class="fas fa-cubes" aria-hidden="true"></i></a>
178
179
			<style>
180
				.sd-shortcode-left-wrap{
181
					float: left;
182
					width: 60%;
183
				}
184
				.sd-shortcode-left-wrap .gd-help-tip{
185
					float: none;
186
				}
187
				.sd-shortcode-right-wrap{
188
					float: right;
189
					width: 35%;
190
				}
191
				#sd-shortcode-output{
192
					height: 250px;
193
					width: 100%;
194
				}
195
			</style>
196
			<script>
197
198
				<?php
199
				if(!empty($insert_shortcode_function)){
200
					echo $insert_shortcode_function;
201
				}else{
202
203
				/**
204
				 * Function for super duper insert shortcode.
205
				 *
206
				 * @since 2.0.0
207
				 */
208
				?>
209
				function sd_insert_shortcode(){
210
					$shortcode = jQuery('#sd-shortcode-output').val();
211
					if($shortcode){
212
//						jQuery('.wp-editor-area').append($shortcode);
213
						console.log(jQuery("#wp-content-editor-container textarea").attr("aria-hidden"));
214
						if(tinyMCE && tinyMCE.activeEditor && jQuery("#wp-content-editor-container textarea").attr( "aria-hidden")=="true") {
215
							tinyMCE.execCommand('mceInsertContent', false, $shortcode);
216
						}else{
217
							//jQuery('#wp-content-editor-container textarea').val($shortcode);
218
//							$( '#wp-content-editor-container' ).find( 'textarea' ).val( 'Some default Text' );
219
							var $txt = jQuery("#wp-content-editor-container textarea");
220
							var caretPos = $txt[0].selectionStart;
221
							var textAreaTxt = $txt.val();
222
							var txtToAdd = $shortcode;
223
							$txt.val(textAreaTxt.substring(0, caretPos) + txtToAdd + textAreaTxt.substring(caretPos) );
224
						}
225
						tb_remove();
226
					}
227
				}
228
				<?php }?>
229
230
				function sd_copy_to_clipboard(){
231
					/* Get the text field */
232
					var copyText = document.getElementById("sd-shortcode-output");
233
					//un-disable the field
234
					copyText.disabled = false;
235
					/* Select the text field */
236
					copyText.select();
237
					/* Copy the text inside the text field */
238
					document.execCommand("Copy");
239
					//re-disable the field
240
					copyText.disabled = true;
241
					/* Alert the copied text */
242
					alert("Copied the text: " + copyText.value);
243
				}
244
				function sd_get_shortcode_options($this){
245
					//console.log($this);
246
					//console.log(jQuery($this).val());
247
					$short_code = jQuery($this).val();
248
					if($short_code){
249
250
						var data = {
251
							'action': 'super_duper_get_widget_settings',
252
							'shortcode': $short_code,
253
							'attributes': 123,
254
							'post_id': 321,
255
							'_ajax_nonce': '<?php echo wp_create_nonce( 'super_duper_output_shortcode' );?>'
256
						};
257
258
						jQuery.post(ajaxurl, data, function (response) {
259
							console.log(response);
260
							jQuery('.sd-shortcode-settings').html(response);
261
262
263
//
264
							jQuery('#'+$short_code).on('change', 'select', function() {
265
								sd_build_shortcode($short_code);
266
							}); // take care of select tags
267
268
							jQuery('#'+$short_code).on('change keypress keyup', 'input', function() {
269
								sd_build_shortcode($short_code);
270
							});
271
272
							sd_build_shortcode($short_code);
273
274
							// resize the window to fit
275
							jQuery('#TB_ajaxContent').css('width','auto').css('height','calc(100% - 46px)');
276
277
278
							return response;
279
						});
280
					}
281
282
				}
283
284
				function sd_build_shortcode($id){
285
286
					var multiSelects = {};
287
					var multiSelectsRemove = [];
288
289
					$output = "["+$id;
290
291
					$form_data = jQuery("#"+$id).serializeArray();
292
293
294
					// run checks for multiselects
295
					jQuery.each($form_data, function( index, element) {
296
						if(element && element.value) {
297
							$field_name = element.name.substr(element.name.indexOf("][") + 2);
298
							$field_name = $field_name.replace("]", "");
299
							// check if its a multiple
300
							if($field_name.includes("[]")){
301
								multiSelectsRemove[multiSelectsRemove.length] = index;
302
								$field_name = $field_name.replace("[]", "");
303
								if($field_name in multiSelects){
304
									multiSelects[$field_name] = multiSelects[$field_name]+","+element.value;
305
								}else{
306
									multiSelects[$field_name] = element.value;
307
								}
308
							}
309
						}
310
					});
311
312
					// fix multiselects if any are found
313
					if(multiSelectsRemove.length){
314
315
						// remove all multiselects
316
						multiSelectsRemove.reverse();
317
						multiSelectsRemove.forEach(function(index) {
318
							$form_data.splice( index, 1 );
319
						});
320
321
						$ms_arr = [];
322
						// add multiselets back
323
						jQuery.each(multiSelects, function( index, value) {
324
							$ms_arr[$ms_arr.length] = {"name": "[]["+index+"]","value":value};
325
						});
326
						$form_data = $form_data.concat($ms_arr);
327
					}
328
329
330
331
					if($form_data ){
332
						$form_data.forEach(function(element) {
333
334
							if(element.value){
335
								$field_name = element.name.substr(element.name.indexOf("][") + 2);
336
								$field_name = $field_name.replace("]", "");
337
								$output = $output +" "+$field_name+'="'+element.value+'"';
338
339
							}
340
341
						});
342
					}
343
					$output = $output +"]";
344
					jQuery('#sd-shortcode-output').html($output);
345
				}
346
			</script>
347
			<?php
348
			$shortcode_insert_button_once = true;
349
		}
350
351
		public function widget_css() {
352
			ob_start();
353
			?>
354
			<style>
355
				/*body {display: none;}*/
356
				.sd-advanced-setting {
357
					display: none;
358
				}
359
360
				.sd-advanced-setting.sd-adv-show {
361
					display: block;
362
				}
363
364
				.sd-argument.sd-require-hide,
365
				.sd-advanced-setting.sd-require-hide {
366
					display: none;
367
				}
368
369
				button.sd-advanced-button {
370
					margin-right: 3px !important;
371
					font-size: 20px !important;
372
				}
373
			</style>
374
			<?php
375
			$output = ob_get_clean();
376
377
			/*
378
			 * We only add the <script> tags for code highlighting, so we strip them from the output.
379
			 */
380
381
			return str_replace( array(
382
				'<style>',
383
				'</style>'
384
			), '', $output );
385
		}
386
387
		public function widget_js() {
388
			ob_start();
389
			?>
390
			<script>
391
392
				/**
393
				 * Toggle advanced settings visibility.
394
				 */
395
				function sd_toggle_advanced($this) {
396
					var form = jQuery($this).parents('form,.form');
397
					form.find('.sd-advanced-setting').toggleClass('sd-adv-show');
398
					return false;// prevent form submit
399
				}
400
401
				/**
402
				 * Check a form to see what items shoudl be shown or hidden.
403
				 */
404
				function sd_show_hide(form) {
405
					console.log('show/hide');
406
					jQuery(form).find(".sd-argument").each(function () {
407
408
						var $element_require = jQuery(this).data('element_require');
409
410
						if ($element_require) {
411
412
							$element_require = $element_require.replace("&#039;", "'"); // replace single quotes
413
							$element_require = $element_require.replace("&quot;", '"'); // replace double quotes
414
415
							if (eval($element_require)) {
416
								jQuery(this).removeClass('sd-require-hide');
417
							} else {
418
								jQuery(this).addClass('sd-require-hide');
419
							}
420
						}
421
					});
422
				}
423
424
				/**
425
				 * Initialise widgets from the widgets screen.
426
				 */
427
				function sd_init_widgets($selector) {
428
					jQuery(".sd-show-advanced").each(function (index) {
429
						sd_init_widget(this,$selector);
430
					});
431
				}
432
433
				/**
434
				 * Initialise a individual widget.
435
				 */
436
				function sd_init_widget($this,$selector) {
437
					console.log($selector);
438
439
					if(!$selector){
440
						$selector = 'form';
441
					}
442
					// only run once.
443
					if (jQuery($this).data('sd-widget-enabled')) {
444
						return;
445
					} else {
446
						jQuery($this).data('sd-widget-enabled', true);
447
					}
448
449
					var $button = '<button 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>';
450
					var form = jQuery($this).parents('' + $selector + '');
451
452
					if (jQuery($this).val() == '1' && jQuery(form).find('.sd-advanced-button').length==0) {
453
						console.log('add advanced button');
454
455
						jQuery(form).find('.widget-control-save').after($button);
456
					}else{
457
						console.log('no advanced button');
458
						console.log(jQuery($this).val());
459
						console.log(jQuery(form).find('.sd-advanced-button').length);
460
461
					}
462
463
					// show hide on form change
464
					jQuery(form).change(function () {
465
						sd_show_hide(form);
466
					});
467
468
					// show hide on load
469
					sd_show_hide(form);
470
				}
471
472
				/**
473
				 * Init a customizer widget.
474
				 */
475
				function sd_init_customizer_widget(section){
476
					if (section.expanded) {
477
						section.expanded.bind(function (isExpanding) {
478
							if (isExpanding) {
479
								// is it a SD widget?
480
								if (jQuery(section.container).find('.sd-show-advanced').length) {
481
									// init the widget
482
									sd_init_widget(jQuery(section.container).find('.sd-show-advanced'),".form");
483
								}
484
							}
485
						});
486
					}
487
				}
488
489
				/**
490
				 * If on widgets screen.
491
				 */
492
				jQuery(function () {
493
					// if not in customizer.
494
					if (!wp.customize) {
495
						sd_init_widgets("form");
496
					}
497
498
499
					// init on widget added
500
					jQuery(document).on('widget-added', function(e, widget){
501
						console.log('widget added');
502
						// is it a SD widget?
503
						if (jQuery(widget).find('.sd-show-advanced').length) {
504
							// init the widget
505
							sd_init_widget(jQuery(widget).find('.sd-show-advanced'),"form");
506
						}
507
					});
508
509
					// inint on widget updated
510
					jQuery(document).on('widget-updated', function(e, widget){
511
						console.log('widget updated');
512
513
						// is it a SD widget?
514
						if (jQuery(widget).find('.sd-show-advanced').length) {
515
							// init the widget
516
							sd_init_widget(jQuery(widget).find('.sd-show-advanced'),"form");
517
						}
518
					});
519
520
				});
521
522
523
				/**
524
				 * We need to run this before jQuery is ready
525
				 */
526
				if (wp.customize) {
527
					wp.customize.bind('ready', function () {
528
529
						// init widgets on load
530
						wp.customize.control.each(function (section) {
531
							sd_init_customizer_widget(section);
532
						});
533
534
						// init widgets on add
535
						wp.customize.control.bind('add', function (section) {
536
							sd_init_customizer_widget(section);
537
						});
538
539
					});
540
541
				}
542
				<?php do_action( 'wp_super_duper_widget_js', $this ); ?>
543
			</script>
544
			<?php
545
			$output = ob_get_clean();
546
547
			/*
548
			 * We only add the <script> tags for code highlighting, so we strip them from the output.
549
			 */
550
551
			return str_replace( array(
552
				'<script>',
553
				'</script>'
554
			), '', $output );
555
		}
556
557
558
		/**
559
		 * Set the name from the argument key.
560
		 *
561
		 * @param $options
562
		 *
563
		 * @return mixed
564
		 */
565
		private function add_name_from_key( $options, $arguments = false ) {
566
			if ( ! empty( $options['arguments'] ) ) {
567
				foreach ( $options['arguments'] as $key => $val ) {
568
					$options['arguments'][ $key ]['name'] = $key;
569
				}
570
			} elseif ( $arguments && is_array( $options ) && ! empty( $options ) ) {
571
				foreach ( $options as $key => $val ) {
572
					$options[ $key ]['name'] = $key;
573
				}
574
			}
575
576
			return $options;
577
		}
578
579
		/**
580
		 * Register the parent shortcode.
581
		 *
582
		 * @since 2.0.0
583
		 */
584
		public function register_shortcode() {
585
			add_shortcode( $this->base_id, array( $this, 'shortcode_output' ) );
586
			add_action( 'wp_ajax_super_duper_output_shortcode', array( __CLASS__, 'render_shortcode' ) );
587
		}
588
589
		/**
590
		 * Render the shortcode via ajax so we can return it to Gutenberg.
591
		 *
592
		 * @since 2.0.0
593
		 */
594
		public static function render_shortcode() {
595
596
			check_ajax_referer( 'super_duper_output_shortcode', '_ajax_nonce', true );
597
			if ( ! current_user_can( 'manage_options' ) ) {
598
				wp_die();
599
			}
600
601
			// we might need the $post value here so lets set it.
602
			if ( isset( $_POST['post_id'] ) && $_POST['post_id'] ) {
603
				$post_obj = get_post( absint( $_POST['post_id'] ) );
604
				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...
605
					global $post;
606
					$post = $post_obj;
607
				}
608
			}
609
610
			if ( isset( $_POST['shortcode'] ) && $_POST['shortcode'] ) {
611
				$shortcode_name   = sanitize_title_with_dashes( $_POST['shortcode'] );
612
				$attributes_array = isset( $_POST['attributes'] ) && $_POST['attributes'] ? $_POST['attributes'] : array();
613
				$attributes       = '';
614
				if ( ! empty( $attributes_array ) ) {
615
					foreach ( $attributes_array as $key => $value ) {
616
						$attributes .= " " . sanitize_title_with_dashes( $key ) . "='" . wp_slash( $value ) . "' ";
617
					}
618
				}
619
620
				$shortcode = "[" . $shortcode_name . " " . $attributes . "]";
621
622
				echo do_shortcode( $shortcode );
623
624
			}
625
			wp_die();
626
		}
627
628
		/**
629
		 * Output the shortcode.
630
		 *
631
		 * @param array $args
632
		 * @param string $content
633
		 */
634
		public function shortcode_output( $args = array(), $content = '' ) {
635
			$args = self::argument_values( $args );
636
637
			// add extra argument so we know its a output to gutenberg
638
			//$args
639
			$args = $this->string_to_bool( $args );
640
641
642
			$calss = isset($this->options['widget_ops']['classname']) ? esc_attr($this->options['widget_ops']['classname']) : '';
643
644
			$calss = apply_filters( 'wp_super_duper_div_classname', $calss, $args, $this );
645
			$calss = apply_filters( 'wp_super_duper_div_classname_' . $this->base_id, $calss, $args, $this );
646
647
			$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...
648
			$attrs = apply_filters( 'wp_super_duper_div_attrs_' . $this->base_id, '', $args, $this );
649
650
			$shortcode_args = array();
651
			$output = '';
652
			$no_wrap = isset($this->options['no_wrap']) && $this->options['no_wrap'] ?  true : false;
653
			$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...
654
			if($main_content && !$no_wrap){
655
				// wrap the shortcode in a dive with the same class as the widget
656
				$output .= '<div class="'.$calss.'" ' . $attrs . '>';
657
				if(!empty($args['title'])){
658
					// if its a shortcode and there is a title try to grab the title wrappers
659
					$shortcode_args = array('before_title'=>'', 'after_title' => '');
660
					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...
661
						global $wp_registered_sidebars;
662
						if(!empty($wp_registered_sidebars)){
663
							foreach($wp_registered_sidebars as $sidebar){
664
								if(!empty($sidebar['before_title'])){
665
									$shortcode_args['before_title'] = $sidebar['before_title'];
666
									$shortcode_args['after_title'] = $sidebar['after_title'];
667
									break;
668
								}
669
							}
670
						}
671
					}
672
					$output .= $this->output_title($shortcode_args,$args);
673
				}
674
				$output .= $main_content;
675
				$output .= '</div>';
676
			}elseif($main_content && $no_wrap){
677
				$output .= $main_content;
678
			}
679
680
			return $output;
681
		}
682
683
684
		/**
685
		 * Sometimes booleans values can be turned to strings, so we fix that.
686
		 *
687
		 * @param $options
688
		 *
689
		 * @return mixed
690
		 */
691
		public function string_to_bool( $options ) {
692
			// convert bool strings to booleans
693
			foreach ( $options as $key => $val ) {
694
				if ( $val == 'false' ) {
695
					$options[ $key ] = false;
696
				} elseif ( $val == 'true' ) {
697
					$options[ $key ] = true;
698
				}
699
			}
700
701
			return $options;
702
		}
703
704
		/**
705
		 * Get the argument values that are also filterable.
706
		 *
707
		 * @param $instance
708
		 *
709
		 * @return array
710
		 */
711
		public function argument_values( $instance ) {
712
			$argument_values = array();
713
714
			// set widget instance
715
			$this->instance = $instance;
716
717
			if ( empty( $this->arguments ) ) {
718
				$this->arguments = $this->get_arguments();
719
			}
720
721
			if ( ! empty( $this->arguments ) ) {
722
				foreach ( $this->arguments as $key => $args ) {
723
					// set the input name from the key
724
					$args['name'] = $key;
725
					//
726
					$argument_values[ $key ] = isset( $instance[ $key ] ) ? $instance[ $key ] : '';
727
					if ( $argument_values[ $key ] == '' && isset( $args['default'] ) ) {
728
						$argument_values[ $key ] = $args['default'];
729
					}
730
				}
731
			}
732
733
			return $argument_values;
734
		}
735
736
		/**
737
		 * Set arguments in super duper.
738
		 *
739
		 * @since 2.0.0
740
		 *
741
		 * @return array Set arguments.
742
		 */
743
		public function set_arguments() {
744
			return $this->arguments;
745
		}
746
747
		/**
748
		 * Get arguments in super duper.
749
		 *
750
		 * @since 2.0.0
751
		 *
752
		 * @return array Get arguments.
753
		 */
754
		public function get_arguments() {
755
			if ( empty( $this->arguments ) ) {
756
				$this->arguments =  $this->set_arguments();
757
			}
758
759
			$this->arguments = apply_filters('wp_super_duper_arguments',$this->arguments,$this->options, $this->instance);
760
			$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...
761
762
763
			return $this->arguments;
764
		}
765
766
		/**
767
		 * This is the main output class for all 3 items, widget, shortcode and block, it is extended in the calling class.
768
		 *
769
		 * @param array $args
770
		 * @param array $widget_args
771
		 * @param string $content
772
		 */
773
		public function output( $args = array(), $widget_args = array(), $content = '' ) {
774
775
		}
776
777
		/**
778
		 * Add the dyanmic block code inline when the wp-block in enqueued.
779
		 */
780
		public function register_block() {
781
			wp_add_inline_script( 'wp-blocks', $this->block() );
782
		}
783
784
785
		/**
786
		 * Check if we need to show advanced options.
787
		 *
788
		 * @return bool
789
		 */
790
		public function block_show_advanced() {
791
			//$this->arguments
792
			$show      = false;
793
			$arguments = $this->arguments;
794
795
			if(empty($arguments)){
796
				$arguments = $this->get_arguments();
797
			}
798
799
			if ( ! empty( $arguments ) ) {
800
				foreach ( $arguments as $argument ) {
801
					if ( isset( $argument['advanced'] ) && $argument['advanced'] ) {
802
						$show = true;
803
					}
804
				}
805
			}
806
807
			return $show;
808
		}
809
810
811
		/**
812
		 * Output the JS for building the dynamic Guntenberg block.
813
		 *
814
		 * @return mixed
815
		 */
816
		public function block() {
817
			ob_start();
818
			?>
819
			<script>
820
				/**
821
				 * BLOCK: Basic
822
				 *
823
				 * Registering a basic block with Gutenberg.
824
				 * Simple block, renders and saves the same content without any interactivity.
825
				 *
826
				 * Styles:
827
				 *        editor.css — Editor styles for the block.
828
				 *        style.css  — Editor & Front end styles for the block.
829
				 */
830
				(function () {
831
					var __ = wp.i18n.__; // The __() for internationalization.
832
					var el = wp.element.createElement; // The wp.element.createElement() function to create elements.
833
					var editable = wp.blocks.Editable;
834
					var blocks = wp.blocks;
835
					var registerBlockType = wp.blocks.registerBlockType; // The registerBlockType() to register blocks.
836
					var is_fetching = false;
837
					var prev_attributes = [];
838
839
					/**
840
					 * Register Basic Block.
841
					 *
842
					 * Registers a new block provided a unique name and an object defining its
843
					 * behavior. Once registered, the block is made available as an option to any
844
					 * editor interface where blocks are implemented.
845
					 *
846
					 * @param  {string}   name     Block name.
847
					 * @param  {Object}   settings Block settings.
848
					 * @return {?WPBlock}          The block, if it has been successfully
849
					 *                             registered; otherwise `undefined`.
850
					 */
851
					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.
852
						title: '<?php echo $this->options['name'];?>', // Block title.
853
						description: '<?php echo esc_attr( $this->options['widget_ops']['description'] )?>', // Block title.
854
						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/.
855
						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.
856
						<?php if ( isset( $this->options['block-keywords'] ) ) {
857
						echo "keywords : " . $this->options['block-keywords'] . ",";
858
					}?>
859
860
						<?php
861
862
						$show_advanced = $this->block_show_advanced();
863
864
						$show_alignment = false;
865
866
						if ( ! empty( $this->arguments ) ) {
867
							echo "attributes : {";
868
869
							if ( $show_advanced ) {
870
								echo "show_advanced: {";
871
								echo "	type: 'boolean',";
872
								echo "  default: false,";
873
								echo "},";
874
							}
875
876
							foreach ( $this->arguments as $key => $args ) {
877
878
								// set if we should show alignment
879
								if ( $key == 'alignment' ) {
880
									$show_alignment = true;
881
								}
882
883
								$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...
884
885
								if ( $args['type'] == 'checkbox' ) {
886
									$type    = 'boolean';
887
									$default = isset( $args['default'] ) && "'" . $args['default'] . "'" ? 'true' : 'false';
888
								} elseif ( $args['type'] == 'number' ) {
889
									$type    = 'number';
890
									$default = isset( $args['default'] ) ? "'" . $args['default'] . "'" : "''";
891
								} elseif ( $args['type'] == 'select' && ! empty( $args['multiple'] ) ) {
892
									$type    = 'array';
893
									if(is_array($args['default'])){
894
										$default = isset( $args['default'] ) ? "['" . implode("','", $args['default']) . "']" : "[]";
895 View Code Duplication
									}else{
896
										$default = isset( $args['default'] ) ? "'" . $args['default'] . "'" : "''";
897
									}
898
								} elseif ( $args['type'] == 'multiselect' ) {
899
									$type    = 'array';
900
									$default = isset( $args['default'] ) ? "'" . $args['default'] . "'" : "''";
901 View Code Duplication
								} else {
902
									$type    = 'string';
903
									$default = isset( $args['default'] ) ? "'" . $args['default'] . "'" : "''";
904
								}
905
								echo $key . " : {";
906
								echo "type : '$type',";
907
								echo "default : $default,";
908
								echo "},";
909
							}
910
911
							echo "content : {type : 'string',default: 'Please select the attributes in the block settings'},";
912
913
							echo "},";
914
915
						}
916
917
						?>
918
919
						// The "edit" property must be a valid function.
920
						edit: function (props) {
921
922
							var content = props.attributes.content;
923
924
							function onChangeContent() {
925
926
								if (!is_fetching && prev_attributes[props.id] != props.attributes) {
927
928
									//console.log(props);
929
930
									is_fetching = true;
931
									var data = {
932
										'action': 'super_duper_output_shortcode',
933
										'shortcode': '<?php echo $this->options['base_id'];?>',
934
										'attributes': props.attributes,
935
										'post_id': <?php global $post; if ( isset( $post->ID ) ) {
936
										echo $post->ID;
937
									}?>,
938
										'_ajax_nonce': '<?php echo wp_create_nonce( 'super_duper_output_shortcode' );?>'
939
									};
940
941
									jQuery.post(ajaxurl, data, function (response) {
942
										return response;
943
									}).then(function (env) {
944
										props.setAttributes({content: env});
945
										is_fetching = false;
946
										prev_attributes[props.id] = props.attributes;
947
									});
948
949
950
								}
951
952
								return props.attributes.content;
953
954
							}
955
956
957
							return [
958
959
								el(wp.editor.BlockControls, {key: 'controls'},
960
961
									<?php if($show_alignment){?>
962
									el(
963
										wp.editor.AlignmentToolbar,
964
										{
965
											value: props.attributes.alignment,
966
											onChange: function (alignment) {
967
												props.setAttributes({alignment: alignment})
968
											}
969
										}
970
									)
971
									<?php }?>
972
973
								),
974
975
								el(wp.editor.InspectorControls, {key: 'inspector'},
976
977
									<?php
978
979
									if(! empty( $this->arguments )){
980
981
									if ( $show_advanced ) {
982
									?>
983
									el(
984
										wp.components.ToggleControl,
985
										{
986
											label: 'Show Advanced Settings?',
987
											checked: props.attributes.show_advanced,
988
											onChange: function (show_advanced) {
989
												props.setAttributes({show_advanced: !props.attributes.show_advanced})
990
											}
991
										}
992
									),
993
									<?php
994
995
									}
996
997
									foreach($this->arguments as $key => $args){
998
									$custom_attributes = !empty($args['custom_attributes']) ? $this->array_to_attributes($args['custom_attributes']) : '';
999
									$options = '';
1000
									$extra = '';
1001
									$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...
1002
									$onchange = "props.setAttributes({ $key: $key } )";
1003
									$value = "props.attributes.$key";
1004
									$text_type = array( 'text', 'password', 'number', 'email', 'tel', 'url', 'color' );
1005
									if ( in_array( $args['type'], $text_type ) ) {
1006
										$type = 'TextControl';
1007
									} elseif ( $args['type'] == 'checkbox' ) {
1008
										$type = 'CheckboxControl';
1009
										$extra .= "checked: props.attributes.$key,";
1010
										$onchange = "props.setAttributes({ $key: ! props.attributes.$key } )";
1011
									} elseif ( $args['type'] == 'select' || $args['type'] == 'multiselect' ) {
1012
										$type = 'SelectControl';
1013
										if ( ! empty( $args['options'] ) ) {
1014
											$options .= "options  : [";
1015
											foreach ( $args['options'] as $option_val => $option_label ) {
1016
												$options .= "{ value : '" . esc_attr( $option_val ) . "',     label : '" . esc_attr( $option_label ) . "'     },";
1017
											}
1018
											$options .= "],";
1019
										}
1020
										if ( isset( $args['multiple'] ) && $args['multiple'] ) { //@todo multiselect does not work at the moment: https://github.com/WordPress/gutenberg/issues/5550
1021
											$extra .= ' multiple: true, ';
1022
											//$onchange = "props.setAttributes({ $key: ['edit'] } )";
1023
											//$value = "['edit', 'delete']";
1024
										}
1025
									} elseif ( $args['type'] == 'alignment' ) {
1026
										$type = 'AlignmentToolbar'; // @todo this does not seem to work but cant find a example
1027
									} else {
1028
										continue;// if we have not implemented the control then don't break the JS.
1029
									}
1030
1031
									// add show only if advanced
1032
									if ( ! empty( $args['advanced'] ) ) {
1033
										echo "props.attributes.show_advanced && ";
1034
									}
1035
									// add setting require if defined
1036
									if ( ! empty( $args['element_require'] ) ) {
1037
										echo $this->block_props_replace( $args['element_require'], true ) . " && ";
1038
									}
1039
									?>
1040
									el(
1041
										wp.components.<?php echo esc_attr( $type );?>,
1042
										{
1043
											label: '<?php echo esc_attr( $args['title'] );?>',
1044
											help: '<?php if ( isset( $args['desc'] ) ) {
1045
												echo esc_attr( $args['desc'] );
1046
											}?>',
1047
											value: <?php echo $value;?>,
1048
											<?php if ( $type == 'TextControl' && $args['type'] != 'text' ) {
1049
											echo "type: '" . esc_attr( $args['type'] ) . "',";
1050
										}?>
1051
											<?php if ( ! empty( $args['placeholder'] ) ) {
1052
											echo "placeholder: '" . esc_attr( $args['placeholder'] ) . "',";
1053
										}?>
1054
											<?php echo $options;?>
1055
											<?php echo $extra;?>
1056
											<?php echo $custom_attributes;?>
1057
											onChange: function ( <?php echo $key;?> ) {
1058
												<?php echo $onchange;?>
1059
											}
1060
										}
1061
									),
1062
									<?php
1063
									}
1064
									}
1065
									?>
1066
1067
								),
1068
1069
								<?php
1070
								// If the user sets block-output array then build it
1071
								if ( ! empty( $this->options['block-output'] ) ) {
1072
								$this->block_element( $this->options['block-output'] );
1073
							}else{
1074
								// if no block-output is set then we try and get the shortcode html output via ajax.
1075
								?>
1076
								el('div', {
1077
									dangerouslySetInnerHTML: {__html: onChangeContent()},
1078
									className: props.className,
1079
									style: {'min-height': '30px'}
1080
								})
1081
								<?php
1082
								}
1083
								?>
1084
							]; // end return
1085
						},
1086
1087
						// The "save" property must be specified and must be a valid function.
1088
						save: function (props) {
1089
1090
							console.log(props);
1091
1092
1093
							var attr = props.attributes;
1094
							var align = '';
1095
1096
							// build the shortcode.
1097
							var content = "[<?php echo $this->options['base_id'];?>";
1098
							<?php
1099
1100
							if(! empty( $this->arguments )){
1101
							foreach($this->arguments as $key => $args){
1102
							?>
1103
							if (attr.hasOwnProperty("<?php echo esc_attr( $key );?>")) {
1104
								content += " <?php echo esc_attr( $key );?>='" + attr.<?php echo esc_attr( $key );?>+ "' ";
1105
							}
1106
							<?php
1107
							}
1108
							}
1109
1110
							?>
1111
							content += "]";
1112
1113
1114
							// @todo should we add inline style here or just css classes?
1115
							if (attr.alignment) {
1116
								if (attr.alignment == 'left') {
1117
									align = 'alignleft';
1118
								}
1119
								if (attr.alignment == 'center') {
1120
									align = 'aligncenter';
1121
								}
1122
								if (attr.alignment == 'right') {
1123
									align = 'alignright';
1124
								}
1125
							}
1126
1127
							console.log(content);
1128
							return el('div', {dangerouslySetInnerHTML: {__html: content}, className: align});
1129
1130
						}
1131
					});
1132
				})();
1133
			</script>
1134
			<?php
1135
			$output = ob_get_clean();
1136
1137
			/*
1138
			 * We only add the <script> tags for code highlighting, so we strip them from the output.
1139
			 */
1140
1141
			return str_replace( array(
1142
				'<script>',
1143
				'</script>'
1144
			), '', $output );
1145
		}
1146
1147
		/**
1148
		 * Convert an array of attributes to block string.
1149
		 *
1150
		 * @todo there is prob a faster way to do this, also we could add some validation here.
1151
		 * @param $custom_attributes
1152
		 *
1153
		 * @return string
1154
		 */
1155
		public function array_to_attributes($custom_attributes, $html = false){
1156
			$attributes = '';
1157
			if(!empty($custom_attributes)){
1158
1159
				if($html){
1160
					foreach($custom_attributes as $key => $val){
1161
						$attributes .= " $key='$val' ";
1162
					}
1163
				}else{
1164
					foreach($custom_attributes as $key => $val){
1165
						$attributes .= "'$key': '$val',";
1166
					}
1167
				}
1168
			}
1169
1170
			return $attributes;
1171
		}
1172
1173
1174
		/**
1175
		 * A self looping function to create the output for JS block elements.
1176
		 *
1177
		 * This is what is output in the WP Editor visual view.
1178
		 *
1179
		 * @param $args
1180
		 */
1181
		public function block_element( $args ) {
1182
1183
1184
			if ( ! empty( $args ) ) {
1185
				foreach ( $args as $element => $new_args ) {
1186
1187
					if ( is_array( $new_args ) ) { // its an element
1188
1189
1190
						if ( isset( $new_args['element'] ) ) {
1191
1192
							//print_r($new_args);
1193
1194 View Code Duplication
							if ( isset( $new_args['element_require'] ) ) {
1195
								echo str_replace( array(
1196
										"'+",
1197
										"+'"
1198
									), '', $this->block_props_replace( $new_args['element_require'] ) ) . " &&  ";
1199
								unset( $new_args['element_require'] );
1200
							}
1201
1202
							echo "\n el( '" . $new_args['element'] . "', {";
1203
1204
							// get the attributes
1205
							foreach ( $new_args as $new_key => $new_value ) {
1206
1207
1208
								if ( $new_key == 'element' || $new_key == 'content' || $new_key == 'element_require' || $new_key == 'element_repeat' || is_array( $new_value ) ) {
1209
									// do nothing
1210
								} else {
1211
									echo $this->block_element( array( $new_key => $new_value ) );
1212
								}
1213
							}
1214
1215
							echo "},";// end attributes
1216
1217
							// get the content
1218
							$first_item = 0;
1219
							foreach ( $new_args as $new_key => $new_value ) {
1220
								if ( $new_key === 'content' || is_array( $new_value ) ) {
1221
									//echo ",".$first_item;// separate the children
1222
1223
1224
									if ( $first_item > 0 ) {
1225
										//echo ",";// separate the children
1226
									} else {
1227
										//echo '####'.$first_item;
1228
									}
1229
1230
									if ( $new_key === 'content' ) {
1231
										//print_r($new_args);
1232
										echo "'" . $this->block_props_replace( $new_value ) . "'";
1233
									}
1234
1235
									if ( is_array( $new_value ) ) {
1236
1237 View Code Duplication
										if ( isset( $new_value['element_require'] ) ) {
1238
											echo str_replace( array(
1239
													"'+",
1240
													"+'"
1241
												), '', $this->block_props_replace( $new_value['element_require'] ) ) . " &&  ";
1242
											unset( $new_value['element_require'] );
1243
										}
1244
1245
										if ( isset( $new_value['element_repeat'] ) ) {
1246
											$x = 1;
1247
											while ( $x <= absint( $new_value['element_repeat'] ) ) {
1248
												$this->block_element( array( '' => $new_value ) );
1249
												$x ++;
1250
											}
1251
										} else {
1252
											$this->block_element( array( '' => $new_value ) );
1253
										}
1254
										//print_r($new_value);
1255
									}
1256
									$first_item ++;
1257
								}
1258
							}
1259
1260
							echo ")";// end content
1261
1262
							//if($first_item>0){
1263
							echo ", \n";
1264
							//}
1265
1266
1267
						}
1268
						//$this->block_element($new_args);
1269
					} else {
1270
1271
						if ( substr( $element, 0, 3 ) === "if_" ) {
1272
							echo str_replace( "if_", "", $element ) . ": " . $this->block_props_replace( $new_args, true ) . ",";
1273
						} elseif ( $element == 'style' ) {
1274
							echo $element . ": " . $this->block_props_replace( $new_args ) . ",";
1275
						} else {
1276
							echo $element . ": '" . $this->block_props_replace( $new_args ) . "',";
1277
						}
1278
1279
					}
1280
1281
1282
				}
1283
			}
1284
		}
1285
1286
		/**
1287
		 * Replace block attributes placeholders with the proper naming.
1288
		 *
1289
		 * @param $string
1290
		 *
1291
		 * @return mixed
1292
		 */
1293
		public function block_props_replace( $string, $no_wrap = false ) {
1294
1295
			if ( $no_wrap ) {
1296
				$string = str_replace( array( "[%", "%]" ), array( "props.attributes.", "" ), $string );
1297
			} else {
1298
				$string = str_replace( array( "[%", "%]" ), array( "'+props.attributes.", "+'" ), $string );
1299
			}
1300
1301
			return $string;
1302
		}
1303
1304
		/**
1305
		 * Outputs the content of the widget
1306
		 *
1307
		 * @param array $args
1308
		 * @param array $instance
1309
		 */
1310
		public function widget( $args, $instance ) {
1311
			// outputs the content of the widget
1312
1313
			// get the filtered values
1314
			$argument_values = $this->argument_values( $instance );
1315
			$argument_values = $this->string_to_bool( $argument_values );
1316
			$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...
1317
1318
			if ( $output ) {
1319
				// Before widget
1320
				$before_widget = $args['before_widget'];
1321
				$before_widget = apply_filters( 'wp_super_duper_before_widget', $before_widget, $args, $instance, $this );
1322
				$before_widget = apply_filters( 'wp_super_duper_before_widget_' . $this->base_id, $before_widget, $args, $instance, $this );
1323
1324
				// After widget
1325
				$after_widget = $args['after_widget'];
1326
				$after_widget = apply_filters( 'wp_super_duper_after_widget', $after_widget, $args, $instance, $this );
1327
				$after_widget = apply_filters( 'wp_super_duper_after_widget_' . $this->base_id, $after_widget, $args, $instance, $this );
1328
1329
				echo $before_widget;
1330
				echo $this->output_title($args, $instance);
1331
				echo $output;
1332
				echo $after_widget;
1333
			}
1334
		}
1335
1336
		/**
1337
		 * Output the super title.
1338
		 *
1339
		 * @param $args
1340
		 * @param array $instance
1341
		 *
1342
		 * @return string
1343
		 */
1344
		public function output_title($args, $instance = array()){
1345
			$output = '';
1346
			if ( ! empty( $instance['title'] ) ) {
1347
				/** This filter is documented in wp-includes/widgets/class-wp-widget-pages.php */
1348
				$title = apply_filters( 'widget_title', $instance['title'], $instance, $this->id_base );
1349
				$output = $args['before_title'] . $title . $args['after_title'];
1350
			}
1351
			return $output;
1352
		}
1353
1354
		/**
1355
		 * Outputs the options form inputs for the widget.
1356
		 *
1357
		 * @param array $instance The widget options.
1358
		 */
1359
		public function form( $instance ) {
1360
1361
			// set widget instance
1362
			$this->instance = $instance;
1363
1364
			// set it as a SD widget
1365
			echo $this->widget_advanced_toggle();
1366
1367
1368
			echo "<p>" . esc_attr( $this->options['widget_ops']['description'] ) . "</p>";
1369
			$arguments = $this->get_arguments();
1370
//			print_r($instance );
1371
//			echo '###';
1372
//			print_r($arguments  );
1373
1374
			if ( is_array( $arguments ) ) {
1375
				foreach ( $arguments as $key => $args ) {
1376
					$this->widget_inputs( $args, $instance );
1377
				}
1378
			}
1379
		}
1380
1381
		/**
1382
		 * Get the hidden input that when added makes the advanced button show on widget settings.
1383
		 *
1384
		 * @return string
1385
		 */
1386
		public function widget_advanced_toggle() {
1387
1388
			$output = '';
1389
			if ( $this->block_show_advanced() ) {
1390
				$val = 1;
1391
			} else {
1392
				$val = 0;
1393
			}
1394
			if($val){
1395
//				$output .=  '<span class="sd-advanced-button-container"><button 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></span>';
1396
			}
1397
1398
			$output .= "<input type='hidden'  class='sd-show-advanced' value='$val' />";
1399
1400
1401
1402
1403
			return $output;
1404
1405
		}
1406
1407
		/**
1408
		 * Convert require element.
1409
		 *
1410
		 * @since 2.0.0
1411
		 *
1412
		 * @param string $input Input element.
1413
		 * @return string $output
1414
		 */
1415
		public function convert_element_require( $input ) {
1416
1417
			$input = str_replace( "'", '"', $input );// we only want double quotes
1418
1419
			$output = esc_attr( str_replace( array( "[%", "%]" ), array(
1420
				"jQuery(form).find('[data-argument=\"",
1421
				"\"]').find('input,select').val()"
1422
			), $input ) );
1423
1424
1425
			return $output;
1426
		}
1427
1428
		/**
1429
		 * Builds the inputs for the widget options.
1430
		 *
1431
		 * @param $args
1432
		 * @param $instance
1433
		 */
1434
		public function widget_inputs( $args, $instance ) {
1435
1436
//print_r($instance );echo '###';
1437
//print_r($args );
1438
			$class           = "";
1439
			$element_require = "";
1440
			$custom_attributes = "";
1441
1442
			// get value
1443
			if ( isset( $instance[ $args['name'] ] ) ) {
1444
				$value = $instance[ $args['name'] ];
1445
			} elseif ( ! isset( $instance[ $args['name'] ] ) && ! empty( $args['default'] ) ) {
1446
				$value = is_array($args['default']) ? array_map("esc_html",$args['default']) : esc_html( $args['default'] );
1447
			} else {
1448
				$value = '';
1449
			}
1450
1451
			// get placeholder
1452 View Code Duplication
			if ( ! empty( $args['placeholder'] ) ) {
1453
				$placeholder = "placeholder='" . esc_html( $args['placeholder'] ) . "'";
1454
			} else {
1455
				$placeholder = '';
1456
			}
1457
1458
			// get if advanced
1459
			if ( isset( $args['advanced'] ) && $args['advanced'] ) {
1460
				$class .= " sd-advanced-setting ";
1461
			}
1462
1463
			// element_require
1464
			if ( isset( $args['element_require'] ) && $args['element_require'] ) {
1465
				$element_require = $args['element_require'];
1466
			}
1467
1468
			// custom_attributes
1469
			if( isset( $args['custom_attributes']) && $args['custom_attributes']){
1470
				$custom_attributes = $this->array_to_attributes($args['custom_attributes'],true);
1471
			}
1472
1473
1474
1475
1476
			// before wrapper
1477
			?>
1478
			<p class="sd-argument <?php echo esc_attr( $class ); ?>"
1479
			   data-argument='<?php echo esc_attr( $args['name'] ); ?>'
1480
			   data-element_require='<?php if ( $element_require ) {
1481
				   echo $this->convert_element_require( $element_require );
1482
			   } ?>'
1483
			>
1484
				<?php
1485
1486
				switch ( $args['type'] ) {
1487
					//array('text','password','number','email','tel','url','color')
1488
					case "text":
1489
					case "password":
1490
					case "number":
1491
					case "email":
1492
					case "tel":
1493
					case "url":
1494 View Code Duplication
					case "color":
1495
						?>
1496
						<label
1497
							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>
1498
						<input <?php echo $placeholder; ?> class="widefat"
1499
							<?php echo $custom_attributes;?>
1500
							                               id="<?php echo esc_attr( $this->get_field_id( $args['name'] ) ); ?>"
1501
							                               name="<?php echo esc_attr( $this->get_field_name( $args['name'] ) ); ?>"
1502
							                               type="<?php echo esc_attr( $args['type'] ); ?>"
1503
							                               value="<?php echo esc_attr( $value ); ?>">
1504
						<?php
1505
1506
						break;
1507
					case "select":
1508
						$multiple = isset( $args['multiple'] ) && $args['multiple']  ? true : false;
1509
						if($multiple){if(empty($value)){$value = array();}}
1510
						?>
1511
						<label
1512
							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>
1513
						<select <?php echo $placeholder; ?> class="widefat"
1514
							<?php echo $custom_attributes;?>
1515
							                                id="<?php echo esc_attr( $this->get_field_id( $args['name'] ) ); ?>"
1516
							                                name="<?php echo esc_attr( $this->get_field_name( $args['name'] ) ); if($multiple){echo "[]";}?>"
1517
							<?php if ($multiple) {
1518
								echo "multiple";
1519
							} //@todo not implemented yet due to gutenberg not supporting it
1520
							?>
1521
						>
1522
							<?php
1523
1524
1525
							if ( ! empty( $args['options'] ) ) {
1526
								foreach ( $args['options'] as $val => $label ) {
1527
//									print_r($value);
1528
//									echo '@@@'.print_r($val,true),'@@@';
1529
//									echo '###'.$value.'###';
1530
									if ($multiple) {$selected = in_array($val,$value) ? 'selected="selected"' : ''; }else{$selected = selected( $value, $val, false );}
1531
									echo "<option value='$val' " . $selected . ">$label</option>";
1532
								}
1533
							}
1534
							?>
1535
						</select>
1536
						<?php
1537
						break;
1538 View Code Duplication
					case "checkbox":
1539
						?>
1540
						<input <?php echo $placeholder; ?>
1541
							<?php checked( 1, $value, true ) ?>
1542
							<?php echo $custom_attributes;?>
1543
							class="widefat" id="<?php echo esc_attr( $this->get_field_id( $args['name'] ) ); ?>"
1544
							name="<?php echo esc_attr( $this->get_field_name( $args['name'] ) ); ?>" type="checkbox"
1545
							value="1">
1546
						<label
1547
							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>
1548
						<?php
1549
						break;
1550
					case "hidden":
1551
						?>
1552
						<input id="<?php echo esc_attr( $this->get_field_id( $args['name'] ) ); ?>"
1553
						       name="<?php echo esc_attr( $this->get_field_name( $args['name'] ) ); ?>" type="hidden"
1554
						       value="<?php echo esc_attr( $value ); ?>">
1555
						<?php
1556
						break;
1557
					default:
1558
						echo "No input type found!"; // @todo we need to add more input types.
1559
				}
1560
1561
				// after wrapper
1562
				?>
1563
			</p>
1564
			<?php
1565
1566
		}
1567
1568
1569
		/**
1570
		 * Get the widget input description html.
1571
		 *
1572
		 * @param $args
1573
		 *
1574
		 * @return string
1575
		 * @todo, need to make its own tooltip script
1576
		 */
1577
		public function widget_field_desc( $args ) {
1578
1579
			$description = '';
1580
			if ( isset( $args['desc'] ) && $args['desc'] ) {
1581
				if ( isset( $args['desc_tip'] ) && $args['desc_tip'] ) {
1582
					$description = $this->desc_tip( $args['desc'] );
1583
				} else {
1584
					$description = '<span class="description">' . wp_kses_post( $args['desc'] ) . '</span>';
1585
				}
1586
			}
1587
1588
			return $description;
1589
		}
1590
1591
1592
		/**
1593
		 * Get the tool tip html.
1594
		 *
1595
		 * @param $tip
1596
		 * @param bool $allow_html
1597
		 *
1598
		 * @return string
1599
		 */
1600
		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...
1601
			if ( $allow_html ) {
1602
				$tip = $this->sanitize_tooltip( $tip );
1603
			} else {
1604
				$tip = esc_attr( $tip );
1605
			}
1606
1607
			return '<span class="gd-help-tip dashicons dashicons-editor-help" title="' . $tip . '"></span>';
1608
		}
1609
1610
		/**
1611
		 * Sanitize a string destined to be a tooltip.
1612
		 *
1613
		 * @param string $var
1614
		 *
1615
		 * @return string
1616
		 */
1617
		public function sanitize_tooltip( $var ) {
1618
			return htmlspecialchars( wp_kses( html_entity_decode( $var ), array(
1619
				'br'     => array(),
1620
				'em'     => array(),
1621
				'strong' => array(),
1622
				'small'  => array(),
1623
				'span'   => array(),
1624
				'ul'     => array(),
1625
				'li'     => array(),
1626
				'ol'     => array(),
1627
				'p'      => array(),
1628
			) ) );
1629
		}
1630
1631
		/**
1632
		 * Processing widget options on save
1633
		 *
1634
		 * @param array $new_instance The new options
1635
		 * @param array $old_instance The previous options
1636
		 *
1637
		 * @return array
1638
		 * @todo we should add some sanitation here.
1639
		 */
1640
		public function update( $new_instance, $old_instance ) {
1641
//			print_r($new_instance);
1642
//			print_r($old_instance);
1643
//			exit;
1644
			//save the widget
1645
			$instance = array_merge( (array) $old_instance, (array) $new_instance );
1646
1647
			// set widget instance
1648
			$this->instance = $instance;
1649
1650
			if(empty($this->arguments)){
1651
				$this->get_arguments();
1652
			}
1653
1654
1655
//			print_r($new_instance);
1656
//			print_r($old_instance);
1657
//			print_r($instance);
1658
//			print_r($this->arguments);
1659
//			exit;
1660
1661
			// check for checkboxes
1662
			if ( ! empty( $this->arguments ) ) {
1663
				foreach ( $this->arguments as $argument ) {
1664
					if ( isset( $argument['type'] ) && $argument['type'] == 'checkbox' && ! isset( $new_instance[ $argument['name'] ] ) ) {
1665
						$instance[ $argument['name'] ] = '0';
1666
					}
1667
				}
1668
			}
1669
1670
			return $instance;
1671
		}
1672
1673
	}
1674
1675
}
1676