lthn.io/app/Core/Config/Models/ConfigVersion.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

188 lines
4.4 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\Models;
use Carbon\Carbon;
use Core\Tenant\Models\Workspace;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
/**
* Configuration version (snapshot).
*
* Stores a point-in-time snapshot of all config values for a scope.
* Used for version history and rollback capability.
*
* @property int $id
* @property int $profile_id
* @property int|null $workspace_id
* @property string $label
* @property string $snapshot
* @property string|null $author
* @property Carbon $created_at
*/
class ConfigVersion extends Model
{
protected $table = 'config_versions';
/**
* Disable updated_at timestamp since versions are immutable.
*/
public const UPDATED_AT = null;
protected $fillable = [
'profile_id',
'workspace_id',
'label',
'snapshot',
'author',
'created_at',
];
protected $casts = [
'created_at' => 'datetime',
];
/**
* The profile this version belongs to.
*/
public function profile(): BelongsTo
{
return $this->belongsTo(ConfigProfile::class, 'profile_id');
}
/**
* Workspace this version is for (null = system).
*
* Requires Core\Tenant module to be installed.
*/
public function workspace(): BelongsTo
{
if (class_exists(Workspace::class)) {
return $this->belongsTo(Workspace::class);
}
// Return a null relationship when Tenant module is not installed
return $this->belongsTo(self::class, 'workspace_id')->whereRaw('1 = 0');
}
/**
* Get the parsed snapshot data.
*
* @return array<string, mixed>
*/
public function getSnapshotData(): array
{
return json_decode($this->snapshot, true) ?? [];
}
/**
* Get the config values from the snapshot.
*
* @return array<array{key: string, value: mixed, locked: bool}>
*/
public function getValues(): array
{
$data = $this->getSnapshotData();
return $data['values'] ?? [];
}
/**
* Get a specific value from the snapshot.
*
* @param string $key Config key code
* @return mixed|null The value or null if not found
*/
public function getValue(string $key): mixed
{
$values = $this->getValues();
foreach ($values as $value) {
if ($value['key'] === $key) {
return $value['value'];
}
}
return null;
}
/**
* Check if a key exists in the snapshot.
*
* @param string $key Config key code
*/
public function hasKey(string $key): bool
{
$values = $this->getValues();
foreach ($values as $value) {
if ($value['key'] === $key) {
return true;
}
}
return false;
}
/**
* Get versions for a scope.
*
* @param int|null $workspaceId Workspace ID or null for system
* @return Collection<int, self>
*/
public static function forScope(?int $workspaceId = null): Collection
{
return static::where('workspace_id', $workspaceId)
->orderByDesc('created_at')
->get();
}
/**
* Get the latest version for a scope.
*
* @param int|null $workspaceId Workspace ID or null for system
*/
public static function latest(?int $workspaceId = null): ?self
{
return static::where('workspace_id', $workspaceId)
->orderByDesc('created_at')
->first();
}
/**
* Get versions created by a specific author.
*
* @return Collection<int, self>
*/
public static function byAuthor(string $author): Collection
{
return static::where('author', $author)
->orderByDesc('created_at')
->get();
}
/**
* Get versions created within a date range.
*
* @param Carbon $from Start date
* @param Carbon $to End date
* @return Collection<int, self>
*/
public static function inDateRange(Carbon $from, Carbon $to): Collection
{
return static::whereBetween('created_at', [$from, $to])
->orderByDesc('created_at')
->get();
}
}