diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index b8a65247..9732e7d8 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -31,8 +31,8 @@ jobs: DB_USER: root DB_PASS: root DB_HOST: localhost - INSTALL_PLUGINS: "admin-menu-editor autoptimize beaver-builder-lite-version contact-form-7 classic-editor custom-post-type-ui elementor forminator jetpack-boost woocommerce wordpress-seo wpforms-lite litespeed-cache wp-crontrol wp-super-cache w3-total-cache wp-fastest-cache wp-optimize sg-cachepress" # Don't include this repository's Plugin here. - INSTALL_PLUGINS_URLS: "https://downloads.wordpress.org/plugin/convertkit-for-woocommerce.1.6.4.zip http://cktestplugins.wpengine.com/wp-content/uploads/2024/01/convertkit-action-filter-tests.zip" # URLs to specific third party Plugins + INSTALL_PLUGINS: "admin-menu-editor autoptimize beaver-builder-lite-version block-visibility contact-form-7 classic-editor custom-post-type-ui elementor forminator jetpack-boost woocommerce wordpress-seo wpforms-lite litespeed-cache wp-crontrol wp-super-cache w3-total-cache wp-fastest-cache wp-optimize sg-cachepress" # Don't include this repository's Plugin here. + INSTALL_PLUGINS_URLS: "https://downloads.wordpress.org/plugin/convertkit-for-woocommerce.1.6.4.zip http://cktestplugins.wpengine.com/wp-content/uploads/2024/01/convertkit-action-filter-tests.zip http://cktestplugins.wpengine.com/wp-content/uploads/2024/11/disable-doing-it-wrong-notices.zip" # URLs to specific third party Plugins CONVERTKIT_API_KEY: ${{ secrets.CONVERTKIT_API_KEY }} # ConvertKit API Key, stored in the repository's Settings > Secrets CONVERTKIT_API_SECRET: ${{ secrets.CONVERTKIT_API_SECRET }} # ConvertKit API Secret, stored in the repository's Settings > Secrets CONVERTKIT_API_KEY_NO_DATA: ${{ secrets.CONVERTKIT_API_KEY_NO_DATA }} # ConvertKit API Key for ConvertKit account with no data, stored in the repository's Settings > Secrets diff --git a/includes/blocks/class-convertkit-block-form.php b/includes/blocks/class-convertkit-block-form.php index 9831500a..dfb0081f 100644 --- a/includes/blocks/class-convertkit-block-form.php +++ b/includes/blocks/class-convertkit-block-form.php @@ -290,6 +290,13 @@ public function get_default_values() { */ public function render( $atts ) { + // Check if the Block Visibility Plugin permits displaying this block. + if ( ! $this->is_block_visible( $atts ) ) { + // Block should not be displayed due to Block Visibility Plugin conditions. + // Return a blank string now. + return ''; + } + // Parse shortcode attributes, defining fallback defaults if required. $atts = shortcode_atts( $this->get_default_values(), diff --git a/includes/blocks/class-convertkit-block.php b/includes/blocks/class-convertkit-block.php index a4440627..61eeded2 100644 --- a/includes/blocks/class-convertkit-block.php +++ b/includes/blocks/class-convertkit-block.php @@ -382,4 +382,49 @@ public function is_block_editor_request() { } + /** + * If the Block Visiblity Plugin is active, run the block through its conditions now. + * We don't wait for Block Visibility to do this, as it performs this on the + * `render_block` filter, by which time the code in this method has fully executed, + * meaning any non-inline Forms will have had their scripts added to the + * `convertkit_output_scripts_footer` hook. + * As a result, the non-inline Form will always display, regardless of whether + * Block Visibility's conditions are met. + * We deliberately don't output non-inline Forms in their block, instead deferring + * to the `convertkit_output_scripts_footer` hook, to ensure the non-inline Forms + * styling are not constrained by the Theme's width, layout or other properties. + * + * @since 2.6.6 + * + * @param array $atts Block Attributes. + * @return bool Display Block + */ + public function is_block_visible( $atts ) { + + // Display the block if the Block Visibility Plugin isn't active. + if ( ! function_exists( '\BlockVisibility\Frontend\render_with_visibility' ) ) { + return true; + } + + // Determine whether the block should display. + $display_block = \BlockVisibility\Frontend\render_with_visibility( + 'block', + array( + 'blockName' => 'convertkit-' . $this->get_name(), + 'attrs' => $atts, + ) + ); + + // If the content returned is a blank string, conditions on this block set + // by the user in the Block Visibility Plugin resulted in the block not displaying. + // Don't display it. + if ( empty( $display_block ) ) { + return false; + } + + // If here, the block can be displayed. + return true; + + } + } diff --git a/includes/class-convertkit-output.php b/includes/class-convertkit-output.php index e6d4df15..80e090eb 100644 --- a/includes/class-convertkit-output.php +++ b/includes/class-convertkit-output.php @@ -391,6 +391,15 @@ public function append_form_to_content( $content ) { */ private function inject_form_after_element( $content, $tag, $index, $form ) { + // Wrap content in ,
and tags now, so we can inject the UTF-8 Content-Type meta tag. + $content = '' . $content . ''; + + // Forcibly tell DOMDocument that this HTML uses the UTF-8 charset. + // isn't enough, as DOMDocument still interprets the HTML as ISO-8859, which breaks character encoding + // Use of mb_convert_encoding() with HTML-ENTITIES is deprecated in PHP 8.2, so we have to use this method. + // If we don't, special characters render incorrectly. + $content = str_replace( '', '' . "\n" . '', $content ); + // Load Page / Post content into DOMDocument. libxml_use_internal_errors( true ); $html = new DOMDocument(); diff --git a/tests/_support/Helper/Acceptance/WPCron.php b/tests/_support/Helper/Acceptance/WPCron.php index 7114632a..7dce90e3 100644 --- a/tests/_support/Helper/Acceptance/WPCron.php +++ b/tests/_support/Helper/Acceptance/WPCron.php @@ -9,6 +9,15 @@ */ class WPCron extends \Codeception\Module { + /** + * Holds the admin UI URL for WP Crontrol. + * + * @since 2.6.6 + * + * @var string + */ + private $adminURL = 'tools.php?page=wp-crontrol'; + /** * Asserts if the given event name is scheduled in WordPress' Cron. * @@ -49,7 +58,7 @@ public function dontSeeCronEvent($I, $name) public function runCronEvent($I, $name) { // List cron event in WP-Crontrol Plugin. - $I->amOnAdminPage('tools.php?page=crontrol_admin_manage_page&s=' . $name); + $I->amOnAdminPage($this->adminURL . '&s=' . $name); // Hover mouse over event's name. $I->moveMouseOver('#the-list tr'); @@ -74,7 +83,7 @@ public function runCronEvent($I, $name) public function deleteCronEvent($I, $name) { // List cron event in WP-Crontrol Plugin. - $I->amOnAdminPage('tools.php?page=crontrol_admin_manage_page&s=' . $name); + $I->amOnAdminPage($this->adminURL . '&s=' . $name); // Hover mouse over event's name. $I->moveMouseOver('#the-list tr'); diff --git a/tests/_support/Helper/Acceptance/WPGutenberg.php b/tests/_support/Helper/Acceptance/WPGutenberg.php index 4e80ec56..3b76886e 100644 --- a/tests/_support/Helper/Acceptance/WPGutenberg.php +++ b/tests/_support/Helper/Acceptance/WPGutenberg.php @@ -405,7 +405,7 @@ public function addGutenbergPageToDatabase($I, $postType = 'page', $title = 'Gut -Item #2
+Item #2: Adhaésionés altéram improbis mi pariendarum sit stulti triarium
diff --git a/tests/acceptance/forms/blocks-shortcodes/PageBlockFormCest.php b/tests/acceptance/forms/blocks-shortcodes/PageBlockFormCest.php index 8790b3fa..edd5cb43 100644 --- a/tests/acceptance/forms/blocks-shortcodes/PageBlockFormCest.php +++ b/tests/acceptance/forms/blocks-shortcodes/PageBlockFormCest.php @@ -1026,6 +1026,55 @@ public function testFormBlockWithWPRocketPluginMinifyJS(AcceptanceTester $I) $I->deactivateThirdPartyPlugin($I, 'wp-rocket'); } + /** + * Test that a non-inline Form is not displayed when specified in the Form Block and the + * Block Visibility Plugin sets the block to not display. + * + * @since 2.6.6 + * + * @param AcceptanceTester $I Tester. + */ + public function testFormBlockWithNonInlineFormAndBlockVisibilityPlugin(AcceptanceTester $I) + { + // Setup Plugin and Resources. + $I->setupConvertKitPlugin($I); + $I->setupConvertKitPluginResources($I); + + // Activate Block Visibility Plugin. + $I->activateThirdPartyPlugin($I, 'block-visibility'); + + // Create a Page as if it were create in Gutenberg with the Form block + // set to display a non-inline Form, and the Block Visibility Plugin + // set to hide the block. + $pageID = $I->havePostInDatabase( + [ + 'post_type' => 'page', + 'post_title' => 'Kit: Page: Form: Block: Block Visibility', + 'post_content' => '', + 'meta_input' => [ + // Configure ConvertKit Plugin to not display a default Form. + '_wp_convertkit_post_meta' => [ + 'form' => '0', + 'landing_page' => '', + 'tag' => '', + ], + ], + ] + ); + + // Load Page. + $I->amOnPage('?p=' . $pageID); + + // Check that no PHP warnings or notices were output. + $I->checkNoWarningsAndNoticesOnScreen($I); + + // Confirm that no ConvertKit Form is displayed. + $I->dontSeeElementInDOM('form[data-sv-form]'); + + // Deactivate Block Visibility Plugin. + $I->deactivateThirdPartyPlugin($I, 'block-visibility'); + } + /** * Deactivate and reset Plugin(s) after each test, if the test passes. * We don't use _after, as this would provide a screenshot of the Plugin diff --git a/tests/acceptance/forms/blocks-shortcodes/PageShortcodeFormCest.php b/tests/acceptance/forms/blocks-shortcodes/PageShortcodeFormCest.php index 6e029610..f70beb45 100644 --- a/tests/acceptance/forms/blocks-shortcodes/PageShortcodeFormCest.php +++ b/tests/acceptance/forms/blocks-shortcodes/PageShortcodeFormCest.php @@ -655,6 +655,7 @@ public function testFormShortcodeWithPerfmattersPlugin(AcceptanceTester $I) $I->setupConvertKitPluginResources($I); // Activate Perfmatters Plugin. + $I->activateThirdPartyPlugin($I, 'disable-_load_textdomain_just_in_time-doing_it_wrong-notice'); $I->activateThirdPartyPlugin($I, 'perfmatters'); // Enable Defer and Delay JavaScript. @@ -700,6 +701,7 @@ public function testFormShortcodeWithPerfmattersPlugin(AcceptanceTester $I) // Deactivate Perfmatters Plugin. $I->deactivateThirdPartyPlugin($I, 'perfmatters'); + $I->deactivateThirdPartyPlugin($I, 'disable-_load_textdomain_just_in_time-doing_it_wrong-notice'); } /** @@ -770,6 +772,7 @@ public function testFormShortcodeWithWPRocketPlugin(AcceptanceTester $I) $I->setupConvertKitPluginResources($I); // Activate WP Rocket Plugin. + $I->activateThirdPartyPlugin($I, 'disable-_load_textdomain_just_in_time-doing_it_wrong-notice'); $I->activateThirdPartyPlugin($I, 'wp-rocket'); // Configure WP Rocket. @@ -806,6 +809,7 @@ public function testFormShortcodeWithWPRocketPlugin(AcceptanceTester $I) // Deactivate WP Rocket Plugin. $I->deactivateThirdPartyPlugin($I, 'wp-rocket'); + $I->deactivateThirdPartyPlugin($I, 'disable-_load_textdomain_just_in_time-doing_it_wrong-notice'); } /** diff --git a/tests/acceptance/forms/post-types/CPTFormCest.php b/tests/acceptance/forms/post-types/CPTFormCest.php index 59904c29..0a5b968c 100644 --- a/tests/acceptance/forms/post-types/CPTFormCest.php +++ b/tests/acceptance/forms/post-types/CPTFormCest.php @@ -314,6 +314,9 @@ public function testAddNewCPTUsingDefaultFormAfterParagraphElement(AcceptanceTes // Confirm that one ConvertKit Form is output in the DOM after the third paragraph. $I->seeFormOutput($I, $_ENV['CONVERTKIT_API_FORM_ID'], 'after_element', 'p', 3); + + // Confirm character encoding is not broken due to using DOMDocument. + $I->seeInSource('Adhaésionés altéram improbis mi pariendarum sit stulti triarium'); } /** @@ -350,6 +353,9 @@ public function testAddNewCPTUsingDefaultFormAfterHeadingElement(AcceptanceTeste // Confirm that one ConvertKit Form is output in the DOM after the second