osm-commerces/src/Command/CleanDuplicateStatsCommand.php
2025-07-14 17:40:34 +02:00

112 lines
No EOL
4.1 KiB
PHP

<?php
namespace App\Command;
use App\Entity\Stats;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;
#[AsCommand(
name: 'app:clean-duplicate-stats',
description: 'Supprime les doublons de Stats ayant le même code INSEE, en gardant le plus ancien. Option dry-run pour simuler.'
)]
class CleanDuplicateStatsCommand extends Command
{
public function __construct(private EntityManagerInterface $entityManager)
{
parent::__construct();
}
protected function configure(): void
{
$this
->addOption('dry-run', null, InputOption::VALUE_NONE, 'Simule la suppression sans rien effacer')
->setHelp('Supprime les doublons de Stats (même code INSEE), en gardant le plus ancien. Utilisez --dry-run pour simuler.');
}
protected function execute(InputInterface $input, OutputInterface $output): int
{
$io = new SymfonyStyle($input, $output);
$dryRun = $input->getOption('dry-run');
$repo = $this->entityManager->getRepository(Stats::class);
$allStats = $repo->findAll();
$io->title('Recherche des doublons Stats par code INSEE');
// Regrouper par code INSEE
$statsByZone = [];
foreach ($allStats as $stat) {
$zone = $stat->getZone();
if (!$zone) continue;
$statsByZone[$zone][] = $stat;
}
$toDelete = [];
$toKeep = [];
foreach ($statsByZone as $zone => $statsList) {
if (count($statsList) > 1) {
// Trier par date_created (le plus ancien d'abord), puis par id si date absente
usort($statsList, function($a, $b) {
$da = $a->getDateCreated();
$db = $b->getDateCreated();
if ($da && $db) {
return $da <=> $db;
} elseif ($da) {
return -1;
} elseif ($db) {
return 1;
} else {
return $a->getId() <=> $b->getId();
}
});
// Garder le premier, supprimer les autres
$toKeep[$zone] = $statsList[0];
$toDelete[$zone] = array_slice($statsList, 1);
}
}
$totalToDelete = array_sum(array_map('count', $toDelete));
if ($totalToDelete === 0) {
$io->success('Aucun doublon trouvé.');
return Command::SUCCESS;
}
$io->section('Résumé des actions par code INSEE :');
foreach ($toDelete as $zone => $statsList) {
$io->writeln("<info>Zone INSEE : $zone</info>");
$statKept = $toKeep[$zone];
$io->writeln(sprintf(" <fg=green>Gardé : [ID %d] %s | Créé: %s</>",
$statKept->getId(),
$statKept->getName(),
$statKept->getDateCreated() ? $statKept->getDateCreated()->format('Y-m-d H:i:s') : 'N/A'
));
foreach ($statsList as $stat) {
$io->writeln(sprintf(" <fg=red>Supprimé: [ID %d] %s | Créé: %s</>",
$stat->getId(),
$stat->getName(),
$stat->getDateCreated() ? $stat->getDateCreated()->format('Y-m-d H:i:s') : 'N/A'
));
}
}
$io->warning($totalToDelete . ' objet(s) Stats seraient supprimés.');
if ($dryRun) {
$io->note('Mode dry-run : aucune suppression effectuée.');
return Command::SUCCESS;
}
foreach ($toDelete as $statsList) {
foreach ($statsList as $stat) {
$this->entityManager->remove($stat);
}
}
$this->entityManager->flush();
$io->success($totalToDelete . ' doublon(s) supprimé(s) !');
return Command::SUCCESS;
}
}