PluginProbe ʕ •ᴥ•ʔ
GenerateBlocks / 1.5.3
GenerateBlocks v1.5.3
trunk 1.0 1.0.1 1.0.2 1.1.0 1.1.1 1.1.2 1.2.0 1.3.0 1.3.1 1.3.2 1.3.3 1.3.4 1.3.5 1.4.0 1.4.1 1.4.2 1.4.3 1.4.4 1.5.0 1.5.1 1.5.2 1.5.3 1.5.4 1.6.0 1.7.0 1.7.1 1.7.2 1.7.3 1.8.0 1.8.1 1.8.2 1.8.3 1.9.0 1.9.1 2.0.0 2.0.1 2.0.2 2.1.0 2.1.1 2.1.2 2.2.0 2.2.1 2.3.0
generateblocks / includes / class-render-blocks.php
generateblocks / includes Last commit date
class-do-css.php 4 years ago class-dynamic-content.php 4 years ago class-enqueue-css.php 4 years ago class-legacy-attributes.php 4 years ago class-plugin-update.php 5 years ago class-query-loop.php 4 years ago class-render-blocks.php 4 years ago class-rest.php 4 years ago class-settings.php 4 years ago dashboard.php 4 years ago defaults.php 4 years ago functions.php 4 years ago general.php 4 years ago generate-css.php 4 years ago
class-render-blocks.php
861 lines
1 <?php
2 /**
3 * This file handles the dynamic parts of our blocks.
4 *
5 * @package GenerateBlocks
6 */
7
8 if ( ! defined( 'ABSPATH' ) ) {
9 exit; // Exit if accessed directly.
10 }
11
12 /**
13 * Render the dynamic aspects of our blocks.
14 *
15 * @since 1.2.0
16 */
17 class GenerateBlocks_Render_Block {
18 /**
19 * Instance.
20 *
21 * @access private
22 * @var object Instance
23 * @since 1.2.0
24 */
25 private static $instance;
26
27 /**
28 * Initiator.
29 *
30 * @since 1.2.0
31 * @return object initialized object of class.
32 */
33 public static function get_instance() {
34 if ( ! isset( self::$instance ) ) {
35 self::$instance = new self();
36 }
37
38 return self::$instance;
39 }
40
41 /**
42 * Constructor.
43 */
44 public function __construct() {
45 add_action( 'init', array( $this, 'register_blocks' ) );
46
47 if ( version_compare( $GLOBALS['wp_version'], '5.9', '>' ) ) {
48 add_filter( 'render_block', array( $this, 'filter_rendered_blocks' ), 10, 3 );
49 }
50 }
51
52 /**
53 * Register our dynamic blocks.
54 *
55 * @since 1.2.0
56 */
57 public function register_blocks() {
58 register_block_type(
59 'generateblocks/container',
60 array(
61 'title' => esc_html__( 'Container', 'generateblocks' ),
62 'render_callback' => array( $this, 'do_container_block' ),
63 'editor_script' => 'generateblocks',
64 'editor_style' => 'generateblocks',
65 )
66 );
67
68 register_block_type(
69 'generateblocks/grid',
70 array(
71 'title' => esc_html__( 'Grid', 'generateblocks' ),
72 'render_callback' => array( $this, 'do_grid_block' ),
73 'uses_context' => array(
74 'generateblocks/query',
75 'generateblocks/queryId',
76 'generateblocks/inheritQuery',
77 ),
78 )
79 );
80
81 register_block_type(
82 'generateblocks/query-loop',
83 array(
84 'title' => esc_html__( 'Query loop', 'generateblocks' ),
85 'render_callback' => array( $this, 'do_grid_block' ),
86 'provides_context' => array(
87 'generateblocks/query' => 'query',
88 'generateblocks/queryId' => 'uniqueId',
89 'generateblocks/inheritQuery' => 'inheritQuery',
90 ),
91 )
92 );
93
94 register_block_type(
95 'generateblocks/button-container',
96 array(
97 'title' => esc_html__( 'Buttons', 'generateblocks' ),
98 'render_callback' => array( $this, 'do_button_container' ),
99 )
100 );
101
102 register_block_type(
103 'generateblocks/headline',
104 array(
105 'title' => esc_html__( 'Headline', 'generateblocks' ),
106 'render_callback' => array( $this, 'do_headline_block' ),
107 )
108 );
109
110 register_block_type(
111 'generateblocks/button',
112 array(
113 'title' => esc_html__( 'Button', 'generateblocks' ),
114 'render_callback' => array( $this, 'do_button_block' ),
115 'uses_context' => array(
116 'generateblocks/query',
117 'generateblocks/queryId',
118 'generateblocks/inheritQuery',
119 ),
120 )
121 );
122
123 register_block_type(
124 GENERATEBLOCKS_DIR . 'dist/blocks/image',
125 array(
126 'title' => esc_html__( 'Image', 'generateblocks' ),
127 'render_callback' => array( $this, 'do_image_block' ),
128 'uses_context' => array(
129 'generateblocks/query',
130 'generateblocks/queryId',
131 'postType',
132 'postId',
133 ),
134 )
135 );
136 }
137
138 /**
139 * Output the dynamic aspects of our Container block.
140 *
141 * @since 1.2.0
142 * @param array $attributes The block attributes.
143 * @param string $content The inner blocks.
144 * @param object $block The block data.
145 */
146 public function do_container_block( $attributes, $content, $block ) {
147 if ( ! isset( $attributes['isDynamic'] ) || ! $attributes['isDynamic'] ) {
148 return $content;
149 }
150
151 $defaults = generateblocks_get_block_defaults();
152
153 $settings = wp_parse_args(
154 $attributes,
155 $defaults['container']
156 );
157
158 $output = '';
159
160 if ( $settings['isGrid'] ) {
161 $gridItemClassNames = array(
162 'gb-grid-column',
163 'gb-grid-column-' . $settings['uniqueId'],
164 );
165
166 $output .= sprintf(
167 '<div %s>',
168 generateblocks_attr(
169 'grid-item',
170 array(
171 'class' => implode( ' ', $gridItemClassNames ),
172 ),
173 $settings,
174 $block
175 )
176 );
177 }
178
179 $classNames = array(
180 'gb-container',
181 'gb-container-' . $settings['uniqueId'],
182 );
183
184 if ( ! empty( $settings['className'] ) ) {
185 $classNames[] = $settings['className'];
186 }
187
188 if ( ! $settings['isGrid'] && ! empty( $settings['align'] ) ) {
189 $classNames[] = 'align' . $settings['align'];
190 }
191
192 // Pass the dynamic url to our URL attribute.
193 if ( isset( $settings['url'] ) ) {
194 if ( $settings['useDynamicData'] && '' !== $settings['dynamicLinkType'] ) {
195 $attributes['url'] = GenerateBlocks_Dynamic_Content::get_dynamic_url( $settings, $block );
196 }
197 }
198
199 $tagName = apply_filters(
200 'generateblocks_container_tagname',
201 $settings['tagName'],
202 $attributes,
203 $block
204 );
205
206 $allowedTagNames = apply_filters(
207 'generateblocks_container_allowed_tagnames',
208 array(
209 'div',
210 'section',
211 'header',
212 'footer',
213 'aside',
214 'a',
215 ),
216 $attributes,
217 $block
218 );
219
220 if ( ! in_array( $tagName, $allowedTagNames ) ) {
221 $tagName = 'div';
222 }
223
224 $output .= sprintf(
225 '<%1$s %2$s>',
226 $tagName,
227 generateblocks_attr(
228 'container',
229 array(
230 'id' => isset( $settings['anchor'] ) ? $settings['anchor'] : null,
231 'class' => implode( ' ', $classNames ),
232 ),
233 $settings,
234 $block
235 )
236 );
237
238 $output = apply_filters(
239 'generateblocks_after_container_open',
240 $output,
241 $attributes,
242 $block
243 );
244
245 $output .= '<div class="gb-inside-container">';
246
247 $output = apply_filters(
248 'generateblocks_inside_container',
249 $output,
250 $attributes,
251 $block
252 );
253
254 $output .= $content;
255 $output .= '</div>';
256
257 $output = apply_filters(
258 'generateblocks_before_container_close',
259 $output,
260 $attributes,
261 $block
262 );
263
264 $output .= sprintf(
265 '</%s>',
266 $tagName
267 );
268
269 if ( $settings['isGrid'] ) {
270 $output .= '</div>';
271 }
272
273 return $output;
274 }
275
276 /**
277 * Output the dynamic aspects of our Grid block.
278 *
279 * @since 1.2.0
280 * @param array $attributes The block attributes.
281 * @param string $content The inner blocks.
282 * @param object $block The block data.
283 */
284 public function do_grid_block( $attributes, $content, $block ) {
285 if ( ! isset( $attributes['isDynamic'] ) || ! $attributes['isDynamic'] ) {
286 return $content;
287 }
288
289 $defaults = generateblocks_get_block_defaults();
290
291 $settings = wp_parse_args(
292 $attributes,
293 $defaults['gridContainer']
294 );
295
296 $classNames = array(
297 'gb-grid-wrapper',
298 'gb-grid-wrapper-' . $settings['uniqueId'],
299 );
300
301 if ( ! empty( $settings['className'] ) ) {
302 $classNames[] = $settings['className'];
303 }
304
305 $output = sprintf(
306 '<div %s>',
307 generateblocks_attr(
308 'grid-wrapper',
309 array(
310 'id' => isset( $settings['anchor'] ) ? $settings['anchor'] : null,
311 'class' => implode( ' ', $classNames ),
312 ),
313 $settings,
314 $block
315 )
316 );
317
318 if ( empty( $attributes['isQueryLoop'] ) ) {
319 $output .= $content;
320 } else {
321 $output .= $this->do_post_template( $attributes, $content, $block );
322 }
323
324 $output .= '</div>';
325
326 return $output;
327 }
328
329 /**
330 * Output the dynamic aspects of our Button Container block.
331 *
332 * @since 1.2.0
333 * @param array $attributes The block attributes.
334 * @param string $content The inner blocks.
335 * @param object $block The block data.
336 */
337 public function do_button_container( $attributes, $content, $block ) {
338 if ( ! isset( $attributes['isDynamic'] ) || ! $attributes['isDynamic'] ) {
339 return $content;
340 }
341
342 if ( isset( $block->parsed_block['innerBlocks'] ) ) {
343 $button_count = apply_filters(
344 'generateblocks_button_count',
345 count( (array) $block->parsed_block['innerBlocks'] ),
346 $attributes,
347 $block
348 );
349
350 if ( 0 === $button_count ) {
351 return;
352 }
353 }
354
355 $defaults = generateblocks_get_block_defaults();
356
357 $settings = wp_parse_args(
358 $attributes,
359 $defaults['buttonContainer']
360 );
361
362 $classNames = array(
363 'gb-button-wrapper',
364 'gb-button-wrapper-' . $settings['uniqueId'],
365 );
366
367 if ( ! empty( $settings['className'] ) ) {
368 $classNames[] = $settings['className'];
369 }
370
371 $output = sprintf(
372 '<div %s>',
373 generateblocks_attr(
374 'button-container',
375 array(
376 'id' => isset( $settings['anchor'] ) ? $settings['anchor'] : null,
377 'class' => implode( ' ', $classNames ),
378 ),
379 $settings,
380 $block
381 )
382 );
383
384 $output .= $content;
385
386 $output .= '</div>';
387
388 return $output;
389 }
390
391 /**
392 * Output the query.
393 *
394 * @param array $attributes The block attributes.
395 * @param string $content The inner blocks.
396 * @param WP_Block $block Block instance.
397 */
398 public function do_post_template( $attributes, $content, $block ) {
399 $page_key = isset( $block->context['generateblocks/queryId'] ) ? 'query-' . $block->context['generateblocks/queryId'] . '-page' : 'query-page';
400 $page = empty( $_GET[ $page_key ] ) ? 1 : (int) $_GET[ $page_key ]; // phpcs:ignore -- No data processing happening.
401 $query_args = GenerateBlocks_Query_Loop::get_query_args( $block, $page );
402
403 // Override the custom query with the global query if needed.
404 $use_global_query = ( isset( $block->context['generateblocks/inheritQuery'] ) && $block->context['generateblocks/inheritQuery'] );
405
406 if ( $use_global_query ) {
407 global $wp_query;
408
409 if ( $wp_query && isset( $wp_query->query_vars ) && is_array( $wp_query->query_vars ) ) {
410 // Unset `offset` because if is set, $wp_query overrides/ignores the paged parameter and breaks pagination.
411 unset( $query_args['offset'] );
412 $query_args = wp_parse_args( $wp_query->query_vars, $query_args );
413
414 if ( empty( $query_args['post_type'] ) && is_singular() ) {
415 $query_args['post_type'] = get_post_type( get_the_ID() );
416 }
417 }
418 }
419
420 $query_args = apply_filters(
421 'generateblocks_query_loop_args',
422 $query_args,
423 $attributes,
424 $block
425 );
426
427 $the_query = new WP_Query( $query_args );
428
429 $content = '';
430 if ( $the_query->have_posts() ) {
431 while ( $the_query->have_posts() ) {
432 $the_query->the_post();
433
434 $block_content = (
435 new WP_Block(
436 $block->parsed_block,
437 array(
438 'postType' => get_post_type(),
439 'postId' => get_the_ID(),
440 )
441 )
442 )->render( array( 'dynamic' => false ) );
443
444 $content .= $block_content;
445 }
446 }
447
448 wp_reset_postdata();
449
450 return $content;
451 }
452
453 /**
454 * Wrapper function for our dynamic headlines.
455 *
456 * @since 1.5.0
457 * @param array $attributes The block attributes.
458 * @param string $content The dynamic text to display.
459 * @param WP_Block $block Block instance.
460 */
461 public static function do_headline_block( $attributes, $content, $block ) {
462 if ( ! isset( $attributes['useDynamicData'] ) || ! $attributes['useDynamicData'] ) {
463 return $content;
464 }
465
466 $allow_empty_content = false;
467
468 if ( empty( $attributes['dynamicContentType'] ) ) {
469 $dynamic_content = GenerateBlocks_Dynamic_Content::get_static_content( $content );
470
471 if ( ! empty( $attributes['hasIcon'] ) && ! empty( $attributes['removeText'] ) ) {
472 // Allow icon-only items to continue.
473 $allow_empty_content = true;
474 }
475 } else {
476 $dynamic_content = GenerateBlocks_Dynamic_Content::get_content( $attributes, $block );
477 }
478
479 if ( ! $dynamic_content && '0' !== $dynamic_content && ! $allow_empty_content ) {
480 return '';
481 }
482
483 $defaults = generateblocks_get_block_defaults();
484
485 $settings = wp_parse_args(
486 $attributes,
487 $defaults['headline']
488 );
489
490 $classNames = array(
491 'gb-headline',
492 'gb-headline-' . $settings['uniqueId'],
493 );
494
495 if ( ! empty( $settings['className'] ) ) {
496 $classNames[] = $settings['className'];
497 }
498
499 if ( empty( $settings['icon'] ) ) {
500 $classNames[] = 'gb-headline-text';
501 }
502
503 $tagName = apply_filters(
504 'generateblocks_dynamic_headline_tagname',
505 $settings['element'],
506 $attributes,
507 $block
508 );
509
510 $allowedTagNames = apply_filters(
511 'generateblocks_dynamic_headline_allowed_tagnames',
512 array(
513 'h1',
514 'h2',
515 'h3',
516 'h4',
517 'h5',
518 'h6',
519 'div',
520 'p',
521 'figcaption',
522 ),
523 $attributes,
524 $block
525 );
526
527 if ( ! in_array( $tagName, $allowedTagNames ) ) {
528 $tagName = 'div';
529 }
530
531 $output = sprintf(
532 '<%1$s %2$s>',
533 $tagName,
534 generateblocks_attr(
535 'dynamic-headline',
536 array(
537 'id' => isset( $settings['anchor'] ) ? $settings['anchor'] : null,
538 'class' => implode( ' ', $classNames ),
539 ),
540 $settings,
541 $block
542 )
543 );
544
545 $icon_html = '';
546
547 // Extract our icon from the static HTML.
548 if ( $settings['hasIcon'] ) {
549 $icon_html = GenerateBlocks_Dynamic_Content::get_icon_html( $content );
550
551 if ( $icon_html ) {
552 $output .= $icon_html;
553 $output .= '<span class="gb-headline-text">';
554 }
555 }
556
557 $dynamic_link = GenerateBlocks_Dynamic_Content::get_dynamic_url( $attributes, $block );
558
559 if ( $dynamic_link ) {
560 $dynamic_content = sprintf(
561 '<a href="%s">%s</a>',
562 $dynamic_link,
563 $dynamic_content
564 );
565 }
566
567 $output .= $dynamic_content;
568
569 if ( $icon_html ) {
570 $output .= '</span>';
571 }
572
573 $output .= sprintf(
574 '</%s>',
575 $tagName
576 );
577
578 return $output;
579 }
580
581 /**
582 * Wrapper function for our dynamic buttons.
583 *
584 * @since 1.5.0
585 * @param array $attributes The block attributes.
586 * @param string $content The dynamic text to display.
587 * @param WP_Block $block Block instance.
588 */
589 public static function do_button_block( $attributes, $content, $block ) {
590 if ( ! isset( $attributes['useDynamicData'] ) || ! $attributes['useDynamicData'] ) {
591 return $content;
592 }
593
594 $allow_empty_content = false;
595
596 // Add an attribute showing we're working with the Button block.
597 $attributes['isButton'] = true;
598
599 if ( empty( $attributes['dynamicContentType'] ) ) {
600 $dynamic_content = GenerateBlocks_Dynamic_Content::get_static_content( $content );
601
602 if ( ! empty( $attributes['hasIcon'] ) && ! empty( $attributes['removeText'] ) ) {
603 // Allow icon-only items to continue.
604 $allow_empty_content = true;
605 }
606 } else {
607 $dynamic_content = GenerateBlocks_Dynamic_Content::get_content( $attributes, $block );
608 }
609
610 if ( ! $dynamic_content && '0' !== $dynamic_content && ! $allow_empty_content ) {
611 return '';
612 }
613
614 $defaults = generateblocks_get_block_defaults();
615
616 $settings = wp_parse_args(
617 $attributes,
618 $defaults['button']
619 );
620
621 $classNames = array(
622 'gb-button',
623 'gb-button-' . $settings['uniqueId'],
624 );
625
626 if ( ! empty( $settings['className'] ) ) {
627 $classNames[] = $settings['className'];
628 }
629
630 if ( empty( $settings['icon'] ) ) {
631 $classNames[] = 'gb-button-text';
632 }
633
634 $relAttributes = array();
635
636 if ( ! empty( $settings['relNoFollow'] ) ) {
637 $relAttributes[] = 'nofollow';
638 }
639
640 if ( ! empty( $settings['target'] ) ) {
641 $relAttributes[] = 'noopener';
642 $relAttributes[] = 'noreferrer';
643 }
644
645 if ( ! empty( $settings['relSponsored'] ) ) {
646 $relAttributes[] = 'sponsored';
647 }
648
649 $icon_html = '';
650
651 // Extract our icon from the static HTML.
652 if ( $settings['hasIcon'] ) {
653 $icon_html = GenerateBlocks_Dynamic_Content::get_icon_html( $content );
654 }
655
656 $output = '';
657
658 foreach ( (array) $dynamic_content as $content ) {
659 $tagName = 'span';
660
661 $dynamic_link = GenerateBlocks_Dynamic_Content::get_dynamic_url( $attributes, $block );
662
663 if ( isset( $content['attributes']['href'] ) || $dynamic_link ) {
664 $tagName = 'a';
665 }
666
667 $button_attributes = array(
668 'id' => isset( $settings['anchor'] ) ? $settings['anchor'] : null,
669 'class' => implode( ' ', $classNames ),
670 'href' => 'a' === $tagName ? $dynamic_link : null,
671 'rel' => ! empty( $relAttributes ) ? implode( ' ', $relAttributes ) : null,
672 'target' => ! empty( $settings['target'] ) ? '_blank' : null,
673 );
674
675 if ( isset( $content['attributes'] ) ) {
676 foreach ( $content['attributes'] as $attribute => $value ) {
677 if ( 'class' === $attribute ) {
678 $button_attributes[ $attribute ] .= ' ' . $value;
679 } else {
680 $button_attributes[ $attribute ] = $value;
681 }
682 }
683 }
684
685 $output .= sprintf(
686 '<%1$s %2$s>',
687 $tagName,
688 generateblocks_attr(
689 'dynamic-button',
690 $button_attributes,
691 $settings,
692 $block
693 )
694 );
695
696 if ( $icon_html ) {
697 if ( 'left' === $settings['iconLocation'] ) {
698 $output .= $icon_html;
699 }
700
701 $output .= '<span class="gb-button-text">';
702 }
703
704 if ( isset( $content['content'] ) ) {
705 $output .= $content['content'];
706 } else {
707 $output .= $content;
708 }
709
710 if ( $icon_html ) {
711 $output .= '</span>';
712
713 if ( 'right' === $settings['iconLocation'] ) {
714 $output .= $icon_html;
715 }
716 }
717
718 $output .= sprintf(
719 '</%s>',
720 $tagName
721 );
722 }
723
724 return $output;
725 }
726
727 /**
728 * Wrapper function for our image block.
729 *
730 * @since 1.5.0
731 * @param array $attributes The block attributes.
732 * @param string $content The dynamic text to display.
733 * @param WP_Block $block Block instance.
734 */
735 public static function do_image_block( $attributes, $content, $block ) {
736 if ( empty( $attributes['useDynamicData'] ) ) {
737 return generateblocks_filter_images( $content, $attributes );
738 }
739
740 $image = empty( $attributes['dynamicContentType'] )
741 ? generateblocks_filter_images( GenerateBlocks_Dynamic_Content::get_static_content( $content ), $attributes )
742 : GenerateBlocks_Dynamic_Content::get_dynamic_image( $attributes, $block );
743
744 if ( ! $image ) {
745 return '';
746 }
747
748 $defaults = generateblocks_get_block_defaults();
749
750 $settings = wp_parse_args(
751 $attributes,
752 $defaults['image']
753 );
754
755 $output = sprintf(
756 '<figure %s>',
757 generateblocks_attr(
758 'image-figure',
759 array(
760 'class' => implode(
761 ' ',
762 array(
763 'gb-block-image',
764 'gb-block-image-' . $settings['uniqueId'],
765 )
766 ),
767 ),
768 $settings,
769 $block
770 )
771 );
772
773 $dynamic_link = GenerateBlocks_Dynamic_Content::get_dynamic_url( $attributes, $block );
774
775 if ( $dynamic_link ) {
776 $relAttributes = array();
777
778 if ( ! empty( $settings['relNoFollow'] ) ) {
779 $relAttributes[] = 'nofollow';
780 }
781
782 if ( ! empty( $settings['openInNewWindow'] ) ) {
783 $relAttributes[] = 'noopener';
784 $relAttributes[] = 'noreferrer';
785 }
786
787 if ( ! empty( $settings['relSponsored'] ) ) {
788 $relAttributes[] = 'sponsored';
789 }
790
791 $dynamic_link_data = array(
792 'href' => $dynamic_link,
793 'rel' => ! empty( $relAttributes ) ? implode( ' ', $relAttributes ) : null,
794 'target' => ! empty( $settings['openInNewWindow'] ) ? '_blank' : null,
795 );
796
797 $dynamic_link_attributes = '';
798
799 foreach ( $dynamic_link_data as $attribute => $value ) {
800 $dynamic_link_attributes .= sprintf(
801 ' %s="%s"',
802 $attribute,
803 $value
804 );
805 }
806
807 $image = sprintf(
808 '<a %s>%s</a>',
809 trim( $dynamic_link_attributes ),
810 $image
811 );
812 }
813
814 $output .= $image;
815
816 if ( isset( $block->parsed_block['innerBlocks'][0]['attrs'] ) ) {
817 $image_id = GenerateBlocks_Dynamic_Content::get_dynamic_image_id( $attributes );
818 $block->parsed_block['innerBlocks'][0]['attrs']['dynamicImage'] = $image_id;
819
820 $caption = (
821 new WP_Block(
822 $block->parsed_block['innerBlocks'][0]
823 )
824 )->render( array( 'dynamic' => true ) );
825
826 if ( $caption ) {
827 $output .= $caption;
828 }
829 }
830
831 $output .= '</figure>';
832
833 return $output;
834 }
835
836 /**
837 * Filter existing rendered blocks.
838 *
839 * @since 1.5.0
840 * @param string $block_content The block content.
841 * @param array $block The block data.
842 * @param WP_Block $instance Block instance.
843 */
844 public function filter_rendered_blocks( $block_content, $block, $instance ) {
845 $attributes = isset( $block['attrs'] ) ? $block['attrs'] : null;
846
847 // Don't output if no dynamic link exists.
848 if ( isset( $attributes ) && ! empty( $attributes['dynamicLinkType'] ) && ! empty( $attributes['dynamicLinkRemoveIfEmpty'] ) ) {
849 $dynamic_link = GenerateBlocks_Dynamic_Content::get_dynamic_url( $attributes, $instance );
850
851 if ( ! $dynamic_link ) {
852 return '';
853 }
854 }
855
856 return $block_content;
857 }
858 }
859
860 GenerateBlocks_Render_Block::get_instance();
861