From 4893ce0c97079e25e103b8e7ef17610ad7e54f14 Mon Sep 17 00:00:00 2001 From: Tim Carr Date: Thu, 26 Feb 2026 14:18:35 +0800 Subject: [PATCH] Default Form Position: Fix errant HTML tags --- includes/class-convertkit-output.php | 21 +++++++++++++------ tests/EndToEnd.suite.yml | 1 - .../EndToEnd/forms/post-types/CPTFormCest.php | 15 +++++++++++++ .../forms/post-types/PageFormCest.php | 16 ++++++++++++-- .../forms/post-types/PostFormCest.php | 15 +++++++++++++ tests/Support/Helper/KitForms.php | 14 +++++++++++++ 6 files changed, 73 insertions(+), 9 deletions(-) diff --git a/includes/class-convertkit-output.php b/includes/class-convertkit-output.php index be427fcf4..4d237ad94 100644 --- a/includes/class-convertkit-output.php +++ b/includes/class-convertkit-output.php @@ -504,14 +504,23 @@ private function inject_form_after_element( $content, $tag, $index, $form ) { return $content . $form; } - // Create new element for the Form. - $form_node = new DOMDocument(); - $form_node->loadHTML( $form, LIBXML_HTML_NODEFDTD ); + // Load the form into the parser. + $form_parser = new ConvertKit_HTML_Parser( $form, LIBXML_HTML_NODEFDTD ); + $form_body = $form_parser->html->getElementsByTagName( 'body' )->item( 0 ); + + // Collect nodes first to avoid live NodeList mutation issues. + $nodes_to_insert = array(); + foreach ( $form_body->childNodes as $child ) { // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase + $nodes_to_insert[] = $parser->html->importNode( $child, true ); + } - // Append the form to the specific element. - $element_node->parentNode->insertBefore( $parser->html->importNode( $form_node->documentElement, true ), $element_node->nextSibling ); // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase + // Inject the form node(s) after the element node e.g. after the paragraph, heading etc. + $next_sibling = $element_node->nextSibling; // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase + foreach ( $nodes_to_insert as $node ) { + $element_node->parentNode->insertBefore( $node, $element_node->nextSibling ); // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase + } - // Fetch HTML string. + // Return modified HTML string. return $parser->get_body_html(); } diff --git a/tests/EndToEnd.suite.yml b/tests/EndToEnd.suite.yml index 7cf15b9ed..d8ef7596f 100644 --- a/tests/EndToEnd.suite.yml +++ b/tests/EndToEnd.suite.yml @@ -55,7 +55,6 @@ modules: capabilities: "goog:chromeOptions": args: - - "--headless" - "--disable-gpu" - "--disable-dev-shm-usage" - "--disable-software-rasterizer" diff --git a/tests/EndToEnd/forms/post-types/CPTFormCest.php b/tests/EndToEnd/forms/post-types/CPTFormCest.php index e3d2b4218..b4edd7e58 100644 --- a/tests/EndToEnd/forms/post-types/CPTFormCest.php +++ b/tests/EndToEnd/forms/post-types/CPTFormCest.php @@ -356,6 +356,9 @@ public function testAddNewCPTUsingDefaultFormAfterParagraphElement(EndToEndTeste // Confirm no meta tag exists within the content. $I->dontSeeInSource(''); + + // Confirm no extra , or tags are output i.e. injecting the form doesn't result in DOMDocument adding tags. + $I->seeNoExtraHtmlHeadBodyTagsOutput($I); } /** @@ -403,6 +406,9 @@ public function testAddNewCPTUsingDefaultNonInlineFormAfterParagraphElement(EndT // Confirm no meta tag exists within the content. $I->dontSeeInSource(''); + + // Confirm no extra , or tags are output i.e. injecting the form doesn't result in DOMDocument adding tags. + $I->seeNoExtraHtmlHeadBodyTagsOutput($I); } /** @@ -455,6 +461,9 @@ public function testAddNewCPTUsingDefaultFormAfterHeadingElement(EndToEndTester // Confirm no meta tag exists within the content. $I->dontSeeInSource(''); + + // Confirm no extra , or tags are output i.e. injecting the form doesn't result in DOMDocument adding tags. + $I->seeNoExtraHtmlHeadBodyTagsOutput($I); } /** @@ -507,6 +516,9 @@ public function testAddNewCPTUsingDefaultFormAfterImageElement(EndToEndTester $I // Confirm no meta tag exists within the content. $I->dontSeeInSource(''); + + // Confirm no extra , or tags are output i.e. injecting the form doesn't result in DOMDocument adding tags. + $I->seeNoExtraHtmlHeadBodyTagsOutput($I); } /** @@ -558,6 +570,9 @@ public function testAddNewCPTUsingDefaultFormAfterOutOfBoundsElement(EndToEndTes // Confirm no meta tag exists within the content. $I->dontSeeInSource(''); + + // Confirm no extra , or tags are output i.e. injecting the form doesn't result in DOMDocument adding tags. + $I->seeNoExtraHtmlHeadBodyTagsOutput($I); } /** diff --git a/tests/EndToEnd/forms/post-types/PageFormCest.php b/tests/EndToEnd/forms/post-types/PageFormCest.php index 66b0e3f06..7d58b1884 100644 --- a/tests/EndToEnd/forms/post-types/PageFormCest.php +++ b/tests/EndToEnd/forms/post-types/PageFormCest.php @@ -278,6 +278,9 @@ public function testAddNewPageUsingDefaultFormAfterParagraphElement(EndToEndTest // Confirm no meta tag exists within the content. $I->dontSeeInSource(''); + + // Confirm no extra , or tags are output i.e. injecting the form doesn't result in DOMDocument adding tags. + $I->seeNoExtraHtmlHeadBodyTagsOutput($I); } /** @@ -324,6 +327,9 @@ public function testAddNewPageUsingDefaultNonInlineFormAfterParagraphElement(End // Confirm no meta tag exists within the content. $I->dontSeeInSource(''); + + // Confirm no extra , or tags are output i.e. injecting the form doesn't result in DOMDocument adding tags. + $I->seeNoExtraHtmlHeadBodyTagsOutput($I); } /** @@ -375,6 +381,9 @@ public function testAddNewPageUsingDefaultFormAfterHeadingElement(EndToEndTester // Confirm no meta tag exists within the content. $I->dontSeeInSource(''); + + // Confirm no extra , or tags are output i.e. injecting the form doesn't result in DOMDocument adding tags. + $I->seeNoExtraHtmlHeadBodyTagsOutput($I); } /** @@ -427,8 +436,8 @@ public function testAddNewPageUsingDefaultFormAfterImageElement(EndToEndTester $ // Confirm no meta tag exists within the content. $I->dontSeeInSource(''); - // Confirm no meta tag exists within the content. - $I->dontSeeInSource(''); + // Confirm no extra , or tags are output i.e. injecting the form doesn't result in DOMDocument adding tags. + $I->seeNoExtraHtmlHeadBodyTagsOutput($I); } /** @@ -479,6 +488,9 @@ public function testAddNewPageUsingDefaultFormAfterOutOfBoundsElement(EndToEndTe // Confirm no meta tag exists within the content. $I->dontSeeInSource(''); + + // Confirm no extra , or tags are output i.e. injecting the form doesn't result in DOMDocument adding tags. + $I->seeNoExtraHtmlHeadBodyTagsOutput($I); } /** diff --git a/tests/EndToEnd/forms/post-types/PostFormCest.php b/tests/EndToEnd/forms/post-types/PostFormCest.php index 9d545a09e..dcf292f09 100644 --- a/tests/EndToEnd/forms/post-types/PostFormCest.php +++ b/tests/EndToEnd/forms/post-types/PostFormCest.php @@ -282,6 +282,9 @@ public function testAddNewPostUsingDefaultFormAfterParagraphElement(EndToEndTest // Confirm no meta tag exists within the content. $I->dontSeeInSource(''); + + // Confirm no extra , or tags are output i.e. injecting the form doesn't result in DOMDocument adding tags. + $I->seeNoExtraHtmlHeadBodyTagsOutput($I); } /** @@ -329,6 +332,9 @@ public function testAddNewPostUsingDefaultNonInlineFormAfterParagraphElement(End // Confirm no meta tag exists within the content. $I->dontSeeInSource(''); + + // Confirm no extra , or tags are output i.e. injecting the form doesn't result in DOMDocument adding tags. + $I->seeNoExtraHtmlHeadBodyTagsOutput($I); } /** @@ -381,6 +387,9 @@ public function testAddNewPostUsingDefaultFormAfterHeadingElement(EndToEndTester // Confirm no meta tag exists within the content. $I->dontSeeInSource(''); + + // Confirm no extra , or tags are output i.e. injecting the form doesn't result in DOMDocument adding tags. + $I->seeNoExtraHtmlHeadBodyTagsOutput($I); } /** @@ -433,6 +442,9 @@ public function testAddNewPostUsingDefaultFormAfterImageElement(EndToEndTester $ // Confirm no meta tag exists within the content. $I->dontSeeInSource(''); + + // Confirm no extra , or tags are output i.e. injecting the form doesn't result in DOMDocument adding tags. + $I->seeNoExtraHtmlHeadBodyTagsOutput($I); } /** @@ -484,6 +496,9 @@ public function testAddNewPostUsingDefaultFormAfterOutOfBoundsElement(EndToEndTe // Confirm no meta tag exists within the content. $I->dontSeeInSource(''); + + // Confirm no extra , or tags are output i.e. injecting the form doesn't result in DOMDocument adding tags. + $I->seeNoExtraHtmlHeadBodyTagsOutput($I); } /** diff --git a/tests/Support/Helper/KitForms.php b/tests/Support/Helper/KitForms.php index 9c676254d..f4525c36c 100644 --- a/tests/Support/Helper/KitForms.php +++ b/tests/Support/Helper/KitForms.php @@ -236,4 +236,18 @@ public function seeLandingPageOutput($I, $langTag = false) $I->seeInSource(''); $I->seeInSource(''); } + + /** + * Confirm no extra , or tags are output i.e. injecting the form doesn't result in DOMDocument adding tags. + * + * @since 3.2.1 + * + * @param EndToEndTester $I Tester. + */ + public function seeNoExtraHtmlHeadBodyTagsOutput($I) + { + $I->seeNumberOfElementsInDOM('html', 1); + $I->seeNumberOfElementsInDOM('head', 1); + $I->seeNumberOfElementsInDOM('body', 1); + } }