diff --git a/includes/admin/views/html-admin-page-status-report.php b/includes/admin/views/html-admin-page-status-report.php index 5b3028a11c5..7b8dd084c09 100644 --- a/includes/admin/views/html-admin-page-status-report.php +++ b/includes/admin/views/html-admin-page-status-report.php @@ -844,10 +844,11 @@ if ( 0 < count( $dropins_mu_plugins['mu_plugins'] ) ) : echo ' ' . wp_kses_post( sprintf( __( 'Page visibility should be public', 'woocommerce' ), 'https://wordpress.org/support/article/content-visibility/' ) ) . ''; $found_error = true; } else { - // Shortcode check. - if ( $_page['shortcode_required'] ) { - if ( ! $_page['shortcode_present'] ) { - echo ' ' . sprintf( esc_html__( 'Page does not contain the shortcode.', 'woocommerce' ), esc_html( $_page['shortcode'] ) ) . ''; + // Shortcode and block check. + if ( $_page['shortcode_required'] || $_page['block_required'] ) { + if ( ! $_page['shortcode_present'] && ! $_page['block_present'] ) { + /* Translators: %1$s: shortcode text, %2$s: block slug. */ + echo ' ' . ( $_page['block_required'] ? sprintf( esc_html__( 'Page does not contain the %1$s shortcode or the %2$s block.', 'woocommerce' ), esc_html( $_page['shortcode'] ), esc_html( $_page['block'] ) ) : sprintf( esc_html__( 'Page does not contain the %s shortcode.', 'woocommerce' ), esc_html( $_page['shortcode'] ) ) ) . ''; /* phpcs:ignore WordPress.XSS.EscapeOutput.OutputNotEscaped */ $found_error = true; } } diff --git a/includes/blocks/class-wc-blocks-utils.php b/includes/blocks/class-wc-blocks-utils.php new file mode 100644 index 00000000000..4ecb4c212e5 --- /dev/null +++ b/includes/blocks/class-wc-blocks-utils.php @@ -0,0 +1,84 @@ +post_content ); + if ( ! $blocks ) { + return array(); + } + + return $blocks; + } + + /** + * Get all instances of the specified block on a specific woo page + * (e.g. `cart` or `checkout` page). + * + * @param string $block_name The name (id) of a block, e.g. `woocommerce/cart`. + * @param string $woo_page_name The woo page to search, e.g. `cart`. + * @return array Array of blocks as returned by parse_blocks(). + */ + public static function get_blocks_from_page( $block_name, $woo_page_name ) { + $page_blocks = self::get_all_blocks_from_page( $woo_page_name ); + + // Get any instances of the specified block. + return array_values( + array_filter( + $page_blocks, + function ( $block ) use ( $block_name ) { + return ( $block_name === $block['blockName'] ); + } + ) + ); + } + + /** + * Check if a given page contains a particular block. + * + * @param int|WP_Post $page Page post ID or post object. + * @param string $block_name The name (id) of a block, e.g. `woocommerce/cart`. + * @return bool Boolean value if the page contains the block or not. Null in case the page does not exist. + */ + public static function has_block_in_page( $page, $block_name ) { + $page_to_check = get_post( $page ); + if ( null === $page_to_check ) { + return false; + } + + $blocks = parse_blocks( $page_to_check->post_content ); + foreach ( $blocks as $block ) { + if ( $block_name === $block['blockName'] ) { + return true; + } + } + + return false; + } +} diff --git a/includes/class-wc-tracker.php b/includes/class-wc-tracker.php index 27a36961c7f..713a9e735b8 100644 --- a/includes/class-wc-tracker.php +++ b/includes/class-wc-tracker.php @@ -660,49 +660,6 @@ class WC_Tracker { return ( '0' !== $result ) ? 'Yes' : 'No'; } - /** - * Get blocks from a woocommerce page. - * - * @param string $woo_page_name A woocommerce page e.g. `checkout` or `cart`. - * @return array Array of blocks as returned by parse_blocks(). - */ - private static function get_all_blocks_from_page( $woo_page_name ) { - $page_id = wc_get_page_id( $woo_page_name ); - - $page = get_post( $page_id ); - if ( ! $page ) { - return array(); - } - - $blocks = parse_blocks( $page->post_content ); - if ( ! $blocks ) { - return array(); - } - - return $blocks; - } - - /** - * Get all instances of the specified block on a specific woo page - * (e.g. `cart` or `checkout` page). - * - * @param string $block_name The name (id) of a block, e.g. `woocommerce/cart`. - * @param string $woo_page_name The woo page to search, e.g. `cart`. - * @return array Array of blocks as returned by parse_blocks(). - */ - private static function get_blocks_from_page( $block_name, $woo_page_name ) { - $page_blocks = self::get_all_blocks_from_page( $woo_page_name ); - - // Get any instances of the specified block. - return array_values( - array_filter( - $page_blocks, - function ( $block ) use ( $block_name ) { - return ( $block_name === $block['blockName'] ); - } - ) - ); - } /** * Get tracker data for a specific block type on a woocommerce page. @@ -714,7 +671,7 @@ class WC_Tracker { * - block_attributes */ public static function get_block_tracker_data( $block_name, $woo_page_name ) { - $blocks = self::get_blocks_from_page( $block_name, $woo_page_name ); + $blocks = WC_Blocks_Utils::get_blocks_from_page( $block_name, $woo_page_name ); $block_present = false; $attributes = array(); diff --git a/includes/class-woocommerce.php b/includes/class-woocommerce.php index 1c79eae5c16..a100353692a 100644 --- a/includes/class-woocommerce.php +++ b/includes/class-woocommerce.php @@ -425,6 +425,7 @@ final class WooCommerce { include_once WC_ABSPATH . 'includes/queue/class-wc-action-queue.php'; include_once WC_ABSPATH . 'includes/queue/class-wc-queue.php'; include_once WC_ABSPATH . 'includes/admin/marketplace-suggestions/class-wc-marketplace-updater.php'; + include_once WC_ABSPATH . 'includes/blocks/class-wc-blocks-utils.php'; /** * Data stores - used to store and retrieve CRUD object data from the database. diff --git a/includes/rest-api/Controllers/Version2/class-wc-rest-system-status-v2-controller.php b/includes/rest-api/Controllers/Version2/class-wc-rest-system-status-v2-controller.php index e2d6569140b..a420be32a5f 100644 --- a/includes/rest-api/Controllers/Version2/class-wc-rest-system-status-v2-controller.php +++ b/includes/rest-api/Controllers/Version2/class-wc-rest-system-status-v2-controller.php @@ -1162,7 +1162,7 @@ class WC_REST_System_Status_V2_Controller extends WC_REST_Controller { /** * Returns a mini-report on WC pages and if they are configured correctly: - * Present, visible, and including the correct shortcode. + * Present, visible, and including the correct shortcode or block. * * @return array */ @@ -1172,22 +1172,27 @@ class WC_REST_System_Status_V2_Controller extends WC_REST_Controller { _x( 'Shop base', 'Page setting', 'woocommerce' ) => array( 'option' => 'woocommerce_shop_page_id', 'shortcode' => '', + 'block' => '', ), _x( 'Cart', 'Page setting', 'woocommerce' ) => array( 'option' => 'woocommerce_cart_page_id', 'shortcode' => '[' . apply_filters( 'woocommerce_cart_shortcode_tag', 'woocommerce_cart' ) . ']', + 'block' => 'woocommerce/cart', ), _x( 'Checkout', 'Page setting', 'woocommerce' ) => array( 'option' => 'woocommerce_checkout_page_id', 'shortcode' => '[' . apply_filters( 'woocommerce_checkout_shortcode_tag', 'woocommerce_checkout' ) . ']', + 'block' => 'woocommerce/checkout', ), _x( 'My account', 'Page setting', 'woocommerce' ) => array( 'option' => 'woocommerce_myaccount_page_id', 'shortcode' => '[' . apply_filters( 'woocommerce_my_account_shortcode_tag', 'woocommerce_my_account' ) . ']', + 'block' => '', ), _x( 'Terms and conditions', 'Page setting', 'woocommerce' ) => array( 'option' => 'woocommerce_terms_page_id', 'shortcode' => '', + 'block' => '', ), ); @@ -1199,6 +1204,8 @@ class WC_REST_System_Status_V2_Controller extends WC_REST_Controller { $page_visible = false; $shortcode_present = false; $shortcode_required = false; + $block_present = false; + $block_required = false; // Page checks. if ( $page_id ) { @@ -1220,6 +1227,12 @@ class WC_REST_System_Status_V2_Controller extends WC_REST_Controller { } } + // Block checks. + if ( $values['block'] && get_post( $page_id ) ) { + $block_required = true; + $block_present = WC_Blocks_Utils::has_block_in_page( $page_id, $values['block'] ); + } + // Wrap up our findings into an output array. $pages_output[] = array( 'page_name' => $page_name, @@ -1228,8 +1241,11 @@ class WC_REST_System_Status_V2_Controller extends WC_REST_Controller { 'page_exists' => $page_exists, 'page_visible' => $page_visible, 'shortcode' => $values['shortcode'], + 'block' => $values['block'], 'shortcode_required' => $shortcode_required, 'shortcode_present' => $shortcode_present, + 'block_present' => $block_present, + 'block_required' => $block_required, ); } diff --git a/tests/legacy/unit-tests/blocks/class-wc-tests-blocks-utils.php b/tests/legacy/unit-tests/blocks/class-wc-tests-blocks-utils.php new file mode 100644 index 00000000000..907846f88f2 --- /dev/null +++ b/tests/legacy/unit-tests/blocks/class-wc-tests-blocks-utils.php @@ -0,0 +1,113 @@ + 'blocks-page', + 'title' => 'Checkout', + 'content' => '
', + ); + + $page_id = wc_create_page( $page['name'], '', $page['title'], $page['content'] ); + + $this->assertTrue( WC_Blocks_Utils::has_block_in_page( $page_id, 'woocommerce/checkout' ) ); + $this->assertFalse( WC_Blocks_Utils::has_block_in_page( $page_id, 'woocommerce/cart' ) ); + } + + /** + * @group block-utils + * Test: has_block_in_page. + * + */ + public function test_has_block_in_page_on_page_with_no_blocks() { + $page = array( + 'name' => 'shortcode-page', + 'title' => 'Checkout', + 'content' => ' [woocommerce_checkout] ', + ); + + $page_id = wc_create_page( $page['name'], '', $page['title'], $page['content'] ); + + $this->assertFalse( WC_Blocks_Utils::has_block_in_page( $page_id, 'woocommerce/checkout' ) ); + $this->assertFalse( WC_Blocks_Utils::has_block_in_page( $page_id, 'woocommerce/cart' ) ); + } + + /** + * @group block-utils + * Test: has_block_in_page. + * + */ + public function test_has_block_in_page_on_page_with_multiple_blocks() { + $page = array( + 'name' => 'shortcode-page', + 'title' => 'Checkout', + 'content' => ' + + + + + + +