From 901878ee3f2bee6605b02d321cc4c92bc32fd5b0 Mon Sep 17 00:00:00 2001 From: nsfisis Date: Sat, 27 Jun 2026 08:44:57 +0900 Subject: refactor(composer): hold managers behind *Interface traits Composer/PartialComposer exposed its RepositoryManager, InstallationManager, EventDispatcher, Locker, DownloadManager, AutoloadGenerator and ArchiveManager as concrete types, but Composer's public setters (setDownloadManager() etc.) let plugins swap in subclasses. Introduce a *Interface trait per manager and store each as Rc> so a replacement is honored. Only Composer's slots and the sinks fed from its accessors become trait objects; managers injected concretely at construction keep their concrete references, matching PHP semantics. Fluent setters on the affected classes now return () and Locker::update_hash is de-generified to a boxed FnOnce so the traits stay object-safe. Co-Authored-By: Claude Opus 4.8 (1M context) --- .../src/event_dispatcher/event_dispatcher.rs | 71 ++++++++++++++++++++-- 1 file changed, 67 insertions(+), 4 deletions(-) (limited to 'crates/shirabe/src/event_dispatcher/event_dispatcher.rs') diff --git a/crates/shirabe/src/event_dispatcher/event_dispatcher.rs b/crates/shirabe/src/event_dispatcher/event_dispatcher.rs index f74b4a2..091160e 100644 --- a/crates/shirabe/src/event_dispatcher/event_dispatcher.rs +++ b/crates/shirabe/src/event_dispatcher/event_dispatcher.rs @@ -125,10 +125,8 @@ impl EventDispatcher { } /// Set whether script handlers are active or not - pub fn set_run_scripts(&mut self, run_scripts: bool) -> &mut Self { + pub fn set_run_scripts(&mut self, run_scripts: bool) { self.run_scripts = run_scripts; - - self } /// Dispatch an event @@ -1193,7 +1191,7 @@ impl EventDispatcher { let installation_manager = composer.get_installation_manager(); let package_map = generator.build_package_map( - &mut installation_manager.borrow_mut(), + &mut *installation_manager.borrow_mut(), package.clone(), packages, )?; @@ -1245,3 +1243,68 @@ impl EventDispatcher { } } } + +// Composer's PartialComposer::setEventDispatcher() accepts any EventDispatcher subclass, so plugins +// may swap in a replacement. The interface captures the methods reached through Composer's accessor +// and through the `Rc>` references fed from it. +pub trait EventDispatcherInterface: std::fmt::Debug { + fn dispatch( + &mut self, + event_name: Option<&str>, + event: Option<&mut dyn EventInterface>, + ) -> anyhow::Result; + fn dispatch_script( + &mut self, + event_name: &str, + dev_mode: bool, + additional_args: Vec, + flags: IndexMap, + ) -> anyhow::Result; + fn dispatch_installer_event( + &mut self, + event_name: &str, + dev_mode: bool, + execute_operations: bool, + transaction: Transaction, + ) -> anyhow::Result; + fn add_listener(&mut self, event_name: &str, listener: Callable, priority: i64); + fn has_event_listeners(&mut self, event: &dyn EventInterface) -> bool; +} + +impl EventDispatcherInterface for EventDispatcher { + fn dispatch( + &mut self, + event_name: Option<&str>, + event: Option<&mut dyn EventInterface>, + ) -> anyhow::Result { + self.dispatch(event_name, event) + } + + fn dispatch_script( + &mut self, + event_name: &str, + dev_mode: bool, + additional_args: Vec, + flags: IndexMap, + ) -> anyhow::Result { + self.dispatch_script(event_name, dev_mode, additional_args, flags) + } + + fn dispatch_installer_event( + &mut self, + event_name: &str, + dev_mode: bool, + execute_operations: bool, + transaction: Transaction, + ) -> anyhow::Result { + self.dispatch_installer_event(event_name, dev_mode, execute_operations, transaction) + } + + fn add_listener(&mut self, event_name: &str, listener: Callable, priority: i64) { + self.add_listener(event_name, listener, priority); + } + + fn has_event_listeners(&mut self, event: &dyn EventInterface) -> bool { + self.has_event_listeners(event) + } +} -- cgit v1.3.1