diff options
| -rw-r--r-- | crates/shirabe-php-rpc/php/worker.php | 13 | ||||
| -rw-r--r-- | crates/shirabe-php-rpc/src/lib.rs | 40 | ||||
| -rw-r--r-- | crates/shirabe/src/platform/runtime.rs | 31 |
3 files changed, 73 insertions, 11 deletions
diff --git a/crates/shirabe-php-rpc/php/worker.php b/crates/shirabe-php-rpc/php/worker.php index 58ba973..cb2bf48 100644 --- a/crates/shirabe-php-rpc/php/worker.php +++ b/crates/shirabe-php-rpc/php/worker.php @@ -9,6 +9,19 @@ if ($client === false) { $dispatch = [ 'defined' => static fn($name) => defined($name), 'constant' => static fn($name) => defined($name) ? constant($name) : null, + 'inet_pton' => static fn($arg) => @inet_pton($arg), + 'curl_version' => static fn($arg) => function_exists('curl_version') ? (curl_version()['version'] ?? null) : null, + 'phpversion' => static fn($name) => phpversion($name), + 'get_loaded_extensions' => static fn($arg) => implode(',', get_loaded_extensions()), + 'extension_info' => static function ($name) { + if (!extension_loaded($name)) { + return ''; + } + $re = new ReflectionExtension($name); + ob_start(); + $re->info(); + return (string) ob_get_clean(); + }, ]; $read_exact = static function ($conn, int $len): ?string { $buf = ''; diff --git a/crates/shirabe-php-rpc/src/lib.rs b/crates/shirabe-php-rpc/src/lib.rs index 04583fa..3b0ee66 100644 --- a/crates/shirabe-php-rpc/src/lib.rs +++ b/crates/shirabe-php-rpc/src/lib.rs @@ -33,6 +33,46 @@ pub fn get_constant(name: &str) -> PhpMixed { call("constant", name).unwrap_or(PhpMixed::Null) } +/// PHP `inet_pton($address)`. +pub fn inet_pton(address: &str) -> PhpMixed { + call("inet_pton", address).unwrap_or(PhpMixed::Bool(false)) +} + +/// PHP `curl_version()['version']`. +pub fn curl_version() -> Option<String> { + match call("curl_version", "") { + Some(PhpMixed::String(s)) => Some(s), + _ => None, + } +} + +/// PHP `(new \ReflectionExtension($name))->info()` output. +pub fn get_extension_info(name: &str) -> String { + match call("extension_info", name) { + Some(PhpMixed::String(s)) => s, + _ => String::new(), + } +} + +/// PHP `phpversion($extension)`. +pub fn phpversion(extension: &str) -> Option<String> { + match call("phpversion", extension) { + Some(PhpMixed::String(s)) => Some(s), + _ => None, + } +} + +/// PHP `get_loaded_extensions()`. +/// +/// Extension names are joined with `,` on the PHP side and split back here; real +/// extension names never contain a comma. +pub fn get_loaded_extensions() -> Vec<String> { + match call("get_loaded_extensions", "") { + Some(PhpMixed::String(s)) if !s.is_empty() => s.split(',').map(|s| s.to_string()).collect(), + _ => Vec::new(), + } +} + const GLUE_SCRIPT: &str = include_str!("../php/worker.php"); struct Worker { diff --git a/crates/shirabe/src/platform/runtime.rs b/crates/shirabe/src/platform/runtime.rs index e4ff64a..4029790 100644 --- a/crates/shirabe/src/platform/runtime.rs +++ b/crates/shirabe/src/platform/runtime.rs @@ -3,8 +3,8 @@ use indexmap::IndexMap; use shirabe_external_packages::composer::pcre::{CaptureKey, Preg}; use shirabe_php_shim::{ - PhpMixed, class_exists, function_exists, get_loaded_extensions, html_entity_decode, implode, - instantiate_class, ltrim, phpversion, strip_tags, trim, + PhpMixed, class_exists, function_exists, html_entity_decode, implode, instantiate_class, ltrim, + strip_tags, trim, }; /// Seam over the PHP runtime so PlatformRepository can be tested against mocked @@ -44,9 +44,21 @@ impl RuntimeInterface for Runtime { fn invoke(&self, callable: PhpMixed, arguments: Vec<PhpMixed>) -> PhpMixed { // PHP: return $callable(...$arguments); - // Dispatching an arbitrary PHP callable needs a PHP runtime; no shim exists. - let _ = (callable, arguments); - todo!() + // Only the specific dynamic callables PlatformRepository actually reaches are + // wired through php-rpc; arbitrary PHP callables are still unsupported. + match (&callable, arguments.as_slice()) { + (PhpMixed::String(name), [PhpMixed::String(arg)]) if name == "inet_pton" => { + shirabe_php_rpc::inet_pton(arg) + } + (PhpMixed::String(name), []) if name == "curl_version" => { + let mut version = IndexMap::new(); + if let Some(v) = shirabe_php_rpc::curl_version() { + version.insert("version".to_string(), PhpMixed::String(v)); + } + PhpMixed::Array(version) + } + _ => todo!(), + } } fn has_class(&self, class: &str) -> bool { @@ -62,18 +74,15 @@ impl RuntimeInterface for Runtime { } fn get_extensions(&self) -> Vec<String> { - get_loaded_extensions() + shirabe_php_rpc::get_loaded_extensions() } fn get_extension_version(&self, extension: &str) -> String { - let version = phpversion(extension); - version.unwrap_or_else(|| "0".to_string()) + shirabe_php_rpc::phpversion(extension).unwrap_or_else(|| "0".to_string()) } fn get_extension_info(&self, extension: &str) -> anyhow::Result<String> { - // Depends on \ReflectionExtension::info() and output buffering; no shim equivalent exists. - let _ = extension; - todo!() + Ok(shirabe_php_rpc::get_extension_info(extension)) } } |
