160 lines
5.4 KiB
PHP
160 lines
5.4 KiB
PHP
<?php
|
|
|
|
namespace App\Console\Commands;
|
|
|
|
use App\Enums\Portal;
|
|
use App\Models\Company;
|
|
use Illuminate\Console\Command;
|
|
use Illuminate\Support\Facades\Storage;
|
|
use Illuminate\Support\Str;
|
|
|
|
class SyncCompanyLogos extends Command
|
|
{
|
|
protected $signature = 'legacy:sync-company-logos
|
|
{--portal=all : Portal (presseecho|businessportal24|all)}
|
|
{--dry-run : Nur prüfen, nichts kopieren oder aktualisieren}
|
|
{--force : Ziel-Dateien erneut überschreiben}';
|
|
|
|
protected $description = 'Kopiert referenzierte Legacy-Firmenlogos in einen sauberen Storage-Pfad und aktualisiert companies.logo_path.';
|
|
|
|
public function handle(): int
|
|
{
|
|
$portals = $this->selectedPortals();
|
|
|
|
if ($portals === []) {
|
|
$this->error('Ungültiges Portal. Erlaubt: presseecho, businessportal24, all.');
|
|
|
|
return self::FAILURE;
|
|
}
|
|
|
|
$dryRun = (bool) $this->option('dry-run');
|
|
$force = (bool) $this->option('force');
|
|
$totals = [
|
|
'referenced' => 0,
|
|
'copied' => 0,
|
|
'updated' => 0,
|
|
'already_synced' => 0,
|
|
'missing' => 0,
|
|
'unused' => 0,
|
|
];
|
|
|
|
foreach ($portals as $portal) {
|
|
$stats = $this->syncPortal($portal, $dryRun, $force);
|
|
|
|
foreach ($totals as $key => $value) {
|
|
$totals[$key] = $value + $stats[$key];
|
|
}
|
|
|
|
$this->line(sprintf(
|
|
'%s: referenziert %d, kopiert %d, DB-Updates %d, bereits synchron %d, fehlend %d, ungenutzt %d',
|
|
$portal,
|
|
$stats['referenced'],
|
|
$stats['copied'],
|
|
$stats['updated'],
|
|
$stats['already_synced'],
|
|
$stats['missing'],
|
|
$stats['unused'],
|
|
));
|
|
}
|
|
|
|
$this->newLine();
|
|
$this->info(sprintf(
|
|
'Gesamt: referenziert %d, kopiert %d, DB-Updates %d, bereits synchron %d, fehlend %d, ungenutzt %d%s',
|
|
$totals['referenced'],
|
|
$totals['copied'],
|
|
$totals['updated'],
|
|
$totals['already_synced'],
|
|
$totals['missing'],
|
|
$totals['unused'],
|
|
$dryRun ? ' (Dry-Run)' : '',
|
|
));
|
|
|
|
return $totals['missing'] > 0 ? self::FAILURE : self::SUCCESS;
|
|
}
|
|
|
|
/**
|
|
* @return list<string>
|
|
*/
|
|
private function selectedPortals(): array
|
|
{
|
|
$portal = (string) $this->option('portal');
|
|
|
|
return match ($portal) {
|
|
'all' => [Portal::Presseecho->value, Portal::Businessportal24->value],
|
|
Portal::Presseecho->value, Portal::Businessportal24->value => [$portal],
|
|
default => [],
|
|
};
|
|
}
|
|
|
|
/**
|
|
* @return array{referenced:int,copied:int,updated:int,already_synced:int,missing:int,unused:int}
|
|
*/
|
|
private function syncPortal(string $portal, bool $dryRun, bool $force): array
|
|
{
|
|
$sourceDirectory = "{$portal}/company";
|
|
$allSourceFiles = collect(Storage::disk('public')->files($sourceDirectory))
|
|
->mapWithKeys(fn (string $path): array => [basename($path) => $path]);
|
|
|
|
$referencedFilenames = [];
|
|
$stats = [
|
|
'referenced' => 0,
|
|
'copied' => 0,
|
|
'updated' => 0,
|
|
'already_synced' => 0,
|
|
'missing' => 0,
|
|
'unused' => 0,
|
|
];
|
|
|
|
Company::withoutGlobalScopes()
|
|
->where('legacy_portal', $portal)
|
|
->whereNotNull('logo_path')
|
|
->select(['id', 'legacy_portal', 'logo_path'])
|
|
->orderBy('id')
|
|
->chunkById(500, function ($companies) use ($allSourceFiles, $dryRun, $force, $portal, &$referencedFilenames, &$stats): void {
|
|
foreach ($companies as $company) {
|
|
$stats['referenced']++;
|
|
|
|
$sourceFilename = basename((string) $company->logo_path);
|
|
$referencedFilenames[$sourceFilename] = true;
|
|
|
|
if (Str::startsWith((string) $company->logo_path, 'company-logos/')) {
|
|
$stats['already_synced']++;
|
|
|
|
continue;
|
|
}
|
|
|
|
$sourcePath = $allSourceFiles->get($sourceFilename);
|
|
|
|
if (! $sourcePath) {
|
|
$stats['missing']++;
|
|
$this->warn("Fehlt: {$portal}/company/{$sourceFilename} (Company #{$company->id})");
|
|
|
|
continue;
|
|
}
|
|
|
|
$destinationPath = "company-logos/{$portal}/{$company->id}/{$sourceFilename}";
|
|
|
|
if (! $dryRun && ($force || ! Storage::disk('public')->exists($destinationPath))) {
|
|
Storage::disk('public')->copy($sourcePath, $destinationPath);
|
|
$stats['copied']++;
|
|
} elseif ($dryRun || Storage::disk('public')->exists($destinationPath)) {
|
|
$stats['copied'] += $dryRun ? 1 : 0;
|
|
}
|
|
|
|
if (! $dryRun) {
|
|
$company->forceFill([
|
|
'logo_path' => $destinationPath,
|
|
])->save();
|
|
}
|
|
|
|
$stats['updated']++;
|
|
}
|
|
});
|
|
|
|
$stats['unused'] = $allSourceFiles->keys()
|
|
->reject(fn (string $filename): bool => isset($referencedFilenames[$filename]))
|
|
->count();
|
|
|
|
return $stats;
|
|
}
|
|
}
|