Skip to content

Commit

Permalink
Add a has_block() function. (#9058)
Browse files Browse the repository at this point in the history
  • Loading branch information
andreilupu authored and pento committed Aug 17, 2018
1 parent 72da0cd commit b38a937
Show file tree
Hide file tree
Showing 2 changed files with 142 additions and 2 deletions.
31 changes: 29 additions & 2 deletions lib/register.php
Original file line number Diff line number Diff line change
Expand Up @@ -365,7 +365,7 @@ function has_blocks( $post = null ) {
* @see gutenberg_parse_blocks()
*
* @since 0.5.0
* @deprecated 3.6.0 Use has_block()
* @deprecated 3.6.0 Use has_blocks()
*
* @param object $post Post.
* @return bool Whether the post has blocks.
Expand All @@ -384,7 +384,7 @@ function gutenberg_post_has_blocks( $post ) {
* @see gutenberg_parse_blocks()
*
* @since 1.6.0
* @deprecated 3.6.0 Use has_block()
* @deprecated 3.6.0 Use has_blocks()
*
* @param string $content Content to test.
* @return bool Whether the content contains blocks.
Expand All @@ -394,6 +394,33 @@ function gutenberg_content_has_blocks( $content ) {
return has_blocks( $content );
}

/**
* Determine whether a $post or a string contains a specific block type.
* This test optimizes for performance rather than strict accuracy, detecting
* the block type exists but not validating its structure.
* For strict accuracy, you should use the block parser on post content.
*
* @since 3.6.0
*
* @param string $block_type Full Block type to look for.
* @param int|string|WP_Post|null $post Optional. Post content, post ID, or post object. Defaults to global $post.
* @return bool Whether the post content contains the specified block.
*/
function has_block( $block_type, $post = null ) {
if ( ! has_blocks( $post ) ) {
return false;
}

if ( ! is_string( $post ) ) {
$wp_post = get_post( $post );
if ( $wp_post instanceof WP_Post ) {
$post = $wp_post->post_content;
}
}

return false !== strpos( $post, '<!-- wp:' . $block_type . ' ' );
}

/**
* Returns the current version of the block format that the content string is using.
*
Expand Down
113 changes: 113 additions & 0 deletions phpunit/class-block-type-test.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,50 @@
* Tests for WP_Block_Type
*/
class Block_Type_Test extends WP_UnitTestCase {
function setUp() {
parent::setUp();
}

/**
* Editor user ID.
*
* @var int
*/
protected static $editor_user_id;

/**
* ID for a post containing blocks.
*
* @var int
*/
protected static $post_with_blocks;

/**
* ID for a post without blocks.
*
* @var int
*/
protected static $post_without_blocks;

/**
* Set up before class.
*/
public static function wpSetUpBeforeClass() {
self::$editor_user_id = self::factory()->user->create( array(
'role' => 'editor',
) );

self::$post_with_blocks = self::factory()->post->create( array(
'post_title' => 'Example',
'post_content' => "<!-- wp:core/text {\"dropCap\":true} -->\n<p class=\"has-drop-cap\">Tester</p>\n<!-- /wp:core/text -->",
) );

self::$post_without_blocks = self::factory()->post->create( array(
'post_title' => 'Example',
'post_content' => 'Tester',
) );
}

function test_set_props() {
$name = 'core/dummy';
$args = array(
Expand Down Expand Up @@ -112,6 +156,75 @@ function test_prepare_attributes() {
), $prepared_attributes );
}

function test_has_block_with_mixed_content() {
$mixed_post_content = 'before' .
'<!-- wp:core/dummy --><!-- /wp:core/dummy -->' .
'<!-- wp:core/dummy_atts {"value":"b1"} --><!-- /wp:core/dummy_atts -->' .
'<!-- wp:core/dummy-child -->
<p>testing the test</p>
<!-- /wp:core/dummy-child -->' .
'between' .
'<!-- wp:core/self-close-dummy /-->' .
'<!-- wp:custom/dummy {"value":"b2"} /-->' .
'after';

$this->assertTrue( has_block( 'core/dummy', $mixed_post_content ) );

$this->assertTrue( has_block( 'core/dummy_atts', $mixed_post_content ) );

$this->assertTrue( has_block( 'core/dummy-child', $mixed_post_content ) );

$this->assertTrue( has_block( 'core/self-close-dummy', $mixed_post_content ) );

$this->assertTrue( has_block( 'custom/dummy', $mixed_post_content ) );

// checking for a partial block name should fail.
$this->assertFalse( has_block( 'core/dumm', $mixed_post_content ) );

// checking for a wrong namespace should fail.
$this->assertFalse( has_block( 'custom/dummy_atts', $mixed_post_content ) );

// checking for namespace only should not work. Or maybe ... ?
$this->assertFalse( has_block( 'core', $mixed_post_content ) );
}

function test_has_block_with_invalid_content() {
// some content with invalid HMTL comments and a single valid block.
$invalid_content = 'before' .
'<!- - wp:core/weird-space --><!-- /wp:core/weird-space -->' .
'<!--wp:core/untrimmed-left --><!-- /wp:core/untrimmed -->' .
'<!-- wp:core/dummy --><!-- /wp:core/dummy -->' .
'<!-- wp:core/untrimmed-right--><!-- /wp:core/untrimmed2 -->' .
'after';

$this->assertFalse( has_block( 'core/text', self::$post_without_blocks ) );

$this->assertFalse( has_block( 'core/weird-space', $invalid_content ) );

$this->assertFalse( has_block( 'core/untrimmed-left', $invalid_content ) );

$this->assertFalse( has_block( 'core/untrimmed-right', $invalid_content ) );

$this->assertTrue( has_block( 'core/dummy', $invalid_content ) );
}

function test_post_has_block() {
// should fail for a non-existent block `custom/dummy`.
$this->assertFalse( has_block( 'custom/dummy', self::$post_with_blocks ) );

// this functions should not work without the second param until the $post global is set.
$this->assertFalse( has_block( 'core/text' ) );
$this->assertFalse( has_block( 'core/dummy' ) );

global $post;
$post = get_post( self::$post_with_blocks );

// check if the function correctly detects content from the $post global.
$this->assertTrue( has_block( 'core/text' ) );
// even if it detects a proper $post global it should still be false for a missing block.
$this->assertFalse( has_block( 'core/dummy' ) );
}

function render_dummy_block( $attributes ) {
return json_encode( $attributes );
}
Expand Down

0 comments on commit b38a937

Please sign in to comment.