Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merge 2.2.x into 2.3.x #2350

Merged
merged 25 commits into from
Aug 5, 2021
Merged
Show file tree
Hide file tree
Changes from 24 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
887a62e
Fix locking when ClassMetadata is unserialized
buffcode Feb 3, 2021
a97aab0
Test serialization of lock/version fields
buffcode Feb 4, 2021
cbe6a2f
Merge pull request #2281 from buffcode/patch-3
malarzm Feb 4, 2021
b243e4b
Update working-with-objects.rst
Feb 5, 2021
b7a35e4
Merge pull request #2285 from jeeiex/patch-1
malarzm Feb 5, 2021
5a0af40
Update storage-strategies.rst
Feb 5, 2021
f8b40c8
Merge pull request #2286 from jeeiex/patch-2
SenseException Feb 5, 2021
1276c9c
Fix invalid strict comparison when validating mappings
alcaeus Feb 26, 2021
a88db3e
Merge pull request #2290 from alcaeus/fix-metadata-validation
malarzm Feb 26, 2021
8069ded
Correctly handle write concern specified in defaultCommitOptions (#2294)
ossinkine Mar 10, 2021
841221b
Fix documentation for uploadFromFile
rrajkomar Feb 4, 2021
6c0b48a
Merge pull request #2284 from rrajkomar/patch-1
malarzm Mar 15, 2021
a3efe06
Fix mapping of the nullable option for XML driver
wuchen90 Mar 15, 2021
6e42eed
Merge pull request #2297 from wuchen90/fix-xml-nullable
malarzm Mar 16, 2021
05c9a25
Fix query preparation when in elemMatch (#2299)
alcaeus Apr 13, 2021
4984784
Fix preparation of $elemMatch operators in queries (#2298)
alcaeus Apr 13, 2021
18d9ac7
Fix using null values in partial filter expressions (#2300)
alcaeus Apr 14, 2021
5ca00af
Fix errors with nullable typed associations (#2302)
alcaeus Apr 22, 2021
f225a0c
Allow mixed value in $not operator (#2307)
franmomu May 20, 2021
ccf26d9
[2.2] Fix builds (#2319)
alcaeus Jun 2, 2021
5aa06c0
Fix wrong handling for nullable fields in upsert and update (#2318)
alcaeus Jun 15, 2021
f20b3cd
Fix handling of upserts during scheduling for deletion (#2334)
webmozart Jun 29, 2021
85d2b9f
Fix wrong assertion (#2335)
alcaeus Jul 5, 2021
f013d11
Merge branch '2.2.x' into merge-2.2.x-into-2.3.x
alcaeus Aug 2, 2021
0abe370
Remove psalm-baseline.xml
alcaeus Aug 5, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .github/workflows/coding-standards.yml
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,11 @@ jobs:
- name: "Install dependencies with Composer"
uses: "ramsey/composer-install@v1"

- name: "Upload composer.lock as build artifact"
uses: actions/upload-artifact@v2
with:
name: composer.lock
path: composer.lock

# https://github.com/doctrine/.github/issues/3
- name: "Run PHP_CodeSniffer"
Expand Down
12 changes: 7 additions & 5 deletions .github/workflows/continuous-integration.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,10 @@ env:
jobs:
phpunit:
name: "PHPUnit"
runs-on: "${{ matrix.os }}"
runs-on: "ubuntu-18.04"

strategy:
matrix:
os:
- "ubuntu-18.04"
php-version:
- "7.2"
- "7.3"
Expand All @@ -35,13 +33,11 @@ jobs:
- "highest"
include:
- deps: "lowest"
os: "ubuntu-16.04"
php-version: "7.2"
mongodb-version: "3.6"
driver-version: "1.5.0"
topology: "server"
- topology: "sharded_cluster"
os: "ubuntu-18.04"
php-version: "8.0"
mongodb-version: "4.4"
driver-version: "stable"
Expand Down Expand Up @@ -86,6 +82,12 @@ jobs:
dependency-versions: "${{ matrix.dependencies }}"
composer-options: "--prefer-dist"

- name: "Upload composer.lock as build artifact"
uses: actions/upload-artifact@v2
with:
name: composer.lock
path: composer.lock

- id: setup-mongodb
uses: mongodb-labs/drivers-evergreen-tools@master
with:
Expand Down
6 changes: 6 additions & 0 deletions .github/workflows/performance.yml
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,12 @@ jobs:
- name: "Install dependencies with Composer"
uses: "ramsey/composer-install@v1"

- name: "Upload composer.lock as build artifact"
uses: actions/upload-artifact@v2
with:
name: composer.lock
path: composer.lock

# https://github.com/doctrine/.github/issues/3
- name: "Run PHP_CodeSniffer"
run: "vendor/bin/phpbench run --report=default --revs=100 --iterations=5 --report=aggregate"
12 changes: 12 additions & 0 deletions .github/workflows/static-analysis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,12 @@ jobs:
- name: "Install dependencies with Composer"
uses: "ramsey/composer-install@v1"

- name: "Upload composer.lock as build artifact"
uses: actions/upload-artifact@v2
with:
name: composer.lock
path: composer.lock

- name: "Run a static analysis with phpstan/phpstan"
run: "vendor/bin/phpstan analyse --error-format=github"

Expand All @@ -75,5 +81,11 @@ jobs:
- name: "Install dependencies with Composer"
uses: "ramsey/composer-install@v1"

- name: "Upload composer.lock as build artifact"
uses: actions/upload-artifact@v2
with:
name: composer.lock
path: composer.lock

- name: "Run a static analysis with vimeo/psalm"
run: "vendor/bin/psalm --show-info=false --stats --output-format=github --threads=$(nproc) --php-version=${{ matrix.php-version }}"
98 changes: 48 additions & 50 deletions lib/Doctrine/ODM/MongoDB/Persisters/PersistenceBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -68,14 +68,11 @@ public function prepareInsertData($document)
foreach ($class->fieldMappings as $mapping) {
$new = $changeset[$mapping['fieldName']][1] ?? null;

if ($new === null && $mapping['nullable']) {
$insertData[$mapping['name']] = null;
}

/* Nothing more to do for null values, since we're either storing
* them (if nullable was true) or not.
*/
if ($new === null) {
if ($mapping['nullable']) {
$insertData[$mapping['name']] = null;
}

continue;
}

Expand Down Expand Up @@ -143,34 +140,36 @@ public function prepareUpdateData($document)

[$old, $new] = $change;

if ($new === null) {
if ($mapping['nullable'] === true) {
$updateData['$set'][$mapping['name']] = null;
} else {
$updateData['$unset'][$mapping['name']] = true;
}

continue;
}

// Scalar fields
if (! isset($mapping['association'])) {
if ($new === null && $mapping['nullable'] !== true) {
$updateData['$unset'][$mapping['name']] = true;
if (isset($mapping['strategy']) && $mapping['strategy'] === ClassMetadata::STORAGE_STRATEGY_INCREMENT) {
$operator = '$inc';
$type = Type::getType($mapping['type']);
assert($type instanceof Incrementable);
$value = $type->convertToDatabaseValue($type->diff($old, $new));
} else {
if ($new !== null && isset($mapping['strategy']) && $mapping['strategy'] === ClassMetadata::STORAGE_STRATEGY_INCREMENT) {
$operator = '$inc';
$type = Type::getType($mapping['type']);
assert($type instanceof Incrementable);
$value = $type->convertToDatabaseValue($type->diff($old, $new));
} else {
$operator = '$set';
$value = $new === null ? null : Type::getType($mapping['type'])->convertToDatabaseValue($new);
}

$updateData[$operator][$mapping['name']] = $value;
$operator = '$set';
$value = Type::getType($mapping['type'])->convertToDatabaseValue($new);
}

$updateData[$operator][$mapping['name']] = $value;

// @EmbedOne
} elseif (isset($mapping['association']) && $mapping['association'] === ClassMetadata::EMBED_ONE) {
// If we have a new embedded document then lets set the whole thing
if ($new && $this->uow->isScheduledForInsert($new)) {
if ($this->uow->isScheduledForInsert($new)) {
$updateData['$set'][$mapping['name']] = $this->prepareEmbeddedDocumentValue($mapping, $new);

// If we don't have a new value then lets unset the embedded document
} elseif (! $new) {
$updateData['$unset'][$mapping['name']] = true;

// Update existing embedded document
} else {
$update = $this->prepareUpdateData($new);
Expand All @@ -182,7 +181,7 @@ public function prepareUpdateData($document)
}

// @ReferenceMany, @EmbedMany
} elseif (isset($mapping['association']) && $mapping['type'] === ClassMetadata::MANY && $new) {
} elseif (isset($mapping['association']) && $mapping['type'] === ClassMetadata::MANY) {
if (CollectionHelper::isAtomic($mapping['strategy']) && $this->uow->isCollectionScheduledForUpdate($new)) {
$updateData['$set'][$mapping['name']] = $this->prepareAssociatedCollectionValue($new, true);
} elseif (CollectionHelper::isAtomic($mapping['strategy']) && $this->uow->isCollectionScheduledForDeletion($new)) {
Expand All @@ -208,11 +207,7 @@ public function prepareUpdateData($document)

// @ReferenceOne
} elseif (isset($mapping['association']) && $mapping['association'] === ClassMetadata::REFERENCE_ONE) {
if (isset($new) || $mapping['nullable'] === true) {
$updateData['$set'][$mapping['name']] = $new === null ? null : $this->prepareReferencedDocumentValue($mapping, $new);
} else {
$updateData['$unset'][$mapping['name']] = true;
}
$updateData['$set'][$mapping['name']] = $this->prepareReferencedDocumentValue($mapping, $new);
}
}

Expand Down Expand Up @@ -250,31 +245,36 @@ public function prepareUpsertData($document)

[$old, $new] = $change;

// Fields with a null value should only be written for inserts
if ($new === null) {
if ($mapping['nullable'] === true) {
$updateData['$setOnInsert'][$mapping['name']] = null;
}

continue;
}

// Scalar fields
if (! isset($mapping['association'])) {
if ($new !== null) {
if (empty($mapping['id']) && isset($mapping['strategy']) && $mapping['strategy'] === ClassMetadata::STORAGE_STRATEGY_INCREMENT) {
$operator = '$inc';
$type = Type::getType($mapping['type']);
assert($type instanceof Incrementable);
$value = $type->convertToDatabaseValue($type->diff($old, $new));
} else {
$operator = '$set';
$value = Type::getType($mapping['type'])->convertToDatabaseValue($new);
}

$updateData[$operator][$mapping['name']] = $value;
} elseif ($mapping['nullable'] === true) {
$updateData['$setOnInsert'][$mapping['name']] = null;
if (empty($mapping['id']) && isset($mapping['strategy']) && $mapping['strategy'] === ClassMetadata::STORAGE_STRATEGY_INCREMENT) {
$operator = '$inc';
$type = Type::getType($mapping['type']);
assert($type instanceof Incrementable);
$value = $type->convertToDatabaseValue($type->diff($old, $new));
} else {
$operator = '$set';
$value = Type::getType($mapping['type'])->convertToDatabaseValue($new);
}

$updateData[$operator][$mapping['name']] = $value;

// @EmbedOne
} elseif (isset($mapping['association']) && $mapping['association'] === ClassMetadata::EMBED_ONE) {
// If we don't have a new value then do nothing on upsert
// If we have a new embedded document then lets set the whole thing
if ($new && $this->uow->isScheduledForInsert($new)) {
if ($this->uow->isScheduledForInsert($new)) {
$updateData['$set'][$mapping['name']] = $this->prepareEmbeddedDocumentValue($mapping, $new);
} elseif ($new) {
} else {
// Update existing embedded document
$update = $this->prepareUpsertData($new);
foreach ($update as $cmd => $values) {
Expand All @@ -286,9 +286,7 @@ public function prepareUpsertData($document)

// @ReferenceOne
} elseif (isset($mapping['association']) && $mapping['association'] === ClassMetadata::REFERENCE_ONE) {
if (isset($new) || $mapping['nullable'] === true) {
$updateData['$set'][$mapping['name']] = $new === null ? null : $this->prepareReferencedDocumentValue($mapping, $new);
}
$updateData['$set'][$mapping['name']] = $this->prepareReferencedDocumentValue($mapping, $new);

// @ReferenceMany, @EmbedMany
} elseif (
Expand Down
6 changes: 3 additions & 3 deletions lib/Doctrine/ODM/MongoDB/Query/Builder.php
Original file line number Diff line number Diff line change
Expand Up @@ -1028,11 +1028,11 @@ public function nearSphere($x, $y = null): self
* @see Expr::not()
* @see https://docs.mongodb.com/manual/reference/operator/not/
*
* @param array|Expr $expression
* @param array|Expr|mixed $valueOrExpression
*/
public function not($expression): self
public function not($valueOrExpression): self
{
$this->expr->not($expression);
$this->expr->not($valueOrExpression);

return $this;
}
Expand Down
2 changes: 1 addition & 1 deletion lib/Doctrine/ODM/MongoDB/Query/Expr.php
Original file line number Diff line number Diff line change
Expand Up @@ -861,7 +861,7 @@ public function nearSphere($x, $y = null): self
* @see Builder::not()
* @see https://docs.mongodb.com/manual/reference/operator/not/
*
* @param array|Expr $expression
* @param array|Expr|mixed $expression
*/
public function not($expression): self
{
Expand Down
4 changes: 4 additions & 0 deletions lib/Doctrine/ODM/MongoDB/UnitOfWork.php
Original file line number Diff line number Diff line change
Expand Up @@ -1459,6 +1459,10 @@ public function scheduleForDelete(object $document, bool $isView = false): void
unset($this->documentUpdates[$oid]);
}

if (isset($this->documentUpserts[$oid])) {
unset($this->documentUpserts[$oid]);
}

if (isset($this->documentDeletions[$oid])) {
return;
}
Expand Down
31 changes: 31 additions & 0 deletions psalm-baseline.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?xml version="1.0" encoding="UTF-8"?>
<files psalm-version="4.7.3@38c452ae584467e939d55377aaf83b5a26f19dd1">
<file src="lib/Doctrine/ODM/MongoDB/DocumentManager.php">
<ParamNameMismatch occurrences="8">
<code>$document</code>
<code>$document</code>
<code>$document</code>
<code>$document</code>
<code>$document</code>
<code>$document</code>
<code>$documentName</code>
<code>$documentName</code>
</ParamNameMismatch>
</file>
<file src="lib/Doctrine/ODM/MongoDB/Mapping/ClassMetadata.php">
<ParamNameMismatch occurrences="2">
<code>$fieldName</code>
<code>$fieldName</code>
</ParamNameMismatch>
</file>
<file src="lib/Doctrine/ODM/MongoDB/PersistentCollection/PersistentCollectionTrait.php">
<ParamNameMismatch occurrences="1">
<code>$value</code>
</ParamNameMismatch>
</file>
<file src="lib/Doctrine/ODM/MongoDB/Query/QueryExpressionVisitor.php">
<ParamNameMismatch occurrences="1">
<code>$compositeExpr</code>
</ParamNameMismatch>
</file>
</files>
1 change: 1 addition & 0 deletions psalm.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="https://getpsalm.org/schema/config"
xsi:schemaLocation="https://getpsalm.org/schema/config vendor/vimeo/psalm/config.xsd"
errorBaseline="psalm-baseline.xml"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤔 I think I fixed these ParamNameMismatch some time ago (in 2.3.x), probably this is not needed.

This is what I don't like about ignoring issues in the psalm baseline, that it doesn't complain about non existing ignored issues.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll recreate the baseline and see what happens.

Copy link
Member Author

@alcaeus alcaeus Aug 5, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See f995aad - this now has an empty baseline. Do you want me to drop the file and config?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would remove it if it is not needed and add it when we need it.

>
<projectFiles>
<directory name="lib/Doctrine/ODM/MongoDB" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -431,6 +431,7 @@ public function testRemoveEmbeddedDocument(): void

$check = $this->dm->getDocumentCollection(User::class)->findOne();
$this->assertEmpty($check['phonenumbers']);
$this->assertNull($check['addressNullable']);
$this->assertArrayNotHasKey('address', $check);
}

Expand Down
22 changes: 22 additions & 0 deletions tests/Doctrine/ODM/MongoDB/Tests/Functional/QueryTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
use InvalidArgumentException;
use IteratorAggregate;
use MongoDB\BSON\ObjectId;
use MongoDB\BSON\Regex;
use MongoDB\BSON\UTCDateTime;

use function array_values;
Expand Down Expand Up @@ -102,6 +103,27 @@ public function testAddNot(): void
$this->assertNotNull($user);
}

public function testNotAllowsRegex(): void
{
$user = new User();
$user->setUsername('boo');

$this->dm->persist($user);
$this->dm->flush();

$qb = $this->dm->createQueryBuilder(User::class);
$qb->field('username')->not(new Regex('Boo', 'i'));
$query = $qb->getQuery();
$user = $query->getSingleResult();
$this->assertNull($user);

$qb = $this->dm->createQueryBuilder(User::class);
$qb->field('username')->not(new Regex('Boo'));
$query = $qb->getQuery();
$user = $query->getSingleResult();
$this->assertNotNull($user);
}

public function testDistinct(): void
{
$user = new User();
Expand Down
Loading