Passed
Push — master ( 877d43...e9e8ae )
by Brian
06:03
created

WP_Super_Duper_Block::block_row_start()   C

Complexity

Conditions 14
Paths 73

Size

Total Lines 68
Code Lines 55

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 14
eloc 55
nc 73
nop 2
dl 0
loc 68
rs 6.2666
c 1
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

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

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

Commonly applied refactorings include:

1
<?php
2
/**
3
 * Contains the block class.
4
 *
5
 * @since 2.0.0
6
 */
7
8
defined( 'ABSPATH' ) || exit;
9
10
/**
11
 *
12
 * The block super duper class.
13
 *
14
 *
15
 * @since 2.0.0
16
 * @version 2.0.0
17
 */
18
class WP_Super_Duper_Block {
19
20
	/**
21
	 * @var WP_Super_Duper
22
	 */
23
	protected $sd;
24
25
	/**
26
	 * Class constructor.
27
	 *
28
	 * @param WP_Super_Duper $super_duper
29
	 */
30
	public function __construct( $super_duper ) {
31
32
		$this->sd = $super_duper;
33
34
		// Process the SD shortcode preview.
35
		add_action( 'wp_ajax_super_duper_output_shortcode', array( __CLASS__, 'render_shortcode' ) );
36
		add_action( 'admin_enqueue_scripts', array( $this, 'register_block' ) );
37
		add_action( 'admin_footer-post.php', array( $this, 'enqueue_editor_assets' ) );
38
		add_action( 'admin_footer-post-new.php', array( $this, 'enqueue_editor_assets' ) );
39
	}
40
41
	/**
42
	 * Render the shortcode via ajax so we can return it to Gutenberg.
43
	 *
44
	 * @since 1.0.0
45
	 */
46
	public static function render_shortcode() {
47
48
		// Verify nonce.
49
		check_ajax_referer( 'super_duper_output_shortcode', '_ajax_nonce', true );
50
51
		// And permissions.
52
		if ( ! current_user_can( 'manage_options' ) ) {
53
			wp_die();
54
		}
55
56
		// Ensure a shortcode is provided.
57
		if ( empty( $_POST['shortcode'] ) ) {
58
			wp_die();
59
		}
60
61
		// We might need the $post value here so lets set it.
62
		if ( isset( $_POST['post_id'] ) && $_POST['post_id'] ) {
63
			$post_obj = get_post( absint( $_POST['post_id'] ) );
64
			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...
65
				global $post;
66
				$post = $post_obj;
67
			}
68
		}
69
70
		// Prepare args.
71
		$shortcode_name   = sanitize_title_with_dashes( $_POST['shortcode'] );
72
		$attributes_array = isset( $_POST['attributes'] ) && $_POST['attributes'] ? $_POST['attributes'] : array();
73
		$attributes       = '';
74
75
		// Convert attributes array into a string.
76
		if ( ! empty( $attributes_array ) ) {
77
			foreach ( $attributes_array as $key => $value ) {
78
				if ( is_array( $value ) ) {
79
					$value = implode( ',', $value );
80
				}
81
				$key   = sanitize_title_with_dashes( $key );
82
				$value = wp_slash( $value );
83
				$attributes .= " $key='$value' ";
84
			}
85
		}
86
87
		echo do_shortcode( "[$shortcode_name $attributes]" );
88
		exit;
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
89
90
	}
91
92
	/**
93
	 * Add the dynamic block code inline when the wp-block in enqueued.
94
	 */
95
	public function register_block() {
96
		wp_add_inline_script( 'wp-blocks', $this->block() );
97
		if ( class_exists( 'SiteOrigin_Panels' ) ) {
98
			wp_add_inline_script( 'wp-blocks', WP_Super_Duper::siteorigin_js() );
99
		}
100
	}
101
102
	/**
103
	 * Output the JS for building the dynamic Guntenberg block.
104
	 *
105
	 * @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.
106
	 * @since 1.0.9 Save numbers as numbers and not strings.
107
	 * @since 1.1.0 Font Awesome classes can be used for icons.
108
	 * @return mixed
109
	 */
110
	public function block() {
111
		ob_start();
112
113
		$block_name    = str_replace( '_', '-', sanitize_title_with_dashes( $this->sd->options['textdomain'] ) . '/' . sanitize_title_with_dashes( $this->sd->options['class_name'] ) );
114
		$show_advanced = $this->sd->block_show_advanced();
115
		$id            = $this->sd->base_id . '-' . $this->sd->get_number();
116
		?>
117
		<script>
118
			/**
119
			 * BLOCK: Basic
120
			 *
121
			 * Registering a basic block with Gutenberg.
122
			 * Simple block, renders and saves the same content without any interactivity.
123
			 *
124
			 * Styles:
125
			 *        editor.css — Editor styles for the block.
126
			 *        style.css  — Editor & Front end styles for the block.
127
			 */
128
			(function () {
129
				var __ = wp.i18n.__; // The __() for internationalization.
130
				var el = wp.element.createElement; // The wp.element.createElement() function to create elements.
131
				var editable = wp.blocks.Editable;
132
				var blocks = wp.blocks;
133
				var registerBlockType = wp.blocks.registerBlockType; // The registerBlockType() to register blocks.
134
				var is_fetching = false;
135
				var prev_attributes = [];
136
137
				var term_query_type = '';
138
				var post_type_rest_slugs = <?php if ( ! empty( $this->sd->arguments ) && isset( $this->sd->arguments['post_type']['onchange_rest']['values'] ) ) {
139
					echo "[" . json_encode( $this->sd->arguments['post_type']['onchange_rest']['values'] ) . "]";
140
				} else {
141
					echo "[]";
142
				} ?>;
143
				const taxonomies_<?php echo str_replace( "-", "_", $id );?> = [{label: "Please wait", value: 0}];
144
				const sort_by_<?php echo str_replace( "-", "_", $id );?> = [{label: "Please wait", value: 0}];
145
146
				/**
147
				 * Register Basic Block.
148
				 *
149
				 * Registers a new block provided a unique name and an object defining its
150
				 * behavior. Once registered, the block is made available as an option to any
151
				 * editor interface where blocks are implemented.
152
				 *
153
				 * @param  {string}   name     Block name.
154
				 * @param  {Object}   settings Block settings.
155
				 * @return {?WPBlock}          The block, if it has been successfully
156
				 *                             registered; otherwise `undefined`.
157
				 */
158
				registerBlockType('<?php echo $block_name;  ?>', { // Block name. Block names must be string that contains a namespace prefix. Example: my-plugin/my-custom-block.
159
					title: '<?php echo addslashes( $this->sd->options['name'] ); ?>', // Block title.
160
					description: '<?php echo addslashes( $this->sd->options['widget_ops']['description'] )?>', // Block title.
161
					icon: <?php echo $this->get_block_icon( $this->sd->options['block-icon'] );?>,//'<?php echo isset( $this->sd->options['block-icon'] ) ? esc_attr( $this->sd->options['block-icon'] ) : 'shield-alt';?>', // Block icon from Dashicons → https://developer.wordpress.org/resource/dashicons/.
162
					supports: {
163
						<?php
164
						if ( isset( $this->sd->options['block-supports'] ) ) {
165
							echo $this->sd->array_to_attributes( $this->sd->options['block-supports'] );
166
						}
167
						?>
168
					},
169
					category: '<?php echo isset( $this->sd->options['block-category'] ) ? esc_attr( $this->sd->options['block-category'] ) : 'common';?>', // Block category — Group blocks together based on common traits E.g. common, formatting, layout widgets, embed.
170
					<?php if ( isset( $this->sd->options['block-keywords'] ) ) {
171
					echo "keywords : " . $this->sd->options['block-keywords'] . ",";
172
				}?>
173
174
					<?php
175
176
					// maybe set no_wrap
177
					$no_wrap = isset( $this->sd->options['no_wrap'] ) && $this->sd->options['no_wrap'] ? true : false;
178
					if ( isset( $this->sd->arguments['no_wrap'] ) && $this->sd->arguments['no_wrap'] ) {
179
						$no_wrap = true;
180
					}
181
					if ( $no_wrap ) {
182
						$this->sd->options['block-wrap'] = '';
183
					}
184
185
					$show_alignment = false;
186
187
					if ( ! empty( $this->sd->arguments ) ) {
188
						echo "attributes : {";
189
190
						if ( $show_advanced ) {
191
							echo "show_advanced: {";
192
							echo "	type: 'boolean',";
193
							echo "  default: false,";
194
							echo "},";
195
						}
196
197
						// block wrap element
198
						if ( ! empty( $this->sd->options['block-wrap'] ) ) { //@todo we should validate this?
199
							echo "block_wrap: {";
200
							echo "	type: 'string',";
201
							echo "  default: '" . esc_attr( $this->sd->options['block-wrap'] ) . "',";
202
							echo "},";
203
						}
204
205
						foreach ( $this->sd->arguments as $key => $args ) {
206
207
							// set if we should show alignment
208
							if ( $key == 'alignment' ) {
209
								$show_alignment = true;
210
							}
211
212
							$extra = '';
0 ignored issues
show
Unused Code introduced by
The assignment to $extra is dead and can be removed.
Loading history...
213
214
							if ( $args['type'] == 'checkbox' ) {
215
								$type    = 'boolean';
216
								$default = isset( $args['default'] ) && $args['default'] ? 'true' : 'false';
217
							} elseif ( $args['type'] == 'number' ) {
218
								$type    = 'number';
219
								$default = isset( $args['default'] ) ? "'" . $args['default'] . "'" : "''";
220
							} elseif ( $args['type'] == 'select' && ! empty( $args['multiple'] ) ) {
221
								$type = 'array';
222
								if ( isset( $args['default'] ) && is_array( $args['default'] ) ) {
223
									$default = ! empty( $args['default'] ) ? "['" . implode( "','", $args['default'] ) . "']" : "[]";
224
								} else {
225
									$default = isset( $args['default'] ) ? "'" . $args['default'] . "'" : "''";
226
								}
227
							} elseif ( $args['type'] == 'multiselect' ) {
228
								$type    = 'array';
229
								$default = isset( $args['default'] ) ? "'" . $args['default'] . "'" : "''";
230
							} else {
231
								$type    = 'string';
232
								$default = isset( $args['default'] ) ? "'" . $args['default'] . "'" : "''";
233
							}
234
							echo str_replace( '-','__', $key ) . " : {";
235
							echo "type : '$type',";
236
							echo "default : $default,";
237
							echo "},";
238
						}
239
240
						echo "content : {type : 'string',default: 'Please select the attributes in the block settings'},";
241
						echo "className: { type: 'string', default: '' },";
242
						echo "},";
243
244
					}
245
246
					?>
247
248
					// The "edit" property must be a valid function.
249
					edit: function (props) {
250
251
252
						var $value = '';
253
						<?php
254
						// if we have a post_type and a category then link them
255
						if( isset( $this->sd->arguments['post_type'] ) && isset( $this->sd->arguments['category'] ) && ! empty( $this->sd->arguments['category']['post_type_linked'] ) ){
256
						?>
257
						if (typeof(prev_attributes[props.id]) != 'undefined') {
258
							$pt = props.attributes.post_type;
259
							if (post_type_rest_slugs.length) {
260
								$value = post_type_rest_slugs[0][$pt];
261
							}
262
							var run = false;
263
264
							if ($pt != term_query_type) {
265
								run = true;
266
								term_query_type = $pt;
267
							}
268
269
							// taxonomies
270
							if ($value && 'post_type' in prev_attributes[props.id] && 'category' in prev_attributes[props.id] && run) {
271
								wp.apiFetch({
272
									path: "<?php if ( isset( $this->sd->arguments['post_type']['onchange_rest']['path'] ) ) {
273
										echo $this->sd->arguments['post_type']['onchange_rest']['path'];
274
									} else {
275
										'/wp/v2/"+$value+"/categories/?per_page=100';
276
									} ?>"
277
								}).then(terms => {
278
									while (taxonomies_<?php echo str_replace( "-", "_", $id );?>.length
279
							)
280
								{
281
									taxonomies_<?php echo str_replace("-","_", $id);?>.pop();
282
								}
283
								taxonomies_<?php echo str_replace("-","_", $id);?>.push({label: "All", value: 0});
284
								jQuery.each(terms, function (key, val) {
285
									taxonomies_<?php echo str_replace("-","_", $id);?>.push({
286
										label: val.name,
287
										value: val.id
288
									});
289
								});
290
291
								// setting the value back and fourth fixes the no update issue that sometimes happens where it won't update the options.
292
								var $old_cat_value = props.attributes.category;
293
								props.setAttributes({category: [0]});
294
								props.setAttributes({category: $old_cat_value});
295
296
								return taxonomies_<?php echo str_replace( "-", "_", $id );?>;
297
							})
298
							};
299
300
							// sort_by
301
							if ($value && 'post_type' in prev_attributes[props.id] && 'sort_by' in prev_attributes[props.id] && run) {
302
								var data = {
303
									'action': 'geodir_get_sort_options',
304
									'post_type': $pt
305
								};
306
								jQuery.post(ajaxurl, data, function (response) {
307
									response = JSON.parse(response);
308
									while (sort_by_<?php echo str_replace( "-", "_", $id );?>.length) {
309
										sort_by_<?php echo str_replace("-","_", $id);?>.pop();
310
									}
311
312
									jQuery.each(response, function (key, val) {
313
										sort_by_<?php echo str_replace("-","_", $id);?>.push({label: val, value: key});
314
									});
315
316
									// setting the value back and fourth fixes the no update issue that sometimes happens where it won't update the options.
317
									var $old_sort_by_value = props.attributes.sort_by;
318
									props.setAttributes({sort_by: [0]});
319
									props.setAttributes({sort_by: $old_sort_by_value});
320
321
									return sort_by_<?php echo str_replace( "-", "_", $id );?>;
322
								});
323
324
							}
325
						}
326
						<?php }?>
327
328
329
						var content = props.attributes.content;
330
331
						function onChangeContent() {
332
333
							$refresh = false;
334
335
							// Set the old content the same as the new one so we only compare all other attributes
336
							if (typeof(prev_attributes[props.id]) != 'undefined') {
337
								prev_attributes[props.id].content = props.attributes.content;
338
							} else if (props.attributes.content === "") {
339
								// if first load and content empty then refresh
340
								$refresh = true;
341
							}
342
343
							if (( !is_fetching && JSON.stringify(prev_attributes[props.id]) != JSON.stringify(props.attributes) ) || $refresh) {
344
345
								is_fetching = true;
346
								var data = {
347
									'action': 'super_duper_output_shortcode',
348
									'shortcode': '<?php echo $this->sd->options['base_id'];?>',
349
									'attributes': props.attributes,
350
									'post_id': <?php global $post; if ( isset( $post->ID ) ) {
351
									echo $post->ID;
352
								} else {
353
									echo '0';
354
								}?>,
355
									'_ajax_nonce': '<?php echo wp_create_nonce( 'super_duper_output_shortcode' );?>'
356
								};
357
358
								jQuery.post(ajaxurl, data, function (response) {
359
									return response;
360
								}).then(function (env) {
361
362
									// if the content is empty then we place some placeholder text
363
									if (env == '') {
364
										env = "<div style='background:#0185ba33;padding: 10px;border: 4px #ccc dashed;'>" + "<?php _e( 'Placeholder for: ' );?>" + props.name + "</div>";
365
									}
366
367
									props.setAttributes({content: env});
368
									is_fetching = false;
369
									prev_attributes[props.id] = props.attributes;
370
371
									// if AUI is active call the js init function
372
									if (typeof aui_init === "function") {
373
										aui_init();
374
									}
375
								});
376
377
378
							}
379
380
							return props.attributes.content;
381
382
						}
383
384
						return [
385
386
							el(wp.blockEditor.BlockControls, {key: 'controls'},
387
388
								<?php if($show_alignment){?>
389
								el(
390
									wp.blockEditor.AlignmentToolbar,
391
									{
392
										value: props.attributes.alignment,
393
										onChange: function (alignment) {
394
											props.setAttributes({alignment: alignment})
395
										}
396
									}
397
								)
398
								<?php }?>
399
400
							),
401
402
							el(wp.blockEditor.InspectorControls, {key: 'inspector'},
403
404
								<?php
405
406
								if(! empty( $this->sd->arguments )){
407
408
								if ( $show_advanced ) {
409
								?>
410
								el('div', {
411
										style: {'padding-left': '16px', 'padding-right': '16px'}
412
									},
413
									el(
414
										wp.components.ToggleControl,
415
										{
416
											label: 'Show Advanced Settings?',
417
											checked: props.attributes.show_advanced,
418
											onChange: function (show_advanced) {
419
												props.setAttributes({show_advanced: !props.attributes.show_advanced})
420
											}
421
										}
422
									)
423
								)
424
								,
425
								<?php
426
427
								}
428
429
								$arguments = $this->sd->group_arguments( $this->sd->arguments );
430
431
								// Do we have sections?
432
								$has_sections = $arguments == $this->sd->arguments ? false : true;
433
434
435
								if($has_sections){
436
								$panel_count = 0;
437
								foreach($arguments as $key => $args){
438
								?>
439
								el(wp.components.PanelBody, {
440
										title: '<?php esc_attr_e( $key ); ?>',
441
										initialOpen: <?php if ( $panel_count ) {
442
										echo "false";
443
									} else {
444
										echo "true";
445
									}?>
446
									},
447
									<?php
448
449
									foreach ( $args as $k => $a ) {
450
										$k = str_replace('-','__', $k);
451
										$this->block_row_start( $k, $a );
452
										$this->build_block_arguments( $k, $a );
453
										$this->block_row_end( $k, $a );
454
									}
455
									?>
456
								),
457
								<?php
458
								$panel_count ++;
459
460
								}
461
								}else {
462
								?>
463
								el(wp.components.PanelBody, {
464
										title: '<?php esc_attr_e( "Settings" ); ?>',
465
										initialOpen: true
466
									},
467
									<?php
468
									foreach ( $this->sd->arguments as $key => $args ) {
469
										$key = str_replace('-','__', $key);
470
										$this->block_row_start( $key, $args );
471
										$this->build_block_arguments( $key, $args );
472
										$this->block_row_end( $key, $args );
473
									}
474
									?>
475
								),
476
								<?php
477
								}
478
479
								}
480
								?>
481
482
							),
483
484
							<?php
485
							// If the user sets block-output array then build it
486
							if ( ! empty( $this->sd->options['block-output'] ) ) {
487
							$this->block_element( $this->sd->options['block-output'] );
488
						}else{
489
							// if no block-output is set then we try and get the shortcode html output via ajax.
490
							?>
491
							el('div', {
492
								dangerouslySetInnerHTML: {__html: onChangeContent()},
493
								className: props.className,
494
								style: {'minHeight': '30px'}
495
							})
496
							<?php
497
							}
498
							?>
499
						]; // end return
500
					},
501
502
					// Enable transforming from Legacy widgets.
503
					transforms: {
504
						from: [
505
							{
506
								type: "block",
507
								blocks: ["core/legacy-widget"],
508
								isMatch: function isMatch(attributes) {
509
									var idBase = attributes.idBase,
510
										instance = attributes.instance;
511
512
									if (!(instance !== null && instance !== void 0 && instance.raw)) {
513
										// Can't transform if raw instance is not shown in REST API.
514
										return false;
515
									}
516
517
									return idBase === "<?php echo $this->sd->options['base_id'];?>";
518
								},
519
								transform: function transform(attributes) {
520
									var instance = attributes.instance;
521
522
									return wp.blocks.createBlock("<?php echo $block_name;?>", instance.raw);
523
								}
524
							}
525
						]
526
					},
527
528
					// The "save" property must be specified and must be a valid function.
529
					save: function (props) {
530
531
						//console.log(props);
532
533
534
						var attr = props.attributes;
535
						var align = '';
536
537
						// build the shortcode.
538
						var content = "[<?php echo $this->sd->options['base_id'];?>";
539
						$html = '';
540
						<?php
541
542
						if(! empty( $this->sd->arguments )){
543
544
						foreach($this->sd->arguments as $key => $args){
545
						$key = str_replace('-','__', $key);
546
						?>
547
						if (attr.hasOwnProperty("<?php echo esc_attr( $key );?>")) {
548
							if ('<?php echo esc_attr( $key );?>' == 'html') {
549
								$html = attr.<?php echo esc_attr( $key );?>;
550
							} else {
551
								content += " <?php echo str_replace( '__','-', esc_attr( $key ) );?>='" + attr.<?php echo esc_attr( $key );?>+ "' ";
552
							}
553
						}
554
						<?php
555
						}
556
						}
557
558
						?>
559
						content += "]";
560
561
						// if has html element
562
						if ($html) {
563
							content += $html + "[/<?php echo $this->sd->options['base_id'];?>]";
564
						}
565
566
567
						// @todo should we add inline style here or just css classes?
568
						if (attr.alignment) {
569
							if (attr.alignment == 'left') {
570
								align = 'alignleft';
571
							}
572
							if (attr.alignment == 'center') {
573
								align = 'aligncenter';
574
							}
575
							if (attr.alignment == 'right') {
576
								align = 'alignright';
577
							}
578
						}
579
580
						<?php
581
						if(isset( $this->sd->options['block-wrap'] ) && $this->sd->options['block-wrap'] == ''){
582
						?>
583
						return content;
584
						<?php
585
						}else{
586
						?>
587
						var block_wrap = 'div';
588
						if (attr.hasOwnProperty("block_wrap")) {
589
							block_wrap = attr.block_wrap;
590
						}
591
						return el(block_wrap, {dangerouslySetInnerHTML: {__html: content}, className: align});
592
						<?php
593
						}
594
						?>
595
596
597
					}
598
				});
599
			})();
600
		</script>
601
		<?php
602
		$output = ob_get_clean();
603
604
		/*
605
		 * We only add the <script> tags for code highlighting, so we strip them from the output.
606
		 */
607
608
		return str_replace( array(
609
			'<script>',
610
			'</script>'
611
		), '', $output );
612
	}
613
614
	/**
615
	 * Generate the block icon.
616
	 *
617
	 * Enables the use of Font Awesome icons.
618
	 *
619
	 * @note xlink:href is actually deprecated but href is not supported by all so we use both.
620
	 *
621
	 * @param $icon
622
	 *
623
	 * @since 1.1.0
624
	 * @return string
625
	 */
626
	public function get_block_icon( $icon ) {
627
628
		// check if we have a Font Awesome icon
629
		$fa_type = '';
630
		if ( substr( $icon, 0, 7 ) === 'fas fa-' ) {
631
			$fa_type = 'solid';
632
		} elseif ( substr( $icon, 0, 7 ) === 'far fa-' ) {
633
			$fa_type = 'regular';
634
		} elseif ( substr( $icon, 0, 7 ) === 'fab fa-' ) {
635
			$fa_type = 'brands';
636
		} else {
637
			$icon = sprintf( "'%s'", esc_js( $icon ) );
638
		}
639
640
		// set the icon if we found one
641
		if ( $fa_type ) {
642
			$fa_icon = substr( $icon, 7 );
643
			$icon    = "el('svg',{width: 20, height: 20, viewBox: '0 0 20 20'},el('use', {'xlink:href': '" . $this->sd->get_url() . "icons/" . $fa_type . ".svg#" . $fa_icon . "','href': '" . $this->sd->get_url() . "icons/" . $fa_type . ".svg#" . $fa_icon . "'}))";
644
		}
645
646
		return $icon;
647
	}
648
649
	public function block_row_start( $key, $args ) {
650
		// check for row
651
		if ( ! empty( $args['row'] ) ) {
652
			if ( ! empty( $args['row']['open'] ) ) {
653
				// element require
654
				$element_require = ! empty( $args['element_require'] ) ? $this->block_props_replace( $args['element_require'], true ) . " && " : "";
655
				echo $element_require;
656
			if ( false ){
657
				?>
658
				<script><?php }?>
659
					el('div', {
660
							className: 'bsui components-base-control',
661
						},
662
						<?php if(! empty( $args['row']['title'] )){ ?>
663
						el('label', {
664
								className: 'components-base-control__label',
665
								key: '<?php esc_attr( $key )?>-title'
666
							},
667
							'<?php echo addslashes( $args['row']['title'] ); ?>'
668
						),
669
						<?php }?>
670
						<?php if(! empty( $args['row']['desc'] )){ ?>
671
						el('p', {
672
								className: 'components-base-control__help mb-0',
673
								key: '<?php esc_attr( $key )?>-desc'
674
							},
675
							'<?php echo addslashes( $args['row']['desc'] ); ?>'
676
						),
677
						<?php }?>
678
						el(
679
							'div',
680
							{
681
								className: 'row mb-n2 <?php if ( ! empty( $args['row']['class'] ) ) {
682
									echo esc_attr( $args['row']['class'] );
683
								} ?>',
684
							},
685
							el(
686
								'div',
687
								{
688
									className: 'col pr-2',
689
								},
690
					<?php
691
					if ( false ){
692
					?></script><?php }
693
			} elseif ( ! empty( $args['row']['close'] ) ) {
694
			if ( false ){
695
				?>
696
				<script><?php }?>
697
					el(
698
						'div',
699
						{
700
							className: 'col pl-0',
701
						},
702
					<?php
703
					if ( false ){
704
					?></script><?php }
705
			} else {
706
			if ( false ){
707
				?>
708
				<script><?php }?>
709
					el(
710
						'div',
711
						{
712
							className: 'col pl-0 pr-2',
713
						},
714
					<?php
715
					if ( false ){
716
					?></script><?php }
717
			}
718
		}
719
	}
720
721
	/**
722
	 * Replace block attributes placeholders with the proper naming.
723
	 *
724
	 * @param $string
725
	 *
726
	 * @return mixed
727
	 */
728
	public function block_props_replace( $string, $no_wrap = false ) {
729
730
		if ( $no_wrap ) {
731
			$string = str_replace( array( "[%", "%]" ), array( "props.attributes.", "" ), $string );
732
		} else {
733
			$string = str_replace( array( "[%", "%]" ), array( "'+props.attributes.", "+'" ), $string );
734
		}
735
736
		return $string;
737
	}
738
739
	public function build_block_arguments( $key, $args ) {
740
		$custom_attributes = ! empty( $args['custom_attributes'] ) ? $this->sd->array_to_attributes( $args['custom_attributes'] ) : '';
741
		$options           = '';
742
		$key               = sanitize_key( $key );
743
		$extra             = "key: '$key',";
744
745
		// `content` is a protected and Gutenberg special argument
746
		if ( $key == 'content' ) {
747
			return;
748
		}
749
750
		// icon
751
		$icon = '';
752
		if ( ! empty( $args['icon'] ) ) {
753
			$icon .= "el('div', {";
754
			$icon .= "dangerouslySetInnerHTML: {__html: '" . $this->sd->get_widget_icon( esc_attr( $args['icon'] ) ) . "'},";
0 ignored issues
show
Bug introduced by
Are you sure $this->sd->get_widget_ic...sc_attr($args['icon'])) of type array can be used in concatenation? ( Ignorable by Annotation )

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

754
			$icon .= "dangerouslySetInnerHTML: {__html: '" . /** @scrutinizer ignore-type */ $this->sd->get_widget_icon( esc_attr( $args['icon'] ) ) . "'},";
Loading history...
755
			$icon .= "className: 'text-center',";
756
			$icon .= "title: '" . addslashes( $args['title'] ) . "',";
757
			$icon .= "}),";
758
			// blank title as its added to the icon.
759
			$args['title'] = '';
760
		}
761
762
		// require advanced
763
		$require_advanced = ! empty( $args['advanced'] ) ? "props.attributes.show_advanced && " : "";
764
765
		// element require
766
		$element_require  = ! empty( $args['element_require'] ) ? $this->block_props_replace( $args['element_require'], true ) . " && " : "";
767
		$onchange         = "props.setAttributes({ $key: $key } )";
768
		$onchangecomplete = "";
769
		$value            = "props.attributes.$key";
770
		$text_type        = array( 'text', 'password', 'number', 'email', 'tel', 'url', 'colorx' );
771
		if ( in_array( $args['type'], $text_type ) ) {
772
			$type = 'TextControl';
773
			// Save numbers as numbers and not strings
774
			if ( $args['type'] == 'number' ) {
775
				$onchange = "props.setAttributes({ $key: Number($key) } )";
776
			}
777
		} elseif ( $args['type'] == 'color' ) {
778
			$type     = 'ColorPicker';
779
			$onchange = "";
780
			$extra .= "color: $value,";
781
			if ( ! empty( $args['disable_alpha'] ) ) {
782
				$extra .= "disableAlpha: true,";
783
			}
784
			$onchangecomplete = "onChangeComplete: function($key) {
785
			value =  $key.rgb.a && $key.rgb.a < 1 ? \"rgba(\"+$key.rgb.r+\",\"+$key.rgb.g+\",\"+$key.rgb.b+\",\"+$key.rgb.a+\")\" : $key.hex;
786
                        props.setAttributes({
787
                            $key: value
788
                        });
789
                    },";
790
		} elseif ( $args['type'] == 'checkbox' ) {
791
			$type = 'CheckboxControl';
792
			$extra .= "checked: props.attributes.$key,";
793
			$onchange = "props.setAttributes({ $key: ! props.attributes.$key } )";
794
		} elseif ( $args['type'] == 'textarea' ) {
795
			$type = 'TextareaControl';
796
		} elseif ( $args['type'] == 'select' || $args['type'] == 'multiselect' ) {
797
			$type = 'SelectControl';
798
			if ( $args['name'] == 'category' && ! empty( $args['post_type_linked'] ) ) {
799
				$options .= "options: taxonomies_" . str_replace( "-", "_", $this->sd->base_id . '_' . $this->sd->get_number() ) . ",";
800
			} elseif ( $args['name'] == 'sort_by' && ! empty( $args['post_type_linked'] ) ) {
801
				$options .= "options: sort_by_" . str_replace( "-", "_", $this->sd->base_id . '_' . $this->sd->get_number() ) . ",";
802
			} else {
803
				if ( ! empty( $args['options'] ) ) {
804
					$options .= "options: [";
805
					foreach ( $args['options'] as $option_val => $option_label ) {
806
						$options .= "{ value: '" . esc_attr( $option_val ) . "', label: '" . addslashes( $option_label ) . "' },";
807
					}
808
					$options .= "],";
809
				}
810
			}
811
			if ( isset( $args['multiple'] ) && $args['multiple'] ) { //@todo multiselect does not work at the moment: https://github.com/WordPress/gutenberg/issues/5550
812
				$extra .= ' multiple: true, ';
813
			}
814
		} elseif ( $args['type'] == 'alignment' ) {
815
			$type = 'AlignmentToolbar'; // @todo this does not seem to work but cant find a example
816
		} elseif ( $args['type'] == 'margins' ) {
817
		} else {
818
			return;// if we have not implemented the control then don't break the JS.
819
		}
820
821
		// color input does not show the labels so we add them
822
		if ( $args['type'] == 'color' ) {
823
			// add show only if advanced
824
			echo $require_advanced;
825
			// add setting require if defined
826
			echo $element_require;
827
			echo "el('div', {style: {'marginBottom': '8px'}}, '" . addslashes( $args['title'] ) . "'),";
828
		}
829
830
		// add show only if advanced
831
		echo $require_advanced;
832
		// add setting require if defined
833
		echo $element_require;
834
835
		// icon
836
		echo $icon;
837
		?>
838
		el( wp.components.<?php echo $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...
839
		label: '<?php echo addslashes( $args['title'] ); ?>',
840
		help: '<?php if ( isset( $args['desc'] ) ) {
841
			echo addslashes( $args['desc'] );
842
		} ?>',
843
		value: <?php echo $value; ?>,
844
		<?php if ( $type == 'TextControl' && $args['type'] != 'text' ) {
845
			echo "type: '" . addslashes( $args['type'] ) . "',";
846
		} ?>
847
		<?php if ( ! empty( $args['placeholder'] ) ) {
848
			echo "placeholder: '" . addslashes( $args['placeholder'] ) . "',";
849
		}
850
		echo $options;
851
		echo $extra;
852
		echo $custom_attributes;
853
		echo $onchangecomplete . "\n"; ?>
854
		onChange: function ( <?php echo $key; ?> ) {<?php echo $onchange; ?>}
855
		} ),
856
		<?php
857
	}
858
859
	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

859
	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...
860
		if ( ! empty( $args['row'] ) ) {
861
			// maybe close
862
			if ( ! empty( $args['row']['close'] ) ) {
863
				echo "))";
864
			}
865
			echo "),";
866
		}
867
	}
868
869
	/**
870
	 * A self looping function to create the output for JS block elements.
871
	 *
872
	 * This is what is output in the WP Editor visual view.
873
	 *
874
	 * @param $args
875
	 */
876
	public function block_element( $args ) {
877
878
		// Make sure we have args.
879
		if ( ! empty( $args ) ) {
880
881
			// For each argument...
882
			foreach ( $args as $element => $new_args ) {
883
884
				// Check if its an element.
885
				if ( is_array( $new_args ) ) {
886
					if ( isset( $new_args['element'] ) ) {
887
						if ( isset( $new_args['element_require'] ) ) {
888
							echo str_replace( array(
889
									"'+",
890
									"+'"
891
								), '', $this->block_props_replace( $new_args['element_require'] ) ) . " &&  ";
892
							unset( $new_args['element_require'] );
893
						}
894
895
						echo "\n el( '" . $new_args['element'] . "', {";
896
897
						// get the attributes
898
						foreach ( $new_args as $new_key => $new_value ) {
899
							if ( $new_key == 'element' || $new_key == 'content' || $new_key == 'element_require' || $new_key == 'element_repeat' || is_array( $new_value ) ) {
900
								// do nothing
901
							} else {
902
								echo $this->block_element( array( $new_key => $new_value ) );
903
							}
904
						}
905
906
						echo "key: '$element'},";// end attributes
907
908
						// get the content
909
						$first_item = 0;
910
						foreach ( $new_args as $new_key => $new_value ) {
911
							if ( $new_key === 'content' || is_array( $new_value ) ) {
912
								if ( $new_key === 'content' ) {
913
									echo "'" . $this->block_props_replace( wp_slash( $new_value ) ) . "'";
914
								}
915
916
								if ( is_array( $new_value ) ) {
917
									if ( isset( $new_value['element_require'] ) ) {
918
										echo str_replace( array(
919
												"'+",
920
												"+'"
921
											), '', $this->block_props_replace( $new_value['element_require'] ) ) . " &&  ";
922
										unset( $new_value['element_require'] );
923
									}
924
925
									if ( isset( $new_value['element_repeat'] ) ) {
926
										$x = 1;
927
										while ( $x <= absint( $new_value['element_repeat'] ) ) {
928
											$this->block_element( array( '' => $new_value ) );
929
											$x ++;
930
										}
931
									} else {
932
										$this->block_element( array( '' => $new_value ) );
933
									}
934
								}
935
								$first_item ++;
936
							}
937
						}
938
						echo ")";// end content
939
						echo ", \n";
940
					}
941
942
					// Or an attribute.
943
				} else {
944
					if ( substr( $element, 0, 3 ) === 'if_' ) {
945
						echo str_replace( 'if_', '', $element ) . ": " . $this->block_props_replace( $new_args, true ) . ",";
946
					} elseif ( $element == 'style' ) {
947
						echo $element . ": " . $this->block_props_replace( $new_args ) . ",";
948
					} else {
949
						echo $element . ": '" . $this->block_props_replace( $new_args ) . "',";
950
					}
951
				}
952
			}
953
954
		}
955
	}
956
957
	/**
958
	 * Enqueue CSS assets in the editor if defined
959
	 */
960
	public function enqueue_editor_assets() {
961
		if ( isset( $this->sd->options['block-editor-style'] ) ) {
962
			echo "<link rel='stylesheet' id='glossary-shortcode' href='" . $this->sd->options['block-editor-style'] . "'/>";
963
		}
964
	}
965
966
}
967