Skip to content

Commit b8926ae

Browse files
authored
Deprecate not overriding Type::closureToPHP() (#2960)
The default implementation of Type::closureToPhp() is incorrect as it forwards the unmodified value. In 3.0, I want to change the default implementation to use the one from the ClosureToPHP trait that calls the type class. Also adding the missing implementation for collection and hash. Any type that does not override the closureToPhp will get a deprecation notice.
1 parent 80a032a commit b8926ae

File tree

10 files changed

+70
-1
lines changed

10 files changed

+70
-1
lines changed

UPGRADE-2.16.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,16 @@ be supported in MongoDB ODM 3.0.
1414
Calling `Doctrine\ODM\MongoDB\Configuration::setProxyDir()` or
1515
`Doctrine\ODM\MongoDB\Configuration::getProxyDir()` is deprecated and triggers
1616
a deprecation notice when using native lazy objects.
17+
18+
## Override `Type::closureToPHP()` for custom type classes
19+
20+
The default implementation of `Doctrine\ODM\MongoDB\Types\Type::closureToPHP()`
21+
will change in MongoDB ODM 3.0 to call `convertToPHPValue()`. If you have custom
22+
type classes, use the `Doctrine\ODM\MongoDB\Types\ClosureToPHP` trait or
23+
implement `closureToPHP()`.
24+
25+
## Deprecate `Type::closureToMongo()`
26+
27+
The method `Doctrine\ODM\MongoDB\Types\Type::closureToMongo()` is not used,
28+
and will be removed in MongoDB ODM 3.0. Don't call this method, but use
29+
`convertToDatabaseValue()` instead.

src/Types/ClosureToPHP.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
use function sprintf;
88

9+
/** This trait will be deprecated in 3.0 as this behavior will be used by default */
910
trait ClosureToPHP
1011
{
1112
/** @return string Redirects to the method convertToPHPValue from child class */

src/Types/CollectionType.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,4 +29,9 @@ public function convertToPHPValue($value)
2929
{
3030
return $value !== null ? array_values($value) : null;
3131
}
32+
33+
public function closureToPHP(): string
34+
{
35+
return '$return = array_values($value);';
36+
}
3237
}

src/Types/HashType.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,4 +28,9 @@ public function convertToPHPValue($value)
2828
{
2929
return $value !== null ? (array) $value : null;
3030
}
31+
32+
public function closureToPHP(): string
33+
{
34+
return '$return = (array) $value;';
35+
}
3136
}

src/Types/KeyType.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
*/
1313
class KeyType extends Type
1414
{
15+
use ClosureToPHP;
16+
1517
/** @return MinKey|MaxKey|null */
1618
public function convertToDatabaseValue($value)
1719
{

src/Types/TimestampType.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
*/
1515
class TimestampType extends Type
1616
{
17+
use ClosureToPHP;
18+
1719
/** @return Timestamp|null */
1820
public function convertToDatabaseValue($value)
1921
{

src/Types/Type.php

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
use function gettype;
1616
use function is_object;
1717
use function str_replace;
18+
use function trigger_deprecation;
1819

1920
/**
2021
* The Type interface.
@@ -129,18 +130,26 @@ public function convertToPHPValue($value)
129130
/**
130131
* Get the PHP code equivalent to {@see convertToDatabaseValue()}, used in code generator.
131132
* Use variables $value for input and $return for output.
133+
*
134+
* @deprecated Since 2.16, will be removed in 3.0.
132135
*/
133136
public function closureToMongo(): string
134137
{
138+
trigger_deprecation('doctrine/mongodb-odm', '2.16', 'Type::closureToMongo() is deprecated and will be removed in 3.0.');
139+
135140
return '$return = $value;';
136141
}
137142

138143
/**
139144
* Get the PHP code equivalent to {@see convertToPHPValue()}, used in code generator.
140145
* Use variables $value for input and $return for output.
146+
*
147+
* @abstract The default implementation will change in 3.0.
141148
*/
142149
public function closureToPHP(): string
143150
{
151+
trigger_deprecation('doctrine/mongodb-odm', '2.16', 'The method Type::closureToPHP() will change its default implementation in 3.0 to use convertToPHPValue(). Override this method if you need custom behavior before upgrading to 3.0 or use the trait ClosureToPHP to get the upcoming behavior now.');
152+
144153
return '$return = $value;';
145154
}
146155

tests/Tests/CaptureDeprecationMessages.php

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,13 @@ trait CaptureDeprecationMessages
1616
* This method can be replaced with expectUserDeprecationMessage() in PHPUnit 11+.
1717
* https://docs.phpunit.de/en/11.1/error-handling.html#expecting-deprecations-e-user-deprecated
1818
*
19-
* @param list<string> $errors
19+
* @param callable(): T $callable
20+
* @param list<string> $errors
21+
*
22+
* @return T
2023
*
2124
* @param-out list<string> $errors
25+
* @template T
2226
*/
2327
private function captureDeprecationMessages(callable $callable, ?array &$errors): mixed
2428
{

tests/Tests/Functional/CustomTypeTest.php

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
use DateTime;
88
use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM;
99
use Doctrine\ODM\MongoDB\Tests\BaseTestCase;
10+
use Doctrine\ODM\MongoDB\Tests\CaptureDeprecationMessages;
1011
use Doctrine\ODM\MongoDB\Types\ClosureToPHP;
1112
use Doctrine\ODM\MongoDB\Types\Type;
1213
use Exception;
@@ -20,12 +21,15 @@
2021

2122
class CustomTypeTest extends BaseTestCase
2223
{
24+
use CaptureDeprecationMessages;
25+
2326
public function setUp(): void
2427
{
2528
parent::setUp();
2629

2730
Type::addType('date_collection', DateCollectionType::class);
2831
Type::addType(Language::class, LanguageType::class);
32+
Type::addType('custom_type_without_closure_to_php', CustomTypeWithoutClosureToPHP::class);
2933
}
3034

3135
#[After]
@@ -89,6 +93,16 @@ public function testTypeFromPHPVariable(): void
8993
$databaseValue = Type::convertPHPToDatabaseValue($lang);
9094
self::assertSame(['name' => 'French', 'code' => 'fr'], $databaseValue);
9195
}
96+
97+
public function testNotOverridingClosureToPHPIsDeprecated(): void
98+
{
99+
$type = Type::getType('custom_type_without_closure_to_php');
100+
101+
$code = $this->captureDeprecationMessages(static fn () => $type->closureToPHP(), $deprecations);
102+
103+
self::assertSame('$return = $value;', $code);
104+
self::assertSame(['Since doctrine/mongodb-odm 2.16: The method Type::closureToPHP() will change its default implementation in 3.0 to use convertToPHPValue(). Override this method if you need custom behavior before upgrading to 3.0 or use the trait ClosureToPHP to get the upcoming behavior now.'], $deprecations);
105+
}
92106
}
93107

94108
class DateCollectionType extends Type
@@ -198,3 +212,7 @@ public function convertToPHPValue($value): ?Language
198212
return new Language($value['name'], $value['code']);
199213
}
200214
}
215+
216+
class CustomTypeWithoutClosureToPHP extends Type
217+
{
218+
}

tests/Tests/Types/TypeTest.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,16 @@ public function testConversion(string $typeName, mixed $phpValue, mixed $bsonVal
4242
self::assertSameTypeAndValue($bsonValue, $type->convertToDatabaseValue($phpValue));
4343
}
4444

45+
#[DataProvider('provideTypes')]
46+
public function testConversionWithClosureToPHP(string $typeIdentifier, mixed $expectedValue, mixed $value = null): void
47+
{
48+
$value ??= $expectedValue;
49+
$return = $this;
50+
eval(Type::getType($typeIdentifier)->closureToPHP());
51+
52+
self::assertSameTypeAndValue($expectedValue, $return);
53+
}
54+
4555
public static function provideTypes(): array
4656
{
4757
return [

0 commit comments

Comments
 (0)