e9d8696c93
- register_group() keeps the first definition but records a field diff (added/removed/changed) when the same entity/group is re-registered differently; identical re-registration stays silent - Surface collisions via Site Health (wpdo_entity_group_collisions), the admin Doctor tab, and wp wpdo doctor; warning log throttled to once a day - Verify: EntityRegistryCollisionTest (7); core unit 613 / integration 432, HP 141/49, WC 10/22 OK - PR: PR-017
98 lines
4.2 KiB
PHP
98 lines
4.2 KiB
PHP
<?php
|
|
declare(strict_types=1);
|
|
|
|
use PHPUnit\Framework\TestCase;
|
|
|
|
/**
|
|
* Entity group name collisions.
|
|
*
|
|
* Two providers registering the same entity/group name used to have the
|
|
* second definition dropped with no trace. Identical re-registration (core
|
|
* re-fires the registration hooks on init:1) stays silent; a different
|
|
* definition is recorded with a field diff and surfaced in Site Health.
|
|
*/
|
|
class EntityRegistryCollisionTest extends TestCase {
|
|
|
|
protected function setUp(): void {
|
|
if ( ! class_exists( 'TMDO_Site_Health' ) ) {
|
|
require_once TMDO_PATH . 'includes/diagnostic/class-tmdo-site-health.php';
|
|
}
|
|
TMDO_Entity_Registry::init();
|
|
TMDO_Entity_Registry::register_adapter( 'post', $this->createMock( TMDO_Entity_Adapter_Interface::class ) );
|
|
$GLOBALS['_wp_options'] = array();
|
|
}
|
|
|
|
private function first_definition(): array {
|
|
return array(
|
|
array( 'key' => 'hp_price', 'type' => 'decimal', 'searchable' => true ),
|
|
array( 'key' => 'hp_featured', 'type' => 'boolean' ),
|
|
);
|
|
}
|
|
|
|
public function test_identical_reregistration_is_silent(): void {
|
|
$this->assertTrue( TMDO_Entity_Registry::register_group( 'post', 'hp_listing_core', $this->first_definition() ) );
|
|
$this->assertFalse( TMDO_Entity_Registry::register_group( 'post', 'hp_listing_core', $this->first_definition() ) );
|
|
|
|
$this->assertSame( array(), TMDO_Entity_Registry::get_collisions() );
|
|
}
|
|
|
|
public function test_different_definition_is_recorded_with_field_diff(): void {
|
|
TMDO_Entity_Registry::register_group( 'post', 'hp_listing_core', $this->first_definition() );
|
|
|
|
$second = array(
|
|
array( 'key' => 'hp_price', 'type' => 'integer', 'searchable' => true ),
|
|
array( 'key' => 'hp_vendor', 'type' => 'integer' ),
|
|
);
|
|
$this->assertFalse( TMDO_Entity_Registry::register_group( 'post', 'hp_listing_core', $second ) );
|
|
|
|
$collisions = TMDO_Entity_Registry::get_collisions();
|
|
$this->assertCount( 1, $collisions );
|
|
$this->assertSame( 'post', $collisions[0]['entity_type'] );
|
|
$this->assertSame( 'hp_listing_core', $collisions[0]['group'] );
|
|
$this->assertSame( array( 'hp_vendor' ), $collisions[0]['added'] );
|
|
$this->assertSame( array( 'hp_featured' ), $collisions[0]['removed'] );
|
|
$this->assertSame( array( 'hp_price' ), $collisions[0]['changed'] );
|
|
}
|
|
|
|
public function test_first_definition_wins(): void {
|
|
TMDO_Entity_Registry::register_group( 'post', 'hp_listing_core', $this->first_definition() );
|
|
TMDO_Entity_Registry::register_group( 'post', 'hp_listing_core', array( array( 'key' => 'hp_vendor', 'type' => 'integer' ) ) );
|
|
|
|
$this->assertSame( array( 'hp_price', 'hp_featured' ), TMDO_Entity_Registry::get_group_keys( 'post', 'hp_listing_core' ) );
|
|
$this->assertNull( TMDO_Entity_Registry::get_field( 'post', 'hp_vendor' ) );
|
|
}
|
|
|
|
public function test_same_collision_is_recorded_once_per_request(): void {
|
|
TMDO_Entity_Registry::register_group( 'post', 'g', $this->first_definition() );
|
|
$other = array( array( 'key' => 'x', 'type' => 'text' ) );
|
|
TMDO_Entity_Registry::register_group( 'post', 'g', $other );
|
|
TMDO_Entity_Registry::register_group( 'post', 'g', $other );
|
|
|
|
$this->assertCount( 1, TMDO_Entity_Registry::get_collisions() );
|
|
}
|
|
|
|
public function test_init_clears_collisions(): void {
|
|
TMDO_Entity_Registry::register_group( 'post', 'g', $this->first_definition() );
|
|
TMDO_Entity_Registry::register_group( 'post', 'g', array( array( 'key' => 'x', 'type' => 'text' ) ) );
|
|
TMDO_Entity_Registry::init();
|
|
|
|
$this->assertSame( array(), TMDO_Entity_Registry::get_collisions() );
|
|
}
|
|
|
|
public function test_site_health_reports_collisions(): void {
|
|
$this->assertSame( 'good', TMDO_Site_Health::check_entity_group_collisions()['status'] );
|
|
|
|
TMDO_Entity_Registry::register_group( 'post', 'hp_listing_core', $this->first_definition() );
|
|
TMDO_Entity_Registry::register_group( 'post', 'hp_listing_core', array( array( 'key' => 'x', 'type' => 'text' ) ) );
|
|
|
|
$result = TMDO_Site_Health::check_entity_group_collisions();
|
|
$this->assertSame( 'recommended', $result['status'] );
|
|
$this->assertStringContainsString( 'post/hp_listing_core', $result['description'] );
|
|
}
|
|
|
|
public function test_site_health_registers_the_collision_test(): void {
|
|
$tests = TMDO_Site_Health::register_tests( array() );
|
|
$this->assertArrayHasKey( 'wpdo_entity_group_collisions', $tests['direct'] );
|
|
}
|
|
}
|