aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authornsfisis <nsfisis@gmail.com>2026-08-23 12:36:15 +0900
committernsfisis <nsfisis@gmail.com>2026-08-23 12:36:15 +0900
commit890a50de2a740cc4c4edba12b37cc9aa4d0efdc5 (patch)
treee9925bfa7874680dde9d229bc869867ad7779b8e
parent2f07bd12c0c77e8985646a9f21a62a91311d82c0 (diff)
downloadphp-shirabe-890a50de2a740cc4c4edba12b37cc9aa4d0efdc5.tar.gz
php-shirabe-890a50de2a740cc4c4edba12b37cc9aa4d0efdc5.tar.zst
php-shirabe-890a50de2a740cc4c4edba12b37cc9aa4d0efdc5.zip
fix(config-command): print config values PHP would stringify
`config --list` and `config <key>` rendered a value with `as_string()`, which yields None for everything but a string, so every int-valued setting printed as an empty string: `cache-ttl`, `cache-files-ttl` and the resolved value of `cache-files-maxsize`. PHP builds that output by concatenating the value into the message, which casts it, so the ports now go through `php_to_string`. Two more differences in the same rendering path: The `[a, b]` branch flattened the array through `as_list()`, which sees only `PhpMixed::List`, so a keyed array reaching it rendered as `[]`. PHP takes that branch whenever the first key is numeric, so the values now come from `array_values_mixed`, which covers both representations. The raw-vs-resolved comparison deciding between `raw (value)` and `value` compared the two as strings. PHP compares with `!==`, which also compares the type: with a `cache-ttl` of `"15552000"` in composer.json, the raw string and the resolved int are not identical and Composer prints `15552000 (15552000)`. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
-rw-r--r--crates/shirabe-php-shim/src/array.rs8
-rw-r--r--crates/shirabe/src/command/config_command.rs60
2 files changed, 33 insertions, 35 deletions
diff --git a/crates/shirabe-php-shim/src/array.rs b/crates/shirabe-php-shim/src/array.rs
index 3870d59e..ec9adb26 100644
--- a/crates/shirabe-php-shim/src/array.rs
+++ b/crates/shirabe-php-shim/src/array.rs
@@ -6,6 +6,14 @@ pub fn array_values<V: Clone>(array: &IndexMap<String, V>) -> Vec<V> {
array.values().cloned().collect()
}
+pub fn array_values_mixed(value: &PhpMixed) -> Vec<PhpMixed> {
+ match value {
+ PhpMixed::List(items) => items.clone(),
+ PhpMixed::Array(map) => map.values().cloned().collect(),
+ _ => panic!("array_values(): Argument #1 ($array) must be of type array"),
+ }
+}
+
pub fn array_keys<V>(array: &IndexMap<String, V>) -> Vec<String> {
array.keys().cloned().collect()
}
diff --git a/crates/shirabe/src/command/config_command.rs b/crates/shirabe/src/command/config_command.rs
index 53e1fe7c..2f3c5fd7 100644
--- a/crates/shirabe/src/command/config_command.rs
+++ b/crates/shirabe/src/command/config_command.rs
@@ -20,10 +20,10 @@ use crate::util::Silencer;
use indexmap::IndexMap;
use shirabe_php_shim::{
InvalidArgumentException, PhpMixed, RuntimeException, array_is_list, array_merge,
- escapeshellcmd, exec, explode, file_exists, impl_php_class, implode, in_array_loose,
- in_array_strict, is_array, is_bool, is_dir, is_numeric, is_object, is_string, json_encode,
- php_regex, preg_is_match, preg_match, preg_replace, str_replace, strpos, strtolower, system,
- touch, var_export,
+ array_values_mixed, escapeshellcmd, exec, explode, file_exists, impl_php_class, implode,
+ in_array_loose, in_array_strict, is_array, is_bool, is_dir, is_numeric, is_object, is_string,
+ json_encode, php_regex, php_to_string, preg_is_match, preg_match, preg_replace, str_replace,
+ strpos, strtolower, system, touch, var_export,
};
use shirabe_semver::VersionParser;
use shirabe_symfony_console::command::Command;
@@ -199,7 +199,7 @@ impl ConfigCommand {
let raw_val = raw_contents_arr.get(key).cloned().unwrap_or(PhpMixed::Null);
- let value_inner = value.clone();
+ let mut value_inner = value.clone();
if is_array(&value_inner)
&& (!is_numeric(&key_first_key(&value_inner).unwrap_or_default().into())
@@ -224,27 +224,23 @@ impl ConfigCommand {
continue;
}
- let value_display: String = if is_array(&value_inner) {
- let arr_strs: Vec<String> = value_inner
- .as_list()
- .map(|l| {
- l.iter()
- .map(|val| {
- if is_array(val) {
- json_encode(val).unwrap_or_default()
- } else {
- val.as_string().unwrap_or("").to_string()
- }
- })
- .collect::<Vec<_>>()
+ if is_array(&value_inner) {
+ let arr_strs: Vec<String> = array_values_mixed(&value_inner)
+ .iter()
+ .map(|val| {
+ if is_array(val) {
+ json_encode(val).unwrap_or_default()
+ } else {
+ php_to_string(val)
+ }
})
- .unwrap_or_default();
- format!("[{}]", implode(", ", &arr_strs))
- } else if is_bool(&value_inner) {
- var_export(&value_inner, true)
- } else {
- value_inner.as_string().unwrap_or("").to_string()
- };
+ .collect();
+ value_inner = PhpMixed::String(format!("[{}]", implode(", ", &arr_strs)));
+ }
+
+ if is_bool(&value_inner) {
+ value_inner = PhpMixed::String(var_export(&value_inner, true));
+ }
let source = if show_source {
format!(
@@ -278,13 +274,7 @@ impl ConfigCommand {
let id = preg_replace(php_regex!("{-+}"), "-", &id);
format!("https://getcomposer.org/doc/06-config.md#{}", id)
};
- if is_string(&raw_val)
- && raw_val
- .as_string()
- .map(|s| s.to_string())
- .unwrap_or_default()
- != value_display
- {
+ if is_string(&raw_val) && raw_val.as_string() != value_inner.as_string() {
self.get_io().write3(
&format!(
"[<fg=yellow;href={}>{}{}</>] <info>{} ({})</info>{}",
@@ -292,7 +282,7 @@ impl ConfigCommand {
k.clone().unwrap_or_default(),
key,
raw_val.as_string().unwrap_or(""),
- value_display,
+ php_to_string(&value_inner),
source
),
true,
@@ -305,7 +295,7 @@ impl ConfigCommand {
link,
k.clone().unwrap_or_default(),
key,
- value_display,
+ php_to_string(&value_inner),
source
),
true,
@@ -843,7 +833,7 @@ impl Command for ConfigCommand {
},
)?
} else {
- value.as_string().unwrap_or("").to_string()
+ php_to_string(&value)
};
let mut source_of_config_value = String::new();