[ Index ] |
PHP Cross Reference of WordPress Trunk (Updated Daily) |
[Summary view] [Print] [Text view]
1 <?php 2 /** 3 * Block Bindings API: WP_Block_Bindings_Registry class. 4 * 5 * Supports overriding content in blocks by connecting them to different sources. 6 * 7 * @package WordPress 8 * @subpackage Block Bindings 9 * @since 6.5.0 10 */ 11 12 /** 13 * Core class used for interacting with block bindings sources. 14 * 15 * @since 6.5.0 16 */ 17 final class WP_Block_Bindings_Registry { 18 19 /** 20 * Holds the registered block bindings sources, keyed by source identifier. 21 * 22 * @since 6.5.0 23 * @var WP_Block_Bindings_Source[] 24 */ 25 private $sources = array(); 26 27 /** 28 * Container for the main instance of the class. 29 * 30 * @since 6.5.0 31 * @var WP_Block_Bindings_Registry|null 32 */ 33 private static $instance = null; 34 35 /** 36 * Supported source properties that can be passed to the registered source. 37 * 38 * @since 6.5.0 39 * @var string[] 40 */ 41 private $allowed_source_properties = array( 42 'label', 43 'get_value_callback', 44 'uses_context', 45 ); 46 47 /** 48 * Supported blocks that can use the block bindings API. 49 * 50 * @since 6.5.0 51 * @var string[] 52 */ 53 private $supported_blocks = array( 54 'core/paragraph', 55 'core/heading', 56 'core/image', 57 'core/button', 58 ); 59 60 /** 61 * Registers a new block bindings source. 62 * 63 * This is a low-level method. For most use cases, it is recommended to use 64 * the `register_block_bindings_source()` function instead. 65 * 66 * @see register_block_bindings_source() 67 * 68 * Sources are used to override block's original attributes with a value 69 * coming from the source. Once a source is registered, it can be used by a 70 * block by setting its `metadata.bindings` attribute to a value that refers 71 * to the source. 72 * 73 * @since 6.5.0 74 * 75 * @param string $source_name The name of the source. It must be a string containing a namespace prefix, i.e. 76 * `my-plugin/my-custom-source`. It must only contain lowercase alphanumeric 77 * characters, the forward slash `/` and dashes. 78 * @param array $source_properties { 79 * The array of arguments that are used to register a source. 80 * 81 * @type string $label The label of the source. 82 * @type callable $get_value_callback A callback executed when the source is processed during block rendering. 83 * The callback should have the following signature: 84 * 85 * `function ($source_args, $block_instance,$attribute_name): mixed` 86 * - @param array $source_args Array containing source arguments 87 * used to look up the override value, 88 * i.e. {"key": "foo"}. 89 * - @param WP_Block $block_instance The block instance. 90 * - @param string $attribute_name The name of the target attribute. 91 * The callback has a mixed return type; it may return a string to override 92 * the block's original value, null, false to remove an attribute, etc. 93 * @type string[] $uses_context (optional) Array of values to add to block `uses_context` needed by the source. 94 * } 95 * @return WP_Block_Bindings_Source|false Source when the registration was successful, or `false` on failure. 96 */ 97 public function register( string $source_name, array $source_properties ) { 98 if ( ! is_string( $source_name ) ) { 99 _doing_it_wrong( 100 __METHOD__, 101 __( 'Block bindings source name must be a string.' ), 102 '6.5.0' 103 ); 104 return false; 105 } 106 107 if ( preg_match( '/[A-Z]+/', $source_name ) ) { 108 _doing_it_wrong( 109 __METHOD__, 110 __( 'Block bindings source names must not contain uppercase characters.' ), 111 '6.5.0' 112 ); 113 return false; 114 } 115 116 $name_matcher = '/^[a-z0-9-]+\/[a-z0-9-]+$/'; 117 if ( ! preg_match( $name_matcher, $source_name ) ) { 118 _doing_it_wrong( 119 __METHOD__, 120 __( 'Block bindings source names must contain a namespace prefix. Example: my-plugin/my-custom-source' ), 121 '6.5.0' 122 ); 123 return false; 124 } 125 126 if ( $this->is_registered( $source_name ) ) { 127 _doing_it_wrong( 128 __METHOD__, 129 /* translators: %s: Block bindings source name. */ 130 sprintf( __( 'Block bindings source "%s" already registered.' ), $source_name ), 131 '6.5.0' 132 ); 133 return false; 134 } 135 136 // Validates that the source properties contain the label. 137 if ( ! isset( $source_properties['label'] ) ) { 138 _doing_it_wrong( 139 __METHOD__, 140 __( 'The $source_properties must contain a "label".' ), 141 '6.5.0' 142 ); 143 return false; 144 } 145 146 // Validates that the source properties contain the get_value_callback. 147 if ( ! isset( $source_properties['get_value_callback'] ) ) { 148 _doing_it_wrong( 149 __METHOD__, 150 __( 'The $source_properties must contain a "get_value_callback".' ), 151 '6.5.0' 152 ); 153 return false; 154 } 155 156 // Validates that the get_value_callback is a valid callback. 157 if ( ! is_callable( $source_properties['get_value_callback'] ) ) { 158 _doing_it_wrong( 159 __METHOD__, 160 __( 'The "get_value_callback" parameter must be a valid callback.' ), 161 '6.5.0' 162 ); 163 return false; 164 } 165 166 // Validates that the uses_context parameter is an array. 167 if ( isset( $source_properties['uses_context'] ) && ! is_array( $source_properties['uses_context'] ) ) { 168 _doing_it_wrong( 169 __METHOD__, 170 __( 'The "uses_context" parameter must be an array.' ), 171 '6.5.0' 172 ); 173 return false; 174 } 175 176 if ( ! empty( array_diff( array_keys( $source_properties ), $this->allowed_source_properties ) ) ) { 177 _doing_it_wrong( 178 __METHOD__, 179 __( 'The $source_properties array contains invalid properties.' ), 180 '6.5.0' 181 ); 182 return false; 183 } 184 185 $source = new WP_Block_Bindings_Source( 186 $source_name, 187 $source_properties 188 ); 189 190 $this->sources[ $source_name ] = $source; 191 192 // Adds `uses_context` defined by block bindings sources. 193 add_filter( 194 'get_block_type_uses_context', 195 function ( $uses_context, $block_type ) use ( $source ) { 196 if ( ! in_array( $block_type->name, $this->supported_blocks, true ) || empty( $source->uses_context ) ) { 197 return $uses_context; 198 } 199 // Use array_values to reset the array keys. 200 return array_values( array_unique( array_merge( $uses_context, $source->uses_context ) ) ); 201 }, 202 10, 203 2 204 ); 205 206 return $source; 207 } 208 209 /** 210 * Unregisters a block bindings source. 211 * 212 * @since 6.5.0 213 * 214 * @param string $source_name Block bindings source name including namespace. 215 * @return WP_Block_Bindings_Source|false The unregistered block bindings source on success and `false` otherwise. 216 */ 217 public function unregister( string $source_name ) { 218 if ( ! $this->is_registered( $source_name ) ) { 219 _doing_it_wrong( 220 __METHOD__, 221 /* translators: %s: Block bindings source name. */ 222 sprintf( __( 'Block binding "%s" not found.' ), $source_name ), 223 '6.5.0' 224 ); 225 return false; 226 } 227 228 $unregistered_source = $this->sources[ $source_name ]; 229 unset( $this->sources[ $source_name ] ); 230 231 return $unregistered_source; 232 } 233 234 /** 235 * Retrieves the list of all registered block bindings sources. 236 * 237 * @since 6.5.0 238 * 239 * @return WP_Block_Bindings_Source[] The array of registered sources. 240 */ 241 public function get_all_registered() { 242 return $this->sources; 243 } 244 245 /** 246 * Retrieves a registered block bindings source. 247 * 248 * @since 6.5.0 249 * 250 * @param string $source_name The name of the source. 251 * @return WP_Block_Bindings_Source|null The registered block bindings source, or `null` if it is not registered. 252 */ 253 public function get_registered( string $source_name ) { 254 if ( ! $this->is_registered( $source_name ) ) { 255 return null; 256 } 257 258 return $this->sources[ $source_name ]; 259 } 260 261 /** 262 * Checks if a block bindings source is registered. 263 * 264 * @since 6.5.0 265 * 266 * @param string $source_name The name of the source. 267 * @return bool `true` if the block bindings source is registered, `false` otherwise. 268 */ 269 public function is_registered( $source_name ) { 270 return isset( $this->sources[ $source_name ] ); 271 } 272 273 /** 274 * Wakeup magic method. 275 * 276 * @since 6.5.0 277 */ 278 public function __wakeup() { 279 if ( ! $this->sources ) { 280 return; 281 } 282 if ( ! is_array( $this->sources ) ) { 283 throw new UnexpectedValueException(); 284 } 285 foreach ( $this->sources as $value ) { 286 if ( ! $value instanceof WP_Block_Bindings_Source ) { 287 throw new UnexpectedValueException(); 288 } 289 } 290 } 291 292 /** 293 * Utility method to retrieve the main instance of the class. 294 * 295 * The instance will be created if it does not exist yet. 296 * 297 * @since 6.5.0 298 * 299 * @return WP_Block_Bindings_Registry The main instance. 300 */ 301 public static function get_instance() { 302 if ( null === self::$instance ) { 303 self::$instance = new self(); 304 } 305 306 return self::$instance; 307 } 308 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated : Fri May 3 08:20:01 2024 | Cross-referenced by PHPXref |