diff options
| author | nsfisis <nsfisis@gmail.com> | 2026-08-04 06:33:32 +0900 |
|---|---|---|
| committer | nsfisis <nsfisis@gmail.com> | 2026-08-04 06:33:32 +0900 |
| commit | 11cdaae87c37e479fea6c39447041c312410b101 (patch) | |
| tree | 06e67edf1f437850f6f319c02f1304d130081fab /crates/shirabe/src/plugin/capability | |
| parent | 901cbbf285ed4e9c1f7bf75b413643c117a6105a (diff) | |
| download | php-shirabe-11cdaae87c37e479fea6c39447041c312410b101.tar.gz php-shirabe-11cdaae87c37e479fea6c39447041c312410b101.tar.zst php-shirabe-11cdaae87c37e479fea6c39447041c312410b101.zip | |
feat(plugin): instantiate plugin capabilities through the PHP RPC worker
getPluginCapability was a no-op returning None. Now it runs the real
flow: class_exists in the worker, new $capabilityClass($ctorArgs) with
the plugin's own phandle spliced in as $ctorArgs['plugin'], both
instanceof checks answered by is_a in the child, and a per-interface
Rust adapter over the resulting entity (CommandProvider and the plain
Capability marker; anything else is an explicit error).
getPluginCapabilities now propagates errors instead of swallowing them.
Capable::get_capabilities widens from IndexMap<String, String> to
IndexMap<String, PhpMixed>: upstream casts the return with (array) and
validates only the queried key, so the narrow type both rejected maps
Composer accepts and made the invalidImplementationClassNames data
provider unrepresentable. The old code also returned ' 0 ' (trimmed to
the falsy '0') as a valid class name where upstream throws; the
rewritten validation follows upstream's empty/is_string/trim sequence.
CommandProvider::get_commands returns BaseCommand adapters whose name is
read back over RPC after the PHP constructor ran configure(); executing
one still needs the PHP-side Symfony Application and stays an explicit
error. The is_array / instanceof BaseCommand checks that upstream's
Application::getPluginCommands performs on the raw getCommands value
live in the adapter, because Vec<Box<dyn BaseCommand>> asserts every
element up front.
Ports testCommandProviderCapability (plugin-v8 end to end against the
real worker) and testQueryingWithInvalidCapabilityClassNameThrows (all
eight provider cases); the two tests that pass a PHPUnit mock plugin
into PHP stay ignored — a Rust-native mock has no PHP-side entity to
cross the boundary as $ctorArgs['plugin'].
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Diffstat (limited to 'crates/shirabe/src/plugin/capability')
| -rw-r--r-- | crates/shirabe/src/plugin/capability/capability.rs | 14 | ||||
| -rw-r--r-- | crates/shirabe/src/plugin/capability/command_provider.rs | 8 |
2 files changed, 18 insertions, 4 deletions
diff --git a/crates/shirabe/src/plugin/capability/capability.rs b/crates/shirabe/src/plugin/capability/capability.rs index 1788d9a0..aa70ffa0 100644 --- a/crates/shirabe/src/plugin/capability/capability.rs +++ b/crates/shirabe/src/plugin/capability/capability.rs @@ -1,4 +1,14 @@ //! ref: composer/src/Composer/Plugin/Capability/Capability.php -// TODO(plugin): Marker interface for Plugin capabilities. Every new Capability which is added to the Plugin API must implement this interface. -pub trait Capability {} +use crate::plugin::capability::CommandProvider; + +/// Marker interface for Plugin capabilities. Every new Capability which is added to the +/// Plugin API must implement this interface. +/// +/// The accessor replaces PHP's `instanceof` downcast on a capability instance of unknown +/// concrete type (the way `PluginInterface::as_capable` does for plugins). +pub trait Capability { + fn as_command_provider(&self) -> Option<&dyn CommandProvider> { + None + } +} diff --git a/crates/shirabe/src/plugin/capability/command_provider.rs b/crates/shirabe/src/plugin/capability/command_provider.rs index 6d6f6cf1..2453860a 100644 --- a/crates/shirabe/src/plugin/capability/command_provider.rs +++ b/crates/shirabe/src/plugin/capability/command_provider.rs @@ -1,9 +1,13 @@ //! ref: composer/src/Composer/Plugin/Capability/CommandProvider.php -// TODO(plugin): Commands Provider Interface. Plugins implementing this capability provide a list of commands. use crate::command::BaseCommand; use crate::plugin::capability::Capability; +/// Commands Provider Interface. Plugins implementing this capability provide a list of +/// commands. +/// +/// The sole implementor is the PHP capability proxy (Composer itself never implements a +/// capability), so the method is fallible: the answer crosses the RPC boundary. pub trait CommandProvider: Capability { - fn get_commands(&self) -> Vec<Box<dyn BaseCommand>>; + fn get_commands(&self) -> anyhow::Result<Vec<Box<dyn BaseCommand>>>; } |
