PluginProbe
Gutenberg / 23.3.0
Gutenberg v23.3.0
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.3.0, at lib/block-supports/block-visibility.php

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