PluginProbe
Gutenberg / 23.5.3
Gutenberg v23.5.3
23.9.1 23.9.0 23.8.0 23.7.2 23.7.1 23.7.0 23.6.1 23.6.2 23.6.0 23.5.3 23.5.2 23.5.1 23.5.0 23.4.0 23.3.2 23.3.1 23.3.0 23.2.0 23.2.1 23.2.2 23.1.1 23.1.0 23.0.1 12.6.0 7.4.0 All 402 releases
gutenberg / lib / block-supports / block-visibility.php

block-visibility.php in Gutenberg 23.5.3, at lib/block-supports/block-visibility.php

170 lines 5.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Block visibility block support flag.
4 *
5 * @package gutenberg
6 */
7
8 /**
9 * Render nothing if the block is hidden, or add viewport visibility styles.
10 *
11 * @param string $block_content Rendered block content.
12 * @param array $block Block object.
13 * @return string Filtered block content.
14 */
15 function gutenberg_render_block_visibility_support( $block_content, $block ) {
16 $block_type = WP_Block_Type_Registry::get_instance()->get_registered( $block['blockName'] );
17
18 if ( ! $block_type ) {
19 return $block_content;
20 }
21
22 $block_visibility = $block['attrs']['metadata']['blockVisibility'] ?? null;
23
24 // Hide the block whenever the value is boolean false, regardless of the
25 // block's current visibility support. This prevents blocks that previously
26 // supported visibility from unintentionally appearing on the front end
27 // after their support was disabled.
28 if ( false === $block_visibility ) {
29 return '';
30 }
31
32 if ( ! block_has_support( $block_type, 'visibility', true ) ) {
33 return $block_content;
34 }
35
36 if ( is_array( $block_visibility ) && ! empty( $block_visibility ) ) {
37 // Get viewport configuration from nested structure.
38 $viewport_config = $block_visibility['viewport'] ?? null;
39
40 // If no viewport config, return unchanged.
41 if ( ! is_array( $viewport_config ) || empty( $viewport_config ) ) {
42 return $block_content;
43 }
44
45 /*
46 * Viewport size definitions are in several places in WordPress packages.
47 * The following are taken from: https://github.com/WordPress/gutenberg/blob/trunk/packages/base-styles/_breakpoints.scss
48 * The array is in a future, potential JSON format, and will be centralized
49 * as the feature is developed.
50 *
51 * Viewport sizes as array items are defined sequentially. The first item's size is the max value.
52 * Each subsequent item starts after the previous size (using > operator), and its size is the max.
53 * The last item starts after the previous size (using > operator), and it has no max.
54 */
55 $viewport_sizes = array(
56 array(
57 'name' => 'Mobile',
58 'slug' => 'mobile',
59 'size' => '480px',
60 ),
61 array(
62 'name' => 'Tablet',
63 'slug' => 'tablet',
64 'size' => '782px',
65 ),
66 array(
67 'name' => 'Desktop',
68 'slug' => 'desktop',
69 /*
70 * Note: the last item in the $viewport_sizes array does not technically require a 'size' key,
71 * as the last item's media query is calculated using `width > previous size`.
72 * The last item is present for validating the attribute values, and in order to indicate
73 * that this is the final viewport size, and to calculate the previous media query accordingly.
74 */
75 ),
76 );
77
78 /*
79 * Build media queries from viewport size definitions using the CSS range syntax.
80 * Could be absorbed into the style engine,
81 * as well as classname building, and declaration of the display property, if required.
82 */
83 $viewport_media_queries = array();
84 $previous_size = null;
85 foreach ( $viewport_sizes as $index => $viewport_size ) {
86 // First item: width <= size.
87 if ( 0 === $index ) {
88 $viewport_media_queries[ $viewport_size['slug'] ] = "@media (width <= {$viewport_size['size']})";
89 } elseif ( count( $viewport_sizes ) - 1 === $index && $previous_size ) {
90 // Last item: width > previous size.
91 $viewport_media_queries[ $viewport_size['slug'] ] = "@media (width > $previous_size)";
92 } else {
93 // Middle items: previous size < width <= size.
94 $viewport_media_queries[ $viewport_size['slug'] ] = "@media ({$previous_size} < width <= {$viewport_size['size']})";
95 }
96
97 $previous_size = $viewport_size['size'] ?? null;
98 }
99
100 $hidden_on = array();
101
102 // Collect which viewport the block is hidden on (only known viewport sizes).
103 foreach ( $viewport_config as $viewport_config_size => $is_visible ) {
104 if ( false === $is_visible && isset( $viewport_media_queries[ $viewport_config_size ] ) ) {
105 $hidden_on[] = $viewport_config_size;
106 }
107 }
108
109 // If no viewport sizes have visibility set to false, return unchanged.
110 if ( empty( $hidden_on ) ) {
111 return $block_content;
112 }
113
114 // Maintain consistent order of viewport sizes for class name generation.
115 sort( $hidden_on );
116
117 $css_rules = array();
118 $class_names = array();
119
120 foreach ( $hidden_on as $hidden_viewport_size ) {
121 /*
122 * If these values ever become user-defined,
123 * they should be sanitized and kebab-cased.
124 */
125 $visibility_class = 'wp-block-hidden-' . $hidden_viewport_size;
126 $class_names[] = $visibility_class;
127 $css_rules[] = array(
128 'selector' => '.' . $visibility_class,
129 'declarations' => array(
130 'display' => 'none !important',
131 ),
132 'rules_group' => $viewport_media_queries[ $hidden_viewport_size ],
133 );
134 }
135
136 gutenberg_style_engine_get_stylesheet_from_css_rules(
137 $css_rules,
138 array(
139 'context' => 'block-supports',
140 'prettify' => false,
141 )
142 );
143
144 if ( ! empty( $block_content ) ) {
145 $processor = new WP_HTML_Tag_Processor( $block_content );
146 if ( $processor->next_tag() ) {
147 $processor->add_class( implode( ' ', $class_names ) );
148
149 /*
150 * Set all IMG tags to be `fetchpriority=auto` so that wp_get_loading_optimization_attributes() won't add
151 * `fetchpriority=high` or increment the media count to affect whether subsequent IMG tags get `loading=lazy`.
152 */
153 do {
154 if ( 'IMG' === $processor->get_tag() ) {
155 $processor->set_attribute( 'fetchpriority', 'auto' );
156 }
157 } while ( $processor->next_tag() );
158 $block_content = $processor->get_updated_html();
159 }
160 }
161 }
162
163 return $block_content;
164 }
165
166 if ( function_exists( 'wp_render_block_visibility_support' ) ) {
167 remove_filter( 'render_block', 'wp_render_block_visibility_support' );
168 }
169 add_filter( 'render_block', 'gutenberg_render_block_visibility_support', 10, 2 );
170