Changeset 60684
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/wp-includes/class-wp-block.php
r60663 r60684 417 417 case 'html': 418 418 case 'rich-text': 419 $block_reader = new WP_HTML_Tag_Processor( $block_content );419 $block_reader = self::get_block_bindings_processor( $block_content ); 420 420 421 421 // TODO: Support for CSS selectors whenever they are ready in the HTML API. … … 425 425 $block_reader->next_tag(); 426 426 $block_reader->set_bookmark( 'iterate-selectors' ); 427 428 // TODO: This shouldn't be needed when the `set_inner_html` function is ready.429 // Store the parent tag and its attributes to be able to restore them later in the button.430 // The button block has a wrapper while the paragraph and heading blocks don't.431 if ( 'core/button' === $this->name ) {432 $button_wrapper = $block_reader->get_tag();433 $button_wrapper_attribute_names = $block_reader->get_attribute_names_with_prefix( '' );434 $button_wrapper_attrs = array();435 foreach ( $button_wrapper_attribute_names as $name ) {436 $button_wrapper_attrs[ $name ] = $block_reader->get_attribute( $name );437 }438 }439 427 440 428 foreach ( $selectors as $selector ) { … … 445 433 ) 446 434 ) ) { 435 // TODO: Use `WP_HTML_Processor::set_inner_html` method once it's available. 447 436 $block_reader->release_bookmark( 'iterate-selectors' ); 448 449 // TODO: Use `set_inner_html` method whenever it's ready in the HTML API. 450 // Until then, it is hardcoded for the paragraph, heading, and button blocks. 451 // Store the tag and its attributes to be able to restore them later. 452 $selector_attribute_names = $block_reader->get_attribute_names_with_prefix( '' ); 453 $selector_attrs = array(); 454 foreach ( $selector_attribute_names as $name ) { 455 $selector_attrs[ $name ] = $block_reader->get_attribute( $name ); 456 } 457 $selector_markup = "<$selector>" . wp_kses_post( $source_value ) . "</$selector>"; 458 $amended_content = new WP_HTML_Tag_Processor( $selector_markup ); 459 $amended_content->next_tag(); 460 foreach ( $selector_attrs as $attribute_key => $attribute_value ) { 461 $amended_content->set_attribute( $attribute_key, $attribute_value ); 462 } 463 if ( 'core/paragraph' === $this->name || 'core/heading' === $this->name ) { 464 return $amended_content->get_updated_html(); 465 } 466 if ( 'core/button' === $this->name ) { 467 $button_markup = "<$button_wrapper>{$amended_content->get_updated_html()}</$button_wrapper>"; 468 $amended_button = new WP_HTML_Tag_Processor( $button_markup ); 469 $amended_button->next_tag(); 470 foreach ( $button_wrapper_attrs as $attribute_key => $attribute_value ) { 471 $amended_button->set_attribute( $attribute_key, $attribute_value ); 472 } 473 return $amended_button->get_updated_html(); 474 } 437 $block_reader->replace_rich_text( wp_kses_post( $source_value ) ); 438 return $block_reader->get_updated_html(); 475 439 } else { 476 440 $block_reader->seek( 'iterate-selectors' ); … … 498 462 } 499 463 464 private static function get_block_bindings_processor( string $block_content ) { 465 $internal_processor_class = new class('', WP_HTML_Processor::CONSTRUCTOR_UNLOCK_CODE) extends WP_HTML_Processor { 466 /** 467 * Replace the rich text content between a tag opener and matching closer. 468 * 469 * When stopped on a tag opener, replace the content enclosed by it and its 470 * matching closer with the provided rich text. 471 * 472 * @param string $rich_text The rich text to replace the original content with. 473 * @return bool True on success. 474 */ 475 public function replace_rich_text( $rich_text ) { 476 if ( $this->is_tag_closer() || ! $this->expects_closer() ) { 477 return false; 478 } 479 480 $depth = $this->get_current_depth(); 481 482 $this->set_bookmark( '_wp_block_bindings_tag_opener' ); 483 // The bookmark names are prefixed with `_` so the key below has an extra `_`. 484 $tag_opener = $this->bookmarks['__wp_block_bindings_tag_opener']; 485 $start = $tag_opener->start + $tag_opener->length; 486 $this->release_bookmark( '_wp_block_bindings_tag_opener' ); 487 488 // Find matching tag closer. 489 while ( $this->next_token() && $this->get_current_depth() >= $depth ) { 490 } 491 492 $this->set_bookmark( '_wp_block_bindings_tag_closer' ); 493 $tag_closer = $this->bookmarks['__wp_block_bindings_tag_closer']; 494 $end = $tag_closer->start; 495 $this->release_bookmark( '_wp_block_bindings_tag_closer' ); 496 497 $this->lexical_updates[] = new WP_HTML_Text_Replacement( 498 $start, 499 $end - $start, 500 $rich_text 501 ); 502 503 return true; 504 } 505 }; 506 507 return $internal_processor_class::create_fragment( $block_content ); 508 } 500 509 501 510 /** -
trunk/tests/phpunit/tests/block-bindings/render.php
r60611 r60684 62 62 } 63 63 64 public function data_update_block_with_value_from_source() { 65 return array( 66 'paragraph block' => array( 67 'content', 68 <<<HTML 69 <!-- wp:paragraph --> 70 <p>This should not appear</p> 71 <!-- /wp:paragraph --> 72 HTML 73 , 74 '<p>test source value</p>', 75 ), 76 'button block' => array( 77 'text', 78 <<<HTML 79 <!-- wp:button --> 80 <div class="wp-block-button"><a class="wp-block-button__link wp-element-button">This should not appear</a></div> 81 <!-- /wp:button --> 82 HTML 83 , 84 '<div class="wp-block-button"><a class="wp-block-button__link wp-element-button">test source value</a></div>', 85 ), 86 ); 87 } 88 64 89 /** 65 90 * Test if the block content is updated with the value returned by the source. … … 68 93 * 69 94 * @covers ::register_block_bindings_source 70 */ 71 public function test_update_block_with_value_from_source() { 95 * 96 * @dataProvider data_update_block_with_value_from_source 97 */ 98 public function test_update_block_with_value_from_source( $bound_attribute, $block_content, $expected_result ) { 72 99 $get_value_callback = function () { 73 100 return 'test source value'; … … 82 109 ); 83 110 84 $block_content = <<<HTML 85 <!-- wp:paragraph {"metadata":{"bindings":{"content":{"source":"test/source"}}}} --> 86 <p>This should not appear</p> 87 <!-- /wp:paragraph --> 88 HTML; 89 $parsed_blocks = parse_blocks( $block_content ); 90 $block = new WP_Block( $parsed_blocks[0] ); 91 $result = $block->render(); 111 $parsed_blocks = parse_blocks( $block_content ); 112 113 $parsed_blocks[0]['attrs']['metadata'] = array( 114 'bindings' => array( 115 $bound_attribute => array( 116 'source' => self::SOURCE_NAME, 117 ), 118 ), 119 ); 120 121 $block = new WP_Block( $parsed_blocks[0] ); 122 $result = $block->render(); 92 123 93 124 $this->assertSame( 94 125 'test source value', 95 $block->attributes[ 'content'],96 "The ' content' attribute should be updated with the value returned by the source."97 ); 98 $this->assertSame( 99 '<p>test source value</p>',126 $block->attributes[ $bound_attribute ], 127 "The '{$bound_attribute}' attribute should be updated with the value returned by the source." 128 ); 129 $this->assertSame( 130 $expected_result, 100 131 trim( $result ), 101 132 'The block content should be updated with the value returned by the source.'
Note: See TracChangeset
for help on using the changeset viewer.