lthn.io/app/Core/Config/ConfigResult.php
Claude 41a90cbff8
feat: lthn.io API serving live chain data
Fixed: basePath self→static binding, namespace detection, event wiring,
SQLite cache, file cache driver. All Mod Boot classes converted to
$listens pattern for lifecycle event discovery.

Working endpoints:
- /v1/explorer/info — live chain height, difficulty, aliases
- /v1/explorer/stats — formatted chain statistics
- /v1/names/directory — alias directory grouped by type
- /v1/names/available/{name} — name availability check
- /v1/names/lookup/{name} — name details

Co-Authored-By: Charon <charon@lethean.io>
2026-04-03 17:17:42 +01:00

211 lines
4.9 KiB
PHP

<?php
/*
* Core PHP Framework
*
* Licensed under the European Union Public Licence (EUPL) v1.2.
* See LICENSE file for details.
*/
declare(strict_types=1);
namespace Core\Config;
use Core\Config\Enums\ConfigType;
use Core\Config\Enums\ScopeType;
/**
* Immutable result of config resolution.
*
* Contains the resolved value plus metadata about where it came from.
* This is what gets cached for fast last-mile access.
*/
final readonly class ConfigResult
{
public function __construct(
public string $key,
public mixed $value,
public ConfigType $type,
public bool $found,
public bool $locked,
public bool $virtual = false,
public ?ScopeType $resolvedFrom = null,
public ?int $profileId = null,
public ?int $channelId = null,
) {}
/**
* Create a found result.
*/
public static function found(
string $key,
mixed $value,
ConfigType $type,
bool $locked,
?ScopeType $resolvedFrom = null,
?int $profileId = null,
?int $channelId = null,
): self {
return new self(
key: $key,
value: $type->cast($value),
type: $type,
found: true,
locked: $locked,
virtual: false,
resolvedFrom: $resolvedFrom,
profileId: $profileId,
channelId: $channelId,
);
}
/**
* Create a result from a virtual provider.
*/
public static function virtual(
string $key,
mixed $value,
ConfigType $type,
): self {
return new self(
key: $key,
value: $type->cast($value),
type: $type,
found: true,
locked: false,
virtual: true,
);
}
/**
* Create a not-found result with default value.
*/
public static function notFound(string $key, mixed $defaultValue, ConfigType $type): self
{
return new self(
key: $key,
value: $type->cast($defaultValue),
type: $type,
found: false,
locked: false,
);
}
/**
* Create a result for unconfigured key.
*/
public static function unconfigured(string $key): self
{
return new self(
key: $key,
value: null,
type: ConfigType::STRING,
found: false,
locked: false,
);
}
/**
* Check if the key was found (has a value).
*/
public function isConfigured(): bool
{
return $this->found && $this->value !== null;
}
/**
* Check if the value is locked (FINAL).
*/
public function isLocked(): bool
{
return $this->locked;
}
/**
* Check if the value came from a virtual provider.
*/
public function isVirtual(): bool
{
return $this->virtual;
}
/**
* Get the value, with optional fallback.
*/
public function get(mixed $default = null): mixed
{
return $this->value ?? $default;
}
/**
* Get value as string.
*/
public function string(string $default = ''): string
{
return (string) ($this->value ?? $default);
}
/**
* Get value as integer.
*/
public function int(int $default = 0): int
{
return (int) ($this->value ?? $default);
}
/**
* Get value as boolean.
*/
public function bool(bool $default = false): bool
{
return (bool) ($this->value ?? $default);
}
/**
* Get value as array.
*/
public function array(array $default = []): array
{
if ($this->value === null) {
return $default;
}
return is_array($this->value) ? $this->value : $default;
}
/**
* Convert to array for caching.
*/
public function toArray(): array
{
return [
'key' => $this->key,
'value' => $this->value,
'type' => $this->type->value,
'found' => $this->found,
'locked' => $this->locked,
'virtual' => $this->virtual,
'resolved_from' => $this->resolvedFrom?->value,
'profile_id' => $this->profileId,
'channel_id' => $this->channelId,
];
}
/**
* Reconstruct from cached array.
*/
public static function fromArray(array $data): self
{
return new self(
key: $data['key'],
value: $data['value'],
type: ConfigType::from($data['type']),
found: $data['found'],
locked: $data['locked'],
virtual: $data['virtual'] ?? false,
resolvedFrom: ($data['resolved_from'] ?? null) ? ScopeType::from($data['resolved_from']) : null,
profileId: $data['profile_id'] ?? null,
channelId: $data['channel_id'] ?? null,
);
}
}