feat: introduce a path-mapping source modifier
This modifier can be used to change paths in the source data using a dot
notation.
The mapping is done using an associative array of path mappings. This
array must have the source path as key and the target path as value.
The source path uses the dot notation (eg `A.B.C`) and can contain one
`*` for array paths (eg `A.B.*.C`).
```php
final class Country
{
/** @var City[] */
public readonly array $cities;
}
final class City
{
public readonly string $name;
}
$source = new \CuyZ\Valinor\Mapper\Source\Modifier\PathMapping([
'towns' => [
['label' => 'Ankh Morpork'],
['label' => 'Minas Tirith'],
],
], [
'towns' => 'cities',
'towns.*.label' => 'name',
]);
// After modification this is what the source will look like:
[
'cities' => [
['name' => 'Ankh Morpork'],
['name' => 'Minas Tirith'],
],
];
(new \CuyZ\Valinor\MapperBuilder())
->mapper()
->map(Country::class, $source);
```
2022-02-26 11:33:50 +01:00
|
|
|
<?php
|
|
|
|
|
|
|
|
declare(strict_types=1);
|
|
|
|
|
2022-03-24 14:23:03 +01:00
|
|
|
namespace CuyZ\Valinor\Tests\Integration\Mapping\Source\Modifier;
|
feat: introduce a path-mapping source modifier
This modifier can be used to change paths in the source data using a dot
notation.
The mapping is done using an associative array of path mappings. This
array must have the source path as key and the target path as value.
The source path uses the dot notation (eg `A.B.C`) and can contain one
`*` for array paths (eg `A.B.*.C`).
```php
final class Country
{
/** @var City[] */
public readonly array $cities;
}
final class City
{
public readonly string $name;
}
$source = new \CuyZ\Valinor\Mapper\Source\Modifier\PathMapping([
'towns' => [
['label' => 'Ankh Morpork'],
['label' => 'Minas Tirith'],
],
], [
'towns' => 'cities',
'towns.*.label' => 'name',
]);
// After modification this is what the source will look like:
[
'cities' => [
['name' => 'Ankh Morpork'],
['name' => 'Minas Tirith'],
],
];
(new \CuyZ\Valinor\MapperBuilder())
->mapper()
->map(Country::class, $source);
```
2022-02-26 11:33:50 +01:00
|
|
|
|
|
|
|
use CuyZ\Valinor\Mapper\MappingError;
|
|
|
|
use CuyZ\Valinor\Mapper\Source\Modifier\PathMapping;
|
2022-05-22 20:43:01 +02:00
|
|
|
use CuyZ\Valinor\MapperBuilder;
|
feat: introduce a path-mapping source modifier
This modifier can be used to change paths in the source data using a dot
notation.
The mapping is done using an associative array of path mappings. This
array must have the source path as key and the target path as value.
The source path uses the dot notation (eg `A.B.C`) and can contain one
`*` for array paths (eg `A.B.*.C`).
```php
final class Country
{
/** @var City[] */
public readonly array $cities;
}
final class City
{
public readonly string $name;
}
$source = new \CuyZ\Valinor\Mapper\Source\Modifier\PathMapping([
'towns' => [
['label' => 'Ankh Morpork'],
['label' => 'Minas Tirith'],
],
], [
'towns' => 'cities',
'towns.*.label' => 'name',
]);
// After modification this is what the source will look like:
[
'cities' => [
['name' => 'Ankh Morpork'],
['name' => 'Minas Tirith'],
],
];
(new \CuyZ\Valinor\MapperBuilder())
->mapper()
->map(Country::class, $source);
```
2022-02-26 11:33:50 +01:00
|
|
|
use CuyZ\Valinor\Tests\Integration\IntegrationTest;
|
|
|
|
|
|
|
|
final class PathMappingTest extends IntegrationTest
|
|
|
|
{
|
|
|
|
public function test_path_with_sub_paths_are_mapped(): void
|
|
|
|
{
|
|
|
|
$map = [
|
|
|
|
'A1' => 'newA1',
|
|
|
|
'A1.B1' => 'value',
|
|
|
|
'A2' => 'newA2',
|
|
|
|
'A2.*.B1' => 'value',
|
|
|
|
'A3' => 'newA3',
|
|
|
|
'A3.B1' => 'newB1',
|
|
|
|
'A3.B2' => 'newB2',
|
|
|
|
'A3.*.C' => 'value',
|
|
|
|
'A4' => 'newA4',
|
|
|
|
'A4.B' => 'newB',
|
|
|
|
'A4.B.*.B1' => 'value',
|
|
|
|
];
|
|
|
|
|
|
|
|
$keys = array_keys($map);
|
|
|
|
shuffle($keys);
|
|
|
|
$randomMap = [];
|
|
|
|
|
|
|
|
foreach ($keys as $key) {
|
|
|
|
$randomMap[$key] = $map[$key];
|
|
|
|
}
|
|
|
|
|
|
|
|
try {
|
2022-05-22 20:43:01 +02:00
|
|
|
$object = (new MapperBuilder())->mapper()->map(
|
feat: introduce a path-mapping source modifier
This modifier can be used to change paths in the source data using a dot
notation.
The mapping is done using an associative array of path mappings. This
array must have the source path as key and the target path as value.
The source path uses the dot notation (eg `A.B.C`) and can contain one
`*` for array paths (eg `A.B.*.C`).
```php
final class Country
{
/** @var City[] */
public readonly array $cities;
}
final class City
{
public readonly string $name;
}
$source = new \CuyZ\Valinor\Mapper\Source\Modifier\PathMapping([
'towns' => [
['label' => 'Ankh Morpork'],
['label' => 'Minas Tirith'],
],
], [
'towns' => 'cities',
'towns.*.label' => 'name',
]);
// After modification this is what the source will look like:
[
'cities' => [
['name' => 'Ankh Morpork'],
['name' => 'Minas Tirith'],
],
];
(new \CuyZ\Valinor\MapperBuilder())
->mapper()
->map(Country::class, $source);
```
2022-02-26 11:33:50 +01:00
|
|
|
SomeRootClass::class,
|
|
|
|
new PathMapping(
|
|
|
|
[
|
|
|
|
'A1' => [
|
|
|
|
'B1' => 'foo',
|
|
|
|
],
|
|
|
|
'A2' => [
|
|
|
|
['B1' => 'bar'],
|
|
|
|
['B1' => 'buz'],
|
|
|
|
],
|
|
|
|
'A3' => [
|
|
|
|
'B1' => ['C' => 'biz'],
|
|
|
|
'B2' => ['C' => 'boz'],
|
|
|
|
],
|
|
|
|
'A4' => [
|
|
|
|
'B' => [
|
|
|
|
['B1' => 'faz'],
|
|
|
|
['B1' => 'fyz'],
|
|
|
|
],
|
|
|
|
],
|
|
|
|
],
|
|
|
|
$randomMap
|
|
|
|
)
|
|
|
|
);
|
|
|
|
} catch (MappingError $error) {
|
|
|
|
$this->mappingFail($error);
|
|
|
|
}
|
|
|
|
|
|
|
|
self::assertSame('foo', $object->newA1->value);
|
|
|
|
|
|
|
|
self::assertCount(2, $object->newA2);
|
|
|
|
self::assertSame('bar', $object->newA2[0]->value);
|
|
|
|
self::assertSame('buz', $object->newA2[1]->value);
|
|
|
|
|
|
|
|
self::assertSame('biz', $object->newA3->newB1->value);
|
|
|
|
self::assertSame('boz', $object->newA3->newB2->value);
|
|
|
|
|
|
|
|
self::assertCount(2, $object->newA4->newB);
|
|
|
|
self::assertSame('faz', $object->newA4->newB[0]->value);
|
|
|
|
self::assertSame('fyz', $object->newA4->newB[1]->value);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
class SomeRootClass
|
|
|
|
{
|
|
|
|
public SomeClassWithOneProperty $newA1;
|
|
|
|
|
|
|
|
/** @var array<SomeClassWithOneProperty> */
|
|
|
|
public array $newA2;
|
|
|
|
|
|
|
|
public SomeClassWithTwoProperties $newA3;
|
|
|
|
|
|
|
|
public SomeClassWithArrayProperty $newA4;
|
|
|
|
}
|
|
|
|
|
|
|
|
class SomeClassWithOneProperty
|
|
|
|
{
|
|
|
|
public string $value;
|
|
|
|
}
|
|
|
|
|
|
|
|
class SomeClassWithTwoProperties
|
|
|
|
{
|
|
|
|
public SomeClassWithOneProperty $newB1;
|
|
|
|
public SomeClassWithOneProperty $newB2;
|
|
|
|
}
|
|
|
|
|
|
|
|
class SomeClassWithArrayProperty
|
|
|
|
{
|
|
|
|
/** @var array<SomeClassWithOneProperty> */
|
|
|
|
public array $newB;
|
|
|
|
}
|