Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add rich-text source support for WordPress 6.5 #58

Merged
merged 6 commits into from
Mar 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions phpcs.xml.dist
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,9 @@
<exclude name="PEAR.Functions.FunctionCallSignature.MultipleArguments" />
<exclude name="PEAR.Functions.FunctionCallSignature.CloseBracketLine" />

<!-- This rule requires all comments to end with a full stop or other punctuation -->
<exclude name="Squiz.Commenting.InlineComment.InvalidEndChar" />

<!-- Allow short array syntax -->
<exclude name="Universal.Arrays.DisallowShortArraySyntax.Found" />

Expand Down
64 changes: 49 additions & 15 deletions src/parser/content-parser.php
Original file line number Diff line number Diff line change
Expand Up @@ -289,12 +289,17 @@ protected function source_attribute( $crawler, $block_attribute_definition ) {
$attribute_source = $block_attribute_definition['source'];

// See block attribute sources:
// https://developer.wordpress.org/block-editor/reference-guides/block-api/block-attributes/#value-source.
// https://developer.wordpress.org/block-editor/reference-guides/block-api/block-attributes/#value-source
if ( 'attribute' === $attribute_source || 'property' === $attribute_source ) {
// 'property' sources were removed in 2018. Default to attribute value.
// https://github.com/WordPress/gutenberg/pull/8276.
// https://github.com/WordPress/gutenberg/pull/8276

$attribute_value = $this->source_block_attribute( $crawler, $block_attribute_definition );
} elseif ( 'rich-text' === $attribute_source ) {
// Most 'html' sources were converted to 'rich-text' in WordPress 6.5.
// https://github.com/WordPress/gutenberg/pull/43204

$attribute_value = $this->source_block_rich_text( $crawler, $block_attribute_definition );
} elseif ( 'html' === $attribute_source ) {
$attribute_value = $this->source_block_html( $crawler, $block_attribute_definition );
} elseif ( 'text' === $attribute_source ) {
Expand Down Expand Up @@ -332,7 +337,7 @@ protected function source_attribute( $crawler, $block_attribute_definition ) {
*/
protected function source_block_attribute( $crawler, $block_attribute_definition ) {
// 'attribute' sources:
// https://developer.wordpress.org/block-editor/reference-guides/block-api/block-attributes/#attribute-source.
// https://developer.wordpress.org/block-editor/reference-guides/block-api/block-attributes/#attribute-source

$attribute_value = null;
$attribute = $block_attribute_definition['attribute'];
Expand Down Expand Up @@ -361,7 +366,7 @@ protected function source_block_attribute( $crawler, $block_attribute_definition
*/
protected function source_block_html( $crawler, $block_attribute_definition ) {
// 'html' sources:
// https://developer.wordpress.org/block-editor/reference-guides/block-api/block-attributes/#html-source.
// https://developer.wordpress.org/block-editor/reference-guides/block-api/block-attributes/#html-source

$attribute_value = null;
$selector = $block_attribute_definition['selector'] ?? null;
Expand All @@ -387,6 +392,35 @@ protected function source_block_html( $crawler, $block_attribute_definition ) {
return $attribute_value;
}

/**
* Helper function to process the `rich-text` source attribute.
* At present, the main difference from `html` is that `rich-text` does not support multiline selectors.
*
* @param Symfony\Component\DomCrawler\Crawler $crawler Crawler instance.
* @param array $block_attribute_definition Definition of the block attribute.
*
* @return string|null
*
* @access private
*/
protected function source_block_rich_text( $crawler, $block_attribute_definition ) {
// 'rich-text' sources:
// https://github.com/WordPress/gutenberg/blob/6a42225124e69276a2deec4597a855bb504b37cc/packages/blocks/src/api/parser/get-block-attributes.js#L228-L232

$attribute_value = null;
$selector = $block_attribute_definition['selector'] ?? null;

if ( null !== $selector ) {
$crawler = $crawler->filter( $selector );
}

if ( $crawler->count() > 0 ) {
$attribute_value = $crawler->html();
}

return $attribute_value;
}

/**
* Helper function to process the `text` source attribute.
*
Expand All @@ -399,7 +433,7 @@ protected function source_block_html( $crawler, $block_attribute_definition ) {
*/
protected function source_block_text( $crawler, $block_attribute_definition ) {
// 'text' sources:
// https://developer.wordpress.org/block-editor/reference-guides/block-api/block-attributes/#text-source.
// https://developer.wordpress.org/block-editor/reference-guides/block-api/block-attributes/#text-source

$attribute_value = null;
$selector = $block_attribute_definition['selector'] ?? null;
Expand Down Expand Up @@ -427,7 +461,7 @@ protected function source_block_text( $crawler, $block_attribute_definition ) {
*/
protected function source_block_query( $crawler, $block_attribute_definition ) {
// 'query' sources:
// https://developer.wordpress.org/block-editor/reference-guides/block-api/block-attributes/#query-source.
// https://developer.wordpress.org/block-editor/reference-guides/block-api/block-attributes/#query-source

$query_items = $block_attribute_definition['query'];
$selector = $block_attribute_definition['selector'] ?? null;
Expand Down Expand Up @@ -465,9 +499,9 @@ protected function source_block_query( $crawler, $block_attribute_definition ) {
*/
protected function source_block_tag( $crawler, $block_attribute_definition ) {
// The only current usage of the 'tag' attribute is Gutenberg core is the 'core/table' block:
// https://github.com/WordPress/gutenberg/blob/796b800/packages/block-library/src/table/block.json#L39.
// https://github.com/WordPress/gutenberg/blob/796b800/packages/block-library/src/table/block.json#L39
// Also see tag attribute parsing in Gutenberg:
// https://github.com/WordPress/gutenberg/blob/6517008/packages/blocks/src/api/parser/get-block-attributes.js#L225.
// https://github.com/WordPress/gutenberg/blob/6517008/packages/blocks/src/api/parser/get-block-attributes.js#L225

$attribute_value = null;
$selector = $block_attribute_definition['selector'] ?? null;
Expand All @@ -494,9 +528,9 @@ protected function source_block_tag( $crawler, $block_attribute_definition ) {
*/
protected function source_block_raw( $crawler ) {
// The only current usage of the 'raw' attribute in Gutenberg core is the 'core/html' block:
// https://github.com/WordPress/gutenberg/blob/6517008/packages/block-library/src/html/block.json#L13.
// https://github.com/WordPress/gutenberg/blob/6517008/packages/block-library/src/html/block.json#L13
// Also see tag attribute parsing in Gutenberg:
// https://github.com/WordPress/gutenberg/blob/6517008/packages/blocks/src/api/parser/get-block-attributes.js#L131.
// https://github.com/WordPress/gutenberg/blob/6517008/packages/blocks/src/api/parser/get-block-attributes.js#L131

$attribute_value = null;

Expand All @@ -518,7 +552,7 @@ protected function source_block_raw( $crawler ) {
*/
protected function source_block_meta( $block_attribute_definition ) {
// 'meta' sources:
// https://developer.wordpress.org/block-editor/reference-guides/block-api/block-attributes/#meta-source.
// https://developer.wordpress.org/block-editor/reference-guides/block-api/block-attributes/#meta-source

$post = get_post( $this->post_id );
if ( null === $post ) {
Expand Down Expand Up @@ -547,9 +581,9 @@ protected function source_block_meta( $block_attribute_definition ) {
*/
protected function source_block_children( $crawler, $block_attribute_definition ) {
// 'children' attribute usage was removed from core in 2018, but not officically deprecated until WordPress 6.1:
// https://github.com/WordPress/gutenberg/pull/44265.
// https://github.com/WordPress/gutenberg/pull/44265
// Parsing code for 'children' sources can be found here:
// https://github.com/WordPress/gutenberg/blob/dd0504b/packages/blocks/src/api/children.js#L149.
// https://github.com/WordPress/gutenberg/blob/dd0504b/packages/blocks/src/api/children.js#L149

$attribute_values = [];
$selector = $block_attribute_definition['selector'] ?? null;
Expand Down Expand Up @@ -599,9 +633,9 @@ protected function source_block_children( $crawler, $block_attribute_definition
*/
protected function source_block_node( $crawler, $block_attribute_definition ) {
// 'node' attribute usage was removed from core in 2018, but not officically deprecated until WordPress 6.1:
// https://github.com/WordPress/gutenberg/pull/44265.
// https://github.com/WordPress/gutenberg/pull/44265
// Parsing code for 'node' sources can be found here:
// https://github.com/WordPress/gutenberg/blob/dd0504bd34c29b5b2824d82c8d2bb3a8d0f071ec/packages/blocks/src/api/node.js#L125.
// https://github.com/WordPress/gutenberg/blob/dd0504bd34c29b5b2824d82c8d2bb3a8d0f071ec/packages/blocks/src/api/node.js#L125

$attribute_value = null;
$selector = $block_attribute_definition['selector'] ?? null;
Expand Down
139 changes: 139 additions & 0 deletions tests/parser/sources/test-source-rich-text.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
<?php
/**
* Class SourceHtmlTest
*
* @package vip-block-data-api
*/

namespace WPCOMVIP\BlockDataApi;

/**
* Test sourced attributes with the 'rich-text' type, added in WordPress 6.5:
* https://github.com/WordPress/gutenberg/pull/43204
*/
class SourceRichTextTest extends RegistryTestCase {
public function test_parse_rich_text_source() {
$this->register_block_with_attributes( 'test/code', [
'content' => [
'type' => 'rich-text',
'source' => 'rich-text',
'selector' => 'code',
],
] );

$html = '
<!-- wp:test/code -->
<pre class="wp-block-code"><code>This is a code block &lt;strong&gt;See!&lt;/strong&gt;</code></pre>
<!-- /wp:test/code -->
';

$expected_blocks = [
[
'name' => 'test/code',
'attributes' => [
'content' => 'This is a code block &lt;strong&gt;See!&lt;/strong&gt;',
],
],
];

$content_parser = new ContentParser( $this->registry );
$blocks = $content_parser->parse( $html );
$this->assertArrayHasKey( 'blocks', $blocks, sprintf( 'Unexpected parser output: %s', wp_json_encode( $blocks ) ) );
$this->assertArraySubset( $expected_blocks, $blocks['blocks'], true );
}

public function test_parse_rich_text_source__with_formatting() {
$this->register_block_with_attributes( 'test/captioned-image', [
'caption' => [
'type' => 'rich-text',
'source' => 'rich-text',
'selector' => 'figcaption',
],
] );

$html = '
<!-- wp:test/captioned-image -->
<figure>
<img src="http://example.com/image.jpg" />
<figcaption><strong>RICH</strong> text caption.</figcaption>
</figure>
<!-- /wp:test/captioned-image -->
';

$expected_blocks = [
[
'name' => 'test/captioned-image',
'attributes' => [
'caption' => '<strong>RICH</strong> text caption.',
],
],
];

$content_parser = new ContentParser( $this->registry );
$blocks = $content_parser->parse( $html );
$this->assertArrayHasKey( 'blocks', $blocks, sprintf( 'Unexpected parser output: %s', wp_json_encode( $blocks ) ) );
$this->assertArraySubset( $expected_blocks, $blocks['blocks'], true );
}

public function test_parse_rich_text_source__with_default_value() {
$this->register_block_with_attributes( 'test/image', [
'caption' => [
'type' => 'rich-text',
'source' => 'rich-text',
'selector' => 'figcaption',
'default' => 'Default rich-text caption',
],
] );

$html = '
<!-- wp:test/image -->
<img src="/test.jpg" />
<!-- /wp:test/image -->
';

$expected_blocks = [
[
'name' => 'test/image',
'attributes' => [
'caption' => 'Default rich-text caption',
],
],
];

$content_parser = new ContentParser( $this->registry );
$blocks = $content_parser->parse( $html );
$this->assertArrayHasKey( 'blocks', $blocks, sprintf( 'Unexpected parser output: %s', wp_json_encode( $blocks ) ) );
$this->assertArraySubset( $expected_blocks, $blocks['blocks'], true );
}

public function test_parse_rich_text_source__with_default_value_with_formatting() {
$this->register_block_with_attributes( 'test/image', [
'caption' => [
'type' => 'rich-text',
'source' => 'rich-text',
'selector' => 'figcaption',
'default' => 'Default <em>rich-text</em> caption',
],
] );

$html = '
<!-- wp:test/image -->
<img src="/test.jpg" />
<!-- /wp:test/image -->
';

$expected_blocks = [
[
'name' => 'test/image',
'attributes' => [
'caption' => 'Default <em>rich-text</em> caption',
],
],
];

$content_parser = new ContentParser( $this->registry );
$blocks = $content_parser->parse( $html );
$this->assertArrayHasKey( 'blocks', $blocks, sprintf( 'Unexpected parser output: %s', wp_json_encode( $blocks ) ) );
$this->assertArraySubset( $expected_blocks, $blocks['blocks'], true );
}
}
Loading