From 941e3cdc9c158fb3f65bb5b203130109ff49e3c6 Mon Sep 17 00:00:00 2001 From: tim Date: Fri, 23 Sep 2022 23:39:16 +0200 Subject: [PATCH] Create generic command with builder to easily edit entities from console --- src/Command/AbstractEntityCommand.php | 76 ++++++++++++++++++- .../{SimpleElement.php => BaseElement.php} | 7 +- src/EntityBuilder/Builder.php | 48 +++++++++--- 3 files changed, 119 insertions(+), 12 deletions(-) rename src/EntityBuilder/{SimpleElement.php => BaseElement.php} (83%) diff --git a/src/Command/AbstractEntityCommand.php b/src/Command/AbstractEntityCommand.php index 6856407..89ad507 100644 --- a/src/Command/AbstractEntityCommand.php +++ b/src/Command/AbstractEntityCommand.php @@ -2,29 +2,101 @@ namespace Ardent\UtilBundle\Command; +use App\Entity\Configuration; use Ardent\UtilBundle\EntityBuilder\Builder; +use Doctrine\ORM\EntityManagerInterface; +use Doctrine\ORM\EntityRepository; +use Exception; use Symfony\Component\Console\Command\Command; +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 Symfony\Component\Console\Question\ChoiceQuestion; +use Symfony\Component\Console\Question\ConfirmationQuestion; +use Symfony\Component\Console\Style\SymfonyStyle; abstract class AbstractEntityCommand extends Command { - abstract function getConfig(): Builder; + public function __construct( + private EntityManagerInterface $em, + ) + { + parent::__construct(); + } + + abstract function getConfig(Builder $builder): void; + + abstract function getEntityClass(): string; protected function configure(): void { $this + ->addArgument('id', InputArgument::OPTIONAL, 'Object Id') ->addOption('create', 'c', InputOption::VALUE_NONE, 'Create entity') - ->addOption('edit', 'e', InputOption::VALUE_NONE, 'Edit entity') + ->addOption('modify', 'm', InputOption::VALUE_NONE, 'Edit entity') ->addOption('delete', 'd', InputOption::VALUE_NONE, 'Delete entity') ->addOption('show', 's', InputOption::VALUE_NONE, 'Show entity'); } protected function execute(InputInterface $input, OutputInterface $output): int { + $io = new SymfonyStyle($input, $output); + $id = $input->getArgument('id'); + $builder = new Builder($io); + $this->getConfig($builder); + + if ($input->getOption('create')) { + $entity = new ($this->getEntityClass())(); + $builder->setAll($entity); + + if ($io->askQuestion(new ConfirmationQuestion(sprintf('Are you sure you want to create %s with above properties', $entity)))) { + $io->success(sprintf('Object "%s" (id: %s) stored successfully', $entity, $entity->getId())); + } + } elseif ($input->getOption('modify')) { + $entity = $this->select($io, $id); + $builder->setByQuestion($entity); + } elseif ($input->getOption('delete')) { + $entity = $this->select($io, $id); + if ($io->askQuestion(new ConfirmationQuestion(sprintf('Are you sure you want to delete %s', $entity)))) { + $name = (string)$entity; + $this->em->remove($entity); + $io->success(sprintf('Config "%s" deleted', $name)); + } + } elseif ($input->getOption('show')) { + $entity = $this->select($io, $id); + $table = $io->createTable(); + $table->setHeaders(['property', 'value']); + $table->setRows($builder->getAllproperties($entity)); + $table->setHeaderTitle(sprintf('id: %s', $entity->getId())); + $table->render(); + } else { + $io->error('Select at least one of the options'); + return Command::FAILURE; + } + + $this->em->persist($entity); + $this->em->flush(); return Command::SUCCESS; } + + private function select(SymfonyStyle $io, ?int $id): object + { + $repo = $this->em->getRepository($this->getEntityClass()); + if ($id) { + $object = $repo->find($id); + if ($object) { + return $object; + } + } + $entities = $repo->findAll(); + + if (empty($entities)) { + throw new Exception('No objects found'); + } + $question = new ChoiceQuestion('Select configuration to delete', $entities); + return $io->askQuestion($question); + } } \ No newline at end of file diff --git a/src/EntityBuilder/SimpleElement.php b/src/EntityBuilder/BaseElement.php similarity index 83% rename from src/EntityBuilder/SimpleElement.php rename to src/EntityBuilder/BaseElement.php index 16e681d..4a10b0b 100644 --- a/src/EntityBuilder/SimpleElement.php +++ b/src/EntityBuilder/BaseElement.php @@ -4,7 +4,7 @@ namespace Ardent\UtilBundle\EntityBuilder; use Symfony\Component\Console\Question\Question; -class SimpleElement +class BaseElement { public function getQuestion(): Question { @@ -23,4 +23,9 @@ class SimpleElement { return $this->property; } + + public function __toString(): string + { + return $this->property; + } } \ No newline at end of file diff --git a/src/EntityBuilder/Builder.php b/src/EntityBuilder/Builder.php index 918caa3..98389ef 100644 --- a/src/EntityBuilder/Builder.php +++ b/src/EntityBuilder/Builder.php @@ -3,39 +3,69 @@ namespace Ardent\UtilBundle\EntityBuilder; use Exception; +use Symfony\Component\Console\Question\ChoiceQuestion; use Symfony\Component\Console\Style\SymfonyStyle; class Builder { /** - * @var SimpleElement[] + * @var BaseElement[] */ private array $elements = []; + public function __construct( private readonly SymfonyStyle $io, ) { } - public function add(SimpleElement|string $element): self + public function add(BaseElement|string $element): self { if (is_string($element)) { - $element = new SimpleElement($element); + $element = new BaseElement($element); } $this->elements[] = $element; return $this; } - public function setObject(mixed $object): void + private function getPopertyNames(): array + { + return array_map(fn(BaseElement $element) => $element->getProperty(), $this->elements); + } + + private function setProperty(object $object, BaseElement $element): void + { + $setter = sprintf('set%s', ucfirst($element->getProperty())); + if (!method_exists($object, $setter)) { + throw new Exception(sprintf('Object does not have setter "%s"', $setter)); + } + $object->$setter($this->io->askQuestion($element->getQuestion())); + } + + public function setAll(object $object): void { foreach ($this->elements as $element) { - $setter = sprintf('set%s', ucfirst($element->getProperty())); - if (!method_exists($object, $setter)) { - throw new Exception(sprintf('Object does not have setter "%s"', $setter)); - } - $object->$setter($this->io->askQuestion($element->getQuestion())); + $this->setProperty($object, $element); } } + + public function setByQuestion(object $object): void + { + $element = $this->io->askQuestion(new ChoiceQuestion('Select property to modify', $this->elements)); + $getter = sprintf('get%s', ucfirst($element->getProperty())); + $this->io->writeln(sprintf('Current value: %s', $object->$getter())); + $this->setProperty($object, $element); + } + + public function getAllproperties(object $object): array + { + $data = []; + foreach ($this->elements as $element) { + $getter = sprintf('get%s', ucfirst($element->getProperty())); + $data[] = [$element->getProperty(), $object->$getter()]; + } + return $data; + } } \ No newline at end of file