12-05-2026 Frontend dev
Some checks are pending
linter / quality (push) Waiting to run
tests / ci (push) Waiting to run

This commit is contained in:
Kevin Adametz 2026-05-12 18:32:33 +02:00
parent 405df0a122
commit 5b8bdf4182
779 changed files with 480564 additions and 6241 deletions

View file

@ -0,0 +1,144 @@
<?php
namespace App\Console\Commands;
use App\Services\Auth\UserRolePermissionSyncService;
use App\Services\Import\CategoryImporter;
use App\Services\Import\CompanyImporter;
use App\Services\Import\ContactImporter;
use App\Services\Import\ImportContext;
use App\Services\Import\ImportResult;
use App\Services\Import\PressReleaseImporter;
use App\Services\Import\UserAssociationLinker;
use App\Services\Import\UserImporter;
use Illuminate\Console\Command;
/**
* Legacy-Import-Master-Command (Phase 6 Datenmigration).
*
* Verwendung:
* php artisan legacy:import --source=presseecho --dry-run
* php artisan legacy:import --source=businessportal24 --step=users
* php artisan legacy:import --source=all --step=categories
* php artisan legacy:import --source=all --step=link-associations NEU
* php artisan legacy:import --source=presseecho --force
*
* Schritte (--step):
* categories Kategorien + Translations (einmalig, beide Portale identisch)
* users sf_guard_user + sf_guard_user_profile + Rollen
* companies company + company_user + responsible_company_user
* contacts contact
* press-releases press_release + press_release_image + press_release_contact
* link-associations User↔Kontakt direkt verknüpfen (via Firma-Zugehörigkeit)
* all alle Schritte in korrekter Reihenfolge (Standard)
*/
class ImportLegacyData extends Command
{
protected $signature = 'legacy:import
{--source=all : Portal (presseecho|businessportal24|all)}
{--step=all : Schritt (categories|users|companies|contacts|press-releases|link-associations|all)}
{--dry-run : Nichts schreiben, nur zählen}
{--force : Bereits importierte Datensätze erneut verarbeiten}
{--chunk-size=500 : Batch-Größe (Debugging)}';
protected $description = 'Legacy-Daten aus Presseecho / Businessportal24 in die neue DB importieren.';
private const STEPS = [
'categories',
'users',
'companies',
'contacts',
'press-releases',
'link-associations',
];
private const PORTALS = ['presseecho', 'businessportal24'];
public function handle(UserRolePermissionSyncService $roleSync): int
{
$source = $this->option('source');
$step = $this->option('step');
$isDryRun = (bool) $this->option('dry-run');
$isForce = (bool) $this->option('force');
$portals = $source === 'all' ? self::PORTALS : [$source];
$steps = $step === 'all' ? self::STEPS : [$step];
if (! $isDryRun && ! $this->option('force')) {
$this->warn('WICHTIG: Dieser Command schreibt Daten in die Produktions-DB.');
$this->line(' Portale: '.implode(', ', $portals));
$this->line(' Schritte: '.implode(', ', $steps));
$this->newLine();
if (! $this->confirm('Import starten?')) {
$this->info('Abgebrochen.');
return self::SUCCESS;
}
}
if ($isDryRun) {
$this->warn('[DRY-RUN] Kein tatsächlicher Schreibvorgang.');
}
$totalStart = microtime(true);
foreach ($steps as $currentStep) {
// link-associations arbeitet auf der neuen DB → einmalig, portal-unabhängig
if ($currentStep === 'link-associations') {
$ctx = new ImportContext('all', $isDryRun, $isForce);
$this->info('▶ Schritt [link-associations] (beide Portale, neue DB)');
$start = microtime(true);
$result = app(UserAssociationLinker::class)->run($ctx);
$elapsed = round(microtime(true) - $start, 1);
$this->line("{$result->summary()} ({$elapsed}s)");
continue;
}
// Kategorien sind portal-übergreifend → nur einmal
$stepPortals = ($currentStep === 'categories') ? [$portals[0]] : $portals;
foreach ($stepPortals as $portal) {
$ctx = new ImportContext($portal, $isDryRun, $isForce);
$this->info("▶ Schritt [{$currentStep}] Portal [{$portal}]");
$start = microtime(true);
$result = $this->runStep($currentStep, $ctx, $roleSync);
$elapsed = round(microtime(true) - $start, 1);
$this->line("{$result->summary()} ({$elapsed}s)");
foreach (array_slice($result->errors(), 0, 10) as $err) {
$this->warn(" ! {$err}");
}
if (count($result->errors()) > 10) {
$this->warn(' ! ... und '.(count($result->errors()) - 10).' weitere Fehler.');
}
}
}
$total = round(microtime(true) - $totalStart, 1);
$this->newLine();
$this->info("Import abgeschlossen in {$total}s.");
return self::SUCCESS;
}
private function runStep(
string $step,
ImportContext $ctx,
UserRolePermissionSyncService $roleSync,
): ImportResult {
return match ($step) {
'categories' => app(CategoryImporter::class)->run($ctx),
'users' => app(UserImporter::class, ['roleSync' => $roleSync])->run($ctx),
'companies' => app(CompanyImporter::class)->run($ctx),
'contacts' => app(ContactImporter::class)->run($ctx),
'press-releases' => app(PressReleaseImporter::class)->run($ctx),
default => throw new \InvalidArgumentException("Unbekannter Schritt: {$step}"),
};
}
}