diff --git a/includes/back-compat/trait-wpdo-anti-eav-aware-alias.php b/includes/back-compat/trait-wpdo-anti-eav-aware-alias.php index 2d54ec6..c42c5ae 100644 --- a/includes/back-compat/trait-wpdo-anti-eav-aware-alias.php +++ b/includes/back-compat/trait-wpdo-anti-eav-aware-alias.php @@ -30,11 +30,6 @@ if ( ! trait_exists( 'WPDO_Anti_EAV_Aware', false ) && trait_exists( 'TMDO_Anti_ } } -if ( ! interface_exists( 'WPDO_Entity_Adapter_Interface', false ) && interface_exists( 'TMDO_Entity_Adapter_Interface', false ) ) { - /** - * Backward-compat alias interface. PHP allows interface inheritance, so - * extending the new interface gives implementing classes the same - * obligations under the old name. - */ - interface WPDO_Entity_Adapter_Interface extends TMDO_Entity_Adapter_Interface {} -} +// NOTE: WPDO_Entity_Adapter_Interface is declared in +// back-compat/interface-wpdo-entity-adapter-alias.php — it used to be duplicated +// here, which made composer's classmap ambiguous. diff --git a/includes/class-tmdo-back-compat.php b/includes/class-tmdo-back-compat.php index 8f5be88..e32a644 100644 --- a/includes/class-tmdo-back-compat.php +++ b/includes/class-tmdo-back-compat.php @@ -128,7 +128,7 @@ $tmdo_class_aliases = array( 'TMDO_Zone_Archive' => 'WPDO_Zone_Archive', 'TMDO_Interceptor_Base' => 'WPDO_Interceptor_Base', 'TMDO_Query_Interceptor_Base' => 'WPDO_Query_Interceptor_Base', - 'TMDO_Notifier' => 'WPDO_Notifier', + 'TMDO_Abstract_Notifier' => 'WPDO_Abstract_Notifier', ); foreach ( $tmdo_class_aliases as $tmdo_class => $wpdo_alias ) { @@ -172,7 +172,21 @@ if ( ! defined( 'WPDO_IS_MYSQL' ) ) { } // ── Hook dual-fire bridge ───────────────────────────────────────────────── -// Phase 1 過渡期:tmdo_* 與 wpdo_* hook 雙向轉發,讓既有 listener 仍能接收事件。 +// 核心一律 do_action( 'wpdo_*' ),所以單向的 tmdo_* → wpdo_* 轉發等於讓 tmdo_* +// 契約永遠收不到事件。這裡做雙向轉發,並用共用旗標防止 A→B→A 無限迴圈與 +// listener 被觸發兩次。 +$tmdo_make_relay = static function ( string $source, string $target ): callable { + return static function ( ...$args ) use ( $source, $target ) { + $base = preg_replace( '/^(wpdo|tmdo)_/', '', $source ); + if ( ! empty( $GLOBALS['tmdo_hook_relay_active'][ $base ] ) ) { + return; + } + $GLOBALS['tmdo_hook_relay_active'][ $base ] = true; + do_action_ref_array( $target, $args ); + $GLOBALS['tmdo_hook_relay_active'][ $base ] = false; + }; +}; + foreach ( array( 'wpdo_register_fields', 'wpdo_register_entity_fields', @@ -185,12 +199,29 @@ foreach ( array( 'wpdo_auto_promoted', ) as $tmdo_back_compat_hook ) { $tmdo_new_hook = preg_replace( '/^wpdo_/', 'tmdo_', $tmdo_back_compat_hook ); - add_action( - $tmdo_new_hook, - static function ( ...$args ) use ( $tmdo_back_compat_hook ) { - do_action_ref_array( $tmdo_back_compat_hook, $args ); - }, - 1 - ); + add_action( $tmdo_new_hook, $tmdo_make_relay( $tmdo_new_hook, $tmdo_back_compat_hook ), 1 ); + add_action( $tmdo_back_compat_hook, $tmdo_make_relay( $tmdo_back_compat_hook, $tmdo_new_hook ), 1 ); +} +unset( $tmdo_back_compat_hook, $tmdo_new_hook, $tmdo_make_relay ); + +// ── 函式別名(sister plugin 可能 remove_action 'plugins_loaded', 'wpdo_run')── +if ( ! function_exists( 'wpdo_run' ) ) { + /** + * Back-compat shim for the old boot function name. + * + * @return void + */ + function wpdo_run(): void { + tmdo_run(); + } +} +if ( ! function_exists( 'wpdo_load_textdomain' ) ) { + /** + * Back-compat shim for the old textdomain loader name. + * + * @return void + */ + function wpdo_load_textdomain(): void { + tmdo_load_textdomain(); + } } -unset( $tmdo_back_compat_hook, $tmdo_new_hook ); diff --git a/tests/bootstrap.php b/tests/bootstrap.php index 5b591bf..1c4a5a2 100644 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -174,6 +174,11 @@ if ( ! function_exists( 'do_action' ) ) { } } } +if ( ! function_exists( 'do_action_ref_array' ) ) { + function do_action_ref_array( string $hook, array $args ): void { + do_action( $hook, ...$args ); + } +} if ( ! function_exists( 'wp_next_scheduled' ) ) { function wp_next_scheduled( string $hook ): int|false { return false; } } diff --git a/tests/integration/bootstrap.php b/tests/integration/bootstrap.php index 78022a7..6ed4d1b 100644 --- a/tests/integration/bootstrap.php +++ b/tests/integration/bootstrap.php @@ -272,6 +272,11 @@ if ( ! function_exists( 'do_action' ) ) { } } } +if ( ! function_exists( 'do_action_ref_array' ) ) { + function do_action_ref_array( string $hook, array $args ): void { + do_action( $hook, ...$args ); + } +} if ( ! function_exists( 'is_admin' ) ) { function is_admin(): bool { return ! empty( $GLOBALS['_wp_is_admin'] ); } } if ( ! function_exists( 'is_singular' ) ) { function is_singular( $t = '' ): bool { return false; } }