Skip to content

Commit

Permalink
Default value for properties
Browse files Browse the repository at this point in the history
  • Loading branch information
jan888adams committed Oct 9, 2023
1 parent 0d82ffd commit f3255b3
Show file tree
Hide file tree
Showing 7 changed files with 70 additions and 9 deletions.
11 changes: 10 additions & 1 deletion src/DependencyInjection/Configuration.php
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,16 @@ private function addConverterSection(ArrayNodeDefinition $rootNode): void
->info('Mapping of source properties (value) to target properties (key)')
->normalizeKeys(false)
->useAttributeAsKey('target')
->prototype('scalar')->end()
->arrayPrototype()
->beforeNormalization()
->ifString()
->then(fn (string $v) => ['source' => $v, 'default' => null])
->end()
->children()
->scalarNode('source')->end()
->scalarNode('default')->end()
->end()
->end()
->end()
->arrayNode('context')
->info('Mapping of context properties (value) to target properties (key)')
Expand Down
5 changes: 3 additions & 2 deletions src/DependencyInjection/NeustaConverterExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,12 +40,13 @@ public function loadInternal(array $mergedConfig, ContainerBuilder $container):
*/
private function registerConverterConfiguration(string $id, array $config, ContainerBuilder $container): void
{
foreach ($config['properties'] ?? [] as $targetProperty => $sourceProperty) {
foreach ($config['properties'] ?? [] as $targetProperty => $sourceConfig) {
$config['populators'][] = $propertyPopulatorId = "{$id}.populator.{$targetProperty}";
$container->register($propertyPopulatorId, PropertyMappingPopulator::class)
->setArguments([
'$targetProperty' => $targetProperty,
'$sourceProperty' => $sourceProperty ?? $targetProperty,
'$sourceProperty' => $sourceConfig['source'] ?? $targetProperty,
'$defaultValue' => $sourceConfig['default'] ?? null,
'$mapper' => null,
'$accessor' => new Reference('property_accessor'),
]);
Expand Down
4 changes: 2 additions & 2 deletions src/Populator/ConvertingPopulator.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,8 @@ public function __construct(
$this->populator = new PropertyMappingPopulator(
$targetPropertyName,
$sourcePropertyName,
\Closure::fromCallable([$converter, 'convert']),
$accessor,
mapper: \Closure::fromCallable([$converter, 'convert']),
accessor: $accessor,
);
}

Expand Down
5 changes: 4 additions & 1 deletion src/Populator/PropertyMappingPopulator.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ final class PropertyMappingPopulator implements Populator
public function __construct(
private string $targetProperty,
private string $sourceProperty,
private mixed $defaultValue = null,
\Closure $mapper = null,
PropertyAccessorInterface $accessor = null,
) {
Expand All @@ -41,10 +42,12 @@ public function __construct(
public function populate(object $target, object $source, object $ctx = null): void
{
try {
$value = $this->accessor->getValue($source, $this->sourceProperty);

$this->accessor->setValue(
$target,
$this->targetProperty,
($this->mapper)($this->accessor->getValue($source, $this->sourceProperty), $ctx),
($this->mapper)($value ?? $this->defaultValue, $ctx),
);
} catch (\Throwable $exception) {
throw new PopulationException($this->sourceProperty, $this->targetProperty, $exception);
Expand Down
37 changes: 37 additions & 0 deletions tests/DependencyInjection/NeustaConverterExtensionTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,43 @@ public function test_with_array_converting_populator_with_inner_property_first()
self::assertSame('value', $populator->getArgument('$sourceArrayItemPropertyName'));
}

public function test_with_array_converting_populator_with_default_value(): void
{
$container = $this->buildContainer([
'converter' => [
'foobar' => [
'target_factory' => PersonFactory::class,
'properties' => [
'name' => [
'source' => null,
'default' => 'John Doe',
],
'ageInYears' => [
'source' => 'age',
'default' => 42,
],
],
],
],
]);

// name property populator
$namePopulator = $container->getDefinition('foobar.populator.name');
self::assertSame(PropertyMappingPopulator::class, $namePopulator->getClass());
self::assertIsReference('property_accessor', $namePopulator->getArgument('$accessor'));
self::assertSame('name', $namePopulator->getArgument('$targetProperty'));
self::assertSame('name', $namePopulator->getArgument('$sourceProperty'));
self::assertSame('John Doe', $namePopulator->getArgument('$defaultValue'));

// ageInYears property populator
$ageInYearsPopulator = $container->getDefinition('foobar.populator.ageInYears');
self::assertSame(PropertyMappingPopulator::class, $ageInYearsPopulator->getClass());
self::assertIsReference('property_accessor', $ageInYearsPopulator->getArgument('$accessor'));
self::assertSame('ageInYears', $ageInYearsPopulator->getArgument('$targetProperty'));
self::assertSame('age', $ageInYearsPopulator->getArgument('$sourceProperty'));
self::assertSame(42, $ageInYearsPopulator->getArgument('$defaultValue'));
}

private static function assertIsReference(string $expected, mixed $actual): void
{
self::assertInstanceOf(Reference::class, $actual);
Expand Down
6 changes: 3 additions & 3 deletions tests/Fixtures/Model/User.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ class User
private int $uuid;
private string $firstname;
private string $lastname;
private string $fullName;
private ?string $fullName;
private int $ageInYears;
private Address $address;

Expand Down Expand Up @@ -60,12 +60,12 @@ public function setLastname(string $lastname): self
return $this;
}

public function getFullName(): string
public function getFullName(): ?string
{
return $this->fullName;
}

public function setFullName(string $fullName): self
public function setFullName(?string $fullName): self
{
$this->fullName = $fullName;

Expand Down
11 changes: 11 additions & 0 deletions tests/Populator/PropertyMappingPopulatorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,15 @@ public function test_populate(): void

self::assertEquals(37, $person->getAge());
}

public function test_populate_default_value(): void
{
$populator = new PropertyMappingPopulator('fullName', 'fullName', 'default');
$user = (new User())->setFullName(null);
$person = new Person();

$populator->populate($person, $user);

self::assertSame('default', $person->getFullName());
}
}

0 comments on commit f3255b3

Please sign in to comment.