lthn.io/app/CorePlug/Registry.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

208 lines
4.6 KiB
PHP

<?php
declare(strict_types=1);
namespace Core\Plug;
use Illuminate\Support\Collection;
use Illuminate\Support\Str;
/**
* Provider registry with auto-discovery.
*
* Discovers providers from directory structure and provides
* capability checking and class resolution.
*/
class Registry
{
private array $providers = [];
private bool $discovered = false;
/**
* Categories in the Plug directory.
*/
private const CATEGORIES = ['Social', 'Web3', 'Content', 'Chat', 'Business'];
/**
* Discover all providers from directory structure.
*/
public function discover(): void
{
if ($this->discovered) {
return;
}
$basePath = __DIR__;
foreach (self::CATEGORIES as $category) {
$categoryPath = $basePath.'/'.$category;
if (! is_dir($categoryPath)) {
continue;
}
foreach (scandir($categoryPath) as $provider) {
if ($provider === '.' || $provider === '..') {
continue;
}
$providerPath = $categoryPath.'/'.$provider;
if (! is_dir($providerPath)) {
continue;
}
$identifier = Str::lower($provider);
$this->providers[$identifier] = [
'category' => $category,
'name' => $provider,
'namespace' => "Plug\\{$category}\\{$provider}",
'path' => $providerPath,
];
}
}
$this->discovered = true;
}
/**
* Register a provider programmatically.
*
* Used by plug packages to self-register without filesystem scanning.
*/
public function register(string $identifier, string $category, string $name, string $namespace): void
{
$this->providers[$identifier] = [
'category' => $category,
'name' => $name,
'namespace' => $namespace,
'path' => null,
];
}
/**
* Get all registered provider identifiers.
*
* @return string[]
*/
public function identifiers(): array
{
$this->discover();
return array_keys($this->providers);
}
/**
* Check if a provider exists.
*/
public function has(string $identifier): bool
{
$this->discover();
return isset($this->providers[$identifier]);
}
/**
* Get provider metadata.
*/
public function get(string $identifier): ?array
{
$this->discover();
return $this->providers[$identifier] ?? null;
}
/**
* Check if provider supports an operation.
*/
public function supports(string $identifier, string $operation): bool
{
$meta = $this->get($identifier);
if (! $meta) {
return false;
}
$className = $meta['namespace'].'\\'.ucfirst($operation);
return class_exists($className);
}
/**
* Get an operation class for a provider.
*
* @return class-string|null
*/
public function operation(string $identifier, string $operation): ?string
{
if (! $this->supports($identifier, $operation)) {
return null;
}
$meta = $this->get($identifier);
return $meta['namespace'].'\\'.ucfirst($operation);
}
/**
* Get all providers.
*/
public function all(): Collection
{
$this->discover();
return collect($this->providers);
}
/**
* Get provider identifiers by category.
*/
public function byCategory(string $category): Collection
{
$this->discover();
return collect($this->providers)
->filter(fn ($meta) => $meta['category'] === $category)
->keys();
}
/**
* Get providers that support a specific operation.
*/
public function withCapability(string $operation): Collection
{
$this->discover();
return collect($this->providers)->filter(
fn ($meta, $id) => $this->supports($id, $operation)
);
}
/**
* Get available categories.
*
* @return string[]
*/
public function categories(): array
{
return self::CATEGORIES;
}
/**
* Get the display name for a provider.
*/
public function displayName(string $identifier): ?string
{
$authClass = $this->operation($identifier, 'auth');
if ($authClass && method_exists($authClass, 'name')) {
return $authClass::name();
}
$meta = $this->get($identifier);
return $meta['name'] ?? null;
}
}