Skip to content

Commit 2941d94

Browse files
committed
feat('Profiler`): Show mapping table.
1 parent 91829f2 commit 2941d94

File tree

11 files changed

+153
-13
lines changed

11 files changed

+153
-13
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
contains an eager argument, then the rest of the arguments must be eager.
1313
* fix(`ObjectToObjectMetadataFactory`): If the target is not writable, skip the
1414
mapping.
15+
* feat(`Profiler`): Show mapping table.
1516

1617
## 0.7.2
1718

config/services.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,7 @@
201201

202202
$services
203203
->set('rekalogika.mapper.mapping_factory.caching', WarmableMappingFactory::class)
204-
->decorate('rekalogika.mapper.mapping_factory')
204+
->decorate('rekalogika.mapper.mapping_factory', null, 500)
205205
->args([
206206
service('rekalogika.mapper.mapping_factory.caching.inner'),
207207
service('kernel')

src/Debug/Helper.php

+3-2
Original file line numberDiff line numberDiff line change
@@ -13,16 +13,17 @@
1313

1414
namespace Rekalogika\Mapper\Debug;
1515

16+
use Rekalogika\Mapper\Transformer\Contracts\MixedType;
1617
use Rekalogika\Mapper\Util\TypeUtil;
1718
use Symfony\Component\PropertyInfo\Type;
1819

1920
final class Helper
2021
{
2122
/**
22-
* @param Type|array<int,Type> $type
23+
* @param Type|array<int,Type|MixedType> $type
2324
* @return string
2425
*/
25-
public function typeToHtml(Type|array|null $type): string
26+
public function typeToHtml(Type|MixedType|array|null $type): string
2627
{
2728
if ($type === null) {
2829
return 'mixed';

src/Debug/MapperDataCollector.php

+17
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
namespace Rekalogika\Mapper\Debug;
1515

16+
use Rekalogika\Mapper\Mapping\Mapping;
1617
use Rekalogika\Mapper\Transformer\ObjectToObjectMetadata\ObjectToObjectMetadata;
1718
use Symfony\Bundle\FrameworkBundle\DataCollector\AbstractDataCollector;
1819
use Symfony\Component\HttpFoundation\Request;
@@ -51,6 +52,11 @@ public function collectObjectToObjectMetadata(
5152
$this->data['object_to_object_metadata'][$key] = $objectToObjectMetadata;
5253
}
5354

55+
public function collectMappingTable(Mapping $mapping): void
56+
{
57+
$this->data['mapping'] = $mapping;
58+
}
59+
5460
public function getHelper(): Helper
5561
{
5662
return new Helper();
@@ -74,6 +80,17 @@ public function getObjectToObjectMetadatas(): array
7480
return array_values($this->data['object_to_object_metadata'] ?? []);
7581
}
7682

83+
public function getMappingTable(): Mapping
84+
{
85+
$result = $this->data['mapping'] ?? new Mapping();
86+
87+
if (!$result instanceof Mapping) {
88+
return new Mapping();
89+
}
90+
91+
return $result;
92+
}
93+
7794
private ?int $totalMappings = null;
7895

7996
public function getTotalMappings(): int

src/Debug/TraceableMappingFactory.php

+60
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/*
6+
* This file is part of rekalogika/mapper package.
7+
*
8+
* (c) Priyadi Iman Nurcahyo <https://rekalogika.dev>
9+
*
10+
* For the full copyright and license information, please view the LICENSE file
11+
* that was distributed with this source code.
12+
*/
13+
14+
namespace Rekalogika\Mapper\Debug;
15+
16+
use Rekalogika\Mapper\Mapping\Mapping;
17+
use Rekalogika\Mapper\Mapping\MappingFactoryInterface;
18+
use Symfony\Component\HttpKernel\CacheWarmer\CacheWarmerInterface;
19+
20+
final class TraceableMappingFactory implements
21+
MappingFactoryInterface,
22+
CacheWarmerInterface
23+
{
24+
private bool $mappingCollected = false;
25+
26+
public function __construct(
27+
private MappingFactoryInterface $decorated,
28+
private MapperDataCollector $dataCollector
29+
) {
30+
}
31+
32+
public function isOptional(): bool
33+
{
34+
return $this->decorated instanceof CacheWarmerInterface && $this->decorated->isOptional();
35+
}
36+
37+
public function warmUp(string $cacheDir, ?string $buildDir = null): array
38+
{
39+
if ($this->decorated instanceof CacheWarmerInterface) {
40+
// @phpstan-ignore-next-line
41+
return $this->decorated->warmUp($cacheDir, $buildDir);
42+
}
43+
44+
return [];
45+
}
46+
47+
public function getMapping(): Mapping
48+
{
49+
if ($this->mappingCollected) {
50+
return $this->decorated->getMapping();
51+
}
52+
53+
$mapping = $this->decorated->getMapping();
54+
55+
$this->dataCollector->collectMappingTable($mapping);
56+
$this->mappingCollected = true;
57+
58+
return $mapping;
59+
}
60+
}

src/Debug/TraceableTransformer.php

+2-1
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,13 @@
1818
use Rekalogika\Mapper\MainTransformer\MainTransformerInterface;
1919
use Rekalogika\Mapper\MainTransformer\Model\DebugContext;
2020
use Rekalogika\Mapper\MainTransformer\Model\Path;
21+
use Rekalogika\Mapper\Transformer\AbstractTransformerDecorator;
2122
use Rekalogika\Mapper\Transformer\Contracts\MainTransformerAwareInterface;
2223
use Rekalogika\Mapper\Transformer\Contracts\MainTransformerAwareTrait;
2324
use Rekalogika\Mapper\Transformer\Contracts\TransformerInterface;
2425
use Symfony\Component\PropertyInfo\Type;
2526

26-
final class TraceableTransformer implements
27+
final class TraceableTransformer extends AbstractTransformerDecorator implements
2728
TransformerInterface,
2829
MainTransformerAwareInterface
2930
{

src/DependencyInjection/CompilerPass/DebugPass.php

+13-1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
namespace Rekalogika\Mapper\DependencyInjection\CompilerPass;
1515

16+
use Rekalogika\Mapper\Debug\TraceableMappingFactory;
1617
use Rekalogika\Mapper\Debug\TraceableObjectToObjectMetadataFactory;
1718
use Rekalogika\Mapper\Debug\TraceableTransformer;
1819
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
@@ -55,7 +56,18 @@ public function process(ContainerBuilder $container)
5556
$serviceId = 'rekalogika.mapper.object_to_object_metadata_factory.cache';
5657
$decoratedService = $container->getDefinition($serviceId);
5758
$container->register('debug.' . $serviceId, TraceableObjectToObjectMetadataFactory::class)
58-
->setDecoratedService($serviceId, null)
59+
->setDecoratedService($serviceId)
60+
->setArguments([
61+
$decoratedService,
62+
$dataCollector,
63+
]);
64+
65+
// decorates mapping factory
66+
67+
$serviceId = 'rekalogika.mapper.mapping_factory';
68+
$decoratedService = $container->getDefinition($serviceId);
69+
$container->register('debug.' . $serviceId, TraceableMappingFactory::class)
70+
->setDecoratedService($serviceId, null, 100)
5971
->setArguments([
6072
$decoratedService,
6173
$dataCollector,

src/Mapping/Implementation/MappingFactory.php

+5
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
use Rekalogika\Mapper\Mapping\Mapping;
1717
use Rekalogika\Mapper\Mapping\MappingFactoryInterface;
18+
use Rekalogika\Mapper\Transformer\AbstractTransformerDecorator;
1819
use Rekalogika\Mapper\Transformer\Contracts\MixedType;
1920
use Rekalogika\Mapper\Transformer\Contracts\TransformerInterface;
2021
use Rekalogika\Mapper\TypeResolver\TypeResolverInterface;
@@ -70,6 +71,10 @@ private function addMapping(
7071
$targetTypes = $this->getSimpleTypes($typeMapping->getTargetType());
7172
$isVariantTargetType = $typeMapping->isVariantTargetType();
7273

74+
if ($transformer instanceof AbstractTransformerDecorator) {
75+
$transformer = $transformer->getDecorated();
76+
}
77+
7378
foreach ($sourceTypes as $sourceType) {
7479
foreach ($targetTypes as $targetType) {
7580
$sourceTypeString = $this->typeResolver->getTypeString($sourceType);

src/Transformer/AbstractTransformerDecorator.php

+5
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,11 @@ public function __construct(
2424
) {
2525
}
2626

27+
public function getDecorated(): TransformerInterface
28+
{
29+
return $this->decorated;
30+
}
31+
2732
public function transform(
2833
mixed $source,
2934
mixed $target,

src/Transformer/ObjectToObjectMetadata/Implementation/ObjectToObjectMetadataFactory.php

+8-8
Original file line numberDiff line numberDiff line change
@@ -214,15 +214,15 @@ public function createObjectToObjectMetadata(
214214

215215
if ($targetWriteMode === WriteMode::None) {
216216
continue;
217-
} else {
218-
$targetWriteName = $targetWriteInfo->getName();
219-
$targetWriteVisibility = match ($targetWriteInfo->getVisibility()) {
220-
PropertyWriteInfo::VISIBILITY_PUBLIC => Visibility::Public,
221-
PropertyWriteInfo::VISIBILITY_PROTECTED => Visibility::Protected,
222-
PropertyWriteInfo::VISIBILITY_PRIVATE => Visibility::Private,
223-
default => Visibility::None,
224-
};
225217
}
218+
$targetWriteName = $targetWriteInfo->getName();
219+
$targetWriteVisibility = match ($targetWriteInfo->getVisibility()) {
220+
PropertyWriteInfo::VISIBILITY_PUBLIC => Visibility::Public,
221+
PropertyWriteInfo::VISIBILITY_PROTECTED => Visibility::Protected,
222+
PropertyWriteInfo::VISIBILITY_PRIVATE => Visibility::Private,
223+
default => Visibility::None,
224+
};
225+
226226
}
227227

228228
// get source property types

templates/data_collector.html.twig

+38
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@
5454
<div class="sf-tabs">
5555
{{ _self.render_mappings_tab(collector.mappings) }}
5656
{{ _self.render_o2o_tab(collector.objectToObjectMetadatas, helper) }}
57+
{{ _self.render_mapping_table(collector.mappingTable, helper) }}
5758
</div>
5859
{% endif %}
5960

@@ -124,6 +125,43 @@
124125
</div>
125126
{% endmacro %}
126127

128+
{% macro render_mapping_table(table, helper) %}
129+
<div class="tab">
130+
<h3 class="tab-title">
131+
Mapping Table
132+
</h3>
133+
134+
<div class="tab-content">
135+
<table>
136+
<thead>
137+
<tr>
138+
<th>#</th>
139+
<th>Source</th>
140+
<th>Target</th>
141+
<th>Target Variance</th>
142+
<th>Transformer</th>
143+
</tr>
144+
</thead>
145+
{% for row in table %}
146+
<tr>
147+
<td>{{ row.order }}</td>
148+
<td>{{ helper.typeToHtml(row.sourceType)|raw }}</td>
149+
<td>{{ helper.typeToHtml(row.targetType)|raw }}</td>
150+
<td>
151+
{% if row.variantTargetType %}
152+
<span class="badge badge-warning">Variant</span>
153+
{% else %}
154+
<span class="badge badge-info">Invariant</span>
155+
{% endif %}
156+
</td>
157+
<td>{{ row.class|abbr_class }}</td>
158+
</tr>
159+
{% endfor %}
160+
</table>
161+
</div>
162+
</div>
163+
{% endmacro %}
164+
127165
{% macro render_row(tracedata, depth) %}
128166
{% if depth == 0 %}
129167
<tr class="status-success">

0 commit comments

Comments
 (0)