* * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ namespace Chill\PersonBundle\Command; use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; use Chill\PersonBundle\Actions\Remove\PersonMove; use Doctrine\ORM\EntityManagerInterface; use Chill\PersonBundle\Entity\Person; use Symfony\Component\Console\Exception\RuntimeException; use Psr\Log\LoggerInterface; class ChillPersonMoveCommand extends ContainerAwareCommand { /** * * @var PersonMove */ protected $mover; /** * * @var EntityManagerInterface */ protected $em; /** * * @var LoggerInterface */ protected $chillLogger; public function __construct( PersonMove $mover, EntityManagerInterface $em, LoggerInterface $chillLogger ) { parent::__construct('chill:person:move'); $this->mover = $mover; $this->em = $em; $this->chillLogger = $chillLogger; } protected function configure() { $this ->setName('chill:person:move') ->setDescription('Move all the associated entities on a "from" person to a "to" person and remove the old person') ->addOption('from', 'f', InputOption::VALUE_REQUIRED, "The person id to delete, all associated data will be moved before") ->addOption('to', 't', InputOption::VALUE_REQUIRED, "The person id which will received data") ->addOption('dump-sql', null, InputOption::VALUE_NONE, "dump sql to stdout") ->addOption('force', null, InputOption::VALUE_NONE, "execute sql instead of dumping it") ->addOption('delete-entity', null, InputOption::VALUE_REQUIRED|InputOption::VALUE_IS_ARRAY, "entity to delete", []) ; } protected function interact(InputInterface $input, OutputInterface $output) { if (FALSE === $input->hasOption('dump-sql') && FALSE === $input->hasOption('force')) { $msg = "You must use \"--dump-sql\" or \"--force\""; throw new RuntimeException($msg); } foreach (["from", "to"] as $name) { if (empty($input->getOption($name))) { throw new RuntimeException("You must set a \"$name\" option"); } $id = $input->getOption($name); if (\ctype_digit($id) === FALSE) { throw new RuntimeException("The id in \"$name\" field does not contains " . "only digits: $id"); } } } protected function execute(InputInterface $input, OutputInterface $output) { $repository = $this->em->getRepository(Person::class); $from = $repository->find($input->getOption('from')); $to = $repository->find($input->getOption('to')); $deleteEntities = $input->getOption('delete-entity'); if ($from === NULL) { throw new RuntimeException(sprintf("Person \"from\" with id %d not found", $input->getOption('from'))); } if ($to === NULL) { throw new RuntimeException(sprintf("Person \"to\" with id %d not found", $input->getOption('to'))); } $sqls = $this->mover->getSQL($from, $to, $deleteEntities); if ($input->getOption('dump-sql')) { foreach($sqls as $sql) { $output->writeln($sql); } } else { $ctxt = $this->buildLoggingContext($from, $to, $deleteEntities, $sqls); $this->chillLogger->notice("Trying to move a person from command line", $ctxt); $connection = $this->em->getConnection(); $connection->beginTransaction(); foreach($sqls as $sql) { if ($output->isVerbose()) { $output->writeln($sql); } $connection->executeQuery($sql); } $connection->commit(); $this->chillLogger->notice("Move a person from command line succeeded", $ctxt); } } protected function buildLoggingContext(Person $from, Person $to, $deleteEntities, $sqls) { $ctxt = [ 'from' => $from->getId(), 'to' => $to->getId() ]; foreach ($deleteEntities as $key => $de) { $ctxt['delete_entity_'.$key] = $de; } foreach ($sqls as $key => $sql) { $ctxt['sql_'.$key] = $sql; } return $ctxt; } }