diff --git a/src/wp-includes/html-api/class-wp-html-processor.php b/src/wp-includes/html-api/class-wp-html-processor.php index 4f771535edaa7..dd4469d5277d9 100644 --- a/src/wp-includes/html-api/class-wp-html-processor.php +++ b/src/wp-includes/html-api/class-wp-html-processor.php @@ -143,6 +143,14 @@ * @see WP_HTML_Tag_Processor * @link https://html.spec.whatwg.org/ * @phpstan-consistent-constructor + * + * @phpstan-type Query array{ + * tag_name?: non-empty-string|null, + * match_offset?: int<1, max>|null, + * class_name?: non-empty-string|null, + * tag_closers?: 'visit'|'skip'|null, + * breadcrumbs?: array, + * }|non-empty-string|null */ class WP_HTML_Processor extends WP_HTML_Tag_Processor { /** @@ -237,6 +245,7 @@ class WP_HTML_Processor extends WP_HTML_Tag_Processor { * @since 6.7.0 * * @var string[] + * @phpstan-var list */ private $breadcrumbs = array(); @@ -687,6 +696,8 @@ public function get_unsupported_exception() { * May also contain the wildcard `*` which matches a single element, e.g. `array( 'SECTION', '*' )`. * } * @return bool Whether a tag was matched. + * + * @phpstan-param Query $query */ public function next_tag( $query = null ): bool { $visit_closers = isset( $query['tag_closers'] ) && 'visit' === $query['tag_closers']; @@ -930,6 +941,8 @@ private function is_virtual(): bool { * @param string[] $breadcrumbs DOM sub-path at which element is found, e.g. `array( 'FIGURE', 'IMG' )`. * May also contain the wildcard `*` which matches a single element, e.g. `array( 'SECTION', '*' )`. * @return bool Whether the currently-matched tag is found at the given nested structure. + * + * @phpstan-param array $breadcrumbs */ public function matches_breadcrumbs( $breadcrumbs ): bool { // Everything matches when there are zero constraints. @@ -1201,6 +1214,8 @@ public function step( $node_to_process = self::PROCESS_NEXT_NODE ): bool { * @since 6.4.0 * * @return string[] Array of tag names representing path to matched node. + * + * @phpstan-return list */ public function get_breadcrumbs(): array { return $this->breadcrumbs; @@ -5154,6 +5169,8 @@ public function get_namespace(): string { * @since 6.4.0 * * @return string|null Name of currently matched tag in input HTML, or `null` if none found. + * + * @phpstan-return non-falsy-string|null */ public function get_tag(): ?string { if ( null !== $this->last_error ) { @@ -5219,6 +5236,8 @@ public function has_self_closing_flag(): bool { * @since 6.6.0 Subclassed for the HTML Processor. * * @return string|null Name of the matched token. + * + * @phpstan-return non-falsy-string|null */ public function get_token_name(): ?string { return $this->is_virtual() @@ -6276,6 +6295,8 @@ private function insert_foreign_element( WP_HTML_Token $token, bool $only_add_to * @param string|null $bookmark_name Optional. Name to give bookmark for created virtual node. * Defaults to auto-creating a bookmark name. * @return WP_HTML_Token Newly-created virtual token. + * + * @phpstan-param non-falsy-string $token_name */ private function insert_virtual_node( $token_name, $bookmark_name = null ): WP_HTML_Token { $here = $this->bookmarks[ $this->state->current_token->bookmark_name ]; diff --git a/src/wp-includes/html-api/class-wp-html-tag-processor.php b/src/wp-includes/html-api/class-wp-html-tag-processor.php index c39368e9a40c1..cb92daa3d5a8c 100644 --- a/src/wp-includes/html-api/class-wp-html-tag-processor.php +++ b/src/wp-includes/html-api/class-wp-html-tag-processor.php @@ -407,6 +407,13 @@ * @since 6.5.0 Pauses processor when input ends in an incomplete syntax token. * Introduces "special" elements which act like void elements, e.g. TITLE, STYLE. * Allows scanning through all tokens and processing modifiable text, where applicable. + * + * @phpstan-type Query array{ + * tag_name?: non-empty-string|null, + * match_offset?: int<1, max>|null, + * class_name?: non-empty-string|null, + * tag_closers?: 'visit'|'skip'|null, + * }|non-empty-string|null */ class WP_HTML_Tag_Processor { /** @@ -443,7 +450,8 @@ class WP_HTML_Tag_Processor { * The last query passed to next_tag(). * * @since 6.2.0 - * @var array|null + * @var array|string|null + * @phpstan-var Query */ private $last_query; @@ -452,6 +460,7 @@ class WP_HTML_Tag_Processor { * * @since 6.2.0 * @var string|null + * @phpstan-var non-empty-string|null */ private $sought_tag_name; @@ -460,6 +469,7 @@ class WP_HTML_Tag_Processor { * * @since 6.2.0 * @var string|null + * @phpstan-var non-empty-string|null */ private $sought_class_name; @@ -468,6 +478,7 @@ class WP_HTML_Tag_Processor { * * @since 6.2.0 * @var int|null + * @phpstan-var int<1, max>|null */ private $sought_match_offset; @@ -895,6 +906,7 @@ public function change_parsing_namespace( string $new_namespace ): bool { * } * @return bool Whether a tag was matched. * + * @phpstan-param Query $query * @phpstan-impure */ public function next_tag( $query = null ): bool { @@ -3034,12 +3046,22 @@ public function get_namespace(): string { * @since 6.2.0 * * @return string|null Name of currently matched tag in input HTML, or `null` if none found. + * + * @phpstan-return non-falsy-string|null */ public function get_tag(): ?string { if ( null === $this->tag_name_starts_at ) { return null; } + /** + * The name is never empty and never "0": a tag name starts with an ASCII + * letter, a processing instruction target with a letter or "_", and the + * target of a comment which looks like a processing instruction with a + * letter, ":", or "_". + * + * @var non-falsy-string $tag_name + */ $tag_name = str_replace( "\x00", "\u{FFFD}", substr( $this->html, $this->tag_name_starts_at, $this->tag_name_length ) ); if ( self::STATE_MATCHED_TAG === $this->parser_state ) { @@ -3071,6 +3093,8 @@ public function get_tag(): ?string { * @since 6.7.0 * * @return string|null Name of current tag name. + * + * @phpstan-return non-falsy-string|null */ public function get_qualified_tag_name(): ?string { $tag_name = $this->get_tag(); @@ -3569,6 +3593,8 @@ public function get_token_type(): ?string { * @since 6.5.0 * * @return string|null Name of the matched token. + * + * @phpstan-return non-falsy-string|null */ public function get_token_name(): ?string { switch ( $this->parser_state ) { @@ -4988,6 +5014,7 @@ public function get_updated_html(): string { * @type string|null $class_name Tag must contain this class name to match. * @type string $tag_closers "visit" or "skip": whether to stop on tag closers, e.g. . * } + * @phpstan-param Query $query */ private function parse_query( $query ) { if ( null !== $query && $query === $this->last_query ) { diff --git a/src/wp-includes/html-api/class-wp-html-token.php b/src/wp-includes/html-api/class-wp-html-token.php index 01701d02ec9d1..926a12cf8200f 100644 --- a/src/wp-includes/html-api/class-wp-html-token.php +++ b/src/wp-includes/html-api/class-wp-html-token.php @@ -43,6 +43,7 @@ class WP_HTML_Token { * @see WP_HTML_Processor::get_tag() * * @var string + * @phpstan-var non-falsy-string */ public $node_name = null; @@ -96,6 +97,8 @@ class WP_HTML_Token { * @param string $node_name Name of node token represents; if uppercase, an HTML element; if lowercase, a special value like "marker". * @param bool $has_self_closing_flag Whether the source token contains the self-closing flag, regardless of whether it's valid. * @param callable|null $on_destroy Optional. Function to call when destroying token, useful for releasing the bookmark. + * + * @phpstan-param non-falsy-string $node_name */ public function __construct( ?string $bookmark_name, string $node_name, bool $has_self_closing_flag, ?callable $on_destroy = null ) { $this->bookmark_name = $bookmark_name;