[ Index ]

PHP Cross Reference of WordPress Trunk (Updated Daily)

Search

title

Body

[close]

/wp-includes/ -> class-wp-block-processor.php (summary)

Efficiently scan through block structure in document without parsing the entire block tree and all of its JSON attributes into memory.

File Size: 1983 lines (69 kb)
Included or required:0 times
Referenced: 0 times
Includes or requires: 0 files

Defines 1 class

WP_Block_Processor:: (24 methods):
  __construct()
  next_block()
  next_delimiter()
  next_token()
  get_breadcrumbs()
  get_depth()
  extract_block()
  find_html_comment_end()
  get_last_error()
  get_last_json_error()
  get_delimiter_type()
  has_closing_flag()
  is_block_type()
  are_equal_block_types()
  opens_block()
  is_html()
  is_non_whitespace_html()
  get_html_content()
  get_block_type()
  get_printable_block_type()
  normalize_block_type()
  get_attributes()
  allocate_and_return_parsed_attributes()
  get_span()


Class: WP_Block_Processor  - X-Ref

Class for efficiently scanning through block structure in a document
without parsing the entire block tree and JSON attributes into memory.

## Overview

This class is designed to help analyze and modify block structure in a
streaming fashion and to bridge the gap between parsed block trees and
the text representing them.

Use-cases for this class include but are not limited to:

- Counting block types in a document.
- Queuing stylesheets based on the presence of various block types.
- Modifying blocks of a given type, i.e. migrations, updates, and styling.
- Searching for content of specific kinds, e.g. checking for blocks
with certain theme support attributes, or block bindings.
- Adding CSS class names to the element wrapping a block’s inner blocks.

> *Note!* If a fully-parsed block tree of a document is necessary, including
>         all the parsed JSON attributes, nested blocks, and HTML, consider
>         using {@see \parse_blocks()} instead which will parse the document
>         in one swift pass.

For typical usage, jump first to the methods {@see self::next_block()},
{@see self::next_delimiter()}, or {@see self::next_token()}.

### Values

As a lower-level interface than {@see parse_blocks()} this class follows
different performance-focused values:

- Minimize allocations so that documents of any size may be processed
on a fixed or marginal amount of memory.
- Make hidden costs explicit so that calling code only has to pay the
performance penalty for features it needs.
- Operate with a streaming and re-entrant design to make it possible
to operate on chunks of a document and to resume after pausing.

This means that some operations might appear more cumbersome than one
might expect. This design tradeoff opens up opportunity to wrap this in
a convenience class to add higher-level functionality.

## Concepts

All text documents can be considered a block document containing a combination
of “freeform HTML” and explicit block structure. Block structure forms through
special HTML comments called _delimiters_ which include a block type and,
optionally, block attributes encoded as a JSON object payload.

This processor is designed to scan through a block document from delimiter to
delimiter, tracking how the delimiters impact the structure of the document.
Spans of HTML appear between delimiters. If these spans exist at the top level
of the document, meaning there is no containing block around them, they are
considered freeform HTML content. If, however, they appear _inside_ block
structure they are interpreted as `innerHTML` for the containing block.

### Tokens and scanning

As the processor scans through a document is reports information about the token
on which is pauses. Tokens represent spans of text in the input comprising block
delimiters and spans of HTML.

- {@see self::next_token()} visits every contiguous subspan of text in the
input document. This includes all explicit block comment delimiters and spans
of HTML content (whether freeform or inner HTML).
- {@see self::next_delimiter()} visits every explicit block comment delimiter
unless passed a block type which covers freeform HTML content. In these cases
it will stop at top-level spans of HTML and report a `null` block type.
- {@see self::next_block()} visits every block delimiter which _opens_ a block.
This includes opening block delimiters as well as void block delimiters. With
the same exception as above for freeform HTML block types, this will visit
top-level spans of HTML content.

When matched on a particular token, the following methods provide structural
and textual information about it:

- {@see self::get_delimiter_type()} reports whether the delimiter is an opener,
a closer, or if it represents a whole void block.
- {@see self::get_block_type()} reports the fully-qualified block type which
the delimiter represents.
- {@see self::get_printable_block_type()} reports the fully-qualified block type,
but returns `core/freeform` instead of `null` for top-level freeform HTML content.
- {@see self::is_block_type()} indicates if the delimiter represents a block of
the given block type, or wildcard or pseudo-block type described below.
- {@see self::opens_block()} indicates if the delimiter opens a block of one
of the provided block types. Opening, void, and top-level freeform HTML content
all open blocks.
- {@see static::get_attributes()} is currently reserved for a future streaming
JSON parser class.
- {@see self::allocate_and_return_parsed_attributes()} extracts the JSON attributes
for delimiters which open blocks and return the fully-parsed attributes as an
associative array. {@see static::get_last_json_error()} for when this fails.
- {@see self::is_html()} indicates if the token is a span of HTML which might
be top-level freeform content or a block’s inner HTML.
- {@see self::get_html_content()} returns the span of HTML.
- {@see self::get_span()} for the byte offset and length into the input document
representing the token.

It’s possible for the processor to fail to scan forward if the input document ends
in a proper prefix of an explicit block comment delimiter. For example, if the input
ends in `<!-- wp:` then it _might_ be the start of another delimiter. The parser
cannot know, however, and therefore refuses to proceed. {@see static::get_last_error()}
to distinguish between a failure to find the next token and an incomplete input.

### Block types

A block’s “type” comprises an optional _namespace_ and _name_. If the namespace
isn’t provided it will be interpreted as the implicit `core` namespace. For example,
the type `gallery` is the name of the block in the `core` namespace, but the type
`abc/gallery` is the _fully-qualified_ block type for the block whose name is still
`gallery`, but in the `abc` namespace.

Methods on this class are aware of this block naming semantic and anywhere a block
type is an argument to a method it will be normalized to account for implicit namespaces.
Passing `paragraph` is the same as passing `core/paragraph`. On the contrary, anywhere
this class returns a block type, it will return the fully-qualified and normalized form.
For example, for the `<!-- wp:group -->` delimiter it will return `core/group` as the
block type.

There are two special block types that change the behavior of the processor:

- The wildcard `*` represents _any block_. In addition to matching all block types,
it also represents top-level freeform HTML whose block type is reported as `null`.

- The `core/freeform` block type is a pseudo-block type which explicitly matches
top-level freeform HTML.

These special block types can be passed into any method which searches for blocks.

There is one additional special block type which may be returned from
{@see self::get_printable_block_type()}. This is the `#innerHTML` type, which
indicates that the HTML span on which the processor is paused is inner HTML for
a containing block.

### Spans of HTML

Non-block content plays a complicated role in processing block documents. This
processor exposes tools to help work with these spans of HTML.

- {@see self::is_html()} indicates if the processor is paused at a span of
HTML but does not differentiate between top-level freeform content and inner HTML.
- {@see self::is_non_whitespace_html()} indicates not only if the processor
is paused at a span of HTML, but also whether that span incorporates more than
whitespace characters. Because block serialization often inserts newlines between
block comment delimiters, this is useful for distinguishing “real” freeform
content from purely aesthetic syntax.
- {@see self::is_block_type()} matches top-level freeform HTML content when
provided one of the special block types described above.

### Block structure

As the processor traverses block delimiters it maintains a stack of which blocks are
open at the given place in the document where it’s paused. This stack represents the
block structure of a document and is used to determine where blocks end, which blocks
represent inner blocks, whether a span of HTML is top-level freeform content, and
more. Investigate the stack with {@see self::get_breadcrumbs()}, which returns an
array of block types starting at the outermost-open block and descending to the
currently-visited block.

Unlike {@parse_blocks()}, spans of HTML appear in this structure as the special
reported block type `#html`. Such a span represents inner HTML for a block if the
depth reported by {@see self::get_depth()} is greater than one.

It will generally not be necessary to inspect the stack of open blocks, though
depth may be important for finding where blocks end. When visiting a block opener,
the depth will have been increased before pausing; in contrast the depth is
decremented before visiting a closer. This makes the following an easy way to
determine if a block is still open.

Example:

$depth = $processor->get_depth();
while ( $processor->next_token() && $processor->get_depth() > $depth ) {
continue
}
// Processor is now paused at the token immediately following the closed block.

#### Extracting blocks

A unique feature of this processor is the ability to return the same output as
{@see \parse_blocks()} would produce, but for a subset of the input document.
For example, it’s possible to extract an image block, manipulate that parsed
block, and re-serialize it into the original document. It’s possible to do so
while skipping over the parse of the rest of the document.

{@see self::extract_block()} will scan forward from the current block opener
and build the parsed block structure until the current block is closed. It will
include all inner HTML and inner blocks, and parse all of the inner blocks. It
can be used to extract a block at any depth in the document, helpful for operating
on blocks within nested structure.

Example:

if ( ! $processor->next_block( 'gallery' ) ) {
return $post_content;
}

$gallery_at    = $processor->get_span()->start;
$gallery_block = $processor->extract_block();
$after_gallery = $processor->get_span()->start;
return (
substr( $post_content, 0, $gallery_at ) .
serialize_block( modify_gallery( $gallery_block ) .
substr( $post_content, $after_gallery )
);

#### Handling of malformed structure

There are situations where closing block delimiters appear for which no open block
exists, or where a document ends before a block is closed, or where a closing block
delimiter appears but references a different block type than the most-recently
opened block does. In all of these cases, the stack of open blocks should mirror
the behavior in {@see \parse_blocks()}.

Unlike {@see \parse_blocks()}, however, this processor can still operate on the
invalid block delimiters. It provides a few functions which can be used for building
custom and non-spec-compliant error handling.

- {@see self::has_closing_flag()} indicates if the block delimiter contains the
closing flag at the end. Some invalid block delimiters might contain both the
void and closing flag, in which case {@see self::get_delimiter_type()} will
report that it’s a void block.
- {@see static::get_last_error()} indicates if the processor reached an invalid
block closing. Depending on the context, {@see \parse_blocks()} might instead
ignore the token or treat it as freeform HTML content.

## Static helpers

This class provides helpers for performing semantic block-related operations.

- {@see self::normalize_block_type()} takes a block type with or without the
implicit `core` namespace and returns a fully-qualified block type.
- {@see self::are_equal_block_types()} indicates if two spans across one or
more input texts represent the same fully-qualified block type.

## Subclassing

This processor is designed to accurately parse a block document. Therefore, many
of its methods are not meant for subclassing. However, overall this class supports
building higher-level convenience classes which may choose to subclass it. For those
classes, avoid re-implementing methods except for the list below. Instead, create
new names representing the higher-level concepts being introduced. For example, instead
of creating a new method named `next_block()` which only advances to blocks of a given
kind, consider creating a new method named something like `next_layout_block()` which
won’t interfere with the base class method.

- {@see static::get_last_error()} may be reimplemented to report new errors in the subclass
which aren’t intrinsic to block parsing.
- {@see static::get_attributes()} may be reimplemented to provide a streaming interface
to reading and modifying a block’s JSON attributes. It should be fast and memory efficient.
- {@see static::get_last_json_error()} may be reimplemented to report new errors introduced
with a reimplementation of {@see static::get_attributes()}.

__construct( string $source_text )   X-Ref
Creates a new block processor.

Example:

$processor = new WP_Block_Processor( $post_content );
if ( $processor->next_block( 'core/image' ) ) {
echo "Found an image!\n";
}

param: string $source_text Input document potentially containing block content.

next_block( ?string $block_type = null )   X-Ref
Advance to the next block delimiter which opens a block, indicating if one was found.

Delimiters which open blocks include opening and void block delimiters. To visit
freeform HTML content, pass the wildcard “*” as the block type.

Use this function to walk through the blocks in a document, pausing where they open.

Example blocks:

// The first delimiter opens the paragraph block.
<⃨!⃨-⃨-⃨ ⃨w⃨p⃨:⃨p⃨a⃨r⃨a⃨g⃨r⃨a⃨p⃨h⃨ ⃨-⃨-⃨>⃨<p>Content</p><!-- /wp:paragraph-->

// The void block is the first opener in this sequence of closers.
<!-- /wp:group --><⃨!⃨-⃨-⃨ ⃨w⃨p⃨:⃨s⃨p⃨a⃨c⃨e⃨r⃨ ⃨{⃨"⃨h⃨e⃨i⃨g⃨h⃨t⃨"⃨:⃨"⃨2⃨0⃨0⃨p⃨x⃨"⃨}⃨ ⃨/⃨-⃨-⃨>⃨<!-- /wp:group -->

// If, however, `*` is provided as the block type, freeform content is matched.
<⃨h⃨2⃨>⃨M⃨y⃨ ⃨s⃨y⃨n⃨o⃨p⃨s⃨i⃨s⃨<⃨/⃨h⃨2⃨>⃨\⃨n⃨<!-- wp:my/table-of-contents /-->

// Inner HTML is never freeform content, and will not be matched even with the wildcard.
<!-- /wp:list-item --></ul><!-- /wp:list --><⃨!⃨-⃨-⃨ ⃨w⃨p⃨:⃨p⃨a⃨r⃨a⃨g⃨r⃨a⃨p⃨h⃨ ⃨-⃨>⃨<p>

Example:

// Find all textual ranges of image block opening delimiters.
$images = array();
$processor = new WP_Block_Processor( $html );
while ( $processor->next_block( 'core/image' ) ) {
$images[] = $processor->get_span();
}

In some cases it may be useful to conditionally visit the implicit freeform
blocks, such as when determining if a post contains freeform content that
isn’t purely whitespace.

Example:

$seen_block_types = [];
$block_type       = '*';
$processor        = new WP_Block_Processor( $html );
while ( $processor->next_block( $block_type ) {
// Stop wasting time visiting freeform blocks after one has been found.
if (
'*' === $block_type &&
null === $processor->get_block_type() &&
$processor->is_non_whitespace_html()
) {
$block_type = null;
$seen_block_types['core/freeform'] = true;
continue;
}

$seen_block_types[ $processor->get_block_type() ] = true;
}

param: string|null $block_type Optional. If provided, advance until a block of this type is found.
return: bool Whether an opening delimiter for a block was found.

next_delimiter( ?string $block_name = null )   X-Ref
Advance to the next block delimiter in a document, indicating if one was found.

Delimiters may include invalid JSON. This parser does not attempt to parse the
JSON attributes until requested; when invalid, the attributes will be null. This
matches the behavior of {@see \parse_blocks()}. To visit freeform HTML content,
pass the wildcard “*” as the block type.

Use this function to walk through the block delimiters in a document.

Example delimiters:

<!-- wp:paragraph {"dropCap": true} -->
<!-- wp:separator /-->
<!-- /wp:paragraph -->

// If the wildcard `*` is provided as the block type, freeform content is matched.
<⃨h⃨2⃨>⃨M⃨y⃨ ⃨s⃨y⃨n⃨o⃨p⃨s⃨i⃨s⃨<⃨/⃨h⃨2⃨>⃨\⃨n⃨<!-- wp:my/table-of-contents /-->

// Inner HTML is never freeform content, and will not be matched even with the wildcard.
...</ul><⃨!⃨-⃨-⃨ ⃨/⃨w⃨p⃨:⃨l⃨i⃨s⃨t⃨ ⃨-⃨-⃨>⃨<!-- wp:paragraph --><p>

Example:

$html      = '<!-- wp:void /-->\n<!-- wp:void /-->';
$processor = new WP_Block_Processor( $html );
while ( $processor->next_delimiter() {
// Runs twice, seeing both void blocks of type “core/void.”
}

$processor = new WP_Block_Processor( $html );
while ( $processor->next_delimiter( '*' ) ) {
// Runs thrice, seeing the void block, the newline span, and the void block.
}

param: string|null $block_name Optional. Keep searching until a block of this name is found.
return: bool Whether a block delimiter was matched.

next_token()   X-Ref
Advance to the next block delimiter or HTML span in a document, indicating if one was found.

This function steps through every syntactic chunk in a document. This includes explicit
block comment delimiters, freeform non-block content, and inner HTML segments.

Example tokens:

<!-- wp:paragraph {"dropCap": true} -->
<!-- wp:separator /-->
<!-- /wp:paragraph -->
<p>Normal HTML content</p>
Plaintext content too!

Example:

// Find span containing wrapping HTML element surrounding inner blocks.
$processor = new WP_Block_Processor( $html );
if ( ! $processor->next_block( 'gallery' ) ) {
return null;
}

$containing_span = null;
while ( $processor->next_token() && $processor->is_html() ) {
$containing_span = $processor->get_span();
}

This method will visit all HTML spans including those forming freeform non-block
content as well as those which are part of a block’s inner HTML.

return: bool Whether a token was matched or the end of the document was reached without finding any.

get_breadcrumbs()   X-Ref
Returns an array containing the names of the currently-open blocks, in order
from outermost to innermost, with HTML spans indicated as “#html”.

Example:

// Freeform HTML content is an HTML span.
$processor = new WP_Block_Processor( 'Just text' );
$processor->next_token();
array( '#text' ) === $processor->get_breadcrumbs();

$processor = new WP_Block_Processor( '<!-- wp:a --><!-- wp:b --><!-- wp:c /--><!-- /wp:b --><!-- /wp:a -->' );
$processor->next_token();
array( 'core/a' ) === $processor->get_breadcrumbs();
$processor->next_token();
array( 'core/a', 'core/b' ) === $processor->get_breadcrumbs();
$processor->next_token();
// Void blocks are only open while visiting them.
array( 'core/a', 'core/b', 'core/c' ) === $processor->get_breadcrumbs();
$processor->next_token();
// Blocks are closed before visiting their closing delimiter.
array( 'core/a' ) === $processor->get_breadcrumbs();
$processor->next_token();
array() === $processor->get_breadcrumbs();

// Inner HTML is also an HTML span.
$processor = new WP_Block_Processor( '<!-- wp:a -->Inner HTML<!-- /wp:a -->' );
$processor->next_token();
$processor->next_token();
array( 'core/a', '#html' ) === $processor->get_breadcrumbs();

return: string[]

get_depth()   X-Ref
Returns the depth of the open blocks where the processor is currently matched.

Depth increases before visiting openers and void blocks and decreases before
visiting closers. HTML spans behave like void blocks.

return: int

extract_block()   X-Ref
Extracts a block object, and all inner content, starting at a matched opening
block delimiter, or at a matched top-level HTML span as freeform HTML content.

Use this function to extract some blocks within a document, but not all. For example,
one might want to find image galleries, parse them, modify them, and then reserialize
them in place.

Once this function returns, the parser will be matched on token following the close
of the given block.

The return type of this method is compatible with the return of {@see \parse_blocks()}.

Example:

$processor = new WP_Block_Processor( $post_content );
if ( ! $processor->next_block( 'gallery' ) ) {
return $post_content;
}

$gallery_at  = $processor->get_span()->start;
$gallery     = $processor->extract_block();
$ends_before = $processor->get_span();
$ends_before = $ends_before->start ?? strlen( $post_content );

$new_gallery = update_gallery( $gallery );
$new_gallery = serialize_block( $new_gallery );

return (
substr( $post_content, 0, $gallery_at ) .
$new_gallery .
substr( $post_content, $ends_before )
);

return: array[]|null {

find_html_comment_end( int $comment_starting_at, int $search_end )   X-Ref
Returns the byte-offset after the ending character of an HTML comment,
assuming the proper starting byte offset.

param: int $comment_starting_at Where the HTML comment started, the leading `<`.
param: int $search_end          Last offset in which to search, for limiting search span.
return: int Offset after the current HTML comment ends, or `$search_end` if no end was found.

get_last_error()   X-Ref
Indicates if the last attempt to parse a block comment delimiter
failed, if set, otherwise `null` if the last attempt succeeded.

return: string|null Error from last attempt at parsing next block delimiter,

get_last_json_error()   X-Ref
Indicates if the last attempt to parse a block’s JSON attributes failed.

return: int JSON_ERROR_ code from last attempt to parse block JSON attributes.

get_delimiter_type()   X-Ref
Returns the type of the block comment delimiter.

One of:

- {@see self::OPENER}
- {@see self::CLOSER}
- {@see self::VOID}
- `null`

return: string|null type of the block comment delimiter, if currently matched.

has_closing_flag()   X-Ref
Returns whether the delimiter contains the closing flag.

This should be avoided except in cases of custom error-handling
with block closers containing the void flag. For normative use,
{@see self::get_delimiter_type()}.

return: bool Whether the currently-matched block delimiter contains the closing flag.

is_block_type( string $block_type )   X-Ref
Indicates if the block delimiter represents a block of the given type.

Since the “core” namespace may be implicit, it’s allowable to pass
either the fully-qualified block type with namespace and block name
as well as the shorthand version only containing the block name, if
the desired block is in the “core” namespace.

Since freeform HTML content is non-block content, it has no block type.
Passing the wildcard “*” will, however, return true for all block types,
even the implicit freeform content, though not for spans of inner HTML.

Example:

$is_core_paragraph = $processor->is_block_type( 'paragraph' );
$is_core_paragraph = $processor->is_block_type( 'core/paragraph' );
$is_formula        = $processor->is_block_type( 'math-block/formula' );

param: string $block_type Block type name for the desired block.
return: bool Whether this delimiter represents a block of the given type.

are_equal_block_types( string $a_text, int $a_at, int $a_length, string $b_text, int $b_at, int $b_length )   X-Ref
Given two spans of text, indicate if they represent identical block types.

This function normalizes block types to account for implicit core namespacing.

Note! This function only returns valid results when the complete block types are
represented in the span offsets and lengths. This means that the full optional
namespace and block name must be represented in the input arguments.

Example:

0    5   10   15   20   25   30   35   40
$text = '<!-- wp:block --><!-- /wp:core/block -->';

true  === WP_Block_Processor::are_equal_block_types( $text, 9, 5, $text, 27, 10 );
false === WP_Block_Processor::are_equal_block_types( $text, 9, 5, 'my/block', 0, 8 );

param: string $a_text   Text in which first block type appears.
param: int    $a_at     Byte offset into text in which first block type starts.
param: int    $a_length Byte length of first block type.
param: string $b_text   Text in which second block type appears (may be the same as the first text).
param: int    $b_at     Byte offset into text in which second block type starts.
param: int    $b_length Byte length of second block type.
return: bool Whether the spans of text represent identical block types, normalized for namespacing.

opens_block( string ...$block_type )   X-Ref
Indicates if the matched delimiter is an opening or void delimiter of the given type,
if a type is provided, otherwise if it opens any block or implicit freeform HTML content.

This is a helper method to ease handling of code inspecting where blocks start, and for
checking if the blocks are of a given type. The function is variadic to allow for
checking if the delimiter opens one of many possible block types.

To advance to the start of a block {@see self::next_block()}.

Example:

$processor = new WP_Block_Processor( $html );
while ( $processor->next_delimiter() ) {
if ( $processor->opens_block( 'core/code', 'syntaxhighlighter/code' ) ) {
echo "Found code!";
continue;
}

if ( $processor->opens_block( 'core/image' ) ) {
echo "Found an image!";
continue;
}

if ( $processor->opens_block() ) {
echo "Found a new block!";
}
}

param: string[] $block_type Optional. Is the matched block type one of these?
return: bool Whether the matched block delimiter opens a block, and whether it

is_html()   X-Ref
Indicates if the matched delimiter is an HTML span.

return: bool Whether the processor is matched on an HTML span.

is_non_whitespace_html()   X-Ref
Indicates if the matched delimiter is an HTML span and comprises more
than whitespace characters, i.e. contains real content.

Many block serializers introduce newlines between block delimiters,
so the presence of top-level non-block content does not imply that
there are “real” freeform HTML blocks. Checking if there is content
beyond whitespace is a more certain check, such as for determining
whether to load CSS for the freeform or fallback block type.

return: bool Whether the currently-matched delimiter is an HTML

get_html_content()   X-Ref
Returns the string content of a matched HTML span, or `null` otherwise.

return: string|null Raw HTML content, or `null` if not currently matched on HTML.

get_block_type()   X-Ref
Allocates a substring for the block type and returns the fully-qualified
name, including the namespace, if matched on a delimiter, otherwise `null`.

This function is like {@see self::get_printable_block_type()} but when
paused on a freeform HTML block, will return `null` instead of “core/freeform”.
The `null` behavior matches what {@see \parse_blocks()} returns but may not
be as useful as having a string value.

This function allocates a substring for the given block type. This
allocation will be small and likely fine in most cases, but it's
preferable to call {@see self::is_block_type()} if only needing
to know whether the delimiter is for a given block type, as that
function is more efficient for this purpose and avoids the allocation.

Example:

// Avoid.
'core/paragraph' = $processor->get_block_type();

// Prefer.
$processor->is_block_type( 'core/paragraph' );
$processor->is_block_type( 'paragraph' );
$processor->is_block_type( 'core/freeform' );

// Freeform HTML content has no block type.
$processor = new WP_Block_Processor( 'non-block content' );
$processor->next_token();
null === $processor->get_block_type();

return: string|null Fully-qualified block namespace and type, e.g. "core/paragraph",

get_printable_block_type()   X-Ref
Allocates a printable substring for the block type and returns the fully-qualified
name, including the namespace, if matched on a delimiter or freeform block, otherwise `null`.

This function is like {@see self::get_block_type()} but when paused on a freeform
HTML block, will return “core/freeform” instead of `null`. The `null` behavior matches
what {@see \parse_blocks()} returns but may not be as useful as having a string value.

This function allocates a substring for the given block type. This
allocation will be small and likely fine in most cases, but it's
preferable to call {@see self::is_block_type()} if only needing
to know whether the delimiter is for a given block type, as that
function is more efficient for this purpose and avoids the allocation.

Example:

// Avoid.
'core/paragraph' = $processor->get_printable_block_type();

// Prefer.
$processor->is_block_type( 'core/paragraph' );
$processor->is_block_type( 'paragraph' );
$processor->is_block_type( 'core/freeform' );

// Freeform HTML content is given an implicit type.
$processor = new WP_Block_Processor( 'non-block content' );
$processor->next_token();
'core/freeform' === $processor->get_printable_block_type();

return: string|null Fully-qualified block namespace and type, e.g. "core/paragraph",

normalize_block_type( string $block_type )   X-Ref
Normalizes a block name to ensure that missing implicit “core” namespaces are present.

Example:

'core/paragraph' === WP_Block_Processor::normalize_block_byte( 'paragraph' );
'core/paragraph' === WP_Block_Processor::normalize_block_byte( 'core/paragraph' );
'my/paragraph'   === WP_Block_Processor::normalize_block_byte( 'my/paragraph' );

param: string $block_type Valid block name, potentially without a namespace.
return: string Fully-qualified block type including namespace.

get_attributes()   X-Ref
Returns a lazy wrapper around the block attributes, which can be used
for efficiently interacting with the JSON attributes.

This stub hints that there should be a lazy interface for parsing
block attributes but doesn’t define it. It serves both as a placeholder
for one to come as well as a guard against implementing an eager
function in its place.

return: never

allocate_and_return_parsed_attributes()   X-Ref
Attempts to parse and return the entire JSON attributes from the delimiter,
allocating memory and processing the JSON span in the process.

This does not return any parsed attributes for a closing block delimiter
even if there is a span of JSON content; this JSON is a parsing error.

Consider calling {@see static::get_attributes()} instead if it's not
necessary to read all the attributes at the same time, as that provides
a more efficient mechanism for typical use cases.

Since the JSON span inside the comment delimiter may not be valid JSON,
this function will return `null` if it cannot parse the span and set the
{@see static::get_last_json_error()} to the appropriate JSON_ERROR_ constant.

If the delimiter contains no JSON span, it will also return `null`,
but the last error will be set to {@see \JSON_ERROR_NONE}.

Example:

$processor = new WP_Block_Processor( '<!-- wp:image {"url": "https://wordpress.org/favicon.ico"} -->' );
$processor->next_delimiter();
$memory_hungry_and_slow_attributes = $processor->allocate_and_return_parsed_attributes();
$memory_hungry_and_slow_attributes === array( 'url' => 'https://wordpress.org/favicon.ico' );

$processor = new WP_Block_Processor( '<!-- /wp:image {"url": "https://wordpress.org/favicon.ico"} -->' );
$processor->next_delimiter();
null            = $processor->allocate_and_return_parsed_attributes();
JSON_ERROR_NONE = $processor->get_last_json_error();

$processor = new WP_Block_Processor( '<!-- wp:separator {} /-->' );
$processor->next_delimiter();
array() === $processor->allocate_and_return_parsed_attributes();

$processor = new WP_Block_Processor( '<!-- wp:separator /-->' );
$processor->next_delimiter();
null = $processor->allocate_and_return_parsed_attributes();

$processor = new WP_Block_Processor( '<!-- wp:image {"url} -->' );
$processor->next_delimiter();
null                 = $processor->allocate_and_return_parsed_attributes();
JSON_ERROR_CTRL_CHAR = $processor->get_last_json_error();

return: array|null Parsed JSON attributes, if present and valid, otherwise `null`.

get_span()   X-Ref
Returns the span representing the currently-matched delimiter, if matched, otherwise `null`.

Example:

$processor = new WP_Block_Processor( '<!-- wp:void /-->' );
null     === $processor->get_span();

$processor->next_delimiter();
WP_HTML_Span( 0, 17 ) === $processor->get_span();

return: WP_HTML_Span|null Span of text in source text spanning matched delimiter.



Generated : Fri Oct 17 08:20:04 2025 Cross-referenced by PHPXref