[ Index ]

PHP Cross Reference of WordPress Trunk (Updated Daily)

Search

title

Body

[close]

/wp-includes/ -> class-wp-block-supports.php (source)

   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  }


Generated : Thu Jun 25 08:20:12 2026 Cross-referenced by PHPXref