Skip to content

Commit ea34077

Browse files
committed
ai performance improvements
1 parent 8b79f21 commit ea34077

10 files changed

Lines changed: 215 additions & 97 deletions

src/Extension/Cryptography/CryptographyMetadataEnricher.php

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,14 @@ final class CryptographyMetadataEnricher implements MetadataEnricher
1717
public function enrich(ClassMetadata $classMetadata): void
1818
{
1919
$subjectIdMapping = [];
20+
$subjectIdProperties = [];
21+
$sensitiveProperties = [];
2022

2123
foreach ($classMetadata->properties as $property) {
2224
$isSubjectId = false;
2325
$attributeReflectionList = $property->reflection->getAttributes(DataSubjectId::class);
2426

25-
if ($attributeReflectionList) {
27+
if ($attributeReflectionList !== []) {
2628
$subjectIdIdentifier = $attributeReflectionList[0]->newInstance()->name;
2729

2830
if (array_key_exists($subjectIdIdentifier, $subjectIdMapping)) {
@@ -35,6 +37,7 @@ public function enrich(ClassMetadata $classMetadata): void
3537
}
3638

3739
$subjectIdMapping[$subjectIdIdentifier] = $property->fieldName;
40+
$subjectIdProperties[$subjectIdIdentifier] = $property;
3841

3942
$isSubjectId = true;
4043
}
@@ -50,13 +53,17 @@ public function enrich(ClassMetadata $classMetadata): void
5053
}
5154

5255
$property->extras[SensitiveDataInfo::class] = $sensitiveDataInfo;
56+
$sensitiveProperties[] = $property;
5357
}
5458

55-
if ($subjectIdMapping === []) {
56-
return;
59+
if ($sensitiveProperties !== []) {
60+
$classMetadata->extras[SensitiveDataInfo::class . '::properties'] = $sensitiveProperties;
5761
}
5862

59-
$classMetadata->extras[SubjectIdFieldMapping::class] = new SubjectIdFieldMapping($subjectIdMapping);
63+
if ($subjectIdMapping !== []) {
64+
$classMetadata->extras[SubjectIdFieldMapping::class] = new SubjectIdFieldMapping($subjectIdMapping);
65+
$classMetadata->extras[SubjectIdFieldMapping::class . '::properties'] = $subjectIdProperties;
66+
}
6067
}
6168

6269
private function sensitiveDataInfo(ReflectionProperty $reflectionProperty): SensitiveDataInfo|null

src/Extension/Cryptography/CryptographyMiddleware.php

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -36,39 +36,48 @@ public function __construct(
3636
*/
3737
public function hydrate(ClassMetadata $metadata, array $data, array $context, Stack $stack): object
3838
{
39+
/** @var list<PropertyMetadata>|null $properties */
40+
$properties = $metadata->extras[SensitiveDataInfo::class . '::properties'] ?? null;
41+
42+
if ($properties === null) {
43+
return $stack->next()->hydrate($metadata, $data, $context, $stack);
44+
}
45+
3946
$context[SubjectIds::class] = $subjectIds = $this->resolveSubjectIds($metadata, $data, $context);
47+
$cryptographer = $this->cryptographer;
4048

41-
foreach ($metadata->properties as $propertyMetadata) {
42-
$info = $propertyMetadata->extras[SensitiveDataInfo::class] ?? null;
49+
foreach ($properties as $propertyMetadata) {
50+
$fieldName = $propertyMetadata->fieldName;
4351

44-
if (!$info instanceof SensitiveDataInfo) {
52+
if (!isset($data[$fieldName])) {
4553
continue;
4654
}
4755

48-
$value = $data[$propertyMetadata->fieldName] ?? null;
56+
$value = $data[$fieldName];
4957

50-
if ($value === null) {
58+
if (!$cryptographer->supports($value)) {
5159
continue;
5260
}
5361

54-
if (!$this->cryptographer->supports($value)) {
55-
continue;
56-
}
62+
$info = $propertyMetadata->extras[SensitiveDataInfo::class];
63+
assert($info instanceof SensitiveDataInfo);
5764

5865
$subjectId = $subjectIds->get($info->subjectIdName);
5966

6067
try {
61-
$data[$propertyMetadata->fieldName] = $this->cryptographer->decrypt($subjectId, $value);
68+
$data[$fieldName] = $cryptographer->decrypt($subjectId, $value);
6269
} catch (DecryptionFailed | CipherKeyNotExists) {
6370
$fallback = $info->fallback instanceof Closure
6471
? ($info->fallback)($subjectId)
6572
: $info->fallback;
6673

67-
if ($propertyMetadata->normalizer) {
68-
$fallback = $propertyMetadata->normalizer->normalize($fallback, $context);
74+
$normalizer = $propertyMetadata->normalizer;
75+
76+
if ($normalizer !== null) {
77+
$fallback = $normalizer->normalize($fallback, $context);
6978
}
7079

71-
$data[$propertyMetadata->fieldName] = $fallback;
80+
$data[$fieldName] = $fallback;
7281
}
7382
}
7483

src/Metadata/ClassMetadata.php

Lines changed: 43 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,13 @@ final class ClassMetadata
2222
public readonly string $className;
2323

2424
/** @var array<string, PropertyMetadata> */
25-
public readonly array $properties;
25+
public array $properties;
26+
27+
/** @var list<PropertyMetadata> */
28+
public array $propertiesWithNormalizer;
29+
30+
/** @var list<PropertyMetadata> */
31+
public array $propertiesWithoutNormalizer;
2632

2733
/** @var array<string, ReflectionParameter>|null */
2834
private array|null $promotedConstructorDefaults = null;
@@ -40,13 +46,29 @@ public function __construct(
4046
) {
4147
$this->className = $reflection->getName();
4248

49+
$this->updateProperties($properties);
50+
}
51+
52+
/** @param list<PropertyMetadata> $properties */
53+
public function updateProperties(array $properties): void
54+
{
4355
$map = [];
56+
$withNormalizer = [];
57+
$withoutNormalizer = [];
4458

4559
foreach ($properties as $property) {
4660
$map[$property->propertyName] = $property;
61+
62+
if ($property->normalizer !== null) {
63+
$withNormalizer[] = $property;
64+
} else {
65+
$withoutNormalizer[] = $property;
66+
}
4767
}
4868

4969
$this->properties = $map;
70+
$this->propertiesWithNormalizer = $withNormalizer;
71+
$this->propertiesWithoutNormalizer = $withoutNormalizer;
5072
}
5173

5274
public function propertyForField(string $name): PropertyMetadata
@@ -97,7 +119,7 @@ public function __serialize(): array
97119
{
98120
return [
99121
'className' => $this->className,
100-
'properties' => $this->properties,
122+
'properties' => array_values($this->properties),
101123
'lazy' => $this->lazy,
102124
'extras' => $this->extras,
103125
];
@@ -107,7 +129,25 @@ public function __serialize(): array
107129
public function __unserialize(array $data): void
108130
{
109131
$this->reflection = new ReflectionClass($data['className']);
110-
$this->properties = $data['properties'];
132+
133+
$map = [];
134+
$withNormalizer = [];
135+
$withoutNormalizer = [];
136+
137+
foreach ($data['properties'] as $property) {
138+
$map[$property->propertyName] = $property;
139+
140+
if ($property->normalizer !== null) {
141+
$withNormalizer[] = $property;
142+
} else {
143+
$withoutNormalizer[] = $property;
144+
}
145+
}
146+
147+
$this->className = $data['className'];
148+
$this->properties = $map;
149+
$this->propertiesWithNormalizer = $withNormalizer;
150+
$this->propertiesWithoutNormalizer = $withoutNormalizer;
111151
$this->lazy = $data['lazy'];
112152
$this->extras = $data['extras'];
113153
}

src/Metadata/EnrichingMetadataFactory.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,14 @@ public function metadata(string $class): ClassMetadata
1717
{
1818
$metadata = $this->factory->metadata($class);
1919

20+
$enriched = false;
2021
foreach ($this->enrichers as $enricher) {
2122
$enricher->enrich($metadata);
23+
$enriched = true;
24+
}
25+
26+
if ($enriched) {
27+
$metadata->updateProperties(array_values($metadata->properties));
2228
}
2329

2430
return $metadata;

src/MetadataHydrator.php

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,15 @@ final class MetadataHydrator implements Hydrator
2323
/** @var array<class-string, ClassMetadata> */
2424
private array $classMetadata = [];
2525

26+
private readonly Stack $stack;
27+
2628
/** @param list<Middleware> $middlewares */
2729
public function __construct(
2830
private readonly MetadataFactory $metadataFactory = new AttributeMetadataFactory(),
2931
private readonly array $middlewares = [new TransformMiddleware()],
3032
private readonly bool $defaultLazy = false,
3133
) {
34+
$this->stack = new Stack($this->middlewares);
3235
}
3336

3437
/**
@@ -48,23 +51,21 @@ public function hydrate(string $class, array $data, array $context = []): object
4851
throw new ClassNotSupported($class, $e);
4952
}
5053

51-
if (PHP_VERSION_ID < 80400) {
52-
$stack = new Stack($this->middlewares);
54+
$stack = clone $this->stack;
5355

56+
if (PHP_VERSION_ID < 80400) {
5457
return $stack->next()->hydrate($metadata, $data, $context, $stack);
5558
}
5659

5760
$lazy = $metadata->lazy ?? $this->defaultLazy;
5861

5962
if (!$lazy) {
60-
$stack = new Stack($this->middlewares);
61-
6263
return $stack->next()->hydrate($metadata, $data, $context, $stack);
6364
}
6465

6566
return (new ReflectionClass($class))->newLazyProxy(
6667
function () use ($metadata, $data, $context): object {
67-
$stack = new Stack($this->middlewares);
68+
$stack = clone $this->stack;
6869

6970
return $stack->next()->hydrate($metadata, $data, $context, $stack);
7071
},
@@ -79,7 +80,7 @@ function () use ($metadata, $data, $context): object {
7980
public function extract(object $object, array $context = []): array
8081
{
8182
$metadata = $this->metadata($object::class);
82-
$stack = new Stack($this->middlewares);
83+
$stack = clone $this->stack;
8384

8485
return $stack->next()->extract($metadata, $object, $context, $stack);
8586
}
@@ -93,18 +94,18 @@ public function extract(object $object, array $context = []): array
9394
*/
9495
public function metadata(string $class): ClassMetadata
9596
{
96-
if (array_key_exists($class, $this->classMetadata)) {
97+
if (isset($this->classMetadata[$class])) {
9798
return $this->classMetadata[$class];
9899
}
99100

100101
$this->classMetadata[$class] = $metadata = $this->metadataFactory->metadata($class);
101102

102103
foreach ($metadata->properties as $property) {
103-
if (!($property->normalizer instanceof HydratorAwareNormalizer)) {
104-
continue;
105-
}
104+
$normalizer = $property->normalizer;
106105

107-
$property->normalizer->setHydrator($this);
106+
if ($normalizer instanceof HydratorAwareNormalizer) {
107+
$normalizer->setHydrator($this);
108+
}
108109
}
109110

110111
return $metadata;

src/Middleware/Stack.php

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,6 @@ public function __construct(
1616

1717
public function next(): Middleware
1818
{
19-
$next = $this->middlewares[$this->index] ?? null;
20-
21-
if ($next === null) {
22-
throw new NoMoreMiddleware();
23-
}
24-
25-
$this->index++;
26-
27-
return $next;
19+
return $this->middlewares[$this->index++] ?? throw new NoMoreMiddleware();
2820
}
2921
}

0 commit comments

Comments
 (0)