wp/wp-includes/class-wp-block-parser.php
changeset 18 be944660c56a
parent 9 177826044cd9
child 21 48c4eec2b7e6
equal deleted inserted replaced
17:34716fd837a4 18:be944660c56a
     8 /**
     8 /**
     9  * Class WP_Block_Parser_Block
     9  * Class WP_Block_Parser_Block
    10  *
    10  *
    11  * Holds the block structure in memory
    11  * Holds the block structure in memory
    12  *
    12  *
    13  * @since 3.8.0
    13  * @since 5.0.0
    14  */
    14  */
    15 class WP_Block_Parser_Block {
    15 class WP_Block_Parser_Block {
    16 	/**
    16 	/**
    17 	 * Name of block
    17 	 * Name of block
    18 	 *
    18 	 *
    19 	 * @example "core/paragraph"
    19 	 * @example "core/paragraph"
    20 	 *
    20 	 *
    21 	 * @since 3.8.0
    21 	 * @since 5.0.0
    22 	 * @var string
    22 	 * @var string
    23 	 */
    23 	 */
    24 	public $blockName;
    24 	public $blockName;
    25 
    25 
    26 	/**
    26 	/**
    27 	 * Optional set of attributes from block comment delimiters
    27 	 * Optional set of attributes from block comment delimiters
    28 	 *
    28 	 *
    29 	 * @example null
    29 	 * @example null
    30 	 * @example array( 'columns' => 3 )
    30 	 * @example array( 'columns' => 3 )
    31 	 *
    31 	 *
    32 	 * @since 3.8.0
    32 	 * @since 5.0.0
    33 	 * @var array|null
    33 	 * @var array|null
    34 	 */
    34 	 */
    35 	public $attrs;
    35 	public $attrs;
    36 
    36 
    37 	/**
    37 	/**
    38 	 * List of inner blocks (of this same class)
    38 	 * List of inner blocks (of this same class)
    39 	 *
    39 	 *
    40 	 * @since 3.8.0
    40 	 * @since 5.0.0
    41 	 * @var WP_Block_Parser_Block[]
    41 	 * @var WP_Block_Parser_Block[]
    42 	 */
    42 	 */
    43 	public $innerBlocks;
    43 	public $innerBlocks;
    44 
    44 
    45 	/**
    45 	/**
    46 	 * Resultant HTML from inside block comment delimiters
    46 	 * Resultant HTML from inside block comment delimiters
    47 	 * after removing inner blocks
    47 	 * after removing inner blocks
    48 	 *
    48 	 *
    49 	 * @example "...Just <!-- wp:test /--> testing..." -> "Just testing..."
    49 	 * @example "...Just <!-- wp:test /--> testing..." -> "Just testing..."
    50 	 *
    50 	 *
    51 	 * @since 3.8.0
    51 	 * @since 5.0.0
    52 	 * @var string
    52 	 * @var string
    53 	 */
    53 	 */
    54 	public $innerHTML;
    54 	public $innerHTML;
    55 
    55 
    56 	/**
    56 	/**
    70 	/**
    70 	/**
    71 	 * Constructor.
    71 	 * Constructor.
    72 	 *
    72 	 *
    73 	 * Will populate object properties from the provided arguments.
    73 	 * Will populate object properties from the provided arguments.
    74 	 *
    74 	 *
    75 	 * @since 3.8.0
    75 	 * @since 5.0.0
    76 	 *
    76 	 *
    77 	 * @param string $name         Name of block.
    77 	 * @param string $name         Name of block.
    78 	 * @param array  $attrs        Optional set of attributes from block comment delimiters.
    78 	 * @param array  $attrs        Optional set of attributes from block comment delimiters.
    79 	 * @param array  $innerBlocks  List of inner blocks (of this same class).
    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.
    80 	 * @param string $innerHTML    Resultant HTML from inside block comment delimiters after removing inner blocks.
    93  * Class WP_Block_Parser_Frame
    93  * Class WP_Block_Parser_Frame
    94  *
    94  *
    95  * Holds partial blocks in memory while parsing
    95  * Holds partial blocks in memory while parsing
    96  *
    96  *
    97  * @internal
    97  * @internal
    98  * @since 3.8.0
    98  * @since 5.0.0
    99  */
    99  */
   100 class WP_Block_Parser_Frame {
   100 class WP_Block_Parser_Frame {
   101 	/**
   101 	/**
   102 	 * Full or partial block
   102 	 * Full or partial block
   103 	 *
   103 	 *
   104 	 * @since 3.8.0
   104 	 * @since 5.0.0
   105 	 * @var WP_Block_Parser_Block
   105 	 * @var WP_Block_Parser_Block
   106 	 */
   106 	 */
   107 	public $block;
   107 	public $block;
   108 
   108 
   109 	/**
   109 	/**
   110 	 * Byte offset into document for start of parse token
   110 	 * Byte offset into document for start of parse token
   111 	 *
   111 	 *
   112 	 * @since 3.8.0
   112 	 * @since 5.0.0
   113 	 * @var int
   113 	 * @var int
   114 	 */
   114 	 */
   115 	public $token_start;
   115 	public $token_start;
   116 
   116 
   117 	/**
   117 	/**
   118 	 * Byte length of entire parse token string
   118 	 * Byte length of entire parse token string
   119 	 *
   119 	 *
   120 	 * @since 3.8.0
   120 	 * @since 5.0.0
   121 	 * @var int
   121 	 * @var int
   122 	 */
   122 	 */
   123 	public $token_length;
   123 	public $token_length;
   124 
   124 
   125 	/**
   125 	/**
   126 	 * Byte offset into document for after parse token ends
   126 	 * Byte offset into document for after parse token ends
   127 	 * (used during reconstruction of stack into parse production)
   127 	 * (used during reconstruction of stack into parse production)
   128 	 *
   128 	 *
   129 	 * @since 3.8.0
   129 	 * @since 5.0.0
   130 	 * @var int
   130 	 * @var int
   131 	 */
   131 	 */
   132 	public $prev_offset;
   132 	public $prev_offset;
   133 
   133 
   134 	/**
   134 	/**
   135 	 * Byte offset into document where leading HTML before token starts
   135 	 * Byte offset into document where leading HTML before token starts
   136 	 *
   136 	 *
   137 	 * @since 3.8.0
   137 	 * @since 5.0.0
   138 	 * @var int
   138 	 * @var int
   139 	 */
   139 	 */
   140 	public $leading_html_start;
   140 	public $leading_html_start;
   141 
   141 
   142 	/**
   142 	/**
   143 	 * Constructor
   143 	 * Constructor
   144 	 *
   144 	 *
   145 	 * Will populate object properties from the provided arguments.
   145 	 * Will populate object properties from the provided arguments.
   146 	 *
   146 	 *
   147 	 * @since 3.8.0
   147 	 * @since 5.0.0
   148 	 *
   148 	 *
   149 	 * @param WP_Block_Parser_Block $block              Full or partial block.
   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.
   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.
   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.
   152 	 * @param int                   $prev_offset        Byte offset into document for after parse token ends.
   164 /**
   164 /**
   165  * Class WP_Block_Parser
   165  * Class WP_Block_Parser
   166  *
   166  *
   167  * Parses a document and constructs a list of parsed block objects
   167  * Parses a document and constructs a list of parsed block objects
   168  *
   168  *
   169  * @since 3.8.0
   169  * @since 5.0.0
   170  * @since 4.0.0 returns arrays not objects, all attributes are arrays
   170  * @since 4.0.0 returns arrays not objects, all attributes are arrays
   171  */
   171  */
   172 class WP_Block_Parser {
   172 class WP_Block_Parser {
   173 	/**
   173 	/**
   174 	 * Input document being parsed
   174 	 * Input document being parsed
   175 	 *
   175 	 *
   176 	 * @example "Pre-text\n<!-- wp:paragraph -->This is inside a block!<!-- /wp:paragraph -->"
   176 	 * @example "Pre-text\n<!-- wp:paragraph -->This is inside a block!<!-- /wp:paragraph -->"
   177 	 *
   177 	 *
   178 	 * @since 3.8.0
   178 	 * @since 5.0.0
   179 	 * @var string
   179 	 * @var string
   180 	 */
   180 	 */
   181 	public $document;
   181 	public $document;
   182 
   182 
   183 	/**
   183 	/**
   184 	 * Tracks parsing progress through document
   184 	 * Tracks parsing progress through document
   185 	 *
   185 	 *
   186 	 * @since 3.8.0
   186 	 * @since 5.0.0
   187 	 * @var int
   187 	 * @var int
   188 	 */
   188 	 */
   189 	public $offset;
   189 	public $offset;
   190 
   190 
   191 	/**
   191 	/**
   192 	 * List of parsed blocks
   192 	 * List of parsed blocks
   193 	 *
   193 	 *
   194 	 * @since 3.8.0
   194 	 * @since 5.0.0
   195 	 * @var WP_Block_Parser_Block[]
   195 	 * @var WP_Block_Parser_Block[]
   196 	 */
   196 	 */
   197 	public $output;
   197 	public $output;
   198 
   198 
   199 	/**
   199 	/**
   200 	 * Stack of partially-parsed structures in memory during parse
   200 	 * Stack of partially-parsed structures in memory during parse
   201 	 *
   201 	 *
   202 	 * @since 3.8.0
   202 	 * @since 5.0.0
   203 	 * @var WP_Block_Parser_Frame[]
   203 	 * @var WP_Block_Parser_Frame[]
   204 	 */
   204 	 */
   205 	public $stack;
   205 	public $stack;
   206 
   206 
   207 	/**
   207 	/**
   217 	 *
   217 	 *
   218 	 * When encountering an invalid parse will return a best-effort
   218 	 * When encountering an invalid parse will return a best-effort
   219 	 * parse. In contrast to the specification parser this does not
   219 	 * parse. In contrast to the specification parser this does not
   220 	 * return an error on invalid inputs.
   220 	 * return an error on invalid inputs.
   221 	 *
   221 	 *
   222 	 * @since 3.8.0
   222 	 * @since 5.0.0
   223 	 *
   223 	 *
   224 	 * @param string $document Input document being parsed.
   224 	 * @param string $document Input document being parsed.
   225 	 * @return WP_Block_Parser_Block[]
   225 	 * @return WP_Block_Parser_Block[]
   226 	 */
   226 	 */
   227 	function parse( $document ) {
   227 	function parse( $document ) {
   247 	 * with that token before descending deeper into a
   247 	 * with that token before descending deeper into a
   248 	 * nested block tree or continuing along the document
   248 	 * nested block tree or continuing along the document
   249 	 * or breaking out of a level of nesting.
   249 	 * or breaking out of a level of nesting.
   250 	 *
   250 	 *
   251 	 * @internal
   251 	 * @internal
   252 	 * @since 3.8.0
   252 	 * @since 5.0.0
   253 	 * @return bool
   253 	 * @return bool
   254 	 */
   254 	 */
   255 	function proceed() {
   255 	function proceed() {
   256 		$next_token = $this->next_token();
   256 		$next_token = $this->next_token();
   257 		list( $token_type, $block_name, $attrs, $start_offset, $token_length ) = $next_token;
   257 		list( $token_type, $block_name, $attrs, $start_offset, $token_length ) = $next_token;
   298 				 * easy case is if we stumbled upon a void block
   298 				 * easy case is if we stumbled upon a void block
   299 				 * in the top-level of the document
   299 				 * in the top-level of the document
   300 				 */
   300 				 */
   301 				if ( 0 === $stack_depth ) {
   301 				if ( 0 === $stack_depth ) {
   302 					if ( isset( $leading_html_start ) ) {
   302 					if ( isset( $leading_html_start ) ) {
   303 						$this->output[] = (array) self::freeform(
   303 						$this->output[] = (array) $this->freeform(
   304 							substr(
   304 							substr(
   305 								$this->document,
   305 								$this->document,
   306 								$leading_html_start,
   306 								$leading_html_start,
   307 								$start_offset - $leading_html_start
   307 								$start_offset - $leading_html_start
   308 							)
   308 							)
   392 	 * and finds the next valid token to parse if it exists
   392 	 * and finds the next valid token to parse if it exists
   393 	 *
   393 	 *
   394 	 * Returns the type of the find: kind of find, block information, attributes
   394 	 * Returns the type of the find: kind of find, block information, attributes
   395 	 *
   395 	 *
   396 	 * @internal
   396 	 * @internal
   397 	 * @since 3.8.0
   397 	 * @since 5.0.0
   398 	 * @since 4.6.1 fixed a bug in attribute parsing which caused catastrophic backtracking on invalid block comments
   398 	 * @since 4.6.1 fixed a bug in attribute parsing which caused catastrophic backtracking on invalid block comments
   399 	 * @return array
   399 	 * @return array
   400 	 */
   400 	 */
   401 	function next_token() {
   401 	function next_token() {
   402 		$matches = null;
   402 		$matches = null;
   480 	/**
   480 	/**
   481 	 * Pushes a length of text from the input document
   481 	 * Pushes a length of text from the input document
   482 	 * to the output list as a freeform block.
   482 	 * to the output list as a freeform block.
   483 	 *
   483 	 *
   484 	 * @internal
   484 	 * @internal
   485 	 * @since 3.8.0
   485 	 * @since 5.0.0
   486 	 * @param null $length how many bytes of document text to output.
   486 	 * @param null $length how many bytes of document text to output.
   487 	 */
   487 	 */
   488 	function add_freeform( $length = null ) {
   488 	function add_freeform( $length = null ) {
   489 		$length = $length ? $length : strlen( $this->document ) - $this->offset;
   489 		$length = $length ? $length : strlen( $this->document ) - $this->offset;
   490 
   490 
   491 		if ( 0 === $length ) {
   491 		if ( 0 === $length ) {
   492 			return;
   492 			return;
   493 		}
   493 		}
   494 
   494 
   495 		$this->output[] = (array) self::freeform( substr( $this->document, $this->offset, $length ) );
   495 		$this->output[] = (array) $this->freeform( substr( $this->document, $this->offset, $length ) );
   496 	}
   496 	}
   497 
   497 
   498 	/**
   498 	/**
   499 	 * Given a block structure from memory pushes
   499 	 * Given a block structure from memory pushes
   500 	 * a new block to the output list.
   500 	 * a new block to the output list.
   501 	 *
   501 	 *
   502 	 * @internal
   502 	 * @internal
   503 	 * @since 3.8.0
   503 	 * @since 5.0.0
   504 	 * @param WP_Block_Parser_Block $block        The block to add to the output.
   504 	 * @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.
   505 	 * @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.
   506 	 * @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.
   507 	 * @param int|null              $last_offset  Last byte offset into document if continuing form earlier output.
   508 	 */
   508 	 */
   522 
   522 
   523 	/**
   523 	/**
   524 	 * Pushes the top block from the parsing stack to the output list.
   524 	 * Pushes the top block from the parsing stack to the output list.
   525 	 *
   525 	 *
   526 	 * @internal
   526 	 * @internal
   527 	 * @since 3.8.0
   527 	 * @since 5.0.0
   528 	 * @param int|null $end_offset byte offset into document for where we should stop sending text output as HTML.
   528 	 * @param int|null $end_offset byte offset into document for where we should stop sending text output as HTML.
   529 	 */
   529 	 */
   530 	function add_block_from_stack( $end_offset = null ) {
   530 	function add_block_from_stack( $end_offset = null ) {
   531 		$stack_top   = array_pop( $this->stack );
   531 		$stack_top   = array_pop( $this->stack );
   532 		$prev_offset = $stack_top->prev_offset;
   532 		$prev_offset = $stack_top->prev_offset;
   539 			$stack_top->block->innerHTML     .= $html;
   539 			$stack_top->block->innerHTML     .= $html;
   540 			$stack_top->block->innerContent[] = $html;
   540 			$stack_top->block->innerContent[] = $html;
   541 		}
   541 		}
   542 
   542 
   543 		if ( isset( $stack_top->leading_html_start ) ) {
   543 		if ( isset( $stack_top->leading_html_start ) ) {
   544 			$this->output[] = (array) self::freeform(
   544 			$this->output[] = (array) $this->freeform(
   545 				substr(
   545 				substr(
   546 					$this->document,
   546 					$this->document,
   547 					$stack_top->leading_html_start,
   547 					$stack_top->leading_html_start,
   548 					$stack_top->token_start - $stack_top->leading_html_start
   548 					$stack_top->token_start - $stack_top->leading_html_start
   549 				)
   549 				)