Skip to content

Commit b8d9631

Browse files
[DoctrineBridge] Map entities by single-key when disabling auto-mapping
1 parent 069af99 commit b8d9631

File tree

3 files changed

+92
-3
lines changed

3 files changed

+92
-3
lines changed

src/Symfony/Bridge/Doctrine/ArgumentResolver/EntityValueResolver.php

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -123,15 +123,21 @@ private function getIdentifier(Request $request, MapEntity $options, string $nam
123123
{
124124
if (\is_array($options->id)) {
125125
$id = [];
126+
$usedAttributes = [];
126127
foreach ($options->id as $field) {
127128
// Convert "%s_uuid" to "foobar_uuid"
128129
if (str_contains($field, '%s')) {
129130
$field = sprintf($field, $name);
130131
}
131132

133+
$usedAttributes[] = $field;
132134
$id[$field] = $request->attributes->get($field);
133135
}
134136

137+
if ($usedAttributes) {
138+
$request->attributes->set('_entity_used_attributes', array_merge($request->attributes->get('_entity_used_attributes') ?? [], $usedAttributes));
139+
}
140+
135141
return $id;
136142
}
137143

@@ -140,10 +146,14 @@ private function getIdentifier(Request $request, MapEntity $options, string $nam
140146
}
141147

142148
if ($request->attributes->has($name)) {
149+
$request->attributes->set('_entity_used_attributes', array_merge($request->attributes->get('_entity_used_attributes') ?? [], [$name]));
150+
143151
return $request->attributes->get($name) ?? ($options->stripNull ? false : null);
144152
}
145153

146154
if (!$options->id && $request->attributes->has('id')) {
155+
$request->attributes->set('_entity_used_attributes', array_merge($request->attributes->get('_entity_used_attributes') ?? [], ['id']));
156+
147157
return $request->attributes->get('id') ?? ($options->stripNull ? false : null);
148158
}
149159

@@ -152,11 +162,15 @@ private function getIdentifier(Request $request, MapEntity $options, string $nam
152162

153163
private function getCriteria(Request $request, MapEntity $options, ObjectManager $manager): array
154164
{
155-
if (null === $mapping = $options->mapping) {
156-
$mapping = $request->attributes->keys();
165+
$singleKey = [] === $options->mapping;
166+
167+
if (!$mapping = $options->mapping) {
168+
$mapping = $request->attributes->all();
169+
unset($mapping['_entity_used_attributes']);
170+
$mapping = array_keys($mapping);
157171
}
158172

159-
if ($mapping && \is_array($mapping) && array_is_list($mapping)) {
173+
if ($mapping && array_is_list($mapping)) {
160174
$mapping = array_combine($mapping, $mapping);
161175
}
162176

@@ -176,13 +190,29 @@ private function getCriteria(Request $request, MapEntity $options, ObjectManager
176190

177191
$criteria = [];
178192
$metadata = $manager->getClassMetadata($options->class);
193+
$usedAttributes = [];
194+
195+
if ($singleKey) {
196+
foreach ($request->attributes->get('_entity_used_attributes') ?? [] as $attribute) {
197+
unset($mapping[$attribute]);
198+
}
199+
}
179200

180201
foreach ($mapping as $attribute => $field) {
181202
if (!$metadata->hasField($field) && (!$metadata->hasAssociation($field) || !$metadata->isSingleValuedAssociation($field))) {
182203
continue;
183204
}
184205

206+
$usedAttributes[] = $attribute;
185207
$criteria[$field] = $request->attributes->get($attribute);
208+
209+
if ($singleKey) {
210+
break;
211+
}
212+
}
213+
214+
if ($usedAttributes) {
215+
$request->attributes->set('_entity_used_attributes', array_merge($request->attributes->get('_entity_used_attributes') ?? [], $usedAttributes));
186216
}
187217

188218
if ($options->stripNull) {

src/Symfony/Bridge/Doctrine/CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
CHANGELOG
22
=========
33

4+
7.1
5+
---
6+
7+
* Map entities by single-key when disabling auto-mapping
8+
49
7.0
510
---
611

src/Symfony/Bridge/Doctrine/Tests/ArgumentResolver/EntityValueResolverTest.php

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,60 @@ public function testResolveWithMappingAndExclude()
257257
$this->assertSame([$object], $resolver->resolve($request, $argument));
258258
}
259259

260+
public function testResolveWithMultipleEntitiesAndNoAutoMapping()
261+
{
262+
$manager = $this->getMockBuilder(ObjectManager::class)->getMock();
263+
$registry = $this->createRegistry($manager);
264+
$resolver = new EntityValueResolver($registry);
265+
266+
$request = new Request();
267+
$request->attributes->set('foo', 1);
268+
$request->attributes->set('bar', 2);
269+
270+
$argument1 = $this->createArgument('Foo', new MapEntity('Foo', mapping: []));
271+
$argument2 = $this->createArgument('Bar', new MapEntity('Bar', mapping: []));
272+
273+
$metadata1 = $this->getMockBuilder(ClassMetadata::class)->getMock();
274+
$metadata1->expects($this->once())
275+
->method('hasField')
276+
->with('foo')
277+
->willReturn(true);
278+
279+
$metadata2 = $this->getMockBuilder(ClassMetadata::class)->getMock();
280+
$metadata2->expects($this->once())
281+
->method('hasField')
282+
->with('bar')
283+
->willReturn(true);
284+
285+
$manager->expects($this->any())
286+
->method('getClassMetadata')
287+
->willReturnCallback(static fn ($v) => match ($v) {
288+
'Foo' => $metadata1,
289+
'Bar' => $metadata2,
290+
});
291+
292+
$object1 = new \stdClass();
293+
$object2 = new \stdClass();
294+
295+
$repository = $this->getMockBuilder(ObjectRepository::class)->getMock();
296+
$repository->expects($this->any())
297+
->method('findOneBy')
298+
->willReturnCallback(static fn ($v) => match ($v) {
299+
['foo' => 1] => $object1,
300+
['bar' => 2] => $object2,
301+
});
302+
303+
$manager->expects($this->any())
304+
->method('getRepository')
305+
->willReturn($repository);
306+
307+
$this->assertSame([$object1], $resolver->resolve($request, $argument1));
308+
$this->assertSame(['foo'], $request->attributes->get('_entity_used_attributes'));
309+
310+
$this->assertSame([$object2], $resolver->resolve($request, $argument2));
311+
$this->assertSame(['foo', 'bar'], $request->attributes->get('_entity_used_attributes'));
312+
}
313+
260314
public function testExceptionWithExpressionIfNoLanguageAvailable()
261315
{
262316
$manager = $this->getMockBuilder(ObjectManager::class)->getMock();

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy