From 0f667366c39f3f3efa70f3354619d64a9eec8bbb Mon Sep 17 00:00:00 2001
From: Priyadi Iman Nurcahyo <1102197+priyadi@users.noreply.github.com>
Date: Sun, 14 Jan 2024 06:06:18 +0700
Subject: [PATCH] feat: `TryProperty` command, or
`rekalogika:mapper:tryproperty` in console.
---
CHANGELOG.md | 1 +
src/Command/TryPropertyCommand.php | 115 ++++++++++++++++++++++++++++
src/MapperFactory/MapperFactory.php | 16 ++++
3 files changed, 132 insertions(+)
create mode 100644 src/Command/TryPropertyCommand.php
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 594ff2f6..77853766 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,6 +5,7 @@
* fix: PropertyAccessor `UninitializedPropertyException` error now is regarded
as null.
* fix: Transformer `SearchResult` was not properly ordered.
+* feat: `TryProperty` command, or `rekalogika:mapper:tryproperty` in console.
## 0.5.7
diff --git a/src/Command/TryPropertyCommand.php b/src/Command/TryPropertyCommand.php
new file mode 100644
index 00000000..27858412
--- /dev/null
+++ b/src/Command/TryPropertyCommand.php
@@ -0,0 +1,115 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE file
+ * that was distributed with this source code.
+ */
+
+namespace Rekalogika\Mapper\Command;
+
+use Rekalogika\Mapper\Transformer\Contracts\MixedType;
+use Rekalogika\Mapper\TransformerRegistry\TransformerRegistryInterface;
+use Rekalogika\Mapper\TypeResolver\TypeResolverInterface;
+use Symfony\Component\Console\Attribute\AsCommand;
+use Symfony\Component\Console\Command\Command;
+use Symfony\Component\Console\Helper\Table;
+use Symfony\Component\Console\Input\InputArgument;
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Output\OutputInterface;
+use Symfony\Component\Console\Style\SymfonyStyle;
+use Symfony\Component\PropertyInfo\PropertyInfoExtractorInterface;
+
+#[AsCommand(name: 'rekalogika:mapper:tryproperty', description: 'Gets the mapping result by providing the class and property name of the source and target.')]
+class TryPropertyCommand extends Command
+{
+ public function __construct(
+ private TransformerRegistryInterface $transformerRegistry,
+ private TypeResolverInterface $typeResolver,
+ private PropertyInfoExtractorInterface $propertyInfoExtractor,
+ ) {
+ parent::__construct();
+ }
+
+ protected function configure(): void
+ {
+ $this
+ ->addArgument('sourceClass', InputArgument::REQUIRED, 'The source class')
+ ->addArgument('sourceProperty', InputArgument::REQUIRED, 'The source property')
+ ->addArgument('targetClass', InputArgument::REQUIRED, 'The target class')
+ ->addArgument('targetProperty', InputArgument::REQUIRED, 'The target property')
+ ->setHelp("The %command.name% displays the mapping result by providing the class and property name of the source and target.");
+ }
+
+ protected function execute(InputInterface $input, OutputInterface $output): int
+ {
+ $io = new SymfonyStyle($input, $output);
+ $rows = [];
+
+ //
+ // source type
+ //
+
+ /** @var string */
+ $sourceClass = $input->getArgument('sourceClass');
+ /** @var string */
+ $sourceProperty = $input->getArgument('sourceProperty');
+ /** @var string */
+ $targetClass = $input->getArgument('targetClass');
+ /** @var string */
+ $targetProperty = $input->getArgument('targetProperty');
+
+ $sourceTypes = $this->propertyInfoExtractor
+ ->getTypes($sourceClass, $sourceProperty);
+
+ if ($sourceTypes === null || count($sourceTypes) === 0) {
+ $sourceTypes = [MixedType::instance()];
+ }
+
+ $targetTypes = $this->propertyInfoExtractor
+ ->getTypes($targetClass, $targetProperty);
+
+ if ($targetTypes === null || count($targetTypes) === 0) {
+ $targetTypes = [MixedType::instance()];
+ }
+
+
+ $results = $this->transformerRegistry
+ ->findBySourceAndTargetTypes($sourceTypes, $targetTypes);
+
+ foreach ($results as $result) {
+ $rows[] = [
+ $result->getMappingOrder(),
+ $this->typeResolver->getTypeString($result->getSourceType()),
+ $this->typeResolver->getTypeString($result->getTargetType()),
+ $result->getTransformer()::class,
+ ];
+ }
+
+ //
+ // render
+ //
+
+ $io->section('Applicable Transformers');
+
+ if (count($rows) === 0) {
+ $io->error('No applicable transformers found.');
+
+ return Command::SUCCESS;
+ }
+
+ $table = new Table($output);
+ $table->setVertical();
+ $table->setHeaders(['Mapping Order', 'Source Type', 'Target Type', 'Transformer']);
+ $table->setStyle('box');
+ $table->setRows($rows);
+ $table->render();
+
+ return Command::SUCCESS;
+ }
+}
diff --git a/src/MapperFactory/MapperFactory.php b/src/MapperFactory/MapperFactory.php
index 681b1a99..8c8331dc 100644
--- a/src/MapperFactory/MapperFactory.php
+++ b/src/MapperFactory/MapperFactory.php
@@ -17,6 +17,7 @@
use Psr\Container\ContainerInterface;
use Rekalogika\Mapper\Command\MappingCommand;
use Rekalogika\Mapper\Command\TryCommand;
+use Rekalogika\Mapper\Command\TryPropertyCommand;
use Rekalogika\Mapper\MainTransformer\MainTransformer;
use Rekalogika\Mapper\Mapper;
use Rekalogika\Mapper\MapperInterface;
@@ -102,6 +103,7 @@ class MapperFactory
private ?MappingCommand $mappingCommand = null;
private ?TryCommand $tryCommand = null;
+ private ?TryPropertyCommand $tryPropertyCommand = null;
private ?Application $application = null;
/**
@@ -527,12 +529,26 @@ protected function getTryCommand(): TryCommand
return $this->tryCommand;
}
+ protected function getTryPropertyCommand(): TryPropertyCommand
+ {
+ if (null === $this->tryPropertyCommand) {
+ $this->tryPropertyCommand = new TryPropertyCommand(
+ $this->getTransformerRegistry(),
+ $this->getTypeResolver(),
+ $this->getPropertyInfoExtractor(),
+ );
+ }
+
+ return $this->tryPropertyCommand;
+ }
+
public function getApplication(): Application
{
if (null === $this->application) {
$this->application = new Application();
$this->application->add($this->getMappingCommand());
$this->application->add($this->getTryCommand());
+ $this->application->add($this->getTryPropertyCommand());
}
return $this->application;