true ); TMDO_Mode_Manager::reset_cache(); } private function modes( array $modes ): void { $GLOBALS['_wp_options']['wpdo_bridge_modes'] = $modes; TMDO_Mode_Manager::reset_cache(); } public function test_without_integrations_aeav_only_is_allowed(): void { $this->modes( array( 'post' => 'shadow_read' ) ); $this->assertTrue( TMDO_Mode_Manager::set( 'post', 'aeav_only' ) ); $this->assertNull( TMDO_Promotion_Guard::check_cleanup( 'post' ) ); $this->assertSame( array(), TMDO_Promotion_Guard::violations() ); } /** * @runInSeparateProcess * @preserveGlobalState disabled */ public function test_hivepress_refuses_aeav_only_for_every_entity(): void { eval( 'namespace HivePress; class Core {}' ); foreach ( array( 'post', 'user', 'term', 'comment' ) as $type ) { $this->modes( array( $type => 'shadow_read' ) ); $result = TMDO_Mode_Manager::set( $type, 'aeav_only' ); $this->assertInstanceOf( WP_Error::class, $result, $type ); $this->assertSame( 'promotion_guarded', $result->get_error_code(), $type ); $this->assertStringContainsString( 'HivePress', $result->get_error_message(), $type ); $this->assertSame( 'shadow_read', TMDO_Mode_Manager::get( $type ), "{$type} mode must not change" ); $this->assertSame( array( $type => 'shadow_read' ), $GLOBALS['_wp_options']['wpdo_bridge_modes'], "{$type} option must not change" ); } } /** * @runInSeparateProcess * @preserveGlobalState disabled */ public function test_woocommerce_guards_post_and_user_only(): void { eval( 'class WooCommerce {}' ); $this->modes( array( 'post' => 'shadow_read', 'user' => 'shadow_read', 'term' => 'shadow_read' ) ); $this->assertInstanceOf( WP_Error::class, TMDO_Mode_Manager::set( 'post', 'aeav_only' ) ); $this->assertInstanceOf( WP_Error::class, TMDO_Mode_Manager::set( 'user', 'aeav_only' ) ); $this->assertTrue( TMDO_Mode_Manager::set( 'term', 'aeav_only' ) ); } /** * @runInSeparateProcess * @preserveGlobalState disabled */ public function test_guard_allows_lower_modes_and_demotion(): void { eval( 'namespace HivePress; class Core {}' ); $this->modes( array( 'post' => 'disabled' ) ); $this->assertTrue( TMDO_Mode_Manager::set( 'post', 'dual_write' ) ); $this->assertTrue( TMDO_Mode_Manager::set( 'post', 'shadow_read' ) ); $this->modes( array( 'post' => 'aeav_only' ) ); $this->assertTrue( TMDO_Mode_Manager::set( 'post', 'dual_write' ), 'the way out of aeav_only stays open' ); } /** * @runInSeparateProcess * @preserveGlobalState disabled */ public function test_filter_can_allow_a_guarded_promotion(): void { eval( 'namespace HivePress; class Core {}' ); add_filter( 'tmdo_promotion_guard_allow', static function ( $allow, $entity_type, $action, $integrations ) { return 'user' === $entity_type && 'aeav_only' === $action && array( 'HivePress' ) === $integrations; }, 10, 4 ); $this->modes( array( 'user' => 'shadow_read', 'post' => 'shadow_read' ) ); $this->assertTrue( TMDO_Mode_Manager::set( 'user', 'aeav_only' ) ); $this->assertInstanceOf( WP_Error::class, TMDO_Mode_Manager::set( 'post', 'aeav_only' ) ); } /** * @runInSeparateProcess * @preserveGlobalState disabled */ public function test_cleanup_is_refused_even_in_aeav_only(): void { eval( 'namespace HivePress; class Core {}' ); $this->modes( array( 'post' => 'aeav_only', 'user' => 'aeav_only' ) ); $error = TMDO_Promotion_Guard::check_cleanup( 'post' ); $this->assertInstanceOf( WP_Error::class, $error ); try { TMDO_Post_Migration::cleanup(); $this->fail( 'post cleanup must be refused' ); } catch ( RuntimeException $e ) { $this->assertStringContainsString( 'HivePress', $e->getMessage() ); } $job = array( 'log' => array(), 'options' => array() ); try { ( new TMDO_Phase_Cleanup( 'user' ) )->execute( $job ); $this->fail( 'user cleanup phase must be refused' ); } catch ( RuntimeException $e ) { $this->assertStringContainsString( 'HivePress', $e->getMessage() ); } } /** * @runInSeparateProcess * @preserveGlobalState disabled */ public function test_sites_already_in_aeav_only_are_reported(): void { eval( 'class WooCommerce {}' ); $this->modes( array( 'post' => 'aeav_only', 'term' => 'aeav_only' ) ); $this->assertSame( array( 'post' => array( 'WooCommerce' ) ), TMDO_Promotion_Guard::violations() ); ob_start(); TMDO_Promotion_Guard_Notice::render(); $html = (string) ob_get_clean(); $this->assertStringContainsString( 'post', $html ); $this->assertStringContainsString( 'bridge-restore-native post', $html ); } public function test_notice_is_silent_without_violations(): void { $this->modes( array( 'post' => 'aeav_only' ) ); ob_start(); TMDO_Promotion_Guard_Notice::render(); $this->assertSame( '', ob_get_clean() ); } }