2 /** |
2 /** |
3 * Block Serialization Parser |
3 * Block Serialization Parser |
4 * |
4 * |
5 * @package WordPress |
5 * @package WordPress |
6 */ |
6 */ |
7 |
|
8 /** |
|
9 * Class WP_Block_Parser_Block |
|
10 * |
|
11 * Holds the block structure in memory |
|
12 * |
|
13 * @since 5.0.0 |
|
14 */ |
|
15 class WP_Block_Parser_Block { |
|
16 /** |
|
17 * Name of block |
|
18 * |
|
19 * @example "core/paragraph" |
|
20 * |
|
21 * @since 5.0.0 |
|
22 * @var string |
|
23 */ |
|
24 public $blockName; |
|
25 |
|
26 /** |
|
27 * Optional set of attributes from block comment delimiters |
|
28 * |
|
29 * @example null |
|
30 * @example array( 'columns' => 3 ) |
|
31 * |
|
32 * @since 5.0.0 |
|
33 * @var array|null |
|
34 */ |
|
35 public $attrs; |
|
36 |
|
37 /** |
|
38 * List of inner blocks (of this same class) |
|
39 * |
|
40 * @since 5.0.0 |
|
41 * @var WP_Block_Parser_Block[] |
|
42 */ |
|
43 public $innerBlocks; |
|
44 |
|
45 /** |
|
46 * Resultant HTML from inside block comment delimiters |
|
47 * after removing inner blocks |
|
48 * |
|
49 * @example "...Just <!-- wp:test /--> testing..." -> "Just testing..." |
|
50 * |
|
51 * @since 5.0.0 |
|
52 * @var string |
|
53 */ |
|
54 public $innerHTML; |
|
55 |
|
56 /** |
|
57 * List of string fragments and null markers where inner blocks were found |
|
58 * |
|
59 * @example array( |
|
60 * 'innerHTML' => 'BeforeInnerAfter', |
|
61 * 'innerBlocks' => array( block, block ), |
|
62 * 'innerContent' => array( 'Before', null, 'Inner', null, 'After' ), |
|
63 * ) |
|
64 * |
|
65 * @since 4.2.0 |
|
66 * @var array |
|
67 */ |
|
68 public $innerContent; |
|
69 |
|
70 /** |
|
71 * Constructor. |
|
72 * |
|
73 * Will populate object properties from the provided arguments. |
|
74 * |
|
75 * @since 5.0.0 |
|
76 * |
|
77 * @param string $name Name of block. |
|
78 * @param array $attrs Optional set of attributes from block comment delimiters. |
|
79 * @param array $innerBlocks List of inner blocks (of this same class). |
|
80 * @param string $innerHTML Resultant HTML from inside block comment delimiters after removing inner blocks. |
|
81 * @param array $innerContent List of string fragments and null markers where inner blocks were found. |
|
82 */ |
|
83 function __construct( $name, $attrs, $innerBlocks, $innerHTML, $innerContent ) { |
|
84 $this->blockName = $name; |
|
85 $this->attrs = $attrs; |
|
86 $this->innerBlocks = $innerBlocks; |
|
87 $this->innerHTML = $innerHTML; |
|
88 $this->innerContent = $innerContent; |
|
89 } |
|
90 } |
|
91 |
|
92 /** |
|
93 * Class WP_Block_Parser_Frame |
|
94 * |
|
95 * Holds partial blocks in memory while parsing |
|
96 * |
|
97 * @internal |
|
98 * @since 5.0.0 |
|
99 */ |
|
100 class WP_Block_Parser_Frame { |
|
101 /** |
|
102 * Full or partial block |
|
103 * |
|
104 * @since 5.0.0 |
|
105 * @var WP_Block_Parser_Block |
|
106 */ |
|
107 public $block; |
|
108 |
|
109 /** |
|
110 * Byte offset into document for start of parse token |
|
111 * |
|
112 * @since 5.0.0 |
|
113 * @var int |
|
114 */ |
|
115 public $token_start; |
|
116 |
|
117 /** |
|
118 * Byte length of entire parse token string |
|
119 * |
|
120 * @since 5.0.0 |
|
121 * @var int |
|
122 */ |
|
123 public $token_length; |
|
124 |
|
125 /** |
|
126 * Byte offset into document for after parse token ends |
|
127 * (used during reconstruction of stack into parse production) |
|
128 * |
|
129 * @since 5.0.0 |
|
130 * @var int |
|
131 */ |
|
132 public $prev_offset; |
|
133 |
|
134 /** |
|
135 * Byte offset into document where leading HTML before token starts |
|
136 * |
|
137 * @since 5.0.0 |
|
138 * @var int |
|
139 */ |
|
140 public $leading_html_start; |
|
141 |
|
142 /** |
|
143 * Constructor |
|
144 * |
|
145 * Will populate object properties from the provided arguments. |
|
146 * |
|
147 * @since 5.0.0 |
|
148 * |
|
149 * @param WP_Block_Parser_Block $block Full or partial block. |
|
150 * @param int $token_start Byte offset into document for start of parse token. |
|
151 * @param int $token_length Byte length of entire parse token string. |
|
152 * @param int $prev_offset Byte offset into document for after parse token ends. |
|
153 * @param int $leading_html_start Byte offset into document where leading HTML before token starts. |
|
154 */ |
|
155 function __construct( $block, $token_start, $token_length, $prev_offset = null, $leading_html_start = null ) { |
|
156 $this->block = $block; |
|
157 $this->token_start = $token_start; |
|
158 $this->token_length = $token_length; |
|
159 $this->prev_offset = isset( $prev_offset ) ? $prev_offset : $token_start + $token_length; |
|
160 $this->leading_html_start = $leading_html_start; |
|
161 } |
|
162 } |
|
163 |
7 |
164 /** |
8 /** |
165 * Class WP_Block_Parser |
9 * Class WP_Block_Parser |
166 * |
10 * |
167 * Parses a document and constructs a list of parsed block objects |
11 * Parses a document and constructs a list of parsed block objects |
203 * @var WP_Block_Parser_Frame[] |
47 * @var WP_Block_Parser_Frame[] |
204 */ |
48 */ |
205 public $stack; |
49 public $stack; |
206 |
50 |
207 /** |
51 /** |
208 * Empty associative array, here due to PHP quirks |
|
209 * |
|
210 * @since 4.4.0 |
|
211 * @var array empty associative array |
|
212 */ |
|
213 public $empty_attrs; |
|
214 |
|
215 /** |
|
216 * Parses a document and returns a list of block structures |
52 * Parses a document and returns a list of block structures |
217 * |
53 * |
218 * When encountering an invalid parse will return a best-effort |
54 * When encountering an invalid parse will return a best-effort |
219 * parse. In contrast to the specification parser this does not |
55 * parse. In contrast to the specification parser this does not |
220 * return an error on invalid inputs. |
56 * return an error on invalid inputs. |
221 * |
57 * |
222 * @since 5.0.0 |
58 * @since 5.0.0 |
223 * |
59 * |
224 * @param string $document Input document being parsed. |
60 * @param string $document Input document being parsed. |
225 * @return WP_Block_Parser_Block[] |
61 * @return array[] |
226 */ |
62 */ |
227 function parse( $document ) { |
63 public function parse( $document ) { |
228 $this->document = $document; |
64 $this->document = $document; |
229 $this->offset = 0; |
65 $this->offset = 0; |
230 $this->output = array(); |
66 $this->output = array(); |
231 $this->stack = array(); |
67 $this->stack = array(); |
232 $this->empty_attrs = json_decode( '{}', true ); |
68 |
233 |
69 while ( $this->proceed() ) { |
234 do { |
70 continue; |
235 // twiddle our thumbs. |
71 } |
236 } while ( $this->proceed() ); |
|
237 |
72 |
238 return $this->output; |
73 return $this->output; |
239 } |
74 } |
240 |
75 |
241 /** |
76 /** |
468 * Returns a new block object for freeform HTML |
303 * Returns a new block object for freeform HTML |
469 * |
304 * |
470 * @internal |
305 * @internal |
471 * @since 3.9.0 |
306 * @since 3.9.0 |
472 * |
307 * |
473 * @param string $innerHTML HTML content of block. |
308 * @param string $inner_html HTML content of block. |
474 * @return WP_Block_Parser_Block freeform block object. |
309 * @return WP_Block_Parser_Block freeform block object. |
475 */ |
310 */ |
476 function freeform( $innerHTML ) { |
311 public function freeform( $inner_html ) { |
477 return new WP_Block_Parser_Block( null, $this->empty_attrs, array(), $innerHTML, array( $innerHTML ) ); |
312 return new WP_Block_Parser_Block( null, array(), array(), $inner_html, array( $inner_html ) ); |
478 } |
313 } |
479 |
314 |
480 /** |
315 /** |
481 * Pushes a length of text from the input document |
316 * Pushes a length of text from the input document |
482 * to the output list as a freeform block. |
317 * to the output list as a freeform block. |
483 * |
318 * |
484 * @internal |
319 * @internal |
485 * @since 5.0.0 |
320 * @since 5.0.0 |
486 * @param null $length how many bytes of document text to output. |
321 * @param null $length how many bytes of document text to output. |
487 */ |
322 */ |
488 function add_freeform( $length = null ) { |
323 public function add_freeform( $length = null ) { |
489 $length = $length ? $length : strlen( $this->document ) - $this->offset; |
324 $length = $length ? $length : strlen( $this->document ) - $this->offset; |
490 |
325 |
491 if ( 0 === $length ) { |
326 if ( 0 === $length ) { |
492 return; |
327 return; |
493 } |
328 } |
504 * @param WP_Block_Parser_Block $block The block to add to the output. |
339 * @param WP_Block_Parser_Block $block The block to add to the output. |
505 * @param int $token_start Byte offset into the document where the first token for the block starts. |
340 * @param int $token_start Byte offset into the document where the first token for the block starts. |
506 * @param int $token_length Byte length of entire block from start of opening token to end of closing token. |
341 * @param int $token_length Byte length of entire block from start of opening token to end of closing token. |
507 * @param int|null $last_offset Last byte offset into document if continuing form earlier output. |
342 * @param int|null $last_offset Last byte offset into document if continuing form earlier output. |
508 */ |
343 */ |
509 function add_inner_block( WP_Block_Parser_Block $block, $token_start, $token_length, $last_offset = null ) { |
344 public function add_inner_block( WP_Block_Parser_Block $block, $token_start, $token_length, $last_offset = null ) { |
510 $parent = $this->stack[ count( $this->stack ) - 1 ]; |
345 $parent = $this->stack[ count( $this->stack ) - 1 ]; |
511 $parent->block->innerBlocks[] = (array) $block; |
346 $parent->block->innerBlocks[] = (array) $block; |
512 $html = substr( $this->document, $parent->prev_offset, $token_start - $parent->prev_offset ); |
347 $html = substr( $this->document, $parent->prev_offset, $token_start - $parent->prev_offset ); |
513 |
348 |
514 if ( ! empty( $html ) ) { |
349 if ( ! empty( $html ) ) { |
525 * |
360 * |
526 * @internal |
361 * @internal |
527 * @since 5.0.0 |
362 * @since 5.0.0 |
528 * @param int|null $end_offset byte offset into document for where we should stop sending text output as HTML. |
363 * @param int|null $end_offset byte offset into document for where we should stop sending text output as HTML. |
529 */ |
364 */ |
530 function add_block_from_stack( $end_offset = null ) { |
365 public function add_block_from_stack( $end_offset = null ) { |
531 $stack_top = array_pop( $this->stack ); |
366 $stack_top = array_pop( $this->stack ); |
532 $prev_offset = $stack_top->prev_offset; |
367 $prev_offset = $stack_top->prev_offset; |
533 |
368 |
534 $html = isset( $end_offset ) |
369 $html = isset( $end_offset ) |
535 ? substr( $this->document, $prev_offset, $end_offset - $prev_offset ) |
370 ? substr( $this->document, $prev_offset, $end_offset - $prev_offset ) |