| [ Index ] |
PHP Cross Reference of WordPress Trunk (Updated Daily) |
[Summary view] [Print] [Text view]
1 <?php 2 /** 3 * Block support flags. 4 * 5 * @package WordPress 6 * 7 * @since 5.6.0 8 */ 9 10 /** 11 * Class encapsulating and implementing Block Supports. 12 * 13 * @since 5.6.0 14 * 15 * @access private 16 * 17 * @phpstan-type ApplyCallback callable( WP_Block_Type, array<string, mixed> ): array<string, mixed> 18 * @phpstan-type RegisterCallback callable( WP_Block_Type ): void 19 */ 20 #[AllowDynamicProperties] 21 class WP_Block_Supports { 22 23 /** 24 * Config. 25 * 26 * @since 5.6.0 27 * @var array 28 * @phpstan-var array<string, array{ 29 * name: string, 30 * apply?: ApplyCallback, 31 * register_attribute?: RegisterCallback, 32 * }> 33 */ 34 private $block_supports = array(); 35 36 /** 37 * Tracks the current block to be rendered. 38 * 39 * @since 5.6.0 40 * @var array|null 41 * @phpstan-var array<string, mixed>|null 42 */ 43 public static $block_to_render = null; 44 45 /** 46 * Container for the main instance of the class. 47 * 48 * @since 5.6.0 49 * @var WP_Block_Supports|null 50 */ 51 private static $instance = null; 52 53 /** 54 * Utility method to retrieve the main instance of the class. 55 * 56 * The instance will be created if it does not exist yet. 57 * 58 * @since 5.6.0 59 * 60 * @return WP_Block_Supports The main instance. 61 */ 62 public static function get_instance() { 63 if ( null === self::$instance ) { 64 self::$instance = new self(); 65 } 66 67 return self::$instance; 68 } 69 70 /** 71 * Initializes the block supports. It registers the block supports block attributes. 72 * 73 * @since 5.6.0 74 * 75 * @return void 76 */ 77 public static function init() { 78 $instance = self::get_instance(); 79 $instance->register_attributes(); 80 } 81 82 /** 83 * Registers a block support. 84 * 85 * @since 5.6.0 86 * 87 * @link https://developer.wordpress.org/block-editor/reference-guides/block-api/block-supports/ 88 * 89 * @param string $block_support_name Block support name. 90 * @param array $block_support_config Array containing the properties of the block support. 91 * 92 * @phpstan-param array{ 93 * apply?: ApplyCallback, 94 * register_attribute?: RegisterCallback, 95 * } $block_support_config 96 * 97 * @return void 98 */ 99 public function register( $block_support_name, $block_support_config ) { 100 $this->block_supports[ $block_support_name ] = array_merge( 101 $block_support_config, 102 array( 'name' => $block_support_name ) 103 ); 104 } 105 106 /** 107 * Generates an array of HTML attributes, such as classes, by applying to 108 * the given block all of the features that the block supports. 109 * 110 * @since 5.6.0 111 * 112 * @return string[] Array of HTML attribute values keyed by their name. 113 */ 114 public function apply_block_supports() { 115 if ( ! is_array( self::$block_to_render ) ) { 116 return array(); 117 } 118 119 $block_type = WP_Block_Type_Registry::get_instance()->get_registered( 120 self::$block_to_render['blockName'] 121 ); 122 123 // If no render_callback, assume styles have been previously handled. 124 if ( ! $block_type ) { 125 return array(); 126 } 127 128 $block_attributes = array_key_exists( 'attrs', self::$block_to_render ) && is_array( self::$block_to_render['attrs'] ) 129 ? $block_type->prepare_attributes_for_render( self::$block_to_render['attrs'] ) 130 : array(); 131 132 $output = array(); 133 foreach ( $this->block_supports as $block_support_config ) { 134 if ( ! isset( $block_support_config['apply'] ) ) { 135 continue; 136 } 137 138 $new_attributes = call_user_func( 139 $block_support_config['apply'], 140 $block_type, 141 $block_attributes 142 ); 143 144 if ( ! empty( $new_attributes ) ) { 145 foreach ( $new_attributes as $attribute_name => $attribute_value ) { 146 if ( ! is_scalar( $attribute_value ) || is_bool( $attribute_value ) ) { 147 continue; 148 } 149 $attribute_value = (string) $attribute_value; 150 if ( ! array_key_exists( $attribute_name, $output ) || '' === $output[ $attribute_name ] ) { 151 $output[ $attribute_name ] = $attribute_value; 152 } else { 153 $output[ $attribute_name ] .= " $attribute_value"; 154 } 155 } 156 } 157 } 158 159 return $output; 160 } 161 162 /** 163 * Registers the block attributes required by the different block supports. 164 * 165 * @since 5.6.0 166 * 167 * @return void 168 */ 169 private function register_attributes() { 170 $block_registry = WP_Block_Type_Registry::get_instance(); 171 $registered_block_types = $block_registry->get_all_registered(); 172 foreach ( $registered_block_types as $block_type ) { 173 if ( ! ( $block_type instanceof WP_Block_Type ) ) { 174 continue; 175 } 176 if ( ! $block_type->attributes ) { 177 $block_type->attributes = array(); 178 } 179 180 foreach ( $this->block_supports as $block_support_config ) { 181 if ( ! isset( $block_support_config['register_attribute'] ) ) { 182 continue; 183 } 184 185 call_user_func( 186 $block_support_config['register_attribute'], 187 $block_type 188 ); 189 } 190 } 191 } 192 } 193 194 /** 195 * Generates a string of attributes by applying to the current block being 196 * rendered all of the features that the block supports. 197 * 198 * @since 5.6.0 199 * 200 * @param string[] $extra_attributes Optional. Array of extra attributes to render on the block wrapper. 201 * @return string String of HTML attributes. 202 */ 203 function get_block_wrapper_attributes( $extra_attributes = array() ) { 204 $new_attributes = WP_Block_Supports::get_instance()->apply_block_supports(); 205 206 if ( empty( $new_attributes ) && empty( $extra_attributes ) ) { 207 return ''; 208 } 209 210 // Attribute values are concatenated or overridden depending on the attribute type. 211 // This is hardcoded on purpose, as we only support a fixed list of attributes. 212 $attribute_merge_callbacks = array( 213 'style' => static function ( $new_attribute, $extra_attribute ) { 214 $styles = array_filter( 215 array( 216 rtrim( trim( $new_attribute ), ';' ), 217 rtrim( trim( $extra_attribute ), ';' ), 218 ) 219 ); 220 return safecss_filter_attr( implode( ';', array_filter( $styles ) ) ); 221 }, 222 'class' => static function ( $new_attribute, $extra_attribute ) { 223 $classes = array_merge( 224 (array) preg_split( '/\s+/', $extra_attribute, -1, PREG_SPLIT_NO_EMPTY ), 225 (array) preg_split( '/\s+/', $new_attribute, -1, PREG_SPLIT_NO_EMPTY ) 226 ); 227 $classes = array_unique( $classes ); 228 return implode( ' ', $classes ); 229 }, 230 'id' => static function ( $new_attribute, $extra_attribute ) { 231 return '' !== $extra_attribute ? $extra_attribute : $new_attribute; 232 }, 233 'aria-label' => static function ( $new_attribute, $extra_attribute ) { 234 return '' !== $extra_attribute ? $extra_attribute : $new_attribute; 235 }, 236 ); 237 238 // Accept strings and numbers (cast to string); reject other types (bool, null, array, object). 239 $attributes = array(); 240 foreach ( $attribute_merge_callbacks as $attribute_name => $merge_callback ) { 241 $new_attribute = $new_attributes[ $attribute_name ] ?? ''; 242 $extra_attribute = $extra_attributes[ $attribute_name ] ?? ''; 243 $new_attribute = is_scalar( $new_attribute ) && ! is_bool( $new_attribute ) ? (string) $new_attribute : ''; 244 $extra_attribute = is_scalar( $extra_attribute ) && ! is_bool( $extra_attribute ) ? (string) $extra_attribute : ''; 245 246 if ( '' === $new_attribute && '' === $extra_attribute ) { 247 continue; 248 } 249 250 $attributes[ $attribute_name ] = $merge_callback( $new_attribute, $extra_attribute ); 251 } 252 253 foreach ( $extra_attributes as $attribute_name => $value ) { 254 if ( ! isset( $attribute_merge_callbacks[ $attribute_name ] ) && is_scalar( $value ) && ! is_bool( $value ) ) { 255 $attributes[ $attribute_name ] = (string) $value; 256 } 257 } 258 259 if ( empty( $attributes ) ) { 260 return ''; 261 } 262 263 $normalized_attributes = array(); 264 foreach ( $attributes as $key => $value ) { 265 $normalized_attributes[] = $key . '="' . esc_attr( $value ) . '"'; 266 } 267 268 return implode( ' ', $normalized_attributes ); 269 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
| Generated : Thu Jun 25 08:20:12 2026 | Cross-referenced by PHPXref |