Files
nexus/modules/mining-checker/bootstrap.php
Lars Gebhardt-Kusche f46de880f4
All checks were successful
Deploy / deploy-staging (push) Successful in 5s
Deploy / deploy-production (push) Has been skipped
sadsad
2026-05-11 02:03:32 +02:00

236 lines
11 KiB
PHP

<?php
declare(strict_types=1);
use Modules\MiningChecker\Infrastructure\ConnectionFactory;
use Modules\MiningChecker\Infrastructure\MiningRepository;
use Modules\MiningChecker\Infrastructure\ModuleConfig;
use Modules\MiningChecker\Infrastructure\SchemaManager;
spl_autoload_register(static function (string $class): void {
$prefix = 'Modules\\MiningChecker\\';
if (!str_starts_with($class, $prefix)) {
return;
}
$relativeClass = substr($class, strlen($prefix));
$file = __DIR__ . '/src/' . str_replace('\\', '/', $relativeClass) . '.php';
if (is_file($file)) {
require_once $file;
}
});
$mm = isset($modules) && $modules instanceof App\ModuleManager ? $modules : modules();
$moduleName = 'mining-checker';
$mm->registerFunction($moduleName, 'runtime_settings', static function (): array {
$moduleBasePath = __DIR__;
$config = ModuleConfig::load($moduleBasePath);
$projectKey = $config->defaultProjectKey();
$user = auth_user() ?? [];
$ownerSub = trim((string) ($user['sub'] ?? '')) !== '' ? trim((string) ($user['sub'] ?? '')) : 'local';
$pdo = ConnectionFactory::make($config);
$repository = new MiningRepository($pdo, $config->tablePrefix(), null, $ownerSub);
$settings = $repository->getSettings($projectKey) ?? [];
$displayTimezone = trim((string) ($settings['display_timezone'] ?? nexus_display_timezone_name()));
if ($displayTimezone === '') {
$displayTimezone = nexus_display_timezone_name();
}
$baselineMeasuredAt = trim((string) ($settings['baseline_measured_at'] ?? ''));
if ($baselineMeasuredAt !== '') {
try {
$baselineMeasuredAt = (new DateTimeImmutable($baselineMeasuredAt, new DateTimeZone('UTC')))
->setTimezone(new DateTimeZone($displayTimezone))
->format('Y-m-d\TH:i');
} catch (\Throwable) {
$baselineMeasuredAt = '';
}
}
return [
'baseline_measured_at' => $baselineMeasuredAt,
'baseline_coins_total' => isset($settings['baseline_coins_total']) ? (string) $settings['baseline_coins_total'] : '',
'report_currency' => strtoupper(trim((string) ($settings['report_currency'] ?? 'EUR'))) ?: 'EUR',
];
});
$mm->registerFunction($moduleName, 'save_runtime_settings', static function (array $payload): array {
$moduleBasePath = __DIR__;
$config = ModuleConfig::load($moduleBasePath);
$projectKey = $config->defaultProjectKey();
$user = auth_user() ?? [];
$ownerSub = trim((string) ($user['sub'] ?? '')) !== '' ? trim((string) ($user['sub'] ?? '')) : 'local';
$pdo = ConnectionFactory::make($config);
$schema = new SchemaManager($pdo, $config->tablePrefix(), $moduleBasePath);
$schema->ensureSchema();
$repository = new MiningRepository($pdo, $config->tablePrefix(), null, $ownerSub);
$repository->ensureProject($projectKey, strtoupper(str_replace('-', ' ', $projectKey)));
$existing = $repository->getSettings($projectKey) ?? [];
$displayTimezone = trim((string) ($existing['display_timezone'] ?? nexus_display_timezone_name()));
if ($displayTimezone === '') {
$displayTimezone = nexus_display_timezone_name();
}
try {
$displayTz = new DateTimeZone($displayTimezone);
} catch (\Throwable) {
throw new RuntimeException('Ungueltige Anzeige-Zeitzone.');
}
$baselineInput = trim((string) ($payload['baseline_measured_at'] ?? ($existing['baseline_measured_at'] ?? '')));
if ($baselineInput === '') {
throw new RuntimeException('Baseline Zeitpunkt fehlt.');
}
try {
$baselineUtc = (new DateTimeImmutable($baselineInput, $displayTz))
->setTimezone(new DateTimeZone('UTC'))
->format('Y-m-d H:i:s');
} catch (\Throwable) {
throw new RuntimeException('Baseline Zeitpunkt ist ungueltig.');
}
$baselineCoins = trim((string) ($payload['baseline_coins_total'] ?? ($existing['baseline_coins_total'] ?? '')));
if ($baselineCoins === '' || !is_numeric($baselineCoins)) {
throw new RuntimeException('Baseline Coins muessen numerisch sein.');
}
$preferredCurrencies = $existing['preferred_currencies'] ?? ['DOGE', 'USD', 'EUR'];
if (is_string($preferredCurrencies)) {
$preferredCurrencies = preg_split('/[\s,;]+/', $preferredCurrencies) ?: [];
}
$preferredCurrencies = array_values(array_unique(array_filter(array_map(
static fn (mixed $value): string => strtoupper(trim((string) $value)),
is_array($preferredCurrencies) ? $preferredCurrencies : []
), static fn (string $value): bool => $value !== '')));
$settings = [
'baseline_measured_at' => $baselineUtc,
'baseline_coins_total' => (float) $baselineCoins,
'daily_cost_amount' => isset($existing['daily_cost_amount']) && is_numeric((string) $existing['daily_cost_amount'])
? (float) $existing['daily_cost_amount']
: 0.0,
'daily_cost_currency' => strtoupper(trim((string) ($existing['daily_cost_currency'] ?? 'EUR'))) ?: 'EUR',
'report_currency' => strtoupper(trim((string) ($payload['report_currency'] ?? ($existing['report_currency'] ?? 'EUR')))) ?: 'EUR',
'crypto_currency' => strtoupper(trim((string) ($existing['crypto_currency'] ?? 'DOGE'))) ?: 'DOGE',
'display_timezone' => $displayTimezone,
'fx_max_age_hours' => isset($existing['fx_max_age_hours']) && is_numeric((string) $existing['fx_max_age_hours'])
? (int) $existing['fx_max_age_hours']
: 3,
'module_theme_mode' => in_array((string) ($existing['module_theme_mode'] ?? 'inherit'), ['inherit', 'custom'], true)
? (string) $existing['module_theme_mode']
: 'inherit',
'module_theme_accent' => in_array((string) ($existing['module_theme_accent'] ?? 'teal'), ['teal', 'logo', 'pink', 'cyan', 'orange', 'green'], true)
? (string) $existing['module_theme_accent']
: 'teal',
'preferred_currencies' => $preferredCurrencies,
];
$repository->saveSettings($projectKey, $settings);
return module_fn('mining-checker', 'runtime_settings');
});
$mm->registerFunction($moduleName, 'setup_actions', static function (): array {
return [
[
'name' => 'initialize_schema',
'label' => 'Tabellen importieren',
'section' => 'database',
'help' => 'Legt die Mining-Checker Tabellen an, wenn sie noch nicht vorhanden sind.',
],
[
'name' => 'upgrade_schema',
'label' => 'Tabellen updaten',
'section' => 'database',
'help' => 'Fuehrt fehlende Tabellen- und Spalten-Upgrades fuer den Mining-Checker aus.',
],
[
'name' => 'seed_import',
'label' => 'Seed-Daten importieren',
'section' => 'database',
'help' => 'Importiert die vordefinierten Startdaten fuer das Standardprojekt.',
],
];
});
$mm->registerFunction($moduleName, 'setup_status', static function (): array {
$moduleBasePath = __DIR__;
$config = ModuleConfig::load($moduleBasePath);
$pdo = ConnectionFactory::make($config);
$schema = new SchemaManager($pdo, $config->tablePrefix(), $moduleBasePath);
$status = $schema->schemaStatus();
return [
'title' => 'Tabellenstatus',
'type' => !empty($status['all_present']) && empty($status['pending_upgrades']) ? 'success' : 'hint',
'text' => !empty($status['all_present'])
? (empty($status['pending_upgrades'])
? 'Alle Mining-Checker Tabellen sind vorhanden.'
: 'Alle Grundtabellen sind vorhanden, aber es gibt noch ausstehende Upgrades.')
: 'Das Mining-Checker Schema ist noch unvollstaendig.',
'stats' => [
['label' => 'Vorhandene Tabellen', 'value' => (string) ((int) ($status['present_count'] ?? 0) . '/' . count((array) ($status['required_tables'] ?? [])))],
['label' => 'Fehlende Tabellen', 'value' => !empty($status['missing_tables']) ? implode(', ', (array) $status['missing_tables']) : 'keine'],
['label' => 'Ausstehende Upgrades', 'value' => !empty($status['pending_upgrades']) ? implode(', ', (array) $status['pending_upgrades']) : 'keine'],
],
];
});
$mm->registerFunction($moduleName, 'run_setup_action', static function (string $action): array {
$moduleBasePath = __DIR__;
$config = ModuleConfig::load($moduleBasePath);
$projectKey = $config->defaultProjectKey();
$user = auth_user() ?? [];
$ownerSub = trim((string) ($user['sub'] ?? '')) !== '' ? trim((string) ($user['sub'] ?? '')) : 'local';
$pdo = ConnectionFactory::make($config);
$schema = new SchemaManager($pdo, $config->tablePrefix(), $moduleBasePath);
$repository = new MiningRepository($pdo, $config->tablePrefix(), null, $ownerSub);
return match ($action) {
'initialize_schema' => (static function () use ($schema): array {
$result = $schema->initializeSchema(false);
$after = is_array($result['after'] ?? null) ? $result['after'] : [];
return [
'message' => ($result['message'] ?? 'Schema initialisiert.')
. ' Vorhanden: ' . (int) ($after['present_count'] ?? 0)
. '/' . count((array) ($after['required_tables'] ?? [])) . '.',
];
})(),
'upgrade_schema' => (static function () use ($schema): array {
$result = $schema->upgradeSchemaDirect();
$applied = array_values(array_filter(array_map('strval', (array) ($result['upgraded'] ?? []))));
return [
'message' => ($result['message'] ?? 'Schema-Upgrade ausgefuehrt.')
. ($applied !== [] ? ' Upgrades: ' . implode(', ', $applied) . '.' : ''),
];
})(),
'seed_import' => (static function () use ($schema, $repository, $projectKey): array {
$schema->ensureSchema();
$repository->ensureProject($projectKey, strtoupper(str_replace('-', ' ', $projectKey)));
$result = (new \Modules\MiningChecker\Domain\SeedImporter($repository))->import($projectKey);
return [
'message' => 'Seed-Daten importiert. Eingefuegt: ' . (int) ($result['inserted'] ?? 0) . '.',
];
})(),
default => throw new RuntimeException('Unbekannte Setup-Aktion.'),
};
});
$mm->registerFunction('mining-checker', 'sql_import_target', static function (): array {
$moduleBasePath = __DIR__;
$config = ModuleConfig::load($moduleBasePath);
return [
'pdo' => ConnectionFactory::make($config),
'label' => 'Mining-Checker Projekt-Datenbank',
];
});