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

This commit is contained in:
2026-04-11 03:25:38 +02:00
parent 37f5b7f5e6
commit 067f962cb2
8 changed files with 277 additions and 25 deletions

View File

@@ -220,6 +220,11 @@ final class ModuleManager
return ($this->callbacks[$key])(...$args);
}
public function hasFunction(string $module, string $name): bool
{
return isset($this->callbacks[$module . ':' . $name]);
}
private function scanModules(): void
{
$this->modules = [];

View File

@@ -0,0 +1,116 @@
<?php
declare(strict_types=1);
namespace App;
use PDO;
final class ModuleSqlImportService
{
public function __construct(private ModuleManager $modules)
{
}
public function importableModules(): array
{
$items = [];
foreach ($this->modules->all() as $name => $module) {
if ($this->supportsGenericImport($name, $module)) {
$items[] = [
'name' => $name,
'title' => (string) ($module['title'] ?? $name),
'description' => (string) ($module['description'] ?? ''),
];
}
}
usort($items, static fn (array $left, array $right): int => strcmp($left['title'], $right['title']));
return $items;
}
public function importUploadedFile(string $moduleName, array $uploadedFile): array
{
$module = $this->modules->get($moduleName);
if ($module === null) {
throw new \RuntimeException('Unbekanntes Modul.');
}
$file = UploadedSqlFile::read($uploadedFile);
$target = $this->resolveImportTarget($moduleName, $module);
$statementCount = (new SqlDataImporter($target['pdo']))->importString((string) $file['sql']);
return [
'module' => $moduleName,
'module_title' => (string) ($module['title'] ?? $moduleName),
'target_label' => $target['label'],
'file' => (string) $file['file'],
'statement_count' => $statementCount,
'message' => 'SQL-Datei wurde erfolgreich importiert.',
];
}
private function supportsGenericImport(string $moduleName, array $module): bool
{
if ($this->modules->hasFunction($moduleName, 'sql_import_target')) {
return true;
}
if ($this->modules->hasFunction($moduleName, 'pdo')) {
return true;
}
$settings = $this->modules->settings($moduleName);
if (is_array($settings['db'] ?? null) && !empty($settings['db'])) {
return true;
}
return is_array($module['db_defaults'] ?? null) && !empty($module['db_defaults']);
}
private function resolveImportTarget(string $moduleName, array $module): array
{
if ($this->modules->hasFunction($moduleName, 'sql_import_target')) {
return $this->normalizeTarget(
$moduleName,
$this->modules->call($moduleName, 'sql_import_target')
);
}
if ($this->modules->hasFunction($moduleName, 'pdo')) {
return $this->normalizeTarget(
$moduleName,
$this->modules->call($moduleName, 'pdo')
);
}
$fallback = is_array($module['db_defaults'] ?? null) ? $module['db_defaults'] : [];
$pdo = $this->modules->modulePdo($moduleName, $fallback);
if (!$pdo instanceof PDO) {
throw new \RuntimeException('Fuer dieses Modul ist keine SQL-Datenbank verfuegbar.');
}
return [
'pdo' => $pdo,
'label' => (string) ($module['title'] ?? $moduleName) . ' Datenbank',
];
}
private function normalizeTarget(string $moduleName, mixed $target): array
{
if ($target instanceof PDO) {
return [
'pdo' => $target,
'label' => $moduleName . ' Datenbank',
];
}
if (is_array($target) && ($target['pdo'] ?? null) instanceof PDO) {
return [
'pdo' => $target['pdo'],
'label' => (string) ($target['label'] ?? ($moduleName . ' Datenbank')),
];
}
throw new \RuntimeException('Ungueltiges SQL-Import-Ziel fuer Modul ' . $moduleName . '.');
}
}

View File

@@ -0,0 +1,35 @@
<?php
declare(strict_types=1);
namespace App;
final class UploadedSqlFile
{
public static function read(array $uploadedFile): array
{
$errorCode = (int) ($uploadedFile['error'] ?? UPLOAD_ERR_NO_FILE);
if ($errorCode !== UPLOAD_ERR_OK) {
throw new \RuntimeException('SQL-Datei konnte nicht hochgeladen werden. Upload-Fehler: ' . $errorCode);
}
$originalName = (string) ($uploadedFile['name'] ?? 'import.sql');
$tmpPath = (string) ($uploadedFile['tmp_name'] ?? '');
if ($tmpPath === '' || !is_uploaded_file($tmpPath)) {
throw new \RuntimeException('Ungueltige Upload-Datei fuer SQL-Import.');
}
if (!preg_match('/\.sql$/i', $originalName)) {
throw new \RuntimeException('Bitte eine SQL-Datei mit Endung .sql hochladen.');
}
$sql = @file_get_contents($tmpPath);
if (!is_string($sql) || trim($sql) === '') {
throw new \RuntimeException('Die hochgeladene SQL-Datei ist leer oder konnte nicht gelesen werden.');
}
return [
'file' => $originalName,
'sql' => $sql,
];
}
}