Passed
Push — master ( b8ec21...553136 )
by Stiofan
16:20 queued 11:06
created

WP_Super_Duper::group_block_tabs()   C

Complexity

Conditions 12
Paths 9

Size

Total Lines 39
Code Lines 20

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 12
eloc 20
nc 9
nop 2
dl 0
loc 39
rs 6.9666
c 0
b 0
f 0

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

176
				/** @scrutinizer ignore-call */ 
177
    fusion_builder_map( $args );
Loading history...
177
			}
178
179
		}
180
181
		public function get_fusion_params() {
182
			$params    = array();
183
			$arguments = $this->get_arguments();
184
185
			if ( ! empty( $arguments ) ) {
186
				foreach ( $arguments as $key => $val ) {
187
					$param = array();
188
					// type
189
					$param['type'] = str_replace(
190
						array(
191
							"text",
192
							"number",
193
							"email",
194
							"color",
195
							"checkbox"
196
						),
197
						array(
198
							"textfield",
199
							"textfield",
200
							"textfield",
201
							"colorpicker",
202
							"select",
203
204
						),
205
						$val['type'] );
206
207
					// multiselect
208
					if ( $val['type'] == 'multiselect' || ( ( $param['type'] == 'select' || $val['type'] == 'select' ) && ! empty( $val['multiple'] ) ) ) {
209
						$param['type']     = 'multiple_select';
210
						$param['multiple'] = true;
211
					}
212
213
					// heading
214
					$param['heading'] = $val['title'];
215
216
					// description
217
					$param['description'] = isset( $val['desc'] ) ? $val['desc'] : '';
218
219
					// param_name
220
					$param['param_name'] = $key;
221
222
					// Default
223
					$param['default'] = isset( $val['default'] ) ? $val['default'] : '';
224
225
					// Group
226
					if ( isset( $val['group'] ) ) {
227
						$param['group'] = $val['group'];
228
					}
229
230
					// value
231
					if ( $val['type'] == 'checkbox' ) {
232
						if ( isset( $val['default'] ) && $val['default'] == '0' ) {
233
							unset( $param['default'] );
234
						}
235
						$param['value'] = array( '' => __( "No" ), '1' => __( "Yes" ) );
236
					} elseif ( $param['type'] == 'select' || $param['type'] == 'multiple_select' ) {
237
						$param['value'] = isset( $val['options'] ) ? $val['options'] : array();
238
					} else {
239
						$param['value'] = isset( $val['default'] ) ? $val['default'] : '';
240
					}
241
242
					// setup the param
243
					$params[] = $param;
244
245
				}
246
			}
247
248
249
			return $params;
250
		}
251
252
		/**
253
		 * Maybe insert the shortcode inserter button in the footer if we are in the cornerstone builder
254
		 */
255
		public static function maybe_cornerstone_builder() {
256
			if ( did_action( 'cornerstone_before_boot_app' ) ) {
257
				self::shortcode_insert_button_script();
258
			}
259
		}
260
261
		/**
262
		 * A function to ge the shortcode builder picker html.
263
		 *
264
		 * @param string $editor_id
265
		 *
266
		 * @return string
267
		 */
268
		public static function get_picker( $editor_id = '' ) {
269
270
			ob_start();
271
			if ( isset( $_POST['editor_id'] ) ) {
272
				$editor_id = esc_attr( $_POST['editor_id'] );
273
			} elseif ( isset( $_REQUEST['et_fb'] ) ) {
274
				$editor_id = 'main_content_content_vb_tiny_mce';
275
			}
276
277
			global $sd_widgets;
278
279
//			print_r($sd_widgets);exit;
280
			?>
281
282
			<div class="sd-shortcode-left-wrap">
283
				<?php
284
				ksort( $sd_widgets );
285
				//				print_r($sd_widgets);exit;
286
				if ( ! empty( $sd_widgets ) ) {
287
					echo '<select class="widefat" onchange="sd_get_shortcode_options(this);">';
288
					echo "<option>" . __( 'Select shortcode' ) . "</option>";
289
					foreach ( $sd_widgets as $shortcode => $class ) {
290
						if(!empty($class['output_types']) && !in_array('shortcode', $class['output_types'])){ continue; }
291
						echo "<option value='" . esc_attr( $shortcode ) . "'>" . esc_attr( $shortcode ) . " (" . esc_attr( $class['name'] ) . ")</option>";
292
					}
293
					echo "</select>";
294
295
				}
296
				?>
297
				<div class="sd-shortcode-settings"></div>
298
299
			</div>
300
301
			<div class="sd-shortcode-right-wrap">
302
				<textarea id='sd-shortcode-output' disabled></textarea>
303
				<div id='sd-shortcode-output-actions'>
304
					<?php if ( $editor_id != '' ) { ?>
305
						<button class="button sd-insert-shortcode-button"
306
						        onclick="sd_insert_shortcode(<?php if ( ! empty( $editor_id ) ) {
307
							        echo "'" . $editor_id . "'";
308
						        } ?>)"><?php _e( 'Insert shortcode' ); ?></button>
309
					<?php } ?>
310
					<button class="button"
311
					        onclick="sd_copy_to_clipboard()"><?php _e( 'Copy shortcode' ); ?></button>
312
				</div>
313
			</div>
314
			<?php
315
316
			$html = ob_get_clean();
317
318
			if ( wp_doing_ajax() ) {
319
				echo $html;
320
				$should_die = true;
321
322
				// some builder get the editor via ajax so we should not die on those occasions
323
				$dont_die = array(
324
					'parent_tag',// WP Bakery
325
					'avia_request' // enfold
326
				);
327
328
				foreach ( $dont_die as $request ) {
329
					if ( isset( $_REQUEST[ $request ] ) ) {
330
						$should_die = false;
331
					}
332
				}
333
334
				if ( $should_die ) {
335
					wp_die();
336
				}
337
338
			} else {
339
				return $html;
340
			}
341
342
			return '';
343
344
		}
345
346
		/**
347
		 * Output the version in the header.
348
		 */
349
		public function generator() {
350
			$file = str_replace( array( "/", "\\" ), "/", realpath( __FILE__ ) );
351
			$plugins_dir = str_replace( array( "/", "\\" ), "/", realpath( WP_PLUGIN_DIR ) );
352
353
			// Find source plugin/theme of SD
354
			$source = array();
355
			if ( strpos( $file, $plugins_dir ) !== false ) {
356
				$source = explode( "/", plugin_basename( $file ) );
357
			} else if ( function_exists( 'get_theme_root' ) ) {
358
				$themes_dir = str_replace( array( "/", "\\" ), "/", realpath( get_theme_root() ) );
359
360
				if ( strpos( $file, $themes_dir ) !== false ) {
361
					$source = explode( "/", ltrim( str_replace( $themes_dir, "", $file ), "/" ) );
362
				}
363
			}
364
365
			echo '<meta name="generator" content="WP Super Duper v' . $this->version . '"' . ( ! empty( $source[0] ) ? ' data-sd-source="' . esc_attr( $source[0] ) . '"' : '' ) . ' />';
366
		}
367
368
		/**
369
		 * Get widget settings.
370
		 *
371
		 * @since 1.0.0
372
		 */
373
		public static function get_widget_settings() {
374
			global $sd_widgets;
375
376
			$shortcode = isset( $_REQUEST['shortcode'] ) && $_REQUEST['shortcode'] ? sanitize_title_with_dashes( $_REQUEST['shortcode'] ) : '';
377
			if ( ! $shortcode ) {
378
				wp_die();
379
			}
380
			$widget_args = isset( $sd_widgets[ $shortcode ] ) ? $sd_widgets[ $shortcode ] : '';
381
			if ( ! $widget_args ) {
382
				wp_die();
383
			}
384
			$class_name = isset( $widget_args['class_name'] ) && $widget_args['class_name'] ? $widget_args['class_name'] : '';
385
			if ( ! $class_name ) {
386
				wp_die();
387
			}
388
389
			// invoke an instance method
390
			$widget = new $class_name;
391
392
			ob_start();
393
			$widget->form( array() );
394
			$form = ob_get_clean();
395
			echo "<form id='$shortcode'>" . $form . "<div class=\"widget-control-save\"></div></form>";
396
			echo "<style>" . $widget->widget_css() . "</style>";
397
			echo "<script>" . $widget->widget_js() . "</script>";
398
			?>
399
			<?php
400
			wp_die();
401
		}
402
403
		/**
404
		 * Insert shortcode builder button to classic editor (not inside Gutenberg, not needed).
405
		 *
406
		 * @param string $editor_id Optional. Shortcode editor id. Default null.
407
		 * @param string $insert_shortcode_function Optional. Insert shortcode function. Default null.
408
		 *
409
		 *@since 1.0.0
410
		 *
411
		 */
412
		public static function shortcode_insert_button( $editor_id = '', $insert_shortcode_function = '' ) {
413
			global $sd_widgets, $shortcode_insert_button_once;
414
			if ( $shortcode_insert_button_once ) {
415
				return;
416
			}
417
			add_thickbox();
418
419
420
			/**
421
			 * Cornerstone makes us play dirty tricks :/
422
			 * 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.
423
			 */
424
			if ( function_exists( 'cornerstone_plugin_init' ) && ! is_admin() ) {
425
				echo '<span id="insert-media-button">';
426
			}
427
428
			echo self::shortcode_button( 'this', 'true' );
429
430
			// see opening note
431
			if ( function_exists( 'cornerstone_plugin_init' ) && ! is_admin() ) {
432
				echo '</span>'; // end #insert-media-button
433
			}
434
435
			// Add separate script for generatepress theme sections
436
			if ( function_exists( 'generate_sections_sections_metabox' ) && did_action( 'generate_sections_metabox' ) ) {
437
			} else {
438
				self::shortcode_insert_button_script( $editor_id, $insert_shortcode_function );
439
			}
440
441
			$shortcode_insert_button_once = true;
442
		}
443
444
		/**
445
		 * Gets the shortcode insert button html.
446
		 *
447
		 * @param string $id
448
		 * @param string $search_for_id
449
		 *
450
		 * @return mixed
451
		 */
452
		public static function shortcode_button( $id = '', $search_for_id = '' ) {
453
			ob_start();
454
			?>
455
			<span class="sd-lable-shortcode-inserter">
456
				<a onclick="sd_ajax_get_picker(<?php echo $id;
457
				if ( $search_for_id ) {
458
					echo "," . $search_for_id;
459
				} ?>);" href="#TB_inline?width=100%&height=550&inlineId=super-duper-content-ajaxed"
460
				   class="thickbox button super-duper-content-open" title="Add Shortcode">
461
					<span style="vertical-align: middle;line-height: 18px;font-size: 20px;"
462
					      class="dashicons dashicons-screenoptions"></span>
463
				</a>
464
				<div id="super-duper-content-ajaxed" style="display:none;">
465
					<span>Loading</span>
466
				</div>
467
			</span>
468
469
			<?php
470
			$html = ob_get_clean();
471
472
			// remove line breaks so we can use it in js
473
			return preg_replace( "/\r|\n/", "", trim( $html ) );
474
		}
475
476
		/**
477
		 * Makes SD work with the siteOrigin page builder.
478
		 *
479
		 * @return mixed
480
		 *@since 1.0.6
481
		 */
482
		public static function siteorigin_js() {
483
			ob_start();
484
			?>
485
			<script>
486
				/**
487
				 * Check a form to see what items should be shown or hidden.
488
				 */
489
				function sd_so_show_hide(form) {
490
					jQuery(form).find(".sd-argument").each(function () {
491
492
						var $element_require = jQuery(this).data('element_require');
493
494
						if ($element_require) {
495
496
							$element_require = $element_require.replace("&#039;", "'"); // replace single quotes
497
							$element_require = $element_require.replace("&quot;", '"'); // replace double quotes
498
499
							if (eval($element_require)) {
500
								jQuery(this).removeClass('sd-require-hide');
501
							} else {
502
								jQuery(this).addClass('sd-require-hide');
503
							}
504
						}
505
					});
506
				}
507
508
				/**
509
				 * Toggle advanced settings visibility.
510
				 */
511
				function sd_so_toggle_advanced($this) {
512
					var form = jQuery($this).parents('form,.form,.so-content');
513
					form.find('.sd-advanced-setting').toggleClass('sd-adv-show');
514
					return false;// prevent form submit
515
				}
516
517
				/**
518
				 * Initialise a individual widget.
519
				 */
520
				function sd_so_init_widget($this, $selector) {
521
					if (!$selector) {
522
						$selector = 'form';
523
					}
524
					// only run once.
525
					if (jQuery($this).data('sd-widget-enabled')) {
526
						return;
527
					} else {
528
						jQuery($this).data('sd-widget-enabled', true);
529
					}
530
531
					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>';
532
					var form = jQuery($this).parents('' + $selector + '');
533
534
					if (jQuery($this).val() == '1' && jQuery(form).find('.sd-advanced-button').length == 0) {
535
						jQuery(form).append($button);
536
					}
537
538
					// show hide on form change
539
					jQuery(form).on("change", function () {
540
						sd_so_show_hide(form);
541
					});
542
543
					// show hide on load
544
					sd_so_show_hide(form);
545
				}
546
547
				jQuery(function () {
548
					jQuery(document).on('open_dialog', function (w, e) {
549
						setTimeout(function () {
550
							if (jQuery('.so-panels-dialog-wrapper:visible .so-content.panel-dialog .sd-show-advanced').length) {
551
								if (jQuery('.so-panels-dialog-wrapper:visible .so-content.panel-dialog .sd-show-advanced').val() == '1') {
552
									sd_so_init_widget('.so-panels-dialog-wrapper:visible .so-content.panel-dialog .sd-show-advanced', 'div');
553
								}
554
							}
555
						}, 200);
556
					});
557
				});
558
			</script>
559
			<?php
560
			$output = ob_get_clean();
561
562
			/*
563
			 * We only add the <script> tags for code highlighting, so we strip them from the output.
564
			 */
565
566
			return str_replace( array(
567
				'<script>',
568
				'</script>'
569
			), '', $output );
570
		}
571
572
		/**
573
		 * Output the JS and CSS for the shortcode insert button.
574
		 *
575
		 * @param string $editor_id
576
		 * @param string $insert_shortcode_function
577
		 *
578
		 *@since 1.0.6
579
		 *
580
		 */
581
		public static function shortcode_insert_button_script( $editor_id = '', $insert_shortcode_function = '' ) {
582
			?>
583
			<style>
584
				.sd-shortcode-left-wrap {
585
					float: left;
586
					width: 60%;
587
				}
588
589
				.sd-shortcode-left-wrap .gd-help-tip {
590
					float: none;
591
				}
592
593
				.sd-shortcode-left-wrap .widefat {
594
					border-spacing: 0;
595
					width: 100%;
596
					clear: both;
597
					margin: 0;
598
					border: 1px solid #ddd;
599
					box-shadow: inset 0 1px 2px rgba(0, 0, 0, .07);
600
					background-color: #fff;
601
					color: #32373c;
602
					outline: 0;
603
					transition: 50ms border-color ease-in-out;
604
					padding: 3px 5px;
605
				}
606
607
				.sd-shortcode-left-wrap input[type=checkbox].widefat {
608
					border: 1px solid #b4b9be;
609
					background: #fff;
610
					color: #555;
611
					clear: none;
612
					cursor: pointer;
613
					display: inline-block;
614
					line-height: 0;
615
					height: 16px;
616
					margin: -4px 4px 0 0;
617
					margin-top: 0;
618
					outline: 0;
619
					padding: 0 !important;
620
					text-align: center;
621
					vertical-align: middle;
622
					width: 16px;
623
					min-width: 16px;
624
					-webkit-appearance: none;
625
					box-shadow: inset 0 1px 2px rgba(0, 0, 0, .1);
626
					transition: .05s border-color ease-in-out;
627
				}
628
629
				.sd-shortcode-left-wrap input[type=checkbox]:checked:before {
630
					content: "\f147";
631
					margin: -3px 0 0 -4px;
632
					color: #1e8cbe;
633
					float: left;
634
					display: inline-block;
635
					vertical-align: middle;
636
					width: 16px;
637
					font: normal 21px/1 dashicons;
638
					speak: none;
639
					-webkit-font-smoothing: antialiased;
640
					-moz-osx-font-smoothing: grayscale;
641
				}
642
643
				#sd-shortcode-output-actions button,
644
				.sd-advanced-button {
645
					color: #555;
646
					border-color: #ccc;
647
					background: #f7f7f7;
648
					box-shadow: 0 1px 0 #ccc;
649
					vertical-align: top;
650
					display: inline-block;
651
					text-decoration: none;
652
					font-size: 13px;
653
					line-height: 26px;
654
					height: 28px;
655
					margin: 0;
656
					padding: 0 10px 1px;
657
					cursor: pointer;
658
					border-width: 1px;
659
					border-style: solid;
660
					-webkit-appearance: none;
661
					border-radius: 3px;
662
					white-space: nowrap;
663
					box-sizing: border-box;
664
				}
665
666
				button.sd-advanced-button {
667
					background: #0073aa;
668
					border-color: #006799;
669
					box-shadow: inset 0 2px 0 #006799;
670
					vertical-align: top;
671
					color: #fff;
672
					text-decoration: none;
673
					text-shadow: 0 -1px 1px #006799, 1px 0 1px #006799, 0 1px 1px #006799, -1px 0 1px #006799;
674
					float: right;
675
					margin-right: 3px !important;
676
					font-size: 20px !important;
677
				}
678
679
				.sd-shortcode-right-wrap {
680
					float: right;
681
					width: 35%;
682
				}
683
684
				#sd-shortcode-output {
685
					background: rgba(255, 255, 255, .5);
686
					border-color: rgba(222, 222, 222, .75);
687
					box-shadow: inset 0 1px 2px rgba(0, 0, 0, .04);
688
					color: rgba(51, 51, 51, .5);
689
					overflow: auto;
690
					padding: 2px 6px;
691
					line-height: 1.4;
692
					resize: vertical;
693
				}
694
695
				#sd-shortcode-output {
696
					height: 250px;
697
					width: 100%;
698
				}
699
700
				<?php if ( function_exists( 'generate_sections_sections_metabox' ) ) { ?>
701
				.generate-sections-modal #custom-media-buttons > .sd-lable-shortcode-inserter {
702
					display: inline;
703
				}
704
				<?php } ?>
705
				<?php if ( function_exists( 'et_builder_is_tb_admin_screen' ) && et_builder_is_tb_admin_screen() ) { ?>
706
				body.divi_page_et_theme_builder div#TB_window.gd-tb-window{z-index:9999999}
707
				<?php } ?>
708
			</style>
709
			<?php
710
			if ( class_exists( 'SiteOrigin_Panels' ) ) {
711
				echo "<script>" . self::siteorigin_js() . "</script>";
712
			}
713
			?>
714
			<script>
715
				<?php
716
				if(! empty( $insert_shortcode_function )){
717
					echo $insert_shortcode_function;
718
				}else{
719
720
				/**
721
				 * Function for super duper insert shortcode.
722
				 *
723
				 * @since 1.0.0
724
				 */
725
				?>
726
				function sd_insert_shortcode($editor_id) {
727
					$shortcode = jQuery('#TB_ajaxContent #sd-shortcode-output').val();
728
					if ($shortcode) {
729
						if (!$editor_id) {
730
							<?php
731
							if ( isset( $_REQUEST['et_fb'] ) ) {
732
								echo '$editor_id = "#main_content_content_vb_tiny_mce";';
733
							} elseif ( isset( $_REQUEST['action'] ) && $_REQUEST['action'] == 'elementor' ) {
734
								echo '$editor_id = "#elementor-controls .wp-editor-container textarea";';
735
							} else {
736
								echo '$editor_id = "#wp-content-editor-container textarea";';
737
							}
738
							?>
739
						} else {
740
							$editor_id = '#' + $editor_id;
741
						}
742
						tmceActive = jQuery($editor_id).attr("aria-hidden") == "true" ? true : false;
743
						/* GeneratePress */
744
						if (jQuery('#generate-sections-modal-dialog ' + $editor_id).length) {
745
							$editor_id = '#generate-sections-modal-dialog ' + $editor_id;
746
							tmceActive = jQuery($editor_id).closest('.wp-editor-wrap').hasClass('tmce-active') ? true : false;
747
						}
748
						if (typeof tinyMCE !== 'undefined' && tinyMCE.activeEditor && tmceActive) {
749
							tinyMCE.execCommand('mceInsertContent', false, $shortcode);
750
						} else {
751
							var $txt = jQuery($editor_id);
752
							var caretPos = $txt[0].selectionStart;
753
							var textAreaTxt = $txt.val();
754
							var txtToAdd = $shortcode;
755
							var textareaValue = textAreaTxt.substring(0, caretPos) + txtToAdd + textAreaTxt.substring(caretPos);
756
							$txt.focus().val(textareaValue).change().keydown().blur().keyup().keypress().trigger('input').trigger('change');
757
758
							// set Divi react input value
759
							var input = document.getElementById("main_content_content_vb_tiny_mce");
760
							if (input) {
761
								sd_setNativeValue(input, textareaValue);
762
							}
763
764
						}
765
						tb_remove();
766
					}
767
				}
768
769
				/*
770
				 Set the value of elements controlled via react.
771
				 */
772
				function sd_setNativeValue(element, value) {
773
					let lastValue = element.value;
774
					element.value = value;
775
					let event = new Event("input", {target: element, bubbles: true});
776
					// React 15
777
					event.simulated = true;
778
					// React 16
779
					let tracker = element._valueTracker;
780
					if (tracker) {
781
						tracker.setValue(lastValue);
782
					}
783
					element.dispatchEvent(event);
784
				}
785
				<?php }?>
786
787
				/*
788
				 Copies the shortcode to the clipboard.
789
				 */
790
				function sd_copy_to_clipboard() {
791
					/* Get the text field */
792
					var copyText = document.querySelector("#TB_ajaxContent #sd-shortcode-output");
793
					//un-disable the field
794
					copyText.disabled = false;
795
					/* Select the text field */
796
					copyText.select();
797
					/* Copy the text inside the text field */
798
					document.execCommand("Copy");
799
					//re-disable the field
800
					copyText.disabled = true;
801
					/* Alert the copied text */
802
					alert("Copied the text: " + copyText.value);
803
				}
804
805
				/*
806
				 Gets the shortcode options.
807
				 */
808
				function sd_get_shortcode_options($this) {
809
					$short_code = jQuery($this).val();
810
					if ($short_code) {
811
						var data = {
812
							'action': 'super_duper_get_widget_settings',
813
							'shortcode': $short_code,
814
							'attributes': 123,
815
							'post_id': 321,
816
							'_ajax_nonce': '<?php echo wp_create_nonce( 'super_duper_output_shortcode' );?>'
817
						};
818
819
						if (typeof ajaxurl === 'undefined') {
820
							var ajaxurl = "<?php echo admin_url( 'admin-ajax.php' );?>";
821
						}
822
823
						jQuery.post(ajaxurl, data, function (response) {
824
							jQuery('#TB_ajaxContent .sd-shortcode-settings').html(response);
825
826
							jQuery('#' + $short_code).on('change', 'select', function () {
827
								sd_build_shortcode($short_code);
828
							}); // take care of select tags
829
830
							jQuery('#' + $short_code).on('change keypress keyup', 'input,textarea', function () {
831
								sd_build_shortcode($short_code);
832
							});
833
834
							sd_build_shortcode($short_code);
835
836
							// resize the window to fit
837
							setTimeout(function () {
838
								jQuery('#TB_ajaxContent').css('width', 'auto').css('height', '75vh');
839
							}, 200);
840
841
							return response;
842
						});
843
					}
844
				}
845
846
				/*
847
				 Builds and inserts the shortcode into the viewer.
848
				 */
849
				function sd_build_shortcode($id) {
850
					var multiSelects = {};
851
					var multiSelectsRemove = [];
852
853
					$output = "[" + $id;
854
855
					$form_data = jQuery("#" + $id).serializeArray();
856
857
					// run checks for multiselects
858
					jQuery.each($form_data, function (index, element) {
859
						if (element && element.value) {
860
							$field_name = element.name.substr(element.name.indexOf("][") + 2);
861
							$field_name = $field_name.replace("]", "");
862
							// check if its a multiple
863
							if ($field_name.includes("[]")) {
864
								multiSelectsRemove[multiSelectsRemove.length] = index;
865
								$field_name = $field_name.replace("[]", "");
866
								if ($field_name in multiSelects) {
867
									multiSelects[$field_name] = multiSelects[$field_name] + "," + element.value;
868
								} else {
869
									multiSelects[$field_name] = element.value;
870
								}
871
							}
872
						}
873
					});
874
875
					// fix multiselects if any are found
876
					if (multiSelectsRemove.length) {
877
878
						// remove all multiselects
879
						multiSelectsRemove.reverse();
880
						multiSelectsRemove.forEach(function (index) {
881
							$form_data.splice(index, 1);
882
						});
883
884
						$ms_arr = [];
885
						// add multiselets back
886
						jQuery.each(multiSelects, function (index, value) {
887
							$ms_arr[$ms_arr.length] = {"name": "[][" + index + "]", "value": value};
888
						});
889
						$form_data = $form_data.concat($ms_arr);
890
					}
891
892
					if ($form_data) {
893
						$content = '';
894
						$form_data.forEach(function (element) {
895
							if (element.value) {
896
								$field_name = element.name.substr(element.name.indexOf("][") + 2);
897
								$field_name = $field_name.replace("]", "");
898
								if ($field_name == 'html') {
899
									$content = element.value;
900
								} else {
901
									$output = $output + " " + $field_name + '="' + element.value + '"';
902
								}
903
							}
904
						});
905
					}
906
					$output = $output + "]";
907
908
					// check for content field
909
					if ($content) {
910
						$output = $output + $content + "[/" + $id + "]";
911
					}
912
913
					jQuery('#TB_ajaxContent #sd-shortcode-output').html($output);
914
				}
915
916
				/*
917
				 Delay the init of the textareas for 1 second.
918
				 */
919
				(function () {
920
					setTimeout(function () {
921
						sd_init_textareas();
922
					}, 1000);
923
				})();
924
925
				/*
926
				 Init the textareas to be able to show the shortcode builder button.
927
				 */
928
				function sd_init_textareas() {
929
					// General textareas
930
					jQuery(document).on('focus', 'textarea', function () {
931
						if (jQuery(this).hasClass('wp-editor-area')) {
932
							// insert the shortcode button to the textarea lable if not there already
933
							if (!jQuery(this).parent().find('.sd-lable-shortcode-inserter').length) {
934
								jQuery(this).parent().find('.quicktags-toolbar').append(sd_shortcode_button(jQuery(this).attr('id')));
935
							}
936
						} else {
937
							// insert the shortcode button to the textarea lable if not there already
938
							if (!jQuery("label[for='" + jQuery(this).attr('id') + "']").find('.sd-lable-shortcode-inserter').length) {
939
								jQuery("label[for='" + jQuery(this).attr('id') + "']").append(sd_shortcode_button(jQuery(this).attr('id')));
940
							}
941
						}
942
					});
943
944
					// The below tries to add the shortcode builder button to the builders own raw/shortcode sections.
945
946
					// DIVI
947
					jQuery(document).on('focusin', '.et-fb-codemirror', function () {
948
						// insert the shortcode button to the textarea lable if not there already
949
						if (!jQuery(this).closest('.et-fb-form__group').find('.sd-lable-shortcode-inserter').length) {
950
							jQuery(this).closest('.et-fb-form__group').find('.et-fb-form__label-text').append(sd_shortcode_button());
951
						}
952
					});
953
954
					// Beaver
955
					jQuery(document).on('focusin', '.fl-code-field', function () {
956
						// insert the shortcode button to the textarea lable if not there already
957
						if (!jQuery(this).closest('.fl-field-control-wrapper').find('.sd-lable-shortcode-inserter').length) {
958
							jQuery(this).closest('.fl-field-control-wrapper').prepend(sd_shortcode_button());
959
						}
960
					});
961
962
					// Fushion builder (avada)
963
					jQuery(document).on('focusin', '.CodeMirror.cm-s-default', function () {
964
						// insert the shortcode button to the textarea lable if not there already
965
						if (!jQuery(this).parent().find('.sd-lable-shortcode-inserter').length) {
966
							jQuery(sd_shortcode_button()).insertBefore(this);
967
						}
968
					});
969
970
					// Avia builder (enfold)
971
					jQuery(document).on('focusin', '#aviaTBcontent', function () {
972
						// insert the shortcode button to the textarea lable if not there already
973
						if (!jQuery(this).parent().parent().find('.avia-name-description ').find('.sd-lable-shortcode-inserter').length) {
974
							jQuery(this).parent().parent().find('.avia-name-description strong').append(sd_shortcode_button(jQuery(this).attr('id')));
975
						}
976
					});
977
978
					// Cornerstone textareas
979
					jQuery(document).on('focusin', '.cs-control.cs-control-textarea', function () {
980
						// insert the shortcode button to the textarea lable if not there already
981
						if (!jQuery(this).find('.cs-control-header label').find('.sd-lable-shortcode-inserter').length) {
982
							jQuery(this).find('.cs-control-header label').append(sd_shortcode_button());
983
						}
984
					});
985
986
					// Cornerstone main bar
987
					setTimeout(function () {
988
						// insert the shortcode button to the textarea lable if not there already
989
						if (!jQuery('.cs-bar-btns').find('.sd-lable-shortcode-inserter').length) {
990
							jQuery('<li style="text-align: center;padding: 5px;list-style: none;">' + sd_shortcode_button() + '</li>').insertBefore('.cs-action-toggle-custom-css');
991
						}
992
					}, 2000);
993
994
995
					// WP Bakery, code editor does not render shortcodes.
996
//					jQuery(document).on('focusin', '.wpb-textarea_raw_html', function () {
997
//						// insert the shortcode button to the textarea lable if not there already
998
//						if(!jQuery(this).parent().parent().find('.wpb_element_label').find('.sd-lable-shortcode-inserter').length){
999
//							jQuery(this).parent().parent().find('.wpb_element_label').append(sd_shortcode_button());
1000
//						}
1001
//					});
1002
				}
1003
1004
				/**
1005
				 * Gets the html for the picker via ajax and updates it on the fly.
1006
				 *
1007
				 * @param $id
1008
				 * @param $search
1009
				 */
1010
				function sd_ajax_get_picker($id, $search) {
1011
					if ($search) {
1012
						$this = $id;
1013
						$id = jQuery($this).closest('.wp-editor-wrap').find('.wp-editor-container textarea').attr('id');
1014
					}
1015
1016
					var data = {
1017
						'action': 'super_duper_get_picker',
1018
						'editor_id': $id,
1019
						'_ajax_nonce': '<?php echo wp_create_nonce( 'super_duper_picker' );?>'
1020
					};
1021
1022
					if (!ajaxurl) {
1023
						var ajaxurl = "<?php echo admin_url( 'admin-ajax.php' ); ?>";
1024
					}
1025
1026
					jQuery.post(ajaxurl, data, function (response) {
1027
						jQuery('#TB_ajaxContent').closest('#TB_window').addClass('gd-tb-window');
1028
						jQuery('#TB_ajaxContent').html(response);
1029
						//return response;
1030
					}).then(function (env) {
1031
						jQuery('body').on('thickbox:removed', function () {
1032
							jQuery('#super-duper-content-ajaxed').html('');
1033
						});
1034
					});
1035
				}
1036
1037
				/**
1038
				 * Get the html for the shortcode inserter button depending on if a textarea id is available.
1039
				 *
1040
				 * @param $id string The textarea id.
1041
				 * @returns {string}
1042
				 */
1043
				function sd_shortcode_button($id) {
1044
					if ($id) {
1045
						return '<?php echo self::shortcode_button( "\\''+\$id+'\\'" );?>';
1046
					} else {
1047
						return '<?php echo self::shortcode_button();?>';
1048
					}
1049
				}
1050
			</script>
1051
			<?php
1052
		}
1053
1054
		/**
1055
		 * Gets some CSS for the widgets screen.
1056
		 *
1057
		 * @param bool $advanced If we should include advanced CSS.
1058
		 *
1059
		 * @return mixed
1060
		 */
1061
		public function widget_css( $advanced = true ) {
1062
			ob_start();
1063
			?>
1064
			<style>
1065
				<?php if( $advanced ){ ?>
1066
				.sd-advanced-setting {
1067
					display: none;
1068
				}
1069
1070
				.sd-advanced-setting.sd-adv-show {
1071
					display: block;
1072
				}
1073
1074
				.sd-argument.sd-require-hide,
1075
				.sd-advanced-setting.sd-require-hide {
1076
					display: none;
1077
				}
1078
1079
				button.sd-advanced-button {
1080
					margin-right: 3px !important;
1081
					font-size: 20px !important;
1082
				}
1083
1084
				<?php } ?>
1085
1086
				button.sd-toggle-group-button {
1087
					background-color: #f3f3f3;
1088
					color: #23282d;
1089
					cursor: pointer;
1090
					padding: 10px;
1091
					width: 100%;
1092
					border: none;
1093
					text-align: left;
1094
					outline: none;
1095
					font-size: 13px;
1096
					font-weight: bold;
1097
					margin-bottom: 1px;
1098
				}
1099
			</style>
1100
			<?php
1101
			$output = ob_get_clean();
1102
1103
			/*
1104
			 * We only add the <script> tags for code highlighting, so we strip them from the output.
1105
			 */
1106
1107
			return str_replace( array(
1108
				'<style>',
1109
				'</style>'
1110
			), '', $output );
1111
		}
1112
1113
		/**
1114
		 * Gets some JS for the widgets screen.
1115
		 *
1116
		 * @return mixed
1117
		 */
1118
		public function widget_js() {
1119
			ob_start();
1120
			?>
1121
			<script>
1122
1123
				/**
1124
				 * Toggle advanced settings visibility.
1125
				 */
1126
				function sd_toggle_advanced($this) {
1127
					var form = jQuery($this).parents('form,.form');
1128
					form.find('.sd-advanced-setting').toggleClass('sd-adv-show');
1129
					return false;// prevent form submit
1130
				}
1131
1132
				/**
1133
				 * Check a form to see what items should be shown or hidden.
1134
				 */
1135
				function sd_show_hide(form) {
1136
					jQuery(form).find(".sd-argument").each(function () {
1137
1138
						var $element_require = jQuery(this).data('element_require');
1139
1140
						if ($element_require) {
1141
1142
							$element_require = $element_require.replace("&#039;", "'"); // replace single quotes
1143
							$element_require = $element_require.replace("&quot;", '"'); // replace double quotes
1144
1145
							if (eval($element_require)) {
1146
								jQuery(this).removeClass('sd-require-hide');
1147
							} else {
1148
								jQuery(this).addClass('sd-require-hide');
1149
							}
1150
						}
1151
					});
1152
				}
1153
1154
				/**
1155
				 * Initialise widgets from the widgets screen.
1156
				 */
1157
				function sd_init_widgets($selector) {
1158
					jQuery(".sd-show-advanced").each(function (index) {
1159
						sd_init_widget(this, $selector);
1160
					});
1161
				}
1162
1163
				/**
1164
				 * Initialise a individual widget.
1165
				 */
1166
				function sd_init_widget($this, $selector, $form) {
1167
					if (!$selector) {
1168
						$selector = 'form';
1169
					}
1170
					// Only run once.
1171
					if (jQuery($this).data('sd-widget-enabled')) {
1172
						return;
1173
					} else {
1174
						jQuery($this).data('sd-widget-enabled', true);
1175
					}
1176
1177
					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>';
1178
					var form = $form ? $form : jQuery($this).parents('' + $selector + '');
1179
1180
					if (jQuery($this).val() == '1' && jQuery(form).find('.sd-advanced-button').length == 0) {
1181
						console.log('add advanced button');
1182
						if (jQuery(form).find('.widget-control-save').length > 0) {
1183
							jQuery(form).find('.widget-control-save').after($button);
1184
						} else {
1185
							jQuery(form).find('.sd-show-advanced').after($button);
1186
						}
1187
					} else {
1188
						console.log('no advanced button, ' + jQuery($this).val() + ', ' + jQuery(form).find('.sd-advanced-button').length);
1189
					}
1190
1191
					/* Show hide on form change */
1192
					jQuery(form).on("change", function() {
1193
						sd_show_hide(form);
1194
					});
1195
1196
					/* Show hide on load */
1197
					sd_show_hide(form);
1198
				}
1199
1200
				/**
1201
				 * Init a customizer widget.
1202
				 */
1203
				function sd_init_customizer_widget(section) {
1204
					if (section.expanded) {
1205
						section.expanded.bind(function (isExpanding) {
1206
							if (isExpanding) {
1207
								// is it a SD widget?
1208
								if (jQuery(section.container).find('.sd-show-advanced').length) {
1209
									// init the widget
1210
									sd_init_widget(jQuery(section.container).find('.sd-show-advanced'), ".form");
1211
								}
1212
							}
1213
						});
1214
					}
1215
				}
1216
1217
				/**
1218
				 * If on widgets screen.
1219
				 */
1220
				jQuery(function () {
1221
					// if not in customizer.
1222
					if (!wp.customize) {
1223
						sd_init_widgets("form");
1224
					}
1225
1226
					/* Init on widget added */
1227
					jQuery(document).on('widget-added', function (e, widget) {
1228
						/* Is it a SD widget? */
1229
						if (jQuery(widget).find('.sd-show-advanced').length) {
1230
							var widgetId = jQuery(widget).find('[name="widget-id"]').length ? ': ' + jQuery(widget).find('[name="widget-id"]').val() : '';
1231
							console.log('widget added' + widgetId);
1232
							/* Init the widget */
1233
							sd_init_widget(jQuery(widget).find('.sd-show-advanced'), "form", jQuery(widget).find('.sd-show-advanced').closest('form'));
1234
						}
1235
					});
1236
1237
					/* Init on widget updated */
1238
					jQuery(document).on('widget-updated', function (e, widget) {
1239
						/* Is it a SD widget? */
1240
						if (jQuery(widget).find('.sd-show-advanced').length) {
1241
							var widgetId = jQuery(widget).find('[name="widget-id"]').length ? ': ' + jQuery(widget).find('[name="widget-id"]').val() : '';
1242
							console.log('widget updated' + widgetId);
1243
							/* Init the widget */
1244
							sd_init_widget(jQuery(widget).find('.sd-show-advanced'), "form", jQuery(widget).find('.sd-show-advanced').closest('form'));
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
		 * Parse used group tabs.
1716
		 *
1717
		 * @since 1.1.17
1718
		 */
1719
		public function group_block_tabs( $tabs, $arguments ) {
1720
			if ( ! empty( $tabs ) && ! empty( $arguments ) ) {
1721
				$has_sections = false;
1722
1723
				foreach ( $this->arguments as $key => $args ) {
1724
					if ( isset( $args['group'] ) ) {
1725
						$has_sections = true;
1726
						break;
1727
					}
1728
				}
1729
1730
				if ( ! $has_sections ) {
1731
					return $tabs;
1732
				}
1733
1734
				$new_tabs = array();
1735
1736
				foreach ( $tabs as $tab_key => $tab ) {
1737
					$new_groups = array();
1738
1739
					if ( ! empty( $tab['groups'] ) && is_array( $tab['groups'] ) ) {
1740
						foreach ( $tab['groups'] as $group ) {
1741
							if ( isset( $arguments[ $group ] ) ) {
1742
								$new_groups[] = $group;
1743
							}
1744
						}
1745
					}
1746
1747
					if ( ! empty( $new_groups ) ) {
1748
						$tab['groups'] = $new_groups;
1749
1750
						$new_tabs[ $tab_key ] = $tab;
1751
					}
1752
				}
1753
1754
				$tabs = $new_tabs;
1755
			}
1756
1757
			return $tabs;
1758
		}
1759
1760
		/**
1761
		 * Output the JS for building the dynamic Guntenberg block.
1762
		 *
1763
		 * @return mixed
1764
		 *@since 1.0.9 Save numbers as numbers and not strings.
1765
		 * @since 1.1.0 Font Awesome classes can be used for icons.
1766
		 * @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.
1767
		 */
1768
		public function block() {
1769
            global $sd_is_js_functions_loaded, $aui_bs5;
1770
1771
			ob_start();
1772
1773
			$show_advanced = $this->block_show_advanced();
1774
1775
1776
			?>
1777
			<script>
1778
1779
			<?php
1780
			if(!$sd_is_js_functions_loaded){
1781
                $sd_is_js_functions_loaded = true;
1782
            ?>
1783
1784
function sd_show_view_options($this){
1785
	if(jQuery($this).html().length){
1786
		jQuery($this).html('');
1787
	}else{
1788
		jQuery($this).html('<div class="position-absolute d-flex flex-column bg-white p-1 rounded border shadow-lg " style="top:-80px;left:-5px;"><div class="dashicons dashicons-desktop mb-1" onclick="sd_set_view_type(\'Desktop\');"></div><div class="dashicons dashicons-tablet mb-1" onclick="sd_set_view_type(\'Tablet\');"></div><div class="dashicons dashicons-smartphone" onclick="sd_set_view_type(\'Mobile\');"></div></div>');
1789
	}
1790
}
1791
1792
function sd_set_view_type($device){
1793
	wp.data.dispatch('core/edit-site') ? wp.data.dispatch('core/edit-site').__experimentalSetPreviewDeviceType($device) : wp.data.dispatch('core/edit-post').__experimentalSetPreviewDeviceType($device);
1794
}
1795
/**
1796
 * Try to auto-recover blocks.
1797
 */
1798
function sd_auto_recover_blocks() {
1799
	var recursivelyRecoverInvalidBlockList = blocks => {
1800
		const _blocks = [...blocks]
1801
		let recoveryCalled = false
1802
		const recursivelyRecoverBlocks = willRecoverBlocks => {
1803
			willRecoverBlocks.forEach(_block => {
1804
				if (!_block.isValid) {
1805
					recoveryCalled = true
1806
					const newBlock = recoverBlock(_block)
1807
					for (const key in newBlock) {
1808
						_block[key] = newBlock[key]
1809
					}
1810
				}
1811
				if (_block.innerBlocks.length) {
1812
					recursivelyRecoverBlocks(_block.innerBlocks)
1813
				}
1814
			})
1815
		}
1816
		recursivelyRecoverBlocks(_blocks)
1817
		return [_blocks, recoveryCalled]
1818
	}
1819
	var recoverBlock = ({ name, attributes, innerBlocks }) => wp.blocks.createBlock(name, attributes, innerBlocks);
1820
	var recoverBlocks = blocks => {
1821
		return blocks.map(_block => {
1822
			const block = _block;
1823
			// If the block is a reusable block, recover the Stackable blocks inside it.
1824
			if (_block.name === 'core/block') {
1825
				const { attributes: { ref } } = _block
1826
				const parsedBlocks = wp.blocks.parse(wp.data.select('core').getEntityRecords('postType', 'wp_block', { include: [ref] })?.[0]?.content?.raw) || []
1827
				const [recoveredBlocks, recoveryCalled] = recursivelyRecoverInvalidBlockList(parsedBlocks)
1828
				if (recoveryCalled) {
1829
					console.log('Stackable notice: block ' + block.name + ' (' + block.clientId + ') was auto-recovered, you should not see this after saving your page.');
1830
					return { blocks: recoveredBlocks, isReusable: true, ref }
1831
				}
1832
			} else if (_block.name === 'core/template-part' && _block.attributes && _block.attributes.theme) {
1833
				var tmplPart = wp.data.select('core').getEntityRecord('postType', 'wp_template_part', _block.attributes.theme + '//' + _block.attributes.slug);
1834
				var tmplPartBlocks = block.innerBlocks && block.innerBlocks.length ? block.innerBlocks : wp.blocks.parse(tmplPart?.content?.raw) || [];
1835
				if (tmplPartBlocks && tmplPartBlocks.length && tmplPartBlocks.some(block => !block.isValid)) {
1836
					block.innerBlocks = tmplPartBlocks;
1837
					block.tmplPartId = _block.attributes.theme + '//' + _block.attributes.slug;
1838
				}
1839
			}
1840
			if (block.innerBlocks && block.innerBlocks.length) {
1841
				if (block.tmplPartId) {
1842
					console.log('Template part ' + block.tmplPartId + ' block ' + block.name + ' (' + block.clientId + ') starts');
1843
				}
1844
				const newInnerBlocks = recoverBlocks(block.innerBlocks)
1845
				if (newInnerBlocks.some(block => block.recovered)) {
1846
					block.innerBlocks = newInnerBlocks
1847
					block.replacedClientId = block.clientId
1848
					block.recovered = true
1849
				}
1850
				if (block.tmplPartId) {
1851
					console.log('Template part ' + block.tmplPartId + ' block ' + block.name + ' (' + block.clientId + ') ends');
1852
				}
1853
			}
1854
			if (!block.isValid) {
1855
				const newBlock = recoverBlock(block)
1856
				newBlock.replacedClientId = block.clientId
1857
				newBlock.recovered = true
1858
				console.log('Stackable notice: block ' + block.name + ' (' + block.clientId + ') was auto-recovered, you should not see this after saving your page.');
1859
				return newBlock
1860
			}
1861
			return block
1862
		})
1863
	}
1864
	// Recover all the blocks that we can find.
1865
	var mainBlocks = recoverBlocks(wp.data.select('core/block-editor').getBlocks());
1866
	// Replace the recovered blocks with the new ones.
1867
	mainBlocks.forEach(block => {
1868
		if (block.isReusable && block.ref) {
1869
			// Update the reusable blocks.
1870
			wp.data.dispatch('core').editEntityRecord('postType', 'wp_block', block.ref, {
1871
				content: wp.blocks.serialize(block.blocks)
1872
			}).then(() => {
1873
				// But don't save them, let the user do the saving themselves. Our goal is to get rid of the block error visually.
1874
			})
1875
		}
1876
		if (block.recovered && block.replacedClientId) {
1877
			wp.data.dispatch('core/block-editor').replaceBlock(block.replacedClientId, block)
1878
		}
1879
	})
1880
}
1881
1882
/**
1883
 * Try to auto-recover OUR blocks if traditional way fails.
1884
 */
1885
function sd_auto_recover_blocks_fallback() {
1886
	jQuery(".edit-site-visual-editor__editor-canvas").contents().find('div[class*=" wp-block-blockstrap-"] .block-editor-warning__actions  .block-editor-warning__action .components-button.is-primary').not(":contains('Keep as HTML')").removeAttr('disabled').click();
1887
}
1888
1889
// Wait will window is loaded before calling.
1890
window.onload = function() {
1891
	sd_auto_recover_blocks();
1892
	// fire a second time incase of load delays.
1893
	setTimeout(function() {
1894
		sd_auto_recover_blocks();
1895
	}, 5000);
1896
1897
	setTimeout(function() {
1898
		sd_auto_recover_blocks_fallback();
1899
	}, 6000);
1900
1901
	setTimeout(function() {
1902
		sd_auto_recover_blocks_fallback();
1903
	}, 10000);
1904
1905
	setTimeout(function() {
1906
		sd_auto_recover_blocks_fallback();
1907
	}, 15000);
1908
1909
	setTimeout(function() {
1910
		sd_auto_recover_blocks_fallback();
1911
	}, 20000);
1912
};
1913
1914
// fire when URL changes also.
1915
let lastUrl = location.href;
1916
new MutationObserver(() => {
1917
    const url = location.href;
1918
    if (url !== lastUrl) {
1919
        lastUrl = url;
1920
        sd_auto_recover_blocks();
1921
        // fire a second time incase of load delays.
1922
        setTimeout(function() {
1923
            sd_auto_recover_blocks();
1924
			sd_auto_recover_blocks_fallback();
1925
        }, 2000);
1926
1927
		setTimeout(function() {
1928
		sd_auto_recover_blocks_fallback();
1929
		}, 10000);
1930
1931
		setTimeout(function() {
1932
		sd_auto_recover_blocks_fallback();
1933
		}, 15000);
1934
1935
		setTimeout(function() {
1936
		sd_auto_recover_blocks_fallback();
1937
		}, 20000);
1938
1939
    }
1940
}).observe(document, {
1941
    subtree: true,
1942
    childList: true
1943
});
1944
1945
1946
			/**
1947
			*
1948
* @param $args
1949
* @returns {*|{}}
1950
*/
1951
            function sd_build_aui_styles($args){
1952
1953
                $styles = {};
1954
                // background color
1955
                if ( $args['bg'] !== undefined && $args['bg'] !== '' ) {
1956
                   if( $args['bg'] == 'custom-color' ){
1957
                       $styles['background-color']=  $args['bg_color'];
1958
                   }else  if( $args['bg'] == 'custom-gradient' ){
1959
                       $styles['background-image']=  $args['bg_gradient'];
1960
1961
					    // use background on text
1962
						 if( $args['bg_on_text'] !== undefined && $args['bg_on_text'] ){
1963
							$styles['backgroundClip'] = "text";
1964
							$styles['WebkitBackgroundClip'] = "text";
1965
							$styles['text-fill-color'] = "transparent";
1966
							$styles['WebkitTextFillColor'] = "transparent";
1967
						 }
1968
                   }
1969
1970
                }
1971
1972
				let $bg_image = $args['bg_image'] !== undefined && $args['bg_image'] !== '' ? $args['bg_image'] : '';
1973
1974
				// maybe use featured image.
1975
				if( $args['bg_image_use_featured'] !== undefined && $args['bg_image_use_featured'] ){
1976
					$bg_image = '<?php echo $this->get_url();?>icons/placeholder.png';
1977
				}
1978
1979
                if( $bg_image !== undefined && $bg_image !== '' ){
1980
                    var hasImage = true
1981
                    if($styles['background-color'] !== undefined && $args['bg'] == 'custom-color'){
1982
                           $styles['background-image'] = "url("+$bg_image+")";
1983
                           $styles['background-blend-mode'] =  "overlay";
1984
                    }else if($styles['background-image'] !== undefined && $args['bg'] == 'custom-gradient'){
1985
                           $styles['background-image'] +=  ",url("+$bg_image+")";
1986
                    }else if($args['bg'] !== undefined && $args['bg'] != '' && $args['bg'] != 'transparent' ){
1987
                           // do nothing as we alreay have a preset
1988
                           hasImage = false;
1989
                    }else{
1990
                           $styles['background-image'] = "url("+$bg_image+")";
1991
                    }
1992
1993
                    if( hasImage){
1994
                         $styles['background-size'] = "cover";
1995
1996
						 if( $args['bg_image_fixed'] !== undefined && $args['bg_image_fixed'] ){
1997
							 $styles['background-attachment'] = "fixed";
1998
						 }
1999
                    }
2000
2001
                    if( hasImage && $args['bg_image_xy'].x !== undefined && $args['bg_image_xy'].x >=0 ){
2002
                          $styles['background-position'] =  ($args['bg_image_xy'].x * 100 ) + "% " + ( $args['bg_image_xy'].y * 100) + "%";
2003
                    }
2004
                }
2005
2006
2007
2008
				// sticky offset top
2009
				if( $args['sticky_offset_top'] !== undefined && $args['sticky_offset_top'] !== '' ){
2010
					$styles['top'] =  $args['sticky_offset_top'];
2011
				}
2012
2013
				// sticky offset bottom
2014
				if( $args['sticky_offset_bottom'] !== undefined && $args['sticky_offset_bottom'] !== '' ){
2015
					$styles['bottom'] =  $args['sticky_offset_bottom'];
2016
				}
2017
2018
				// font size
2019
				if( $args['font_size'] === undefined || $args['font_size'] === 'custom' ){
2020
					if( $args['font_size_custom'] !== undefined && $args['font_size_custom'] !== '' ){
2021
						$styles['fontSize'] =  $args['font_size_custom'] + "rem";
2022
					}
2023
				}
2024
2025
				// font color
2026
				if( $args['text_color'] === undefined || $args['text_color'] === 'custom' ){
2027
					if( $args['text_color_custom'] !== undefined && $args['text_color_custom'] !== '' ){
2028
						$styles['color'] =  $args['text_color_custom'];
2029
					}
2030
				}
2031
2032
				// font line height
2033
				if( $args['font_line_height'] !== undefined && $args['font_line_height'] !== '' ){
2034
					$styles['lineHeight'] =  $args['font_line_height'];
2035
				}
2036
2037
				// max height
2038
				if( $args['max_height'] !== undefined && $args['max_height'] !== '' ){
2039
					$styles['maxHeight'] =  $args['max_height'];
2040
				}
2041
2042
                return $styles;
2043
2044
            }
2045
2046
            function sd_build_aui_class($args){
2047
2048
                $classes = [];
2049
2050
				<?php
2051
				if($aui_bs5){
2052
					?>
2053
				$aui_bs5 = true;
2054
				$p_ml = 'ms-';
2055
				$p_mr = 'me-';
2056
2057
				$p_pl = 'ps-';
2058
				$p_pr = 'pe-';
2059
					<?php
2060
				}else{
2061
						?>
2062
				$aui_bs5 = false;
2063
				$p_ml = 'ml-';
2064
				$p_mr = 'mr-';
2065
2066
				$p_pl = 'pl-';
2067
				$p_pr = 'pr-';
2068
					<?php
2069
				}
2070
				?>
2071
2072
                // margins
2073
	            if ( $args['mt'] !== undefined && $args['mt'] !== '' ) { $classes.push( "mt-" + $args['mt'] );  $mt = $args['mt']; }else{$mt = null;}
2074
	            if ( $args['mr'] !== undefined && $args['mr'] !== '' ) { $classes.push( $p_mr + $args['mr'] );  $mr = $args['mr']; }else{$mr = null;}
2075
	            if ( $args['mb'] !== undefined && $args['mb'] !== '' ) { $classes.push( "mb-" + $args['mb'] );  $mb = $args['mb']; }else{$mb = null;}
2076
	            if ( $args['ml'] !== undefined && $args['ml'] !== '' ) { $classes.push( $p_ml + $args['ml'] );  $ml = $args['ml']; }else{$ml = null;}
2077
2078
                // margins tablet
2079
	            if ( $args['mt_md'] !== undefined && $args['mt_md'] !== '' ) { $classes.push( "mt-md-" + $args['mt_md'] );  $mt_md = $args['mt_md']; }else{$mt_md = null;}
2080
	            if ( $args['mr_md'] !== undefined && $args['mr_md'] !== '' ) { $classes.push( $p_mr + "md-" + $args['mr_md'] );  $mt_md = $args['mr_md']; }else{$mr_md = null;}
2081
	            if ( $args['mb_md'] !== undefined && $args['mb_md'] !== '' ) { $classes.push( "mb-md-" + $args['mb_md'] );  $mt_md = $args['mb_md']; }else{$mb_md = null;}
2082
	            if ( $args['ml_md'] !== undefined && $args['ml_md'] !== '' ) { $classes.push( $p_ml + "md-" + $args['ml_md'] );  $mt_md = $args['ml_md']; }else{$ml_md = null;}
2083
2084
                // margins desktop
2085
                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'] ); } }
2086
	            if ( $args['mr_lg'] !== undefined && $args['mr_lg'] !== '' ) { if($mr == null && $mr_md == null){ $classes.push( $p_mr + $args['mr_lg'] ); }else{$classes.push( $p_mr + "lg-" + $args['mr_lg'] ); } }
2087
	            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'] ); } }
2088
	            if ( $args['ml_lg'] !== undefined && $args['ml_lg'] !== '' ) { if($ml == null && $ml_md == null){ $classes.push( $p_ml + $args['ml_lg'] ); }else{$classes.push( $p_ml + "lg-" + $args['ml_lg'] ); } }
2089
2090
                // padding
2091
                if ( $args['pt'] !== undefined && $args['pt'] !== '' ) { $classes.push( "pt-" + $args['pt'] ); $pt = $args['pt']; }else{$pt = null;}
2092
	            if ( $args['pr'] !== undefined && $args['pr'] !== '' ) { $classes.push( $p_pr + $args['pr'] ); $pr = $args['pt']; }else{$pr = null;}
2093
	            if ( $args['pb'] !== undefined && $args['pb'] !== '' ) { $classes.push( "pb-" + $args['pb'] ); $pb = $args['pt']; }else{$pb = null;}
2094
	            if ( $args['pl'] !== undefined && $args['pl'] !== '' ) { $classes.push( $p_pl + $args['pl'] ); $pl = $args['pt']; }else{$pl = null;}
2095
2096
                // padding tablet
2097
                if ( $args['pt_md'] !== undefined && $args['pt_md'] !== '' ) { $classes.push( "pt-md-" + $args['pt_md'] ); $pt_md = $args['pt_md']; }else{$pt_md = null;}
2098
	            if ( $args['pr_md'] !== undefined && $args['pr_md'] !== '' ) { $classes.push( $p_pr + "md-" + $args['pr_md'] ); $pr_md = $args['pt_md']; }else{$pr_md = null;}
2099
	            if ( $args['pb_md'] !== undefined && $args['pb_md'] !== '' ) { $classes.push( "pb-md-" + $args['pb_md'] ); $pb_md = $args['pt_md']; }else{$pb_md = null;}
2100
	            if ( $args['pl_md'] !== undefined && $args['pl_md'] !== '' ) { $classes.push( $p_pl + "md-" + $args['pl_md'] ); $pl_md = $args['pt_md']; }else{$pl_md = null;}
2101
2102
                // padding desktop
2103
                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'] ); } }
2104
	            if ( $args['pr_lg'] !== undefined && $args['pr_lg'] !== '' ) { if($pr == null && $pr_md == null){ $classes.push( $p_pr + $args['pr_lg'] ); }else{$classes.push( $p_pr + "lg-" + $args['pr_lg'] ); } }
2105
	            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'] ); } }
2106
	            if ( $args['pl_lg'] !== undefined && $args['pl_lg'] !== '' ) { if($pl == null && $pl_md == null){ $classes.push( $p_pl + $args['pl_lg'] ); }else{$classes.push( $p_pl + "lg-" + $args['pl_lg'] ); } }
2107
2108
				// row cols, mobile, tablet, desktop
2109
	            if ( $args['row_cols'] !== undefined && $args['row_cols'] !== '' ) { $classes.push( "row-cols-" + $args['row_cols'] );  $row_cols = $args['row_cols']; }else{$row_cols = null;}
2110
	            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;}
2111
                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'] ); } }
2112
2113
				// columns , mobile, tablet, desktop
2114
	            if ( $args['col'] !== undefined && $args['col'] !== '' ) { $classes.push( "col-" + $args['col'] );  $col = $args['col']; }else{$col = null;}
2115
	            if ( $args['col_md'] !== undefined && $args['col_md'] !== '' ) { $classes.push( "col-md-" + $args['col_md'] );  $col_md = $args['col_md']; }else{$col_md = null;}
2116
                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'] ); } }
2117
2118
2119
                // border
2120
                if ( $args['border'] === undefined || $args['border']=='')  { }
2121
                else if ( $args['border'] !== undefined && ( $args['border']=='none' || $args['border']==='0') ) { $classes.push( "border-0" ); }
2122
	            else if ( $args['border'] !== undefined ) {
2123
					if($aui_bs5 && $args['border_type'] !== undefined){
2124
						$args['border_type'] = $args['border_type'].replace('-left','-start').replace('-right','-end');
2125
					}
2126
					$border_class = 'border';
2127
					if ( $args['border_type'] !== undefined && ! $args['border_type'].includes( '-0' )  ) {
2128
						$border_class = '';
2129
					}
2130
					$classes.push( $border_class + " border-" + $args['border'] );
2131
				}
2132
2133
                // border radius type
2134
              //  if ( $args['rounded'] !== undefined && $args['rounded'] !== '' ) { $classes.push($args['rounded']); }
2135
2136
                // border radius size
2137
                if( $args['rounded_size'] !== undefined && ( $args['rounded_size']==='sm' || $args['rounded_size']==='lg' ) ){
2138
					if ( $args['rounded_size'] !== undefined && $args['rounded_size'] !== '' ) {
2139
						$classes.push("rounded-" + $args['rounded_size']);
2140
						// if we set a size then we need to remove "rounded" if set
2141
						var index = $classes.indexOf("rounded");
2142
						if (index !== -1) {
2143
						  $classes.splice(index, 1);
2144
						}
2145
                	}
2146
                }else{
2147
					// rounded_size , mobile, tablet, desktop
2148
					if ( $args['rounded_size'] !== undefined && $args['rounded_size'] !== '' ) { $classes.push( "rounded-" + $args['rounded_size'] );  $rounded_size = $args['rounded_size']; }else{$rounded_size = null;}
2149
					if ( $args['rounded_size_md'] !== undefined && $args['rounded_size_md'] !== '' ) { $classes.push( "rounded-md-" + $args['rounded_size_md'] );  $rounded_size_md = $args['rounded_size_md']; }else{$rounded_size_md = null;}
2150
					if ( $args['rounded_size_lg'] !== undefined && $args['rounded_size_lg'] !== '' ) { if($rounded_size == null && $rounded_size_md == null){ $classes.push( "rounded-" + $args['rounded_size_lg'] ); }else{$classes.push( "rounded-lg-" + $args['rounded_size_lg'] ); } }
2151
                }
2152
2153
2154
                // shadow
2155
               // if ( $args['shadow'] !== undefined && $args['shadow'] !== '' ) { $classes.push($args['shadow']); }
2156
2157
                // background
2158
                if ( $args['bg'] !== undefined  && $args['bg'] !== '' ) { $classes.push("bg-" + $args['bg']); }
2159
2160
                // text_color
2161
                if ( $args['text_color'] !== undefined && $args['text_color'] !== '' ) { $classes.push( "text-" + $args['text_color']); }
2162
2163
                // text_align
2164
                if ( $args['text_justify'] !== undefined && $args['text_justify'] ) { $classes.push('text-justify'); }
2165
                else{
2166
                    if ( $args['text_align'] !== undefined && $args['text_align'] !== '' ) {
2167
						if($aui_bs5){ $args['text_align'] = $args['text_align'].replace('-left','-start').replace('-right','-end'); }
2168
						$classes.push($args['text_align']); $text_align = $args['text_align'];
2169
					}else{$text_align = null;}
2170
                    if ( $args['text_align_md'] !== undefined && $args['text_align_md'] !== '' ) {
2171
						if($aui_bs5){ $args['text_align_md'] = $args['text_align_md'].replace('-left','-start').replace('-right','-end'); }
2172
						$classes.push($args['text_align_md']); $text_align_md = $args['text_align_md'];
2173
					}else{$text_align_md = null;}
2174
                    if ( $args['text_align_lg'] !== undefined && $args['text_align_lg'] !== '' ) {
2175
						if($aui_bs5){ $args['text_align_lg'] = $args['text_align_lg'].replace('-left','-start').replace('-right','-end'); }
2176
						if($text_align  == null && $text_align_md == null){ $classes.push($args['text_align_lg'].replace("-lg", ""));
2177
						}else{$classes.push($args['text_align_lg']);} }
2178
                }
2179
2180
				// display
2181
			  	if ( $args['display'] !== undefined && $args['display'] !== '' ) { $classes.push($args['display']); $display = $args['display']; }else{$display = null;}
2182
				if ( $args['display_md'] !== undefined && $args['display_md'] !== '' ) { $classes.push($args['display_md']); $display_md = $args['display_md']; }else{$display_md = null;}
2183
				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']);} }
2184
2185
				// bgtus - background transparent until scroll
2186
                if ( $args['bgtus'] !== undefined && $args['bgtus'] ) { $classes.push("bg-transparent-until-scroll"); }
2187
2188
				// cscos - change color scheme on scroll
2189
                if ( $args['bgtus'] !== undefined && $args['bgtus'] && $args['cscos'] !== undefined && $args['cscos'] ) { $classes.push("color-scheme-flip-on-scroll"); }
2190
2191
				// hover animations
2192
                if ( $args['hover_animations'] !== undefined && $args['hover_animations'] ) { $classes.push($args['hover_animations'].toString().replace(',',' ')); }
2193
2194
				// absolute_position
2195
				if ( $args['absolute_position'] !== undefined ) {
2196
					if ( 'top-left' === $args['absolute_position'] ) {
2197
						$classes.push('start-0 top-0');
2198
					} else if ( 'top-center' === $args['absolute_position'] ) {
2199
						$classes.push('start-50 top-0 translate-middle');
2200
					} else if ( 'top-right' === $args['absolute_position'] ) {
2201
						$classes.push('end-0 top-0');
2202
					} else if ( 'center-left' === $args['absolute_position'] ) {
2203
						$classes.push('start-0 bottom-50');
2204
					} else if ( 'center' === $args['absolute_position'] ) {
2205
						$classes.push('start-50 top-50 translate-middle');
2206
					} else if ( 'center-right' === $args['absolute_position'] ) {
2207
						$classes.push('end-0 top-50');
2208
					} else if ( 'bottom-left' === $args['absolute_position'] ) {
2209
						$classes.push('start-0 bottom-0');
2210
					} else if ( 'bottom-center' === $args['absolute_position'] ) {
2211
						$classes.push('start-50 bottom-0 translate-middle');
2212
					} else if ( 'bottom-right' === $args['absolute_position'] ) {
2213
						$classes.push('end-0 bottom-0');
2214
					}
2215
				}
2216
2217
				// build classes from build keys
2218
				$build_keys = sd_get_class_build_keys();
2219
				if ( $build_keys.length ) {
2220
					$build_keys.forEach($key => {
2221
2222
						if($key.endsWith("-MTD")){
2223
2224
							$k = $key.replace("-MTD","");
2225
2226
							// Mobile, Tablet, Desktop
2227
							if ( $args[$k] !== undefined && $args[$k] !== '' ) { $classes.push( $args[$k] );  $v = $args[$k]; }else{$v = null;}
2228
							if ( $args[$k + '_md'] !== undefined && $args[$k + '_md'] !== '' ) { $classes.push( $args[$k + '_md'] );  $v_md = $args[$k + '_md']; }else{$v_md = null;}
2229
							if ( $args[$k + '_lg'] !== undefined && $args[$k + '_lg'] !== '' ) { if($v == null && $v_md == null){ $classes.push( $args[$k + '_lg'].replace('-lg','') ); }else{$classes.push( $args[$k + '_lg'] ); } }
2230
2231
						}else{
2232
							if ( $key == 'font_size' && $args[ $key ] == 'custom' ) {
2233
							 return;
2234
							}
2235
							if ( $args[$key] !== undefined && $args[$key] !== '' ) { $classes.push($args[$key]); }
2236
						}
2237
2238
					});
2239
				}
2240
2241
                return $classes.join(" ");
2242
            }
2243
2244
			function sd_get_class_build_keys(){
2245
				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...
2246
			}
2247
2248
            <?php
2249
2250
2251
            }
2252
2253
			if(method_exists($this,'block_global_js')){
2254
					echo $this->block_global_js();
2255
			}
2256
			?>
2257
2258
jQuery(function() {
2259
2260
				/**
2261
				 * BLOCK: Basic
2262
				 *
2263
				 * Registering a basic block with Gutenberg.
2264
				 * Simple block, renders and saves the same content without any interactivity.
2265
				 *
2266
				 * Styles:
2267
				 *        editor.css — Editor styles for the block.
2268
				 *        style.css  — Editor & Front end styles for the block.
2269
				 */
2270
				(function (blocksx, elementx, blockEditor) {
2271
					var __ = wp.i18n.__; // The __() for internationalization.
2272
					var el = wp.element.createElement; // The wp.element.createElement() function to create elements.
2273
					var editable = wp.blocks.Editable;
2274
					var blocks = wp.blocks;
2275
					var registerBlockType = wp.blocks.registerBlockType; // The registerBlockType() to register blocks.
2276
					var is_fetching = false;
2277
					var prev_attributes = [];
2278
2279
                    var InnerBlocks = blockEditor.InnerBlocks;
2280
2281
					var term_query_type = '';
2282
					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 "[]";} ?>;
2283
					const taxonomies_<?php echo str_replace("-","_", $this->id);?> = [{label: "Please wait", value: 0}];
2284
					const sort_by_<?php echo str_replace("-","_", $this->id);?> = [{label: "Please wait", value: 0}];
2285
                    const MediaUpload = wp.blockEditor.MediaUpload;
2286
2287
					/**
2288
					 * Register Basic Block.
2289
					 *
2290
					 * Registers a new block provided a unique name and an object defining its
2291
					 * behavior. Once registered, the block is made available as an option to any
2292
					 * editor interface where blocks are implemented.
2293
					 *
2294
					 * @param  {string}   name     Block name.
2295
					 * @param  {Object}   settings Block settings.
2296
					 * @return {?WPBlock}          The block, if it has been successfully
2297
					 *                             registered; otherwise `undefined`.
2298
					 */
2299
					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.
2300
						apiVersion: <?php echo isset($this->options['block-api-version']) ? absint($this->options['block-api-version']) : 2 ; ?>,
2301
                        title: '<?php echo addslashes( $this->options['name'] ); ?>', // Block title.
2302
						description: '<?php echo addslashes( $this->options['widget_ops']['description'] )?>', // Block title.
2303
						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/.
2304
						supports: {
2305
							<?php
2306
							if ( isset( $this->options['block-supports'] ) ) {
2307
								echo $this->array_to_attributes( $this->options['block-supports'] );
2308
							}
2309
							?>
2310
						},
2311
						<?php
2312
						if ( isset( $this->options['block-label'] ) ) {
2313
						?>
2314
						__experimentalLabel( attributes, { context } ) {
2315
                            return <?php echo $this->options['block-label']; ?>;
2316
                        },
2317
                        <?php
2318
                        }
2319
                        ?>
2320
						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.
2321
						<?php if ( isset( $this->options['block-keywords'] ) ) {
2322
						echo "keywords : " . $this->options['block-keywords'] . ",";
2323
2324
//						// block hover preview.
2325
//						$example_args = array();
2326
//						if(!empty($this->arguments)){
2327
//							foreach($this->arguments as $key => $a_args){
2328
//								if(isset($a_args['example'])){
2329
//									$example_args[$key] = $a_args['example'];
2330
//								}
2331
//							}
2332
//						}
2333
//						$viewport_width = isset($this->options['example']['viewportWidth']) ? 'viewportWidth: '.absint($this->options['example']['viewportWidth']) : '';
2334
//						if( isset( $this->options['example'] ) && $this->options['example'] === false ){
2335
//							// no preview if set to false
2336
//						}elseif( !empty( $example_args ) ){
2337
//							echo "example : {attributes:{".$this->array_to_attributes( $example_args )."},$viewport_width},";
2338
//						}elseif( !empty( $this->options['example'] ) ){
2339
//							unset($this->options['example']['viewportWidth']);
2340
//							echo "example : {".$this->array_to_attributes( $this->options['example'] ).$viewport_width."},";
2341
//						}else{
2342
//							echo 'example : {'.$viewport_width.'},';
2343
//						}
2344
2345
                        }
2346
2347
						// maybe set no_wrap
2348
						$no_wrap = isset( $this->options['no_wrap'] ) && $this->options['no_wrap'] ? true : false;
2349
						if ( isset( $this->arguments['no_wrap'] ) && $this->arguments['no_wrap'] ) {
2350
							$no_wrap = true;
2351
						}
2352
						if ( $no_wrap ) {
2353
							$this->options['block-wrap'] = '';
2354
						}
2355
2356
						// maybe load the drag/drop functions.
2357
						$img_drag_drop = false;
2358
2359
						$show_alignment = false;
2360
						// align feature
2361
						/*echo "supports: {";
2362
						echo "	align: true,";
2363
						echo "  html: false";
2364
						echo "},";*/
2365
2366
						if ( ! empty( $this->arguments ) ) {
2367
							echo "attributes : {";
2368
2369
							if ( $show_advanced ) {
2370
								echo "show_advanced: {";
2371
								echo "	type: 'boolean',";
2372
								echo "  default: false,";
2373
								echo "},";
2374
							}
2375
2376
							// block wrap element
2377
							if ( ! empty( $this->options['block-wrap'] ) ) { //@todo we should validate this?
2378
								echo "block_wrap: {";
2379
								echo "	type: 'string',";
2380
								echo "  default: '" . esc_attr( $this->options['block-wrap'] ) . "',";
2381
								echo "},";
2382
							}
2383
2384
2385
2386
							foreach ( $this->arguments as $key => $args ) {
2387
2388
								if( $args['type'] == 'image' ||  $args['type'] == 'images' ){
2389
									$img_drag_drop = true;
2390
								}
2391
2392
								// set if we should show alignment
2393
								if ( $key == 'alignment' ) {
2394
									$show_alignment = true;
2395
								}
2396
2397
								$extra = '';
0 ignored issues
show
Unused Code introduced by
The assignment to $extra is dead and can be removed.
Loading history...
2398
2399
								if ( $args['type'] == 'notice' ||  $args['type'] == 'tab' ) {
2400
									continue;
2401
								}
2402
								elseif ( $args['type'] == 'checkbox' ) {
2403
									$type    = 'boolean';
2404
									$default = isset( $args['default'] ) && $args['default'] ? 'true' : 'false';
2405
								} elseif ( $args['type'] == 'number' ) {
2406
									$type    = 'number';
2407
									$default = isset( $args['default'] ) ? "'" . $args['default'] . "'" : "''";
2408
								} elseif ( $args['type'] == 'select' && ! empty( $args['multiple'] ) ) {
2409
									$type = 'array';
2410
									if ( isset( $args['default'] ) && is_array( $args['default'] ) ) {
2411
										$default = ! empty( $args['default'] ) ? "['" . implode( "','", $args['default'] ) . "']" : "[]";
2412
									} else {
2413
										$default = isset( $args['default'] ) ? "'" . $args['default'] . "'" : "''";
2414
									}
2415
								} elseif ( $args['type'] == 'tagselect' ) {
2416
									$type    = 'array';
2417
									$default = isset( $args['default'] ) ? "'" . $args['default'] . "'" : "''";
2418
								} elseif ( $args['type'] == 'multiselect' ) {
2419
									$type    = 'array';
2420
									$default = isset( $args['default'] ) ? "'" . $args['default'] . "'" : "''";
2421
								} elseif ( $args['type'] == 'image_xy' ) {
2422
									$type    = 'object';
2423
									$default = isset( $args['default'] ) ? "'" . $args['default'] . "'" : "''";
2424
								} elseif ( $args['type'] == 'image' ) {
2425
									$type    = 'string';
2426
									$default = isset( $args['default'] ) ? "'" . $args['default'] . "'" : "''";
2427
2428
                                    // add a field for ID
2429
//                                    echo $key . "_id : {";
2430
//                                    echo "type : 'number',";
2431
//                                    echo "},";
2432
//                                    echo $key . "_xy : {";
2433
//                                    echo "type : 'object',";
2434
//                                    echo "},";
2435
2436
								} else {
2437
									$type    = !empty($args['hidden_type']) ? esc_attr($args['hidden_type']) : 'string';
2438
									$default = isset( $args['default'] ) ? "'" . $args['default'] . "'" : "''";
2439
2440
								}
2441
								echo $key . " : {";
2442
								echo "type : '$type',";
2443
								echo "default : $default,";
2444
								echo "},";
2445
							}
2446
2447
							echo "content : {type : 'string',default: 'Please select the attributes in the block settings'},";
2448
							echo "className: { type: 'string', default: '' },";
2449
2450
							echo "},";
2451
2452
						}
2453
2454
						?>
2455
2456
						// The "edit" property must be a valid function.
2457
						edit: function (props) {
2458
2459
2460
<?php
2461
// only include the drag/drop functions if required.
2462
if( $img_drag_drop ){
2463
2464
?>
2465
2466
function enableDragSort(listClass) {
2467
	setTimeout(function(){
2468
		 const sortableLists = document.getElementsByClassName(listClass);
2469
		 Array.prototype.map.call(sortableLists, (list) => {enableDragList(list)});
2470
	}, 300);
2471
}
2472
2473
function enableDragList(list) {
2474
  Array.prototype.map.call(list.children, (item) => {enableDragItem(item)});
2475
}
2476
2477
function enableDragItem(item) {
2478
  item.setAttribute('draggable', true)
2479
  item.ondrag = handleDrag;
2480
  item.ondragend = handleDrop;
2481
}
2482
2483
function handleDrag(item) {
2484
  const selectedItem = item.target,
2485
        list = selectedItem.parentNode,
2486
        x = event.clientX,
2487
        y = event.clientY;
2488
2489
  selectedItem.classList.add('drag-sort-active');
2490
  let swapItem = document.elementFromPoint(x, y) === null ? selectedItem : document.elementFromPoint(x, y);
2491
2492
  if (list === swapItem.parentNode) {
2493
    swapItem = swapItem !== selectedItem.nextSibling ? swapItem : swapItem.nextSibling;
2494
    list.insertBefore(selectedItem, swapItem);
2495
  }
2496
}
2497
2498
function handleDrop(item) {
2499
2500
	item.target.classList.remove('drag-sort-active');
2501
2502
	const newOrder = [];
2503
	let $parent = item.target.parentNode;
2504
	let $field = $parent.dataset.field;
2505
	let $imgs = JSON.parse('[' + props.attributes[$field] + ']');
2506
	item.target.parentNode.classList.add('xxx');
2507
	$children = $parent.children;
2508
2509
	Object.keys($children).forEach(function(key) {
2510
	  let $nKey = $children[key].dataset.index
2511
	  newOrder.push($imgs[$nKey]);
2512
	});
2513
2514
	// @todo find out why we need to empty the value first otherwise the order is wrong.
2515
	props.setAttributes({ [$field]: '' });
2516
	setTimeout(function(){
2517
		props.setAttributes({ [$field]: JSON.stringify(newOrder).replace('[','').replace(']','') });
2518
	}, 100);
2519
2520
}
2521
<?php } ?>
2522
2523
							if (typeof(props.attributes.styleid) !== 'undefined'){
2524
								if(props.attributes.styleid==''){ props.setAttributes({ 'styleid': 'block-'+(Math.random() + 1).toString(36).substring(2) } ); }
2525
							}
2526
2527
                            <?php
2528
                            if(!empty($this->options['block-edit-raw'])) {
2529
                                echo $this->options['block-edit-raw']; // strings have to be in single quotes, may cause issues
2530
                            }else{
2531
                            ?>
2532
2533
function hasSelectedInnerBlock(props) {
2534
    const select = wp.data.select('core/editor');
2535
    const selected = select.getBlockSelectionStart();
2536
    const inner = select.getBlock(props.clientId).innerBlocks;
2537
    for (let i = 0; i < inner.length; i++) {
2538
        if (inner[i].clientId === selected || inner[i].innerBlocks.length && hasSelectedInnerBlock(inner[i])) {
2539
            return true;
2540
        }
2541
    }
2542
    return false;
2543
};
2544
2545
const parentBlocksIDs = wp.data.select( 'core/block-editor' ).getBlockParents(props.clientId);
2546
const parentBlocks = wp.data.select('core/block-editor').getBlocksByClientId(parentBlocksIDs);
2547
// const isParentOfSelectedBlock = useSelect( ( select ) => wp.data.select( 'core/block-editor' ).hasSelectedInnerBlock( props.clientId, true ) ):
2548
    const block = wp.data.select('core/block-editor').getBlocksByClientId(props.clientId);//.[0].innerBlocks;
2549
    const childBlocks = block[0] == null ? '' : block[0].innerBlocks;
2550
2551
	var $value = '';
2552
	<?php
2553
	// if we have a post_type and a category then link them
2554
	if( isset($this->arguments['post_type']) && isset($this->arguments['category']) && !empty($this->arguments['category']['post_type_linked']) ){
2555
	?>
2556
	if(typeof(prev_attributes[props.clientId]) != 'undefined'){
2557
		$pt = props.attributes.post_type;
2558
		if(post_type_rest_slugs.length){
2559
			$value = post_type_rest_slugs[0][$pt];
2560
		}
2561
		var run = false;
2562
2563
		if($pt != term_query_type){
2564
			run = true;
2565
			term_query_type = $pt;
2566
		}
2567
<?php
2568
	$cat_path = '';
2569
	if ( ! empty( $this->arguments['post_type']['onchange_rest']['path'] ) ) {
2570
		$cat_path = esc_js( strip_tags( $this->arguments['post_type']['onchange_rest']['path'] ) );
2571
		$cat_path = str_replace( array( '&quot;', '&#039;' ), array( '"', "'" ), $cat_path );
2572
	}
2573
?>
2574
		/* taxonomies */
2575
		if($value && 'post_type' in prev_attributes[props.clientId] && 'category' in prev_attributes[props.clientId] && run){
2576
			if (!window.gdCPTCats) {
2577
				window.gdCPTCats = [];
2578
			}
2579
			var gdCatPath = "<?php echo ( ! empty( $cat_path ) ? $cat_path : "/wp/v2/" + $value + "/categories/?per_page=100" ); ?>";
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $value seems to be never defined.
Loading history...
2580
			if (window.gdCPTCats[gdCatPath]) {
2581
				terms = window.gdCPTCats[gdCatPath];
2582
				while (taxonomies_<?php echo str_replace("-","_", $this->id);?>.length) {
2583
					taxonomies_<?php echo str_replace("-","_", $this->id);?>.pop();
2584
				}
2585
				taxonomies_<?php echo str_replace("-","_", $this->id);?>.push({label: "All", value: 0});
2586
				jQuery.each( terms, function( key, val ) {
2587
					taxonomies_<?php echo str_replace("-","_", $this->id);?>.push({label: val.name, value: val.id});
2588
				});
2589
2590
				/* Setting the value back and fourth fixes the no update issue that sometimes happens where it won't update the options. */
2591
				var $old_cat_value = props.attributes.category
2592
				props.setAttributes({category: [0] });
2593
				props.setAttributes({category: $old_cat_value });
2594
			} else {
2595
				wp.apiFetch({path: gdCatPath}).then(terms => {
2596
					window.gdCPTCats[gdCatPath] = terms;
2597
					while (taxonomies_<?php echo str_replace("-","_", $this->id);?>.length) {
2598
						taxonomies_<?php echo str_replace("-","_", $this->id);?>.pop();
2599
					}
2600
					taxonomies_<?php echo str_replace("-","_", $this->id);?>.push({label: "All", value: 0});
2601
					jQuery.each( terms, function( key, val ) {
2602
						taxonomies_<?php echo str_replace("-","_", $this->id);?>.push({label: val.name, value: val.id});
2603
					});
2604
2605
					/* Setting the value back and fourth fixes the no update issue that sometimes happens where it won't update the options. */
2606
					var $old_cat_value = props.attributes.category
2607
					props.setAttributes({category: [0] });
2608
					props.setAttributes({category: $old_cat_value });
2609
2610
					return taxonomies_<?php echo str_replace("-","_", $this->id);?>;
2611
				});
2612
			}
2613
		}
2614
2615
		/* sort_by */
2616
		if($value && 'post_type' in prev_attributes[props.clientId] && 'sort_by' in prev_attributes[props.clientId] && run){
2617
			if (!window.gdCPTSort) {
2618
				window.gdCPTSort = [];
2619
			}
2620
			if (window.gdCPTSort[$pt]) {
2621
				response = window.gdCPTSort[$pt];
2622
				while (sort_by_<?php echo str_replace("-","_", $this->id);?>.length) {
2623
					sort_by_<?php echo str_replace("-","_", $this->id);?>.pop();
2624
				}
2625
2626
				jQuery.each( response, function( key, val ) {
2627
					sort_by_<?php echo str_replace("-","_", $this->id);?>.push({label: val, value: key});
2628
				});
2629
2630
				// setting the value back and fourth fixes the no update issue that sometimes happens where it won't update the options.
2631
				var $old_sort_by_value = props.attributes.sort_by
2632
				props.setAttributes({sort_by: [0] });
2633
				props.setAttributes({sort_by: $old_sort_by_value });
2634
			} else {
2635
				var data = {
2636
					'action': 'geodir_get_sort_options',
2637
					'post_type': $pt
2638
				};
2639
				jQuery.post(ajaxurl, data, function(response) {
2640
					response = JSON.parse(response);
2641
					window.gdCPTSort[$pt] = response;
2642
					while (sort_by_<?php echo str_replace("-","_", $this->id);?>.length) {
2643
						sort_by_<?php echo str_replace("-","_", $this->id);?>.pop();
2644
					}
2645
2646
					jQuery.each( response, function( key, val ) {
2647
						sort_by_<?php echo str_replace("-","_", $this->id);?>.push({label: val, value: key});
2648
					});
2649
2650
					// setting the value back and fourth fixes the no update issue that sometimes happens where it won't update the options.
2651
					var $old_sort_by_value = props.attributes.sort_by
2652
					props.setAttributes({sort_by: [0] });
2653
					props.setAttributes({sort_by: $old_sort_by_value });
2654
2655
					return sort_by_<?php echo str_replace("-","_", $this->id);?>;
2656
				});
2657
			}
2658
		}
2659
	}
2660
	<?php } ?>
2661
<?php
2662
$current_screen = function_exists('get_current_screen') ? get_current_screen() : '';
0 ignored issues
show
Bug introduced by
Are you sure the usage of get_current_screen() 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...
2663
if(!empty($current_screen->base) && $current_screen->base==='widgets'){
0 ignored issues
show
Bug introduced by
The property base does not exist on string.
Loading history...
2664
	echo 'const { deviceType } = "";';
2665
}else{
2666
?>
2667
/** Get device type const. */
2668
const { deviceType } = wp.data.useSelect != 'undefined' ?  wp.data.useSelect(select => {
2669
	const { __experimentalGetPreviewDeviceType } = select('core/edit-site') ? select('core/edit-site') : select('core/edit-post') ? select('core/edit-post') : ''; // For sie editor https://github.com/WordPress/gutenberg/issues/39248
2670
	return {
2671
		deviceType: __experimentalGetPreviewDeviceType(),
2672
	}
2673
}, []) : '';
2674
<?php } ?>
2675
							var content = props.attributes.content;
2676
2677
							function onChangeContent($type) {
2678
// console.log(deviceType);
2679
								$refresh = false;
2680
								// Set the old content the same as the new one so we only compare all other attributes
2681
								if(typeof(prev_attributes[props.clientId]) != 'undefined'){
2682
									prev_attributes[props.clientId].content = props.attributes.content;
2683
								}else if(props.attributes.content === ""){
2684
									// if first load and content empty then refresh
2685
									$refresh = true;
2686
								}
2687
2688
								if ( ( !is_fetching &&  JSON.stringify(prev_attributes[props.clientId]) != JSON.stringify(props.attributes) ) || $refresh  ) {
2689
2690
									is_fetching = true;
2691
2692
									var data = {
2693
										'action': 'super_duper_output_shortcode',
2694
										'shortcode': '<?php echo $this->options['base_id'];?>',
2695
										'attributes': props.attributes,
2696
										'block_parent_name': parentBlocks.length ? parentBlocks[parentBlocks.length - 1].name : '',
2697
										'post_id': <?php global $post; if ( isset( $post->ID ) ) {
2698
										echo $post->ID;
2699
									}else{echo '0';}?>,
2700
										'_ajax_nonce': '<?php echo wp_create_nonce( 'super_duper_output_shortcode' );?>'
2701
									};
2702
2703
									jQuery.post(ajaxurl, data, function (response) {
2704
										return response;
2705
									}).then(function (env) {
2706
2707
										// if the content is empty then we place some placeholder text
2708
										if (env == '') {
2709
											env = "<div style='background:#0185ba33;padding: 10px;border: 4px #ccc dashed;'>" + "<?php _e( 'Placeholder for: ' );?>" + props.name + "</div>";
2710
										}
2711
2712
                                         <?php
2713
                                        if(!empty($this->options['nested-block'])){
2714
                                            ?>
2715
                                            // props.setAttributes({content: env});
2716
										is_fetching = false;
2717
										prev_attributes[props.clientId] = props.attributes;
2718
                                             <?php
2719
                                        }else{
2720
                                        ?>
2721
                                        props.setAttributes({content: env});
2722
										is_fetching = false;
2723
										prev_attributes[props.clientId] = props.attributes;
2724
                                        <?php
2725
                                        }
2726
                                        ?>
2727
2728
2729
										// if AUI is active call the js init function
2730
										if (typeof aui_init === "function") {
2731
											aui_init();
2732
										}
2733
									});
2734
2735
2736
								}
2737
2738
2739
								return props.attributes.content;
2740
2741
							}
2742
2743
                            <?php
2744
                            if(!empty($this->options['block-edit-js'])) {
2745
                                echo  $this->options['block-edit-js'] ; // strings have to be in single quotes, may cause issues
2746
                            }
2747
2748
2749
2750
                            ?>
2751
2752
2753
2754
							return [
2755
2756
								el(wp.blockEditor.BlockControls, {key: 'controls'},
2757
2758
									<?php if($show_alignment){?>
2759
									el(
2760
										wp.blockEditor.AlignmentToolbar,
2761
										{
2762
											value: props.attributes.alignment,
2763
											onChange: function (alignment) {
2764
												props.setAttributes({alignment: alignment})
2765
											}
2766
										}
2767
									)
2768
									<?php }?>
2769
2770
								),
2771
2772
								el(wp.blockEditor.InspectorControls, {key: 'inspector'},
2773
2774
									<?php
2775
2776
									if(! empty( $this->arguments )){
2777
2778
									if ( $show_advanced ) {
2779
									?>
2780
									el('div', {
2781
											style: {'padding-left': '16px','padding-right': '16px'}
2782
										},
2783
										el(
2784
											wp.components.ToggleControl,
2785
											{
2786
												label: 'Show Advanced Settings?',
2787
												checked: props.attributes.show_advanced,
2788
												onChange: function (show_advanced) {
2789
													props.setAttributes({show_advanced: !props.attributes.show_advanced})
2790
												}
2791
											}
2792
										)
2793
									)
2794
									,
2795
									<?php
2796
2797
									}
2798
2799
									$arguments = $this->group_arguments( $this->arguments );
2800
									$block_group_tabs = ! empty( $this->options['block_group_tabs'] ) ? $this->group_block_tabs( $this->options['block_group_tabs'], $arguments ) : array();
2801
2802
									// Do we have sections?
2803
									$has_sections = $arguments == $this->arguments ? false : true;
2804
2805
2806
									if($has_sections){
2807
									$panel_count = 0;
2808
									$open_tab = '';
2809
2810
									$open_tab_groups = array();
2811
									$used_tabs = array();
2812
2813
									foreach ( $arguments as $key => $args ) {
2814
										$close_tab = false;
2815
										$close_tabs = false;
2816
2817
										 if ( ! empty( $block_group_tabs ) ) {
2818
											foreach ( $block_group_tabs as $tab_name => $tab_args ) {
2819
												if ( in_array( $key, $tab_args['groups'] ) ) {
2820
													$open_tab_groups[] = $key;
2821
2822
													if ( $open_tab != $tab_name ) {
2823
														$tab_args['tab']['tabs_open'] = $open_tab == '' ? true : false;
2824
														$tab_args['tab']['open'] = true;
2825
2826
														$this->block_tab_start( '', $tab_args );
2827
														$open_tab = $tab_name;
2828
														$used_tabs[] = $tab_name;
2829
													}
2830
2831
													if ( $open_tab_groups == $tab_args['groups'] ) {
2832
														$close_tab = true;
2833
														$open_tab_groups = array();
2834
2835
														if ( $used_tabs == array_keys( $block_group_tabs ) ) {
2836
															$close_tabs = true;
2837
														}
2838
													}
2839
												}
2840
											}
2841
										}
2842
										?>
2843
										el(wp.components.PanelBody, {
2844
												title: '<?php esc_attr_e( $key ); ?>',
2845
												initialOpen: <?php if ( $panel_count ) {
2846
												echo "false";
2847
											} else {
2848
												echo "true";
2849
											}?>
2850
											},
2851
											<?php
2852
											foreach ( $args as $k => $a ) {
2853
												$this->block_tab_start( $k, $a );
2854
												$this->block_row_start( $k, $a );
2855
												$this->build_block_arguments( $k, $a );
2856
												$this->block_row_end( $k, $a );
2857
												$this->block_tab_end( $k, $a );
2858
											}
2859
											?>
2860
										),
2861
										<?php
2862
										$panel_count ++;
2863
2864
										if($close_tab || $close_tabs){
2865
											$tab_args = array(
2866
												'tab'	=> array(
2867
													'tabs_close' => $close_tabs,
2868
												'close' => true,
2869
												)
2870
2871
											);
2872
											$this->block_tab_end( '', $tab_args );
2873
//											echo '###close'; print_r($tab_args);
2874
											$panel_count = 0;
2875
										}
2876
//
2877
2878
									}
2879
									}else {
2880
									?>
2881
									el(wp.components.PanelBody, {
2882
											title: '<?php esc_attr_e( "Settings" ); ?>',
2883
											initialOpen: true
2884
										},
2885
										<?php
2886
										foreach ( $this->arguments as $key => $args ) {
2887
											$this->block_row_start( $key, $args );
2888
											$this->build_block_arguments( $key, $args );
2889
											$this->block_row_end( $key, $args );
2890
										}
2891
										?>
2892
									),
2893
									<?php
2894
									}
2895
2896
									}
2897
									?>
2898
2899
								),
2900
2901
								<?php
2902
								// If the user sets block-output array then build it
2903
								if ( ! empty( $this->options['block-output'] ) ) {
2904
								$this->block_element( $this->options['block-output'] );
2905
							}elseif(!empty($this->options['block-edit-return'])){
2906
                                   echo $this->options['block-edit-return'];
2907
							}else{
2908
								// if no block-output is set then we try and get the shortcode html output via ajax.
2909
								$block_edit_wrap_tag = !empty($this->options['block_edit_wrap_tag']) ? esc_attr($this->options['block_edit_wrap_tag']) : 'div';
2910
								?>
2911
								el('<?php echo esc_attr($block_edit_wrap_tag); ?>', wp.blockEditor.useBlockProps({
2912
									dangerouslySetInnerHTML: {__html: onChangeContent()},
2913
									className: props.className,
2914
									style: {'minHeight': '30px'}
2915
								}))
2916
								<?php
2917
								}
2918
								?>
2919
							]; // end return
2920
2921
							<?php
2922
                            } // end block-edit-raw else
2923
                            ?>
2924
						},
2925
2926
						// The "save" property must be specified and must be a valid function.
2927
						save: function (props) {
2928
2929
							var attr = props.attributes;
2930
							var align = '';
2931
2932
							// build the shortcode.
2933
							var content = "[<?php echo $this->options['base_id'];?>";
2934
							$html = '';
2935
							<?php
2936
2937
							if(! empty( $this->arguments )){
2938
2939
							foreach($this->arguments as $key => $args){
2940
                               // if($args['type']=='tabs'){continue;}
2941
							?>
2942
							if (attr.hasOwnProperty("<?php echo esc_attr( $key );?>")) {
2943
								if ('<?php echo esc_attr( $key );?>' == 'html') {
2944
									$html = attr.<?php echo esc_attr( $key );?>;
2945
								} else if ('<?php echo esc_attr( $args['type'] );?>' == 'image_xy') {
2946
									content += " <?php echo esc_attr( $key );?>='{x:" + attr.<?php echo esc_attr( $key );?>.x + ",y:"+attr.<?php echo esc_attr( $key );?>.y +"}' ";
2947
								} else {
2948
									content += " <?php echo esc_attr( $key );?>='" + attr.<?php echo esc_attr( $key );?>.toString().replace('\'','&#39;') + "' ";
2949
								}
2950
							}
2951
							<?php
2952
							}
2953
							}
2954
2955
							?>
2956
							content += "]";
2957
2958
                            <?php
2959
//                            if(!empty($this->options['nested-block'])){
2960
//                                ?>
2961
//                                $html = 'el( InnerBlocks.Content )';
2962
//                                <?php
2963
//                            }
2964
                            ?>
2965
							// if has html element
2966
							if ($html) {
2967
								content += $html + "[/<?php echo $this->options['base_id'];?>]";
2968
							}
2969
2970
							// @todo should we add inline style here or just css classes?
2971
							if (attr.alignment) {
2972
								if (attr.alignment == 'left') {
2973
									align = 'alignleft';
2974
								}
2975
								if (attr.alignment == 'center') {
2976
									align = 'aligncenter';
2977
								}
2978
								if (attr.alignment == 'right') {
2979
									align = 'alignright';
2980
								}
2981
							}
2982
2983
							<?php
2984
//							if(!empty($this->options['nested-block'])){
2985
//                                ?x>
2986
//                              return el(
2987
//                                    'div',
2988
//                                    { className: props.className,
2989
//                                        style: {'minHeight': '300px','position':'relative','overflow':'hidden','backgroundImage': 'url(https://s.w.org/images/core/5.5/don-quixote-06.jpg)'}
2990
//                                    },
2991
//                                    el( InnerBlocks.Content ),
2992
//                                    el('div', {dangerouslySetInnerHTML: {__html: content}, className: align})
2993
//                                );
2994
//                                <x?php
2995
//							}else
2996
2997
                            if(!empty($this->options['block-output'])){
2998
//                               echo "return";
2999
//                               $this->block_element( $this->options['block-output'], true );
3000
//                               echo ";";
3001
3002
                               ?>
3003
                              return el(
3004
                                   '',
3005
                                   {},
3006
                                   el('', {dangerouslySetInnerHTML: {__html: content}}),
3007
                                   <?php $this->block_element( $this->options['block-output'], true ); ?>
3008
                                   el('', {dangerouslySetInnerHTML: {__html: "[/<?php echo $this->options['base_id'];?>]"}})
3009
                               );
3010
                                <?php
3011
3012
							}elseif(!empty($this->options['block-save-return'])){
3013
                                   echo 'return ' . $this->options['block-save-return'];
3014
							}elseif(!empty($this->options['nested-block'])){
3015
                                ?>
3016
                              return el(
3017
                                   '',
3018
                                   {},
3019
                                   el('', {dangerouslySetInnerHTML: {__html: content+"\n"}}),
3020
                                   InnerBlocks.Content ? el( InnerBlocks.Content ) : '', // @todo i think we need a comma here
3021
                                   el('', {dangerouslySetInnerHTML: {__html: "[/<?php echo $this->options['base_id'];?>]"}})
3022
                               );
3023
                                <?php
3024
							}elseif(!empty( $this->options['block-save-return'] ) ){
3025
                                echo "return ". $this->options['block-edit-return'].";";
3026
							}elseif(isset( $this->options['block-wrap'] ) && $this->options['block-wrap'] == ''){
3027
							?>
3028
							return content;
3029
							<?php
3030
							}else{
3031
							?>
3032
							var block_wrap = 'div';
3033
							if (attr.hasOwnProperty("block_wrap")) {
3034
								block_wrap = attr.block_wrap;
3035
							}
3036
							return el(block_wrap, wp.blockEditor.useBlockProps.save( {dangerouslySetInnerHTML: {__html: content}, className: align} ));
3037
							<?php
3038
							}
3039
							?>
3040
3041
3042
						}
3043
					});
3044
				})(
3045
                    window.wp.blocks,
3046
    window.wp.element,
3047
    window.wp.blockEditor
3048
				);
3049
3050
                });
3051
			</script>
3052
			<?php
3053
			$output = ob_get_clean();
3054
3055
			/*
3056
			 * We only add the <script> tags for code highlighting, so we strip them from the output.
3057
			 */
3058
3059
			return str_replace( array(
3060
				'<script>',
3061
				'</script>'
3062
			), '', $output );
3063
		}
3064
3065
3066
3067
		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

3067
		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...
3068
3069
			// check for row
3070
			if(!empty($args['row'])){
3071
3072
				if(!empty($args['row']['open'])){
3073
3074
				// element require
3075
				$element_require = ! empty( $args['element_require'] ) ? $this->block_props_replace( $args['element_require'], true ) . " && " : "";
3076
                $device_type = ! empty( $args['device_type'] ) ? esc_attr($args['device_type']) : '';
3077
                $device_type_require = ! empty( $args['device_type'] ) ? " deviceType == '" . esc_attr($device_type) . "' && " : '';
3078
                $device_type_icon = '';
3079
                if($device_type=='Desktop'){
3080
                    $device_type_icon = '<span class="dashicons dashicons-desktop" style="font-size: 18px;" onclick="sd_show_view_options(this);"></span>';
3081
                }elseif($device_type=='Tablet'){
3082
                    $device_type_icon = '<span class="dashicons dashicons-tablet" style="font-size: 18px;" onclick="sd_show_view_options(this);"></span>';
3083
                }elseif($device_type=='Mobile'){
3084
                    $device_type_icon = '<span class="dashicons dashicons-smartphone" style="font-size: 18px;" onclick="sd_show_view_options(this);"></span>';
3085
                }
3086
				echo $element_require;
3087
                echo $device_type_require;
3088
3089
					if(false){?><script><?php }?>
3090
						el('div', {
3091
								className: 'bsui components-base-control',
3092
							},
3093
							<?php if(!empty($args['row']['title'])){ ?>
3094
							el('label', {
3095
									className: 'components-base-control__label position-relative',
3096
									style: {width:"100%"}
3097
								},
3098
								el('span',{dangerouslySetInnerHTML: {__html: '<?php echo addslashes( $args['row']['title'] ) ?>'}}),
3099
								<?php if($device_type_icon){ ?>
3100
                                    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)"}})
3101
								<?php
3102
                                }
3103
                                ?>
3104
3105
3106
							),
3107
							<?php }?>
3108
							<?php if(!empty($args['row']['desc'])){ ?>
3109
							el('p', {
3110
									className: 'components-base-control__help mb-0',
3111
								},
3112
								'<?php echo addslashes( $args['row']['desc'] ); ?>'
3113
							),
3114
							<?php }?>
3115
							el(
3116
								'div',
3117
								{
3118
									className: 'row mb-n2 <?php if(!empty($args['row']['class'])){ echo esc_attr($args['row']['class']);} ?>',
3119
								},
3120
								el(
3121
									'div',
3122
									{
3123
										className: 'col pr-2 pe-2',
3124
									},
3125
3126
					<?php
3127
					if(false){?></script><?php }
3128
				}elseif(!empty($args['row']['close'])){
3129
					if(false){?><script><?php }?>
3130
						el(
3131
							'div',
3132
							{
3133
								className: 'col pl-0 ps-0',
3134
							},
3135
					<?php
3136
					if(false){?></script><?php }
3137
				}else{
3138
					if(false){?><script><?php }?>
3139
						el(
3140
							'div',
3141
							{
3142
								className: 'col pl-0 ps-0 pr-2 pe-2',
3143
							},
3144
					<?php
3145
					if(false){?></script><?php }
3146
				}
3147
3148
			}
3149
3150
		}
3151
3152
		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

3152
		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...
3153
3154
			if(!empty($args['row'])){
3155
				// maybe close
3156
				if(!empty($args['row']['close'])){
3157
					echo "))";
3158
				}
3159
3160
				echo "),";
3161
			}
3162
		}
3163
3164
		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

3164
		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...
3165
3166
			// check for row
3167
			if(!empty($args['tab'])){
3168
3169
				if(!empty($args['tab']['tabs_open'])){
3170
3171
					if(false){?><script><?php }?>
3172
3173
el('div',{className: 'bsui'},
3174
3175
						el('hr', {className: 'm-0'}), el(
3176
									wp.components.TabPanel,
3177
									{
3178
                                        activeClass: 'is-active',
3179
                                        className: 'btn-groupx',
3180
                                        initialTabName: '<?php echo addslashes( esc_attr( $args['tab']['key']) ); ?>',
3181
										tabs: [
3182
3183
					<?php
3184
					if(false){?></script><?php }
3185
				}
3186
3187
				if(!empty($args['tab']['open'])){
3188
3189
					if(false){?><script><?php }?>
3190
							{
3191
												name: '<?php echo addslashes( esc_attr( $args['tab']['key']) ); ?>',
3192
												title: el('div', {dangerouslySetInnerHTML: {__html: '<?php echo addslashes( esc_attr( $args['tab']['title']) ); ?>'}}),
3193
												className: '<?php echo addslashes( esc_attr( $args['tab']['class']) ); ?>',
3194
												content: el('div',{}, <?php if(!empty($args['tab']['desc'])){ ?>el('p', {
3195
									className: 'components-base-control__help mb-0',
3196
									dangerouslySetInnerHTML: {__html:'<?php echo addslashes( $args['tab']['desc'] ); ?>'}
3197
								}),<?php }
3198
					if(false){?></script><?php }
3199
				}
3200
3201
			}
3202
3203
		}
3204
3205
		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

3205
		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...
3206
3207
			if(!empty($args['tab'])){
3208
				// maybe close
3209
				if(!empty($args['tab']['close'])){
3210
					echo ")}, /* tab close */";
3211
				}
3212
3213
				if(!empty($args['tab']['tabs_close'])){
3214
					if(false){?><script><?php }?>
3215
						]}, ( tab ) => {
3216
								return tab.content;
3217
							}
3218
						)), /* tabs close */
3219
					<?php if(false){ ?></script><?php }
3220
				}
3221
			}
3222
		}
3223
3224
		public function build_block_arguments( $key, $args ) {
3225
			$custom_attributes = ! empty( $args['custom_attributes'] ) ? $this->array_to_attributes( $args['custom_attributes'] ) : '';
3226
			$options           = '';
3227
			$extra             = '';
3228
			$require           = '';
0 ignored issues
show
Unused Code introduced by
The assignment to $require is dead and can be removed.
Loading history...
3229
            $inside_elements   = '';
3230
			$after_elements	   = '';
3231
3232
			// `content` is a protected and special argument
3233
			if ( $key == 'content' ) {
3234
				return;
3235
			}
3236
3237
            $device_type = ! empty( $args['device_type'] ) ? esc_attr($args['device_type']) : '';
3238
            $device_type_require = ! empty( $args['device_type'] ) ? " deviceType == '" . esc_attr($device_type) . "' && " : '';
3239
            $device_type_icon = '';
3240
            if($device_type=='Desktop'){
3241
                $device_type_icon = '<span class="dashicons dashicons-desktop" style="font-size: 18px;" onclick="sd_show_view_options(this);"></span>';
3242
            }elseif($device_type=='Tablet'){
3243
                $device_type_icon = '<span class="dashicons dashicons-tablet" style="font-size: 18px;" onclick="sd_show_view_options(this);"></span>';
3244
            }elseif($device_type=='Mobile'){
3245
                $device_type_icon = '<span class="dashicons dashicons-smartphone" style="font-size: 18px;" onclick="sd_show_view_options(this);"></span>';
3246
            }
3247
3248
			// icon
3249
			$icon = '';
3250
			if( !empty( $args['icon'] ) ){
3251
				$icon .= "el('div', {";
3252
									$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

3252
									$icon .= "dangerouslySetInnerHTML: {__html: '".self::/** @scrutinizer ignore-call */ get_widget_icon( esc_attr($args['icon']))."'},";
Loading history...
3253
									$icon .= "className: 'text-center',";
3254
									$icon .= "title: '".addslashes( $args['title'] )."',";
3255
								$icon .= "}),";
3256
3257
				// blank title as its added to the icon.
3258
				$args['title'] = '';
3259
			}
3260
3261
			// require advanced
3262
			$require_advanced = ! empty( $args['advanced'] ) ? "props.attributes.show_advanced && " : "";
3263
3264
			// element require
3265
			$element_require = ! empty( $args['element_require'] ) ? $this->block_props_replace( $args['element_require'], true ) . " && " : "";
3266
3267
3268
			$onchange  = "props.setAttributes({ $key: $key } )";
3269
			$onchangecomplete  = "";
3270
			$value     = "props.attributes.$key";
3271
			$text_type = array( 'text', 'password', 'number', 'email', 'tel', 'url', 'colorx','range' );
3272
			if ( in_array( $args['type'], $text_type ) ) {
3273
				$type = 'TextControl';
3274
				// Save numbers as numbers and not strings
3275
				if ( $args['type'] == 'number' ) {
3276
					$onchange = "props.setAttributes({ $key: $key ? Number($key) : '' } )";
3277
				}
3278
			}
3279
//			else if ( $args['type'] == 'popup' ) {
3280
//				$type = 'TextControl';
3281
//				$args['type'] == 'text';
3282
//				$after_elements .= "el( wp.components.Button, {
3283
//                          className: 'components-button components-circular-option-picker__clear is-primary is-smallx',
3284
//                          onClick: function(){
3285
//							  aui_modal('','<input id=\'zzz\' value= />');
3286
//							  const source = document.getElementById('zzz');
3287
//							  source.value = props.attributes.$key;
3288
//							  source.addEventListener('input', function(e){props.setAttributes({ $key: e.target.value });});
3289
//                          }
3290
//                        },
3291
//                        'test'
3292
//                        ),";
3293
//
3294
//				$value     = "props.attributes.$key ? props.attributes.$key : ''";
3295
//			}
3296
			else if ( $args['type'] == 'styleid' ) {
3297
				$type = 'TextControl';
3298
				$args['type'] == 'text';
3299
				// Save numbers as numbers and not strings
3300
				$value     = "props.attributes.$key ? props.attributes.$key : ''";
3301
			}else if ( $args['type'] == 'notice' ) {
3302
3303
				$notice_message = !empty($args['desc']) ? addslashes($args['desc']) : '';
3304
				$notice_status = !empty($args['status']) ? esc_attr($args['status']) : 'info';
3305
3306
				$notice = "el('div',{className:'bsui'},el(wp.components.Notice, {status: '$notice_status',isDismissible: false,className: 'm-0 pr-0 pe-0 mb-3'},el('div',{dangerouslySetInnerHTML: {__html: '$notice_message'}}))),";
3307
				echo $notice_message ? $element_require . $notice : '';
3308
				return;
3309
			}
3310
			/*
3311
			 * https://www.wptricks.com/question/set-current-tab-on-a-gutenberg-tabpanel-component-from-outside-that-component/ es5 layout
3312
						elseif($args['type']=='tabs'){
3313
							?>
3314
								el(
3315
									wp.components.TabPanel,
3316
									{
3317
                                        activeClass: 'active-tab',
3318
                                        initialTabName: deviceType,
3319
										tabs: [
3320
											{
3321
												name: 'Desktop',
3322
												title: el('div', {dangerouslySetInnerHTML: {__html: '<i class="fas fa-desktop"></i>'}}),
3323
												className: 'tab-one' + deviceType == 'Desktop' ? ' active-tab' : '',
3324
												content: el('div', {dangerouslySetInnerHTML: {__html: 'ddd'}})
3325
											},
3326
											{
3327
												name: 'Tablet',
3328
												title: el('div', {dangerouslySetInnerHTML: {__html: '<i class="fas fa-tablet-alt"></i>'}}),
3329
												className: 'tab-two' + deviceType == 'Tablet' ? ' active-tab' : '',
3330
												content: el('div', {dangerouslySetInnerHTML: {__html: 'ttt'}})
3331
											},
3332
											{
3333
												name: 'Mobile',
3334
												title: el('div', {dangerouslySetInnerHTML: {__html: '<i class="fas fa-mobile-alt"></i>'}}),
3335
												className: 'tab-two' + deviceType == 'Mobile' ? ' active-tab' : '',
3336
												content: el('div', {dangerouslySetInnerHTML: {__html: 'mmm'}})
3337
											},
3338
										],
3339
									},
3340
									( tab ) => {
3341
3342
// @todo https://github.com/WordPress/gutenberg/issues/39248
3343
									if(tab.name=='Desktop'){
3344
									wp.data.dispatch('core/edit-post').__experimentalSetPreviewDeviceType('Desktop');
3345
wp.data.select('core/edit-post').__experimentalGetPreviewDeviceType();
3346
									}else if(tab.name=='Tablet'){
3347
									wp.data.dispatch('core/edit-post').__experimentalSetPreviewDeviceType('Tablet');
3348
wp.data.select('core/edit-post').__experimentalGetPreviewDeviceType();
3349
									}else if(tab.name=='Mobile'){
3350
									wp.data.dispatch('core/edit-post').__experimentalSetPreviewDeviceType('Mobile');
3351
wp.data.select('core/edit-post').__experimentalGetPreviewDeviceType();
3352
									}
3353
3354
									return tab.content;
3355
3356
								}
3357
								),
3358
3359
							<?php
3360
							return;
3361
						}
3362
*/
3363
			elseif ( $args['type'] == 'color' ) {
3364
				$type = 'ColorPicker';
3365
				$onchange = "";
3366
				$extra = "color: $value,";
3367
				if(!empty($args['disable_alpha'])){
3368
					$extra .= "disableAlpha: true,";
3369
				}
3370
				$onchangecomplete = "onChangeComplete: function($key) {
3371
				value =  $key.rgb.a && $key.rgb.a < 1 ? \"rgba(\"+$key.rgb.r+\",\"+$key.rgb.g+\",\"+$key.rgb.b+\",\"+$key.rgb.a+\")\" : $key.hex;
3372
                        props.setAttributes({
3373
                            $key: value
3374
                        });
3375
                    },";
3376
			}elseif ( $args['type'] == 'gradient' ) {
3377
				$type = 'GradientPicker';
3378
3379
			}elseif ( $args['type'] == 'image' ) {
3380
//                print_r($args);
3381
3382
                $img_preview = isset($args['focalpoint']) && !$args['focalpoint'] ? " props.attributes.$key && el('img', { src: props.attributes.$key,style: {maxWidth:'100%',background: '#ccc'}})," : " ( props.attributes.$key ||  props.attributes.{$key}_use_featured ) && el(wp.components.FocalPointPicker,{
3383
                            url:  props.attributes.{$key}_use_featured === true ? '".$this->get_url()."icons/placeholder.png'  : props.attributes.$key,
3384
                            value: props.attributes.{$key}_xy.x !== undefined && props.attributes.{$key}_xy.x >= 0 ? props.attributes.{$key}_xy  : {x: 0.5,y: 0.5,},
3385
//                            value: props.attributes.{$key}_xy,
3386
                            onChange: function(focalPoint){
3387
                            console.log(props.attributes);
3388
                                              return props.setAttributes({
3389
                                                  {$key}_xy: focalPoint
3390
                                                });
3391
                                    },
3392
                                    // @todo for some reason this does not work as expected.
3393
//                         onDrag: function(focalPointTemp){
3394
//                                  return props.setAttributes({
3395
//                                      {$key}_xy: focalPointTemp
3396
//                                    });
3397
//                        }
3398
3399
3400
                        }), ";
3401
3402
3403
                $value = '""';
3404
				$type = 'MediaUpload';
3405
                $extra .= "onSelect: function(media){
3406
                      return props.setAttributes({
3407
                          $key: media.url,
3408
                          {$key}_id: media.id
3409
                        });
3410
                      },";
3411
                   $extra .= "type: 'image',";
3412
                   $extra .= "render: function (obj) {
3413
                        return el( 'div',{},
3414
                        ( !props.attributes.$key && !props.attributes.{$key}_use_featured ) && el( wp.components.Button, {
3415
                          className: 'components-button components-circular-option-picker__clear is-primary is-smallx',
3416
                          onClick: obj.open
3417
                        },
3418
                        'Upload Image'
3419
                        ),
3420
                       $img_preview
3421
                        props.attributes.$key && el( wp.components.Button, {
3422
                                      className: 'components-button components-circular-option-picker__clear is-secondary is-small',
3423
                                      style: {margin:'8px 0',display: 'block'},
3424
                                      onClick: function(){
3425
                                              return props.setAttributes({
3426
                                                  $key: '',
3427
                                                  {$key}_id: ''
3428
                                                });
3429
                                    }
3430
                                    },
3431
                                    props.attributes.$key? 'Clear' : ''
3432
                            )
3433
                       )
3434
3435
3436
3437
                      }";
3438
                $onchange = "";
3439
3440
                //$inside_elements = ",el('div',{},'file upload')";
3441
			}elseif ( $args['type'] == 'images' ) {
3442
				//                print_r($args);
3443
3444
                $img_preview = "props.attributes.$key && (function() {
3445
3446
                        let uploads = JSON.parse('['+props.attributes.$key+']');
3447
						let images = [];
3448
                      uploads.map((upload, index) => (
3449
3450
							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',{
3451
							className: 'fas fa-times-circle text-danger position-absolute  ml-n2 mt-n1 bg-white rounded-circle c-pointer',
3452
							onClick: function(){
3453
							    aui_confirm('".esc_attr__('Are you sure?')."', '".esc_attr__('Delete')."', '".esc_attr__('Cancel')."', true).then(function(confirmed) {
3454
if (confirmed) {
3455
											let new_uploads = JSON.parse('['+props.attributes.$key+']');
3456
											new_uploads.splice(index, 1); //remove
3457
                                              return props.setAttributes({
3458
                                                  {$key}: JSON.stringify( new_uploads ).replace('[','').replace(']',''),
3459
                                                });
3460
                                                }
3461
                                           });
3462
                                    }},'') ) )
3463
						));
3464
3465
3466
						return images;
3467
})(),";
3468
3469
3470
                $value = '""';
3471
				$type = 'MediaUpload';
3472
                $extra .= "onSelect: function(media){
3473
3474
                let slim_images = props.attributes.$key ? JSON.parse('['+props.attributes.$key+']') : [];
3475
				if(media.length){
3476
						for (var i=0; i < media.length; i++) {
3477
							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});
3478
						}
3479
				}
3480
3481
                      return props.setAttributes({
3482
                          $key: JSON.stringify(slim_images).replace('[','').replace(']',''),
3483
                        });
3484
                      },";
3485
                   $extra .= "type: 'image',";
3486
                   $extra .= "multiple: true,";
3487
                   $extra .= "render: function (obj) {
3488
3489
                   // init the sort
3490
				enableDragSort('sd-sortable');
3491
                        return el( 'div',{},
3492
                        el( wp.components.Button, {
3493
                          className: 'components-button components-circular-option-picker__clear is-primary is-smallx',
3494
                          onClick: obj.open
3495
                        },
3496
                        'Upload Images'
3497
                        ),
3498
3499
3500
						el('div',{className: 'row row-cols-3 px-2 sd-sortable','data-field':'$key'},
3501
3502
                       $img_preview
3503
3504
                       ),
3505
                        props.attributes.$key && el( wp.components.Button, {
3506
                                      className: 'components-button components-circular-option-picker__clear is-secondary is-small',
3507
                                      style: {margin:'8px 0'},
3508
                                      onClick: function(){
3509
                                              return props.setAttributes({
3510
                                                  $key: '',
3511
                                                });
3512
                                    }
3513
                                    },
3514
                                    props.attributes.$key? 'Clear All' : ''
3515
                            )
3516
                       )
3517
3518
3519
3520
3521
3522
                      }";
3523
                $onchange = "";
3524
3525
                //$inside_elements = ",el('div',{},'file upload')";
3526
			}
3527
			elseif ( $args['type'] == 'checkbox' ) {
3528
				$type = 'CheckboxControl';
3529
				$extra .= "checked: props.attributes.$key,";
3530
				$onchange = "props.setAttributes({ $key: ! props.attributes.$key } )";
3531
			} elseif ( $args['type'] == 'textarea' ) {
3532
				$type = 'TextareaControl';
3533
3534
			} elseif ( $args['type'] == 'select' || $args['type'] == 'multiselect' ) {
3535
				$type = 'SelectControl';
3536
3537
				if($args['name'] == 'category' && !empty($args['post_type_linked'])){
3538
					$options .= "options: taxonomies_".str_replace("-","_", $this->id).",";
3539
				}elseif($args['name'] == 'sort_by' && !empty($args['post_type_linked'])){
3540
					$options .= "options: sort_by_".str_replace("-","_", $this->id).",";
3541
				}else {
3542
3543
					if ( ! empty( $args['options'] ) ) {
3544
						$options .= "options: [";
3545
						foreach ( $args['options'] as $option_val => $option_label ) {
3546
							$options .= "{ value: '" . esc_attr( $option_val ) . "', label: '" . addslashes( $option_label ) . "' },";
3547
						}
3548
						$options .= "],";
3549
					}
3550
				}
3551
				if ( isset( $args['multiple'] ) && $args['multiple'] ) { //@todo multiselect does not work at the moment: https://github.com/WordPress/gutenberg/issues/5550
3552
					$extra .= ' multiple:true,style:{height:"auto",paddingRight:"8px","overflow-y":"auto"}, ';
3553
				}
3554
3555
				if($args['type'] == 'multiselect' ||  ( isset( $args['multiple'] ) && $args['multiple'] ) ){
3556
					$after_elements	 .= "props.attributes.$key && el( wp.components.Button, {
3557
                                      className: 'components-button components-circular-option-picker__clear is-secondary is-small',
3558
                                      style: {margin:'-8px 0 8px 0',display: 'block'},
3559
                                      onClick: function(){
3560
                                              return props.setAttributes({
3561
                                                  $key: '',
3562
                                                });
3563
                                    }
3564
                                    },
3565
                                    'Clear'
3566
                            ),";
3567
				}
3568
			} elseif ( $args['type'] == 'tagselect' ) {
3569
//				$type = 'FormTokenField';
3570
//
3571
//				if ( ! empty( $args['options'] ) ) {
3572
//						$options .= "suggestions: [";
3573
//						foreach ( $args['options'] as $option_val => $option_label ) {
3574
//							$options .= "{ value: '" . esc_attr( $option_val ) . "', title: '" . addslashes( $option_label ) . "' },";
3575
////							$options .= "'" . esc_attr( $option_val ) . "':'" . addslashes( $option_label ) . "',";
3576
//						}
3577
//						$options .= "],";
3578
//				}
3579
//
3580
//				$onchangex  = "{ ( selectedItems ) => {
3581
//						// Build array of selected posts.
3582
//						let selectedPostsArray = [];
3583
//						selectedPosts.map(
3584
//							( postName ) => {
3585
//								const matchingPost = posts.find( ( post ) => {
3586
//									return post.title.raw === postName;
3587
//
3588
//								} );
3589
//								if ( matchingPost !== undefined ) {
3590
//									selectedPostsArray.push( matchingPost.id );
3591
//								}
3592
//							}
3593
//						)
3594
//
3595
//						setAttributes( { selectedPosts: selectedPostsArray } );
3596
//					} } ";
3597
//				$onchange  = '';// "props.setAttributes({ $key: [ props.attributes.$key ] } )";
3598
//
3599
////				$options  = "";
3600
//				$value     = "[]";
3601
//				$extra .= ' __experimentalExpandOnFocus: true,';
3602
3603
			} elseif ( $args['type'] == 'alignment' ) {
3604
				$type = 'AlignmentToolbar'; // @todo this does not seem to work but cant find a example
3605
			}elseif ( $args['type'] == 'margins' ) {
3606
3607
			} else {
3608
				return;// if we have not implemented the control then don't break the JS.
3609
			}
3610
3611
3612
3613
			// color input does not show the labels so we add them
3614
			if($args['type']=='color'){
3615
				// add show only if advanced
3616
				echo $require_advanced;
3617
				// add setting require if defined
3618
				echo $element_require;
3619
				echo "el('div', {style: {'marginBottom': '8px'}}, '".addslashes( $args['title'] )."'),";
3620
			}
3621
3622
			// add show only if advanced
3623
			echo $require_advanced;
3624
			// add setting require if defined
3625
			echo $element_require;
3626
            echo $device_type_require;
3627
3628
			// icon
3629
			echo $icon;
3630
			?>
3631
			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...
3632
			label: <?php
3633
			if(empty($args['title'])){
3634
                echo "''";
3635
			}elseif(empty($args['row']) && !empty($args['device_type'])){
3636
                ?>el('label', {
3637
									className: 'components-base-control__label',
3638
									style: {width:"100%"}
3639
								},
3640
								el('span',{dangerouslySetInnerHTML: {__html: '<?php echo addslashes( $args['title'] ) ?>'}}),
3641
								<?php if($device_type_icon){ ?>
3642
                                    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)"}})
3643
								<?php
3644
                                }
3645
                                ?>
3646
3647
3648
							)<?php
3649
3650
			}else{
3651
                 ?>'<?php echo addslashes( $args['title'] ); ?>'<?php
3652
3653
			}
3654
3655
			?>,
3656
			help: <?php if ( isset( $args['desc'] ) ) {
3657
				echo "el('span',{dangerouslySetInnerHTML: {__html: '".wp_kses_post( addslashes($args['desc']) )."'}})";
3658
			}else{ echo "''"; } ?>,
3659
			value: <?php echo $value; ?>,
3660
			<?php if ( $type == 'TextControl' && $args['type'] != 'text' ) {
3661
				echo "type: '" . addslashes( $args['type'] ) . "',";
3662
			} ?>
3663
			<?php if ( ! empty( $args['placeholder'] ) ) {
3664
				echo "placeholder: '" . addslashes( $args['placeholder'] ) . "',";
3665
			} ?>
3666
			<?php echo $options; ?>
3667
			<?php echo $extra; ?>
3668
			<?php echo $custom_attributes; ?>
3669
			<?php echo $onchangecomplete;
3670
            if($onchange){
3671
            ?>
3672
			onChange: function ( <?php echo $key; ?> ) {
3673
			<?php echo $onchange; ?>
3674
			}
3675
			<?php }?>
3676
			} <?php echo $inside_elements; ?> ),
3677
			<?php
3678
			echo $after_elements;
3679
3680
		}
3681
3682
		/**
3683
		 * Convert an array of attributes to block string.
3684
		 *
3685
		 * @param $custom_attributes
3686
		 *
3687
		 * @return string
3688
		 *@todo there is prob a faster way to do this, also we could add some validation here.
3689
		 *
3690
		 */
3691
		public function array_to_attributes( $custom_attributes, $html = false ) {
3692
			$attributes = '';
3693
			if ( ! empty( $custom_attributes ) ) {
3694
3695
				foreach ( $custom_attributes as $key => $val ) {
3696
					if(is_array($val)){
3697
						$attributes .= $key.': {'.$this->array_to_attributes( $val, $html ).'},';
3698
					}else{
3699
						$attributes .= $html ?  " $key='$val' " : "'$key': '$val',";
3700
					}
3701
				}
3702
3703
			}
3704
3705
			return $attributes;
3706
		}
3707
3708
3709
3710
		/**
3711
		 * A self looping function to create the output for JS block elements.
3712
		 *
3713
		 * This is what is output in the WP Editor visual view.
3714
		 *
3715
		 * @param $args
3716
		 */
3717
		public function block_element( $args, $save = false ) {
3718
3719
3720
			if ( ! empty( $args ) ) {
3721
				foreach ( $args as $element => $new_args ) {
3722
3723
					if ( is_array( $new_args ) ) { // its an element
3724
3725
3726
						if ( isset( $new_args['element'] ) ) {
3727
3728
							if ( isset( $new_args['element_require'] ) ) {
3729
								echo str_replace( array(
3730
										"'+",
3731
										"+'"
3732
									), '', $this->block_props_replace( $new_args['element_require'] ) ) . " &&  ";
3733
								unset( $new_args['element_require'] );
3734
							}
3735
3736
                            if($new_args['element']=='InnerBlocks'){
3737
                                echo "\n el( InnerBlocks, {";
3738
                            }elseif($new_args['element']=='innerBlocksProps'){
3739
                                $element = isset($new_args['inner_element']) ? esc_attr($new_args['inner_element']) : 'div';
3740
                              //  echo "\n el( 'section', wp.blockEditor.useInnerBlocksProps( blockProps, {";
3741
//                                echo $save ? "\n el( '$element', wp.blockEditor.useInnerBlocksProps.save( " : "\n el( '$element', wp.blockEditor.useInnerBlocksProps( ";
3742
                                echo $save ? "\n el( '$element', wp.blockEditor.useInnerBlocksProps.save( " : "\n el( '$element', wp.blockEditor.useInnerBlocksProps( ";
3743
                                echo $save ? "wp.blockEditor.useBlockProps.save( {" : "wp.blockEditor.useBlockProps( {";
3744
                                echo !empty($new_args['blockProps']) ? $this->block_element( $new_args['blockProps'],$save ) : '';
3745
3746
                                echo "} ), {";
3747
                                echo !empty($new_args['innerBlocksProps']) && !$save ? $this->block_element( $new_args['innerBlocksProps'],$save ) : '';
3748
                            //    echo '###';
3749
3750
                              //  echo '###';
3751
                            }elseif($new_args['element']=='BlocksProps'){
3752
3753
								if ( isset($new_args['if_inner_element']) ) {
3754
									$element = $new_args['if_inner_element'];
3755
								}else {
3756
									$element = isset($new_args['inner_element']) ? "'".esc_attr($new_args['inner_element'])."'" : "'div'";
3757
								}
3758
3759
								unset($new_args['inner_element']);
3760
                                echo $save ? "\n el( $element, wp.blockEditor.useBlockProps.save( {" : "\n el( $element, wp.blockEditor.useBlockProps( {";
3761
                                echo !empty($new_args['blockProps']) ? $this->block_element( $new_args['blockProps'],$save ) : '';
3762
3763
3764
                               // echo "} ),";
3765
3766
                            }else{
3767
                                echo "\n el( '" . $new_args['element'] . "', {";
3768
                            }
3769
3770
3771
							// get the attributes
3772
							foreach ( $new_args as $new_key => $new_value ) {
3773
3774
3775
								if ( $new_key == 'element' || $new_key == 'content'|| $new_key == 'if_content' || $new_key == 'element_require' || $new_key == 'element_repeat' || is_array( $new_value ) ) {
3776
									// do nothing
3777
								} else {
3778
									echo $this->block_element( array( $new_key => $new_value ),$save );
3779
								}
3780
							}
3781
3782
							echo $new_args['element']=='BlocksProps' ? '} ),' : "},";// end attributes
3783
3784
							// get the content
3785
							$first_item = 0;
3786
							foreach ( $new_args as $new_key => $new_value ) {
3787
								if ( $new_key === 'content' || $new_key === 'if_content' || is_array( $new_value ) ) {
3788
3789
									if ( $new_key === 'content' ) {
3790
										echo "'" . $this->block_props_replace( wp_slash( $new_value ) ) . "'";
3791
									}else if ( $new_key === 'if_content' ) {
3792
										echo  $this->block_props_replace(  $new_value  );
3793
									}
3794
3795
									if ( is_array( $new_value ) ) {
3796
3797
										if ( isset( $new_value['element_require'] ) ) {
3798
											echo str_replace( array(
3799
													"'+",
3800
													"+'"
3801
												), '', $this->block_props_replace( $new_value['element_require'] ) ) . " &&  ";
3802
											unset( $new_value['element_require'] );
3803
										}
3804
3805
										if ( isset( $new_value['element_repeat'] ) ) {
3806
											$x = 1;
3807
											while ( $x <= absint( $new_value['element_repeat'] ) ) {
3808
												$this->block_element( array( '' => $new_value ),$save );
3809
												$x ++;
3810
											}
3811
										} else {
3812
											$this->block_element( array( '' => $new_value ),$save );
3813
										}
3814
									}
3815
									$first_item ++;
3816
								}
3817
							}
3818
3819
                            if($new_args['element']=='innerBlocksProps' || $new_args['element']=='xBlocksProps'){
3820
                                echo "))";// end content
3821
                            }else{
3822
                                echo ")";// end content
3823
                            }
3824
3825
3826
							echo ", \n";
3827
3828
						}
3829
					} else {
3830
3831
						if ( substr( $element, 0, 3 ) === "if_" ) {
3832
							$extra = '';
0 ignored issues
show
Unused Code introduced by
The assignment to $extra is dead and can be removed.
Loading history...
3833
							if( strpos($new_args, '[%WrapClass%]') !== false ){
3834
								$new_args = str_replace('[%WrapClass%]"','" + sd_build_aui_class(props.attributes)',$new_args);
3835
								$new_args = str_replace('[%WrapClass%]','+ sd_build_aui_class(props.attributes)',$new_args);
3836
							}
3837
							echo str_replace( "if_", "", $element ) . ": " . $this->block_props_replace( $new_args, true ) . ",";
3838
						} elseif ( $element == 'style' &&  strpos($new_args, '[%WrapStyle%]') !== false ) {
3839
                            $new_args = str_replace('[%WrapStyle%]','',$new_args);
3840
                            echo $element . ": {..." . $this->block_props_replace( $new_args ) . " , ...sd_build_aui_styles(props.attributes) },";
3841
//                            echo $element . ": " . $this->block_props_replace( $new_args ) . ",";
3842
						} elseif ( $element == 'style' ) {
3843
							echo $element . ": " . $this->block_props_replace( $new_args ) . ",";
3844
						} elseif ( ( $element == 'class' || $element == 'className'  ) &&  strpos($new_args, '[%WrapClass%]') !== false ) {
3845
                            $new_args = str_replace('[%WrapClass%]','',$new_args);
3846
                            echo $element . ": '" . $this->block_props_replace( $new_args ) . "' + sd_build_aui_class(props.attributes),";
3847
						} elseif ( $element == 'template' && $new_args ) {
3848
							echo $element . ": $new_args,";
3849
						} else {
3850
							echo $element . ": '" . $this->block_props_replace( $new_args ) . "',";
3851
						}
3852
3853
					}
3854
				}
3855
			}
3856
		}
3857
3858
		/**
3859
		 * Replace block attributes placeholders with the proper naming.
3860
		 *
3861
		 * @param $string
3862
		 *
3863
		 * @return mixed
3864
		 */
3865
		public function block_props_replace( $string, $no_wrap = false ) {
3866
3867
			if ( $no_wrap ) {
3868
				$string = str_replace( array( "[%", "%]" ), array( "props.attributes.", "" ), $string );
3869
			} else {
3870
				$string = str_replace( array( "[%", "%]" ), array( "'+props.attributes.", "+'" ), $string );
3871
			}
3872
3873
			return $string;
3874
		}
3875
3876
		/**
3877
		 * Outputs the content of the widget
3878
		 *
3879
		 * @param array $args
3880
		 * @param array $instance
3881
		 */
3882
		public function widget( $args, $instance ) {
3883
3884
			// get the filtered values
3885
			$argument_values = $this->argument_values( $instance );
3886
			$argument_values = $this->string_to_bool( $argument_values );
3887
			$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...
3888
3889
			$no_wrap = false;
3890
			if ( isset( $argument_values['no_wrap'] ) && $argument_values['no_wrap'] ) {
3891
				$no_wrap = true;
3892
			}
3893
3894
			ob_start();
3895
			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...
3896
3897
				$class_original = $this->options['widget_ops']['classname'];
3898
				$class = $this->options['widget_ops']['classname']." sdel-".$this->get_instance_hash();
3899
3900
				// Before widget
3901
				$before_widget = ! empty( $args['before_widget'] ) ? $args['before_widget'] : '';
3902
				$before_widget = $before_widget ? str_replace( $class_original, $class, $before_widget ) : $before_widget;
3903
				$before_widget = apply_filters( 'wp_super_duper_before_widget', $before_widget, $args, $instance, $this );
3904
				$before_widget = apply_filters( 'wp_super_duper_before_widget_' . $this->base_id, $before_widget, $args, $instance, $this );
3905
3906
				// After widget
3907
				$after_widget = ! empty( $args['after_widget'] ) ? $args['after_widget'] : '';
3908
				$after_widget = apply_filters( 'wp_super_duper_after_widget', $after_widget, $args, $instance, $this );
3909
				$after_widget = apply_filters( 'wp_super_duper_after_widget_' . $this->base_id, $after_widget, $args, $instance, $this );
3910
3911
				echo $before_widget;
3912
				// elementor strips the widget wrapping div so we check for and add it back if needed
3913
				if ( $this->is_elementor_widget_output() ) {
3914
					// Filter class & attrs for elementor widget output.
3915
					$class = apply_filters( 'wp_super_duper_div_classname', $class, $args, $this );
3916
					$class = apply_filters( 'wp_super_duper_div_classname_' . $this->base_id, $class, $args, $this );
3917
3918
					$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...
3919
					$attrs = apply_filters( 'wp_super_duper_div_attrs_' . $this->base_id, '', $args, $this );
3920
3921
					echo "<span class='" . esc_attr( $class  ) . "' " . $attrs . ">";
3922
				}
3923
				echo $this->output_title( $args, $instance );
3924
				echo $output;
3925
				if ( $this->is_elementor_widget_output() ) {
3926
					echo "</span>";
3927
				}
3928
				echo $after_widget;
3929
			} elseif ( $this->is_preview() && $output == '' ) {// if preview show a placeholder if empty
3930
				$output = $this->preview_placeholder_text( "{{" . $this->base_id . "}}" );
3931
				echo $output;
3932
			} 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...
3933
				echo $output;
3934
			}
3935
			$output = ob_get_clean();
3936
3937
			$output = apply_filters( 'wp_super_duper_widget_output', $output, $instance, $args, $this );
3938
3939
			echo $output;
3940
		}
3941
3942
		/**
3943
		 * Tests if the current output is inside a elementor container.
3944
		 *
3945
		 * @return bool
3946
		 *@since 1.0.4
3947
		 */
3948
		public function is_elementor_widget_output() {
3949
			$result = false;
3950
			if ( defined( 'ELEMENTOR_VERSION' ) && isset( $this->number ) && $this->number == 'REPLACE_TO_ID' ) {
3951
				$result = true;
3952
			}
3953
3954
			return $result;
3955
		}
3956
3957
		/**
3958
		 * Tests if the current output is inside a elementor preview.
3959
		 *
3960
		 * @return bool
3961
		 *@since 1.0.4
3962
		 */
3963
		public function is_elementor_preview() {
3964
			$result = false;
3965
			if ( isset( $_REQUEST['elementor-preview'] ) || ( is_admin() && isset( $_REQUEST['action'] ) && $_REQUEST['action'] == 'elementor' ) || ( isset( $_REQUEST['action'] ) && $_REQUEST['action'] == 'elementor_ajax' ) ) {
3966
				$result = true;
3967
			}
3968
3969
			return $result;
3970
		}
3971
3972
		/**
3973
		 * Tests if the current output is inside a Divi preview.
3974
		 *
3975
		 * @return bool
3976
		 *@since 1.0.6
3977
		 */
3978
		public function is_divi_preview() {
3979
			$result = false;
3980
			if ( isset( $_REQUEST['et_fb'] ) || isset( $_REQUEST['et_pb_preview'] ) || ( is_admin() && isset( $_REQUEST['action'] ) && $_REQUEST['action'] == 'elementor' ) ) {
3981
				$result = true;
3982
			}
3983
3984
			return $result;
3985
		}
3986
3987
		/**
3988
		 * Tests if the current output is inside a Beaver builder preview.
3989
		 *
3990
		 * @return bool
3991
		 *@since 1.0.6
3992
		 */
3993
		public function is_beaver_preview() {
3994
			$result = false;
3995
			if ( isset( $_REQUEST['fl_builder'] ) ) {
3996
				$result = true;
3997
			}
3998
3999
			return $result;
4000
		}
4001
4002
		/**
4003
		 * Tests if the current output is inside a siteorigin builder preview.
4004
		 *
4005
		 * @return bool
4006
		 *@since 1.0.6
4007
		 */
4008
		public function is_siteorigin_preview() {
4009
			$result = false;
4010
			if ( ! empty( $_REQUEST['siteorigin_panels_live_editor'] ) ) {
4011
				$result = true;
4012
			}
4013
4014
			return $result;
4015
		}
4016
4017
		/**
4018
		 * Tests if the current output is inside a cornerstone builder preview.
4019
		 *
4020
		 * @return bool
4021
		 *@since 1.0.8
4022
		 */
4023
		public function is_cornerstone_preview() {
4024
			$result = false;
4025
			if ( ! empty( $_REQUEST['cornerstone_preview'] ) || basename( $_SERVER['REQUEST_URI'] ) == 'cornerstone-endpoint' ) {
4026
				$result = true;
4027
			}
4028
4029
			return $result;
4030
		}
4031
4032
		/**
4033
		 * Tests if the current output is inside a fusion builder preview.
4034
		 *
4035
		 * @return bool
4036
		 *@since 1.1.0
4037
		 */
4038
		public function is_fusion_preview() {
4039
			$result = false;
4040
			if ( ! empty( $_REQUEST['fb-edit'] ) || ! empty( $_REQUEST['fusion_load_nonce'] ) ) {
4041
				$result = true;
4042
			}
4043
4044
			return $result;
4045
		}
4046
4047
		/**
4048
		 * Tests if the current output is inside a Oxygen builder preview.
4049
		 *
4050
		 * @return bool
4051
		 *@since 1.0.18
4052
		 */
4053
		public function is_oxygen_preview() {
4054
			$result = false;
4055
			if ( ! empty( $_REQUEST['ct_builder'] ) || ( ! empty( $_REQUEST['action'] ) && ( substr( $_REQUEST['action'], 0, 11 ) === "oxy_render_" || substr( $_REQUEST['action'], 0, 10 ) === "ct_render_" ) ) ) {
4056
				$result = true;
4057
			}
4058
4059
			return $result;
4060
		}
4061
4062
		/**
4063
		 * General function to check if we are in a preview situation.
4064
		 *
4065
		 * @return bool
4066
		 *@since 1.0.6
4067
		 */
4068
		public function is_preview() {
4069
			$preview = false;
4070
			if ( $this->is_divi_preview() ) {
4071
				$preview = true;
4072
			} elseif ( $this->is_elementor_preview() ) {
4073
				$preview = true;
4074
			} elseif ( $this->is_beaver_preview() ) {
4075
				$preview = true;
4076
			} elseif ( $this->is_siteorigin_preview() ) {
4077
				$preview = true;
4078
			} elseif ( $this->is_cornerstone_preview() ) {
4079
				$preview = true;
4080
			} elseif ( $this->is_fusion_preview() ) {
4081
				$preview = true;
4082
			} elseif ( $this->is_oxygen_preview() ) {
4083
				$preview = true;
4084
			} elseif( $this->is_block_content_call() ) {
4085
				$preview = true;
4086
			}
4087
4088
			return $preview;
4089
		}
4090
4091
		/**
4092
		 * Output the super title.
4093
		 *
4094
		 * @param $args
4095
		 * @param array $instance
4096
		 *
4097
		 * @return string
4098
		 */
4099
		public function output_title( $args, $instance = array() ) {
4100
			$output = '';
4101
			if ( ! empty( $instance['title'] ) ) {
4102
				/** This filter is documented in wp-includes/widgets/class-wp-widget-pages.php */
4103
				$title  = apply_filters( 'widget_title', $instance['title'], $instance, $this->id_base );
4104
4105
				if(empty($instance['widget_title_tag'])){
4106
					$output = $args['before_title'] . $title . $args['after_title'];
4107
				}else{
4108
					$title_tag = esc_attr( $instance['widget_title_tag'] );
4109
4110
					// classes
4111
					$title_classes = array();
4112
					$title_classes[] = !empty( $instance['widget_title_size_class'] ) ? sanitize_html_class( $instance['widget_title_size_class'] ) : '';
4113
					$title_classes[] = !empty( $instance['widget_title_align_class'] ) ? sanitize_html_class( $instance['widget_title_align_class'] ) : '';
4114
					$title_classes[] = !empty( $instance['widget_title_color_class'] ) ? "text-".sanitize_html_class( $instance['widget_title_color_class'] ) : '';
4115
					$title_classes[] = !empty( $instance['widget_title_border_class'] ) ? sanitize_html_class( $instance['widget_title_border_class'] ) : '';
4116
					$title_classes[] = !empty( $instance['widget_title_border_color_class'] ) ? "border-".sanitize_html_class( $instance['widget_title_border_color_class'] ) : '';
4117
					$title_classes[] = !empty( $instance['widget_title_mt_class'] ) ? "mt-".absint( $instance['widget_title_mt_class'] ) : '';
4118
					$title_classes[] = !empty( $instance['widget_title_mr_class'] ) ? "mr-".absint( $instance['widget_title_mr_class'] ) : '';
4119
					$title_classes[] = !empty( $instance['widget_title_mb_class'] ) ? "mb-".absint( $instance['widget_title_mb_class'] ) : '';
4120
					$title_classes[] = !empty( $instance['widget_title_ml_class'] ) ? "ml-".absint( $instance['widget_title_ml_class'] ) : '';
4121
					$title_classes[] = !empty( $instance['widget_title_pt_class'] ) ? "pt-".absint( $instance['widget_title_pt_class'] ) : '';
4122
					$title_classes[] = !empty( $instance['widget_title_pr_class'] ) ? "pr-".absint( $instance['widget_title_pr_class'] ) : '';
4123
					$title_classes[] = !empty( $instance['widget_title_pb_class'] ) ? "pb-".absint( $instance['widget_title_pb_class'] ) : '';
4124
					$title_classes[] = !empty( $instance['widget_title_pl_class'] ) ? "pl-".absint( $instance['widget_title_pl_class'] ) : '';
4125
4126
					$class = !empty( $title_classes ) ? implode(" ",$title_classes) : '';
4127
					$output = "<$title_tag class='$class' >$title</$title_tag>";
4128
				}
4129
4130
			}
4131
4132
			return $output;
4133
		}
4134
4135
		/**
4136
		 * Outputs the options form inputs for the widget.
4137
		 *
4138
		 * @param array $instance The widget options.
4139
		 */
4140
		public function form( $instance ) {
4141
4142
			// set widget instance
4143
			$this->instance = $instance;
4144
4145
			// set it as a SD widget
4146
			echo $this->widget_advanced_toggle();
4147
4148
			echo "<p>" . esc_attr( $this->options['widget_ops']['description'] ) . "</p>";
4149
			$arguments_raw = $this->get_arguments();
4150
4151
			if ( is_array( $arguments_raw ) ) {
0 ignored issues
show
introduced by
The condition is_array($arguments_raw) is always true.
Loading history...
4152
4153
				$arguments = $this->group_arguments( $arguments_raw );
4154
4155
				// Do we have sections?
4156
				$has_sections = $arguments == $arguments_raw ? false : true;
4157
4158
4159
				if ( $has_sections ) {
4160
					$panel_count = 0;
4161
					foreach ( $arguments as $key => $args ) {
4162
4163
						?>
4164
						<script>
4165
							//							jQuery(this).find("i").toggleClass("fas fa-chevron-up fas fa-chevron-down");jQuery(this).next().toggle();
4166
						</script>
4167
						<?php
4168
4169
						$hide       = $panel_count ? ' style="display:none;" ' : '';
4170
						$icon_class = $panel_count ? 'fas fa-chevron-up' : 'fas fa-chevron-down';
4171
						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>";
4172
						echo "<div class='sd-toggle-group sd-input-group-" . sanitize_title_with_dashes( $key ) . "' $hide>";
4173
4174
						foreach ( $args as $k => $a ) {
4175
4176
							$this->widget_inputs_row_start($k, $a);
4177
							$this->widget_inputs( $a, $instance );
4178
							$this->widget_inputs_row_end($k, $a);
4179
4180
						}
4181
4182
						echo "</div>";
4183
4184
						$panel_count ++;
4185
4186
					}
4187
				} else {
4188
					foreach ( $arguments as $key => $args ) {
4189
						$this->widget_inputs_row_start($key, $args);
4190
						$this->widget_inputs( $args, $instance );
4191
						$this->widget_inputs_row_end($key, $args);
4192
					}
4193
				}
4194
4195
			}
4196
		}
4197
4198
		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

4198
		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...
4199
			if(!empty($args['row'])){
4200
				// maybe open
4201
				if(!empty($args['row']['open'])){
4202
					?>
4203
					<div class='bsui sd-argument ' data-argument='<?php echo esc_attr( $args['row']['key'] ); ?>' data-element_require='<?php if ( !empty($args['row']['element_require'])) {
4204
						echo $this->convert_element_require( $args['row']['element_require'] );
4205
					} ?>'>
4206
					<?php if(!empty($args['row']['title'])){ ?>
4207
					<label class="mb-0 "><?php echo esc_attr( $args['row']['title'] ); ?><?php echo $this->widget_field_desc( $args['row'] ); ?></label>
4208
					<?php }?>
4209
					<div class='row <?php if(!empty($args['row']['class'])){ echo esc_attr($args['row']['class']);} ?>'>
4210
					<div class='col pr-2'>
4211
					<?php
4212
				}elseif(!empty($args['row']['close'])){
4213
					echo "<div class='col pl-0 ps-0'>";
4214
				}else{
4215
					echo "<div class='col pl-0 ps-0 pr-2 pe-2'>";
4216
				}
4217
			}
4218
		}
4219
4220
		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

4220
		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...
4221
4222
			if(!empty($args['row'])){
4223
				// maybe close
4224
				if(!empty($args['row']['close'])){
4225
					echo "</div></div>";
4226
				}
4227
4228
				echo "</div>";
4229
			}
4230
		}
4231
4232
		/**
4233
		 * Get the hidden input that when added makes the advanced button show on widget settings.
4234
		 *
4235
		 * @return string
4236
		 */
4237
		public function widget_advanced_toggle() {
4238
4239
			$output = '';
4240
			if ( $this->block_show_advanced() ) {
4241
				$val = 1;
4242
			} else {
4243
				$val = 0;
4244
			}
4245
4246
			$output .= "<input type='hidden'  class='sd-show-advanced' value='$val' />";
4247
4248
			return $output;
4249
		}
4250
4251
		/**
4252
		 * Convert require element.
4253
		 *
4254
		 * @param string $input Input element.
4255
		 *
4256
		 * @return string $output
4257
		 *@since 1.0.0
4258
		 *
4259
		 */
4260
		public function convert_element_require( $input ) {
4261
4262
			$input = str_replace( "'", '"', $input );// we only want double quotes
4263
4264
			$output = esc_attr( str_replace( array( "[%", "%]" ), array(
4265
				"jQuery(form).find('[data-argument=\"",
4266
				"\"]').find('input,select,textarea').val()"
4267
			), $input ) );
4268
4269
			return $output;
4270
		}
4271
4272
		/**
4273
		 * Builds the inputs for the widget options.
4274
		 *
4275
		 * @param $args
4276
		 * @param $instance
4277
		 */
4278
		public function widget_inputs( $args, $instance ) {
4279
4280
			$class             = "";
4281
			$element_require   = "";
4282
			$custom_attributes = "";
4283
4284
			// get value
4285
			if ( isset( $instance[ $args['name'] ] ) ) {
4286
				$value = $instance[ $args['name'] ];
4287
			} elseif ( ! isset( $instance[ $args['name'] ] ) && ! empty( $args['default'] ) ) {
4288
				$value = is_array( $args['default'] ) ? array_map( "esc_html", $args['default'] ) : esc_html( $args['default'] );
4289
			} else {
4290
				$value = '';
4291
			}
4292
4293
			// get placeholder
4294
			if ( ! empty( $args['placeholder'] ) ) {
4295
				$placeholder = "placeholder='" . esc_html( $args['placeholder'] ) . "'";
4296
			} else {
4297
				$placeholder = '';
4298
			}
4299
4300
			// get if advanced
4301
			if ( isset( $args['advanced'] ) && $args['advanced'] ) {
4302
				$class .= " sd-advanced-setting ";
4303
			}
4304
4305
			// element_require
4306
			if ( isset( $args['element_require'] ) && $args['element_require'] ) {
4307
				$element_require = $args['element_require'];
4308
			}
4309
4310
			// custom_attributes
4311
			if ( isset( $args['custom_attributes'] ) && $args['custom_attributes'] ) {
4312
				$custom_attributes = $this->array_to_attributes( $args['custom_attributes'], true );
4313
			}
4314
4315
4316
			// before wrapper
4317
			?>
4318
			<p class="sd-argument <?php echo esc_attr( $class ); ?>"
4319
			data-argument='<?php echo esc_attr( $args['name'] ); ?>'
4320
			data-element_require='<?php if ( $element_require ) {
4321
				echo $this->convert_element_require( $element_require );
4322
			} ?>'
4323
			>
4324
			<?php
4325
4326
4327
			switch ( $args['type'] ) {
4328
				//array('text','password','number','email','tel','url','color')
4329
				case "text":
4330
				case "password":
4331
				case "number":
4332
				case "email":
4333
				case "tel":
4334
				case "url":
4335
				case "color":
4336
					?>
4337
					<label
4338
						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>
4339
					<input <?php echo $placeholder; ?> class="widefat"
4340
						<?php echo $custom_attributes; ?>
4341
						                               id="<?php echo esc_attr( $this->get_field_id( $args['name'] ) ); ?>"
4342
						                               name="<?php echo esc_attr( $this->get_field_name( $args['name'] ) ); ?>"
4343
						                               type="<?php echo esc_attr( $args['type'] ); ?>"
4344
						                               value="<?php echo esc_attr( $value ); ?>">
4345
					<?php
4346
4347
					break;
4348
				case "select":
4349
					$multiple = isset( $args['multiple'] ) && $args['multiple'] ? true : false;
4350
					if ( $multiple ) {
4351
						if ( empty( $value ) ) {
4352
							$value = array();
4353
						}
4354
					}
4355
					?>
4356
					<label
4357
						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>
4358
					<select <?php echo $placeholder; ?> class="widefat"
4359
						<?php echo $custom_attributes; ?>
4360
						                                id="<?php echo esc_attr( $this->get_field_id( $args['name'] ) ); ?>"
4361
						                                name="<?php echo esc_attr( $this->get_field_name( $args['name'] ) );
4362
						                                if ( $multiple ) {
4363
							                                echo "[]";
4364
						                                } ?>"
4365
						<?php if ( $multiple ) {
4366
							echo "multiple";
4367
						} //@todo not implemented yet due to gutenberg not supporting it
4368
						?>
4369
					>
4370
						<?php
4371
4372
						if ( ! empty( $args['options'] ) ) {
4373
							foreach ( $args['options'] as $val => $label ) {
4374
								if ( $multiple ) {
4375
									$selected = in_array( $val, $value ) ? 'selected="selected"' : '';
4376
								} else {
4377
									$selected = selected( $value, $val, false );
4378
								}
4379
								echo "<option value='$val' " . $selected . ">$label</option>";
4380
							}
4381
						}
4382
						?>
4383
					</select>
4384
					<?php
4385
					break;
4386
				case "checkbox":
4387
					?>
4388
					<input <?php echo $placeholder; ?>
4389
						<?php checked( 1, $value, true ) ?>
4390
						<?php echo $custom_attributes; ?>
4391
						class="widefat" id="<?php echo esc_attr( $this->get_field_id( $args['name'] ) ); ?>"
4392
						name="<?php echo esc_attr( $this->get_field_name( $args['name'] ) ); ?>" type="checkbox"
4393
						value="1">
4394
					<label
4395
						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>
4396
					<?php
4397
					break;
4398
				case "textarea":
4399
					?>
4400
					<label
4401
						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>
4402
					<textarea <?php echo $placeholder; ?> class="widefat"
4403
						<?php echo $custom_attributes; ?>
4404
						                                  id="<?php echo esc_attr( $this->get_field_id( $args['name'] ) ); ?>"
4405
						                                  name="<?php echo esc_attr( $this->get_field_name( $args['name'] ) ); ?>"
4406
					><?php echo esc_attr( $value ); ?></textarea>
4407
					<?php
4408
4409
					break;
4410
				case "hidden":
4411
					?>
4412
					<input id="<?php echo esc_attr( $this->get_field_id( $args['name'] ) ); ?>"
4413
					       name="<?php echo esc_attr( $this->get_field_name( $args['name'] ) ); ?>" type="hidden"
4414
					       value="<?php echo esc_attr( $value ); ?>">
4415
					<?php
4416
					break;
4417
				default:
4418
					echo "No input type found!"; // @todo we need to add more input types.
4419
			}
4420
4421
			// after wrapper
4422
			?>
4423
			</p>
4424
			<?php
4425
4426
4427
		}
4428
4429
		public function get_widget_icon($icon = 'box-top', $title = ''){
4430
			if($icon=='box-top'){
4431
				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>';
4432
			}elseif($icon=='box-right'){
4433
				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>';
4434
			}elseif($icon=='box-bottom'){
4435
				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>';
4436
			}elseif($icon=='box-left'){
4437
				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>';
4438
			}
4439
		}
4440
4441
		/**
4442
		 * Get the widget input description html.
4443
		 *
4444
		 * @param $args
4445
		 *
4446
		 * @return string
4447
		 * @todo, need to make its own tooltip script
4448
		 */
4449
		public function widget_field_desc( $args ) {
4450
4451
			$description = '';
4452
			if ( isset( $args['desc'] ) && $args['desc'] ) {
4453
				if ( isset( $args['desc_tip'] ) && $args['desc_tip'] ) {
4454
					$description = $this->desc_tip( $args['desc'] );
4455
				} else {
4456
					$description = '<span class="description">' . wp_kses_post( $args['desc'] ) . '</span>';
4457
				}
4458
			}
4459
4460
			return $description;
4461
		}
4462
4463
		/**
4464
		 * Get the widget input title html.
4465
		 *
4466
		 * @param $args
4467
		 *
4468
		 * @return string
4469
		 */
4470
		public function widget_field_title( $args ) {
4471
4472
			$title = '';
4473
			if ( isset( $args['title'] ) && $args['title'] ) {
4474
				if ( isset( $args['icon'] ) && $args['icon'] ) {
4475
					$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

4475
					/** @scrutinizer ignore-call */ 
4476
     $title = self::get_widget_icon( $args['icon'], $args['title']  );
Loading history...
4476
				} else {
4477
					$title = esc_attr($args['title']);
4478
				}
4479
			}
4480
4481
			return $title;
4482
		}
4483
4484
		/**
4485
		 * Get the tool tip html.
4486
		 *
4487
		 * @param $tip
4488
		 * @param bool $allow_html
4489
		 *
4490
		 * @return string
4491
		 */
4492
		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...
4493
			if ( $allow_html ) {
4494
				$tip = $this->sanitize_tooltip( $tip );
4495
			} else {
4496
				$tip = esc_attr( $tip );
4497
			}
4498
4499
			return '<span class="gd-help-tip dashicons dashicons-editor-help" title="' . $tip . '"></span>';
4500
		}
4501
4502
		/**
4503
		 * Sanitize a string destined to be a tooltip.
4504
		 *
4505
		 * @param string $var
4506
		 *
4507
		 * @return string
4508
		 */
4509
		public function sanitize_tooltip( $var ) {
4510
			return htmlspecialchars( wp_kses( html_entity_decode( $var ), array(
4511
				'br'     => array(),
4512
				'em'     => array(),
4513
				'strong' => array(),
4514
				'small'  => array(),
4515
				'span'   => array(),
4516
				'ul'     => array(),
4517
				'li'     => array(),
4518
				'ol'     => array(),
4519
				'p'      => array(),
4520
			) ) );
4521
		}
4522
4523
		/**
4524
		 * Processing widget options on save
4525
		 *
4526
		 * @param array $new_instance The new options
4527
		 * @param array $old_instance The previous options
4528
		 *
4529
		 * @return array
4530
		 * @todo we should add some sanitation here.
4531
		 */
4532
		public function update( $new_instance, $old_instance ) {
4533
4534
			//save the widget
4535
			$instance = array_merge( (array) $old_instance, (array) $new_instance );
4536
4537
			// set widget instance
4538
			$this->instance = $instance;
4539
4540
			if ( empty( $this->arguments ) ) {
4541
				$this->get_arguments();
4542
			}
4543
4544
			// check for checkboxes
4545
			if ( ! empty( $this->arguments ) ) {
4546
				foreach ( $this->arguments as $argument ) {
4547
					if ( isset( $argument['type'] ) && $argument['type'] == 'checkbox' && ! isset( $new_instance[ $argument['name'] ] ) ) {
4548
						$instance[ $argument['name'] ] = '0';
4549
					}
4550
				}
4551
			}
4552
4553
			return $instance;
4554
		}
4555
4556
		/**
4557
		 * Checks if the current call is a ajax call to get the block content.
4558
		 *
4559
		 * This can be used in your widget to return different content as the block content.
4560
		 *
4561
		 * @return bool
4562
		 *@since 1.0.3
4563
		 */
4564
		public function is_block_content_call() {
4565
			$result = false;
4566
			if ( wp_doing_ajax() && isset( $_REQUEST['action'] ) && $_REQUEST['action'] == 'super_duper_output_shortcode' ) {
4567
				$result = true;
4568
			}
4569
4570
			return $result;
4571
		}
4572
4573
		/**
4574
		 * Get an instance hash that will be unique to the type and settings.
4575
		 *
4576
		 * @return string
4577
		 *@since 1.0.20
4578
		 */
4579
		public function get_instance_hash(){
4580
			$instance_string = $this->base_id.serialize($this->instance);
4581
			return hash('crc32b',$instance_string);
4582
		}
4583
4584
		/**
4585
		 * Generate and return inline styles from CSS rules that will match the unique class of the instance.
4586
		 *
4587
		 * @param array $rules
4588
		 *
4589
		 * @return string
4590
		 *@since 1.0.20
4591
		 */
4592
		public function get_instance_style($rules = array()){
4593
			$css = '';
4594
4595
			if(!empty($rules)){
4596
				$rules = array_unique($rules);
4597
				$instance_hash = $this->get_instance_hash();
4598
				$css .= "<style>";
4599
				foreach($rules as $rule){
4600
					$css .= ".sdel-$instance_hash $rule";
4601
				}
4602
				$css .= "</style>";
4603
			}
4604
4605
			return $css;
4606
		}
4607
4608
		/**
4609
		 * Encode shortcodes tags.
4610
		 *
4611
		 * @param string $content Content to search for shortcode tags.
4612
		 *
4613
*@return string Content with shortcode tags removed.
4614
		 *@since 1.0.28
4615
		 *
4616
		 */
4617
		public function encode_shortcodes( $content ) {
4618
			// Avoids existing encoded tags.
4619
			$trans   = array(
4620
				'&#91;' => '&#091;',
4621
				'&#93;' => '&#093;',
4622
				'&amp;#91;' => '&#091;',
4623
				'&amp;#93;' => '&#093;',
4624
				'&lt;' => '&0lt;',
4625
				'&gt;' => '&0gt;',
4626
				'&amp;lt;' => '&0lt;',
4627
				'&amp;gt;' => '&0gt;',
4628
			);
4629
4630
			$content = strtr( $content, $trans );
4631
4632
			$trans   = array(
4633
				'[' => '&#91;',
4634
				']' => '&#93;',
4635
				'<' => '&lt;',
4636
				'>' => '&gt;',
4637
				'"' => '&quot;',
4638
				"'" => '&#39;',
4639
			);
4640
4641
			$content = strtr( $content, $trans );
4642
4643
			return $content;
4644
		}
4645
4646
		/**
4647
		 * Remove encoded shortcod tags.
4648
		 *
4649
		 * @param string $content Content to search for shortcode tags.
4650
		 *
4651
*@return string Content with decoded shortcode tags.
4652
		 *@since 1.0.28
4653
		 *
4654
		 */
4655
		public function decode_shortcodes( $content ) {
4656
			$trans   = array(
4657
				'&#91;' => '[',
4658
				'&#93;' => ']',
4659
				'&amp;#91;' => '[',
4660
				'&amp;#93;' => ']',
4661
				'&lt;' => '<',
4662
				'&gt;' => '>',
4663
				'&amp;lt;' => '<',
4664
				'&amp;gt;' => '>',
4665
				'&quot;' => '"',
4666
				'&apos;' => "'",
4667
			);
4668
4669
			$content = strtr( $content, $trans );
4670
4671
			$trans   = array(
4672
				'&#091;' => '&#91;',
4673
				'&#093;' => '&#93;',
4674
				'&amp;#091;' => '&#91;',
4675
				'&amp;#093;' => '&#93;',
4676
				'&0lt;' => '&lt;',
4677
				'&0gt;' => '&gt;',
4678
				'&amp;0lt;' => '&lt;',
4679
				'&amp;0gt;' => '&gt;',
4680
			);
4681
4682
			$content = strtr( $content, $trans );
4683
4684
			return $content;
4685
		}
4686
	}
4687
}
4688