| [ Index ] |
PHP Cross Reference of WordPress Trunk (Updated Daily) |
[Summary view] [Print] [Text view]
1 <?php 2 /** 3 * Position block support flag. 4 * 5 * @package WordPress 6 * @since 6.2.0 7 */ 8 9 /** 10 * Registers the style block attribute for block types that support it. 11 * 12 * @since 6.2.0 13 * @access private 14 * 15 * @param WP_Block_Type $block_type Block Type. 16 */ 17 function wp_register_position_support( $block_type ) { 18 $has_position_support = block_has_support( $block_type, 'position', false ); 19 20 // Set up attributes and styles within that if needed. 21 if ( ! $block_type->attributes ) { 22 $block_type->attributes = array(); 23 } 24 25 if ( $has_position_support && ! array_key_exists( 'style', $block_type->attributes ) ) { 26 $block_type->attributes['style'] = array( 27 'type' => 'object', 28 ); 29 } 30 } 31 32 /** 33 * Returns the CSS rules for a position style configuration. 34 * 35 * @since 7.2.0 36 * 37 * @param string $selector CSS selector to scope the rules to. 38 * @param mixed $position Position style configuration. 39 * @param array $allowed_position_types Position types the theme supports. 40 * @return array CSS rules, or an empty array when the configuration is not allowed. 41 */ 42 function wp_get_position_support_styles( $selector, $position, $allowed_position_types ) { 43 $styles = array(); 44 45 if ( ! is_array( $position ) || ! is_string( $position['type'] ?? null ) ) { 46 return $styles; 47 } 48 49 $position_type = $position['type']; 50 51 if ( ! in_array( $position_type, $allowed_position_types, true ) ) { 52 return $styles; 53 } 54 55 $sides = array( 'top', 'right', 'bottom', 'left' ); 56 57 foreach ( $sides as $side ) { 58 $side_value = $position[ $side ] ?? null; 59 if ( null !== $side_value ) { 60 /* 61 * For fixed or sticky top positions, 62 * ensure the value includes an offset for the logged in admin bar. 63 */ 64 if ( 'top' === $side ) { 65 // Ensure 0 values can be used in `calc()` calculations. 66 if ( '0' === $side_value || 0 === $side_value ) { 67 $side_value = '0px'; 68 } 69 70 // Ensure current side value also factors in the height of the logged in admin bar. 71 $side_value = "calc($side_value + var(--wp-admin--admin-bar--position-offset, 0px))"; 72 } 73 74 $styles[] = array( 75 'selector' => $selector, 76 'declarations' => array( 77 $side => $side_value, 78 ), 79 ); 80 } 81 } 82 83 $styles[] = array( 84 'selector' => $selector, 85 'declarations' => array( 86 'position' => $position_type, 87 'z-index' => '10', 88 ), 89 ); 90 91 return $styles; 92 } 93 94 /** 95 * Renders position styles to the block wrapper. 96 * 97 * @since 6.2.0 98 * @since 7.2.0 Added support for viewport states. 99 * @access private 100 * 101 * @param string $block_content Rendered block content. 102 * @param array $block Block object. 103 * @return string Filtered block content. 104 */ 105 function wp_render_position_support( $block_content, $block ) { 106 $block_type = WP_Block_Type_Registry::get_instance()->get_registered( $block['blockName'] ); 107 $has_position_support = block_has_support( $block_type, 'position', false ); 108 $style_attribute = $block['attrs']['style'] ?? null; 109 110 if ( ! $has_position_support || ! is_array( $style_attribute ) ) { 111 return $block_content; 112 } 113 114 /* 115 * Position styles can exist in either the default state or a viewport state. 116 */ 117 $has_position_style = ! empty( $style_attribute['position'] ); 118 if ( ! $has_position_style ) { 119 foreach ( $style_attribute as $key => $style ) { 120 if ( 121 is_string( $key ) && 122 str_starts_with( $key, '@' ) && 123 is_array( $style ) && 124 ! empty( $style['position'] ) 125 ) { 126 $has_position_style = true; 127 break; 128 } 129 } 130 } 131 132 if ( ! $has_position_style ) { 133 return $block_content; 134 } 135 136 $global_settings = wp_get_global_settings(); 137 $theme_has_sticky_support = $global_settings['position']['sticky'] ?? false; 138 $theme_has_fixed_support = $global_settings['position']['fixed'] ?? false; 139 140 // Only allow output for position types that the theme supports. 141 $allowed_position_types = array(); 142 if ( true === $theme_has_sticky_support ) { 143 $allowed_position_types[] = 'sticky'; 144 } 145 if ( true === $theme_has_fixed_support ) { 146 $allowed_position_types[] = 'fixed'; 147 } 148 149 $viewport_settings = $global_settings['viewport'] ?? null; 150 $responsive_media_queries = WP_Theme_JSON::get_viewport_media_queries( $viewport_settings ); 151 $class_name = wp_unique_id( 'wp-container-' ); 152 $selector = ".$class_name"; 153 $position_styles = array(); 154 $wrapper_classes = array(); 155 $base_position = $style_attribute['position'] ?? null; 156 157 // Default viewport (base) position styles. 158 $base_styles = wp_get_position_support_styles( 159 $selector, 160 $base_position, 161 $allowed_position_types 162 ); 163 164 if ( ! empty( $base_styles ) ) { 165 $position_styles = $base_styles; 166 $wrapper_classes[] = 'is-position-' . $base_position['type']; 167 } 168 169 /* 170 * Responsive viewport state styles. A viewport state inherits any values 171 * it does not set from the default state, so a state that only overrides 172 * e.g. the `top` offset keeps the base position type. 173 */ 174 foreach ( $responsive_media_queries as $breakpoint => $media_query ) { 175 $viewport_position_style = $style_attribute[ $breakpoint ]['position'] ?? null; 176 177 if ( empty( $viewport_position_style ) || ! is_array( $viewport_position_style ) ) { 178 continue; 179 } 180 181 $viewport_position = is_array( $base_position ) 182 ? array_replace( $base_position, $viewport_position_style ) 183 : $viewport_position_style; 184 185 $viewport_styles = wp_get_position_support_styles( 186 $selector, 187 $viewport_position, 188 $allowed_position_types 189 ); 190 191 if ( ! empty( $viewport_styles ) ) { 192 $wrapper_classes[] = 'is-position-' . $viewport_position['type']; 193 } elseif ( ! empty( $base_styles ) ) { 194 /* 195 * The viewport state can explicitly clear the position type inherited from the 196 * default state. 197 */ 198 $viewport_styles = array( 199 array( 200 'selector' => $selector, 201 'declarations' => array( 'position' => 'static' ), 202 ), 203 ); 204 } else { 205 continue; 206 } 207 208 foreach ( $viewport_styles as $index => $rule ) { 209 $viewport_styles[ $index ]['rules_group'] = $media_query; 210 } 211 212 $position_styles = array_merge( $position_styles, $viewport_styles ); 213 } 214 215 if ( ! empty( $position_styles ) ) { 216 /* 217 * Add to the style engine store to enqueue and render position styles. 218 */ 219 wp_style_engine_get_stylesheet_from_css_rules( 220 $position_styles, 221 array( 222 'context' => 'block-supports', 223 'prettify' => false, 224 ) 225 ); 226 227 // Inject class name to block container markup. 228 $content = new WP_HTML_Tag_Processor( $block_content ); 229 $content->next_tag(); 230 $content->add_class( $class_name ); 231 foreach ( array_unique( $wrapper_classes ) as $class ) { 232 $content->add_class( $class ); 233 } 234 return (string) $content; 235 } 236 237 return $block_content; 238 } 239 240 // Register the block support. 241 WP_Block_Supports::get_instance()->register( 242 'position', 243 array( 244 'register_attribute' => 'wp_register_position_support', 245 ) 246 ); 247 add_filter( 'render_block', 'wp_render_position_support', 10, 2 );
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
| Generated : Wed Oct 7 08:20:33 2026 | Cross-referenced by PHPXref |