Skip to content

Commit

Permalink
Move to attributes calculation
Browse files Browse the repository at this point in the history
  • Loading branch information
sirreal committed Dec 13, 2024
1 parent e105add commit 51343ec
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 70 deletions.
71 changes: 2 additions & 69 deletions src/wp-includes/class-wp-block-parser.php
Original file line number Diff line number Diff line change
Expand Up @@ -343,7 +343,7 @@ public function add_freeform( $length = null ) {
*/
public function add_inner_block( WP_Block_Parser_Block $block, $token_start, $token_length, $last_offset = null ) {
$parent = $this->stack[ count( $this->stack ) - 1 ];
$parent->block->innerBlocks[] = (array) $this->add_html_attributes_to_block( $block );
$parent->block->innerBlocks[] = (array) $block;
$html = substr( $this->document, $parent->prev_offset, $token_start - $parent->prev_offset );

if ( ! empty( $html ) ) {
Expand Down Expand Up @@ -385,74 +385,7 @@ public function add_block_from_stack( $end_offset = null ) {
);
}

$this->output[] = (array) $this->add_html_attributes_to_block( $stack_top->block );
}

private function add_html_attributes_to_block( WP_Block_Parser_Block $block ): WP_Block_Parser_Block {
//phpcs:disable WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
if ( ! isset( $block->blockName ) ) {
return $block;
}

if ( '' === $block->innerHTML ) {
return $block;
}

$block_registry = WP_Block_Type_Registry::get_instance();
if ( null === $block_registry ) {
return $block;
}

$block_type = $block_registry->get_registered( $block->blockName );
if ( null === $block_type || ! isset( $block_type->attributes ) ) {
return $block;
}

foreach ( $block_type->attributes as $attribute_name => $attribute ) {
if ( ! isset( $attribute['selector'] ) ) {
continue;
}
if ( ! isset( $block->attrs[ $attribute_name ] ) ) {
$processor = WP_HTML_Processor::create_fragment( $block->innerHTML );
$selector = $attribute['selector'];

// This is a workaround for a known unsupported selector in a core block.
if ( 'a:not([download])' === $selector ) {
$selector = 'a';
}

foreach ( $processor->select_all( $selector ) as $_ ) {
// This is a workaround for a known unsupported selector in a core block.
if (
'a:not([download])' === $attribute['selector'] &&
null !== $processor->get_attribute( 'download' )
) {
continue;
}

switch ( $attribute['source'] ) {
case 'attribute':
$attr_value = $processor->get_attribute( $attribute['attribute'] );
if ( null === $attr_value ) {
continue 2;
}
if ( null === $block->attrs ) {
$block->attrs = array();
}
// This could be null, string, true, check what JS parser does.
$block->attrs[ $attribute_name ] = $attr_value;
break;

// @todo see about supporting these.
case 'text':
case 'rich-text':
case 'query':
break;
}
}
}
}
return $block;
$this->output[] = (array) $stack_top->block;
}
}

Expand Down
70 changes: 70 additions & 0 deletions src/wp-includes/class-wp-block-type.php
Original file line number Diff line number Diff line change
Expand Up @@ -532,6 +532,76 @@ public function prepare_attributes_for_render( $attributes ) {
return $attributes;
}

/**
* Adds sourced attributes from the parsed block to the block attributes.
*
* @since TBD
*
* @param array $attributes Original block attributes.
* @param array $parsed_block Parsed block.
* @return array Prepared block attributes.
*/
public function add_sourced_attributes_from_parsed_block( $attributes, $parsed_block ) {
// If there are no attribute definitions for the block type, skip
// processing and return verbatim.
if ( ! isset( $this->attributes ) ) {
return $attributes;
}

// Sourced attributes are extracted from the block's HTML. If there's no
// HTML, there's nothing to do.
if ( '' === $parsed_block['innerHTML'] ) {
return $attributes;
}

foreach ( $this->attributes as $attribute_name => $attribute_definition ) {
if (
! isset( $attribute_definition['source'] ) ||
'attribute' !== $attribute_definition['source'] ||
! is_string( $attribute_definition['attribute'] ) ||
! isset( $attribute_definition['selector'] ) ||

// @todo what to do if it's in serialized attributes already? Skip for now.
isset( $attributes[ $attribute_name ] )
) {
continue;
}

$processor = WP_HTML_Processor::create_fragment( $parsed_block['innerHTML'] );
if ( null === $processor ) {
continue;
}

$selector = $attribute_definition['selector'];

// This is a workaround for a known unsupported selector in a core block.
if ( 'a:not([download])' === $selector ) {
$selector = 'a';
}

foreach ( $processor->select_all( $selector ) as $_ ) {
// This is a workaround for a known unsupported selector in a core block.
if (
'a:not([download])' === $attribute_definition['selector'] &&
null !== $processor->get_attribute( 'download' )
) {
continue;
}

$value = $processor->get_attribute( $attribute_definition['attribute'] );
if ( null === $value ) {
continue 2;
}

// @todo another function validates value types, is that sufficient?
$attributes[ $attribute_name ] = $value;

}
}

return $attributes;
}

/**
* Sets block type properties.
*
Expand Down
3 changes: 2 additions & 1 deletion src/wp-includes/class-wp-block.php
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,8 @@ public function __get( $name ) {
array();

if ( ! is_null( $this->block_type ) ) {
$this->attributes = $this->block_type->prepare_attributes_for_render( $this->attributes );
$this->attributes = $this->block_type->add_sourced_attributes_from_parsed_block( $this->attributes, $this->parsed_block );
$this->attributes = $this->block_type->prepare_attributes_for_render( $this->attributes, $this->parsed_block );
}

return $this->attributes;
Expand Down

0 comments on commit 51343ec

Please sign in to comment.