Skip to content

Commit 81c0d59

Browse files
committed
Implement compatibility with Persistence 4
1 parent 0f11a97 commit 81c0d59

15 files changed

+139
-28
lines changed

composer.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
"doctrine/inflector": "^1.4 || ^2.0",
3232
"doctrine/instantiator": "^1.3 || ^2",
3333
"doctrine/lexer": "^3",
34-
"doctrine/persistence": "^3.3.1",
34+
"doctrine/persistence": "^3.3.1 || ^4",
3535
"psr/cache": "^1 || ^2 || ^3",
3636
"symfony/console": "^5.4 || ^6.0 || ^7.0",
3737
"symfony/var-exporter": "^6.3.9 || ^7.0"

phpcs.xml.dist

+2
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,8 @@
4848
</rule>
4949

5050
<rule ref="PSR1.Classes.ClassDeclaration.MultipleClasses">
51+
<exclude-pattern>src/Mapping/Driver/LoadMappingFileImplementation.php</exclude-pattern>
52+
<exclude-pattern>src/Mapping/GetReflectionClassImplementation.php</exclude-pattern>
5153
<exclude-pattern>tests/*</exclude-pattern>
5254
</rule>
5355

phpstan-baseline.neon

+5
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,11 @@ parameters:
120120
count: 1
121121
path: src/EntityRepository.php
122122

123+
-
124+
message: "#^If condition is always true\\.$#"
125+
count: 1
126+
path: src/Mapping/ClassMetadata.php
127+
123128
-
124129
message: "#^If condition is always true\\.$#"
125130
count: 1

phpstan-dbal3.neon

+5
Original file line numberDiff line numberDiff line change
@@ -34,3 +34,8 @@ parameters:
3434
-
3535
message: '~deprecated class Doctrine\\DBAL\\Tools\\Console\\Command\\ReservedWordsCommand\:~'
3636
path: src/Tools/Console/ConsoleRunner.php
37+
38+
# Compatibility with Persistence 3
39+
-
40+
message: '#Expression on left side of \?\? is not nullable.#'
41+
path: src/Mapping/Driver/AttributeDriver.php

phpstan.neon

+5
Original file line numberDiff line numberDiff line change
@@ -45,3 +45,8 @@ parameters:
4545
message: '#Negated boolean expression is always false\.#'
4646
paths:
4747
- src/Mapping/Driver/AttributeDriver.php
48+
49+
# Compatibility with Persistence 3
50+
-
51+
message: '#Expression on left side of \?\? is not nullable.#'
52+
path: src/Mapping/Driver/AttributeDriver.php

psalm-baseline.xml

+17-6
Original file line numberDiff line numberDiff line change
@@ -298,15 +298,9 @@
298298
<code><![CDATA[$mapping]]></code>
299299
<code><![CDATA[$overrideMapping]]></code>
300300
</InvalidArgument>
301-
<InvalidNullableReturnType>
302-
<code><![CDATA[ReflectionClass|null]]></code>
303-
</InvalidNullableReturnType>
304301
<InvalidPropertyAssignmentValue>
305302
<code><![CDATA[$definition]]></code>
306303
</InvalidPropertyAssignmentValue>
307-
<NullableReturnStatement>
308-
<code><![CDATA[$this->reflClass]]></code>
309-
</NullableReturnStatement>
310304
<ParamNameMismatch>
311305
<code><![CDATA[$entity]]></code>
312306
</ParamNameMismatch>
@@ -340,6 +334,7 @@
340334
<RedundantCondition>
341335
<code><![CDATA[$mapping !== false]]></code>
342336
<code><![CDATA[$mapping !== false]]></code>
337+
<code><![CDATA[$this->reflClass]]></code>
343338
</RedundantCondition>
344339
<RedundantFunctionCall>
345340
<code><![CDATA[array_values]]></code>
@@ -474,6 +469,14 @@
474469
<code><![CDATA[getIndexes]]></code>
475470
</PossiblyNullReference>
476471
</file>
472+
<file src="src/Mapping/Driver/LoadMappingFileImplementation.php">
473+
<LessSpecificImplementedReturnType>
474+
<code><![CDATA[array]]></code>
475+
</LessSpecificImplementedReturnType>
476+
<MissingParamType>
477+
<code><![CDATA[$file]]></code>
478+
</MissingParamType>
479+
</file>
477480
<file src="src/Mapping/Driver/SimplifiedXmlDriver.php">
478481
<MissingParamType>
479482
<code><![CDATA[$fileExtension]]></code>
@@ -526,6 +529,14 @@
526529
<code><![CDATA[$metadata]]></code>
527530
</MoreSpecificImplementedParamType>
528531
</file>
532+
<file src="src/Mapping/GetReflectionClassImplementation.php">
533+
<ImplementedReturnTypeMismatch>
534+
<code><![CDATA[ReflectionClass]]></code>
535+
</ImplementedReturnTypeMismatch>
536+
<InvalidNullableReturnType>
537+
<code><![CDATA[ReflectionClass]]></code>
538+
</InvalidNullableReturnType>
539+
</file>
529540
<file src="src/Mapping/ManyToManyInverseSideMapping.php">
530541
<PropertyNotSetInConstructor>
531542
<code><![CDATA[ManyToManyInverseSideMapping]]></code>

src/EntityManager.php

+2-2
Original file line numberDiff line numberDiff line change
@@ -565,9 +565,9 @@ public function initializeObject(object $obj): void
565565
/**
566566
* {@inheritDoc}
567567
*/
568-
public function isUninitializedObject($obj): bool
568+
public function isUninitializedObject($value): bool
569569
{
570-
return $this->unitOfWork->isUninitializedObject($obj);
570+
return $this->unitOfWork->isUninitializedObject($value);
571571
}
572572

573573
public function getFilters(): FilterCollection

src/Mapping/ClassMetadata.php

+2-10
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,8 @@
7373
*/
7474
class ClassMetadata implements PersistenceClassMetadata, Stringable
7575
{
76+
use GetReflectionClassImplementation;
77+
7678
/* The inheritance mapping types */
7779
/**
7880
* NONE means the class does not participate in an inheritance hierarchy
@@ -932,16 +934,6 @@ public function validateLifecycleCallbacks(ReflectionService $reflService): void
932934
}
933935
}
934936

935-
/**
936-
* {@inheritDoc}
937-
*
938-
* Can return null when using static reflection, in violation of the LSP
939-
*/
940-
public function getReflectionClass(): ReflectionClass|null
941-
{
942-
return $this->reflClass;
943-
}
944-
945937
/** @psalm-param array{usage?: mixed, region?: mixed} $cache */
946938
public function enableCache(array $cache): void
947939
{
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Doctrine\ORM\Mapping\Driver;
6+
7+
use Doctrine\Persistence\Mapping\StaticReflectionService;
8+
9+
use function class_exists;
10+
11+
if (! class_exists(StaticReflectionService::class)) {
12+
/** @internal */
13+
trait LoadMappingFileImplementation
14+
{
15+
/**
16+
* {@inheritDoc}
17+
*/
18+
protected function loadMappingFile($file): array
19+
{
20+
return $this->doLoadMappingFile($file);
21+
}
22+
}
23+
} else {
24+
/** @internal */
25+
trait LoadMappingFileImplementation
26+
{
27+
/**
28+
* {@inheritDoc}
29+
*/
30+
protected function loadMappingFile($file)
31+
{
32+
return $this->doLoadMappingFile($file);
33+
}
34+
}
35+
}

src/Mapping/Driver/XmlDriver.php

+4-4
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@
4343
*/
4444
class XmlDriver extends FileDriver
4545
{
46+
use LoadMappingFileImplementation;
47+
4648
public const DEFAULT_FILE_EXTENSION = '.dcm.xml';
4749

4850
/**
@@ -878,10 +880,8 @@ private function getCascadeMappings(SimpleXMLElement $cascadeElement): array
878880
return $cascades;
879881
}
880882

881-
/**
882-
* {@inheritDoc}
883-
*/
884-
protected function loadMappingFile($file)
883+
/** @return array<class-string, SimpleXMLElement> */
884+
private function doLoadMappingFile(string $file): array
885885
{
886886
$this->validateMapping($file);
887887
$result = [];
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Doctrine\ORM\Mapping;
6+
7+
use Doctrine\Persistence\Mapping\StaticReflectionService;
8+
use ReflectionClass;
9+
10+
use function class_exists;
11+
12+
if (! class_exists(StaticReflectionService::class)) {
13+
trait GetReflectionClassImplementation
14+
{
15+
public function getReflectionClass(): ReflectionClass
16+
{
17+
return $this->reflClass;
18+
}
19+
}
20+
} else {
21+
trait GetReflectionClassImplementation
22+
{
23+
/**
24+
* {@inheritDoc}
25+
*
26+
* Can return null when using static reflection, in violation of the LSP
27+
*/
28+
public function getReflectionClass(): ReflectionClass|null
29+
{
30+
return $this->reflClass;
31+
}
32+
}
33+
}

tests/Performance/Mock/NonProxyLoadingEntityManager.php

+8
Original file line numberDiff line numberDiff line change
@@ -212,4 +212,12 @@ public function contains(object $object): bool
212212
{
213213
return $this->realEntityManager->contains($object);
214214
}
215+
216+
/**
217+
* {@inheritDoc}
218+
*/
219+
public function isUninitializedObject($value): bool
220+
{
221+
return $this->realEntityManager->isUninitializedObject($value);
222+
}
215223
}

tests/Tests/Mocks/MetadataDriverMock.php

+3-3
Original file line numberDiff line numberDiff line change
@@ -15,22 +15,22 @@ class MetadataDriverMock implements MappingDriver
1515
/**
1616
* {@inheritDoc}
1717
*/
18-
public function loadMetadataForClass($className, ClassMetadata $metadata)
18+
public function loadMetadataForClass($className, ClassMetadata $metadata): void
1919
{
2020
}
2121

2222
/**
2323
* {@inheritDoc}
2424
*/
25-
public function isTransient($className)
25+
public function isTransient($className): bool
2626
{
2727
return false;
2828
}
2929

3030
/**
3131
* {@inheritDoc}
3232
*/
33-
public function getAllClassNames()
33+
public function getAllClassNames(): array
3434
{
3535
return [];
3636
}

tests/Tests/ORM/Functional/Ticket/DDC3103Test.php

+12-2
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,28 @@
77
use Doctrine\ORM\Mapping\ClassMetadata;
88
use Doctrine\ORM\Mapping\Column;
99
use Doctrine\ORM\Mapping\Embeddable;
10+
use Doctrine\Persistence\Mapping\StaticReflectionService;
1011
use Doctrine\Tests\OrmFunctionalTestCase;
1112
use PHPUnit\Framework\Attributes\CoversClass;
1213
use PHPUnit\Framework\Attributes\Group;
1314

15+
use function class_exists;
1416
use function serialize;
1517
use function unserialize;
1618

1719
#[CoversClass(ClassMetadata::class)]
1820
#[Group('DDC-3103')]
1921
class DDC3103Test extends OrmFunctionalTestCase
2022
{
23+
protected function setUp(): void
24+
{
25+
if (! class_exists(StaticReflectionService::class)) {
26+
self::markTestSkipped('This test is not supported by the current installed doctrine/persistence version');
27+
}
28+
29+
parent::setUp();
30+
}
31+
2132
public function testIssue(): void
2233
{
2334
$classMetadata = new ClassMetadata(DDC3103ArticleId::class);
@@ -39,7 +50,6 @@ public function testIssue(): void
3950
#[Embeddable]
4051
class DDC3103ArticleId
4152
{
42-
/** @var string */
4353
#[Column(name: 'name', type: 'string', length: 255)]
44-
protected $nameValue;
54+
protected string $nameValue;
4555
}

tests/Tests/ORM/Mapping/ClassMetadataTest.php

+5
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@
5656
use stdClass;
5757

5858
use function assert;
59+
use function class_exists;
5960
use function count;
6061
use function serialize;
6162
use function str_contains;
@@ -979,6 +980,10 @@ public function testCanInstantiateInternalPhpClassSubclassFromUnserializedMetada
979980

980981
public function testWakeupReflectionWithEmbeddableAndStaticReflectionService(): void
981982
{
983+
if (! class_exists(StaticReflectionService::class)) {
984+
self::markTestSkipped('This test is not supported by the current installed doctrine/persistence version');
985+
}
986+
982987
$classMetadata = new ClassMetadata(TestEntity1::class);
983988

984989
$classMetadata->mapEmbedded(

0 commit comments

Comments
 (0)