diff --git a/includes/class-tmdo-hivepress-entity-groups.php b/includes/class-tmdo-hivepress-entity-groups.php index 798fba3..2894502 100644 --- a/includes/class-tmdo-hivepress-entity-groups.php +++ b/includes/class-tmdo-hivepress-entity-groups.php @@ -8,6 +8,14 @@ * post:hp_vendor_core → wp_wpdo_post_hp_vendor_core (hp_vendor) * user:hp_user → wp_wpdo_user_hp_user * + * Fields only the Hot zone used to cover (ADR-003), as their own groups: + * post:hp_draft_flags (hp_listing, hp_request) + * post:hp_booking_core (hp_booking) + * post:hp_membership_plan_core (hp_membership_plan) + * post:hp_membership_core (hp_membership) + * They register FIRST so the legacy last-registered owner of hp_expired_time + * stays hp_request_core. + * * The term/comment groups (hp_taxonomy, hp_review) live in * TMDO_Hivepress_Term_Comment_Fields. * @@ -60,6 +68,10 @@ final class TMDO_HivePress_Entity_Groups { return; } + self::register_hp_draft_flags_group(); + self::register_hp_booking_core_group(); + self::register_hp_membership_plan_core_group(); + self::register_hp_membership_core_group(); self::register_hp_listing_core_group(); self::register_hp_request_core_group(); self::register_hp_vendor_core_group(); @@ -68,6 +80,106 @@ final class TMDO_HivePress_Entity_Groups { // ── Group definitions ──────────────────────────────────────────────────── + /** + * Draft flag shared by listings and requests (user-dashboard filtering). + * + * @return void + */ + private static function register_hp_draft_flags_group(): void { + TMDO_Entity_Registry::register_group( + 'post', + 'hp_draft_flags', + array( + array( + 'key' => 'hp_drafted', + 'type' => 'integer', + 'searchable' => true, + 'label' => 'Drafted flag (0/1)', + ), + ), + array( 'post_types' => array( 'hp_listing', 'hp_request' ) ) + ); + } + + /** + * HivePress Bookings (post_type=hp_booking): slot-availability lookups. + * + * @return void + */ + private static function register_hp_booking_core_group(): void { + TMDO_Entity_Registry::register_group( + 'post', + 'hp_booking_core', + array( + array( + 'key' => 'hp_start_time', + 'type' => 'integer', + 'searchable' => true, + 'label' => 'Booking start unix ts', + ), + array( + 'key' => 'hp_end_time', + 'type' => 'integer', + 'searchable' => true, + 'label' => 'Booking end unix ts', + ), + array( + 'key' => 'hp_quantity', + 'type' => 'integer', + 'label' => 'Places booked', + ), + ), + array( 'post_types' => array( 'hp_booking' ) ) + ); + } + + /** + * HivePress Memberships plan (post_type=hp_membership_plan). + * + * @return void + */ + private static function register_hp_membership_plan_core_group(): void { + TMDO_Entity_Registry::register_group( + 'post', + 'hp_membership_plan_core', + array( + array( + 'key' => 'hp_expire_period', + 'type' => 'integer', + 'label' => 'Plan expiry period (days)', + ), + array( + 'key' => 'hp_primary', + 'type' => 'integer', + 'searchable' => true, + 'label' => 'Primary plan flag (0/1)', + ), + ), + array( 'post_types' => array( 'hp_membership_plan' ) ) + ); + } + + /** + * HivePress Memberships subscription (post_type=hp_membership). + * + * @return void + */ + private static function register_hp_membership_core_group(): void { + TMDO_Entity_Registry::register_group( + 'post', + 'hp_membership_core', + array( + array( + 'key' => 'hp_expired_time', + 'type' => 'integer', + 'searchable' => true, + 'label' => 'Expiry unix ts', + ), + ), + array( 'post_types' => array( 'hp_membership' ) ) + ); + } + /** * HivePress listing core meta keys (post_type=hp_listing). * Aligns with the existing wpdo_hot_hp_listing flat table; v2.9.5 will diff --git a/tests/unit/HivePressEntityGroupsTest.php b/tests/unit/HivePressEntityGroupsTest.php index 72fface..db610ce 100644 --- a/tests/unit/HivePressEntityGroupsTest.php +++ b/tests/unit/HivePressEntityGroupsTest.php @@ -75,7 +75,41 @@ class HivePressEntityGroupsTest extends TestCase { $this->assertNull( TMDO_Entity_Registry::get_field( 'post', 'hp_rating', 'post' ), 'HivePress keys stay native on other post types' ); } - public function test_reconciler_plans_the_eight_misrouted_hivepress_keys(): void { + /** + * Fields only the Hot zone used to cover (ADR-003), as their own groups. + */ + private const HOT_ONLY_GROUPS = array( + 'hp_draft_flags' => array( array( 'hp_listing', 'hp_request' ), array( 'hp_drafted' ) ), + 'hp_booking_core' => array( array( 'hp_booking' ), array( 'hp_start_time', 'hp_end_time', 'hp_quantity' ) ), + 'hp_membership_plan_core' => array( array( 'hp_membership_plan' ), array( 'hp_expire_period', 'hp_primary' ) ), + 'hp_membership_core' => array( array( 'hp_membership' ), array( 'hp_expired_time' ) ), + ); + + public function test_hot_only_fields_have_entity_groups_scoped_to_their_post_types(): void { + foreach ( self::HOT_ONLY_GROUPS as $group => list( $post_types, $keys ) ) { + $this->assertSame( $post_types, TMDO_Entity_Registry::get_group_post_types( 'post', $group ), $group ); + $this->assertSame( $keys, TMDO_Entity_Registry::get_group_keys( 'post', $group ), $group ); + } + } + + public function test_hot_only_fields_route_to_their_group_when_scoped_routing_is_on(): void { + $GLOBALS['_wp_options'][ TMDO_Entity_Registry::SCOPED_ROUTING_OPTION ] = '1'; + + foreach ( self::HOT_ONLY_GROUPS as $group => list( $post_types, $keys ) ) { + foreach ( $post_types as $post_type ) { + foreach ( $keys as $key ) { + $this->assertSame( $group, TMDO_Entity_Registry::get_field( 'post', $key, $post_type )['group'], "{$post_type}:{$key}" ); + } + } + } + $this->assertSame( 'hp_listing_core', TMDO_Entity_Registry::get_field( 'post', 'hp_expired_time', 'hp_listing' )['group'] ); + } + + public function test_hot_only_groups_add_no_collisions(): void { + $this->assertSame( array(), TMDO_Entity_Registry::get_collisions() ); + } + + public function test_reconciler_plans_the_misrouted_hivepress_keys(): void { $moves = array(); foreach ( TMDO_Post_Group_Reconciler::plan() as $m ) { $moves[] = "{$m['source']}>{$m['target']}:{$m['key']}"; @@ -87,6 +121,7 @@ class HivePressEntityGroupsTest extends TestCase { 'hp_request_core>hp_listing_core:hp_expired_time', 'hp_request_core>hp_listing_core:hp_status', 'hp_request_core>hp_listing_core:hp_view_count', + 'hp_request_core>hp_membership_core:hp_expired_time', 'hp_vendor_core>hp_listing_core:hp_hourly_rate', 'hp_vendor_core>hp_listing_core:hp_rating', 'hp_vendor_core>hp_listing_core:hp_rating_count',