Make WordPress Core


Ignore:
Timestamp:
07/19/2024 11:42:14 PM (17 months ago)
Author:
dmsnell
Message:

HTML API: Add PHP type annotations.

This patch adds type annotations to internal and private methods of the HTML
API and the supporting WP_Token_Map. Annotations have not been added to the
public interfaces where it would likely crash a site if called wrong.

These annotations should help avoid unnecessary type-related bugs (as have
been uncovered in earlier work adding such annotations) and provide additional
guidance to developers when interacting with these classes in an IDE.

Developed in https://github.com/WordPress/wordpress-develop/pull/6753
Discussed in https://core.trac.wordpress.org/ticket/61399

Props dmsnell, jonsurrell.
See #61399.

File:
1 edited

Legend:

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

    r58742 r58769  
    160160     * @var WP_HTML_Processor_State
    161161     */
    162     private $state = null;
     162    private $state;
    163163
    164164    /**
     
    209209     * @since 6.4.0
    210210     *
    211      * @var closure
     211     * @var Closure|null
    212212     */
    213213    private $release_internal_bookmark_on_destruct = null;
     
    369369
    370370        $this->state->stack_of_open_elements->set_push_handler(
    371             function ( WP_HTML_Token $token ) {
     371            function ( WP_HTML_Token $token ): void {
    372372                $is_virtual            = ! isset( $this->state->current_token ) || $this->is_tag_closer();
    373373                $same_node             = isset( $this->state->current_token ) && $token->node_name === $this->state->current_token->node_name;
     
    378378
    379379        $this->state->stack_of_open_elements->set_pop_handler(
    380             function ( WP_HTML_Token $token ) {
     380            function ( WP_HTML_Token $token ): void {
    381381                $is_virtual            = ! isset( $this->state->current_token ) || ! $this->is_tag_closer();
    382382                $same_node             = isset( $this->state->current_token ) && $token->node_name === $this->state->current_token->node_name;
     
    391391         * exposing it to any public API.
    392392         */
    393         $this->release_internal_bookmark_on_destruct = function ( $name ) {
     393        $this->release_internal_bookmark_on_destruct = function ( string $name ): void {
    394394            parent::release_bookmark( $name );
    395395        };
     
    404404     *
    405405     * @param string $message Explains support is missing in order to parse the current node.
    406      *
    407      * @return mixed
    408406     */
    409407    private function bail( string $message ) {
     
    458456     * @return string|null The last error, if one exists, otherwise null.
    459457     */
    460     public function get_last_error() {
     458    public function get_last_error(): ?string {
    461459        return $this->last_error;
    462460    }
     
    501499     * @return bool Whether a tag was matched.
    502500     */
    503     public function next_tag( $query = null ) {
     501    public function next_tag( $query = null ): bool {
    504502        $visit_closers = isset( $query['tag_closers'] ) && 'visit' === $query['tag_closers'];
    505503
     
    591589     * @return bool
    592590     */
    593     public function next_token() {
     591    public function next_token(): bool {
    594592        $this->current_element = null;
    595593
     
    644642    }
    645643
    646 
    647644    /**
    648645     * Indicates if the current tag token is a tag closer.
     
    661658     * @return bool Whether the current tag is a tag closer.
    662659     */
    663     public function is_tag_closer() {
     660    public function is_tag_closer(): bool {
    664661        return $this->is_virtual()
    665662            ? ( WP_HTML_Stack_Event::POP === $this->current_element->operation && '#tag' === $this->get_token_type() )
     
    675672     * @return bool Whether the current token is virtual.
    676673     */
    677     private function is_virtual() {
     674    private function is_virtual(): bool {
    678675        return (
    679676            isset( $this->current_element->provenance ) &&
     
    707704     * @return bool Whether the currently-matched tag is found at the given nested structure.
    708705     */
    709     public function matches_breadcrumbs( $breadcrumbs ) {
     706    public function matches_breadcrumbs( $breadcrumbs ): bool {
    710707        // Everything matches when there are zero constraints.
    711708        if ( 0 === count( $breadcrumbs ) ) {
     
    758755     *                   or `null` if not matched on any token.
    759756     */
    760     public function expects_closer( $node = null ) {
     757    public function expects_closer( $node = null ): ?bool {
    761758        $token_name = $node->node_name ?? $this->get_token_name();
    762759        if ( ! isset( $token_name ) ) {
     
    789786     * @return bool Whether a tag was matched.
    790787     */
    791     public function step( $node_to_process = self::PROCESS_NEXT_NODE ) {
     788    public function step( $node_to_process = self::PROCESS_NEXT_NODE ): bool {
    792789        // Refuse to proceed if there was a previous error.
    793790        if ( null !== $this->last_error ) {
     
    939936     * @return string[]|null Array of tag names representing path to matched node, if matched, otherwise NULL.
    940937     */
    941     public function get_breadcrumbs() {
     938    public function get_breadcrumbs(): ?array {
    942939        return $this->breadcrumbs;
    943940    }
     
    968965     * @return int Nesting-depth of current location in the document.
    969966     */
    970     public function get_current_depth() {
     967    public function get_current_depth(): int {
    971968        return count( $this->breadcrumbs );
    972969    }
     
    987984     * @return bool Whether an element was found.
    988985     */
    989     private function step_initial() {
     986    private function step_initial(): bool {
    990987        $this->bail( "No support for parsing in the '{$this->state->insertion_mode}' state." );
    991988    }
     
    10061003     * @return bool Whether an element was found.
    10071004     */
    1008     private function step_before_html() {
     1005    private function step_before_html(): bool {
    10091006        $this->bail( "No support for parsing in the '{$this->state->insertion_mode}' state." );
    10101007    }
     
    10251022     * @return bool Whether an element was found.
    10261023     */
    1027     private function step_before_head() {
     1024    private function step_before_head(): bool {
    10281025        $this->bail( "No support for parsing in the '{$this->state->insertion_mode}' state." );
    10291026    }
     
    10441041     * @return bool Whether an element was found.
    10451042     */
    1046     private function step_in_head() {
     1043    private function step_in_head(): bool {
    10471044        $this->bail( "No support for parsing in the '{$this->state->insertion_mode}' state." );
    10481045    }
     
    10631060     * @return bool Whether an element was found.
    10641061     */
    1065     private function step_in_head_noscript() {
     1062    private function step_in_head_noscript(): bool {
    10661063        $this->bail( "No support for parsing in the '{$this->state->insertion_mode}' state." );
    10671064    }
     
    10821079     * @return bool Whether an element was found.
    10831080     */
    1084     private function step_after_head() {
     1081    private function step_after_head(): bool {
    10851082        $this->bail( "No support for parsing in the '{$this->state->insertion_mode}' state." );
    10861083    }
     
    11011098     * @return bool Whether an element was found.
    11021099     */
    1103     private function step_in_body() {
     1100    private function step_in_body(): bool {
    11041101        $token_name = $this->get_token_name();
    11051102        $token_type = $this->get_token_type();
     
    17241721     * @return bool Whether an element was found.
    17251722     */
    1726     private function step_in_table() {
     1723    private function step_in_table(): bool {
    17271724        $this->bail( "No support for parsing in the '{$this->state->insertion_mode}' state." );
    17281725    }
     
    17431740     * @return bool Whether an element was found.
    17441741     */
    1745     private function step_in_table_text() {
     1742    private function step_in_table_text(): bool {
    17461743        $this->bail( "No support for parsing in the '{$this->state->insertion_mode}' state." );
    17471744    }
     
    17621759     * @return bool Whether an element was found.
    17631760     */
    1764     private function step_in_caption() {
     1761    private function step_in_caption(): bool {
    17651762        $this->bail( "No support for parsing in the '{$this->state->insertion_mode}' state." );
    17661763    }
     
    17811778     * @return bool Whether an element was found.
    17821779     */
    1783     private function step_in_column_group() {
     1780    private function step_in_column_group(): bool {
    17841781        $this->bail( "No support for parsing in the '{$this->state->insertion_mode}' state." );
    17851782    }
     
    18001797     * @return bool Whether an element was found.
    18011798     */
    1802     private function step_in_table_body() {
     1799    private function step_in_table_body(): bool {
    18031800        $this->bail( "No support for parsing in the '{$this->state->insertion_mode}' state." );
    18041801    }
     
    18191816     * @return bool Whether an element was found.
    18201817     */
    1821     private function step_in_row() {
     1818    private function step_in_row(): bool {
    18221819        $this->bail( "No support for parsing in the '{$this->state->insertion_mode}' state." );
    18231820    }
     
    18381835     * @return bool Whether an element was found.
    18391836     */
    1840     private function step_in_cell() {
     1837    private function step_in_cell(): bool {
    18411838        $this->bail( "No support for parsing in the '{$this->state->insertion_mode}' state." );
    18421839    }
     
    18571854     * @return bool Whether an element was found.
    18581855     */
    1859     private function step_in_select() {
     1856    private function step_in_select(): bool {
    18601857        $token_name = $this->get_token_name();
    18611858        $token_type = $this->get_token_type();
     
    20382035     * @return bool Whether an element was found.
    20392036     */
    2040     private function step_in_select_in_table() {
     2037    private function step_in_select_in_table(): bool {
    20412038        $this->bail( "No support for parsing in the '{$this->state->insertion_mode}' state." );
    20422039    }
     
    20572054     * @return bool Whether an element was found.
    20582055     */
    2059     private function step_in_template() {
     2056    private function step_in_template(): bool {
    20602057        $this->bail( "No support for parsing in the '{$this->state->insertion_mode}' state." );
    20612058    }
     
    20762073     * @return bool Whether an element was found.
    20772074     */
    2078     private function step_after_body() {
     2075    private function step_after_body(): bool {
    20792076        $this->bail( "No support for parsing in the '{$this->state->insertion_mode}' state." );
    20802077    }
     
    20952092     * @return bool Whether an element was found.
    20962093     */
    2097     private function step_in_frameset() {
     2094    private function step_in_frameset(): bool {
    20982095        $this->bail( "No support for parsing in the '{$this->state->insertion_mode}' state." );
    20992096    }
     
    21142111     * @return bool Whether an element was found.
    21152112     */
    2116     private function step_after_frameset() {
     2113    private function step_after_frameset(): bool {
    21172114        $this->bail( "No support for parsing in the '{$this->state->insertion_mode}' state." );
    21182115    }
     
    21332130     * @return bool Whether an element was found.
    21342131     */
    2135     private function step_after_after_body() {
     2132    private function step_after_after_body(): bool {
    21362133        $this->bail( "No support for parsing in the '{$this->state->insertion_mode}' state." );
    21372134    }
     
    21522149     * @return bool Whether an element was found.
    21532150     */
    2154     private function step_after_after_frameset() {
     2151    private function step_after_after_frameset(): bool {
    21552152        $this->bail( "No support for parsing in the '{$this->state->insertion_mode}' state." );
    21562153    }
     
    21712168     * @return bool Whether an element was found.
    21722169     */
    2173     private function step_in_foreign_content() {
     2170    private function step_in_foreign_content(): bool {
    21742171        $this->bail( "No support for parsing in the '{$this->state->insertion_mode}' state." );
    21752172    }
     
    22232220     * @return string|null Name of currently matched tag in input HTML, or `null` if none found.
    22242221     */
    2225     public function get_tag() {
     2222    public function get_tag(): ?string {
    22262223        if ( null !== $this->last_error ) {
    22272224            return null;
     
    22642261     * @return bool Whether the currently matched tag contains the self-closing flag.
    22652262     */
    2266     public function has_self_closing_flag() {
     2263    public function has_self_closing_flag(): bool {
    22672264        return $this->is_virtual() ? false : parent::has_self_closing_flag();
    22682265    }
     
    22882285     * @return string|null Name of the matched token.
    22892286     */
    2290     public function get_token_name() {
     2287    public function get_token_name(): ?string {
    22912288        return $this->is_virtual()
    22922289            ? $this->current_element->token->node_name
     
    23162313     * @return string|null What kind of token is matched, or null.
    23172314     */
    2318     public function get_token_type() {
     2315    public function get_token_type(): ?string {
    23192316        if ( $this->is_virtual() ) {
    23202317            /*
     
    23782375     * @return bool Whether an attribute value was set.
    23792376     */
    2380     public function set_attribute( $name, $value ) {
     2377    public function set_attribute( $name, $value ): bool {
    23812378        return $this->is_virtual() ? false : parent::set_attribute( $name, $value );
    23822379    }
     
    23902387     * @return bool Whether an attribute was removed.
    23912388     */
    2392     public function remove_attribute( $name ) {
     2389    public function remove_attribute( $name ): bool {
    23932390        return $this->is_virtual() ? false : parent::remove_attribute( $name );
    23942391    }
     
    24202417     * @return array|null List of attribute names, or `null` when no tag opener is matched.
    24212418     */
    2422     public function get_attribute_names_with_prefix( $prefix ) {
     2419    public function get_attribute_names_with_prefix( $prefix ): ?array {
    24232420        return $this->is_virtual() ? null : parent::get_attribute_names_with_prefix( $prefix );
    24242421    }
     
    24322429     * @return bool Whether the class was set to be added.
    24332430     */
    2434     public function add_class( $class_name ) {
     2431    public function add_class( $class_name ): bool {
    24352432        return $this->is_virtual() ? false : parent::add_class( $class_name );
    24362433    }
     
    24442441     * @return bool Whether the class was set to be removed.
    24452442     */
    2446     public function remove_class( $class_name ) {
     2443    public function remove_class( $class_name ): bool {
    24472444        return $this->is_virtual() ? false : parent::remove_class( $class_name );
    24482445    }
     
    24562453     * @return bool|null Whether the matched tag contains the given class name, or null if not matched.
    24572454     */
    2458     public function has_class( $wanted_class ) {
     2455    public function has_class( $wanted_class ): ?bool {
    24592456        return $this->is_virtual() ? null : parent::has_class( $wanted_class );
    24602457    }
     
    25002497     * @return string
    25012498     */
    2502     public function get_modifiable_text() {
     2499    public function get_modifiable_text(): string {
    25032500        return $this->is_virtual() ? '' : parent::get_modifiable_text();
    25042501    }
     
    25232520     * @return string|null
    25242521     */
    2525     public function get_comment_type() {
     2522    public function get_comment_type(): ?string {
    25262523        return $this->is_virtual() ? null : parent::get_comment_type();
    25272524    }
     
    25382535     * @return bool Whether the bookmark already existed before removal.
    25392536     */
    2540     public function release_bookmark( $bookmark_name ) {
     2537    public function release_bookmark( $bookmark_name ): bool {
    25412538        return parent::release_bookmark( "_{$bookmark_name}" );
    25422539    }
     
    25592556     * @return bool Whether the internal cursor was successfully moved to the bookmark's location.
    25602557     */
    2561     public function seek( $bookmark_name ) {
     2558    public function seek( $bookmark_name ): bool {
    25622559        // Flush any pending updates to the document before beginning.
    25632560        $this->get_updated_html();
     
    27302727     * @return bool Whether the bookmark was successfully created.
    27312728     */
    2732     public function set_bookmark( $bookmark_name ) {
     2729    public function set_bookmark( $bookmark_name ): bool {
    27332730        return parent::set_bookmark( "_{$bookmark_name}" );
    27342731    }
     
    27422739     * @return bool Whether that bookmark exists.
    27432740     */
    2744     public function has_bookmark( $bookmark_name ) {
     2741    public function has_bookmark( $bookmark_name ): bool {
    27452742        return parent::has_bookmark( "_{$bookmark_name}" );
    27462743    }
     
    27592756     * @see https://html.spec.whatwg.org/#close-a-p-element
    27602757     */
    2761     private function close_a_p_element() {
     2758    private function close_a_p_element(): void {
    27622759        $this->generate_implied_end_tags( 'P' );
    27632760        $this->state->stack_of_open_elements->pop_until( 'P' );
     
    27742771     * @param string|null $except_for_this_element Perform as if this element doesn't exist in the stack of open elements.
    27752772     */
    2776     private function generate_implied_end_tags( $except_for_this_element = null ) {
     2773    private function generate_implied_end_tags( ?string $except_for_this_element = null ): void {
    27772774        $elements_with_implied_end_tags = array(
    27782775            'DD',
     
    28102807     * @see https://html.spec.whatwg.org/#generate-implied-end-tags
    28112808     */
    2812     private function generate_implied_end_tags_thoroughly() {
     2809    private function generate_implied_end_tags_thoroughly(): void {
    28132810        $elements_with_implied_end_tags = array(
    28142811            'CAPTION',
     
    28522849     * @return bool Whether any formatting elements needed to be reconstructed.
    28532850     */
    2854     private function reconstruct_active_formatting_elements() {
     2851    private function reconstruct_active_formatting_elements(): bool {
    28552852        /*
    28562853         * > If there are no entries in the list of active formatting elements, then there is nothing
     
    30753072     * @see https://html.spec.whatwg.org/#adoption-agency-algorithm
    30763073     */
    3077     private function run_adoption_agency_algorithm() {
     3074    private function run_adoption_agency_algorithm(): void {
    30783075        $budget       = 1000;
    30793076        $subject      = $this->get_tag();
     
    31833180     * @param WP_HTML_Token $token Name of bookmark pointing to element in original input HTML.
    31843181     */
    3185     private function insert_html_element( $token ) {
     3182    private function insert_html_element( WP_HTML_Token $token ): void {
    31863183        $this->state->stack_of_open_elements->push( $token );
    31873184    }
     
    32013198     * @return bool Whether the element of the given name is in the special category.
    32023199     */
    3203     public static function is_special( $tag_name ) {
     3200    public static function is_special( $tag_name ): bool {
    32043201        $tag_name = strtoupper( $tag_name );
    32053202
     
    33163313     * @return bool Whether the given tag is an HTML Void Element.
    33173314     */
    3318     public static function is_void( $tag_name ) {
     3315    public static function is_void( $tag_name ): bool {
    33193316        $tag_name = strtoupper( $tag_name );
    33203317
Note: See TracChangeset for help on using the changeset viewer.