From 76c4ab8071ed8e6a077538bc55ecc1e3f359864f Mon Sep 17 00:00:00 2001
From: Dennis Snell <dennis.snell@automattic.com>
Date: Sat, 1 Jul 2023 20:13:35 +0100
Subject: [PATCH] Refactor last fix to create post-hooks for element addition
 and removal from the stack of open elements.

---
 .../html-api/class-wp-html-open-elements.php  | 82 +++++++++++++------
 1 file changed, 57 insertions(+), 25 deletions(-)

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 a80973672ec1b..eda310d694015 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
@@ -187,16 +187,7 @@ public function pop() {
 			return false;
 		}
 
-		/*
-		 * When adding support for new elements, expand this switch to trap
-		 * cases where the precalculated value needs to change.
-		 */
-		switch ( $item->node_name ) {
-			case 'P':
-				$this->has_p_in_button_scope = $this->has_element_in_button_scope( 'P' );
-				break;
-		}
-
+		$this->after_element_pop( $item );
 		return true;
 	}
 
@@ -233,16 +224,7 @@ public function pop_until( $tag_name ) {
 	 */
 	public function push( $stack_item ) {
 		$this->stack[] = $stack_item;
-
-		/*
-		 * When adding support for new elements, expand this switch to trap
-		 * cases where the precalculated value needs to change.
-		 */
-		switch ( $stack_item->node_name ) {
-			case 'P':
-				$this->has_p_in_button_scope = true;
-				break;
-		}
+		$this->after_element_push( $stack_item );
 	}
 
 	/**
@@ -257,11 +239,7 @@ public function remove_node( $token ) {
 		foreach ( $this->walk_up() as $position => $item ) {
 			if ( $token->bookmark_name === $item->bookmark_name ) {
 				array_splice( $this->stack, $this->count() - $position - 1, 1 );
-				switch ( $item->node_name ) {
-					case 'P':
-						$this->has_p_in_button_scope = $this->has_element_in_button_scope( 'P' );
-						break;
-				}
+				$this->after_element_pop( $item );
 				return true;
 			}
 		}
@@ -321,4 +299,58 @@ public function walk_up() {
 			yield $this->stack[ $i ];
 		}
 	}
+
+	/*
+	 * Internal helpers.
+	 */
+
+	/**
+	 * Updates internal flags after adding an element.
+	 *
+	 * Certain conditions (such as "has_p_in_button_scope") are maintained here as
+	 * flags that are only modified when adding and removing elements. This allows
+	 * the HTML Processor to quickly check for these conditions instead of iterating
+	 * over the open stack elements upon each new tag it encounters. These flags,
+	 * however, need to be maintained as items are added and removed from the stack.
+	 *
+	 * @since 6.4.0
+	 *
+	 * @param WP_HTML_Token $item Element that was added to the stack of open elements.
+	 */
+	public function after_element_push( $item ) {
+		/*
+		 * When adding support for new elements, expand this switch to trap
+		 * cases where the precalculated value needs to change.
+		 */
+		switch ( $item->node_name ) {
+			case 'P':
+				$this->has_p_in_button_scope = true;
+				break;
+		}
+	}
+
+	/**
+	 * Updates internal flags after removing an element.
+	 *
+	 * Certain conditions (such as "has_p_in_button_scope") are maintained here as
+	 * flags that are only modified when adding and removing elements. This allows
+	 * the HTML Processor to quickly check for these conditions instead of iterating
+	 * over the open stack elements upon each new tag it encounters. These flags,
+	 * however, need to be maintained as items are added and removed from the stack.
+	 *
+	 * @since 6.4.0
+	 *
+	 * @param WP_HTML_Token $item Element that was removed to the stack of open elements.
+	 */
+	public function after_element_pop( $item ) {
+		/*
+		 * When adding support for new elements, expand this switch to trap
+		 * cases where the precalculated value needs to change.
+		 */
+		switch ( $item->node_name ) {
+			case 'P':
+				$this->has_p_in_button_scope = $this->has_element_in_button_scope( 'P' );
+				break;
+		}
+	}
 }