Skip to content

Commit

Permalink
chore: New naming scheme for attributes (#12)
Browse files Browse the repository at this point in the history
  • Loading branch information
Pixelshaped authored Jul 23, 2024
1 parent 563869a commit e29a219
Show file tree
Hide file tree
Showing 27 changed files with 178 additions and 170 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ jobs:
- name: PHPStan
run: vendor/bin/phpstan
- name: PHPUnit
run: vendor/bin/phpunit --coverage-clover=coverage.xml
run: vendor/bin/phpunit

- name: Upload coverage reports to Codecov
uses: codecov/[email protected]
Expand Down
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@
/.phpunit.cache/
/var/
composer.lock
coverage.xml
clover.xml
26 changes: 13 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ You can also use it to map SQL queries to objects, it has no dependency on a par

### At a glance

Given a DTO such as [AuthorDTO](tests/Examples/Valid/ReferencesArray/AuthorDTO.php)
Given a DTO such as [AuthorDTO](tests/Examples/Valid/ReferenceArray/AuthorDTO.php)

```php
$result = $flatMapper->map(AuthorDTO::class, $authorRepository->getAuthorsAndTheirBooks());
Expand Down Expand Up @@ -77,18 +77,18 @@ This bundle comes with several attributes that you can use to add mapping to you
- Use it as a Class attribute if you don't intend to use the property yourself ([see example](tests/Examples/Valid/Complex/ProductDTO.php)). It will then only be used internally and not be mapped to your DTO.
- Use it as a Property attribute if you have some use for it ([see example](tests/Examples/Valid/Complex/CustomerDTO.php)).
- Specify the mapped property name directly on the attribute ([see example](tests/Examples/Valid/Complex/InvoiceDTO.php)). This is mandatory when used as a Class attribute.
- Specify the mapped property name separately with the `InboundProperty` attribute, Doctrine-style ([see example](tests/Examples/Valid/ReferencesArray/AuthorDTO.php)).
- `#[InboundProperty("mapped_property_name")]`: The name of the key on the associative arrays contained by your result set. This is optional if your DTO's property names are already matching the result set ([see example](tests/Examples/Valid/WithoutAttributeDTO.php)).
- `#[ReferencesArray(NestedDTO::class)]`: An array of `NestedDTO` will be created using the mapping information contained in `NestedDTO`.
- `#[ColumnArray("mapped_property_name")]` the column `mapped_property_name` of your result set will be mapped as an array of scalar properties (such as IDs).
- Specify the mapped property name separately with the `InboundProperty` attribute, Doctrine-style ([see example](tests/Examples/Valid/ReferenceArray/AuthorDTO.php)).
- `#[Scalar("mapped_property_name")]`: The name of the key on the associative arrays contained by your result set. This is optional if your DTO's property names are already matching the result set ([see example](tests/Examples/Valid/WithoutAttributeDTO.php)).
- `#[ReferenceArray(NestedDTO::class)]`: An array of `NestedDTO` will be created using the mapping information contained in `NestedDTO`.
- `#[ScalarArray("mapped_property_name")]` the column `mapped_property_name` of your result set will be mapped as an array of scalar properties, such as IDs ([see example](tests/Examples/Valid/ScalarArray/ScalarArrayDTO.php)).

<a name="complete_example"></a>
### Hydrating nested DTOs

Given:

- [AuthorDTO](tests/Examples/Valid/ReferencesArray/AuthorDTO.php)
- [BookDTO](tests/Examples/Valid/ReferencesArray/BookDTO.php)
- [AuthorDTO](tests/Examples/Valid/ReferenceArray/AuthorDTO.php)
- [BookDTO](tests/Examples/Valid/ReferenceArray/BookDTO.php)

Calling FlatMapper with the following result set:

Expand Down Expand Up @@ -160,7 +160,7 @@ Array

### Hydrating Column Arrays

Given [ColumnArrayDTO](tests/Examples/Valid/ColumnArray/ColumnArrayDTO.php)
Given [ScalarArrayDTO](tests/Examples/Valid/ScalarArray/ScalarArrayDTO.php)

Calling FlatMapper with the following result set:
```php
Expand All @@ -178,7 +178,7 @@ Will output:
```php
Array
(
[1] => ColumnArrayDTO Object
[1] => ScalarArrayDTO Object
(
[id] => 1
[name] => Root 1
Expand All @@ -189,7 +189,7 @@ Array
[2] => 3
)
)
[2] => ColumnArrayDTO Object
[2] => ScalarArrayDTO Object
(
[id] => 2
[name] => Root 2
Expand All @@ -212,11 +212,11 @@ class CustomerDTO
{
public function __construct(
#[Identifier]
#[InboundPropertyName('customer_id')]
#[Scalar('customer_id')]
public int $id,
#[InboundPropertyName('customer_name')]
#[Scalar('customer_name')]
public string $name,
#[ColumnArray('shopping_list_id')]
#[ScalarArray('shopping_list_id')]
public array $shoppingListIds
)
}
Expand Down
6 changes: 6 additions & 0 deletions phpunit.xml
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,10 @@
<directory>src/Attributes</directory>
</exclude>
</source>

<coverage>
<report>
<clover outputFile="clover.xml"/>
</report>
</coverage>
</phpunit>
18 changes: 9 additions & 9 deletions src/FlatMapper.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@

namespace Pixelshaped\FlatMapperBundle;

use Pixelshaped\FlatMapperBundle\Attributes\ColumnArray;
use Pixelshaped\FlatMapperBundle\Attributes\Identifier;
use Pixelshaped\FlatMapperBundle\Attributes\InboundPropertyName;
use Pixelshaped\FlatMapperBundle\Attributes\ReferencesArray;
use Pixelshaped\FlatMapperBundle\Exception\MappingCreationException;
use Pixelshaped\FlatMapperBundle\Exception\MappingException;
use Pixelshaped\FlatMapperBundle\Mapping\Identifier;
use Pixelshaped\FlatMapperBundle\Mapping\ReferenceArray;
use Pixelshaped\FlatMapperBundle\Mapping\Scalar;
use Pixelshaped\FlatMapperBundle\Mapping\ScalarArray;
use ReflectionClass;
use Symfony\Contracts\Cache\CacheInterface;

Expand Down Expand Up @@ -95,11 +95,11 @@ private function createMappingRecursive(string $dtoClassName, array& $objectIden
$propertyName = $reflectionParameter->getName();
$isIdentifier = false;
foreach ($reflectionParameter->getAttributes() as $attribute) {
if ($attribute->getName() === ReferencesArray::class) {
if ($attribute->getName() === ReferenceArray::class) {
$objectsMapping[$dtoClassName][$propertyName] = (string)$attribute->getArguments()[0];
$this->createMappingRecursive($attribute->getArguments()[0], $objectIdentifiers, $objectsMapping);
continue 2;
} else if ($attribute->getName() === ColumnArray::class) {
} else if ($attribute->getName() === ScalarArray::class) {
$objectsMapping[$dtoClassName][$propertyName] = (string)$attribute->getArguments()[0];
continue 2;
} else if ($attribute->getName() === Identifier::class) {
Expand All @@ -108,7 +108,7 @@ private function createMappingRecursive(string $dtoClassName, array& $objectIden
if(isset($attribute->getArguments()[0]) && $attribute->getArguments()[0] !== null) {
$propertyName = $attribute->getArguments()[0];
}
} else if ($attribute->getName() === InboundPropertyName::class) {
} else if ($attribute->getName() === Scalar::class) {
$propertyName = $attribute->getArguments()[0];
}
}
Expand Down Expand Up @@ -158,14 +158,14 @@ public function map(string $dtoClassName, iterable $data): array {
foreach ($this->objectsMapping[$dtoClassName][$objectClass] as $objectProperty => $foreignObjectClassOrIdentifier) {
if($foreignObjectClassOrIdentifier !== null) {
if (isset($this->objectsMapping[$dtoClassName][$foreignObjectClassOrIdentifier])) {
// Handles ReferencesArray attribute
// Handles ReferenceArray attribute
$foreignIdentifier = $this->objectIdentifiers[$dtoClassName][$foreignObjectClassOrIdentifier];
if($row[$foreignIdentifier] !== null) { // As objects are constructed from leafs, this array key has already been tested when the leaf was constructed itself
$referencesMap[$objectClass][$row[$identifier]][$objectProperty][$row[$foreignIdentifier]] = $objectsMap[$foreignObjectClassOrIdentifier][$row[$foreignIdentifier]];
}
$constructorValues[] = [];
} else {
// Handles ColumnArray attribute
// Handles ScalarArray attribute
if($row[$foreignObjectClassOrIdentifier] !== null) {
$referencesMap[$objectClass][$row[$identifier]][$objectProperty][] = $row[$foreignObjectClassOrIdentifier];
}
Expand Down
4 changes: 2 additions & 2 deletions src/Attributes/Identifier.php → src/Mapping/Identifier.php
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
<?php
declare(strict_types=1);

namespace Pixelshaped\FlatMapperBundle\Attributes;
namespace Pixelshaped\FlatMapperBundle\Mapping;

use Attribute;

#[Attribute(Attribute::TARGET_PROPERTY | Attribute::TARGET_CLASS)]
final readonly class Identifier
{
public function __construct(
public ?string $inboundPropertyName = null
public ?string $mappedPropertyName = null
) {}
}
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
<?php
declare(strict_types=1);

namespace Pixelshaped\FlatMapperBundle\Attributes;
namespace Pixelshaped\FlatMapperBundle\Mapping;

use Attribute;

#[Attribute(Attribute::TARGET_PROPERTY)]
final readonly class ReferencesArray
final readonly class ReferenceArray
{
public function __construct(
/** @var class-string */
public string $className
public string $referenceClassName
) {}
}
6 changes: 3 additions & 3 deletions src/Attributes/ColumnArray.php → src/Mapping/Scalar.php
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
<?php
declare(strict_types=1);

namespace Pixelshaped\FlatMapperBundle\Attributes;
namespace Pixelshaped\FlatMapperBundle\Mapping;

use Attribute;

#[Attribute(Attribute::TARGET_PROPERTY)]
final readonly class ColumnArray
final readonly class Scalar
{
public function __construct(
public string $inboundPropertyName
public string $mappedPropertyName
) {}
}
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
<?php
declare(strict_types=1);

namespace Pixelshaped\FlatMapperBundle\Attributes;
namespace Pixelshaped\FlatMapperBundle\Mapping;

use Attribute;

#[Attribute(Attribute::TARGET_PROPERTY)]
final readonly class InboundPropertyName
final readonly class ScalarArray
{
public function __construct(
public string $inboundPropertyName
public string $mappedPropertyName
) {}
}
10 changes: 5 additions & 5 deletions tests/Examples/Invalid/LeafDTO.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,18 @@

namespace Pixelshaped\FlatMapperBundle\Tests\Examples\Invalid;

use Pixelshaped\FlatMapperBundle\Attributes\Identifier;
use Pixelshaped\FlatMapperBundle\Attributes\InboundPropertyName;
use Pixelshaped\FlatMapperBundle\Mapping\Identifier;
use Pixelshaped\FlatMapperBundle\Mapping\Scalar;

class LeafDTO
{
public function __construct(
#[Identifier]
#[InboundPropertyName('object1_id')]
#[Scalar('object1_id')]
public int $id,
#[InboundPropertyName('object2_name')]
#[Scalar('object2_name')]
public string $name,
#[InboundPropertyName('object2_value')]
#[Scalar('object2_value')]
public string $value,
) {}
}
12 changes: 6 additions & 6 deletions tests/Examples/Invalid/RootDTO.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@

namespace Pixelshaped\FlatMapperBundle\Tests\Examples\Invalid;

use Pixelshaped\FlatMapperBundle\Attributes\Identifier;
use Pixelshaped\FlatMapperBundle\Attributes\InboundPropertyName;
use Pixelshaped\FlatMapperBundle\Attributes\ReferencesArray;
use Pixelshaped\FlatMapperBundle\Mapping\Identifier;
use Pixelshaped\FlatMapperBundle\Mapping\ReferenceArray;
use Pixelshaped\FlatMapperBundle\Mapping\Scalar;

class RootDTO
{
Expand All @@ -14,11 +14,11 @@ class RootDTO
*/
public function __construct(
#[Identifier]
#[InboundPropertyName('object1_id')]
#[Scalar('object1_id')]
public int $id,
#[InboundPropertyName('object1_name')]
#[Scalar('object1_name')]
public string $name,
#[ReferencesArray(LeafDTO::class)]
#[ReferenceArray(LeafDTO::class)]
public array $leafs,
) {}
}
12 changes: 6 additions & 6 deletions tests/Examples/Invalid/RootDTOWithEmptyClassIdentifier.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@

namespace Pixelshaped\FlatMapperBundle\Tests\Examples\Invalid;

use Pixelshaped\FlatMapperBundle\Attributes\Identifier;
use Pixelshaped\FlatMapperBundle\Attributes\InboundPropertyName;
use Pixelshaped\FlatMapperBundle\Attributes\ReferencesArray;
use Pixelshaped\FlatMapperBundle\Mapping\Identifier;
use Pixelshaped\FlatMapperBundle\Mapping\ReferenceArray;
use Pixelshaped\FlatMapperBundle\Mapping\Scalar;

#[Identifier]
class RootDTOWithEmptyClassIdentifier
Expand All @@ -14,11 +14,11 @@ class RootDTOWithEmptyClassIdentifier
* @param array<LeafDTO> $leafs
*/
public function __construct(
#[InboundPropertyName('object1_id')]
#[Scalar('object1_id')]
public int $id,
#[InboundPropertyName('object1_name')]
#[Scalar('object1_name')]
public string $name,
#[ReferencesArray(LeafDTO::class)]
#[ReferenceArray(LeafDTO::class)]
public array $leafs,
) {}
}
10 changes: 5 additions & 5 deletions tests/Examples/Invalid/RootDTOWithNoIdentifier.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,20 @@

namespace Pixelshaped\FlatMapperBundle\Tests\Examples\Invalid;

use Pixelshaped\FlatMapperBundle\Attributes\InboundPropertyName;
use Pixelshaped\FlatMapperBundle\Attributes\ReferencesArray;
use Pixelshaped\FlatMapperBundle\Mapping\ReferenceArray;
use Pixelshaped\FlatMapperBundle\Mapping\Scalar;

class RootDTOWithNoIdentifier
{
/**
* @param array<LeafDTO> $leafs
*/
public function __construct(
#[InboundPropertyName('object1_id')]
#[Scalar('object1_id')]
public int $id,
#[InboundPropertyName('object1_name')]
#[Scalar('object1_name')]
public string $name,
#[ReferencesArray(LeafDTO::class)]
#[ReferenceArray(LeafDTO::class)]
public array $leafs,
) {}
}
12 changes: 6 additions & 6 deletions tests/Examples/Invalid/RootDTOWithTooManyIdentifiers.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@

namespace Pixelshaped\FlatMapperBundle\Tests\Examples\Invalid;

use Pixelshaped\FlatMapperBundle\Attributes\Identifier;
use Pixelshaped\FlatMapperBundle\Attributes\InboundPropertyName;
use Pixelshaped\FlatMapperBundle\Attributes\ReferencesArray;
use Pixelshaped\FlatMapperBundle\Mapping\Identifier;
use Pixelshaped\FlatMapperBundle\Mapping\ReferenceArray;
use Pixelshaped\FlatMapperBundle\Mapping\Scalar;

class RootDTOWithTooManyIdentifiers
{
Expand All @@ -14,12 +14,12 @@ class RootDTOWithTooManyIdentifiers
*/
public function __construct(
#[Identifier]
#[InboundPropertyName('object1_id')]
#[Scalar('object1_id')]
public int $id,
#[Identifier]
#[InboundPropertyName('object1_name')]
#[Scalar('object1_name')]
public string $name,
#[ReferencesArray(LeafDTO::class)]
#[ReferenceArray(LeafDTO::class)]
public array $leafs,
) {}
}
8 changes: 4 additions & 4 deletions tests/Examples/Invalid/RootDTOWithoutConstructor.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,15 @@

namespace Pixelshaped\FlatMapperBundle\Tests\Examples\Invalid;

use Pixelshaped\FlatMapperBundle\Attributes\Identifier;
use Pixelshaped\FlatMapperBundle\Attributes\InboundPropertyName;
use Pixelshaped\FlatMapperBundle\Mapping\Identifier;
use Pixelshaped\FlatMapperBundle\Mapping\Scalar;

class RootDTOWithoutConstructor
{
#[Identifier]
#[InboundPropertyName('object1_id')]
#[Scalar('object1_id')]
public int $id;

#[InboundPropertyName('object1_name')]
#[Scalar('object1_name')]
public string $name;
}
Loading

0 comments on commit e29a219

Please sign in to comment.