Skip to content

Commit 3589b0e

Browse files
committed
Avoid using deprecated doctrine helpers for resolving classes
1 parent a788b8a commit 3589b0e

4 files changed

Lines changed: 156 additions & 8 deletions

File tree

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
1.4.1
2+
=====
3+
4+
* (improvement) Avoid using deprecated Doctrine internals when resolving class names.
5+
6+
17
1.4.0
28
=====
39

composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
"require-dev": {
2020
"21torr/janus": "^1.5.1",
2121
"bamarni/composer-bin-plugin": "^1.8.2",
22-
"doctrine/common": "^3.5",
22+
"doctrine/orm": "^3.0",
2323
"phpunit/phpunit": "^12.2.5",
2424
"roave/security-advisories": "dev-latest"
2525
},

src/Normalizer/SimpleNormalizer.php

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
namespace Torr\SimpleNormalizer\Normalizer;
44

55
use Doctrine\Common\Util\ClassUtils;
6+
use Doctrine\ORM\EntityManagerInterface;
7+
use Doctrine\ORM\Mapping\ClassMetadataFactory;
68
use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException;
79
use Symfony\Component\DependencyInjection\ServiceLocator;
810
use Torr\SimpleNormalizer\Exception\ObjectTypeNotSupportedException;
@@ -23,14 +25,20 @@
2325
*/
2426
class SimpleNormalizer
2527
{
28+
private readonly ?ClassMetadataFactory $doctrineMetadata;
29+
2630
/**
2731
* @param ServiceLocator<SimpleObjectNormalizerInterface> $objectNormalizers
2832
*/
2933
public function __construct (
3034
private readonly ServiceLocator $objectNormalizers,
3135
private readonly bool $isDebug = false,
3236
private readonly ?ValidJsonVerifier $validJsonVerifier = null,
33-
) {}
37+
?EntityManagerInterface $entityManager = null,
38+
)
39+
{
40+
$this->doctrineMetadata = $entityManager?->getMetadataFactory();
41+
}
3442

3543
/**
3644
*/
@@ -104,12 +112,7 @@ private function recursiveNormalize (mixed $value, array $context = []) : mixed
104112

105113
try
106114
{
107-
$className = $value::class;
108-
109-
if (class_exists(ClassUtils::class))
110-
{
111-
$className = ClassUtils::getRealClass($className);
112-
}
115+
$className = $this->normalizeClassName($value::class);
113116

114117
$normalizer = $this->objectNormalizers->get($className);
115118
\assert($normalizer instanceof SimpleObjectNormalizerInterface);
@@ -131,6 +134,22 @@ private function recursiveNormalize (mixed $value, array $context = []) : mixed
131134
));
132135
}
133136

137+
/**
138+
* Normalizes the class name
139+
*/
140+
private function normalizeClassName (string $className) : string
141+
{
142+
// if there is no doctrine, just return
143+
if (null === $this->doctrineMetadata)
144+
{
145+
return $className;
146+
}
147+
148+
return $this->doctrineMetadata->hasMetadataFor($className)
149+
? $this->doctrineMetadata->getMetadataFor($className)->getName()
150+
: $className;
151+
}
152+
134153
/**
135154
* The actual customized normalization logic for arrays, that recursively normalizes the value.
136155
* It must never call one of the public methods above and just normalizes the value.

tests/Normalizer/SimpleNormalizerTest.php

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22

33
namespace Tests\Torr\SimpleNormalizer\Normalizer;
44

5+
use Doctrine\ORM\EntityManagerInterface;
6+
use Doctrine\ORM\Mapping\ClassMetadata;
7+
use Doctrine\ORM\Mapping\ClassMetadataFactory;
58
use PHPUnit\Framework\Attributes\DataProvider;
69
use PHPUnit\Framework\TestCase;
710
use Symfony\Component\DependencyInjection\ServiceLocator;
@@ -124,6 +127,126 @@ public function testInvalidNestedNormalizer () : void
124127
]);
125128
}
126129

130+
/**
131+
*/
132+
public function testWithoutEntityManager () : void
133+
{
134+
$locator = $this->createMock(ServiceLocator::class);
135+
136+
$locator->expects(self::once())
137+
->method("get")
138+
->with(DummyVO::class)
139+
->willReturn(new readonly class implements SimpleObjectNormalizerInterface {
140+
public function normalize (object $value, array $context, SimpleNormalizer $normalizer) : int
141+
{
142+
return 5;
143+
}
144+
145+
public static function getNormalizedType () : string
146+
{
147+
return DummyVO::class;
148+
}
149+
});
150+
151+
$normalizer = new SimpleNormalizer(
152+
objectNormalizers: $locator,
153+
isDebug: true,
154+
validJsonVerifier: new ValidJsonVerifier(),
155+
);
156+
157+
$normalizer->normalize(new DummyVO(5));
158+
}
159+
160+
/**
161+
*/
162+
public function testWithEntityManagerButNoMapping () : void
163+
{
164+
$metadataFactory = $this->createMock(ClassMetadataFactory::class);
165+
$metadataFactory
166+
->expects(self::once())
167+
->method("hasMetadataFor")
168+
->with(DummyVO::class)
169+
->willReturn(false);
170+
171+
$entityManager = $this->createMock(EntityManagerInterface::class);
172+
$entityManager->method("getMetadataFactory")->willReturn($metadataFactory);
173+
174+
$locator = $this->createMock(ServiceLocator::class);
175+
176+
$locator->expects(self::once())
177+
->method("get")
178+
->with(DummyVO::class)
179+
->willReturn(new readonly class implements SimpleObjectNormalizerInterface {
180+
public function normalize (object $value, array $context, SimpleNormalizer $normalizer) : int
181+
{
182+
return 5;
183+
}
184+
185+
public static function getNormalizedType () : string
186+
{
187+
return DummyVO::class;
188+
}
189+
});
190+
191+
$normalizer = new SimpleNormalizer(
192+
objectNormalizers: $locator,
193+
isDebug: true,
194+
validJsonVerifier: new ValidJsonVerifier(),
195+
entityManager: $entityManager,
196+
);
197+
198+
$normalizer->normalize(new DummyVO(5));
199+
}
200+
201+
/**
202+
*/
203+
public function testWithEntityManagerWithMapping () : void
204+
{
205+
$classMetaData = new ClassMetadata("SomeClass");
206+
207+
$metadataFactory = $this->createMock(ClassMetadataFactory::class);
208+
$metadataFactory
209+
->expects(self::once())
210+
->method("hasMetadataFor")
211+
->with(DummyVO::class)
212+
->willReturn(true);
213+
214+
$metadataFactory
215+
->expects(self::once())
216+
->method("getMetadataFor")
217+
->with(DummyVO::class)
218+
->willReturn($classMetaData);
219+
220+
$entityManager = $this->createMock(EntityManagerInterface::class);
221+
$entityManager->method("getMetadataFactory")->willReturn($metadataFactory);
222+
223+
$locator = $this->createMock(ServiceLocator::class);
224+
225+
$locator->expects(self::once())
226+
->method("get")
227+
->with("SomeClass")
228+
->willReturn(new readonly class implements SimpleObjectNormalizerInterface {
229+
public function normalize (object $value, array $context, SimpleNormalizer $normalizer) : int
230+
{
231+
return 5;
232+
}
233+
234+
public static function getNormalizedType () : string
235+
{
236+
return DummyVO::class;
237+
}
238+
});
239+
240+
$normalizer = new SimpleNormalizer(
241+
objectNormalizers: $locator,
242+
isDebug: true,
243+
validJsonVerifier: new ValidJsonVerifier(),
244+
entityManager: $entityManager,
245+
);
246+
247+
$normalizer->normalize(new DummyVO(5));
248+
}
249+
127250
/**
128251
* @return ServiceLocator<mixed>
129252
*/

0 commit comments

Comments
 (0)