Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 6 additions & 20 deletions .scrutinizer.yml
Original file line number Diff line number Diff line change
@@ -1,31 +1,17 @@
filter:
paths:
- 'src/*'
checks:
php:
uppercase_constants: true
simplify_boolean_return: true
return_doc_comments: true
properties_in_camelcaps: true
phpunit_assertions: true
parameters_in_camelcaps: true
parameter_doc_comments: true

coding_style:
php: { }

tools:
external_code_coverage: false
paths: ['src/*']

build:
environment:
php:
version: 8.0

tests:
override:
-
command: 'vendor/bin/phpunit --configuration ./test/phpunit.xml --coverage-clover=test/clover.xml'
- php-scrutinizer-run --enable-security-analysis
- command: 'XDEBUG_MODE=coverage ./vendor/bin/phpunit --config test/phpunit.xml --coverage-clover=test/clover.xml'
coverage:
file: 'test/clover.xml'
format: 'clover'

tools:
external_code_coverage: false
51 changes: 29 additions & 22 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@
представить в виде строки в формате ISO8601.

```php
use PTS\DataTransformer\DataTransformer;

$dataTransformer = new DataTransformer;
$dataTransformer->getMapsManager()->setMapDir(UserModel::class, __DIR__ . '/data');

Expand All @@ -45,7 +47,7 @@ $dto = $dataTransformer->toDTO($model, 'dto');
$dtoForDb = $dataTransformer->toDTO($model, 'db');
```

А еще у нас может быть просто более компактное представлеиние этой же модели, без лишних деталей.
А еще может быть просто более компактное представлеиние этой же модели, без лишних деталей.

```php
$shortFormatDto = $dataTransformer->toDTO($model, 'short.dto');
Expand All @@ -59,7 +61,7 @@ $shortFormatDto = $dataTransformer->toDTO($model, 'short.dto');
$mapName = 'dto';
$excludedFields = ['name'];
$dtoCollection = $dataTransformer->toDtoCollection($models, $mapName, [
'excludeFields' => $excludedFields
'excludeFields' => $excludedFields
]);
```

Expand All @@ -76,15 +78,14 @@ return [
'name' => [],
'login' => [],
'active' => [
'pipe' => ['boolval']
'pipe-populate' => ['boolval'],
'pipe-extract' => ['boolval'],
],
'email' => [
'pipe' => [
[
'populate' => 'strtolower', // any callable
'extract' => 'strtoupper'
]
]
'pipe-populate' => [ // any callable
'strval',
'strtolower',
]
],
'refModel' => [
'ref' => [
Expand Down Expand Up @@ -134,8 +135,8 @@ $model2 = $dataTransformer->toModel(UserModel::class, [
### Логика в pipe обработчиках

Обработчики pipe позволяют описывать callable методы и писать любую логику, которая будет применяться к значению. В pipe
фильтрах можно кастить типы например. Либо шифровать поля перед записью в БД. В случае необходимости, чтобы вся логика
маппинга была в 1 месте, вы может прокинуть любые зависимости через замыкание в функцию pipe, доставл ее из контейнера.
фильтрах можно кастить типы. Либо шифровать поля перед записью в БД. В случае необходимости, чтобы вся логика
маппинга была в 1 месте, вы может прокинуть любые зависимости через замыкание в функцию pipe, достав ее из контейнера.

```php
<?php
Expand All @@ -152,16 +153,22 @@ return [
'creAt' => [],
'name' => [],
'password' => [
'pipe' => [
[
'extract' => function(string $openPassword) use($encrypter) {
return $encrypter->encrypt($openPassword, false);
},
'populate' => static function(string $ePassword) use($encrypter) {
return $encrypter->decrypt($ePassword, false);
},
]
]
'pipe-populate' => [
'strtolower',
function(string $openPassword) use($encrypter) {
return $encrypter->encrypt($openPassword);
},
],
'pipe-extract' => [
function(string $ePassword) use($encrypter) {
return $encrypter->decrypt($ePassword);
},
'strtolower'
],
];


### migrates

[update 5 to 6](https://github.com/alexpts/php-data-transformer2/blob/master/docs/migrate5to6.md)

];
40 changes: 40 additions & 0 deletions docs/migrate5to6.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# Migrate 5 to 6

Change pipe format in map:
```php
// 5
$mapOld = [
'active' => [
'pipe' => [
[
'populate' => 'boolval',
'extract' => 'boolval',
]
]
],
'email' => [
'pipe-populate' => ['strtolower'],
'pipe-extract' => ['strtolower'],
'pipe' => [
'strtolower'
]
],
];

// 6
$mapNew = [
'active' => [
'pipe-populate' => [
'boolval',
],
'pipe-extract' => [
'boolval',
]
],
'email' => [
'pipe-populate' => ['strtolower'],
'pipe-extract' => ['strtolower'],
],
];

```
38 changes: 10 additions & 28 deletions src/DataTransformer.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,9 @@
use PTS\Hydrator\ExtractorInterface;
use PTS\Hydrator\Hydrator;
use PTS\Hydrator\HydratorInterface;
use function get_class;
use function is_callable;

class DataTransformer implements DataTransformerInterface
{
protected const FILTER_TYPE_POPULATE = 'populate';
protected const FILTER_TYPE_EXTRACT = 'extract';

protected ExtractorInterface $extractor;
protected HydratorInterface $hydrator;
protected MapsManager $mapsManager;
Expand All @@ -37,19 +32,16 @@ public function toModel(string $class, array $dto, string $mapName = 'dto'): obj
{
$map = $this->mapsManager->getMap($class, $mapName);
$dto = $map['refs'] ? $this->resolveRefPopulate($dto, $map['refs']) : $dto;
$dto = $map['pipe'] ? $this->applyPipes($dto, $map['pipe']) : $dto;
$dto = $map['pipe-populate'] ? $this->pipes($dto, $map['pipe-populate']) : $dto;
return $this->hydrator->hydrate($dto, $class, $map['rules']);
}

public function toModelsCollection(string $model, iterable $dtoCollection, string $mapType = 'dto'): array
{
$map = $this->mapsManager->getMap($model, $mapType);

$models = [];
foreach ($dtoCollection as $dto) {
$dto = $map['refs'] ? $this->resolveRefPopulate($dto, $map['refs']) : $dto;
$dto = $map['pipe'] ? $this->applyPipes($dto, $map['pipe']) : $dto;
$models[] = $this->hydrator->hydrate($dto, $model, $map['rules']);
foreach ($dtoCollection as $key => $dto) {
$dto = $this->toModel($model, $dto, $mapType);
$models[$key] = $dto;
}

return $models;
Expand All @@ -59,7 +51,7 @@ public function fillModel(object $model, array $dto, string $mapName = 'dto'): o
{
$map = $this->mapsManager->getMap($model::class, $mapName);
$dto = $map['refs'] ? $this->resolveRefPopulate($dto, $map['refs']) : $dto;
$dto = $map['pipe'] ? $this->applyPipes($dto, $map['pipe']) : $dto;
$dto = $map['pipe-populate'] ? $this->pipes($dto, $map['pipe-populate']) : $dto;
$this->hydrator->hydrateModel($dto, $model, $map['rules']);

return $model;
Expand All @@ -86,7 +78,7 @@ public function toDTO(object $model, string $mapName = 'dto', array $options = [
}

$dto = $this->extractor->extract($model, $map['rules']);
$dto = $map['pipe'] ? $this->applyPipes($dto, $map['pipe'], self::FILTER_TYPE_EXTRACT) : $dto;
$dto = $map['pipe-extract'] ? $this->pipes($dto, $map['pipe-extract']) : $dto;
return $map['refs'] ? $this->resolveRefExtract($dto, $map['refs']) : $dto;
}

Expand Down Expand Up @@ -124,28 +116,18 @@ protected function resolveRefPopulate(array $dto, array $refsRules): array
return $dto;
}

protected function applyPipes(array $dto, array $pipes, string $type = self::FILTER_TYPE_POPULATE): array
protected function pipes(array $dto, array $pipes): array
{
$fieldsPipes = array_intersect_key($pipes, $dto);
foreach ($fieldsPipes as $name => $filters) {
$value = $dto[$name] ?? null;
$dto[$name] = $this->applyFilters($value, $filters, $type);
}

return $dto;
}

protected function applyFilters($value, array $filters, string $type): mixed
{
foreach ($filters as $filter) {
if (is_callable($filter)) {
foreach ($filters as $filter) {
$value = $filter($value);
continue;
}

$value = ($filter[$type] ?? false) ? $filter[$type]($value) : $value;
$dto[$name] = $value;
}

return $value;
return $dto;
}
}
9 changes: 6 additions & 3 deletions src/Normalizer.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,22 @@ class Normalizer implements NormalizerInterface
public function normalize(array $rules): array
{
$map = [
'pipe' => [],
'pipe-populate' => [],
'pipe-extract' => [],
'rules' => $rules,
'refs' => [],
];

foreach ($map['rules'] as $name => &$rule) {
$rule['prop'] ??= $name;
$map['refs'][$name] = $rule['ref'] ?? null;
$map['pipe'][$name] = $rule['pipe'] ?? null;
$map['pipe-populate'][$name] = $rule['pipe-populate'] ?? null;
$map['pipe-extract'][$name] = $rule['pipe-extract'] ?? null;
}

$map['refs'] = array_filter($map['refs']);
$map['pipe'] = array_filter($map['pipe']);
$map['pipe-populate'] = array_filter($map['pipe-populate']);
$map['pipe-extract'] = array_filter($map['pipe-extract']);

return $map;
}
Expand Down
15 changes: 9 additions & 6 deletions test/unit/MapsManagerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,10 @@ public function testGetMap(): void
{
$this->manager->setMapDir('model.user', __DIR__ . '/data');
$map = $this->manager->getMap('model.user');
static::assertCount(3, $map);
static::assertCount(4, $map);
static::assertCount(6, $map['rules']);
static::assertCount(2, $map['pipe']);
static::assertCount(2, $map['pipe-populate']);
static::assertCount(2, $map['pipe-extract']);
static::assertCount(0, $map['refs']);
}

Expand All @@ -38,9 +39,10 @@ public function testGetMapWithCache(): void
$this->manager->setMapDir('model.user', __DIR__ . '/data');
$map = $this->manager->getMap('model.user');
$map2 = $this->manager->getMap('model.user');
static::assertCount(3, $map2);
static::assertCount(4, $map2);
static::assertCount(6, $map2['rules']);
static::assertCount(2, $map2['pipe']);
static::assertCount(2, $map2['pipe-populate']);
static::assertCount(2, $map2['pipe-extract']);
static::assertCount(0, $map2['refs']);
static::assertSame($map, $map2);
}
Expand All @@ -49,9 +51,10 @@ public function testGetMapFromDefaultDir(): void
{
$this->manager->setDefaultMapDir(__DIR__ . '/data');
$map = $this->manager->getMap('Namespace\UserModel');
static::assertCount(3, $map);
static::assertCount(4, $map);
static::assertCount(6, $map['rules']);
static::assertCount(2, $map['pipe']);
static::assertCount(2, $map['pipe-populate']);
static::assertCount(2, $map['pipe-extract']);
static::assertCount(0, $map['refs']);
}

Expand Down
24 changes: 18 additions & 6 deletions test/unit/data/UserModel/dto.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,27 @@
'name' => [],
'login' => [],
'active' => [
'pipe' => [
[
'populate' => 'boolval',
'extract' => 'boolval',
]
// 'pipe' => [
// [
// 'populate' => 'boolval',
// 'extract' => 'boolval',
// ],
// ],
'pipe-populate' => [
'boolval'
],
'pipe-extract' => [
'boolval'
]
],
'email' => [
'pipe' => [
// 'pipe' => [
// 'strtolower',
// ],
'pipe-populate' => [
'strtolower'
],
'pipe-extract' => [
'strtolower'
]
],
Expand Down
13 changes: 4 additions & 9 deletions test/unit/data/dto.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,11 @@
'name' => [],
'login' => [],
'active' => [
'pipe' => [
[
'populate' => 'boolval',
'extract' => 'boolval',
]
]
'pipe-populate' => ['boolval'],
'pipe-extract' => ['boolval'],
],
'email' => [
'pipe' => [
'strtolower'
]
'pipe-populate' => ['strtolower'],
'pipe-extract' => ['strtolower'],
],
];
3 changes: 2 additions & 1 deletion test/unit/data/withRefs.map.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@
'name' => [],
'login' => [],
'active' => [
'pipe' => ['boolval']
'pipe-populate' => ['boolval'],
'pipe-extract' => ['boolval'],
],
'email' => [],
'refModel' => [
Expand Down