From a163b349e12b3d4d93d4d7ecf202660d1b00f617 Mon Sep 17 00:00:00 2001 From: Keith Solomon Date: Sat, 4 Jul 2026 13:54:27 -0500 Subject: [PATCH] feat(hero): add isServicesDescendant() helper and bypass constant --- lib/extras.php | 61 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) diff --git a/lib/extras.php b/lib/extras.php index d60c162..961f706 100644 --- a/lib/extras.php +++ b/lib/extras.php @@ -77,6 +77,67 @@ function hasPageHeader() { return true; } +/** + * Bypass constant for the inner-page hero ancestor check. + * + * When `true`, `isServicesDescendant()` returns `true` for every page. + * Set this in test setup (e.g. in `wp-config.php` or a test bootstrap) so + * test fixture pages that are not Services descendants can still render + * the hero. + */ +if ( ! defined( 'CWC_TEST_BYPASS_HERO_GATE' ) ) { + define( 'CWC_TEST_BYPASS_HERO_GATE', false ); +} + +/** + * Checks if the current page is the Services page, a child of it, or + * a grandchild of it. Used to gate the inner-page hero. + * + * @param WP_Post|null $post The post to check. Defaults to the global `$post`. + * @param int|null $services_id Override the Services page ID. Defaults to + * the page with slug `services`. + * + * @return bool true if the post is the Services page or a descendant up to 2 levels. + */ +function isServicesDescendant( $post = null, $services_id = null ) { + if ( CWC_TEST_BYPASS_HERO_GATE ) { + return true; + } + + if ( null === $post ) { + global $post; + } + + if ( ! $post instanceof WP_Post ) { + return false; + } + + if ( null === $services_id ) { + $services = get_page_by_path( 'services' ); + if ( ! $services ) { + return false; + } + $services_id = (int) $services->ID; + } + + $services_id = (int) $services_id; + + if ( (int) $post->ID === $services_id ) { + return true; + } + + if ( (int) $post->post_parent === $services_id ) { + return true; + } + + $parent = get_post( $post->post_parent ); + if ( $parent && (int) $parent->post_parent === $services_id ) { + return true; + } + + return false; +} + /** Create the Owner role. * * This function creates a new role named "Owner" with all the capabilities of the