Make WordPress Core

Changeset 59757


Ignore:
Timestamp:
02/04/2025 02:47:41 AM (7 weeks ago)
Author:
jorbin
Message:

HTML API: Fix extensibility of WP_HTML_Processor::next_token().

Break out logic from the next_token() method into a private method which may call itself recursively. This allows for subclasses to override the next_token() method and be assured that each call to next_token() corresponds with the consumption of one single token. This also parallels how WP_HTML_Tag_Processor::next_token() wraps a private base_class_next_token() method.

Reviewed by jonsurrell.
Merges [59285], [59364], and [59747] to 6.7 branch.

Props westonruter, jonsurrell, dmsnell, jorbin.

Location:
branches/6.7
Files:
2 added
2 edited

Legend:

Unmodified
Added
Removed
  • branches/6.7/src/wp-includes/html-api/class-wp-html-processor.php

    r59721 r59757  
    609609
    610610    /**
    611      * Ensures internal accounting is maintained for HTML semantic rules while
    612      * the underlying Tag Processor class is seeking to a bookmark.
     611     * Finds the next token in the HTML document.
    613612     *
    614613     * This doesn't currently have a way to represent non-tags and doesn't process
     
    617616     *
    618617     * @since 6.5.0 Added for internal support; do not use.
     618     * @since 6.7.2 Refactored so subclasses may extend.
     619     *
     620     * @return bool Whether a token was parsed.
     621     */
     622    public function next_token(): bool {
     623        return $this->next_visitable_token();
     624    }
     625
     626    /**
     627     * Ensures internal accounting is maintained for HTML semantic rules while
     628     * the underlying Tag Processor class is seeking to a bookmark.
     629     *
     630     * This doesn't currently have a way to represent non-tags and doesn't process
     631     * semantic rules for text nodes. For access to the raw tokens consider using
     632     * WP_HTML_Tag_Processor instead.
     633     *
     634     * Note that this method may call itself recursively. This is why it is not
     635     * implemented as {@see WP_HTML_Processor::next_token()}, which instead calls
     636     * this method similarly to how {@see WP_HTML_Tag_Processor::next_token()}
     637     * calls the {@see WP_HTML_Tag_Processor::base_class_next_token()} method.
     638     *
     639     * @since 6.7.2 Added for internal support.
    619640     *
    620641     * @access private
     
    622643     * @return bool
    623644     */
    624     public function next_token(): bool {
     645    private function next_visitable_token(): bool {
    625646        $this->current_element = null;
    626647
     
    640661         */
    641662        if ( empty( $this->element_queue ) && $this->step() ) {
    642             return $this->next_token();
     663            return $this->next_visitable_token();
    643664        }
    644665
     
    651672            }
    652673
    653             return empty( $this->element_queue ) ? false : $this->next_token();
     674            return empty( $this->element_queue ) ? false : $this->next_visitable_token();
    654675        }
    655676
     
    662683         */
    663684        if ( 'root-node' === $this->current_element->token->bookmark_name ) {
    664             return $this->next_token();
     685            return $this->next_visitable_token();
    665686        }
    666687
     
    674695        // Avoid sending close events for elements which don't expect a closing.
    675696        if ( $is_pop && ! $this->expects_closer( $this->current_element->token ) ) {
    676             return $this->next_token();
     697            return $this->next_visitable_token();
    677698        }
    678699
  • branches/6.7/tests/phpunit/tests/html-api/wpHtmlProcessor.php

    r59721 r59757  
    910910
    911911    /**
     912     * Data provider.
     913     *
     914     * @return array
     915     */
     916    public function data_html_processor_with_extended_next_token() {
     917        return array(
     918            'single_instance_per_tag'   => array(
     919                'html'                  => '
     920                    <html>
     921                        <head>
     922                            <meta charset="utf-8">
     923                            <title>Hello World</title>
     924                        </head>
     925                        <body>
     926                            <h1>Hello World!</h1>
     927                            <img src="example.png">
     928                            <p>Each tag should occur only once in this document.<!--Closing P tag omitted intentionally.-->
     929                            <footer>The end.</footer>
     930                        </body>
     931                    </html>
     932                ',
     933                'expected_token_counts' => array(
     934                    '+HTML'    => 1,
     935                    '+HEAD'    => 1,
     936                    '#text'    => 14,
     937                    '+META'    => 1,
     938                    '+TITLE'   => 1,
     939                    '-HEAD'    => 1,
     940                    '+BODY'    => 1,
     941                    '+H1'      => 1,
     942                    '-H1'      => 1,
     943                    '+IMG'     => 1,
     944                    '+P'       => 1,
     945                    '#comment' => 1,
     946                    '-P'       => 1,
     947                    '+FOOTER'  => 1,
     948                    '-FOOTER'  => 1,
     949                    '-BODY'    => 1,
     950                    '-HTML'    => 1,
     951                    ''         => 1,
     952                ),
     953            ),
     954
     955            'multiple_tag_instances'    => array(
     956                'html'                  => '
     957                    <html>
     958                        <body>
     959                            <h1>Hello World!</h1>
     960                            <p>First
     961                            <p>Second
     962                            <p>Third
     963                            <ul>
     964                                <li>1
     965                                <li>2
     966                                <li>3
     967                            </ul>
     968                        </body>
     969                    </html>
     970                ',
     971                'expected_token_counts' => array(
     972                    '+HTML' => 1,
     973                    '+HEAD' => 1,
     974                    '-HEAD' => 1,
     975                    '+BODY' => 1,
     976                    '#text' => 13,
     977                    '+H1'   => 1,
     978                    '-H1'   => 1,
     979                    '+P'    => 3,
     980                    '-P'    => 3,
     981                    '+UL'   => 1,
     982                    '+LI'   => 3,
     983                    '-LI'   => 3,
     984                    '-UL'   => 1,
     985                    '-BODY' => 1,
     986                    '-HTML' => 1,
     987                    ''      => 1,
     988                ),
     989            ),
     990
     991            'extreme_nested_formatting' => array(
     992                'html'                  => '
     993                    <html>
     994                        <body>
     995                            <p>
     996                                <strong><em><strike><i><b><u>FORMAT</u></b></i></strike></em></strong>
     997                            </p>
     998                        </body>
     999                    </html>
     1000                ',
     1001                'expected_token_counts' => array(
     1002                    '+HTML'   => 1,
     1003                    '+HEAD'   => 1,
     1004                    '-HEAD'   => 1,
     1005                    '+BODY'   => 1,
     1006                    '#text'   => 7,
     1007                    '+P'      => 1,
     1008                    '+STRONG' => 1,
     1009                    '+EM'     => 1,
     1010                    '+STRIKE' => 1,
     1011                    '+I'      => 1,
     1012                    '+B'      => 1,
     1013                    '+U'      => 1,
     1014                    '-U'      => 1,
     1015                    '-B'      => 1,
     1016                    '-I'      => 1,
     1017                    '-STRIKE' => 1,
     1018                    '-EM'     => 1,
     1019                    '-STRONG' => 1,
     1020                    '-P'      => 1,
     1021                    '-BODY'   => 1,
     1022                    '-HTML'   => 1,
     1023                    ''        => 1,
     1024                ),
     1025            ),
     1026        );
     1027    }
     1028
     1029    /**
     1030     * Ensures that subclasses to WP_HTML_Processor can do bookkeeping by extending the next_token() method.
     1031     *
     1032     * @ticket 62269
     1033     * @dataProvider data_html_processor_with_extended_next_token
     1034     */
     1035    public function test_ensure_next_token_method_extensibility( $html, $expected_token_counts ) {
     1036        require_once DIR_TESTDATA . '/html-api/token-counting-html-processor.php';
     1037
     1038        $processor = Token_Counting_HTML_Processor::create_full_parser( $html );
     1039        while ( $processor->next_tag() ) {
     1040            continue;
     1041        }
     1042
     1043        $this->assertEquals( $expected_token_counts, $processor->token_seen_count, 'Snapshot: ' . var_export( $processor->token_seen_count, true ) );
     1044    }
     1045
     1046    /**
    9121047     * Ensure that lowercased tag_name query matches tags case-insensitively.
    9131048     *
Note: See TracChangeset for help on using the changeset viewer.