Skip to content

Commit 61aafa3

Browse files
author
Vincent Le Henaff
committed
Merge remote-tracking branch 'origin/2.3.x' into support-expr-in-queries
# Conflicts: # composer.json # lib/Doctrine/ODM/MongoDB/Persisters/PersistenceBuilder.php # lib/Doctrine/ODM/MongoDB/Query/Expr.php # phpstan-baseline.neon # tests/Doctrine/ODM/MongoDB/Tests/Mapping/ClassMetadataTest.php
2 parents 7ba6315 + bc740ff commit 61aafa3

File tree

143 files changed

+3065
-680
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

143 files changed

+3065
-680
lines changed

.doctrine-project.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@
2626
"name": "2.1",
2727
"branchName": "2.1.x",
2828
"slug": "2.1",
29-
"current": true,
3029
"maintained": false,
3130
"aliases": [
3231
"2.1.x"
@@ -45,6 +44,7 @@
4544
"name": "1.3",
4645
"branchName": "1.3.x",
4746
"slug": "1.3",
47+
"maintained": false,
4848
"aliases": [
4949
"1.3.x"
5050
]

UPGRADE-2.2.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,3 +22,11 @@ Using `@Index` annotation(s) on a class level is a preferred way for defining
2222
indexes for documents. Using `@Index` in the `@Indexes` annotation or an `indexes`
2323
property of other annotations was deprecated and will be removed in ODM 3.0.
2424

25+
## DocumentManager configuration
26+
27+
Using doctrine/cache to cache metadata is deprecated in favor of using PSR-6.
28+
The `getMetadataCacheImpl` and `setMetadataCacheImpl` methods in
29+
`Doctrine\ODM\MongoDB\Configuration` have been deprecated. Please use
30+
`getMetadataCache`and `setMetadataCache` with a PSR-6 implementation instead.
31+
Note that even after switching to PSR-6, `getMetadataCacheImpl` will return a
32+
cache instance that wraps the PSR-6 cache.

UPGRADE-2.3.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# UPGRADE FROM 2.2 to 2.3
2+
3+
## Proxy Class Name Resolution
4+
5+
The `Doctrine\ODM\MongoDB\Proxy\Resolver\ClassNameResolver` interface has been
6+
deprecated in favor of the `Doctrine\Persistence\Mapping\ProxyClassNameResolver`
7+
interface.
8+
9+
The `getClassNameResolver` method in `DocumentManager` is deprecated and should
10+
not be used. To retrieve the mapped class name for any object or class string,
11+
fetch metadata for the class and read the class using `$metadata->getName()`.
12+
The metadata layer is aware of these proxy namespace changes and how to resolve
13+
them, so users should always go through the metadata layer to retrieve mapped
14+
class names.

UPGRADE-3.0.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,3 +21,16 @@ will no longer be extendable.
2121
The `boolean`, `integer`, and `int_id` mapping types have been removed. Use the
2222
`bool`, `int`, and `int` types, respectively. These types behave exactly the
2323
same.
24+
25+
## Proxy Class Name Resolution
26+
27+
The `Doctrine\ODM\MongoDB\Proxy\Resolver\ClassNameResolver` interface has been
28+
dropped in favor of the `Doctrine\Persistence\Mapping\ProxyClassNameResolver`
29+
interface.
30+
31+
The `getClassNameResolver` method in `DocumentManager` has been removed. To
32+
retrieve the mapped class name for any object or class string, fetch metadata
33+
for the class and read the class using `$metadata->getName()`. The metadata
34+
layer is aware of these proxy namespace changes and how to resolve them, so
35+
users should always go through the metadata layer to retrieve mapped class
36+
names.

benchmark/BaseBench.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,13 @@
44

55
namespace Doctrine\ODM\MongoDB\Benchmark;
66

7-
use Doctrine\Common\Cache\ArrayCache;
87
use Doctrine\ODM\MongoDB\Configuration;
98
use Doctrine\ODM\MongoDB\DocumentManager;
109
use Doctrine\ODM\MongoDB\Mapping\Driver\AnnotationDriver;
1110
use MongoDB\Client;
1211
use MongoDB\Model\DatabaseInfo;
1312
use PhpBench\Benchmark\Metadata\Annotations\BeforeMethods;
13+
use Symfony\Component\Cache\Adapter\ArrayAdapter;
1414

1515
use function array_map;
1616
use function getenv;
@@ -48,7 +48,7 @@ public function initDocumentManager()
4848
$config->setPersistentCollectionNamespace('PersistentCollections');
4949
$config->setDefaultDB(self::DATABASE_NAME);
5050
$config->setMetadataDriverImpl(self::createMetadataDriverImpl());
51-
$config->setMetadataCacheImpl(new ArrayCache());
51+
$config->setMetadataCache(new ArrayAdapter());
5252

5353
$client = new Client(
5454
getenv('DOCTRINE_MONGODB_SERVER') ?: self::DEFAULT_MONGODB_SERVER,

composer.json

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -25,27 +25,30 @@
2525
"php": "^7.2 || ^8.0",
2626
"ext-mongodb": "^1.5",
2727
"doctrine/annotations": "^1.6",
28-
"doctrine/cache": "^1.7",
28+
"doctrine/cache": "^1.11 || ^2.0",
2929
"doctrine/collections": "^1.5",
3030
"doctrine/event-manager": "^1.0",
3131
"doctrine/instantiator": "^1.1",
32-
"doctrine/persistence": "^1.3.5|^2.0",
32+
"doctrine/persistence": "^2.2",
3333
"friendsofphp/proxy-manager-lts": "^1.0",
34-
"jean85/pretty-package-versions": "^1.3.0",
34+
"jean85/pretty-package-versions": "^1.3.0 || ^2.0.1",
3535
"mongodb/mongodb": "^1.2.0",
36-
"symfony/console": "^3.4|^4.1|^5.0",
36+
"psr/cache": "^1.0 || ^2.0 || ^3.0",
37+
"symfony/console": "^3.4 || ^4.1 || ^5.0",
3738
"symfony/deprecation-contracts": "^2.2",
38-
"symfony/var-dumper": "^3.4|^4.1|^5.0"
39+
"symfony/var-dumper": "^3.4 || ^4.1 || ^5.0"
3940
},
4041
"require-dev": {
4142
"ext-bcmath": "*",
42-
"doctrine/coding-standard": "^8.2",
43+
"doctrine/coding-standard": "^9.0",
4344
"jmikola/geojson": "^1.0",
4445
"phpbench/phpbench": "^1.0.0",
45-
"phpstan/phpstan": "^0.12.32",
46+
"phpstan/phpstan": "^0.12.89",
47+
"phpstan/phpstan-phpunit": "^0.12.19",
4648
"phpunit/phpunit": "^8.5 || ^9",
4749
"squizlabs/php_codesniffer": "^3.5",
48-
"vimeo/psalm": "^4.2.1"
50+
"symfony/cache": "^4.4 || ^5.0",
51+
"vimeo/psalm": "^4.8.1"
4952
},
5053
"suggest": {
5154
"ext-bcmath": "Decimal128 type support"

docs/en/cookbook/validation-of-documents.rst

Lines changed: 124 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
Validation of Documents
22
=======================
33

4+
Validation of Documents - Application Side
5+
------------------------------------------
6+
47
.. sectionauthor:: Benjamin Eberlei <[email protected]>
58

69
Doctrine does not ship with any internal validators, the reason
@@ -127,4 +130,124 @@ instances. This was already discussed in the previous blog post on
127130
the Versionable extension, which requires another type of event
128131
called "onFlush".
129132

130-
Further readings: :doc:`Lifecycle Events <../reference/events>`
133+
Further readings: :doc:`Lifecycle Events <../reference/events>`
134+
135+
Validation of Documents - Database Side
136+
---------------------------------------
137+
138+
.. sectionauthor:: Alexandre Abrioux <[email protected]>
139+
140+
.. note::
141+
142+
This feature has been introduced in version 2.3.0
143+
144+
MongoDB ≥ 3.6 offers the capability to validate documents during
145+
insertions and updates through a schema associated to the collection
146+
(cf. `MongoDB documentation <https://docs.mongodb.com/manual/core/schema-validation/>`_).
147+
148+
Doctrine MongoDB ODM now provides a way to take advantage of this functionality
149+
thanks to the new :doc:`@Validation <../reference/annotations-reference#validation>`
150+
annotation and its properties (also available with XML mapping):
151+
152+
-
153+
``validator`` - The schema that will be used to validate documents.
154+
It is a string representing a BSON document under the
155+
`Extended JSON specification <https://github.com/mongodb/specifications/blob/master/source/extended-json.rst>`_.
156+
-
157+
``action`` - The behavior followed by MongoDB to handle documents that
158+
violate the validation rules.
159+
-
160+
``level`` - The threshold used by MongoDB to filter operations that
161+
will get validated.
162+
163+
Once defined, those options will be added to the collection after running
164+
the ``odm:schema:create`` or ``odm:schema:update`` command.
165+
166+
.. configuration-block::
167+
168+
.. code-block:: php
169+
170+
<?php
171+
172+
namespace Documents;
173+
174+
use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM;
175+
use Doctrine\ODM\MongoDB\Mapping\ClassMetadata;
176+
177+
/**
178+
* @ODM\Document
179+
* @ODM\Validation(
180+
* validator=SchemaValidated::VALIDATOR,
181+
* action=ClassMetadata::SCHEMA_VALIDATION_ACTION_WARN,
182+
* level=ClassMetadata::SCHEMA_VALIDATION_LEVEL_MODERATE,
183+
* )
184+
*/
185+
class SchemaValidated
186+
{
187+
public const VALIDATOR = <<<'EOT'
188+
{
189+
"$jsonSchema": {
190+
"required": ["name"],
191+
"properties": {
192+
"name": {
193+
"bsonType": "string",
194+
"description": "must be a string and is required"
195+
}
196+
}
197+
},
198+
"$or": [
199+
{ "phone": { "$type": "string" } },
200+
{ "email": { "$regex": { "$regularExpression" : { "pattern": "@mongodb\\.com$", "options": "" } } } },
201+
{ "status": { "$in": [ "Unknown", "Incomplete" ] } }
202+
]
203+
}
204+
EOT;
205+
206+
/** @ODM\Id */
207+
private $id;
208+
209+
/** @ODM\Field(type="string") */
210+
private $name;
211+
212+
/** @ODM\Field(type="string") */
213+
private $phone;
214+
215+
/** @ODM\Field(type="string") */
216+
private $email;
217+
218+
/** @ODM\Field(type="string") */
219+
private $status;
220+
}
221+
222+
.. code-block:: xml
223+
224+
<?xml version="1.0" encoding="UTF-8"?>
225+
<doctrine-mongo-mapping xmlns="http://doctrine-project.org/schemas/odm/doctrine-mongo-mapping"
226+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
227+
xsi:schemaLocation="http://doctrine-project.org/schemas/odm/doctrine-mongo-mapping
228+
http://doctrine-project.org/schemas/odm/doctrine-mongo-mapping.xsd">
229+
230+
<document name="SchemaValidated">
231+
<schema-validation action="warn" level="moderate">
232+
{
233+
"$jsonSchema": {
234+
"required": ["name"],
235+
"properties": {
236+
"name": {
237+
"bsonType": "string",
238+
"description": "must be a string and is required"
239+
}
240+
}
241+
},
242+
"$or": [
243+
{ "phone": { "$type": "string" } },
244+
{ "email": { "$regex": { "$regularExpression" : { "pattern": "@mongodb\\.com$", "options": "" } } } },
245+
{ "status": { "$in": [ "Unknown", "Incomplete" ] } }
246+
]
247+
}
248+
</schema-validation>
249+
</document>
250+
</doctrine-mongo-mapping>
251+
252+
Please refer to the :doc:`@Validation <../reference/annotations-reference#document>` annotation reference
253+
for more details on how to use this feature.

docs/en/reference/annotations-reference.rst

Lines changed: 95 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ and it does not contain the class name of the persisted document, a
139139
@Document
140140
---------
141141

142-
Required annotation to mark a PHP class as a document, whose peristence will be
142+
Required annotation to mark a PHP class as a document, whose persistence will be
143143
managed by ODM.
144144

145145
Optional attributes:
@@ -1092,6 +1092,100 @@ Alias of `@Index`_, with the ``unique`` option set by default.
10921092
10931093
.. _annotations_reference_version:
10941094

1095+
@Validation
1096+
-----------
1097+
1098+
This annotation may be used at the class level to specify the validation schema
1099+
for the related collection.
1100+
1101+
-
1102+
``validator`` - Specifies a schema that will be used by
1103+
MongoDB to validate data inserted or updated in the collection.
1104+
Please refer to the following
1105+
`MongoDB documentation (Schema Validation ¶) <https://docs.mongodb.com/manual/core/schema-validation/>`_
1106+
for more details. The value should be a string representing a BSON document under the
1107+
`Extended JSON specification <https://github.com/mongodb/specifications/blob/master/source/extended-json.rst>`_.
1108+
The recommended way to fill up this property is to create a class constant
1109+
(eg. ``::VALIDATOR``) using the
1110+
`HEREDOC/NOWDOC syntax <https://www.php.net/manual/en/language.types.string.php#language.types.string.syntax.nowdoc>`_
1111+
for clarity and to reference it as the annotation value.
1112+
Please note that if you decide to insert the schema directly in the annotation without
1113+
using a class constant then double quotes ``"`` have to be escaped by doubling them ``""``.
1114+
This method also requires that you don't prefix multiline strings by the Docblock asterisk symbol ``*``.
1115+
-
1116+
``action`` - Determines how MongoDB handles documents that violate
1117+
the validation rules. Please refer to the related
1118+
`MongoDB documentation (Accept or Reject Invalid Documents ¶) <https://docs.mongodb.com/manual/core/schema-validation/#accept-or-reject-invalid-documents>`_
1119+
for more details. The allowed values are the following:
1120+
1121+
- ``error``
1122+
- ``warn``
1123+
1124+
If it is not defined then the default behavior (``error``) will be used.
1125+
Those values are also declared as constants for convenience:
1126+
1127+
- ``\Doctrine\ODM\MongoDB\Mapping\ClassMetadata::SCHEMA_VALIDATION_ACTION_ERROR``
1128+
- ``\Doctrine\ODM\MongoDB\Mapping\ClassMetadata::SCHEMA_VALIDATION_ACTION_WARN``
1129+
1130+
Import the ``ClassMetadata`` namespace to use those constants in your annotation.
1131+
-
1132+
``level`` - Determines which operations MongoDB applies the
1133+
validation rules. Please refer to the related
1134+
`MongoDB documentation (Existing Documents ¶) <https://docs.mongodb.com/manual/core/schema-validation/#existing-documents>`_
1135+
for more details. The allowed values are the following:
1136+
1137+
- ``off``
1138+
- ``strict``
1139+
- ``moderate``
1140+
1141+
If it is not defined then the default behavior (``strict``) will be used.
1142+
Those values are also declared as constants for convenience:
1143+
1144+
- ``\Doctrine\ODM\MongoDB\Mapping\ClassMetadata::SCHEMA_VALIDATION_LEVEL_OFF``
1145+
- ``\Doctrine\ODM\MongoDB\Mapping\ClassMetadata::SCHEMA_VALIDATION_LEVEL_STRICT``
1146+
- ``\Doctrine\ODM\MongoDB\Mapping\ClassMetadata::SCHEMA_VALIDATION_LEVEL_MODERATE``
1147+
1148+
Import the ``ClassMetadata`` namespace to use those constants in your annotation.
1149+
1150+
.. code-block:: php
1151+
1152+
<?php
1153+
1154+
use Doctrine\ODM\MongoDB\Mapping\ClassMetadata;
1155+
// ... other imports
1156+
1157+
/**
1158+
* @Document
1159+
* @Validation(
1160+
* validator=SchemaValidated::VALIDATOR,
1161+
* action=ClassMetadata::SCHEMA_VALIDATION_ACTION_WARN,
1162+
* level=ClassMetadata::SCHEMA_VALIDATION_LEVEL_MODERATE,
1163+
* )
1164+
*/
1165+
class SchemaValidated
1166+
{
1167+
public const VALIDATOR = <<<'EOT'
1168+
{
1169+
"$jsonSchema": {
1170+
"required": ["name"],
1171+
"properties": {
1172+
"name": {
1173+
"bsonType": "string",
1174+
"description": "must be a string and is required"
1175+
}
1176+
}
1177+
},
1178+
"$or": [
1179+
{ "phone": { "$type": "string" } },
1180+
{ "email": { "$regex": { "$regularExpression" : { "pattern": "@mongodb\\.com$", "options": "" } } } },
1181+
{ "status": { "$in": [ "Unknown", "Incomplete" ] } }
1182+
]
1183+
}
1184+
EOT;
1185+
1186+
// rest of the class code...
1187+
}
1188+
10951189
@Version
10961190
--------
10971191

0 commit comments

Comments
 (0)