has_block

The timeline below displays how wordpress function has_block has changed across different WordPress versions. If a version is not listed, refer to the next available version below.

WordPress Version: 3.3

/**
 * Determines whether a $post or a string contains a specific block type.
 *
 * This test optimizes for performance rather than strict accuracy, detecting
 * whether the block type exists but not validating its structure and not checking
 * synced patterns (formerly called reusable blocks). For strict accuracy,
 * you should use the block parser on post content.
 *
 * @since 5.0.0
 *
 * @see parse_blocks()
 *
 * @param string                  $block_name 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_name, $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;
        }
    }
    /*
     * Normalize block name to include namespace, if provided as non-namespaced.
     * This matches behavior for WordPress 5.0.0 - 5.3.0 in matching blocks by
     * their serialized names.
     */
    if (!str_contains($block_name, '/')) {
        $block_name = 'core/' . $block_name;
    }
    // Test for existence of block by its fully qualified name.
    $has_block = str_contains($post, '<!-- wp:' . $block_name . ' ');
    if (!$has_block) {
        /*
         * If the given block name would serialize to a different name, test for
         * existence by the serialized form.
         */
        $serialized_block_name = strip_core_block_namespace($block_name);
        if ($serialized_block_name !== $block_name) {
            $has_block = str_contains($post, '<!-- wp:' . $serialized_block_name . ' ');
        }
    }
    return $has_block;
}

WordPress Version: 6.3

/**
 * Determines whether a $post or a string contains a specific block type.
 *
 * This test optimizes for performance rather than strict accuracy, detecting
 * whether the block type exists but not validating its structure and not checking
 * reusable blocks. For strict accuracy, you should use the block parser on post content.
 *
 * @since 5.0.0
 *
 * @see parse_blocks()
 *
 * @param string                  $block_name 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_name, $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;
        }
    }
    /*
     * Normalize block name to include namespace, if provided as non-namespaced.
     * This matches behavior for WordPress 5.0.0 - 5.3.0 in matching blocks by
     * their serialized names.
     */
    if (!str_contains($block_name, '/')) {
        $block_name = 'core/' . $block_name;
    }
    // Test for existence of block by its fully qualified name.
    $has_block = str_contains($post, '<!-- wp:' . $block_name . ' ');
    if (!$has_block) {
        /*
         * If the given block name would serialize to a different name, test for
         * existence by the serialized form.
         */
        $serialized_block_name = strip_core_block_namespace($block_name);
        if ($serialized_block_name !== $block_name) {
            $has_block = str_contains($post, '<!-- wp:' . $serialized_block_name . ' ');
        }
    }
    return $has_block;
}

WordPress Version: 6.1

/**
 * Determines whether a $post or a string contains a specific block type.
 *
 * This test optimizes for performance rather than strict accuracy, detecting
 * whether the block type exists but not validating its structure and not checking
 * reusable blocks. For strict accuracy, you should use the block parser on post content.
 *
 * @since 5.0.0
 *
 * @see parse_blocks()
 *
 * @param string                  $block_name 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_name, $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;
        }
    }
    /*
     * Normalize block name to include namespace, if provided as non-namespaced.
     * This matches behavior for WordPress 5.0.0 - 5.3.0 in matching blocks by
     * their serialized names.
     */
    if (false === strpos($block_name, '/')) {
        $block_name = 'core/' . $block_name;
    }
    // Test for existence of block by its fully qualified name.
    $has_block = false !== strpos($post, '<!-- wp:' . $block_name . ' ');
    if (!$has_block) {
        /*
         * If the given block name would serialize to a different name, test for
         * existence by the serialized form.
         */
        $serialized_block_name = strip_core_block_namespace($block_name);
        if ($serialized_block_name !== $block_name) {
            $has_block = false !== strpos($post, '<!-- wp:' . $serialized_block_name . ' ');
        }
    }
    return $has_block;
}

WordPress Version: 5.8

/**
 * Determine whether a $post or a string contains a specific block type.
 *
 * This test optimizes for performance rather than strict accuracy, detecting
 * whether the block type exists but not validating its structure and not checking
 * reusable blocks. For strict accuracy, you should use the block parser on post content.
 *
 * @since 5.0.0
 *
 * @see parse_blocks()
 *
 * @param string                  $block_name 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_name, $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;
        }
    }
    /*
     * Normalize block name to include namespace, if provided as non-namespaced.
     * This matches behavior for WordPress 5.0.0 - 5.3.0 in matching blocks by
     * their serialized names.
     */
    if (false === strpos($block_name, '/')) {
        $block_name = 'core/' . $block_name;
    }
    // Test for existence of block by its fully qualified name.
    $has_block = false !== strpos($post, '<!-- wp:' . $block_name . ' ');
    if (!$has_block) {
        /*
         * If the given block name would serialize to a different name, test for
         * existence by the serialized form.
         */
        $serialized_block_name = strip_core_block_namespace($block_name);
        if ($serialized_block_name !== $block_name) {
            $has_block = false !== strpos($post, '<!-- wp:' . $serialized_block_name . ' ');
        }
    }
    return $has_block;
}

WordPress Version: 5.5

/**
 * 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 5.0.0
 *
 * @see parse_blocks()
 *
 * @param string                  $block_name 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_name, $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;
        }
    }
    /*
     * Normalize block name to include namespace, if provided as non-namespaced.
     * This matches behavior for WordPress 5.0.0 - 5.3.0 in matching blocks by
     * their serialized names.
     */
    if (false === strpos($block_name, '/')) {
        $block_name = 'core/' . $block_name;
    }
    // Test for existence of block by its fully qualified name.
    $has_block = false !== strpos($post, '<!-- wp:' . $block_name . ' ');
    if (!$has_block) {
        /*
         * If the given block name would serialize to a different name, test for
         * existence by the serialized form.
         */
        $serialized_block_name = strip_core_block_namespace($block_name);
        if ($serialized_block_name !== $block_name) {
            $has_block = false !== strpos($post, '<!-- wp:' . $serialized_block_name . ' ');
        }
    }
    return $has_block;
}

WordPress Version: 3.1

/**
 * 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 5.0.0
 * @see parse_blocks()
 *
 * @param string                  $block_name 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_name, $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;
        }
    }
    /*
     * Normalize block name to include namespace, if provided as non-namespaced.
     * This matches behavior for WordPress 5.0.0 - 5.3.0 in matching blocks by
     * their serialized names.
     */
    if (false === strpos($block_name, '/')) {
        $block_name = 'core/' . $block_name;
    }
    // Test for existence of block by its fully qualified name.
    $has_block = false !== strpos($post, '<!-- wp:' . $block_name . ' ');
    if (!$has_block) {
        /*
         * If the given block name would serialize to a different name, test for
         * existence by the serialized form.
         */
        $serialized_block_name = strip_core_block_namespace($block_name);
        if ($serialized_block_name !== $block_name) {
            $has_block = false !== strpos($post, '<!-- wp:' . $serialized_block_name . ' ');
        }
    }
    return $has_block;
}

WordPress Version: 5.3

/**
 * 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 5.0.0
 * @see parse_blocks()
 *
 * @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 . ' ');
}

WordPress Version: 2.5

/**
 * 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 5.0.0
 * @see parse_blocks()
 *
 * @param string                  $block_name 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_name, $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;
        }
    }
    /*
     * Normalize block name to include namespace, if provided as non-namespaced.
     * This matches behavior for WordPress 5.0.0 - 5.3.0 in matching blocks by
     * their serialized names.
     */
    if (false === strpos($block_name, '/')) {
        $block_name = 'core/' . $block_name;
    }
    // Test for existence of block by its fully qualified name.
    $has_block = false !== strpos($post, '<!-- wp:' . $block_name . ' ');
    if (!$has_block) {
        /*
         * If the given block name would serialize to a different name, test for
         * existence by the serialized form.
         */
        $serialized_block_name = strip_core_block_namespace($block_name);
        if ($serialized_block_name !== $block_name) {
            $has_block = false !== strpos($post, '<!-- wp:' . $serialized_block_name . ' ');
        }
    }
    return $has_block;
}

WordPress Version: 2.3

/**
 * 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 5.0.0
 * @see parse_blocks()
 *
 * @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 . ' ');
}

WordPress Version: .20

/**
 * 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 5.0.0
 * @see parse_blocks()
 *
 * @param string                  $block_name 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_name, $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;
        }
    }
    /*
     * Normalize block name to include namespace, if provided as non-namespaced.
     * This matches behavior for WordPress 5.0.0 - 5.3.0 in matching blocks by
     * their serialized names.
     */
    if (false === strpos($block_name, '/')) {
        $block_name = 'core/' . $block_name;
    }
    // Test for existence of block by its fully qualified name.
    $has_block = false !== strpos($post, '<!-- wp:' . $block_name . ' ');
    if (!$has_block) {
        /*
         * If the given block name would serialize to a different name, test for
         * existence by the serialized form.
         */
        $serialized_block_name = strip_core_block_namespace($block_name);
        if ($serialized_block_name !== $block_name) {
            $has_block = false !== strpos($post, '<!-- wp:' . $serialized_block_name . ' ');
        }
    }
    return $has_block;
}

WordPress Version: 2.2

/**
 * 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 5.0.0
 * @see parse_blocks()
 *
 * @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 . ' ');
}

WordPress Version: .10

/**
 * 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 5.0.0
 * @see parse_blocks()
 *
 * @param string                  $block_name 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_name, $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;
        }
    }
    /*
     * Normalize block name to include namespace, if provided as non-namespaced.
     * This matches behavior for WordPress 5.0.0 - 5.3.0 in matching blocks by
     * their serialized names.
     */
    if (false === strpos($block_name, '/')) {
        $block_name = 'core/' . $block_name;
    }
    // Test for existence of block by its fully qualified name.
    $has_block = false !== strpos($post, '<!-- wp:' . $block_name . ' ');
    if (!$has_block) {
        /*
         * If the given block name would serialize to a different name, test for
         * existence by the serialized form.
         */
        $serialized_block_name = strip_core_block_namespace($block_name);
        if ($serialized_block_name !== $block_name) {
            $has_block = false !== strpos($post, '<!-- wp:' . $serialized_block_name . ' ');
        }
    }
    return $has_block;
}

WordPress Version: 5.2

/**
 * 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 5.0.0
 * @see parse_blocks()
 *
 * @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 . ' ');
}

WordPress Version: 1.4

/**
 * 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 5.0.0
 * @see parse_blocks()
 *
 * @param string                  $block_name 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_name, $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;
        }
    }
    /*
     * Normalize block name to include namespace, if provided as non-namespaced.
     * This matches behavior for WordPress 5.0.0 - 5.3.0 in matching blocks by
     * their serialized names.
     */
    if (false === strpos($block_name, '/')) {
        $block_name = 'core/' . $block_name;
    }
    // Test for existence of block by its fully qualified name.
    $has_block = false !== strpos($post, '<!-- wp:' . $block_name . ' ');
    if (!$has_block) {
        /*
         * If the given block name would serialize to a different name, test for
         * existence by the serialized form.
         */
        $serialized_block_name = strip_core_block_namespace($block_name);
        if ($serialized_block_name !== $block_name) {
            $has_block = false !== strpos($post, '<!-- wp:' . $serialized_block_name . ' ');
        }
    }
    return $has_block;
}

WordPress Version: 1.2

/**
 * 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 5.0.0
 * @see parse_blocks()
 *
 * @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 . ' ');
}

WordPress Version: .10

/**
 * 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 5.0.0
 * @see parse_blocks()
 *
 * @param string                  $block_name 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_name, $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;
        }
    }
    /*
     * Normalize block name to include namespace, if provided as non-namespaced.
     * This matches behavior for WordPress 5.0.0 - 5.3.0 in matching blocks by
     * their serialized names.
     */
    if (false === strpos($block_name, '/')) {
        $block_name = 'core/' . $block_name;
    }
    // Test for existence of block by its fully qualified name.
    $has_block = false !== strpos($post, '<!-- wp:' . $block_name . ' ');
    if (!$has_block) {
        /*
         * If the given block name would serialize to a different name, test for
         * existence by the serialized form.
         */
        $serialized_block_name = strip_core_block_namespace($block_name);
        if ($serialized_block_name !== $block_name) {
            $has_block = false !== strpos($post, '<!-- wp:' . $serialized_block_name . ' ');
        }
    }
    return $has_block;
}

WordPress Version: 5.1

/**
 * 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 5.0.0
 * @see parse_blocks()
 *
 * @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 . ' ');
}

WordPress Version: 0.8

/**
 * 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 5.0.0
 * @see parse_blocks()
 *
 * @param string                  $block_name 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_name, $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;
        }
    }
    /*
     * Normalize block name to include namespace, if provided as non-namespaced.
     * This matches behavior for WordPress 5.0.0 - 5.3.0 in matching blocks by
     * their serialized names.
     */
    if (false === strpos($block_name, '/')) {
        $block_name = 'core/' . $block_name;
    }
    // Test for existence of block by its fully qualified name.
    $has_block = false !== strpos($post, '<!-- wp:' . $block_name . ' ');
    if (!$has_block) {
        /*
         * If the given block name would serialize to a different name, test for
         * existence by the serialized form.
         */
        $serialized_block_name = strip_core_block_namespace($block_name);
        if ($serialized_block_name !== $block_name) {
            $has_block = false !== strpos($post, '<!-- wp:' . $serialized_block_name . ' ');
        }
    }
    return $has_block;
}

WordPress Version: 0.3

/**
 * 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 5.0.0
 * @see parse_blocks()
 *
 * @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 . ' ');
}

WordPress Version: .20

/**
 * 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 5.0.0
 * @see parse_blocks()
 *
 * @param string                  $block_name 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_name, $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;
        }
    }
    /*
     * Normalize block name to include namespace, if provided as non-namespaced.
     * This matches behavior for WordPress 5.0.0 - 5.3.0 in matching blocks by
     * their serialized names.
     */
    if (false === strpos($block_name, '/')) {
        $block_name = 'core/' . $block_name;
    }
    // Test for existence of block by its fully qualified name.
    $has_block = false !== strpos($post, '<!-- wp:' . $block_name . ' ');
    if (!$has_block) {
        /*
         * If the given block name would serialize to a different name, test for
         * existence by the serialized form.
         */
        $serialized_block_name = strip_core_block_namespace($block_name);
        if ($serialized_block_name !== $block_name) {
            $has_block = false !== strpos($post, '<!-- wp:' . $serialized_block_name . ' ');
        }
    }
    return $has_block;
}

WordPress Version: 0.2

/**
 * 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 5.0.0
 * @see parse_blocks()
 *
 * @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 . ' ');
}

WordPress Version: .10

/**
 * 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 5.0.0
 * @see parse_blocks()
 *
 * @param string                  $block_name 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_name, $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;
        }
    }
    /*
     * Normalize block name to include namespace, if provided as non-namespaced.
     * This matches behavior for WordPress 5.0.0 - 5.3.0 in matching blocks by
     * their serialized names.
     */
    if (false === strpos($block_name, '/')) {
        $block_name = 'core/' . $block_name;
    }
    // Test for existence of block by its fully qualified name.
    $has_block = false !== strpos($post, '<!-- wp:' . $block_name . ' ');
    if (!$has_block) {
        /*
         * If the given block name would serialize to a different name, test for
         * existence by the serialized form.
         */
        $serialized_block_name = strip_core_block_namespace($block_name);
        if ($serialized_block_name !== $block_name) {
            $has_block = false !== strpos($post, '<!-- wp:' . $serialized_block_name . ' ');
        }
    }
    return $has_block;
}

WordPress Version: 5.0

/**
 * 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 5.0.0
 * @see parse_blocks()
 *
 * @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 . ' ');
}