presseportale/app/Console/Commands/ListCompanyMerges.php
Kevin Adametz 235c20ce1d companies: Zusammenführungen zum Nachprüfen auflisten
companies:merges --batch= zeigt je Vorgang Überlebenden, Newsroom-URLs auf
beiden Portalen, aufgegangene Firmen und deren alte URLs (301). Der scharfe
Lauf gibt die ersten 30 Vorgänge jetzt ebenfalls als Tabelle aus.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-15 09:10:54 +00:00

115 lines
4.7 KiB
PHP

<?php
namespace App\Console\Commands;
use App\Enums\CompanyMergeSubject;
use App\Enums\Portal;
use App\Models\Company;
use App\Models\CompanyMerge;
use Illuminate\Console\Command;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Str;
/**
* Zeigt, was eine Zusammenführung (Roadmap 1a.3) getan hat — je Vorgang der
* Überlebende, die aufgegangenen Firmen und die URLs zum Nachprüfen: der
* Newsroom auf beiden Portalen, die alten Slugs, die per 301 weiterführen.
*/
class ListCompanyMerges extends Command
{
protected $signature = 'companies:merges
{--batch= : Nur diesen Lauf}
{--email= : Nur diese Adresse}
{--limit=100 : Höchstens so viele Vorgänge}
{--json : Ausgabe als JSON}';
protected $description = 'Listet Zusammenführungen mit Überlebendem, aufgegangenen Firmen und Prüf-URLs.';
public function handle(): int
{
$merges = CompanyMerge::query()
->when($this->option('batch'), fn (Builder $query, string $batch) => $query->where('batch', $batch))
->when($this->option('email'), fn (Builder $query, string $email) => $query->where('email', Company::emailKey($email)))
->with([
'survivor',
'moves' => fn ($query) => $query->where('subject', CompanyMergeSubject::Company->value),
])
->orderByDesc('id')
->limit(max(1, (int) $this->option('limit')))
->get();
if ($merges->isEmpty()) {
$this->warn('Keine Vorgänge gefunden.');
return self::SUCCESS;
}
$losers = Company::withTrashed()
->withoutGlobalScopes()
->whereIn('id', $merges->flatMap(fn (CompanyMerge $merge) => $merge->moves->pluck('subject_id'))->all())
->get(['id', 'name', 'slug', 'portal'])
->keyBy('id');
$rows = $merges->map(function (CompanyMerge $merge) use ($losers): array {
$survivor = $merge->survivor;
$gone = $merge->moves->map(fn ($move) => $losers->get($move->subject_id))->filter();
return [
'id' => $merge->getKey(),
'batch' => $merge->batch,
'email' => $merge->email,
'rueckabgewickelt' => $merge->reverted_at?->toDateTimeString(),
'bleibt' => ['id' => $survivor->getKey(), 'name' => $survivor->name, 'slug' => $survivor->slug, 'portal' => $survivor->portal->value],
'newsroom' => $this->newsroomUrls($survivor->portal, $survivor->slug),
'aufgegangen' => $gone->map(fn (Company $loser): array => [
'id' => $loser->getKey(),
'name' => $loser->name,
'slug' => $loser->slug,
'portal' => $loser->portal->value,
// Nur bei abweichendem Slug gibt es eine Weiterleitung —
// bei gleichem findet die URL den Überlebenden direkt.
'alte_url' => $loser->slug !== $survivor->slug ? $this->newsroomUrls($loser->portal, $loser->slug) : [],
])->values()->all(),
'meldungen' => $merge->moved_press_releases_count,
];
});
if ($this->option('json')) {
$this->line((string) json_encode($rows->values()->all(), JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
return self::SUCCESS;
}
$this->table(
['#', 'Adresse', 'bleibt', 'Newsroom', 'aufgegangen (alte URL → 301)', 'PM'],
$rows->map(fn (array $row): array => [
$row['id'].($row['rueckabgewickelt'] ? ' (zurück)' : ''),
$row['email'],
sprintf('#%d %s', $row['bleibt']['id'], Str::limit($row['bleibt']['name'], 32)),
implode("\n", $row['newsroom']),
implode("\n", array_map(
fn (array $loser): string => sprintf('#%d %s%s', $loser['id'], Str::limit($loser['name'], 28), $loser['alte_url'] ? "\n ".implode("\n ", $loser['alte_url']) : ' (gleicher Slug)'),
$row['aufgegangen'],
)),
$row['meldungen'],
])->all(),
);
return self::SUCCESS;
}
/**
* Newsroom-URL je Portal, auf dem die Firma erreichbar ist.
*
* @return list<string>
*/
private function newsroomUrls(Portal $portal, string $slug): array
{
$portals = $portal === Portal::Both ? ['presseecho', 'businessportal24'] : [$portal->value];
return array_map(
fn (string $key): string => rtrim((string) config("domains.domains.{$key}.url"), '/').'/de/newsroom/'.$slug,
$portals,
);
}
}