3f4fe52e1b
- Entity groups can declare post_types; get_field() resolves a post's key against its own type's groups first, then unscoped ones (legacy last-wins lookup kept for callers without a post type) - Hook Bus and the post query router pass the post type, so a listing's hp_rating / hp_status / hp_verified map to hp_listing_core instead of the vendor/request tables; core HP groups declare their post types (schema hashes unchanged) - Behind tmdo_post_scoped_routing: on for sites without post flat rows, off where rows may sit in the wrong table until PR-034 reconciles them (dry-run: dev20–22 off, dev23/24/30/31/40 on) - Verify: EntityRegistryScopeTest (8), PostScopedRoutingTest (4); core unit 630 / integration 443, HP 144/49, WC 10/22 OK - PR: PR-033
103 lines
4.8 KiB
PHP
103 lines
4.8 KiB
PHP
<?php
|
|
declare(strict_types=1);
|
|
|
|
use PHPUnit\Framework\TestCase;
|
|
|
|
/**
|
|
* Post entity groups scoped to post types.
|
|
*
|
|
* The post entity used to keep one meta_key index for every post type, so a
|
|
* key shared by several groups (hp_rating in hp_listing_core and
|
|
* hp_vendor_core) was routed to whichever group registered last — a
|
|
* listing's hp_rating landed in the vendor table. Groups can now declare the
|
|
* post types they belong to, and lookups that pass a post type use it.
|
|
*/
|
|
class EntityRegistryScopeTest extends TestCase {
|
|
|
|
protected function setUp(): void {
|
|
TMDO_Entity_Registry::init();
|
|
TMDO_Entity_Registry::register_adapter( 'post', $this->createMock( TMDO_Entity_Adapter_Interface::class ) );
|
|
$GLOBALS['_wp_options'] = array( TMDO_Entity_Registry::SCOPED_ROUTING_OPTION => '1' );
|
|
|
|
TMDO_Entity_Registry::register_group( 'post', 'site_core', array( array( 'key' => '_edit_lock', 'type' => 'text' ) ) );
|
|
TMDO_Entity_Registry::register_group(
|
|
'post',
|
|
'listing_core',
|
|
array(
|
|
array( 'key' => 'rating', 'type' => 'decimal' ),
|
|
array( 'key' => 'price', 'type' => 'decimal' ),
|
|
),
|
|
array( 'post_types' => array( 'hp_listing' ) )
|
|
);
|
|
TMDO_Entity_Registry::register_group(
|
|
'post',
|
|
'vendor_core',
|
|
array( array( 'key' => 'rating', 'type' => 'decimal' ) ),
|
|
array( 'post_types' => array( 'hp_vendor' ) )
|
|
);
|
|
}
|
|
|
|
public function test_shared_key_resolves_to_the_group_of_the_post_type(): void {
|
|
$this->assertSame( 'listing_core', TMDO_Entity_Registry::get_field( 'post', 'rating', 'hp_listing' )['group'] );
|
|
$this->assertSame( 'vendor_core', TMDO_Entity_Registry::get_field( 'post', 'rating', 'hp_vendor' )['group'] );
|
|
}
|
|
|
|
public function test_scoped_key_is_unmanaged_for_other_post_types(): void {
|
|
$this->assertNull( TMDO_Entity_Registry::get_field( 'post', 'rating', 'post' ) );
|
|
$this->assertNull( TMDO_Entity_Registry::get_field( 'post', 'price', 'hp_vendor' ) );
|
|
}
|
|
|
|
public function test_unscoped_group_applies_to_every_post_type(): void {
|
|
$this->assertSame( 'site_core', TMDO_Entity_Registry::get_field( 'post', '_edit_lock', 'hp_listing' )['group'] );
|
|
$this->assertSame( 'site_core', TMDO_Entity_Registry::get_field( 'post', '_edit_lock', 'page' )['group'] );
|
|
}
|
|
|
|
public function test_lookup_without_post_type_keeps_legacy_last_wins(): void {
|
|
$this->assertSame( 'vendor_core', TMDO_Entity_Registry::get_field( 'post', 'rating' )['group'] );
|
|
}
|
|
|
|
public function test_scoping_is_off_until_the_option_enables_it(): void {
|
|
$GLOBALS['_wp_options'][ TMDO_Entity_Registry::SCOPED_ROUTING_OPTION ] = '0';
|
|
|
|
$this->assertSame( 'vendor_core', TMDO_Entity_Registry::get_field( 'post', 'rating', 'hp_listing' )['group'] );
|
|
$this->assertSame( 'listing_core', TMDO_Entity_Registry::get_field( 'post', 'price', 'hp_vendor' )['group'] );
|
|
}
|
|
|
|
public function test_scope_is_not_part_of_the_field_definition(): void {
|
|
// Keeps schema hashes and PR-017 collision checks unchanged.
|
|
$fields = TMDO_Entity_Registry::get_group_fields( 'post', 'vendor_core' );
|
|
$this->assertArrayNotHasKey( 'post_types', $fields[0] );
|
|
}
|
|
|
|
public function test_scoped_routing_default_waits_for_reconcile_on_sites_with_post_flat_data(): void {
|
|
// Existing flat rows may sit in the wrong group table (legacy routing);
|
|
// switching lookups before they are reconciled would hide them.
|
|
$this->assertSame( '0', TMDO_Installer::post_scoped_routing_default( 'aeav_only', true ) );
|
|
$this->assertSame( '0', TMDO_Installer::post_scoped_routing_default( 'dual_write', true ) );
|
|
$this->assertSame( '1', TMDO_Installer::post_scoped_routing_default( 'aeav_only', false ) );
|
|
$this->assertSame( '1', TMDO_Installer::post_scoped_routing_default( 'disabled', true ) );
|
|
}
|
|
|
|
public function test_core_hivepress_groups_are_scoped_without_changing_their_hash(): void {
|
|
TMDO_Entity_Registry::init();
|
|
TMDO_Entity_Registry::register_adapter( 'post', $this->createMock( TMDO_Entity_Adapter_Interface::class ) );
|
|
TMDO_Post_Fields::register_entity_fields();
|
|
|
|
$persisted = array(
|
|
'hp_listing_core' => 'fb5ab760',
|
|
'hp_request_core' => '27d6f4f5',
|
|
'hp_vendor_core' => '5366e5c8',
|
|
);
|
|
foreach ( $persisted as $group => $hash ) {
|
|
$fields = TMDO_Entity_Registry::get_group_fields( 'post', $group );
|
|
$this->assertSame( $hash, substr( TMDO_Schema_Manager::calculate_schema_hash( $fields ), 0, 8 ), $group );
|
|
}
|
|
|
|
$this->assertSame( 'hp_listing_core', TMDO_Entity_Registry::get_field( 'post', 'hp_rating', 'hp_listing' )['group'] );
|
|
$this->assertSame( 'hp_listing_core', TMDO_Entity_Registry::get_field( 'post', 'hp_status', 'hp_listing' )['group'] );
|
|
$this->assertSame( 'hp_request_core', TMDO_Entity_Registry::get_field( 'post', 'hp_status', 'hp_request' )['group'] );
|
|
$this->assertSame( 'hp_vendor_core', TMDO_Entity_Registry::get_field( 'post', 'hp_user', 'hp_vendor' )['group'] );
|
|
$this->assertSame( 'hp_request_core', TMDO_Entity_Registry::get_field( 'post', 'hp_user', 'hp_request' )['group'] );
|
|
}
|
|
}
|