Passed
Push — master ( fd90c2...9b7fbb )
by Brian
05:32
created

WP_Super_Duper::__construct()   F

Complexity

Conditions 17
Paths 1440

Size

Total Lines 96
Code Lines 49

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 17
eloc 49
nc 1440
nop 1
dl 0
loc 96
rs 1.0499
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.16 change log moved to file change-log.txt - CHANGED
16
	 * @ver 1.1.1
17
	 */
18
	class WP_Super_Duper extends WP_Widget {
19
20
		public $version = "1.1.1";
21
		public $font_awesome_icon_version = "5.11.2";
22
		public $block_code;
23
		public $options;
24
		public $base_id;
25
		public $settings_hash;
26
		public $arguments = array();
27
		public $instance = array();
28
		private $class_name;
29
30
		/**
31
		 * The relative url to the current folder.
32
		 *
33
		 * @var string
34
		 */
35
		public $url = '';
36
37
		/**
38
		 * Take the array options and use them to build.
39
		 */
40
		public function __construct( $options ) {
41
			global $sd_widgets;
42
43
			$sd_widgets[ $options['base_id'] ] = array(
44
				'name'       => $options['name'],
45
				'class_name' => $options['class_name'],
46
				'output_types' => !empty($options['output_types']) ? $options['output_types'] : array()
47
			);
48
			$this->base_id                     = $options['base_id'];
49
			// lets filter the options before we do anything
50
			$options       = apply_filters( "wp_super_duper_options", $options );
51
			$options       = apply_filters( "wp_super_duper_options_{$this->base_id}", $options );
52
			$options       = $this->add_name_from_key( $options );
53
			$this->options = $options;
54
55
			$this->base_id   = $options['base_id'];
56
			$this->arguments = isset( $options['arguments'] ) ? $options['arguments'] : array();
57
58
            // nested blocks can't work as a widget
59
            if(!empty($this->options['nested-block'])){
60
                if(empty($this->options['output_types'])){
61
                    $this->options['output_types'] = array('shortcode','block');
62
                }elseif (($key = array_search('widget', $this->options['output_types'])) !== false) {
63
                    unset($this->options['output_types'][$key]);
64
                }
65
            }
66
67
			// init parent
68
			if(empty($this->options['output_types']) || in_array('widget',$this->options['output_types'])){
69
                parent::__construct( $options['base_id'], $options['name'], $options['widget_ops'] );
70
			}
71
72
73
			if ( isset( $options['class_name'] ) ) {
74
				// register widget
75
				$this->class_name = $options['class_name'];
76
77
				// register shortcode, this needs to be done even for blocks and widgets
78
                $this->register_shortcode();
79
80
81
				// Fusion Builder (avada) support
82
				if ( function_exists( 'fusion_builder_map' ) ) {
83
					add_action( 'init', array( $this, 'register_fusion_element' ) );
84
				}
85
86
				// register block
87
				if(empty($this->options['output_types']) || in_array('block',$this->options['output_types'])){
88
				    add_action( 'admin_enqueue_scripts', array( $this, 'register_block' ) );
89
                }
90
			}
91
92
			// add the CSS and JS we need ONCE
93
			global $sd_widget_scripts;
94
95
			if ( ! $sd_widget_scripts ) {
96
				wp_add_inline_script( 'admin-widgets', $this->widget_js() );
97
				wp_add_inline_script( 'customize-controls', $this->widget_js() );
98
				wp_add_inline_style( 'widgets', $this->widget_css() );
99
100
				// maybe add elementor editor styles
101
				add_action( 'elementor/editor/after_enqueue_styles', array( $this, 'elementor_editor_styles' ) );
102
103
				$sd_widget_scripts = true;
104
105
				// add shortcode insert button once
106
				add_action( 'media_buttons', array( $this, 'shortcode_insert_button' ) );
107
				// generatepress theme sections compatibility
108
				if ( function_exists( 'generate_sections_sections_metabox' ) ) {
109
					add_action( 'generate_sections_metabox', array( $this, 'shortcode_insert_button_script' ) );
110
				}
111
				/* Load script on Divi theme builder page */
112
				if ( function_exists( 'et_builder_is_tb_admin_screen' ) && et_builder_is_tb_admin_screen() ) {
113
					add_thickbox();
114
					add_action( 'admin_footer', array( $this, 'shortcode_insert_button_script' ) );
115
				}
116
117
				if ( $this->is_preview() ) {
118
					add_action( 'wp_footer', array( $this, 'shortcode_insert_button_script' ) );
119
					// this makes the insert button work for elementor
120
					add_action( 'elementor/editor/after_enqueue_scripts', array(
121
						$this,
122
						'shortcode_insert_button_script'
123
					) ); // for elementor
124
				}
125
				// this makes the insert button work for cornerstone
126
				add_action( 'wp_print_footer_scripts', array( __CLASS__, 'maybe_cornerstone_builder' ) );
127
128
				add_action( 'wp_ajax_super_duper_get_widget_settings', array( __CLASS__, 'get_widget_settings' ) );
129
				add_action( 'wp_ajax_super_duper_get_picker', array( __CLASS__, 'get_picker' ) );
130
131
				// add generator text to admin head
132
				add_action( 'admin_head', array( $this, 'generator' ) );
133
			}
134
135
			do_action( 'wp_super_duper_widget_init', $options, $this );
136
		}
137
138
        /**
139
         * The register widget function
140
         * @return void
141
         */
142
		public function _register() {
143
            if(empty($this->options['output_types']) || in_array('widget',$this->options['output_types'])){
144
                parent::_register();
145
			}
146
		}
147
148
		/**
149
		 * Add our widget CSS to elementor editor.
150
		 */
151
		public function elementor_editor_styles() {
152
			wp_add_inline_style( 'elementor-editor', $this->widget_css( false ) );
153
		}
154
155
		public function register_fusion_element() {
156
157
			$options = $this->options;
158
159
			if ( $this->base_id ) {
160
161
				$params = $this->get_fusion_params();
162
163
				$args = array(
164
					'name'            => $options['name'],
165
					'shortcode'       => $this->base_id,
166
					'icon'            => $options['block-icon'] ? $options['block-icon'] : 'far fa-square',
167
					'allow_generator' => true,
168
				);
169
170
				if ( ! empty( $params ) ) {
171
					$args['params'] = $params;
172
				}
173
174
				fusion_builder_map( $args );
0 ignored issues
show
Bug introduced by
The function fusion_builder_map was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

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

174
				/** @scrutinizer ignore-call */ 
175
    fusion_builder_map( $args );
Loading history...
175
			}
176
177
		}
178
179
		public function get_fusion_params() {
180
			$params    = array();
181
			$arguments = $this->get_arguments();
182
183
			if ( ! empty( $arguments ) ) {
184
				foreach ( $arguments as $key => $val ) {
185
					$param = array();
186
					// type
187
					$param['type'] = str_replace(
188
						array(
189
							"text",
190
							"number",
191
							"email",
192
							"color",
193
							"checkbox"
194
						),
195
						array(
196
							"textfield",
197
							"textfield",
198
							"textfield",
199
							"colorpicker",
200
							"select",
201
202
						),
203
						$val['type'] );
204
205
					// multiselect
206
					if ( $val['type'] == 'multiselect' || ( ( $param['type'] == 'select' || $val['type'] == 'select' ) && ! empty( $val['multiple'] ) ) ) {
207
						$param['type']     = 'multiple_select';
208
						$param['multiple'] = true;
209
					}
210
211
					// heading
212
					$param['heading'] = $val['title'];
213
214
					// description
215
					$param['description'] = isset( $val['desc'] ) ? $val['desc'] : '';
216
217
					// param_name
218
					$param['param_name'] = $key;
219
220
					// Default
221
					$param['default'] = isset( $val['default'] ) ? $val['default'] : '';
222
223
					// Group
224
					if ( isset( $val['group'] ) ) {
225
						$param['group'] = $val['group'];
226
					}
227
228
					// value
229
					if ( $val['type'] == 'checkbox' ) {
230
						if ( isset( $val['default'] ) && $val['default'] == '0' ) {
231
							unset( $param['default'] );
232
						}
233
						$param['value'] = array( '' => __( "No" ), '1' => __( "Yes" ) );
234
					} elseif ( $param['type'] == 'select' || $param['type'] == 'multiple_select' ) {
235
						$param['value'] = isset( $val['options'] ) ? $val['options'] : array();
236
					} else {
237
						$param['value'] = isset( $val['default'] ) ? $val['default'] : '';
238
					}
239
240
					// setup the param
241
					$params[] = $param;
242
243
				}
244
			}
245
246
247
			return $params;
248
		}
249
250
		/**
251
		 * Maybe insert the shortcode inserter button in the footer if we are in the cornerstone builder
252
		 */
253
		public static function maybe_cornerstone_builder() {
254
			if ( did_action( 'cornerstone_before_boot_app' ) ) {
255
				self::shortcode_insert_button_script();
256
			}
257
		}
258
259
		/**
260
		 * A function to ge the shortcode builder picker html.
261
		 *
262
		 * @param string $editor_id
263
		 *
264
		 * @return string
265
		 */
266
		public static function get_picker( $editor_id = '' ) {
267
268
			ob_start();
269
			if ( isset( $_POST['editor_id'] ) ) {
270
				$editor_id = esc_attr( $_POST['editor_id'] );
271
			} elseif ( isset( $_REQUEST['et_fb'] ) ) {
272
				$editor_id = 'main_content_content_vb_tiny_mce';
273
			}
274
275
			global $sd_widgets;
276
277
//			print_r($sd_widgets);exit;
278
			?>
279
280
			<div class="sd-shortcode-left-wrap">
281
				<?php
282
				ksort( $sd_widgets );
283
				//				print_r($sd_widgets);exit;
284
				if ( ! empty( $sd_widgets ) ) {
285
					echo '<select class="widefat" onchange="sd_get_shortcode_options(this);">';
286
					echo "<option>" . __( 'Select shortcode' ) . "</option>";
287
					foreach ( $sd_widgets as $shortcode => $class ) {
288
						if(!empty($class['output_types']) && !in_array('shortcode', $class['output_types'])){ continue; }
289
						echo "<option value='" . esc_attr( $shortcode ) . "'>" . esc_attr( $shortcode ) . " (" . esc_attr( $class['name'] ) . ")</option>";
290
					}
291
					echo "</select>";
292
293
				}
294
				?>
295
				<div class="sd-shortcode-settings"></div>
296
297
			</div>
298
299
			<div class="sd-shortcode-right-wrap">
300
				<textarea id='sd-shortcode-output' disabled></textarea>
301
				<div id='sd-shortcode-output-actions'>
302
					<?php if ( $editor_id != '' ) { ?>
303
						<button class="button sd-insert-shortcode-button"
304
						        onclick="sd_insert_shortcode(<?php if ( ! empty( $editor_id ) ) {
305
							        echo "'" . $editor_id . "'";
306
						        } ?>)"><?php _e( 'Insert shortcode' ); ?></button>
307
					<?php } ?>
308
					<button class="button"
309
					        onclick="sd_copy_to_clipboard()"><?php _e( 'Copy shortcode' ); ?></button>
310
				</div>
311
			</div>
312
			<?php
313
314
			$html = ob_get_clean();
315
316
			if ( wp_doing_ajax() ) {
317
				echo $html;
318
				$should_die = true;
319
320
				// some builder get the editor via ajax so we should not die on those occasions
321
				$dont_die = array(
322
					'parent_tag',// WP Bakery
323
					'avia_request' // enfold
324
				);
325
326
				foreach ( $dont_die as $request ) {
327
					if ( isset( $_REQUEST[ $request ] ) ) {
328
						$should_die = false;
329
					}
330
				}
331
332
				if ( $should_die ) {
333
					wp_die();
334
				}
335
336
			} else {
337
				return $html;
338
			}
339
340
			return '';
341
342
		}
343
344
		/**
345
		 * Output the version in the admin header.
346
		 */
347
		public function generator() {
348
			echo '<meta name="generator" content="WP Super Duper v' . $this->version . '" />';
349
		}
350
351
		/**
352
		 * Get widget settings.
353
		 *
354
		 * @since 1.0.0
355
		 */
356
		public static function get_widget_settings() {
357
			global $sd_widgets;
358
359
			$shortcode = isset( $_REQUEST['shortcode'] ) && $_REQUEST['shortcode'] ? sanitize_title_with_dashes( $_REQUEST['shortcode'] ) : '';
360
			if ( ! $shortcode ) {
361
				wp_die();
362
			}
363
			$widget_args = isset( $sd_widgets[ $shortcode ] ) ? $sd_widgets[ $shortcode ] : '';
364
			if ( ! $widget_args ) {
365
				wp_die();
366
			}
367
			$class_name = isset( $widget_args['class_name'] ) && $widget_args['class_name'] ? $widget_args['class_name'] : '';
368
			if ( ! $class_name ) {
369
				wp_die();
370
			}
371
372
			// invoke an instance method
373
			$widget = new $class_name;
374
375
			ob_start();
376
			$widget->form( array() );
377
			$form = ob_get_clean();
378
			echo "<form id='$shortcode'>" . $form . "<div class=\"widget-control-save\"></div></form>";
379
			echo "<style>" . $widget->widget_css() . "</style>";
380
			echo "<script>" . $widget->widget_js() . "</script>";
381
			?>
382
			<?php
383
			wp_die();
384
		}
385
386
		/**
387
		 * Insert shortcode builder button to classic editor (not inside Gutenberg, not needed).
388
		 *
389
		 * @param string $editor_id Optional. Shortcode editor id. Default null.
390
		 * @param string $insert_shortcode_function Optional. Insert shortcode function. Default null.
391
		 *
392
		 *@since 1.0.0
393
		 *
394
		 */
395
		public static function shortcode_insert_button( $editor_id = '', $insert_shortcode_function = '' ) {
396
			global $sd_widgets, $shortcode_insert_button_once;
397
			if ( $shortcode_insert_button_once ) {
398
				return;
399
			}
400
			add_thickbox();
401
402
403
			/**
404
			 * Cornerstone makes us play dirty tricks :/
405
			 * 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.
406
			 */
407
			if ( function_exists( 'cornerstone_plugin_init' ) && ! is_admin() ) {
408
				echo '<span id="insert-media-button">';
409
			}
410
411
			echo self::shortcode_button( 'this', 'true' );
412
413
			// see opening note
414
			if ( function_exists( 'cornerstone_plugin_init' ) && ! is_admin() ) {
415
				echo '</span>'; // end #insert-media-button
416
			}
417
418
			// Add separate script for generatepress theme sections
419
			if ( function_exists( 'generate_sections_sections_metabox' ) && did_action( 'generate_sections_metabox' ) ) {
420
			} else {
421
				self::shortcode_insert_button_script( $editor_id, $insert_shortcode_function );
422
			}
423
424
			$shortcode_insert_button_once = true;
425
		}
426
427
		/**
428
		 * Gets the shortcode insert button html.
429
		 *
430
		 * @param string $id
431
		 * @param string $search_for_id
432
		 *
433
		 * @return mixed
434
		 */
435
		public static function shortcode_button( $id = '', $search_for_id = '' ) {
436
			ob_start();
437
			?>
438
			<span class="sd-lable-shortcode-inserter">
439
				<a onclick="sd_ajax_get_picker(<?php echo $id;
440
				if ( $search_for_id ) {
441
					echo "," . $search_for_id;
442
				} ?>);" href="#TB_inline?width=100%&height=550&inlineId=super-duper-content-ajaxed"
443
				   class="thickbox button super-duper-content-open" title="Add Shortcode">
444
					<span style="vertical-align: middle;line-height: 18px;font-size: 20px;"
445
					      class="dashicons dashicons-screenoptions"></span>
446
				</a>
447
				<div id="super-duper-content-ajaxed" style="display:none;">
448
					<span>Loading</span>
449
				</div>
450
			</span>
451
452
			<?php
453
			$html = ob_get_clean();
454
455
			// remove line breaks so we can use it in js
456
			return preg_replace( "/\r|\n/", "", trim( $html ) );
457
		}
458
459
		/**
460
		 * Makes SD work with the siteOrigin page builder.
461
		 *
462
		 * @return mixed
463
		 *@since 1.0.6
464
		 */
465
		public static function siteorigin_js() {
466
			ob_start();
467
			?>
468
			<script>
469
				/**
470
				 * Check a form to see what items should be shown or hidden.
471
				 */
472
				function sd_so_show_hide(form) {
473
					jQuery(form).find(".sd-argument").each(function () {
474
475
						var $element_require = jQuery(this).data('element_require');
476
477
						if ($element_require) {
478
479
							$element_require = $element_require.replace("&#039;", "'"); // replace single quotes
480
							$element_require = $element_require.replace("&quot;", '"'); // replace double quotes
481
482
							if (eval($element_require)) {
483
								jQuery(this).removeClass('sd-require-hide');
484
							} else {
485
								jQuery(this).addClass('sd-require-hide');
486
							}
487
						}
488
					});
489
				}
490
491
				/**
492
				 * Toggle advanced settings visibility.
493
				 */
494
				function sd_so_toggle_advanced($this) {
495
					var form = jQuery($this).parents('form,.form,.so-content');
496
					form.find('.sd-advanced-setting').toggleClass('sd-adv-show');
497
					return false;// prevent form submit
498
				}
499
500
				/**
501
				 * Initialise a individual widget.
502
				 */
503
				function sd_so_init_widget($this, $selector) {
504
					if (!$selector) {
505
						$selector = 'form';
506
					}
507
					// only run once.
508
					if (jQuery($this).data('sd-widget-enabled')) {
509
						return;
510
					} else {
511
						jQuery($this).data('sd-widget-enabled', true);
512
					}
513
514
					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>';
515
					var form = jQuery($this).parents('' + $selector + '');
516
517
					if (jQuery($this).val() == '1' && jQuery(form).find('.sd-advanced-button').length == 0) {
518
						jQuery(form).append($button);
519
					}
520
521
					// show hide on form change
522
					jQuery(form).on("change", function () {
523
						sd_so_show_hide(form);
524
					});
525
526
					// show hide on load
527
					sd_so_show_hide(form);
528
				}
529
530
				jQuery(function () {
531
					jQuery(document).on('open_dialog', function (w, e) {
532
						setTimeout(function () {
533
							if (jQuery('.so-panels-dialog-wrapper:visible .so-content.panel-dialog .sd-show-advanced').length) {
534
								if (jQuery('.so-panels-dialog-wrapper:visible .so-content.panel-dialog .sd-show-advanced').val() == '1') {
535
									sd_so_init_widget('.so-panels-dialog-wrapper:visible .so-content.panel-dialog .sd-show-advanced', 'div');
536
								}
537
							}
538
						}, 200);
539
					});
540
				});
541
			</script>
542
			<?php
543
			$output = ob_get_clean();
544
545
			/*
546
			 * We only add the <script> tags for code highlighting, so we strip them from the output.
547
			 */
548
549
			return str_replace( array(
550
				'<script>',
551
				'</script>'
552
			), '', $output );
553
		}
554
555
		/**
556
		 * Output the JS and CSS for the shortcode insert button.
557
		 *
558
		 * @param string $editor_id
559
		 * @param string $insert_shortcode_function
560
		 *
561
		 *@since 1.0.6
562
		 *
563
		 */
564
		public static function shortcode_insert_button_script( $editor_id = '', $insert_shortcode_function = '' ) {
565
			?>
566
			<style>
567
				.sd-shortcode-left-wrap {
568
					float: left;
569
					width: 60%;
570
				}
571
572
				.sd-shortcode-left-wrap .gd-help-tip {
573
					float: none;
574
				}
575
576
				.sd-shortcode-left-wrap .widefat {
577
					border-spacing: 0;
578
					width: 100%;
579
					clear: both;
580
					margin: 0;
581
					border: 1px solid #ddd;
582
					box-shadow: inset 0 1px 2px rgba(0, 0, 0, .07);
583
					background-color: #fff;
584
					color: #32373c;
585
					outline: 0;
586
					transition: 50ms border-color ease-in-out;
587
					padding: 3px 5px;
588
				}
589
590
				.sd-shortcode-left-wrap input[type=checkbox].widefat {
591
					border: 1px solid #b4b9be;
592
					background: #fff;
593
					color: #555;
594
					clear: none;
595
					cursor: pointer;
596
					display: inline-block;
597
					line-height: 0;
598
					height: 16px;
599
					margin: -4px 4px 0 0;
600
					margin-top: 0;
601
					outline: 0;
602
					padding: 0 !important;
603
					text-align: center;
604
					vertical-align: middle;
605
					width: 16px;
606
					min-width: 16px;
607
					-webkit-appearance: none;
608
					box-shadow: inset 0 1px 2px rgba(0, 0, 0, .1);
609
					transition: .05s border-color ease-in-out;
610
				}
611
612
				.sd-shortcode-left-wrap input[type=checkbox]:checked:before {
613
					content: "\f147";
614
					margin: -3px 0 0 -4px;
615
					color: #1e8cbe;
616
					float: left;
617
					display: inline-block;
618
					vertical-align: middle;
619
					width: 16px;
620
					font: normal 21px/1 dashicons;
621
					speak: none;
622
					-webkit-font-smoothing: antialiased;
623
					-moz-osx-font-smoothing: grayscale;
624
				}
625
626
				#sd-shortcode-output-actions button,
627
				.sd-advanced-button {
628
					color: #555;
629
					border-color: #ccc;
630
					background: #f7f7f7;
631
					box-shadow: 0 1px 0 #ccc;
632
					vertical-align: top;
633
					display: inline-block;
634
					text-decoration: none;
635
					font-size: 13px;
636
					line-height: 26px;
637
					height: 28px;
638
					margin: 0;
639
					padding: 0 10px 1px;
640
					cursor: pointer;
641
					border-width: 1px;
642
					border-style: solid;
643
					-webkit-appearance: none;
644
					border-radius: 3px;
645
					white-space: nowrap;
646
					box-sizing: border-box;
647
				}
648
649
				button.sd-advanced-button {
650
					background: #0073aa;
651
					border-color: #006799;
652
					box-shadow: inset 0 2px 0 #006799;
653
					vertical-align: top;
654
					color: #fff;
655
					text-decoration: none;
656
					text-shadow: 0 -1px 1px #006799, 1px 0 1px #006799, 0 1px 1px #006799, -1px 0 1px #006799;
657
					float: right;
658
					margin-right: 3px !important;
659
					font-size: 20px !important;
660
				}
661
662
				.sd-shortcode-right-wrap {
663
					float: right;
664
					width: 35%;
665
				}
666
667
				#sd-shortcode-output {
668
					background: rgba(255, 255, 255, .5);
669
					border-color: rgba(222, 222, 222, .75);
670
					box-shadow: inset 0 1px 2px rgba(0, 0, 0, .04);
671
					color: rgba(51, 51, 51, .5);
672
					overflow: auto;
673
					padding: 2px 6px;
674
					line-height: 1.4;
675
					resize: vertical;
676
				}
677
678
				#sd-shortcode-output {
679
					height: 250px;
680
					width: 100%;
681
				}
682
683
				<?php if ( function_exists( 'generate_sections_sections_metabox' ) ) { ?>
684
				.generate-sections-modal #custom-media-buttons > .sd-lable-shortcode-inserter {
685
					display: inline;
686
				}
687
				<?php } ?>
688
				<?php if ( function_exists( 'et_builder_is_tb_admin_screen' ) && et_builder_is_tb_admin_screen() ) { ?>
689
				body.divi_page_et_theme_builder div#TB_window.gd-tb-window{z-index:9999999}
690
				<?php } ?>
691
			</style>
692
			<?php
693
			if ( class_exists( 'SiteOrigin_Panels' ) ) {
694
				echo "<script>" . self::siteorigin_js() . "</script>";
695
			}
696
			?>
697
			<script>
698
				<?php
699
				if(! empty( $insert_shortcode_function )){
700
					echo $insert_shortcode_function;
701
				}else{
702
703
				/**
704
				 * Function for super duper insert shortcode.
705
				 *
706
				 * @since 1.0.0
707
				 */
708
				?>
709
				function sd_insert_shortcode($editor_id) {
710
					$shortcode = jQuery('#TB_ajaxContent #sd-shortcode-output').val();
711
					if ($shortcode) {
712
						if (!$editor_id) {
713
							<?php
714
							if ( isset( $_REQUEST['et_fb'] ) ) {
715
								echo '$editor_id = "#main_content_content_vb_tiny_mce";';
716
							} elseif ( isset( $_REQUEST['action'] ) && $_REQUEST['action'] == 'elementor' ) {
717
								echo '$editor_id = "#elementor-controls .wp-editor-container textarea";';
718
							} else {
719
								echo '$editor_id = "#wp-content-editor-container textarea";';
720
							}
721
							?>
722
						} else {
723
							$editor_id = '#' + $editor_id;
724
						}
725
						tmceActive = jQuery($editor_id).attr("aria-hidden") == "true" ? true : false;
726
						/* GeneratePress */
727
						if (jQuery('#generate-sections-modal-dialog ' + $editor_id).length) {
728
							$editor_id = '#generate-sections-modal-dialog ' + $editor_id;
729
							tmceActive = jQuery($editor_id).closest('.wp-editor-wrap').hasClass('tmce-active') ? true : false;
730
						}
731
						if (typeof tinyMCE !== 'undefined' && tinyMCE.activeEditor && tmceActive) {
732
							tinyMCE.execCommand('mceInsertContent', false, $shortcode);
733
						} else {
734
							var $txt = jQuery($editor_id);
735
							var caretPos = $txt[0].selectionStart;
736
							var textAreaTxt = $txt.val();
737
							var txtToAdd = $shortcode;
738
							var textareaValue = textAreaTxt.substring(0, caretPos) + txtToAdd + textAreaTxt.substring(caretPos);
739
							$txt.focus().val(textareaValue).change().keydown().blur().keyup().keypress().trigger('input').trigger('change');
740
741
							// set Divi react input value
742
							var input = document.getElementById("main_content_content_vb_tiny_mce");
743
							if (input) {
744
								sd_setNativeValue(input, textareaValue);
745
							}
746
747
						}
748
						tb_remove();
749
					}
750
				}
751
752
				/*
753
				 Set the value of elements controlled via react.
754
				 */
755
				function sd_setNativeValue(element, value) {
756
					let lastValue = element.value;
757
					element.value = value;
758
					let event = new Event("input", {target: element, bubbles: true});
759
					// React 15
760
					event.simulated = true;
761
					// React 16
762
					let tracker = element._valueTracker;
763
					if (tracker) {
764
						tracker.setValue(lastValue);
765
					}
766
					element.dispatchEvent(event);
767
				}
768
				<?php }?>
769
770
				/*
771
				 Copies the shortcode to the clipboard.
772
				 */
773
				function sd_copy_to_clipboard() {
774
					/* Get the text field */
775
					var copyText = document.querySelector("#TB_ajaxContent #sd-shortcode-output");
776
					//un-disable the field
777
					copyText.disabled = false;
778
					/* Select the text field */
779
					copyText.select();
780
					/* Copy the text inside the text field */
781
					document.execCommand("Copy");
782
					//re-disable the field
783
					copyText.disabled = true;
784
					/* Alert the copied text */
785
					alert("Copied the text: " + copyText.value);
786
				}
787
788
				/*
789
				 Gets the shortcode options.
790
				 */
791
				function sd_get_shortcode_options($this) {
792
793
					$short_code = jQuery($this).val();
794
					if ($short_code) {
795
796
						var data = {
797
							'action': 'super_duper_get_widget_settings',
798
							'shortcode': $short_code,
799
							'attributes': 123,
800
							'post_id': 321,
801
							'_ajax_nonce': '<?php echo wp_create_nonce( 'super_duper_output_shortcode' );?>'
802
						};
803
804
						if (typeof ajaxurl === 'undefined') {
805
							var ajaxurl = "<?php echo admin_url( 'admin-ajax.php' );?>";
806
						}
807
808
						jQuery.post(ajaxurl, data, function (response) {
809
							jQuery('#TB_ajaxContent .sd-shortcode-settings').html(response);
810
811
							jQuery('#' + $short_code).on('change', 'select', function () {
812
								sd_build_shortcode($short_code);
813
							}); // take care of select tags
814
815
							jQuery('#' + $short_code).on('change keypress keyup', 'input,textarea', function () {
816
								sd_build_shortcode($short_code);
817
							});
818
819
							sd_build_shortcode($short_code);
820
821
							// resize the window to fit
822
							setTimeout(function () {
823
								jQuery('#TB_ajaxContent').css('width', 'auto').css('height', '75vh');
824
							}, 200);
825
826
827
							return response;
828
						});
829
					}
830
831
				}
832
833
				/*
834
				 Builds and inserts the shortcode into the viewer.
835
				 */
836
				function sd_build_shortcode($id) {
837
838
					var multiSelects = {};
839
					var multiSelectsRemove = [];
840
841
					$output = "[" + $id;
842
843
					$form_data = jQuery("#" + $id).serializeArray();
844
845
					// run checks for multiselects
846
					jQuery.each($form_data, function (index, element) {
847
						if (element && element.value) {
848
							$field_name = element.name.substr(element.name.indexOf("][") + 2);
849
							$field_name = $field_name.replace("]", "");
850
							// check if its a multiple
851
							if ($field_name.includes("[]")) {
852
								multiSelectsRemove[multiSelectsRemove.length] = index;
853
								$field_name = $field_name.replace("[]", "");
854
								if ($field_name in multiSelects) {
855
									multiSelects[$field_name] = multiSelects[$field_name] + "," + element.value;
856
								} else {
857
									multiSelects[$field_name] = element.value;
858
								}
859
							}
860
						}
861
					});
862
863
					// fix multiselects if any are found
864
					if (multiSelectsRemove.length) {
865
866
						// remove all multiselects
867
						multiSelectsRemove.reverse();
868
						multiSelectsRemove.forEach(function (index) {
869
							$form_data.splice(index, 1);
870
						});
871
872
						$ms_arr = [];
873
						// add multiselets back
874
						jQuery.each(multiSelects, function (index, value) {
875
							$ms_arr[$ms_arr.length] = {"name": "[][" + index + "]", "value": value};
876
						});
877
						$form_data = $form_data.concat($ms_arr);
878
					}
879
880
881
					if ($form_data) {
882
						$content = '';
883
						$form_data.forEach(function (element) {
884
885
							if (element.value) {
886
								$field_name = element.name.substr(element.name.indexOf("][") + 2);
887
								$field_name = $field_name.replace("]", "");
888
								if ($field_name == 'html') {
889
									$content = element.value;
890
								} else {
891
									$output = $output + " " + $field_name + '="' + element.value + '"';
892
								}
893
							}
894
895
						});
896
					}
897
					$output = $output + "]";
898
899
					// check for content field
900
					if ($content) {
901
						$output = $output + $content + "[/" + $id + "]";
902
					}
903
904
					jQuery('#TB_ajaxContent #sd-shortcode-output').html($output);
905
				}
906
907
908
				/*
909
				 Delay the init of the textareas for 1 second.
910
				 */
911
				(function () {
912
					setTimeout(function () {
913
						sd_init_textareas();
914
					}, 1000);
915
				})();
916
917
				/*
918
				 Init the textareas to be able to show the shortcode builder button.
919
				 */
920
				function sd_init_textareas() {
921
922
					// General textareas
923
					jQuery(document).on('focus', 'textarea', function () {
924
925
						if (jQuery(this).hasClass('wp-editor-area')) {
926
							// insert the shortcode button to the textarea lable if not there already
927
							if (!jQuery(this).parent().find('.sd-lable-shortcode-inserter').length) {
928
								jQuery(this).parent().find('.quicktags-toolbar').append(sd_shortcode_button(jQuery(this).attr('id')));
929
							}
930
						} else {
931
							// insert the shortcode button to the textarea lable if not there already
932
							if (!jQuery("label[for='" + jQuery(this).attr('id') + "']").find('.sd-lable-shortcode-inserter').length) {
933
								jQuery("label[for='" + jQuery(this).attr('id') + "']").append(sd_shortcode_button(jQuery(this).attr('id')));
934
							}
935
						}
936
					});
937
938
					// The below tries to add the shortcode builder button to the builders own raw/shortcode sections.
939
940
					// DIVI
941
					jQuery(document).on('focusin', '.et-fb-codemirror', function () {
942
						// insert the shortcode button to the textarea lable if not there already
943
						if (!jQuery(this).closest('.et-fb-form__group').find('.sd-lable-shortcode-inserter').length) {
944
							jQuery(this).closest('.et-fb-form__group').find('.et-fb-form__label-text').append(sd_shortcode_button());
945
						}
946
					});
947
948
					// Beaver
949
					jQuery(document).on('focusin', '.fl-code-field', function () {
950
						// insert the shortcode button to the textarea lable if not there already
951
						if (!jQuery(this).closest('.fl-field-control-wrapper').find('.sd-lable-shortcode-inserter').length) {
952
							jQuery(this).closest('.fl-field-control-wrapper').prepend(sd_shortcode_button());
953
						}
954
					});
955
956
					// Fushion builder (avada)
957
					jQuery(document).on('focusin', '.CodeMirror.cm-s-default', function () {
958
						// insert the shortcode button to the textarea lable if not there already
959
						if (!jQuery(this).parent().find('.sd-lable-shortcode-inserter').length) {
960
							jQuery(sd_shortcode_button()).insertBefore(this);
961
						}
962
					});
963
964
					// Avia builder (enfold)
965
					jQuery(document).on('focusin', '#aviaTBcontent', function () {
966
						// insert the shortcode button to the textarea lable if not there already
967
						if (!jQuery(this).parent().parent().find('.avia-name-description ').find('.sd-lable-shortcode-inserter').length) {
968
							jQuery(this).parent().parent().find('.avia-name-description strong').append(sd_shortcode_button(jQuery(this).attr('id')));
969
						}
970
					});
971
972
					// Cornerstone textareas
973
					jQuery(document).on('focusin', '.cs-control.cs-control-textarea', function () {
974
						// insert the shortcode button to the textarea lable if not there already
975
						if (!jQuery(this).find('.cs-control-header label').find('.sd-lable-shortcode-inserter').length) {
976
							jQuery(this).find('.cs-control-header label').append(sd_shortcode_button());
977
						}
978
					});
979
980
					// Cornerstone main bar
981
					setTimeout(function () {
982
						// insert the shortcode button to the textarea lable if not there already
983
						if (!jQuery('.cs-bar-btns').find('.sd-lable-shortcode-inserter').length) {
984
							jQuery('<li style="text-align: center;padding: 5px;list-style: none;">' + sd_shortcode_button() + '</li>').insertBefore('.cs-action-toggle-custom-css');
985
						}
986
					}, 2000);
987
988
989
					// WP Bakery, code editor does not render shortcodes.
990
//					jQuery(document).on('focusin', '.wpb-textarea_raw_html', function () {
991
//						// insert the shortcode button to the textarea lable if not there already
992
//						if(!jQuery(this).parent().parent().find('.wpb_element_label').find('.sd-lable-shortcode-inserter').length){
993
//							jQuery(this).parent().parent().find('.wpb_element_label').append(sd_shortcode_button());
994
//						}
995
//					});
996
997
				}
998
999
				/**
1000
				 * Gets the html for the picker via ajax and updates it on the fly.
1001
				 *
1002
				 * @param $id
1003
				 * @param $search
1004
				 */
1005
				function sd_ajax_get_picker($id, $search) {
1006
					if ($search) {
1007
						$this = $id;
1008
						$id = jQuery($this).closest('.wp-editor-wrap').find('.wp-editor-container textarea').attr('id');
1009
					}
1010
1011
					var data = {
1012
						'action': 'super_duper_get_picker',
1013
						'editor_id': $id,
1014
						'_ajax_nonce': '<?php echo wp_create_nonce( 'super_duper_picker' );?>'
1015
					};
1016
1017
					if (!ajaxurl) {
1018
						var ajaxurl = "<?php echo admin_url( 'admin-ajax.php' ); ?>";
1019
					}
1020
1021
					jQuery.post(ajaxurl, data, function (response) {
1022
						jQuery('#TB_ajaxContent').closest('#TB_window').addClass('gd-tb-window');
1023
						jQuery('#TB_ajaxContent').html(response);
1024
						//return response;
1025
					}).then(function (env) {
1026
						jQuery('body').on('thickbox:removed', function () {
1027
							jQuery('#super-duper-content-ajaxed').html('');
1028
						});
1029
					});
1030
				}
1031
1032
				/**
1033
				 * Get the html for the shortcode inserter button depending on if a textarea id is available.
1034
				 *
1035
				 * @param $id string The textarea id.
1036
				 * @returns {string}
1037
				 */
1038
				function sd_shortcode_button($id) {
1039
					if ($id) {
1040
						return '<?php echo self::shortcode_button( "\\''+\$id+'\\'" );?>';
1041
					} else {
1042
						return '<?php echo self::shortcode_button();?>';
1043
					}
1044
				}
1045
1046
			</script>
1047
			<?php
1048
		}
1049
1050
		/**
1051
		 * Gets some CSS for the widgets screen.
1052
		 *
1053
		 * @param bool $advanced If we should include advanced CSS.
1054
		 *
1055
		 * @return mixed
1056
		 */
1057
		public function widget_css( $advanced = true ) {
1058
			ob_start();
1059
			?>
1060
			<style>
1061
				<?php if( $advanced ){ ?>
1062
				.sd-advanced-setting {
1063
					display: none;
1064
				}
1065
1066
				.sd-advanced-setting.sd-adv-show {
1067
					display: block;
1068
				}
1069
1070
				.sd-argument.sd-require-hide,
1071
				.sd-advanced-setting.sd-require-hide {
1072
					display: none;
1073
				}
1074
1075
				button.sd-advanced-button {
1076
					margin-right: 3px !important;
1077
					font-size: 20px !important;
1078
				}
1079
1080
				<?php } ?>
1081
1082
				button.sd-toggle-group-button {
1083
					background-color: #f3f3f3;
1084
					color: #23282d;
1085
					cursor: pointer;
1086
					padding: 10px;
1087
					width: 100%;
1088
					border: none;
1089
					text-align: left;
1090
					outline: none;
1091
					font-size: 13px;
1092
					font-weight: bold;
1093
					margin-bottom: 1px;
1094
				}
1095
			</style>
1096
			<?php
1097
			$output = ob_get_clean();
1098
1099
			/*
1100
			 * We only add the <script> tags for code highlighting, so we strip them from the output.
1101
			 */
1102
1103
			return str_replace( array(
1104
				'<style>',
1105
				'</style>'
1106
			), '', $output );
1107
		}
1108
1109
		/**
1110
		 * Gets some JS for the widgets screen.
1111
		 *
1112
		 * @return mixed
1113
		 */
1114
		public function widget_js() {
1115
			ob_start();
1116
			?>
1117
			<script>
1118
1119
				/**
1120
				 * Toggle advanced settings visibility.
1121
				 */
1122
				function sd_toggle_advanced($this) {
1123
					var form = jQuery($this).parents('form,.form');
1124
					form.find('.sd-advanced-setting').toggleClass('sd-adv-show');
1125
					return false;// prevent form submit
1126
				}
1127
1128
				/**
1129
				 * Check a form to see what items should be shown or hidden.
1130
				 */
1131
				function sd_show_hide(form) {
1132
					jQuery(form).find(".sd-argument").each(function () {
1133
1134
						var $element_require = jQuery(this).data('element_require');
1135
1136
						if ($element_require) {
1137
1138
							$element_require = $element_require.replace("&#039;", "'"); // replace single quotes
1139
							$element_require = $element_require.replace("&quot;", '"'); // replace double quotes
1140
1141
							if (eval($element_require)) {
1142
								jQuery(this).removeClass('sd-require-hide');
1143
							} else {
1144
								jQuery(this).addClass('sd-require-hide');
1145
							}
1146
						}
1147
					});
1148
				}
1149
1150
				/**
1151
				 * Initialise widgets from the widgets screen.
1152
				 */
1153
				function sd_init_widgets($selector) {
1154
					jQuery(".sd-show-advanced").each(function (index) {
1155
						sd_init_widget(this, $selector);
1156
					});
1157
				}
1158
1159
				/**
1160
				 * Initialise a individual widget.
1161
				 */
1162
				function sd_init_widget($this, $selector) {
1163
					if (!$selector) {
1164
						$selector = 'form';
1165
					}
1166
					// only run once.
1167
					if (jQuery($this).data('sd-widget-enabled')) {
1168
						return;
1169
					} else {
1170
						jQuery($this).data('sd-widget-enabled', true);
1171
					}
1172
1173
					var $button = '<button title="<?php _e( 'Advanced Settings' );?>" style="line-height: 28px;" class="button button-primary right sd-advanced-button" onclick="sd_toggle_advanced(this);return false;"><span class="dashicons dashicons-admin-settings" style="width: 28px;font-size: 28px;"></span></button>';
1174
					var form = jQuery($this).parents('' + $selector + '');
1175
1176
					if (jQuery($this).val() == '1' && jQuery(form).find('.sd-advanced-button').length == 0) {
1177
						console.log('add advanced button');
1178
						if(jQuery(form).find('.widget-control-save').length > 0){
1179
							jQuery(form).find('.widget-control-save').after($button);
1180
						}else{
1181
							jQuery(form).find('.sd-show-advanced').after($button);
1182
						}
1183
					} else {
1184
						console.log('no advanced button');
1185
						console.log(jQuery($this).val());
1186
						console.log(jQuery(form).find('.sd-advanced-button').length);
1187
1188
					}
1189
1190
					// show hide on form change
1191
					jQuery(form).on("change", function () {
1192
						sd_show_hide(form);
1193
					});
1194
1195
					// show hide on load
1196
					sd_show_hide(form);
1197
				}
1198
1199
				/**
1200
				 * Init a customizer widget.
1201
				 */
1202
				function sd_init_customizer_widget(section) {
1203
					if (section.expanded) {
1204
						section.expanded.bind(function (isExpanding) {
1205
							if (isExpanding) {
1206
								// is it a SD widget?
1207
								if (jQuery(section.container).find('.sd-show-advanced').length) {
1208
									// init the widget
1209
									sd_init_widget(jQuery(section.container).find('.sd-show-advanced'), ".form");
1210
								}
1211
							}
1212
						});
1213
					}
1214
				}
1215
1216
				/**
1217
				 * If on widgets screen.
1218
				 */
1219
				jQuery(function () {
1220
					// if not in customizer.
1221
					if (!wp.customize) {
1222
						sd_init_widgets("form");
1223
					}
1224
1225
					// init on widget added
1226
					jQuery(document).on('widget-added', function (e, widget) {
1227
						console.log('widget added');
1228
						// is it a SD widget?
1229
						if (jQuery(widget).find('.sd-show-advanced').length) {
1230
							// init the widget
1231
							sd_init_widget(jQuery(widget).find('.sd-show-advanced'), "form");
1232
						}
1233
					});
1234
1235
					// init on widget updated
1236
					jQuery(document).on('widget-updated', function (e, widget) {
1237
						console.log('widget updated');
1238
1239
						// is it a SD widget?
1240
						if (jQuery(widget).find('.sd-show-advanced').length) {
1241
							// init the widget
1242
							sd_init_widget(jQuery(widget).find('.sd-show-advanced'), "form");
1243
						}
1244
					});
1245
1246
				});
1247
1248
1249
				/**
1250
				 * We need to run this before jQuery is ready
1251
				 */
1252
				if (wp.customize) {
1253
					wp.customize.bind('ready', function () {
1254
1255
						// init widgets on load
1256
						wp.customize.control.each(function (section) {
1257
							sd_init_customizer_widget(section);
1258
						});
1259
1260
						// init widgets on add
1261
						wp.customize.control.bind('add', function (section) {
1262
							sd_init_customizer_widget(section);
1263
						});
1264
1265
					});
1266
1267
				}
1268
				<?php do_action( 'wp_super_duper_widget_js', $this ); ?>
1269
			</script>
1270
			<?php
1271
			$output = ob_get_clean();
1272
1273
			/*
1274
			 * We only add the <script> tags for code highlighting, so we strip them from the output.
1275
			 */
1276
1277
			return str_replace( array(
1278
				'<script>',
1279
				'</script>'
1280
			), '', $output );
1281
		}
1282
1283
1284
		/**
1285
		 * Set the name from the argument key.
1286
		 *
1287
		 * @param $options
1288
		 *
1289
		 * @return mixed
1290
		 */
1291
		private function add_name_from_key( $options, $arguments = false ) {
1292
			if ( ! empty( $options['arguments'] ) ) {
1293
				foreach ( $options['arguments'] as $key => $val ) {
1294
					$options['arguments'][ $key ]['name'] = $key;
1295
				}
1296
			} elseif ( $arguments && is_array( $options ) && ! empty( $options ) ) {
1297
				foreach ( $options as $key => $val ) {
1298
					$options[ $key ]['name'] = $key;
1299
				}
1300
			}
1301
1302
			return $options;
1303
		}
1304
1305
		/**
1306
		 * Register the parent shortcode.
1307
		 *
1308
		 * @since 1.0.0
1309
		 */
1310
		public function register_shortcode() {
1311
			add_shortcode( $this->base_id, array( $this, 'shortcode_output' ) );
1312
			add_action( 'wp_ajax_super_duper_output_shortcode', array( $this, 'render_shortcode' ) );
1313
		}
1314
1315
		/**
1316
		 * Render the shortcode via ajax so we can return it to Gutenberg.
1317
		 *
1318
		 * @since 1.0.0
1319
		 */
1320
		public function render_shortcode() {
1321
			check_ajax_referer( 'super_duper_output_shortcode', '_ajax_nonce', true );
1322
			if ( ! current_user_can( 'manage_options' ) ) {
1323
				wp_die();
1324
			}
1325
1326
			// we might need the $post value here so lets set it.
1327
			if ( isset( $_POST['post_id'] ) && $_POST['post_id'] ) {
1328
				$post_obj = get_post( absint( $_POST['post_id'] ) );
1329
				if ( ! empty( $post_obj ) && empty( $post ) ) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $post seems to never exist and therefore empty should always be true.
Loading history...
1330
					global $post;
1331
					$post = $post_obj;
1332
				}
1333
			}
1334
1335
			if ( isset( $_POST['shortcode'] ) && $_POST['shortcode'] ) {
1336
				$is_preview = $this->is_preview();
1337
				$shortcode_name   = sanitize_title_with_dashes( $_POST['shortcode'] );
1338
				$attributes_array = isset( $_POST['attributes'] ) && $_POST['attributes'] ? $_POST['attributes'] : array();
1339
				$attributes       = '';
1340
				if ( ! empty( $attributes_array ) ) {
1341
					foreach ( $attributes_array as $key => $value ) {
1342
						if ( is_array( $value ) ) {
1343
							$value = implode( ",", $value );
1344
						}
1345
1346
						if ( ! empty( $value ) ) {
1347
							$value = wp_unslash( $value );
1348
1349
							// Encode [ and ].
1350
							if ( $is_preview ) {
1351
								$value = $this->encode_shortcodes( $value );
1352
							}
1353
						}
1354
						$attributes .= " " . sanitize_title_with_dashes( $key ) . "='" . esc_attr( $value ) . "' ";
1355
					}
1356
				}
1357
1358
				$shortcode = "[" . $shortcode_name . " " . $attributes . "]";
1359
1360
				$content = do_shortcode( $shortcode );
1361
1362
				// Decode [ and ].
1363
				if ( ! empty( $content ) && $is_preview ) {
1364
					$content = $this->decode_shortcodes( $content );
1365
				}
1366
1367
				echo $content;
0 ignored issues
show
Security Cross-Site Scripting introduced by
$content can contain request data and is used in output context(s) leading to a potential security vulnerability.

2 paths for user data to reach this point

  1. Path: Read from $_POST, and Data is passed through sanitize_title_with_dashes(), and sanitize_title_with_dashes($_POST['shortcode']) is assigned to $shortcode_name in vendor/ayecode/wp-super-duper/wp-super-duper.php on line 1337
  1. Read from $_POST, and Data is passed through sanitize_title_with_dashes(), and sanitize_title_with_dashes($_POST['shortcode']) is assigned to $shortcode_name
    in vendor/ayecode/wp-super-duper/wp-super-duper.php on line 1337
  2. '[' . $shortcode_name . ' ' . $attributes . ']' is assigned to $shortcode
    in vendor/ayecode/wp-super-duper/wp-super-duper.php on line 1358
  3. Data is passed through do_shortcode(), and do_shortcode($shortcode) is assigned to $content
    in vendor/ayecode/wp-super-duper/wp-super-duper.php on line 1360
  2. Path: Read from $_POST, and IssetNode && $_POST['attributes'] ? $_POST['attributes'] : array() is assigned to $attributes_array in vendor/ayecode/wp-super-duper/wp-super-duper.php on line 1338
  1. Read from $_POST, and IssetNode && $_POST['attributes'] ? $_POST['attributes'] : array() is assigned to $attributes_array
    in vendor/ayecode/wp-super-duper/wp-super-duper.php on line 1338
  2. $attributes_array is assigned to $key
    in vendor/ayecode/wp-super-duper/wp-super-duper.php on line 1341
  3. Data is passed through sanitize_title_with_dashes(), and ' ' . sanitize_title_with_dashes($key) . '='' . esc_attr($value) . '' ' is assigned to $attributes
    in vendor/ayecode/wp-super-duper/wp-super-duper.php on line 1354
  4. '[' . $shortcode_name . ' ' . $attributes . ']' is assigned to $shortcode
    in vendor/ayecode/wp-super-duper/wp-super-duper.php on line 1358
  5. Data is passed through do_shortcode(), and do_shortcode($shortcode) is assigned to $content
    in vendor/ayecode/wp-super-duper/wp-super-duper.php on line 1360

Preventing Cross-Site-Scripting Attacks

Cross-Site-Scripting allows an attacker to inject malicious code into your website - in particular Javascript code, and have that code executed with the privileges of a visiting user. This can be used to obtain data, or perform actions on behalf of that visiting user.

In order to prevent this, make sure to escape all user-provided data:

// for HTML
$sanitized = htmlentities($tainted, ENT_QUOTES);

// for URLs
$sanitized = urlencode($tainted);

General Strategies to prevent injection

In general, it is advisable to prevent any user-data to reach this point. This can be done by white-listing certain values:

if ( ! in_array($value, array('this-is-allowed', 'and-this-too'), true)) {
    throw new \InvalidArgumentException('This input is not allowed.');
}

For numeric data, we recommend to explicitly cast the data:

$sanitized = (integer) $tainted;
Loading history...
1368
			}
1369
			wp_die();
1370
		}
1371
1372
		/**
1373
		 * Output the shortcode.
1374
		 *
1375
		 * @param array $args
1376
		 * @param string $content
1377
		 *
1378
		 * @return string
1379
		 */
1380
		public function shortcode_output( $args = array(), $content = '' ) {
1381
			$_instance = $args;
1382
1383
			$args = $this->argument_values( $args );
1384
1385
			// add extra argument so we know its a output to gutenberg
1386
			//$args
1387
			$args = $this->string_to_bool( $args );
1388
1389
			// if we have a enclosed shortcode we add it to the special `html` argument
1390
			if ( ! empty( $content ) ) {
1391
				$args['html'] = $content;
1392
			}
1393
1394
			if ( ! $this->is_preview() ) {
1395
				/**
1396
				 * Filters the settings for a particular widget args.
1397
				 *
1398
				 * @param array          $args      The current widget instance's settings.
1399
				 * @param WP_Super_Duper $widget    The current widget settings.
1400
				 * @param array          $_instance An array of default widget arguments.
1401
				 *
1402
				 *@since 1.0.28
1403
				 *
1404
				 */
1405
				$args = apply_filters( 'wp_super_duper_widget_display_callback', $args, $this, $_instance );
1406
1407
				if ( ! is_array( $args ) ) {
1408
					return $args;
1409
				}
1410
			}
1411
1412
			$class = isset( $this->options['widget_ops']['classname'] ) ? esc_attr( $this->options['widget_ops']['classname'] ) : '';
1413
			$class .= " sdel-".$this->get_instance_hash();
1414
1415
			$class = apply_filters( 'wp_super_duper_div_classname', $class, $args, $this );
1416
			$class = apply_filters( 'wp_super_duper_div_classname_' . $this->base_id, $class, $args, $this );
1417
1418
			$attrs = apply_filters( 'wp_super_duper_div_attrs', '', $args, $this );
0 ignored issues
show
Unused Code introduced by
The assignment to $attrs is dead and can be removed.
Loading history...
1419
			$attrs = apply_filters( 'wp_super_duper_div_attrs_' . $this->base_id, '', $args, $this );
1420
1421
			$shortcode_args = array();
1422
			$output         = '';
1423
			$no_wrap        = isset( $this->options['no_wrap'] ) && $this->options['no_wrap'] ? true : false;
1424
			if ( isset( $args['no_wrap'] ) && $args['no_wrap'] ) {
1425
				$no_wrap = true;
1426
			}
1427
			$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) targeting 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...
1428
			if ( $main_content && ! $no_wrap ) {
0 ignored issues
show
introduced by
$main_content is defined implicitly as null, thus it is always evaluated to false.
Loading history...
1429
				// wrap the shortcode in a div with the same class as the widget
1430
				$output .= '<div class="' . $class . '" ' . $attrs . '>';
1431
				if ( ! empty( $args['title'] ) ) {
1432
					// if its a shortcode and there is a title try to grab the title wrappers
1433
					$shortcode_args = array( 'before_title' => '', 'after_title' => '' );
1434
					if ( empty( $instance ) ) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $instance does not exist. Did you maybe mean $_instance?
Loading history...
1435
						global $wp_registered_sidebars;
1436
						if ( ! empty( $wp_registered_sidebars ) ) {
1437
							foreach ( $wp_registered_sidebars as $sidebar ) {
1438
								if ( ! empty( $sidebar['before_title'] ) ) {
1439
									$shortcode_args['before_title'] = $sidebar['before_title'];
1440
									$shortcode_args['after_title']  = $sidebar['after_title'];
1441
									break;
1442
								}
1443
							}
1444
						}
1445
					}
1446
					$output .= $this->output_title( $shortcode_args, $args );
1447
				}
1448
				$output .= $main_content;
1449
				$output .= '</div>';
1450
			} elseif ( $main_content && $no_wrap ) {
0 ignored issues
show
introduced by
$main_content is defined implicitly as null, thus it is always evaluated to false.
Loading history...
1451
				$output .= $main_content;
1452
			}
1453
1454
			// if preview show a placeholder if empty
1455
			if ( $this->is_preview() && $output == '' ) {
1456
				$output = $this->preview_placeholder_text( "{{" . $this->base_id . "}}" );
1457
			}
1458
1459
			return apply_filters( 'wp_super_duper_widget_output', $output, $args, $shortcode_args, $this );
1460
		}
1461
1462
		/**
1463
		 * Placeholder text to show if output is empty and we are on a preview/builder page.
1464
		 *
1465
		 * @param string $name
1466
		 *
1467
		 * @return string
1468
		 */
1469
		public function preview_placeholder_text( $name = '' ) {
1470
			return "<div style='background:#0185ba33;padding: 10px;border: 4px #ccc dashed;'>" . sprintf( __( 'Placeholder for: %s' ), $name ) . "</div>";
1471
		}
1472
1473
		/**
1474
		 * Sometimes booleans values can be turned to strings, so we fix that.
1475
		 *
1476
		 * @param $options
1477
		 *
1478
		 * @return mixed
1479
		 */
1480
		public function string_to_bool( $options ) {
1481
			// convert bool strings to booleans
1482
			foreach ( $options as $key => $val ) {
1483
				if ( $val == 'false' ) {
1484
					$options[ $key ] = false;
1485
				} elseif ( $val == 'true' ) {
1486
					$options[ $key ] = true;
1487
				}
1488
			}
1489
1490
			return $options;
1491
		}
1492
1493
		/**
1494
		 * Get the argument values that are also filterable.
1495
		 *
1496
		 * @param $instance
1497
		 *
1498
		 * @return array
1499
		 *@since 1.0.12 Don't set checkbox default value if the value is empty.
1500
		 *
1501
		 */
1502
		public function argument_values( $instance ) {
1503
			$argument_values = array();
1504
1505
			// set widget instance
1506
			$this->instance = $instance;
1507
1508
			if ( empty( $this->arguments ) ) {
1509
				$this->arguments = $this->get_arguments();
1510
			}
1511
1512
			if ( ! empty( $this->arguments ) ) {
1513
				foreach ( $this->arguments as $key => $args ) {
1514
					// set the input name from the key
1515
					$args['name'] = $key;
1516
					//
1517
					$argument_values[ $key ] = isset( $instance[ $key ] ) ? $instance[ $key ] : '';
1518
					if ( $args['type'] == 'checkbox' && $argument_values[ $key ] == '' ) {
1519
						// don't set default for an empty checkbox
1520
					} elseif ( $argument_values[ $key ] == '' && isset( $args['default'] ) ) {
1521
						$argument_values[ $key ] = $args['default'];
1522
					}
1523
				}
1524
			}
1525
1526
			return $argument_values;
1527
		}
1528
1529
		/**
1530
		 * Set arguments in super duper.
1531
		 *
1532
		 * @return array Set arguments.
1533
		 *@since 1.0.0
1534
		 *
1535
		 */
1536
		public function set_arguments() {
1537
			return $this->arguments;
1538
		}
1539
1540
		/**
1541
		 * Get arguments in super duper.
1542
		 *
1543
		 * @return array Get arguments.
1544
		 *@since 1.0.0
1545
		 *
1546
		 */
1547
		public function get_arguments() {
1548
			if ( empty( $this->arguments ) ) {
1549
				$this->arguments = $this->set_arguments();
1550
			}
1551
1552
			$this->arguments = apply_filters( 'wp_super_duper_arguments', $this->arguments, $this->options, $this->instance );
1553
			$this->arguments = $this->add_name_from_key( $this->arguments, true );
1554
1555
			return $this->arguments;
1556
		}
1557
1558
		/**
1559
		 * This is the main output class for all 3 items, widget, shortcode and block, it is extended in the calling class.
1560
		 *
1561
		 * @param array $args
1562
		 * @param array $widget_args
1563
		 * @param string $content
1564
		 */
1565
		public function output( $args = array(), $widget_args = array(), $content = '' ) {
0 ignored issues
show
Unused Code introduced by
The parameter $widget_args is not used and could be removed. ( Ignorable by Annotation )

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

1565
		public function output( $args = array(), /** @scrutinizer ignore-unused */ $widget_args = array(), $content = '' ) {

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

Loading history...
1566
1567
		}
1568
1569
		/**
1570
		 * Add the dynamic block code inline when the wp-block in enqueued.
1571
		 */
1572
		public function register_block() {
1573
			wp_add_inline_script( 'wp-blocks', $this->block() );
1574
			if ( class_exists( 'SiteOrigin_Panels' ) ) {
1575
				wp_add_inline_script( 'wp-blocks', $this->siteorigin_js() );
1576
			}
1577
		}
1578
1579
		/**
1580
		 * Check if we need to show advanced options.
1581
		 *
1582
		 * @return bool
1583
		 */
1584
		public function block_show_advanced() {
1585
1586
			$show      = false;
1587
			$arguments = $this->get_arguments();
1588
1589
			if ( ! empty( $arguments ) ) {
1590
				foreach ( $arguments as $argument ) {
1591
					if ( isset( $argument['advanced'] ) && $argument['advanced'] ) {
1592
						$show = true;
1593
						break; // no need to continue if we know we have it
1594
					}
1595
				}
1596
			}
1597
1598
			return $show;
1599
		}
1600
1601
		/**
1602
		 * Get the url path to the current folder.
1603
		 *
1604
		 * @return string
1605
		 */
1606
		public function get_url() {
1607
			$url = $this->url;
1608
1609
			if ( ! $url ) {
1610
				$content_dir = wp_normalize_path( untrailingslashit( WP_CONTENT_DIR ) );
1611
				$content_url = untrailingslashit( WP_CONTENT_URL );
1612
1613
				// Replace http:// to https://.
1614
				if ( strpos( $content_url, 'http://' ) === 0 && strpos( plugins_url(), 'https://' ) === 0 ) {
1615
					$content_url = str_replace( 'http://', 'https://', $content_url );
1616
				}
1617
1618
				// Check if we are inside a plugin
1619
				$file_dir = str_replace( "/includes", "", wp_normalize_path( dirname( __FILE__ ) ) );
1620
				$url = str_replace( $content_dir, $content_url, $file_dir );
1621
				$url = trailingslashit( $url );
1622
				$this->url = $url;
1623
			}
1624
1625
			return $url;
1626
		}
1627
1628
		/**
1629
		 * Get the url path to the current folder.
1630
		 *
1631
		 * @return string
1632
		 */
1633
		public function get_url_old() {
1634
1635
			$url = $this->url;
1636
1637
			if ( ! $url ) {
1638
				// check if we are inside a plugin
1639
				$file_dir = str_replace( "/includes", "", dirname( __FILE__ ) );
1640
1641
				$dir_parts = explode( "/wp-content/", $file_dir );
1642
				$url_parts = explode( "/wp-content/", plugins_url() );
1643
1644
				if ( ! empty( $url_parts[0] ) && ! empty( $dir_parts[1] ) ) {
1645
					$url       = trailingslashit( $url_parts[0] . "/wp-content/" . $dir_parts[1] );
1646
					$this->url = $url;
1647
				}
1648
			}
1649
1650
1651
			return $url;
1652
		}
1653
1654
		/**
1655
		 * Generate the block icon.
1656
		 *
1657
		 * Enables the use of Font Awesome icons.
1658
		 *
1659
		 * @note xlink:href is actually deprecated but href is not supported by all so we use both.
1660
		 *
1661
		 * @param $icon
1662
		 *
1663
		 * @return string
1664
		 *@since 1.1.0
1665
		 */
1666
		public function get_block_icon( $icon ) {
1667
1668
			// check if we have a Font Awesome icon
1669
			$fa_type = '';
1670
			if ( substr( $icon, 0, 7 ) === "fas fa-" ) {
1671
				$fa_type = 'solid';
1672
			} elseif ( substr( $icon, 0, 7 ) === "far fa-" ) {
1673
				$fa_type = 'regular';
1674
			} elseif ( substr( $icon, 0, 7 ) === "fab fa-" ) {
1675
				$fa_type = 'brands';
1676
			} else {
1677
				$icon = "'" . $icon . "'";
1678
			}
1679
1680
			// set the icon if we found one
1681
			if ( $fa_type ) {
1682
				$fa_icon = str_replace( array( "fas fa-", "far fa-", "fab fa-" ), "", $icon );
1683
				$icon    = "el('svg',{width: 20, height: 20, viewBox: '0 0 20 20'},el('use', {'xlink:href': '" . $this->get_url() . "icons/" . $fa_type . ".svg#" . $fa_icon . "','href': '" . $this->get_url() . "icons/" . $fa_type . ".svg#" . $fa_icon . "'}))";
1684
			}
1685
1686
			return $icon;
1687
		}
1688
1689
		public function group_arguments( $arguments ) {
1690
//			echo '###';print_r($arguments);
1691
			if ( ! empty( $arguments ) ) {
1692
				$temp_arguments = array();
1693
				$general        = __( "General" );
1694
				$add_sections   = false;
1695
				foreach ( $arguments as $key => $args ) {
1696
					if ( isset( $args['group'] ) ) {
1697
						$temp_arguments[ $args['group'] ][ $key ] = $args;
1698
						$add_sections                             = true;
1699
					} else {
1700
						$temp_arguments[ $general ][ $key ] = $args;
1701
					}
1702
				}
1703
1704
				// only add sections if more than one
1705
				if ( $add_sections ) {
1706
					$arguments = $temp_arguments;
1707
				}
1708
			}
1709
1710
//			echo '###';print_r($arguments);
1711
			return $arguments;
1712
		}
1713
1714
1715
		/**
1716
		 * Output the JS for building the dynamic Guntenberg block.
1717
		 *
1718
		 * @return mixed
1719
		 *@since 1.0.9 Save numbers as numbers and not strings.
1720
		 * @since 1.1.0 Font Awesome classes can be used for icons.
1721
		 * @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.
1722
		 */
1723
		public function block() {
1724
            global $sd_is_js_functions_loaded;
1725
1726
			ob_start();
1727
1728
			$show_advanced = $this->block_show_advanced();
1729
1730
1731
			?>
1732
			<script>
1733
1734
			<?php
1735
			if(!$sd_is_js_functions_loaded){
1736
                $sd_is_js_functions_loaded = true;
1737
            ?>
1738
1739
			/**
1740
 * Try to auto-recover blocks.
1741
 */
1742
function sd_auto_recover_blocks() {
1743
	var recursivelyRecoverInvalidBlockList = blocks => {
1744
		const _blocks = [...blocks]
1745
		let recoveryCalled = false
1746
		const recursivelyRecoverBlocks = willRecoverBlocks => {
1747
			willRecoverBlocks.forEach(_block => {
1748
				if (isInvalid(_block)) {
1749
					recoveryCalled = true
1750
					const newBlock = recoverBlock(_block)
1751
					for (const key in newBlock) {
1752
						_block[key] = newBlock[key]
1753
					}
1754
				}
1755
				if (_block.innerBlocks.length) {
1756
					recursivelyRecoverBlocks(_block.innerBlocks)
1757
				}
1758
			})
1759
		}
1760
1761
		recursivelyRecoverBlocks(_blocks)
1762
		return [_blocks, recoveryCalled]
1763
	}
1764
1765
	var recoverBlock = ({
1766
							name,
1767
							attributes,
1768
							innerBlocks
1769
						}) => wp.blocks.createBlock(name, attributes, innerBlocks);
1770
1771
	var recoverBlocks = blocks => {
1772
		return blocks.map(_block => {
1773
			const block = _block
1774
1775
			// If the block is a reusable block, recover the Stackable blocks inside it.
1776
			if (_block.name === 'core/block') {
1777
				const {
1778
					attributes: {
1779
						ref
1780
					}
1781
				} = _block
1782
				const parsedBlocks = wp.blocks.parse(wp.data.select('core').getEntityRecords('postType', 'wp_block', {
1783
					include: [ref]
1784
				})?.[0]?.content?.raw) || []
1785
1786
				const [recoveredBlocks, recoveryCalled] = recursivelyRecoverInvalidBlockList(parsedBlocks)
1787
1788
				if (recoveryCalled) {
1789
					console.log('Stackable notice: block ' + block.name + ' (' + block.clientId + ') was auto-recovered, you should not see this after saving your page.') // eslint-disable-line no-console
1790
					return {
1791
						blocks: recoveredBlocks,
1792
						isReusable: true,
1793
						ref,
1794
					}
1795
				}
1796
			}
1797
1798
			if (block.innerBlocks && block.innerBlocks.length) {
1799
				const newInnerBlocks = recoverBlocks(block.innerBlocks)
1800
				if (newInnerBlocks.some(block => block.recovered)) {
1801
					block.innerBlocks = newInnerBlocks
1802
					block.replacedClientId = block.clientId
1803
					block.recovered = true
1804
				}
1805
			}
1806
1807
			if (!block.isValid) {
1808
				const newBlock = recoverBlock(block)
1809
				newBlock.replacedClientId = block.clientId
1810
				newBlock.recovered = true
1811
				console.log('Stackable notice: block ' + block.name + ' (' + block.clientId + ') was auto-recovered, you should not see this after saving your page.') // eslint-disable-line no-console
1812
1813
				return newBlock
1814
			}
1815
1816
			return block
1817
		})
1818
	}
1819
1820
	// Recover all the blocks that we can find.
1821
	var mainBlocks = recoverBlocks(wp.data.select('core/block-editor').getBlocks())
1822
1823
	// Replace the recovered blocks with the new ones.
1824
	mainBlocks.forEach(block => {
1825
		if (block.isReusable && block.ref) {
1826
			// Update the reusable blocks.
1827
			wp.data.dispatch('core').editEntityRecord('postType', 'wp_block', block.ref, {
1828
				content: wp.blocks.serialize(block.blocks)
1829
			}).then(() => {
1830
				// But don't save them, let the user do the saving themselves. Our goal is to get rid of the block error visually.
1831
				// dispatch( 'core' ).saveEditedEntityRecord( 'postType', 'wp_block', block.ref )
1832
			})
1833
		}
1834
1835
		if (block.recovered && block.replacedClientId) {
1836
			wp.data.dispatch('core/block-editor').replaceBlock(block.replacedClientId, block)
1837
		}
1838
	})
1839
}
1840
1841
1842
// Wait will window is loaded before calling.
1843
window.onload = function() {
1844
	sd_auto_recover_blocks();
1845
	// fire a second time incase of load delays.
1846
	setTimeout(function(){
1847
		sd_auto_recover_blocks();
1848
	}, 2000);
1849
};
1850
1851
1852
			/**
1853
			*
1854
* @param $args
1855
* @returns {*|{}}
1856
*/
1857
            function sd_build_aui_styles($args){
1858
1859
                $styles = {};
1860
                // background color
1861
                if ( $args['bg'] !== undefined && $args['bg'] !== '' ) {
1862
                   if( $args['bg'] == 'custom-color' ){
1863
                       $styles['background-color']=  $args['bg_color'];
1864
                   }else  if( $args['bg'] == 'custom-gradient' ){
1865
                       $styles['background-image']=  $args['bg_gradient'];
1866
1867
					    // use background on text
1868
						 if( $args['bg_on_text'] !== undefined && $args['bg_on_text'] ){
1869
							$styles['backgroundClip'] = "text";
1870
							$styles['WebkitBackgroundClip'] = "text";
1871
							$styles['text-fill-color'] = "transparent";
1872
							$styles['WebkitTextFillColor'] = "transparent";
1873
						 }
1874
                   }
1875
1876
                }
1877
1878
                if( $args['bg_image'] !== undefined && $args['bg_image'] !== '' ){
1879
                    var hasImage = true
1880
                    if($styles['background-color'] !== undefined && $args['bg'] == 'custom-color'){
1881
                           $styles['background-image'] = "url("+$args['bg_image']+")";
1882
                           $styles['background-blend-mode'] =  "overlay";
1883
                    }else if($styles['background-image'] !== undefined && $args['bg'] == 'custom-gradient'){
1884
                           $styles['background-image'] +=  ",url("+$args['bg_image']+")";
1885
                    }else if($args['bg'] !== undefined && $args['bg'] != '' && $args['bg'] != 'transparent' ){
1886
                           // do nothing as we alreay have a preset
1887
                           hasImage = false;
1888
                    }else{
1889
                           $styles['background-image'] = "url("+$args['bg_image']+")";
1890
                    }
1891
1892
                    if( hasImage){
1893
                         $styles['background-size'] = "cover";
1894
1895
						 if( $args['bg_image_fixed'] !== undefined && $args['bg_image_fixed'] ){
1896
							 $styles['background-attachment'] = "fixed";
1897
						 }
1898
                    }
1899
1900
                    if( hasImage && $args['bg_image_xy'].x !== undefined && $args['bg_image_xy'].x.length){
1901
                          $styles['background-position'] =  ($args['bg_image_xy'].x * 100 ) + "% " + ( $args['bg_image_xy'].y * 100) + "%";
1902
                    }
1903
                }
1904
1905
1906
1907
				// sticky offset top
1908
				if( $args['sticky_offset_top'] !== undefined && $args['sticky_offset_top'] !== '' ){
1909
					$styles['top'] =  $args['sticky_offset_top'];
1910
				}
1911
1912
				// sticky offset bottom
1913
				if( $args['sticky_offset_bottom'] !== undefined && $args['sticky_offset_bottom'] !== '' ){
1914
					$styles['bottom'] =  $args['sticky_offset_bottom'];
1915
				}
1916
1917
				// font size
1918
				if( $args['font_size_custom'] !== undefined && $args['font_size_custom'] !== '' ){
1919
					$styles['fontSize'] =  $args['font_size_custom'] + "rem";
1920
				}
1921
1922
                return $styles;
1923
1924
            }
1925
1926
            function sd_build_aui_class($args){
1927
1928
                $classes = [];
1929
1930
                // margins
1931
	            if ( $args['mt'] !== undefined && $args['mt'] !== '' ) { $classes.push( "mt-" + $args['mt'] );  $mt = $args['mt']; }else{$mt = null;}
1932
	            if ( $args['mr'] !== undefined && $args['mr'] !== '' ) { $classes.push( "mr-" + $args['mr'] );  $mr = $args['mr']; }else{$mr = null;}
1933
	            if ( $args['mb'] !== undefined && $args['mb'] !== '' ) { $classes.push( "mb-" + $args['mb'] );  $mb = $args['mb']; }else{$mb = null;}
1934
	            if ( $args['ml'] !== undefined && $args['ml'] !== '' ) { $classes.push( "ml-" + $args['ml'] );  $ml = $args['ml']; }else{$ml = null;}
1935
1936
                // margins tablet
1937
	            if ( $args['mt_md'] !== undefined && $args['mt_md'] !== '' ) { $classes.push( "mt-md-" + $args['mt_md'] );  $mt_md = $args['mt_md']; }else{$mt_md = null;}
1938
	            if ( $args['mr_md'] !== undefined && $args['mr_md'] !== '' ) { $classes.push( "mr-md-" + $args['mr_md'] );  $mt_md = $args['mr_md']; }else{$mr_md = null;}
1939
	            if ( $args['mb_md'] !== undefined && $args['mb_md'] !== '' ) { $classes.push( "mb-md-" + $args['mb_md'] );  $mt_md = $args['mb_md']; }else{$mb_md = null;}
1940
	            if ( $args['ml_md'] !== undefined && $args['ml_md'] !== '' ) { $classes.push( "ml-md-" + $args['ml_md'] );  $mt_md = $args['ml_md']; }else{$ml_md = null;}
1941
1942
                // margins desktop
1943
                if ( $args['mt_lg'] !== undefined && $args['mt_lg'] !== '' ) { if($mt == null && $mt_md == null){ $classes.push( "mt-" + $args['mt_lg'] ); }else{$classes.push( "mt-lg-" + $args['mt_lg'] ); } }
1944
	            if ( $args['mr_lg'] !== undefined && $args['mr_lg'] !== '' ) { if($mr == null && $mr_md == null){ $classes.push( "mr-" + $args['mr_lg'] ); }else{$classes.push( "mr-lg-" + $args['mr_lg'] ); } }
1945
	            if ( $args['mb_lg'] !== undefined && $args['mb_lg'] !== '' ) { if($mb == null && $mb_md == null){ $classes.push( "mb-" + $args['mb_lg'] ); }else{$classes.push( "mb-lg-" + $args['mb_lg'] ); } }
1946
	            if ( $args['ml_lg'] !== undefined && $args['ml_lg'] !== '' ) { if($ml == null && $ml_md == null){ $classes.push( "ml-" + $args['ml_lg'] ); }else{$classes.push( "ml-lg-" + $args['ml_lg'] ); } }
1947
1948
                // padding
1949
                if ( $args['pt'] !== undefined && $args['pt'] !== '' ) { $classes.push( "pt-" + $args['pt'] ); $pt = $args['pt']; }else{$pt = null;}
1950
	            if ( $args['pr'] !== undefined && $args['pr'] !== '' ) { $classes.push( "pr-" + $args['pr'] ); $pr = $args['pt']; }else{$pr = null;}
1951
	            if ( $args['pb'] !== undefined && $args['pb'] !== '' ) { $classes.push( "pb-" + $args['pb'] ); $pb = $args['pt']; }else{$pb = null;}
1952
	            if ( $args['pl'] !== undefined && $args['pl'] !== '' ) { $classes.push( "pl-" + $args['pl'] ); $pl = $args['pt']; }else{$pl = null;}
1953
1954
                // padding tablet
1955
                if ( $args['pt_md'] !== undefined && $args['pt_md'] !== '' ) { $classes.push( "pt-md-" + $args['pt_md'] ); $pt_md = $args['pt_md']; }else{$pt_md = null;}
1956
	            if ( $args['pr_md'] !== undefined && $args['pr_md'] !== '' ) { $classes.push( "pr-md-" + $args['pr_md'] ); $pr_md = $args['pt_md']; }else{$pr_md = null;}
1957
	            if ( $args['pb_md'] !== undefined && $args['pb_md'] !== '' ) { $classes.push( "pb-md-" + $args['pb_md'] ); $pb_md = $args['pt_md']; }else{$pb_md = null;}
1958
	            if ( $args['pl_md'] !== undefined && $args['pl_md'] !== '' ) { $classes.push( "pl-md-" + $args['pl_md'] ); $pl_md = $args['pt_md']; }else{$pl_md = null;}
1959
1960
                // padding desktop
1961
                if ( $args['pt_lg'] !== undefined && $args['pt_lg'] !== '' ) { if($pt == null && $pt_md == null){ $classes.push( "pt-" + $args['pt_lg'] ); }else{$classes.push( "pt-lg-" + $args['pt_lg'] ); } }
1962
	            if ( $args['pr_lg'] !== undefined && $args['pr_lg'] !== '' ) { if($pr == null && $pr_md == null){ $classes.push( "pr-" + $args['pr_lg'] ); }else{$classes.push( "pr-lg-" + $args['pr_lg'] ); } }
1963
	            if ( $args['pb_lg'] !== undefined && $args['pb_lg'] !== '' ) { if($pb == null && $pb_md == null){ $classes.push( "pb-" + $args['pb_lg'] ); }else{$classes.push( "pb-lg-" + $args['pb_lg'] ); } }
1964
	            if ( $args['pl_lg'] !== undefined && $args['pl_lg'] !== '' ) { if($pl == null && $pl_md == null){ $classes.push( "pl-" + $args['pl_lg'] ); }else{$classes.push( "pl-lg-" + $args['pl_lg'] ); } }
1965
1966
				// row cols, mobile, tablet, desktop
1967
	            if ( $args['row_cols'] !== undefined && $args['row_cols'] !== '' ) { $classes.push( "row-cols-" + $args['row_cols'] );  $row_cols = $args['row_cols']; }else{$row_cols = null;}
1968
	            if ( $args['row_cols_md'] !== undefined && $args['row_cols_md'] !== '' ) { $classes.push( "row-cols-md-" + $args['row_cols_md'] );  $row_cols_md = $args['row_cols_md']; }else{$row_cols_md = null;}
1969
                if ( $args['row_cols_lg'] !== undefined && $args['row_cols_lg'] !== '' ) { if($row_cols == null && $row_cols_md == null){ $classes.push( "row-cols-" + $args['row_cols_lg'] ); }else{$classes.push( "row-cols-lg-" + $args['row_cols_lg'] ); } }
1970
1971
				// columns , mobile, tablet, desktop
1972
	            if ( $args['col'] !== undefined && $args['col'] !== '' ) { $classes.push( "col-" + $args['col'] );  $col = $args['col']; }else{$col = null;}
1973
	            if ( $args['col_md'] !== undefined && $args['col_md'] !== '' ) { $classes.push( "col-md-" + $args['col_md'] );  $col_md = $args['col_md']; }else{$col_md = null;}
1974
                if ( $args['col_lg'] !== undefined && $args['col_lg'] !== '' ) { if($col == null && $col_md == null){ $classes.push( "col-" + $args['col_lg'] ); }else{$classes.push( "col-lg-" + $args['col_lg'] ); } }
1975
1976
1977
                // border
1978
                if ( $args['border'] === undefined || $args['border']=='')  { }
1979
                else if ( $args['border'] !== undefined && ( $args['border']=='none' || $args['border']==='0') ) { $classes.push( "border-0" ); }
1980
	            else if ( $args['border'] !== undefined ) { $classes.push( "border border-" + $args['border'] ); }
1981
1982
                // border radius type
1983
              //  if ( $args['rounded'] !== undefined && $args['rounded'] !== '' ) { $classes.push($args['rounded']); }
1984
1985
                // border radius size
1986
                if ( $args['rounded_size'] !== undefined && $args['rounded_size'] !== '' ) {
1987
                    $classes.push("rounded-" + $args['rounded_size']);
1988
                    // if we set a size then we need to remove "rounded" if set
1989
                    var index = $classes.indexOf("rounded");
1990
                    if (index !== -1) {
1991
                      $classes.splice(index, 1);
1992
                    }
1993
                }
1994
1995
                // shadow
1996
               // if ( $args['shadow'] !== undefined && $args['shadow'] !== '' ) { $classes.push($args['shadow']); }
1997
1998
                // background
1999
                if ( $args['bg'] !== undefined  && $args['bg'] !== '' ) { $classes.push("bg-" + $args['bg']); }
2000
2001
                // text_color
2002
                if ( $args['text_color'] !== undefined && $args['text_color'] !== '' ) { $classes.push( "text-" + $args['text_color']); }
2003
2004
                // text_align
2005
                if ( $args['text_justify'] !== undefined && $args['text_justify'] ) { $classes.push('text-justify'); }
2006
                else{
2007
                    if ( $args['text_align'] !== undefined && $args['text_align'] !== '' ) { $classes.push($args['text_align']); $text_align = $args['text_align']; }else{$text_align = null;}
2008
                    if ( $args['text_align_md'] !== undefined && $args['text_align_md'] !== '' ) { $classes.push($args['text_align_md']); $text_align_md = $args['text_align_md']; }else{$text_align_md = null;}
2009
                    if ( $args['text_align_lg'] !== undefined && $args['text_align_lg'] !== '' ) { if($text_align  == null && $text_align_md == null){ $classes.push($args['text_align_lg'].replace("-lg", "")); }else{$classes.push($args['text_align_lg']);} }
2010
                }
2011
2012
				// display
2013
			  	if ( $args['display'] !== undefined && $args['display'] !== '' ) { $classes.push($args['display']); $display = $args['display']; }else{$display = null;}
2014
				if ( $args['display_md'] !== undefined && $args['display_md'] !== '' ) { $classes.push($args['display_md']); $display_md = $args['display_md']; }else{$display_md = null;}
2015
				if ( $args['display_lg'] !== undefined && $args['display_lg'] !== '' ) { if($display  == null && $display_md == null){ $classes.push($args['display_lg'].replace("-lg", "")); }else{$classes.push($args['display_lg']);} }
2016
2017
				// bgtus - background transparent until scroll
2018
                if ( $args['bgtus'] !== undefined && $args['bgtus'] ) { $classes.push("bg-transparent-until-scroll"); }
2019
2020
2021
				// build classes from build keys
2022
				$build_keys = sd_get_class_build_keys();
2023
				if ( $build_keys.length ) {
2024
					$build_keys.forEach($key => {
2025
						if ( $key == 'font_size' && $args[ $key ] == 'custom' ) {
2026
							 return;
2027
						}
2028
						if ( $args[$key] !== undefined && $args[$key] !== '' ) { $classes.push($args[$key]); }
2029
					});
2030
				}
2031
2032
                return $classes.join(" ");
2033
            }
2034
2035
			function sd_get_class_build_keys(){
2036
				return <?php echo json_encode(sd_get_class_build_keys());?>;
0 ignored issues
show
Bug introduced by
Are you sure the usage of sd_get_class_build_keys() is correct as it seems to always return null.

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

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

}

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

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

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

Loading history...
2037
			}
2038
2039
            <?php
2040
2041
2042
            }
2043
2044
			if(method_exists($this,'block_global_js')){
2045
					echo $this->block_global_js();
2046
			}
2047
			?>
2048
2049
jQuery(function() {
2050
2051
				/**
2052
				 * BLOCK: Basic
2053
				 *
2054
				 * Registering a basic block with Gutenberg.
2055
				 * Simple block, renders and saves the same content without any interactivity.
2056
				 *
2057
				 * Styles:
2058
				 *        editor.css — Editor styles for the block.
2059
				 *        style.css  — Editor & Front end styles for the block.
2060
				 */
2061
				(function (blocksx, elementx, blockEditor) {
2062
					var __ = wp.i18n.__; // The __() for internationalization.
2063
					var el = wp.element.createElement; // The wp.element.createElement() function to create elements.
2064
					var editable = wp.blocks.Editable;
2065
					var blocks = wp.blocks;
2066
					var registerBlockType = wp.blocks.registerBlockType; // The registerBlockType() to register blocks.
2067
					var is_fetching = false;
2068
					var prev_attributes = [];
2069
2070
                    var InnerBlocks = blockEditor.InnerBlocks;
2071
2072
					var term_query_type = '';
2073
					var post_type_rest_slugs = <?php if(! empty( $this->arguments ) && isset($this->arguments['post_type']['onchange_rest']['values'])){echo "[".json_encode($this->arguments['post_type']['onchange_rest']['values'])."]";}else{echo "[]";} ?>;
2074
					const taxonomies_<?php echo str_replace("-","_", $this->id);?> = [{label: "Please wait", value: 0}];
2075
					const sort_by_<?php echo str_replace("-","_", $this->id);?> = [{label: "Please wait", value: 0}];
2076
                    const MediaUpload = wp.blockEditor.MediaUpload;
2077
2078
					/**
2079
					 * Register Basic Block.
2080
					 *
2081
					 * Registers a new block provided a unique name and an object defining its
2082
					 * behavior. Once registered, the block is made available as an option to any
2083
					 * editor interface where blocks are implemented.
2084
					 *
2085
					 * @param  {string}   name     Block name.
2086
					 * @param  {Object}   settings Block settings.
2087
					 * @return {?WPBlock}          The block, if it has been successfully
2088
					 *                             registered; otherwise `undefined`.
2089
					 */
2090
					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.
2091
						apiVersion: 2,
2092
                        title: '<?php echo addslashes( $this->options['name'] ); ?>', // Block title.
2093
						description: '<?php echo addslashes( $this->options['widget_ops']['description'] )?>', // Block title.
2094
						icon: <?php echo $this->get_block_icon( $this->options['block-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/.
2095
						supports: {
2096
							<?php
2097
							if ( isset( $this->options['block-supports'] ) ) {
2098
								echo $this->array_to_attributes( $this->options['block-supports'] );
2099
							}
2100
							?>
2101
						},
2102
						<?php
2103
						if ( isset( $this->options['block-label'] ) ) {
2104
						?>
2105
						__experimentalLabel( attributes, { context } ) {
2106
                            return <?php echo $this->options['block-label']; ?>;
2107
                        },
2108
                        <?php
2109
                        }
2110
                        ?>
2111
						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.
2112
						<?php if ( isset( $this->options['block-keywords'] ) ) {
2113
						echo "keywords : " . $this->options['block-keywords'] . ",";
2114
2115
//						// block hover preview.
2116
//						$example_args = array();
2117
//						if(!empty($this->arguments)){
2118
//							foreach($this->arguments as $key => $a_args){
2119
//								if(isset($a_args['example'])){
2120
//									$example_args[$key] = $a_args['example'];
2121
//								}
2122
//							}
2123
//						}
2124
//						$viewport_width = isset($this->options['example']['viewportWidth']) ? 'viewportWidth: '.absint($this->options['example']['viewportWidth']) : '';
2125
//						if( isset( $this->options['example'] ) && $this->options['example'] === false ){
2126
//							// no preview if set to false
2127
//						}elseif( !empty( $example_args ) ){
2128
//							echo "example : {attributes:{".$this->array_to_attributes( $example_args )."},$viewport_width},";
2129
//						}elseif( !empty( $this->options['example'] ) ){
2130
//							unset($this->options['example']['viewportWidth']);
2131
//							echo "example : {".$this->array_to_attributes( $this->options['example'] ).$viewport_width."},";
2132
//						}else{
2133
//							echo 'example : {'.$viewport_width.'},';
2134
//						}
2135
2136
                        }
2137
2138
						// maybe set no_wrap
2139
						$no_wrap = isset( $this->options['no_wrap'] ) && $this->options['no_wrap'] ? true : false;
2140
						if ( isset( $this->arguments['no_wrap'] ) && $this->arguments['no_wrap'] ) {
2141
							$no_wrap = true;
2142
						}
2143
						if ( $no_wrap ) {
2144
							$this->options['block-wrap'] = '';
2145
						}
2146
2147
						// maybe load the drag/drop functions.
2148
						$img_drag_drop = false;
2149
2150
						$show_alignment = false;
2151
						// align feature
2152
						/*echo "supports: {";
2153
						echo "	align: true,";
2154
						echo "  html: false";
2155
						echo "},";*/
2156
2157
						if ( ! empty( $this->arguments ) ) {
2158
							echo "attributes : {";
2159
2160
							if ( $show_advanced ) {
2161
								echo "show_advanced: {";
2162
								echo "	type: 'boolean',";
2163
								echo "  default: false,";
2164
								echo "},";
2165
							}
2166
2167
							// block wrap element
2168
							if ( ! empty( $this->options['block-wrap'] ) ) { //@todo we should validate this?
2169
								echo "block_wrap: {";
2170
								echo "	type: 'string',";
2171
								echo "  default: '" . esc_attr( $this->options['block-wrap'] ) . "',";
2172
								echo "},";
2173
							}
2174
2175
2176
2177
							foreach ( $this->arguments as $key => $args ) {
2178
2179
								if( $args['type'] == 'image' ||  $args['type'] == 'images' ){
2180
									$img_drag_drop = true;
2181
								}
2182
2183
								// set if we should show alignment
2184
								if ( $key == 'alignment' ) {
2185
									$show_alignment = true;
2186
								}
2187
2188
								$extra = '';
0 ignored issues
show
Unused Code introduced by
The assignment to $extra is dead and can be removed.
Loading history...
2189
2190
								if ( $args['type'] == 'notice' ||  $args['type'] == 'tab' ) {
2191
									continue;
2192
								}
2193
								elseif ( $args['type'] == 'checkbox' ) {
2194
									$type    = 'boolean';
2195
									$default = isset( $args['default'] ) && $args['default'] ? 'true' : 'false';
2196
								} elseif ( $args['type'] == 'number' ) {
2197
									$type    = 'number';
2198
									$default = isset( $args['default'] ) ? "'" . $args['default'] . "'" : "''";
2199
								} elseif ( $args['type'] == 'select' && ! empty( $args['multiple'] ) ) {
2200
									$type = 'array';
2201
									if ( isset( $args['default'] ) && is_array( $args['default'] ) ) {
2202
										$default = ! empty( $args['default'] ) ? "['" . implode( "','", $args['default'] ) . "']" : "[]";
2203
									} else {
2204
										$default = isset( $args['default'] ) ? "'" . $args['default'] . "'" : "''";
2205
									}
2206
								} elseif ( $args['type'] == 'multiselect' ) {
2207
									$type    = 'array';
2208
									$default = isset( $args['default'] ) ? "'" . $args['default'] . "'" : "''";
2209
								} elseif ( $args['type'] == 'image_xy' ) {
2210
									$type    = 'object';
2211
									$default = isset( $args['default'] ) ? "'" . $args['default'] . "'" : "''";
2212
								} elseif ( $args['type'] == 'image' ) {
2213
									$type    = 'string';
2214
									$default = isset( $args['default'] ) ? "'" . $args['default'] . "'" : "''";
2215
2216
                                    // add a field for ID
2217
//                                    echo $key . "_id : {";
2218
//                                    echo "type : 'number',";
2219
//                                    echo "},";
2220
//                                    echo $key . "_xy : {";
2221
//                                    echo "type : 'object',";
2222
//                                    echo "},";
2223
2224
								} else {
2225
									$type    = !empty($args['hidden_type']) ? esc_attr($args['hidden_type']) : 'string';
2226
									$default = isset( $args['default'] ) ? "'" . $args['default'] . "'" : "''";
2227
2228
								}
2229
								echo $key . " : {";
2230
								echo "type : '$type',";
2231
								echo "default : $default,";
2232
								echo "},";
2233
							}
2234
2235
							echo "content : {type : 'string',default: 'Please select the attributes in the block settings'},";
2236
							echo "className: { type: 'string', default: '' },";
2237
2238
							echo "},";
2239
2240
						}
2241
2242
						?>
2243
2244
						// The "edit" property must be a valid function.
2245
						edit: function (props) {
2246
2247
2248
<?php
2249
// only include the drag/drop functions if required.
2250
if( $img_drag_drop ){
2251
2252
?>
2253
2254
function enableDragSort(listClass) {
2255
	setTimeout(function(){
2256
		 const sortableLists = document.getElementsByClassName(listClass);
2257
		 Array.prototype.map.call(sortableLists, (list) => {enableDragList(list)});
2258
	}, 300);
2259
}
2260
2261
function enableDragList(list) {
2262
  Array.prototype.map.call(list.children, (item) => {enableDragItem(item)});
2263
}
2264
2265
function enableDragItem(item) {
2266
  item.setAttribute('draggable', true)
2267
  item.ondrag = handleDrag;
2268
  item.ondragend = handleDrop;
2269
}
2270
2271
function handleDrag(item) {
2272
  const selectedItem = item.target,
2273
        list = selectedItem.parentNode,
2274
        x = event.clientX,
2275
        y = event.clientY;
2276
2277
  selectedItem.classList.add('drag-sort-active');
2278
  let swapItem = document.elementFromPoint(x, y) === null ? selectedItem : document.elementFromPoint(x, y);
2279
2280
  if (list === swapItem.parentNode) {
2281
    swapItem = swapItem !== selectedItem.nextSibling ? swapItem : swapItem.nextSibling;
2282
    list.insertBefore(selectedItem, swapItem);
2283
  }
2284
}
2285
2286
function handleDrop(item) {
2287
2288
	item.target.classList.remove('drag-sort-active');
2289
2290
	const newOrder = [];
2291
	let $parent = item.target.parentNode;
2292
	let $field = $parent.dataset.field;
2293
	let $imgs = JSON.parse('[' + props.attributes[$field] + ']');
2294
	item.target.parentNode.classList.add('xxx');
2295
	$children = $parent.children;
2296
2297
	Object.keys($children).forEach(function(key) {
2298
	  let $nKey = $children[key].dataset.index
2299
	  newOrder.push($imgs[$nKey]);
2300
	});
2301
2302
	// @todo find out why we need to empty the value first otherwise the order is wrong.
2303
	props.setAttributes({ [$field]: '' });
2304
	setTimeout(function(){
2305
		props.setAttributes({ [$field]: JSON.stringify(newOrder).replace('[','').replace(']','') });
2306
	}, 100);
2307
2308
}
2309
<?php } ?>
2310
2311
							if (typeof(props.attributes.styleid) !== 'undefined'){
2312
								if(props.attributes.styleid==''){ props.setAttributes({ 'styleid': 'block-'+(Math.random() + 1).toString(36).substring(2) } ); }
2313
							}
2314
2315
                            <?php
2316
                            if(!empty($this->options['block-edit-raw'])) {
2317
                                echo $this->options['block-edit-raw']; // strings have to be in single quotes, may cause issues
2318
                            }else{
2319
                            ?>
2320
2321
function hasSelectedInnerBlock(props) {
2322
    const select = wp.data.select('core/editor');
2323
    const selected = select.getBlockSelectionStart();
2324
    const inner = select.getBlock(props.clientId).innerBlocks;
2325
    for (let i = 0; i < inner.length; i++) {
2326
        if (inner[i].clientId === selected || inner[i].innerBlocks.length && hasSelectedInnerBlock(inner[i])) {
2327
            return true;
2328
        }
2329
    }
2330
    return false;
2331
};
2332
2333
const parentBlocksIDs = wp.data.select( 'core/block-editor' ).getBlockParents(props.clientId);
2334
const parentBlocks = wp.data.select('core/block-editor').getBlocksByClientId(parentBlocksIDs);
2335
// const isParentOfSelectedBlock = useSelect( ( select ) => wp.data.select( 'core/block-editor' ).hasSelectedInnerBlock( props.clientId, true ) ):
2336
    const block = wp.data.select('core/block-editor').getBlocksByClientId(props.clientId);//.[0].innerBlocks;
2337
    const childBlocks = block[0].innerBlocks;
2338
2339
2340
							var $value = '';
2341
							<?php
2342
							// if we have a post_type and a category then link them
2343
							if( isset($this->arguments['post_type']) && isset($this->arguments['category']) && !empty($this->arguments['category']['post_type_linked']) ){
2344
							?>
2345
							if(typeof(prev_attributes[props.clientId]) != 'undefined' ){
2346
								$pt = props.attributes.post_type;
2347
								if(post_type_rest_slugs.length){
2348
									$value = post_type_rest_slugs[0][$pt];
2349
								}
2350
								var run = false;
2351
2352
								if($pt != term_query_type){
2353
									run = true;
2354
									term_query_type = $pt;
2355
								}
2356
2357
								// taxonomies
2358
								if( $value && 'post_type' in prev_attributes[props.clientId] && 'category' in prev_attributes[props.clientId] && run ){
2359
									wp.apiFetch({path: "<?php if(isset($this->arguments['post_type']['onchange_rest']['path'])){echo $this->arguments['post_type']['onchange_rest']['path'];}else{'/wp/v2/"+$value+"/categories/?per_page=100';} ?>"}).then(terms => {
2360
										while (taxonomies_<?php echo str_replace("-","_", $this->id);?>.length) {
2361
										taxonomies_<?php echo str_replace("-","_", $this->id);?>.pop();
2362
									}
2363
									taxonomies_<?php echo str_replace("-","_", $this->id);?>.push({label: "All", value: 0});
2364
									jQuery.each( terms, function( key, val ) {
2365
										taxonomies_<?php echo str_replace("-","_", $this->id);?>.push({label: val.name, value: val.id});
2366
									});
2367
2368
									// setting the value back and fourth fixes the no update issue that sometimes happens where it won't update the options.
2369
									var $old_cat_value = props.attributes.category
2370
									props.setAttributes({category: [0] });
2371
									props.setAttributes({category: $old_cat_value });
2372
2373
									return taxonomies_<?php echo str_replace("-","_", $this->id);?>;
2374
								});
2375
								}
2376
2377
								// sort_by
2378
								if( $value && 'post_type' in prev_attributes[props.clientId] && 'sort_by' in prev_attributes[props.clientId] && run ){
2379
									var data = {
2380
										'action': 'geodir_get_sort_options',
2381
										'post_type': $pt
2382
									};
2383
									jQuery.post(ajaxurl, data, function(response) {
2384
										response = JSON.parse(response);
2385
										while (sort_by_<?php echo str_replace("-","_", $this->id);?>.length) {
2386
											sort_by_<?php echo str_replace("-","_", $this->id);?>.pop();
2387
										}
2388
2389
										jQuery.each( response, function( key, val ) {
2390
											sort_by_<?php echo str_replace("-","_", $this->id);?>.push({label: val, value: key});
2391
										});
2392
2393
										// setting the value back and fourth fixes the no update issue that sometimes happens where it won't update the options.
2394
										var $old_sort_by_value = props.attributes.sort_by
2395
										props.setAttributes({sort_by: [0] });
2396
										props.setAttributes({sort_by: $old_sort_by_value });
2397
2398
										return sort_by_<?php echo str_replace("-","_", $this->id);?>;
2399
									});
2400
2401
								}
2402
							}
2403
							<?php }?>
2404
// Get device type const.
2405
const { deviceType } = wp.data.useSelect( select => {
2406
        const { __experimentalGetPreviewDeviceType } = select( 'core/edit-site' ) ? select( 'core/edit-site' ) : select( 'core/edit-post' ) ; // for sie editor https://github.com/WordPress/gutenberg/issues/39248
2407
2408
        return {
2409
            deviceType: __experimentalGetPreviewDeviceType(),
2410
        }
2411
    }, [] );
2412
							var content = props.attributes.content;
2413
2414
							function onChangeContent($type) {
2415
// console.log(deviceType);
2416
								$refresh = false;
2417
								// Set the old content the same as the new one so we only compare all other attributes
2418
								if(typeof(prev_attributes[props.clientId]) != 'undefined'){
2419
									prev_attributes[props.clientId].content = props.attributes.content;
2420
								}else if(props.attributes.content === ""){
2421
									// if first load and content empty then refresh
2422
									$refresh = true;
2423
								}
2424
2425
								if ( ( !is_fetching &&  JSON.stringify(prev_attributes[props.clientId]) != JSON.stringify(props.attributes) ) || $refresh  ) {
2426
2427
									is_fetching = true;
2428
2429
									var data = {
2430
										'action': 'super_duper_output_shortcode',
2431
										'shortcode': '<?php echo $this->options['base_id'];?>',
2432
										'attributes': props.attributes,
2433
										'block_parent_name': parentBlocks.length ? parentBlocks[parentBlocks.length - 1].name : '',
2434
										'post_id': <?php global $post; if ( isset( $post->ID ) ) {
2435
										echo $post->ID;
2436
									}else{echo '0';}?>,
2437
										'_ajax_nonce': '<?php echo wp_create_nonce( 'super_duper_output_shortcode' );?>'
2438
									};
2439
2440
									jQuery.post(ajaxurl, data, function (response) {
2441
										return response;
2442
									}).then(function (env) {
2443
2444
										// if the content is empty then we place some placeholder text
2445
										if (env == '') {
2446
											env = "<div style='background:#0185ba33;padding: 10px;border: 4px #ccc dashed;'>" + "<?php _e( 'Placeholder for: ' );?>" + props.name + "</div>";
2447
										}
2448
2449
                                         <?php
2450
                                        if(!empty($this->options['nested-block'])){
2451
                                            ?>
2452
                                            // props.setAttributes({content: env});
2453
										is_fetching = false;
2454
										prev_attributes[props.clientId] = props.attributes;
2455
                                             <?php
2456
                                        }else{
2457
                                        ?>
2458
                                       props.setAttributes({content: env});
2459
										is_fetching = false;
2460
										prev_attributes[props.clientId] = props.attributes;
2461
                                        <?php
2462
                                        }
2463
                                        ?>
2464
2465
2466
										// if AUI is active call the js init function
2467
										if (typeof aui_init === "function") {
2468
											aui_init();
2469
										}
2470
									});
2471
2472
2473
								}
2474
2475
2476
								return props.attributes.content;
2477
2478
							}
2479
2480
                            <?php
2481
                            if(!empty($this->options['block-edit-js'])) {
2482
                                echo  $this->options['block-edit-js'] ; // strings have to be in single quotes, may cause issues
2483
                            }
2484
2485
2486
2487
                            ?>
2488
2489
2490
2491
							return [
2492
2493
								el(wp.blockEditor.BlockControls, {key: 'controls'},
2494
2495
									<?php if($show_alignment){?>
2496
									el(
2497
										wp.blockEditor.AlignmentToolbar,
2498
										{
2499
											value: props.attributes.alignment,
2500
											onChange: function (alignment) {
2501
												props.setAttributes({alignment: alignment})
2502
											}
2503
										}
2504
									)
2505
									<?php }?>
2506
2507
								),
2508
2509
								el(wp.blockEditor.InspectorControls, {key: 'inspector'},
2510
2511
									<?php
2512
2513
									if(! empty( $this->arguments )){
2514
2515
									if ( $show_advanced ) {
2516
									?>
2517
									el('div', {
2518
											style: {'padding-left': '16px','padding-right': '16px'}
2519
										},
2520
										el(
2521
											wp.components.ToggleControl,
2522
											{
2523
												label: 'Show Advanced Settings?',
2524
												checked: props.attributes.show_advanced,
2525
												onChange: function (show_advanced) {
2526
													props.setAttributes({show_advanced: !props.attributes.show_advanced})
2527
												}
2528
											}
2529
										)
2530
									)
2531
									,
2532
									<?php
2533
2534
									}
2535
2536
								//	print_r( $this->arguments);
2537
2538
									//echo '####';
2539
2540
									$arguments = $this->group_arguments( $this->arguments );
2541
//print_r($arguments ); exit;
2542
									// Do we have sections?
2543
									$has_sections = $arguments == $this->arguments ? false : true;
2544
2545
2546
									if($has_sections){
2547
									$panel_count = 0;
2548
									$open_tab = '';
2549
2550
									$open_tab_groups = array();
2551
									$used_tabs = array();
2552
									foreach($arguments as $key => $args){
2553
2554
										$close_tab = false;
2555
										$close_tabs = false;
2556
2557
										 if(!empty($this->options['block_group_tabs'])) {
2558
											foreach($this->options['block_group_tabs'] as $tab_name => $tab_args){
2559
												if(in_array($key,$tab_args['groups'])){
2560
2561
													$open_tab_groups[] = $key;
2562
2563
													if($open_tab != $tab_name){
2564
														$tab_args['tab']['tabs_open'] = $open_tab == '' ? true : false;
2565
														$tab_args['tab']['open'] = true;
2566
2567
														$this->block_tab_start( '', $tab_args );
2568
//														echo '###open'.$tab_name;print_r($tab_args);
2569
														$open_tab = $tab_name;
2570
														$used_tabs[] = $tab_name;
2571
													}
2572
2573
													if($open_tab_groups == $tab_args['groups']){
2574
														//$open_tab = '';
2575
														$close_tab = true;
2576
														$open_tab_groups = array();
2577
2578
//													print_r(array_keys($this->options['block_group_tabs']));echo '####';print_r($used_tabs);
2579
													if($used_tabs == array_keys($this->options['block_group_tabs'])){
2580
//														echo '@@@';
2581
															$close_tabs = true;
2582
														}
2583
													}
2584
2585
												}
2586
											}
2587
										}
2588
2589
//
2590
2591
									//	print_r($arguments);exit;
2592
2593
										?>
2594
										el(wp.components.PanelBody, {
2595
												title: '<?php esc_attr_e( $key ); ?>',
2596
												initialOpen: <?php if ( $panel_count ) {
2597
												echo "false";
2598
											} else {
2599
												echo "true";
2600
											}?>
2601
											},
2602
											<?php
2603
2604
2605
2606
											foreach ( $args as $k => $a ) {
2607
2608
												$this->block_tab_start( $k, $a );
2609
												$this->block_row_start( $k, $a );
2610
												$this->build_block_arguments( $k, $a );
2611
												$this->block_row_end( $k, $a );
2612
												$this->block_tab_end( $k, $a );
2613
											}
2614
											?>
2615
										),
2616
										<?php
2617
										$panel_count ++;
2618
2619
2620
										if($close_tab || $close_tabs){
2621
											$tab_args = array(
2622
												'tab'	=> array(
2623
													'tabs_close' => $close_tabs,
2624
												'close' => true,
2625
												)
2626
2627
											);
2628
											$this->block_tab_end( '', $tab_args );
2629
//											echo '###close'; print_r($tab_args);
2630
											$panel_count = 0;
2631
										}
2632
//
2633
2634
									}
2635
									}else {
2636
									?>
2637
									el(wp.components.PanelBody, {
2638
											title: '<?php esc_attr_e( "Settings" ); ?>',
2639
											initialOpen: true
2640
										},
2641
										<?php
2642
										foreach ( $this->arguments as $key => $args ) {
2643
											$this->block_row_start( $key, $args );
2644
											$this->build_block_arguments( $key, $args );
2645
											$this->block_row_end( $key, $args );
2646
										}
2647
										?>
2648
									),
2649
									<?php
2650
									}
2651
2652
									}
2653
									?>
2654
2655
								),
2656
2657
								<?php
2658
								// If the user sets block-output array then build it
2659
								if ( ! empty( $this->options['block-output'] ) ) {
2660
								$this->block_element( $this->options['block-output'] );
2661
							}elseif(!empty($this->options['block-edit-return'])){
2662
                                   echo $this->options['block-edit-return'];
2663
							}else{
2664
								// if no block-output is set then we try and get the shortcode html output via ajax.
2665
								?>
2666
								el('div', wp.blockEditor.useBlockProps({
2667
									dangerouslySetInnerHTML: {__html: onChangeContent()},
2668
									className: props.className,
2669
									style: {'minHeight': '30px'}
2670
								}))
2671
								<?php
2672
								}
2673
								?>
2674
							]; // end return
2675
2676
							<?php
2677
                            } // end block-edit-raw else
2678
                            ?>
2679
						},
2680
2681
						// The "save" property must be specified and must be a valid function.
2682
						save: function (props) {
2683
2684
							var attr = props.attributes;
2685
							var align = '';
2686
2687
							// build the shortcode.
2688
							var content = "[<?php echo $this->options['base_id'];?>";
2689
							$html = '';
2690
							<?php
2691
2692
							if(! empty( $this->arguments )){
2693
2694
							foreach($this->arguments as $key => $args){
2695
                               // if($args['type']=='tabs'){continue;}
2696
							?>
2697
							if (attr.hasOwnProperty("<?php echo esc_attr( $key );?>")) {
2698
								if ('<?php echo esc_attr( $key );?>' == 'html') {
2699
									$html = attr.<?php echo esc_attr( $key );?>;
2700
								} else if ('<?php echo esc_attr( $args['type'] );?>' == 'image_xy') {
2701
									content += " <?php echo esc_attr( $key );?>='{x:" + attr.<?php echo esc_attr( $key );?>.x + ",y:"+attr.<?php echo esc_attr( $key );?>.y +"}' ";
2702
								} else {
2703
									content += " <?php echo esc_attr( $key );?>='" + attr.<?php echo esc_attr( $key );?>+ "' ";
2704
								}
2705
							}
2706
							<?php
2707
							}
2708
							}
2709
2710
							?>
2711
							content += "]";
2712
2713
                            <?php
2714
//                            if(!empty($this->options['nested-block'])){
2715
//                                ?>
2716
//                                $html = 'el( InnerBlocks.Content )';
2717
//                                <?php
2718
//                            }
2719
                            ?>
2720
							// if has html element
2721
							if ($html) {
2722
								content += $html + "[/<?php echo $this->options['base_id'];?>]";
2723
							}
2724
2725
							// @todo should we add inline style here or just css classes?
2726
							if (attr.alignment) {
2727
								if (attr.alignment == 'left') {
2728
									align = 'alignleft';
2729
								}
2730
								if (attr.alignment == 'center') {
2731
									align = 'aligncenter';
2732
								}
2733
								if (attr.alignment == 'right') {
2734
									align = 'alignright';
2735
								}
2736
							}
2737
2738
							<?php
2739
//							if(!empty($this->options['nested-block'])){
2740
//                                ?x>
2741
//                              return el(
2742
//                                    'div',
2743
//                                    { className: props.className,
2744
//                                        style: {'minHeight': '300px','position':'relative','overflow':'hidden','backgroundImage': 'url(https://s.w.org/images/core/5.5/don-quixote-06.jpg)'}
2745
//                                    },
2746
//                                    el( InnerBlocks.Content ),
2747
//                                    el('div', {dangerouslySetInnerHTML: {__html: content}, className: align})
2748
//                                );
2749
//                                <x?php
2750
//							}else
2751
2752
                            if(!empty($this->options['block-output'])){
2753
//                               echo "return";
2754
//                               $this->block_element( $this->options['block-output'], true );
2755
//                               echo ";";
2756
2757
                               ?>
2758
                              return el(
2759
                                   '',
2760
                                   {},
2761
                                   el('', {dangerouslySetInnerHTML: {__html: content}}),
2762
                                   <?php $this->block_element( $this->options['block-output'], true ); ?>
2763
                                   el('', {dangerouslySetInnerHTML: {__html: "[/<?php echo $this->options['base_id'];?>]"}})
2764
                               );
2765
                                <?php
2766
2767
							}elseif(!empty($this->options['block-save-return'])){
2768
                                   echo 'return ' . $this->options['block-save-return'];
2769
							}elseif(!empty($this->options['nested-block'])){
2770
                                ?>
2771
                              return el(
2772
                                   '',
2773
                                   {},
2774
                                   el('', {dangerouslySetInnerHTML: {__html: content+"\n"}}),
2775
                                   InnerBlocks.Content ? el( InnerBlocks.Content ) : '', // @todo i think we need a comma here
2776
                                   el('', {dangerouslySetInnerHTML: {__html: "[/<?php echo $this->options['base_id'];?>]"}})
2777
                               );
2778
                                <?php
2779
							}elseif(!empty( $this->options['block-save-return'] ) ){
2780
                                echo "return ". $this->options['block-edit-return'].";";
2781
							}elseif(isset( $this->options['block-wrap'] ) && $this->options['block-wrap'] == ''){
2782
							?>
2783
							return content;
2784
							<?php
2785
							}else{
2786
							?>
2787
							var block_wrap = 'div';
2788
							if (attr.hasOwnProperty("block_wrap")) {
2789
								block_wrap = attr.block_wrap;
2790
							}
2791
							return el(block_wrap, wp.blockEditor.useBlockProps.save( {dangerouslySetInnerHTML: {__html: content}, className: align} ));
2792
							<?php
2793
							}
2794
							?>
2795
2796
2797
						}
2798
					});
2799
				})(
2800
                    window.wp.blocks,
2801
    window.wp.element,
2802
    window.wp.blockEditor
2803
				);
2804
2805
                });
2806
			</script>
2807
			<?php
2808
			$output = ob_get_clean();
2809
2810
			/*
2811
			 * We only add the <script> tags for code highlighting, so we strip them from the output.
2812
			 */
2813
2814
			return str_replace( array(
2815
				'<script>',
2816
				'</script>'
2817
			), '', $output );
2818
		}
2819
2820
2821
2822
		public function block_row_start($key, $args){
0 ignored issues
show
Unused Code introduced by
The parameter $key is not used and could be removed. ( Ignorable by Annotation )

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

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

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

Loading history...
2823
2824
			// check for row
2825
			if(!empty($args['row'])){
2826
2827
				if(!empty($args['row']['open'])){
2828
2829
				// element require
2830
				$element_require = ! empty( $args['element_require'] ) ? $this->block_props_replace( $args['element_require'], true ) . " && " : "";
2831
                $device_type = ! empty( $args['device_type'] ) ? esc_attr($args['device_type']) : '';
2832
                $device_type_require = ! empty( $args['device_type'] ) ? " deviceType == '" . esc_attr($device_type) . "' && " : '';
2833
                $device_type_icon = '';
2834
                if($device_type=='Desktop'){
2835
                    $device_type_icon = '<span class="dashicons dashicons-desktop" style="font-size: 18px;"></span>';
2836
                }elseif($device_type=='Tablet'){
2837
                    $device_type_icon = '<span class="dashicons dashicons-tablet" style="font-size: 18px;"></span>';
2838
                }elseif($device_type=='Mobile'){
2839
                    $device_type_icon = '<span class="dashicons dashicons-smartphone" style="font-size: 18px;"></span>';
2840
                }
2841
				echo $element_require;
2842
                echo $device_type_require;
2843
2844
					if(false){?><script><?php }?>
2845
						el('div', {
2846
								className: 'bsui components-base-control',
2847
							},
2848
							<?php if(!empty($args['row']['title'])){ ?>
2849
							el('label', {
2850
									className: 'components-base-control__label',
2851
									style: {width:"100%"}
2852
								},
2853
								el('span',{dangerouslySetInnerHTML: {__html: '<?php echo addslashes( $args['row']['title'] ) ?>'}}),
2854
								<?php if($device_type_icon){ ?>
2855
                                    deviceType == '<?php echo $device_type;?>' && el('span',{dangerouslySetInnerHTML: {__html: '<?php echo $device_type_icon; ?>'},title: deviceType + ": Set preview mode to change",style: {float:"right",color:"var(--wp-admin-theme-color)"}})
2856
								<?php
2857
                                }
2858
                                ?>
2859
2860
2861
							),
2862
							<?php }?>
2863
							<?php if(!empty($args['row']['desc'])){ ?>
2864
							el('p', {
2865
									className: 'components-base-control__help mb-0',
2866
								},
2867
								'<?php echo addslashes( $args['row']['desc'] ); ?>'
2868
							),
2869
							<?php }?>
2870
							el(
2871
								'div',
2872
								{
2873
									className: 'row mb-n2 <?php if(!empty($args['row']['class'])){ echo esc_attr($args['row']['class']);} ?>',
2874
								},
2875
								el(
2876
									'div',
2877
									{
2878
										className: 'col pr-2',
2879
									},
2880
2881
					<?php
2882
					if(false){?></script><?php }
2883
				}elseif(!empty($args['row']['close'])){
2884
					if(false){?><script><?php }?>
2885
						el(
2886
							'div',
2887
							{
2888
								className: 'col pl-0',
2889
							},
2890
					<?php
2891
					if(false){?></script><?php }
2892
				}else{
2893
					if(false){?><script><?php }?>
2894
						el(
2895
							'div',
2896
							{
2897
								className: 'col pl-0 pr-2',
2898
							},
2899
					<?php
2900
					if(false){?></script><?php }
2901
				}
2902
2903
			}
2904
2905
		}
2906
2907
		public function block_row_end($key, $args){
0 ignored issues
show
Unused Code introduced by
The parameter $key is not used and could be removed. ( Ignorable by Annotation )

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

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

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

Loading history...
2908
2909
			if(!empty($args['row'])){
2910
				// maybe close
2911
				if(!empty($args['row']['close'])){
2912
					echo "))";
2913
				}
2914
2915
				echo "),";
2916
			}
2917
		}
2918
2919
		public function block_tab_start($key, $args){
0 ignored issues
show
Unused Code introduced by
The parameter $key is not used and could be removed. ( Ignorable by Annotation )

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

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

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

Loading history...
2920
2921
			// check for row
2922
			if(!empty($args['tab'])){
2923
2924
				if(!empty($args['tab']['tabs_open'])){
2925
2926
					if(false){?><script><?php }?>
2927
2928
el('div',{className: 'bsui'},
2929
2930
						el('hr', {className: 'm-0'}), el(
2931
									wp.components.TabPanel,
2932
									{
2933
                                        activeClass: 'is-active',
2934
                                        className: 'btn-groupx',
2935
                                        initialTabName: '<?php echo addslashes( esc_attr( $args['tab']['key']) ); ?>',
2936
										tabs: [
2937
2938
					<?php
2939
					if(false){?></script><?php }
2940
				}
2941
2942
				if(!empty($args['tab']['open'])){
2943
2944
					if(false){?><script><?php }?>
2945
							{
2946
												name: '<?php echo addslashes( esc_attr( $args['tab']['key']) ); ?>',
2947
												title: el('div', {dangerouslySetInnerHTML: {__html: '<?php echo addslashes( esc_attr( $args['tab']['title']) ); ?>'}}),
2948
												className: '<?php echo addslashes( esc_attr( $args['tab']['class']) ); ?>',
2949
												content: el('div',{}, <?php if(!empty($args['tab']['desc'])){ ?>el('p', {
2950
									className: 'components-base-control__help mb-0',
2951
									dangerouslySetInnerHTML: {__html:'<?php echo addslashes( $args['tab']['desc'] ); ?>'}
2952
								}),<?php }
2953
					if(false){?></script><?php }
2954
				}
2955
2956
			}
2957
2958
		}
2959
2960
		public function block_tab_end($key, $args){
0 ignored issues
show
Unused Code introduced by
The parameter $key is not used and could be removed. ( Ignorable by Annotation )

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

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

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

Loading history...
2961
2962
			if(!empty($args['tab'])){
2963
				// maybe close
2964
				if(!empty($args['tab']['close'])){
2965
					echo ")}, /* tab close */";
2966
				}
2967
2968
				if(!empty($args['tab']['tabs_close'])){
2969
					if(false){?><script><?php }?>
2970
							],
2971
									},
2972
									( tab ) => {
2973
2974
									return tab.content;
2975
2976
								}
2977
								)), /* tabs close */
2978
					<?php if(false){ ?></script><?php }
2979
				}
2980
			}
2981
		}
2982
2983
		public function build_block_arguments( $key, $args ) {
2984
			$custom_attributes = ! empty( $args['custom_attributes'] ) ? $this->array_to_attributes( $args['custom_attributes'] ) : '';
2985
			$options           = '';
2986
			$extra             = '';
2987
			$require           = '';
0 ignored issues
show
Unused Code introduced by
The assignment to $require is dead and can be removed.
Loading history...
2988
            $inside_elements   = '';
2989
2990
			// `content` is a protected and special argument
2991
			if ( $key == 'content' ) {
2992
				return;
2993
			}
2994
2995
            $device_type = ! empty( $args['device_type'] ) ? esc_attr($args['device_type']) : '';
2996
            $device_type_require = ! empty( $args['device_type'] ) ? " deviceType == '" . esc_attr($device_type) . "' && " : '';
2997
            $device_type_icon = '';
2998
            if($device_type=='Desktop'){
2999
                $device_type_icon = '<span class="dashicons dashicons-desktop" style="font-size: 18px;"></span>';
3000
            }elseif($device_type=='Tablet'){
3001
                $device_type_icon = '<span class="dashicons dashicons-tablet" style="font-size: 18px;"></span>';
3002
            }elseif($device_type=='Mobile'){
3003
                $device_type_icon = '<span class="dashicons dashicons-smartphone" style="font-size: 18px;"></span>';
3004
            }
3005
3006
			// icon
3007
			$icon = '';
3008
			if( !empty( $args['icon'] ) ){
3009
				$icon .= "el('div', {";
3010
									$icon .= "dangerouslySetInnerHTML: {__html: '".self::get_widget_icon( esc_attr($args['icon']))."'},";
0 ignored issues
show
Bug Best Practice introduced by
The method WP_Super_Duper::get_widget_icon() is not static, but was called statically. ( Ignorable by Annotation )

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

3010
									$icon .= "dangerouslySetInnerHTML: {__html: '".self::/** @scrutinizer ignore-call */ get_widget_icon( esc_attr($args['icon']))."'},";
Loading history...
3011
									$icon .= "className: 'text-center',";
3012
									$icon .= "title: '".addslashes( $args['title'] )."',";
3013
								$icon .= "}),";
3014
3015
				// blank title as its added to the icon.
3016
				$args['title'] = '';
3017
			}
3018
3019
			// require advanced
3020
			$require_advanced = ! empty( $args['advanced'] ) ? "props.attributes.show_advanced && " : "";
3021
3022
			// element require
3023
			$element_require = ! empty( $args['element_require'] ) ? $this->block_props_replace( $args['element_require'], true ) . " && " : "";
3024
3025
3026
			$onchange  = "props.setAttributes({ $key: $key } )";
3027
			$onchangecomplete  = "";
3028
			$value     = "props.attributes.$key";
3029
			$text_type = array( 'text', 'password', 'number', 'email', 'tel', 'url', 'colorx','range' );
3030
			if ( in_array( $args['type'], $text_type ) ) {
3031
				$type = 'TextControl';
3032
				// Save numbers as numbers and not strings
3033
				if ( $args['type'] == 'number' ) {
3034
					$onchange = "props.setAttributes({ $key: $key ? Number($key) : '' } )";
3035
				}
3036
			}else if ( $args['type'] == 'styleid' ) {
3037
				$type = 'TextControl';
3038
				$args['type'] == 'text';
3039
				// Save numbers as numbers and not strings
3040
				$value     = "props.attributes.$key ? props.attributes.$key : 'aaabbbccc'";
3041
			}else if ( $args['type'] == 'notice' ) {
3042
3043
				$notice_message = !empty($args['desc']) ? addslashes($args['desc']) : '';
3044
				$notice_status = !empty($args['status']) ? esc_attr($args['status']) : 'info';
3045
3046
				$notice = "el('div',{className:'bsui'},el(wp.components.Notice, {status: '$notice_status',isDismissible: false,className: 'm-0 pr-0 mb-3'},el('div',{dangerouslySetInnerHTML: {__html: '$notice_message'}}))),";
3047
				echo $notice_message ? $element_require . $notice : '';
3048
				return;
3049
			}
3050
			/*
3051
			 * https://www.wptricks.com/question/set-current-tab-on-a-gutenberg-tabpanel-component-from-outside-that-component/ es5 layout
3052
						elseif($args['type']=='tabs'){
3053
							?>
3054
								el(
3055
									wp.components.TabPanel,
3056
									{
3057
                                        activeClass: 'active-tab',
3058
                                        initialTabName: deviceType,
3059
										tabs: [
3060
											{
3061
												name: 'Desktop',
3062
												title: el('div', {dangerouslySetInnerHTML: {__html: '<i class="fas fa-desktop"></i>'}}),
3063
												className: 'tab-one' + deviceType == 'Desktop' ? ' active-tab' : '',
3064
												content: el('div', {dangerouslySetInnerHTML: {__html: 'ddd'}})
3065
											},
3066
											{
3067
												name: 'Tablet',
3068
												title: el('div', {dangerouslySetInnerHTML: {__html: '<i class="fas fa-tablet-alt"></i>'}}),
3069
												className: 'tab-two' + deviceType == 'Tablet' ? ' active-tab' : '',
3070
												content: el('div', {dangerouslySetInnerHTML: {__html: 'ttt'}})
3071
											},
3072
											{
3073
												name: 'Mobile',
3074
												title: el('div', {dangerouslySetInnerHTML: {__html: '<i class="fas fa-mobile-alt"></i>'}}),
3075
												className: 'tab-two' + deviceType == 'Mobile' ? ' active-tab' : '',
3076
												content: el('div', {dangerouslySetInnerHTML: {__html: 'mmm'}})
3077
											},
3078
										],
3079
									},
3080
									( tab ) => {
3081
3082
// @todo https://github.com/WordPress/gutenberg/issues/39248
3083
									if(tab.name=='Desktop'){
3084
									wp.data.dispatch('core/edit-post').__experimentalSetPreviewDeviceType('Desktop');
3085
wp.data.select('core/edit-post').__experimentalGetPreviewDeviceType();
3086
									}else if(tab.name=='Tablet'){
3087
									wp.data.dispatch('core/edit-post').__experimentalSetPreviewDeviceType('Tablet');
3088
wp.data.select('core/edit-post').__experimentalGetPreviewDeviceType();
3089
									}else if(tab.name=='Mobile'){
3090
									wp.data.dispatch('core/edit-post').__experimentalSetPreviewDeviceType('Mobile');
3091
wp.data.select('core/edit-post').__experimentalGetPreviewDeviceType();
3092
									}
3093
3094
									return tab.content;
3095
3096
								}
3097
								),
3098
3099
							<?php
3100
							return;
3101
						}
3102
*/
3103
			elseif ( $args['type'] == 'color' ) {
3104
				$type = 'ColorPicker';
3105
				$onchange = "";
3106
				$extra = "color: $value,";
3107
				if(!empty($args['disable_alpha'])){
3108
					$extra .= "disableAlpha: true,";
3109
				}
3110
				$onchangecomplete = "onChangeComplete: function($key) {
3111
				value =  $key.rgb.a && $key.rgb.a < 1 ? \"rgba(\"+$key.rgb.r+\",\"+$key.rgb.g+\",\"+$key.rgb.b+\",\"+$key.rgb.a+\")\" : $key.hex;
3112
                        props.setAttributes({
3113
                            $key: value
3114
                        });
3115
                    },";
3116
			}elseif ( $args['type'] == 'gradient' ) {
3117
				$type = 'GradientPicker';
3118
3119
			}elseif ( $args['type'] == 'image' ) {
3120
//                print_r($args);
3121
3122
                $img_preview = isset($args['focalpoint']) && !$args['focalpoint'] ? "props.attributes.$key && el('img', { src: props.attributes.$key,style: {maxWidth:'100%',background: '#ccc'}})," : " props.attributes.$key && el(wp.components.FocalPointPicker,{
3123
                            url:props.attributes.$key,
3124
                            value: props.attributes.{$key}_xy.x !== undefined && props.attributes.{$key}_xy.x.length ? props.attributes.{$key}_xy  : {x: 0.5,y: 0.5,},
3125
                            onChange: function(focalPoint){
3126
                                              return props.setAttributes({
3127
                                                  {$key}_xy: focalPoint
3128
                                                });
3129
                                    },
3130
                                    // @todo for some reason this does not work as expected.
3131
//                         onDrag: function(focalPointTemp){
3132
//                                  return props.setAttributes({
3133
//                                      {$key}_xy: focalPointTemp
3134
//                                    });
3135
//                        }
3136
3137
3138
                        }), ";
3139
3140
3141
                $value = '""';
3142
				$type = 'MediaUpload';
3143
                $extra .= "onSelect: function(media){
3144
                      return props.setAttributes({
3145
                          $key: media.url,
3146
                          {$key}_id: media.id
3147
                        });
3148
                      },";
3149
                   $extra .= "type: 'image',";
3150
                   $extra .= "render: function (obj) {
3151
                        return el( 'div',{},
3152
                        !props.attributes.$key && el( wp.components.Button, {
3153
                          className: 'components-button components-circular-option-picker__clear is-primary is-smallx',
3154
                          onClick: obj.open
3155
                        },
3156
                        'Upload Image'
3157
                        ),
3158
                       $img_preview
3159
                        props.attributes.$key && el( wp.components.Button, {
3160
                                      className: 'components-button components-circular-option-picker__clear is-secondary is-small',
3161
                                      style: {margin:'8px 0'},
3162
                                      onClick: function(){
3163
                                              return props.setAttributes({
3164
                                                  $key: '',
3165
                                                  {$key}_id: ''
3166
                                                });
3167
                                    }
3168
                                    },
3169
                                    props.attributes.$key? 'Clear' : ''
3170
                            )
3171
                       )
3172
3173
3174
3175
                      }";
3176
                $onchange = "";
3177
3178
                //$inside_elements = ",el('div',{},'file upload')";
3179
			}elseif ( $args['type'] == 'images' ) {
3180
				//                print_r($args);
3181
3182
                $img_preview = "props.attributes.$key && (function() {
3183
3184
                        let uploads = JSON.parse('['+props.attributes.$key+']');
3185
						let images = [];
3186
                      uploads.map((upload, index) => (
3187
3188
							images.push( el('div',{className: 'col p-2',draggable: 'true','data-index': index}, el('img', { src: upload.sizes.thumbnail.url,style: {maxWidth:'100%',background: '#ccc',pointerEvents:'none'}}),el('i',{
3189
							className: 'fas fa-times-circle text-danger position-absolute  ml-n2 mt-n1 bg-white rounded-circle c-pointer',
3190
							onClick: function(){
3191
							    aui_confirm('".__('Are you sure?')."', '".__('Delete')."', '".__('Cancel')."', true).then(function(confirmed) {
3192
if (confirmed) {
3193
											let new_uploads = JSON.parse(props.attributes.$key);
3194
											new_uploads.splice(index, 1); //remove
3195
                                              return props.setAttributes({
3196
                                                  {$key}: JSON.stringify( new_uploads ),
3197
                                                });
3198
                                                }
3199
                                           });
3200
                                    }},'') ) )
3201
						));
3202
3203
3204
						return images;
3205
})(),";
3206
3207
3208
                $value = '""';
3209
				$type = 'MediaUpload';
3210
                $extra .= "onSelect: function(media){
3211
3212
                let slim_images = props.attributes.$key ? JSON.parse('['+props.attributes.$key+']') : [];
3213
				if(media.length){
3214
						for (var i=0; i < media.length; i++) {
3215
							slim_images.push({id: media[i].id, caption: media[i].caption, description: media[i].description,title: media[i].title,alt: media[i].alt,sizes: media[i].sizes});
3216
						}
3217
				}
3218
3219
                      return props.setAttributes({
3220
                          $key: JSON.stringify(slim_images).replace('[','').replace(']',''),
3221
                        });
3222
                      },";
3223
                   $extra .= "type: 'image',";
3224
                   $extra .= "multiple: true,";
3225
                   $extra .= "render: function (obj) {
3226
3227
                   // init the sort
3228
				enableDragSort('sd-sortable');
3229
                        return el( 'div',{},
3230
                        el( wp.components.Button, {
3231
                          className: 'components-button components-circular-option-picker__clear is-primary is-smallx',
3232
                          onClick: obj.open
3233
                        },
3234
                        'Upload Images'
3235
                        ),
3236
3237
3238
						el('div',{className: 'row row-cols-3 px-2 sd-sortable','data-field':'$key'},
3239
3240
                       $img_preview
3241
3242
                       ),
3243
                        props.attributes.$key && el( wp.components.Button, {
3244
                                      className: 'components-button components-circular-option-picker__clear is-secondary is-small',
3245
                                      style: {margin:'8px 0'},
3246
                                      onClick: function(){
3247
                                              return props.setAttributes({
3248
                                                  $key: '',
3249
                                                });
3250
                                    }
3251
                                    },
3252
                                    props.attributes.$key? 'Clear All' : ''
3253
                            )
3254
                       )
3255
3256
3257
3258
3259
3260
                      }";
3261
                $onchange = "";
3262
3263
                //$inside_elements = ",el('div',{},'file upload')";
3264
			}
3265
			elseif ( $args['type'] == 'checkbox' ) {
3266
				$type = 'CheckboxControl';
3267
				$extra .= "checked: props.attributes.$key,";
3268
				$onchange = "props.setAttributes({ $key: ! props.attributes.$key } )";
3269
			} elseif ( $args['type'] == 'textarea' ) {
3270
				$type = 'TextareaControl';
3271
			} elseif ( $args['type'] == 'select' || $args['type'] == 'multiselect' ) {
3272
				$type = 'SelectControl';
3273
3274
				if($args['name'] == 'category' && !empty($args['post_type_linked'])){
3275
					$options .= "options: taxonomies_".str_replace("-","_", $this->id).",";
3276
				}elseif($args['name'] == 'sort_by' && !empty($args['post_type_linked'])){
3277
					$options .= "options: sort_by_".str_replace("-","_", $this->id).",";
3278
				}else {
3279
3280
					if ( ! empty( $args['options'] ) ) {
3281
						$options .= "options: [";
3282
						foreach ( $args['options'] as $option_val => $option_label ) {
3283
							$options .= "{ value: '" . esc_attr( $option_val ) . "', label: '" . addslashes( $option_label ) . "' },";
3284
						}
3285
						$options .= "],";
3286
					}
3287
				}
3288
				if ( isset( $args['multiple'] ) && $args['multiple'] ) { //@todo multiselect does not work at the moment: https://github.com/WordPress/gutenberg/issues/5550
3289
					$extra .= ' multiple:true,style:{height:"auto",paddingRight:"8px"}, ';
3290
				}
3291
			} elseif ( $args['type'] == 'alignment' ) {
3292
				$type = 'AlignmentToolbar'; // @todo this does not seem to work but cant find a example
3293
			}elseif ( $args['type'] == 'margins' ) {
3294
3295
			} else {
3296
				return;// if we have not implemented the control then don't break the JS.
3297
			}
3298
3299
3300
3301
			// color input does not show the labels so we add them
3302
			if($args['type']=='color'){
3303
				// add show only if advanced
3304
				echo $require_advanced;
3305
				// add setting require if defined
3306
				echo $element_require;
3307
				echo "el('div', {style: {'marginBottom': '8px'}}, '".addslashes( $args['title'] )."'),";
3308
			}
3309
3310
			// add show only if advanced
3311
			echo $require_advanced;
3312
			// add setting require if defined
3313
			echo $element_require;
3314
            echo $device_type_require;
3315
3316
			// icon
3317
			echo $icon;
3318
			?>
3319
			el( <?php echo $args['type'] == 'image' || $args['type'] == 'images' ? $type  : "wp.components.".$type; ?>, {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $type does not seem to be defined for all execution paths leading up to this point.
Loading history...
3320
			label: <?php
3321
			if(empty($args['title'])){
3322
                echo "''";
3323
			}elseif(empty($args['row']) && !empty($args['device_type'])){
3324
                ?>el('label', {
3325
									className: 'components-base-control__label',
3326
									style: {width:"100%"}
3327
								},
3328
								el('span',{dangerouslySetInnerHTML: {__html: '<?php echo addslashes( $args['title'] ) ?>'}}),
3329
								<?php if($device_type_icon){ ?>
3330
                                    deviceType == '<?php echo $device_type;?>' && el('span',{dangerouslySetInnerHTML: {__html: '<?php echo $device_type_icon; ?>'},title: deviceType + ": Set preview mode to change",style: {right:"0",position:"absolute",color:"var(--wp-admin-theme-color)"}})
3331
								<?php
3332
                                }
3333
                                ?>
3334
3335
3336
							)<?php
3337
3338
			}else{
3339
                 ?>'<?php echo addslashes( $args['title'] ); ?>'<?php
3340
3341
			}
3342
3343
			?>,
3344
			help: <?php if ( isset( $args['desc'] ) ) {
3345
				echo "el('span',{dangerouslySetInnerHTML: {__html: '".wp_kses_post( addslashes($args['desc']) )."'}})";
3346
			}else{ echo "''"; } ?>,
3347
			value: <?php echo $value; ?>,
3348
			<?php if ( $type == 'TextControl' && $args['type'] != 'text' ) {
3349
				echo "type: '" . addslashes( $args['type'] ) . "',";
3350
			} ?>
3351
			<?php if ( ! empty( $args['placeholder'] ) ) {
3352
				echo "placeholder: '" . addslashes( $args['placeholder'] ) . "',";
3353
			} ?>
3354
			<?php echo $options; ?>
3355
			<?php echo $extra; ?>
3356
			<?php echo $custom_attributes; ?>
3357
			<?php echo $onchangecomplete;
3358
            if($onchange){
3359
            ?>
3360
			onChange: function ( <?php echo $key; ?> ) {
3361
			<?php echo $onchange; ?>
3362
			}
3363
			<?php }?>
3364
			} <?php echo $inside_elements; ?> ),
3365
			<?php
3366
3367
3368
		}
3369
3370
		/**
3371
		 * Convert an array of attributes to block string.
3372
		 *
3373
		 * @param $custom_attributes
3374
		 *
3375
		 * @return string
3376
		 *@todo there is prob a faster way to do this, also we could add some validation here.
3377
		 *
3378
		 */
3379
		public function array_to_attributes( $custom_attributes, $html = false ) {
3380
			$attributes = '';
3381
			if ( ! empty( $custom_attributes ) ) {
3382
3383
				foreach ( $custom_attributes as $key => $val ) {
3384
					if(is_array($val)){
3385
						$attributes .= $key.': {'.$this->array_to_attributes( $val, $html ).'},';
3386
					}else{
3387
						$attributes .= $html ?  " $key='$val' " : "'$key': '$val',";
3388
					}
3389
				}
3390
3391
			}
3392
3393
			return $attributes;
3394
		}
3395
3396
3397
3398
		/**
3399
		 * A self looping function to create the output for JS block elements.
3400
		 *
3401
		 * This is what is output in the WP Editor visual view.
3402
		 *
3403
		 * @param $args
3404
		 */
3405
		public function block_element( $args, $save = false ) {
3406
3407
3408
			if ( ! empty( $args ) ) {
3409
				foreach ( $args as $element => $new_args ) {
3410
3411
					if ( is_array( $new_args ) ) { // its an element
3412
3413
3414
						if ( isset( $new_args['element'] ) ) {
3415
3416
							if ( isset( $new_args['element_require'] ) ) {
3417
								echo str_replace( array(
3418
										"'+",
3419
										"+'"
3420
									), '', $this->block_props_replace( $new_args['element_require'] ) ) . " &&  ";
3421
								unset( $new_args['element_require'] );
3422
							}
3423
3424
                            if($new_args['element']=='InnerBlocks'){
3425
                                echo "\n el( InnerBlocks, {";
3426
                            }elseif($new_args['element']=='innerBlocksProps'){
3427
                                $element = isset($new_args['inner_element']) ? esc_attr($new_args['inner_element']) : 'div';
3428
                              //  echo "\n el( 'section', wp.blockEditor.useInnerBlocksProps( blockProps, {";
3429
//                                echo $save ? "\n el( '$element', wp.blockEditor.useInnerBlocksProps.save( " : "\n el( '$element', wp.blockEditor.useInnerBlocksProps( ";
3430
                                echo $save ? "\n el( '$element', wp.blockEditor.useInnerBlocksProps.save( " : "\n el( '$element', wp.blockEditor.useInnerBlocksProps( ";
3431
                                echo $save ? "wp.blockEditor.useBlockProps.save( {" : "wp.blockEditor.useBlockProps( {";
3432
                                echo !empty($new_args['blockProps']) ? $this->block_element( $new_args['blockProps'],$save ) : '';
3433
3434
                                echo "} ), {";
3435
                                echo !empty($new_args['innerBlocksProps']) && !$save ? $this->block_element( $new_args['innerBlocksProps'],$save ) : '';
3436
                            //    echo '###';
3437
3438
                              //  echo '###';
3439
                            }elseif($new_args['element']=='BlocksProps'){
3440
3441
								if ( isset($new_args['if_inner_element']) ) {
3442
									$element = $new_args['if_inner_element'];
3443
								}else {
3444
									$element = isset($new_args['inner_element']) ? "'".esc_attr($new_args['inner_element'])."'" : "'div'";
3445
								}
3446
3447
								unset($new_args['inner_element']);
3448
                                echo $save ? "\n el( $element, wp.blockEditor.useBlockProps.save( {" : "\n el( $element, wp.blockEditor.useBlockProps( {";
3449
                                echo !empty($new_args['blockProps']) ? $this->block_element( $new_args['blockProps'],$save ) : '';
3450
3451
3452
                               // echo "} ),";
3453
3454
                            }else{
3455
                                echo "\n el( '" . $new_args['element'] . "', {";
3456
                            }
3457
3458
3459
							// get the attributes
3460
							foreach ( $new_args as $new_key => $new_value ) {
3461
3462
3463
								if ( $new_key == 'element' || $new_key == 'content'|| $new_key == 'if_content' || $new_key == 'element_require' || $new_key == 'element_repeat' || is_array( $new_value ) ) {
3464
									// do nothing
3465
								} else {
3466
									echo $this->block_element( array( $new_key => $new_value ),$save );
3467
								}
3468
							}
3469
3470
							echo $new_args['element']=='BlocksProps' ? '} ),' : "},";// end attributes
3471
3472
							// get the content
3473
							$first_item = 0;
3474
							foreach ( $new_args as $new_key => $new_value ) {
3475
								if ( $new_key === 'content' || $new_key === 'if_content' || is_array( $new_value ) ) {
3476
3477
									if ( $new_key === 'content' ) {
3478
										echo "'" . $this->block_props_replace( wp_slash( $new_value ) ) . "'";
3479
									}else if ( $new_key === 'if_content' ) {
3480
										echo  $this->block_props_replace(  $new_value  );
3481
									}
3482
3483
									if ( is_array( $new_value ) ) {
3484
3485
										if ( isset( $new_value['element_require'] ) ) {
3486
											echo str_replace( array(
3487
													"'+",
3488
													"+'"
3489
												), '', $this->block_props_replace( $new_value['element_require'] ) ) . " &&  ";
3490
											unset( $new_value['element_require'] );
3491
										}
3492
3493
										if ( isset( $new_value['element_repeat'] ) ) {
3494
											$x = 1;
3495
											while ( $x <= absint( $new_value['element_repeat'] ) ) {
3496
												$this->block_element( array( '' => $new_value ),$save );
3497
												$x ++;
3498
											}
3499
										} else {
3500
											$this->block_element( array( '' => $new_value ),$save );
3501
										}
3502
									}
3503
									$first_item ++;
3504
								}
3505
							}
3506
3507
                            if($new_args['element']=='innerBlocksProps' || $new_args['element']=='xBlocksProps'){
3508
                                echo "))";// end content
3509
                            }else{
3510
                                echo ")";// end content
3511
                            }
3512
3513
3514
							echo ", \n";
3515
3516
						}
3517
					} else {
3518
3519
						if ( substr( $element, 0, 3 ) === "if_" ) {
3520
							$extra = '';
0 ignored issues
show
Unused Code introduced by
The assignment to $extra is dead and can be removed.
Loading history...
3521
							if( strpos($new_args, '[%WrapClass%]') !== false ){
3522
								$new_args = str_replace('[%WrapClass%]"','" + sd_build_aui_class(props.attributes)',$new_args);
3523
								$new_args = str_replace('[%WrapClass%]','+ sd_build_aui_class(props.attributes)',$new_args);
3524
							}
3525
							echo str_replace( "if_", "", $element ) . ": " . $this->block_props_replace( $new_args, true ) . ",";
3526
						} elseif ( $element == 'style' &&  strpos($new_args, '[%WrapStyle%]') !== false ) {
3527
                            $new_args = str_replace('[%WrapStyle%]','',$new_args);
3528
                            echo $element . ": {..." . $this->block_props_replace( $new_args ) . " , ...sd_build_aui_styles(props.attributes) },";
3529
//                            echo $element . ": " . $this->block_props_replace( $new_args ) . ",";
3530
						} elseif ( $element == 'style' ) {
3531
							echo $element . ": " . $this->block_props_replace( $new_args ) . ",";
3532
						} elseif ( ( $element == 'class' || $element == 'className'  ) &&  strpos($new_args, '[%WrapClass%]') !== false ) {
3533
                            $new_args = str_replace('[%WrapClass%]','',$new_args);
3534
                            echo $element . ": '" . $this->block_props_replace( $new_args ) . "' + sd_build_aui_class(props.attributes),";
3535
						} elseif ( $element == 'template' && $new_args ) {
3536
							echo $element . ": $new_args,";
3537
						} else {
3538
							echo $element . ": '" . $this->block_props_replace( $new_args ) . "',";
3539
						}
3540
3541
					}
3542
				}
3543
			}
3544
		}
3545
3546
		/**
3547
		 * Replace block attributes placeholders with the proper naming.
3548
		 *
3549
		 * @param $string
3550
		 *
3551
		 * @return mixed
3552
		 */
3553
		public function block_props_replace( $string, $no_wrap = false ) {
3554
3555
			if ( $no_wrap ) {
3556
				$string = str_replace( array( "[%", "%]" ), array( "props.attributes.", "" ), $string );
3557
			} else {
3558
				$string = str_replace( array( "[%", "%]" ), array( "'+props.attributes.", "+'" ), $string );
3559
			}
3560
3561
			return $string;
3562
		}
3563
3564
		/**
3565
		 * Outputs the content of the widget
3566
		 *
3567
		 * @param array $args
3568
		 * @param array $instance
3569
		 */
3570
		public function widget( $args, $instance ) {
3571
3572
			// get the filtered values
3573
			$argument_values = $this->argument_values( $instance );
3574
			$argument_values = $this->string_to_bool( $argument_values );
3575
			$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) targeting 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...
3576
3577
			$no_wrap = false;
3578
			if ( isset( $argument_values['no_wrap'] ) && $argument_values['no_wrap'] ) {
3579
				$no_wrap = true;
3580
			}
3581
3582
			ob_start();
3583
			if ( $output && ! $no_wrap ) {
0 ignored issues
show
introduced by
$output is defined implicitly as null, thus it is always evaluated to false.
Loading history...
3584
3585
				$class_original = $this->options['widget_ops']['classname'];
3586
				$class = $this->options['widget_ops']['classname']." sdel-".$this->get_instance_hash();
3587
3588
				// Before widget
3589
				$before_widget = $args['before_widget'];
3590
				$before_widget = str_replace($class_original,$class,$before_widget);
3591
				$before_widget = apply_filters( 'wp_super_duper_before_widget', $before_widget, $args, $instance, $this );
3592
				$before_widget = apply_filters( 'wp_super_duper_before_widget_' . $this->base_id, $before_widget, $args, $instance, $this );
3593
3594
				// After widget
3595
				$after_widget = $args['after_widget'];
3596
				$after_widget = apply_filters( 'wp_super_duper_after_widget', $after_widget, $args, $instance, $this );
3597
				$after_widget = apply_filters( 'wp_super_duper_after_widget_' . $this->base_id, $after_widget, $args, $instance, $this );
3598
3599
				echo $before_widget;
3600
				// elementor strips the widget wrapping div so we check for and add it back if needed
3601
				if ( $this->is_elementor_widget_output() ) {
3602
					// Filter class & attrs for elementor widget output.
3603
					$class = apply_filters( 'wp_super_duper_div_classname', $class, $args, $this );
3604
					$class = apply_filters( 'wp_super_duper_div_classname_' . $this->base_id, $class, $args, $this );
3605
3606
					$attrs = apply_filters( 'wp_super_duper_div_attrs', '', $args, $this );
0 ignored issues
show
Unused Code introduced by
The assignment to $attrs is dead and can be removed.
Loading history...
3607
					$attrs = apply_filters( 'wp_super_duper_div_attrs_' . $this->base_id, '', $args, $this );
3608
3609
					echo "<span class='" . esc_attr( $class  ) . "' " . $attrs . ">";
3610
				}
3611
				echo $this->output_title( $args, $instance );
3612
				echo $output;
3613
				if ( $this->is_elementor_widget_output() ) {
3614
					echo "</span>";
3615
				}
3616
				echo $after_widget;
3617
			} elseif ( $this->is_preview() && $output == '' ) {// if preview show a placeholder if empty
3618
				$output = $this->preview_placeholder_text( "{{" . $this->base_id . "}}" );
3619
				echo $output;
3620
			} elseif ( $output && $no_wrap ) {
0 ignored issues
show
introduced by
$output is defined implicitly as null, thus it is always evaluated to false.
Loading history...
3621
				echo $output;
3622
			}
3623
			$output = ob_get_clean();
3624
3625
			$output = apply_filters( 'wp_super_duper_widget_output', $output, $instance, $args, $this );
3626
3627
			echo $output;
3628
		}
3629
3630
		/**
3631
		 * Tests if the current output is inside a elementor container.
3632
		 *
3633
		 * @return bool
3634
		 *@since 1.0.4
3635
		 */
3636
		public function is_elementor_widget_output() {
3637
			$result = false;
3638
			if ( defined( 'ELEMENTOR_VERSION' ) && isset( $this->number ) && $this->number == 'REPLACE_TO_ID' ) {
3639
				$result = true;
3640
			}
3641
3642
			return $result;
3643
		}
3644
3645
		/**
3646
		 * Tests if the current output is inside a elementor preview.
3647
		 *
3648
		 * @return bool
3649
		 *@since 1.0.4
3650
		 */
3651
		public function is_elementor_preview() {
3652
			$result = false;
3653
			if ( isset( $_REQUEST['elementor-preview'] ) || ( is_admin() && isset( $_REQUEST['action'] ) && $_REQUEST['action'] == 'elementor' ) || ( isset( $_REQUEST['action'] ) && $_REQUEST['action'] == 'elementor_ajax' ) ) {
3654
				$result = true;
3655
			}
3656
3657
			return $result;
3658
		}
3659
3660
		/**
3661
		 * Tests if the current output is inside a Divi preview.
3662
		 *
3663
		 * @return bool
3664
		 *@since 1.0.6
3665
		 */
3666
		public function is_divi_preview() {
3667
			$result = false;
3668
			if ( isset( $_REQUEST['et_fb'] ) || isset( $_REQUEST['et_pb_preview'] ) || ( is_admin() && isset( $_REQUEST['action'] ) && $_REQUEST['action'] == 'elementor' ) ) {
3669
				$result = true;
3670
			}
3671
3672
			return $result;
3673
		}
3674
3675
		/**
3676
		 * Tests if the current output is inside a Beaver builder preview.
3677
		 *
3678
		 * @return bool
3679
		 *@since 1.0.6
3680
		 */
3681
		public function is_beaver_preview() {
3682
			$result = false;
3683
			if ( isset( $_REQUEST['fl_builder'] ) ) {
3684
				$result = true;
3685
			}
3686
3687
			return $result;
3688
		}
3689
3690
		/**
3691
		 * Tests if the current output is inside a siteorigin builder preview.
3692
		 *
3693
		 * @return bool
3694
		 *@since 1.0.6
3695
		 */
3696
		public function is_siteorigin_preview() {
3697
			$result = false;
3698
			if ( ! empty( $_REQUEST['siteorigin_panels_live_editor'] ) ) {
3699
				$result = true;
3700
			}
3701
3702
			return $result;
3703
		}
3704
3705
		/**
3706
		 * Tests if the current output is inside a cornerstone builder preview.
3707
		 *
3708
		 * @return bool
3709
		 *@since 1.0.8
3710
		 */
3711
		public function is_cornerstone_preview() {
3712
			$result = false;
3713
			if ( ! empty( $_REQUEST['cornerstone_preview'] ) || basename( $_SERVER['REQUEST_URI'] ) == 'cornerstone-endpoint' ) {
3714
				$result = true;
3715
			}
3716
3717
			return $result;
3718
		}
3719
3720
		/**
3721
		 * Tests if the current output is inside a fusion builder preview.
3722
		 *
3723
		 * @return bool
3724
		 *@since 1.1.0
3725
		 */
3726
		public function is_fusion_preview() {
3727
			$result = false;
3728
			if ( ! empty( $_REQUEST['fb-edit'] ) || ! empty( $_REQUEST['fusion_load_nonce'] ) ) {
3729
				$result = true;
3730
			}
3731
3732
			return $result;
3733
		}
3734
3735
		/**
3736
		 * Tests if the current output is inside a Oxygen builder preview.
3737
		 *
3738
		 * @return bool
3739
		 *@since 1.0.18
3740
		 */
3741
		public function is_oxygen_preview() {
3742
			$result = false;
3743
			if ( ! empty( $_REQUEST['ct_builder'] ) || ( ! empty( $_REQUEST['action'] ) && ( substr( $_REQUEST['action'], 0, 11 ) === "oxy_render_" || substr( $_REQUEST['action'], 0, 10 ) === "ct_render_" ) ) ) {
3744
				$result = true;
3745
			}
3746
3747
			return $result;
3748
		}
3749
3750
		/**
3751
		 * General function to check if we are in a preview situation.
3752
		 *
3753
		 * @return bool
3754
		 *@since 1.0.6
3755
		 */
3756
		public function is_preview() {
3757
			$preview = false;
3758
			if ( $this->is_divi_preview() ) {
3759
				$preview = true;
3760
			} elseif ( $this->is_elementor_preview() ) {
3761
				$preview = true;
3762
			} elseif ( $this->is_beaver_preview() ) {
3763
				$preview = true;
3764
			} elseif ( $this->is_siteorigin_preview() ) {
3765
				$preview = true;
3766
			} elseif ( $this->is_cornerstone_preview() ) {
3767
				$preview = true;
3768
			} elseif ( $this->is_fusion_preview() ) {
3769
				$preview = true;
3770
			} elseif ( $this->is_oxygen_preview() ) {
3771
				$preview = true;
3772
			} elseif( $this->is_block_content_call() ) {
3773
				$preview = true;
3774
			}
3775
3776
			return $preview;
3777
		}
3778
3779
		/**
3780
		 * Output the super title.
3781
		 *
3782
		 * @param $args
3783
		 * @param array $instance
3784
		 *
3785
		 * @return string
3786
		 */
3787
		public function output_title( $args, $instance = array() ) {
3788
			$output = '';
3789
			if ( ! empty( $instance['title'] ) ) {
3790
				/** This filter is documented in wp-includes/widgets/class-wp-widget-pages.php */
3791
				$title  = apply_filters( 'widget_title', $instance['title'], $instance, $this->id_base );
3792
3793
				if(empty($instance['widget_title_tag'])){
3794
					$output = $args['before_title'] . $title . $args['after_title'];
3795
				}else{
3796
					$title_tag = esc_attr( $instance['widget_title_tag'] );
3797
3798
					// classes
3799
					$title_classes = array();
3800
					$title_classes[] = !empty( $instance['widget_title_size_class'] ) ? sanitize_html_class( $instance['widget_title_size_class'] ) : '';
3801
					$title_classes[] = !empty( $instance['widget_title_align_class'] ) ? sanitize_html_class( $instance['widget_title_align_class'] ) : '';
3802
					$title_classes[] = !empty( $instance['widget_title_color_class'] ) ? "text-".sanitize_html_class( $instance['widget_title_color_class'] ) : '';
3803
					$title_classes[] = !empty( $instance['widget_title_border_class'] ) ? sanitize_html_class( $instance['widget_title_border_class'] ) : '';
3804
					$title_classes[] = !empty( $instance['widget_title_border_color_class'] ) ? "border-".sanitize_html_class( $instance['widget_title_border_color_class'] ) : '';
3805
					$title_classes[] = !empty( $instance['widget_title_mt_class'] ) ? "mt-".absint( $instance['widget_title_mt_class'] ) : '';
3806
					$title_classes[] = !empty( $instance['widget_title_mr_class'] ) ? "mr-".absint( $instance['widget_title_mr_class'] ) : '';
3807
					$title_classes[] = !empty( $instance['widget_title_mb_class'] ) ? "mb-".absint( $instance['widget_title_mb_class'] ) : '';
3808
					$title_classes[] = !empty( $instance['widget_title_ml_class'] ) ? "ml-".absint( $instance['widget_title_ml_class'] ) : '';
3809
					$title_classes[] = !empty( $instance['widget_title_pt_class'] ) ? "pt-".absint( $instance['widget_title_pt_class'] ) : '';
3810
					$title_classes[] = !empty( $instance['widget_title_pr_class'] ) ? "pr-".absint( $instance['widget_title_pr_class'] ) : '';
3811
					$title_classes[] = !empty( $instance['widget_title_pb_class'] ) ? "pb-".absint( $instance['widget_title_pb_class'] ) : '';
3812
					$title_classes[] = !empty( $instance['widget_title_pl_class'] ) ? "pl-".absint( $instance['widget_title_pl_class'] ) : '';
3813
3814
					$class = !empty( $title_classes ) ? implode(" ",$title_classes) : '';
3815
					$output = "<$title_tag class='$class' >$title</$title_tag>";
3816
				}
3817
3818
			}
3819
3820
			return $output;
3821
		}
3822
3823
		/**
3824
		 * Outputs the options form inputs for the widget.
3825
		 *
3826
		 * @param array $instance The widget options.
3827
		 */
3828
		public function form( $instance ) {
3829
3830
			// set widget instance
3831
			$this->instance = $instance;
3832
3833
			// set it as a SD widget
3834
			echo $this->widget_advanced_toggle();
3835
3836
			echo "<p>" . esc_attr( $this->options['widget_ops']['description'] ) . "</p>";
3837
			$arguments_raw = $this->get_arguments();
3838
3839
			if ( is_array( $arguments_raw ) ) {
0 ignored issues
show
introduced by
The condition is_array($arguments_raw) is always true.
Loading history...
3840
3841
				$arguments = $this->group_arguments( $arguments_raw );
3842
3843
				// Do we have sections?
3844
				$has_sections = $arguments == $arguments_raw ? false : true;
3845
3846
3847
				if ( $has_sections ) {
3848
					$panel_count = 0;
3849
					foreach ( $arguments as $key => $args ) {
3850
3851
						?>
3852
						<script>
3853
							//							jQuery(this).find("i").toggleClass("fas fa-chevron-up fas fa-chevron-down");jQuery(this).next().toggle();
3854
						</script>
3855
						<?php
3856
3857
						$hide       = $panel_count ? ' style="display:none;" ' : '';
3858
						$icon_class = $panel_count ? 'fas fa-chevron-up' : 'fas fa-chevron-down';
3859
						echo "<button onclick='jQuery(this).find(\"i\").toggleClass(\"fas fa-chevron-up fas fa-chevron-down\");jQuery(this).next().slideToggle();' type='button' class='sd-toggle-group-button sd-input-group-toggle" . sanitize_title_with_dashes( $key ) . "'>" . esc_attr( $key ) . " <i style='float:right;' class='" . $icon_class . "'></i></button>";
3860
						echo "<div class='sd-toggle-group sd-input-group-" . sanitize_title_with_dashes( $key ) . "' $hide>";
3861
3862
						foreach ( $args as $k => $a ) {
3863
3864
							$this->widget_inputs_row_start($k, $a);
3865
							$this->widget_inputs( $a, $instance );
3866
							$this->widget_inputs_row_end($k, $a);
3867
3868
						}
3869
3870
						echo "</div>";
3871
3872
						$panel_count ++;
3873
3874
					}
3875
				} else {
3876
					foreach ( $arguments as $key => $args ) {
3877
						$this->widget_inputs_row_start($key, $args);
3878
						$this->widget_inputs( $args, $instance );
3879
						$this->widget_inputs_row_end($key, $args);
3880
					}
3881
				}
3882
3883
			}
3884
		}
3885
3886
		public function widget_inputs_row_start($key, $args){
0 ignored issues
show
Unused Code introduced by
The parameter $key is not used and could be removed. ( Ignorable by Annotation )

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

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

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

Loading history...
3887
			if(!empty($args['row'])){
3888
				// maybe open
3889
				if(!empty($args['row']['open'])){
3890
					?>
3891
					<div class='bsui sd-argument ' data-argument='<?php echo esc_attr( $args['row']['key'] ); ?>' data-element_require='<?php if ( !empty($args['row']['element_require'])) {
3892
						echo $this->convert_element_require( $args['row']['element_require'] );
3893
					} ?>'>
3894
					<?php if(!empty($args['row']['title'])){ ?>
3895
					<label class="mb-0 "><?php echo esc_attr( $args['row']['title'] ); ?><?php echo $this->widget_field_desc( $args['row'] ); ?></label>
3896
					<?php }?>
3897
					<div class='row <?php if(!empty($args['row']['class'])){ echo esc_attr($args['row']['class']);} ?>'>
3898
					<div class='col pr-2'>
3899
					<?php
3900
				}elseif(!empty($args['row']['close'])){
3901
					echo "<div class='col pl-0'>";
3902
				}else{
3903
					echo "<div class='col pl-0 pr-2'>";
3904
				}
3905
			}
3906
		}
3907
3908
		public function widget_inputs_row_end($key, $args){
0 ignored issues
show
Unused Code introduced by
The parameter $key is not used and could be removed. ( Ignorable by Annotation )

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

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

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

Loading history...
3909
3910
			if(!empty($args['row'])){
3911
				// maybe close
3912
				if(!empty($args['row']['close'])){
3913
					echo "</div></div>";
3914
				}
3915
3916
				echo "</div>";
3917
			}
3918
		}
3919
3920
		/**
3921
		 * Get the hidden input that when added makes the advanced button show on widget settings.
3922
		 *
3923
		 * @return string
3924
		 */
3925
		public function widget_advanced_toggle() {
3926
3927
			$output = '';
3928
			if ( $this->block_show_advanced() ) {
3929
				$val = 1;
3930
			} else {
3931
				$val = 0;
3932
			}
3933
3934
			$output .= "<input type='hidden'  class='sd-show-advanced' value='$val' />";
3935
3936
			return $output;
3937
		}
3938
3939
		/**
3940
		 * Convert require element.
3941
		 *
3942
		 * @param string $input Input element.
3943
		 *
3944
		 * @return string $output
3945
		 *@since 1.0.0
3946
		 *
3947
		 */
3948
		public function convert_element_require( $input ) {
3949
3950
			$input = str_replace( "'", '"', $input );// we only want double quotes
3951
3952
			$output = esc_attr( str_replace( array( "[%", "%]" ), array(
3953
				"jQuery(form).find('[data-argument=\"",
3954
				"\"]').find('input,select,textarea').val()"
3955
			), $input ) );
3956
3957
			return $output;
3958
		}
3959
3960
		/**
3961
		 * Builds the inputs for the widget options.
3962
		 *
3963
		 * @param $args
3964
		 * @param $instance
3965
		 */
3966
		public function widget_inputs( $args, $instance ) {
3967
3968
			$class             = "";
3969
			$element_require   = "";
3970
			$custom_attributes = "";
3971
3972
			// get value
3973
			if ( isset( $instance[ $args['name'] ] ) ) {
3974
				$value = $instance[ $args['name'] ];
3975
			} elseif ( ! isset( $instance[ $args['name'] ] ) && ! empty( $args['default'] ) ) {
3976
				$value = is_array( $args['default'] ) ? array_map( "esc_html", $args['default'] ) : esc_html( $args['default'] );
3977
			} else {
3978
				$value = '';
3979
			}
3980
3981
			// get placeholder
3982
			if ( ! empty( $args['placeholder'] ) ) {
3983
				$placeholder = "placeholder='" . esc_html( $args['placeholder'] ) . "'";
3984
			} else {
3985
				$placeholder = '';
3986
			}
3987
3988
			// get if advanced
3989
			if ( isset( $args['advanced'] ) && $args['advanced'] ) {
3990
				$class .= " sd-advanced-setting ";
3991
			}
3992
3993
			// element_require
3994
			if ( isset( $args['element_require'] ) && $args['element_require'] ) {
3995
				$element_require = $args['element_require'];
3996
			}
3997
3998
			// custom_attributes
3999
			if ( isset( $args['custom_attributes'] ) && $args['custom_attributes'] ) {
4000
				$custom_attributes = $this->array_to_attributes( $args['custom_attributes'], true );
4001
			}
4002
4003
4004
			// before wrapper
4005
			?>
4006
			<p class="sd-argument <?php echo esc_attr( $class ); ?>"
4007
			data-argument='<?php echo esc_attr( $args['name'] ); ?>'
4008
			data-element_require='<?php if ( $element_require ) {
4009
				echo $this->convert_element_require( $element_require );
4010
			} ?>'
4011
			>
4012
			<?php
4013
4014
4015
			switch ( $args['type'] ) {
4016
				//array('text','password','number','email','tel','url','color')
4017
				case "text":
4018
				case "password":
4019
				case "number":
4020
				case "email":
4021
				case "tel":
4022
				case "url":
4023
				case "color":
4024
					?>
4025
					<label
4026
						for="<?php echo esc_attr( $this->get_field_id( $args['name'] ) ); ?>"><?php echo $this->widget_field_title( $args );?><?php echo $this->widget_field_desc( $args ); ?></label>
4027
					<input <?php echo $placeholder; ?> class="widefat"
4028
						<?php echo $custom_attributes; ?>
4029
						                               id="<?php echo esc_attr( $this->get_field_id( $args['name'] ) ); ?>"
4030
						                               name="<?php echo esc_attr( $this->get_field_name( $args['name'] ) ); ?>"
4031
						                               type="<?php echo esc_attr( $args['type'] ); ?>"
4032
						                               value="<?php echo esc_attr( $value ); ?>">
4033
					<?php
4034
4035
					break;
4036
				case "select":
4037
					$multiple = isset( $args['multiple'] ) && $args['multiple'] ? true : false;
4038
					if ( $multiple ) {
4039
						if ( empty( $value ) ) {
4040
							$value = array();
4041
						}
4042
					}
4043
					?>
4044
					<label
4045
						for="<?php echo esc_attr( $this->get_field_id( $args['name'] ) ); ?>"><?php echo $this->widget_field_title( $args ); ?><?php echo $this->widget_field_desc( $args ); ?></label>
4046
					<select <?php echo $placeholder; ?> class="widefat"
4047
						<?php echo $custom_attributes; ?>
4048
						                                id="<?php echo esc_attr( $this->get_field_id( $args['name'] ) ); ?>"
4049
						                                name="<?php echo esc_attr( $this->get_field_name( $args['name'] ) );
4050
						                                if ( $multiple ) {
4051
							                                echo "[]";
4052
						                                } ?>"
4053
						<?php if ( $multiple ) {
4054
							echo "multiple";
4055
						} //@todo not implemented yet due to gutenberg not supporting it
4056
						?>
4057
					>
4058
						<?php
4059
4060
						if ( ! empty( $args['options'] ) ) {
4061
							foreach ( $args['options'] as $val => $label ) {
4062
								if ( $multiple ) {
4063
									$selected = in_array( $val, $value ) ? 'selected="selected"' : '';
4064
								} else {
4065
									$selected = selected( $value, $val, false );
4066
								}
4067
								echo "<option value='$val' " . $selected . ">$label</option>";
4068
							}
4069
						}
4070
						?>
4071
					</select>
4072
					<?php
4073
					break;
4074
				case "checkbox":
4075
					?>
4076
					<input <?php echo $placeholder; ?>
4077
						<?php checked( 1, $value, true ) ?>
4078
						<?php echo $custom_attributes; ?>
4079
						class="widefat" id="<?php echo esc_attr( $this->get_field_id( $args['name'] ) ); ?>"
4080
						name="<?php echo esc_attr( $this->get_field_name( $args['name'] ) ); ?>" type="checkbox"
4081
						value="1">
4082
					<label
4083
						for="<?php echo esc_attr( $this->get_field_id( $args['name'] ) ); ?>"><?php echo $this->widget_field_title( $args );?><?php echo $this->widget_field_desc( $args ); ?></label>
4084
					<?php
4085
					break;
4086
				case "textarea":
4087
					?>
4088
					<label
4089
						for="<?php echo esc_attr( $this->get_field_id( $args['name'] ) ); ?>"><?php echo $this->widget_field_title( $args ); ?><?php echo $this->widget_field_desc( $args ); ?></label>
4090
					<textarea <?php echo $placeholder; ?> class="widefat"
4091
						<?php echo $custom_attributes; ?>
4092
						                                  id="<?php echo esc_attr( $this->get_field_id( $args['name'] ) ); ?>"
4093
						                                  name="<?php echo esc_attr( $this->get_field_name( $args['name'] ) ); ?>"
4094
					><?php echo esc_attr( $value ); ?></textarea>
4095
					<?php
4096
4097
					break;
4098
				case "hidden":
4099
					?>
4100
					<input id="<?php echo esc_attr( $this->get_field_id( $args['name'] ) ); ?>"
4101
					       name="<?php echo esc_attr( $this->get_field_name( $args['name'] ) ); ?>" type="hidden"
4102
					       value="<?php echo esc_attr( $value ); ?>">
4103
					<?php
4104
					break;
4105
				default:
4106
					echo "No input type found!"; // @todo we need to add more input types.
4107
			}
4108
4109
			// after wrapper
4110
			?>
4111
			</p>
4112
			<?php
4113
4114
4115
		}
4116
4117
		public function get_widget_icon($icon = 'box-top', $title = ''){
4118
			if($icon=='box-top'){
4119
				return '<svg title="'.esc_attr($title).'" width="20px" height="20px" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg" fill-rule="evenodd" clip-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" role="img" aria-hidden="true" focusable="false"><rect x="2.714" y="5.492" width="1.048" height="9.017" fill="#555D66"></rect><rect x="16.265" y="5.498" width="1.023" height="9.003" fill="#555D66"></rect><rect x="5.518" y="2.186" width="8.964" height="2.482" fill="#272B2F"></rect><rect x="5.487" y="16.261" width="9.026" height="1.037" fill="#555D66"></rect></svg>';
4120
			}elseif($icon=='box-right'){
4121
				return '<svg title="'.esc_attr($title).'" width="20px" height="20px" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg" fill-rule="evenodd" clip-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" role="img" aria-hidden="true" focusable="false"><rect x="2.714" y="5.492" width="1.046" height="9.017" fill="#555D66"></rect><rect x="15.244" y="5.498" width="2.518" height="9.003" fill="#272B2F"></rect><rect x="5.518" y="2.719" width="8.964" height="0.954" fill="#555D66"></rect><rect x="5.487" y="16.308" width="9.026" height="0.99" fill="#555D66"></rect></svg>';
4122
			}elseif($icon=='box-bottom'){
4123
				return '<svg title="'.esc_attr($title).'" width="20px" height="20px" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg" fill-rule="evenodd" clip-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" role="img" aria-hidden="true" focusable="false"><rect x="2.714" y="5.492" width="1" height="9.017" fill="#555D66"></rect><rect x="16.261" y="5.498" width="1.027" height="9.003" fill="#555D66"></rect><rect x="5.518" y="2.719" width="8.964" height="0.968" fill="#555D66"></rect><rect x="5.487" y="15.28" width="9.026" height="2.499" fill="#272B2F"></rect></svg>';
4124
			}elseif($icon=='box-left'){
4125
				return '<svg title="'.esc_attr($title).'" width="20px" height="20px" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg" fill-rule="evenodd" clip-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414" role="img" aria-hidden="true" focusable="false"><rect x="2.202" y="5.492" width="2.503" height="9.017" fill="#272B2F"></rect><rect x="16.276" y="5.498" width="1.012" height="9.003" fill="#555D66"></rect><rect x="5.518" y="2.719" width="8.964" height="0.966" fill="#555D66"></rect><rect x="5.487" y="16.303" width="9.026" height="0.995" fill="#555D66"></rect></svg>';
4126
			}
4127
		}
4128
4129
		/**
4130
		 * Get the widget input description html.
4131
		 *
4132
		 * @param $args
4133
		 *
4134
		 * @return string
4135
		 * @todo, need to make its own tooltip script
4136
		 */
4137
		public function widget_field_desc( $args ) {
4138
4139
			$description = '';
4140
			if ( isset( $args['desc'] ) && $args['desc'] ) {
4141
				if ( isset( $args['desc_tip'] ) && $args['desc_tip'] ) {
4142
					$description = $this->desc_tip( $args['desc'] );
4143
				} else {
4144
					$description = '<span class="description">' . wp_kses_post( $args['desc'] ) . '</span>';
4145
				}
4146
			}
4147
4148
			return $description;
4149
		}
4150
4151
		/**
4152
		 * Get the widget input title html.
4153
		 *
4154
		 * @param $args
4155
		 *
4156
		 * @return string
4157
		 */
4158
		public function widget_field_title( $args ) {
4159
4160
			$title = '';
4161
			if ( isset( $args['title'] ) && $args['title'] ) {
4162
				if ( isset( $args['icon'] ) && $args['icon'] ) {
4163
					$title = self::get_widget_icon( $args['icon'], $args['title']  );
0 ignored issues
show
Bug Best Practice introduced by
The method WP_Super_Duper::get_widget_icon() is not static, but was called statically. ( Ignorable by Annotation )

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

4163
					/** @scrutinizer ignore-call */ 
4164
     $title = self::get_widget_icon( $args['icon'], $args['title']  );
Loading history...
4164
				} else {
4165
					$title = esc_attr($args['title']);
4166
				}
4167
			}
4168
4169
			return $title;
4170
		}
4171
4172
		/**
4173
		 * Get the tool tip html.
4174
		 *
4175
		 * @param $tip
4176
		 * @param bool $allow_html
4177
		 *
4178
		 * @return string
4179
		 */
4180
		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...
4181
			if ( $allow_html ) {
4182
				$tip = $this->sanitize_tooltip( $tip );
4183
			} else {
4184
				$tip = esc_attr( $tip );
4185
			}
4186
4187
			return '<span class="gd-help-tip dashicons dashicons-editor-help" title="' . $tip . '"></span>';
4188
		}
4189
4190
		/**
4191
		 * Sanitize a string destined to be a tooltip.
4192
		 *
4193
		 * @param string $var
4194
		 *
4195
		 * @return string
4196
		 */
4197
		public function sanitize_tooltip( $var ) {
4198
			return htmlspecialchars( wp_kses( html_entity_decode( $var ), array(
4199
				'br'     => array(),
4200
				'em'     => array(),
4201
				'strong' => array(),
4202
				'small'  => array(),
4203
				'span'   => array(),
4204
				'ul'     => array(),
4205
				'li'     => array(),
4206
				'ol'     => array(),
4207
				'p'      => array(),
4208
			) ) );
4209
		}
4210
4211
		/**
4212
		 * Processing widget options on save
4213
		 *
4214
		 * @param array $new_instance The new options
4215
		 * @param array $old_instance The previous options
4216
		 *
4217
		 * @return array
4218
		 * @todo we should add some sanitation here.
4219
		 */
4220
		public function update( $new_instance, $old_instance ) {
4221
4222
			//save the widget
4223
			$instance = array_merge( (array) $old_instance, (array) $new_instance );
4224
4225
			// set widget instance
4226
			$this->instance = $instance;
4227
4228
			if ( empty( $this->arguments ) ) {
4229
				$this->get_arguments();
4230
			}
4231
4232
			// check for checkboxes
4233
			if ( ! empty( $this->arguments ) ) {
4234
				foreach ( $this->arguments as $argument ) {
4235
					if ( isset( $argument['type'] ) && $argument['type'] == 'checkbox' && ! isset( $new_instance[ $argument['name'] ] ) ) {
4236
						$instance[ $argument['name'] ] = '0';
4237
					}
4238
				}
4239
			}
4240
4241
			return $instance;
4242
		}
4243
4244
		/**
4245
		 * Checks if the current call is a ajax call to get the block content.
4246
		 *
4247
		 * This can be used in your widget to return different content as the block content.
4248
		 *
4249
		 * @return bool
4250
		 *@since 1.0.3
4251
		 */
4252
		public function is_block_content_call() {
4253
			$result = false;
4254
			if ( wp_doing_ajax() && isset( $_REQUEST['action'] ) && $_REQUEST['action'] == 'super_duper_output_shortcode' ) {
4255
				$result = true;
4256
			}
4257
4258
			return $result;
4259
		}
4260
4261
		/**
4262
		 * Get an instance hash that will be unique to the type and settings.
4263
		 *
4264
		 * @return string
4265
		 *@since 1.0.20
4266
		 */
4267
		public function get_instance_hash(){
4268
			$instance_string = $this->base_id.serialize($this->instance);
4269
			return hash('crc32b',$instance_string);
4270
		}
4271
4272
		/**
4273
		 * Generate and return inline styles from CSS rules that will match the unique class of the instance.
4274
		 *
4275
		 * @param array $rules
4276
		 *
4277
		 * @return string
4278
		 *@since 1.0.20
4279
		 */
4280
		public function get_instance_style($rules = array()){
4281
			$css = '';
4282
4283
			if(!empty($rules)){
4284
				$rules = array_unique($rules);
4285
				$instance_hash = $this->get_instance_hash();
4286
				$css .= "<style>";
4287
				foreach($rules as $rule){
4288
					$css .= ".sdel-$instance_hash $rule";
4289
				}
4290
				$css .= "</style>";
4291
			}
4292
4293
			return $css;
4294
		}
4295
4296
		/**
4297
		 * Encode shortcodes tags.
4298
		 *
4299
		 * @param string $content Content to search for shortcode tags.
4300
		 *
4301
*@return string Content with shortcode tags removed.
4302
		 *@since 1.0.28
4303
		 *
4304
		 */
4305
		public function encode_shortcodes( $content ) {
4306
			// Avoids existing encoded tags.
4307
			$trans   = array(
4308
				'&#91;' => '&#091;',
4309
				'&#93;' => '&#093;',
4310
				'&amp;#91;' => '&#091;',
4311
				'&amp;#93;' => '&#093;',
4312
				'&lt;' => '&0lt;',
4313
				'&gt;' => '&0gt;',
4314
				'&amp;lt;' => '&0lt;',
4315
				'&amp;gt;' => '&0gt;',
4316
			);
4317
4318
			$content = strtr( $content, $trans );
4319
4320
			$trans   = array(
4321
				'[' => '&#91;',
4322
				']' => '&#93;',
4323
				'<' => '&lt;',
4324
				'>' => '&gt;',
4325
				'"' => '&quot;',
4326
				"'" => '&apos;',
4327
			);
4328
4329
			$content = strtr( $content, $trans );
4330
4331
			return $content;
4332
		}
4333
4334
		/**
4335
		 * Remove encoded shortcod tags.
4336
		 *
4337
		 * @param string $content Content to search for shortcode tags.
4338
		 *
4339
*@return string Content with decoded shortcode tags.
4340
		 *@since 1.0.28
4341
		 *
4342
		 */
4343
		public function decode_shortcodes( $content ) {
4344
			$trans   = array(
4345
				'&#91;' => '[',
4346
				'&#93;' => ']',
4347
				'&amp;#91;' => '[',
4348
				'&amp;#93;' => ']',
4349
				'&lt;' => '<',
4350
				'&gt;' => '>',
4351
				'&amp;lt;' => '<',
4352
				'&amp;gt;' => '>',
4353
				'&quot;' => '"',
4354
				'&apos;' => "'",
4355
			);
4356
4357
			$content = strtr( $content, $trans );
4358
4359
			$trans   = array(
4360
				'&#091;' => '&#91;',
4361
				'&#093;' => '&#93;',
4362
				'&amp;#091;' => '&#91;',
4363
				'&amp;#093;' => '&#93;',
4364
				'&0lt;' => '&lt;',
4365
				'&0gt;' => '&gt;',
4366
				'&amp;0lt;' => '&lt;',
4367
				'&amp;0gt;' => '&gt;',
4368
			);
4369
4370
			$content = strtr( $content, $trans );
4371
4372
			return $content;
4373
		}
4374
	}
4375
}
4376