From 3f3ad76eafcc5513000ac7526c74c2009bb390d8 Mon Sep 17 00:00:00 2001 From: nsfisis Date: Tue, 4 Aug 2026 04:31:51 +0900 Subject: feat(plugin): remove subscribed listeners when a plugin is removed Wire removePlugin to EventDispatcher::removeListener now that subscriber listeners carry the plugin's P-table handle: PHP's $candidate[0] === $listener identity check maps to phandle equality on Callable::PhpMethod. Co-Authored-By: Claude Fable 5 --- .../shirabe/tests/command/archive_command_test.rs | 1 + crates/shirabe/tests/installer_test.rs | 1 + crates/shirabe/tests/plugin/subscriber_test.rs | 32 ++++++++++++++++++++++ 3 files changed, 34 insertions(+) (limited to 'crates/shirabe/tests') diff --git a/crates/shirabe/tests/command/archive_command_test.rs b/crates/shirabe/tests/command/archive_command_test.rs index 655020e0..6d20fda0 100644 --- a/crates/shirabe/tests/command/archive_command_test.rs +++ b/crates/shirabe/tests/command/archive_command_test.rs @@ -89,6 +89,7 @@ mockall::mock! { &mut self, subscriber: &'a dyn shirabe::event_dispatcher::EventSubscriberInterface, ) -> anyhow::Result<()>; + fn remove_listener<'a>(&mut self, listener: &'a shirabe_php_rpc::PhpObjHandle); fn has_event_listeners(&mut self, event: &dyn EventInterface) -> bool; } } diff --git a/crates/shirabe/tests/installer_test.rs b/crates/shirabe/tests/installer_test.rs index 1a8b7ccc..f5e84558 100644 --- a/crates/shirabe/tests/installer_test.rs +++ b/crates/shirabe/tests/installer_test.rs @@ -194,6 +194,7 @@ impl EventDispatcherInterface for StubEventDispatcher { ) -> anyhow::Result<()> { Ok(()) } + fn remove_listener(&mut self, _listener: &shirabe_php_rpc::PhpObjHandle) {} fn has_event_listeners(&mut self, _event: &dyn EventInterface) -> bool { false } diff --git a/crates/shirabe/tests/plugin/subscriber_test.rs b/crates/shirabe/tests/plugin/subscriber_test.rs index 8de3d8c2..1d6a7ece 100644 --- a/crates/shirabe/tests/plugin/subscriber_test.rs +++ b/crates/shirabe/tests/plugin/subscriber_test.rs @@ -93,6 +93,38 @@ fn test_subscriber_listener_returning_false_sets_return_code() { ); } +#[test] +fn test_remove_plugin_removes_its_subscribed_listeners() { + if !php_runtime_available() { + return; + } + let _worker = lock_php_worker(); + let set_up = set_up(); + install_subscriber_plugin(&set_up); + + assert_eq!(0, dispatch(&set_up, "post-install-cmd")); + + let plugin = set_up + .pm + .borrow() + .get_plugins() + .iter() + .find(|p| p.borrow().get_class_name() == "Subscriber\\Plugin") + .expect("the subscriber plugin is registered") + .clone(); + set_up.pm.borrow_mut().remove_plugin(&plugin).unwrap(); + + // removePlugin removed the plugin's `[$subscriber, 'onPostInstall']` listener, so the + // second dispatch produces no further output. + let return_code = dispatch(&set_up, "post-install-cmd"); + + assert_eq!(0, return_code); + assert_eq!( + "activate subscriber-v1\nsubscriber saw post-install-cmd\n", + set_up.io.borrow().get_output() + ); +} + #[test] fn test_unrelated_event_does_not_reach_the_subscriber() { if !php_runtime_available() { -- cgit v1.3.1