TypePHP 编译器
https://swoole.com/aot/
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
105 lines
2.8 KiB
105 lines
2.8 KiB
--TEST--
|
|
ThinkPHP Config pattern: lazy hook fallback and dotted key lookup
|
|
--XFAIL--
|
|
Known AOT bug: nullable mixed default/value flow can be narrowed incorrectly after dotted array lookup.
|
|
--FILE--
|
|
<?php
|
|
|
|
class ThinkConfigLike
|
|
{
|
|
private array $config = [];
|
|
private array $hook = [];
|
|
|
|
public function hook(Closure $callback, ?string $key = null): void
|
|
{
|
|
$this->hook[$key ?? 'global'] = $callback;
|
|
}
|
|
|
|
public function set(array $config, ?string $name = null): array
|
|
{
|
|
if (empty($name)) {
|
|
$this->config = array_merge($this->config, array_change_key_case($config));
|
|
return $this->config;
|
|
}
|
|
|
|
$result = isset($this->config[$name]) ? array_merge($this->config[$name], $config) : $config;
|
|
$this->config[$name] = $result;
|
|
return $result;
|
|
}
|
|
|
|
public function get(?string $name = null, mixed $default = null): mixed
|
|
{
|
|
if (empty($name)) {
|
|
return $this->config;
|
|
}
|
|
|
|
if (!str_contains($name, '.')) {
|
|
$name = strtolower($name);
|
|
$result = $this->config[$name] ?? [];
|
|
return $this->hook ? $this->lazy($name, $result, []) : $result;
|
|
}
|
|
|
|
$item = explode('.', $name);
|
|
$item[0] = strtolower($item[0]);
|
|
$config = $this->config;
|
|
|
|
foreach ($item as $val) {
|
|
if (isset($config[$val])) {
|
|
$config = $config[$val];
|
|
} else {
|
|
return $this->hook ? $this->lazy($name, null, $default) : $default;
|
|
}
|
|
}
|
|
|
|
return $this->hook ? $this->lazy($name, $config, $default) : $config;
|
|
}
|
|
|
|
private function lazy(string $name, mixed $value = null, mixed $default = null): mixed
|
|
{
|
|
$key = strpos($name, '.') ? strstr($name, '.', true) : $name;
|
|
if (isset($this->hook[$key])) {
|
|
$call = $this->hook[$key];
|
|
} elseif (isset($this->hook['global'])) {
|
|
$call = $this->hook['global'];
|
|
}
|
|
|
|
if (isset($call)) {
|
|
$result = call_user_func_array($call, [$name, $value]);
|
|
if (is_null($result)) {
|
|
return $default;
|
|
}
|
|
}
|
|
|
|
return $result ?? ($value ?: $default);
|
|
}
|
|
}
|
|
|
|
function main(): void
|
|
{
|
|
$config = new ThinkConfigLike();
|
|
$config->set(['Debug' => true, 'cache' => ['ttl' => 60]]);
|
|
$config->hook(fn ($name, $value) => $name === 'cache.missing' ? null : ['hooked', $name, $value]);
|
|
|
|
var_dump($config->get('debug'));
|
|
var_dump($config->get('cache.ttl'));
|
|
var_dump($config->get('cache.missing', 'fallback'));
|
|
}
|
|
?>
|
|
--EXPECT--
|
|
array(3) {
|
|
[0]=>
|
|
string(6) "hooked"
|
|
[1]=>
|
|
string(5) "debug"
|
|
[2]=>
|
|
bool(true)
|
|
}
|
|
array(3) {
|
|
[0]=>
|
|
string(6) "hooked"
|
|
[1]=>
|
|
string(9) "cache.ttl"
|
|
[2]=>
|
|
int(60)
|
|
}
|
|
string(8) "fallback"
|
|
|