[ 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          self::$instance ??= new self();
  64  
  65          return self::$instance;
  66      }
  67  
  68      /**
  69       * Initializes the block supports. It registers the block supports block attributes.
  70       *
  71       * @since 5.6.0
  72       *
  73       * @return void
  74       */
  75  	public static function init() {
  76          $instance = self::get_instance();
  77          $instance->register_attributes();
  78      }
  79  
  80      /**
  81       * Registers a block support.
  82       *
  83       * @since 5.6.0
  84       *
  85       * @link https://developer.wordpress.org/block-editor/reference-guides/block-api/block-supports/
  86       *
  87       * @param string $block_support_name   Block support name.
  88       * @param array  $block_support_config Array containing the properties of the block support.
  89       *
  90       * @phpstan-param array{
  91       *     apply?: ApplyCallback,
  92       *     register_attribute?: RegisterCallback,
  93       * } $block_support_config
  94       *
  95       * @return void
  96       */
  97  	public function register( $block_support_name, $block_support_config ) {
  98          $this->block_supports[ $block_support_name ] = array_merge(
  99              $block_support_config,
 100              array( 'name' => $block_support_name )
 101          );
 102      }
 103  
 104      /**
 105       * Generates an array of HTML attributes, such as classes, by applying to
 106       * the given block all of the features that the block supports.
 107       *
 108       * @since 5.6.0
 109       *
 110       * @return string[] Array of HTML attribute values keyed by their name.
 111       */
 112  	public function apply_block_supports() {
 113          if ( ! is_array( self::$block_to_render ) ) {
 114              return array();
 115          }
 116  
 117          $block_type = WP_Block_Type_Registry::get_instance()->get_registered(
 118              self::$block_to_render['blockName']
 119          );
 120  
 121          // If no render_callback, assume styles have been previously handled.
 122          if ( ! $block_type ) {
 123              return array();
 124          }
 125  
 126          $block_attributes = array_key_exists( 'attrs', self::$block_to_render ) && is_array( self::$block_to_render['attrs'] )
 127              ? $block_type->prepare_attributes_for_render( self::$block_to_render['attrs'] )
 128              : array();
 129  
 130          $output = array();
 131          foreach ( $this->block_supports as $block_support_config ) {
 132              if ( ! isset( $block_support_config['apply'] ) ) {
 133                  continue;
 134              }
 135  
 136              $new_attributes = call_user_func(
 137                  $block_support_config['apply'],
 138                  $block_type,
 139                  $block_attributes
 140              );
 141  
 142              if ( ! empty( $new_attributes ) ) {
 143                  foreach ( $new_attributes as $attribute_name => $attribute_value ) {
 144                      if ( ! is_scalar( $attribute_value ) || is_bool( $attribute_value ) ) {
 145                          continue;
 146                      }
 147                      $attribute_value = (string) $attribute_value;
 148                      if ( ! array_key_exists( $attribute_name, $output ) || '' === $output[ $attribute_name ] ) {
 149                          $output[ $attribute_name ] = $attribute_value;
 150                      } else {
 151                          $output[ $attribute_name ] .= " $attribute_value";
 152                      }
 153                  }
 154              }
 155          }
 156  
 157          return $output;
 158      }
 159  
 160      /**
 161       * Registers the block attributes required by the different block supports.
 162       *
 163       * @since 5.6.0
 164       *
 165       * @return void
 166       */
 167  	private function register_attributes() {
 168          $block_registry         = WP_Block_Type_Registry::get_instance();
 169          $registered_block_types = $block_registry->get_all_registered();
 170          foreach ( $registered_block_types as $block_type ) {
 171              if ( ! ( $block_type instanceof WP_Block_Type ) ) {
 172                  continue;
 173              }
 174              if ( ! $block_type->attributes ) {
 175                  $block_type->attributes = array();
 176              }
 177  
 178              foreach ( $this->block_supports as $block_support_config ) {
 179                  if ( ! isset( $block_support_config['register_attribute'] ) ) {
 180                      continue;
 181                  }
 182  
 183                  call_user_func(
 184                      $block_support_config['register_attribute'],
 185                      $block_type
 186                  );
 187              }
 188          }
 189      }
 190  }
 191  
 192  /**
 193   * Generates a string of attributes by applying to the current block being
 194   * rendered all of the features that the block supports.
 195   *
 196   * @since 5.6.0
 197   *
 198   * @param string[] $extra_attributes Optional. Array of extra attributes to render on the block wrapper.
 199   * @return string String of HTML attributes.
 200   */
 201  function get_block_wrapper_attributes( $extra_attributes = array() ) {
 202      $new_attributes = WP_Block_Supports::get_instance()->apply_block_supports();
 203  
 204      if ( empty( $new_attributes ) && empty( $extra_attributes ) ) {
 205          return '';
 206      }
 207  
 208      // Attribute values are concatenated or overridden depending on the attribute type.
 209      // This is hardcoded on purpose, as we only support a fixed list of attributes.
 210      $attribute_merge_callbacks = array(
 211          'style'      => static function ( $new_attribute, $extra_attribute ) {
 212              $styles = array_filter(
 213                  array(
 214                      rtrim( trim( $new_attribute ), ';' ),
 215                      rtrim( trim( $extra_attribute ), ';' ),
 216                  )
 217              );
 218              return safecss_filter_attr( implode( ';', array_filter( $styles ) ) );
 219          },
 220          'class'      => static function ( $new_attribute, $extra_attribute ) {
 221              $classes = array_merge(
 222                  (array) preg_split( '/\s+/', $extra_attribute, -1, PREG_SPLIT_NO_EMPTY ),
 223                  (array) preg_split( '/\s+/', $new_attribute, -1, PREG_SPLIT_NO_EMPTY )
 224              );
 225              $classes = array_unique( $classes );
 226              return implode( ' ', $classes );
 227          },
 228          'id'         => static function ( $new_attribute, $extra_attribute ) {
 229              return '' !== $extra_attribute ? $extra_attribute : $new_attribute;
 230          },
 231          'aria-label' => static function ( $new_attribute, $extra_attribute ) {
 232              return '' !== $extra_attribute ? $extra_attribute : $new_attribute;
 233          },
 234      );
 235  
 236      // Accept strings and numbers (cast to string); reject other types (bool, null, array, object).
 237      $attributes = array();
 238      foreach ( $attribute_merge_callbacks as $attribute_name => $merge_callback ) {
 239          $new_attribute   = $new_attributes[ $attribute_name ] ?? '';
 240          $extra_attribute = $extra_attributes[ $attribute_name ] ?? '';
 241          $new_attribute   = is_scalar( $new_attribute ) && ! is_bool( $new_attribute ) ? (string) $new_attribute : '';
 242          $extra_attribute = is_scalar( $extra_attribute ) && ! is_bool( $extra_attribute ) ? (string) $extra_attribute : '';
 243  
 244          if ( '' === $new_attribute && '' === $extra_attribute ) {
 245              continue;
 246          }
 247  
 248          $attributes[ $attribute_name ] = $merge_callback( $new_attribute, $extra_attribute );
 249      }
 250  
 251      foreach ( $extra_attributes as $attribute_name => $value ) {
 252          if ( ! isset( $attribute_merge_callbacks[ $attribute_name ] ) && is_scalar( $value ) && ! is_bool( $value ) ) {
 253              $attributes[ $attribute_name ] = (string) $value;
 254          }
 255      }
 256  
 257      if ( empty( $attributes ) ) {
 258          return '';
 259      }
 260  
 261      $normalized_attributes = array();
 262      foreach ( $attributes as $key => $value ) {
 263          $normalized_attributes[] = $key . '="' . esc_attr( $value ) . '"';
 264      }
 265  
 266      return implode( ' ', $normalized_attributes );
 267  }


Generated : Fri Sep 18 08:20:28 2026 Cross-referenced by PHPXref