aboutsummaryrefslogtreecommitdiffhomepage
path: root/crates/shirabe-php-rpc/src
diff options
context:
space:
mode:
authornsfisis <nsfisis@gmail.com>2026-08-12 06:29:43 +0900
committernsfisis <nsfisis@gmail.com>2026-08-15 09:19:39 +0900
commitbb4684f7d1c51bc1be9c1bda1b00cb52c839cd25 (patch)
tree18fcdf1f9c9c64fc68e08bd5fab132808ca1cfcf /crates/shirabe-php-rpc/src
parent9e5bb3e4253dda96345f4d1a3421077a72295048 (diff)
downloadphp-shirabe-bb4684f7d1c51bc1be9c1bda1b00cb52c839cd25.tar.gz
php-shirabe-bb4684f7d1c51bc1be9c1bda1b00cb52c839cd25.tar.zst
php-shirabe-bb4684f7d1c51bc1be9c1bda1b00cb52c839cd25.zip
feat(php-shim): drop the modelled PHP version constants
The shim reported a fixed PHP 8.1.0 through PHP_VERSION, PHP_VERSION_ID, the major/minor/release triple and the PHP_WINDOWS_VERSION_* trio. Their uses split in two. Some guarded branches PHP only needs on runtimes this port cannot be: proc_get_status reports the exit status on every call, so Symfony's pre-8.3 exit-code cache has nothing to work around; hash_raw and hash_file always offer xxh3, so the sha1 fallback is unreachable; and http_get_last_response_headers is always available, so the pre-8.4 $http_response_header branch is gone. safeJunctions reads the host Windows version rather than PHP state, and joins the Windows work on hold. The rest ask about the PHP the user actually runs, and now reach the worker through a new php-rpc PhpVersion payload: the startup banner and the 7.2.5 warning, self-update's min-php filter, the ext-* recommendation in VersionSelector, the stream User-Agent, and whether PhpFileParser scans for enums. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Diffstat (limited to 'crates/shirabe-php-rpc/src')
-rw-r--r--crates/shirabe-php-rpc/src/lib.rs75
1 files changed, 56 insertions, 19 deletions
diff --git a/crates/shirabe-php-rpc/src/lib.rs b/crates/shirabe-php-rpc/src/lib.rs
index e5234ecd..f95a9d45 100644
--- a/crates/shirabe-php-rpc/src/lib.rs
+++ b/crates/shirabe-php-rpc/src/lib.rs
@@ -16,20 +16,38 @@ use std::os::unix::net::UnixStream;
use std::sync::atomic::{AtomicBool, AtomicU64, Ordering};
use std::sync::{LazyLock, Mutex, OnceLock};
-/// PHP `\PHP_VERSION`.
-pub fn get_php_version() -> String {
- match get_constant("PHP_VERSION") {
- PhpMixed::String(s) => s,
- other => panic!("PHP RPC: PHP_VERSION constant did not resolve to a string: {other:?}"),
- }
+/// The version constants of the PHP the worker runs.
+#[derive(Debug)]
+pub struct PhpVersion {
+ /// `\PHP_VERSION`.
+ pub version: String,
+ /// `\PHP_VERSION_ID`.
+ pub version_id: i64,
+ /// `\PHP_MAJOR_VERSION`.
+ pub major: i64,
+ /// `\PHP_MINOR_VERSION`.
+ pub minor: i64,
+ /// `\PHP_RELEASE_VERSION`.
+ pub release: i64,
+}
+
+static PHP_VERSION: OnceLock<PhpVersion> = OnceLock::new();
+
+/// The PHP version the worker runs. The worker is queried once per process; subsequent calls
+/// reuse the cached constants.
+pub fn get_php_version() -> &'static PhpVersion {
+ PHP_VERSION.get_or_init(|| PhpVersion {
+ version: string_constant("PHP_VERSION"),
+ version_id: int_constant("PHP_VERSION_ID"),
+ major: int_constant("PHP_MAJOR_VERSION"),
+ minor: int_constant("PHP_MINOR_VERSION"),
+ release: int_constant("PHP_RELEASE_VERSION"),
+ })
}
/// PHP `\PHP_BINARY`.
pub fn get_php_binary() -> String {
- match get_constant("PHP_BINARY") {
- PhpMixed::String(s) => s,
- other => panic!("PHP RPC: PHP_BINARY constant did not resolve to a string: {other:?}"),
- }
+ string_constant("PHP_BINARY")
}
/// PHP `constant($name)`.
@@ -37,6 +55,20 @@ fn get_constant(name: &str) -> PhpMixed {
call("constant", name)
}
+fn string_constant(name: &str) -> String {
+ match get_constant(name) {
+ PhpMixed::String(s) => s,
+ other => panic!("PHP RPC: {name} constant did not resolve to a string: {other:?}"),
+ }
+}
+
+fn int_constant(name: &str) -> i64 {
+ match get_constant(name) {
+ PhpMixed::Int(n) => n,
+ other => panic!("PHP RPC: {name} constant did not resolve to an int: {other:?}"),
+ }
+}
+
/// `curl_version()`, together with the `CURL_*` constants the `diagnose` command consults. Every
/// `Option` field is `None` when the corresponding array key or constant is absent.
#[derive(Debug)]
@@ -1237,7 +1269,7 @@ mod tests {
}
let diagnostics = get_diagnostics();
- assert_eq!(diagnostics.php_version, get_php_version());
+ assert_eq!(diagnostics.php_version, get_php_version().version);
assert!(diagnostics.php_version_id >= 70205);
let php_binary = get_php_binary();
assert_eq!(diagnostics.php_binary.as_deref(), Some(php_binary.as_str()));
@@ -1257,15 +1289,20 @@ mod tests {
return;
}
- let version = get_php_version();
- assert!(!version.is_empty(), "expected a PHP version");
- assert!(
- version
+ let php = get_php_version();
+ assert!(!php.version.is_empty(), "expected a PHP version");
+ assert_eq!(
+ php.version
.split('.')
.next()
- .and_then(|n| n.parse::<u32>().ok())
- .is_some(),
- "version should start with a number: {version}",
+ .and_then(|n| n.parse::<i64>().ok()),
+ Some(php.major),
+ "version should start with the major version: {}",
+ php.version,
+ );
+ assert_eq!(
+ php.version_id,
+ php.major * 10000 + php.minor * 100 + php.release
);
let binary = get_php_binary();
@@ -1292,7 +1329,7 @@ mod tests {
);
assert_eq!(
platform_info.get_extension_version("Core"),
- get_php_version()
+ get_php_version().version
);
assert!(platform_info.has_constant("PHP_VERSION", None));