adasd
All checks were successful
Deploy / deploy-staging (push) Successful in 5s
Deploy / deploy-production (push) Has been skipped

This commit is contained in:
2026-05-10 23:58:51 +02:00
parent 9848c1709b
commit 7c33d60f14
4 changed files with 129 additions and 45 deletions

View File

@@ -134,24 +134,19 @@ $mm->registerFunction($moduleName, 'save_runtime_settings', static function (arr
$repository->saveSettings($projectKey, $settings);
return module_fn($moduleName, 'runtime_settings');
return module_fn('mining-checker', 'runtime_settings');
});
$mm->registerFunction($moduleName, 'setup_actions', static function (): array {
return [
[
'name' => 'connection_test',
'label' => 'DB-Verbindung testen',
'help' => 'Prueft, ob die Projekt-Datenbank fuer den Mining-Checker erreichbar ist.',
],
[
'name' => 'initialize_schema',
'label' => 'Schema initialisieren',
'label' => 'Tabellen importieren',
'help' => 'Legt die Mining-Checker Tabellen an, wenn sie noch nicht vorhanden sind.',
],
[
'name' => 'upgrade_schema',
'label' => 'Tabellen auf neuesten Stand bringen',
'label' => 'Tabellen updaten',
'help' => 'Fuehrt fehlende Tabellen- und Spalten-Upgrades fuer den Mining-Checker aus.',
],
[
@@ -162,6 +157,29 @@ $mm->registerFunction($moduleName, 'setup_actions', static function (): array {
];
});
$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);
@@ -174,23 +192,6 @@ $mm->registerFunction($moduleName, 'run_setup_action', static function (string $
$repository = new MiningRepository($pdo, $config->tablePrefix(), null, $ownerSub);
return match ($action) {
'connection_test' => (static function () use ($pdo, $config): array {
$driver = strtolower((string) $pdo->getAttribute(PDO::ATTR_DRIVER_NAME));
$database = 'n/a';
try {
$database = match ($driver) {
'pgsql' => (string) ($pdo->query('SELECT current_database()')->fetchColumn() ?: 'n/a'),
'mysql' => (string) ($pdo->query('SELECT DATABASE()')->fetchColumn() ?: 'n/a'),
default => 'n/a',
};
} catch (\Throwable) {
$database = 'n/a';
}
return [
'message' => 'DB-Verbindung erfolgreich. Driver: ' . $driver . ', Datenbank: ' . $database . ', Tabellenpraefix: ' . $config->tablePrefix() . '.',
];
})(),
'initialize_schema' => (static function () use ($schema): array {
$result = $schema->initializeSchema(false);
$after = is_array($result['after'] ?? null) ? $result['after'] : [];

View File

@@ -5,7 +5,18 @@
"description": "Erfassung, OCR-Auswertung und Analyse von DOGE-Mining-Messwerten als eingebettetes Modul.",
"enabled_by_default": true,
"setup": {
"sections": {
"database": true
},
"fields": [
{ "name": "use_separate_db", "label": "Datenbank-Modus", "type": "select", "required": false, "help": "Standard nutzt die Nexus-Datenbank. Custom nutzt eine eigene Datenbankverbindung.", "options": { "0": "Standard", "1": "Custom Datenbank" } },
{ "name": "db.driver", "label": "DB Driver", "type": "text", "required": false, "help": "z.B. pgsql oder mysql" },
{ "name": "db.host", "label": "DB Host", "type": "text", "required": false },
{ "name": "db.port", "label": "DB Port", "type": "number", "required": false },
{ "name": "db.dbname", "label": "DB Name", "type": "text", "required": false },
{ "name": "db.schema", "label": "DB Schema", "type": "text", "required": false },
{ "name": "db.user", "label": "DB User", "type": "text", "required": false },
{ "name": "db.password", "label": "DB Passwort", "type": "password", "required": false },
{ "name": "baseline_measured_at", "label": "Baseline Zeitpunkt", "type": "datetime-local", "required": false, "help": "Referenzzeitpunkt fuer die erste Baseline-Messung." },
{ "name": "baseline_coins_total", "label": "Baseline Coins", "type": "number", "required": false, "help": "Coin-Bestand zum Baseline-Zeitpunkt." },
{ "name": "report_currency", "label": "Standard-Berichtswaehrung", "type": "text", "required": false, "help": "Zielwaehrung fuer Kennzahlen und Berichte, z.B. EUR." }

View File

@@ -11,8 +11,19 @@ final class ConnectionFactory
{
public static function make(ModuleConfig $config): PDO
{
if (!$config->useProjectDatabase()) {
throw new ApiException('Mining-Checker erwartet aktuell die Projekt-Datenbank. Eigene Modul-Datenbanken sind hier noch nicht implementiert.', 500);
$moduleSettings = modules()->settings('mining-checker');
$useSeparateDb = self::usesSeparateDatabase($moduleSettings);
if ($useSeparateDb) {
$dbConfig = is_array($moduleSettings['db'] ?? null) ? $moduleSettings['db'] : [];
if ($dbConfig === []) {
throw new ApiException('Custom-Datenbank ist aktiviert, aber nicht vollstaendig konfiguriert.', 500);
}
self::assertSupportedDriver($dbConfig);
if (method_exists(AppDatabase::class, 'connectFromConfig')) {
return AppDatabase::connectFromConfig($dbConfig);
}
return AppDatabase::createFromArray($dbConfig);
}
$dbConfig = app()->config()->dbConfig;
@@ -20,14 +31,7 @@ final class ConnectionFactory
throw new ApiException('Projekt-Datenbankkonfiguration fehlt in config/db_settings_basic.php.', 500);
}
$driver = strtolower((string) ($dbConfig['driver'] ?? ($dbConfig['dsn'] ?? '')));
if ($driver !== '' && !in_array($driver, ['mysql', 'pgsql'], true) && !str_starts_with($driver, 'mysql:') && !str_starts_with($driver, 'pgsql:' )) {
throw new ApiException(
'Mining-Checker unterstuetzt aktuell MySQL/MariaDB und PostgreSQL. Stelle in config/db_settings_basic.php den Driver auf mysql oder pgsql.',
500,
['driver' => $dbConfig['driver'] ?? 'unknown']
);
}
self::assertSupportedDriver($dbConfig);
if (method_exists(AppDatabase::class, 'connectFromConfig')) {
return AppDatabase::connectFromConfig($dbConfig);
@@ -35,4 +39,27 @@ final class ConnectionFactory
return AppDatabase::createFromArray($dbConfig);
}
private static function usesSeparateDatabase(array $moduleSettings): bool
{
$raw = $moduleSettings['use_separate_db'] ?? false;
if (is_bool($raw)) {
return $raw;
}
$normalized = strtolower(trim((string) $raw));
return in_array($normalized, ['1', 'true', 'yes', 'on', 'custom'], true);
}
private static function assertSupportedDriver(array $dbConfig): void
{
$driver = strtolower((string) ($dbConfig['driver'] ?? ($dbConfig['dsn'] ?? '')));
if ($driver !== '' && !in_array($driver, ['mysql', 'pgsql'], true) && !str_starts_with($driver, 'mysql:') && !str_starts_with($driver, 'pgsql:')) {
throw new ApiException(
'Mining-Checker unterstuetzt aktuell MySQL/MariaDB und PostgreSQL. Stelle den Driver auf mysql oder pgsql.',
500,
['driver' => $dbConfig['driver'] ?? 'unknown']
);
}
}
}