diff --git a/src/wp-includes/html-api/class-wp-html-open-elements.php b/src/wp-includes/html-api/class-wp-html-open-elements.php index 1265e81513a00..f0b0fcb595f56 100644 --- a/src/wp-includes/html-api/class-wp-html-open-elements.php +++ b/src/wp-includes/html-api/class-wp-html-open-elements.php @@ -145,25 +145,45 @@ public function current_node() { } /** - * Checks if the node at the top of the stack matches provided node name. + * Indicates if the current node is of a given type or name. * - * @example - * // Is the current node a text node: - * $stack->current_node_is( '#text' ); + * It's possible to pass either a node type or a node name to this function. + * In the case there is no current element it will always return `false`. * - * // Is the current node a DIV element: - * $stack->current_node_is( 'DIV' ); + * Example: + * + * // Is the current node a text node? + * $stack->current_node_is( '#text' ); + * + * // Is the current node a DIV element? + * $stack->current_node_is( 'DIV' ); + * + * // Is the current node any element/tag? + * $stack->current_node_is( '#tag' ); + * + * @see WP_HTML_Tag_Processor::get_token_type + * @see WP_HTML_Tag_Processor::get_token_name * * @since 6.7.0 * - * @param string $node_name The node name to match. Provide a tag name for tags or a - * token name for other types of tokens. - * @return bool True if there are nodes on the stack and the top node has - * a matching node_name. + * @access private + * + * @param string $identity Check if the current node has this name or type (depending on what is provided). + * @return bool Whether there is a current element that matches the given identity, whether a token name or type. */ - public function current_node_is( string $node_name ): bool { + public function current_node_is( string $identity ): bool { $current_node = end( $this->stack ); - return $current_node && $current_node->node_name === $node_name; + if ( false === $current_node ) { + return false; + } + + $current_node_name = $current_node->node_name; + + return ( + $current_node_name === $identity || + ( '#doctype' === $identity && 'html' === $current_node_name ) || + ( '#tag' === $identity && ctype_upper( $current_node_name ) ) + ); } /** 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 49634d8571f12..2c2baadd2ce26 100644 --- a/src/wp-includes/html-api/class-wp-html-processor.php +++ b/src/wp-includes/html-api/class-wp-html-processor.php @@ -1035,7 +1035,7 @@ private function step_in_body() { } $this->generate_implied_end_tags(); - if ( $this->state->stack_of_open_elements->current_node()->node_name !== $token_name ) { + if ( ! $this->state->stack_of_open_elements->current_node_is( $token_name ) ) { // @todo Record parse error: this error doesn't impact parsing. } $this->state->stack_of_open_elements->pop_until( $token_name ); @@ -1100,7 +1100,7 @@ private function step_in_body() { $this->generate_implied_end_tags(); - if ( $this->state->stack_of_open_elements->current_node()->node_name !== $token_name ) { + if ( ! $this->state->stack_of_open_elements->current_node_is( $token_name ) ) { // @todo Record parse error: this error doesn't impact parsing. } @@ -1126,7 +1126,7 @@ private function step_in_body() { if ( $is_li ? 'LI' === $node->node_name : ( 'DD' === $node->node_name || 'DT' === $node->node_name ) ) { $node_name = $is_li ? 'LI' : $node->node_name; $this->generate_implied_end_tags( $node_name ); - if ( $node_name !== $this->state->stack_of_open_elements->current_node()->node_name ) { + if ( ! $this->state->stack_of_open_elements->current_node_is( $node_name ) ) { // @todo Indicate a parse error once it's possible. This error does not impact the logic here. } @@ -1203,7 +1203,7 @@ private function step_in_body() { $this->generate_implied_end_tags( $token_name ); - if ( $token_name !== $this->state->stack_of_open_elements->current_node()->node_name ) { + if ( ! $this->state->stack_of_open_elements->current_node_is( $token_name ) ) { // @todo Indicate a parse error once it's possible. This error does not impact the logic here. } diff --git a/src/wp-includes/pluggable.php b/src/wp-includes/pluggable.php index 04a4ef8b55797..0e9e0d4579c19 100644 --- a/src/wp-includes/pluggable.php +++ b/src/wp-includes/pluggable.php @@ -2224,7 +2224,15 @@ function wp_new_user_notification( $user_id, $deprecated = null, $notify = '' ) /* translators: %s: User login. */ $message = sprintf( __( 'Username: %s' ), $user->user_login ) . "\r\n\r\n"; $message .= __( 'To set your password, visit the following address:' ) . "\r\n\r\n"; - $message .= network_site_url( "wp-login.php?action=rp&key=$key&login=" . rawurlencode( $user->user_login ), 'login' ) . "\r\n\r\n"; + + /* + * Since some user login names end in a period, this could produce ambiguous URLs that + * end in a period. To avoid the ambiguity, ensure that the login is not the last query + * arg in the URL. If moving it to the end, a trailing period will need to be escaped. + * + * @see https://core.trac.wordpress.org/tickets/42957 + */ + $message .= network_site_url( 'wp-login.php?login=' . rawurlencode( $user->user_login ) . "&key=$key&action=rp", 'login' ) . "\r\n\r\n"; $message .= wp_login_url() . "\r\n"; diff --git a/src/wp-includes/user.php b/src/wp-includes/user.php index 38ff198286b3e..5a05fff2f4c73 100644 --- a/src/wp-includes/user.php +++ b/src/wp-includes/user.php @@ -3219,7 +3219,15 @@ function retrieve_password( $user_login = null ) { $message .= sprintf( __( 'Username: %s' ), $user_login ) . "\r\n\r\n"; $message .= __( 'If this was a mistake, ignore this email and nothing will happen.' ) . "\r\n\r\n"; $message .= __( 'To reset your password, visit the following address:' ) . "\r\n\r\n"; - $message .= network_site_url( "wp-login.php?action=rp&key=$key&login=" . rawurlencode( $user_login ), 'login' ) . '&wp_lang=' . $locale . "\r\n\r\n"; + + /* + * Since some user login names end in a period, this could produce ambiguous URLs that + * end in a period. To avoid the ambiguity, ensure that the login is not the last query + * arg in the URL. If moving it to the end, a trailing period will need to be escaped. + * + * @see https://core.trac.wordpress.org/tickets/42957 + */ + $message .= network_site_url( 'wp-login.php?login=' . rawurlencode( $user_login ) . "&key=$key&action=rp", 'login' ) . '&wp_lang=' . $locale . "\r\n\r\n"; if ( ! is_user_logged_in() ) { $requester_ip = $_SERVER['REMOTE_ADDR']; diff --git a/tests/phpunit/tests/rest-api/rest-global-styles-revisions-controller.php b/tests/phpunit/tests/rest-api/rest-global-styles-revisions-controller.php index 6b03aa3af1f42..b01ada9be28ff 100644 --- a/tests/phpunit/tests/rest-api/rest-global-styles-revisions-controller.php +++ b/tests/phpunit/tests/rest-api/rest-global-styles-revisions-controller.php @@ -272,12 +272,12 @@ protected function check_get_revision_response( $response_revision_item, $revisi // Global styles. $config = ( new WP_Theme_JSON( json_decode( $revision_expected_item->post_content, true ), 'custom' ) )->get_raw_data(); - $this->assertEquals( + $this->assertSame( $config['settings'], $response_revision_item['settings'], 'Check that the revision settings exist in the response.' ); - $this->assertEquals( + $this->assertSame( $config['styles'], $response_revision_item['styles'], 'Check that the revision styles match the updated styles.' @@ -371,7 +371,7 @@ public function test_get_items_eligible_roles() { $data = $response->get_data(); $this->assertCount( $this->total_revisions + 1, $data, 'Check that extra revision exist' ); - $this->assertEquals( self::$second_admin_id, $data[0]['author'], 'Check that second author id returns expected value.' ); + $this->assertSame( self::$second_admin_id, $data[0]['author'], 'Check that second author id returns expected value.' ); } /**