Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit a7b30d5

Browse files
committedApr 3, 2023
Restore document proxy state to uninitialized on load exception
1 parent 3091159 commit a7b30d5

File tree

3 files changed

+169
-1
lines changed

3 files changed

+169
-1
lines changed
 

‎lib/Doctrine/ODM/MongoDB/Proxy/Factory/StaticProxyFactory.php

+8-1
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,14 @@ private function createInitializer(
108108
$initializer = null;
109109
$identifier = $metadata->getIdentifierValue($ghostObject);
110110

111-
if (! $documentPersister->load(['_id' => $identifier], $ghostObject)) {
111+
try {
112+
$document = $documentPersister->load(['_id' => $identifier], $ghostObject);
113+
} catch (\Exception $exception) {
114+
$initializer = $originalInitializer;
115+
116+
throw $exception;
117+
}
118+
if (! $document) {
112119
$initializer = $originalInitializer;
113120

114121
if (! $this->lifecycleEventManager->documentNotFound($ghostObject, $identifier)) {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
<?php
2+
3+
declare(strict_types = 1);
4+
5+
namespace Doctrine\ODM\MongoDB\Tests\Proxy\Factory;
6+
7+
use Doctrine\ODM\MongoDB\DocumentManager;
8+
use Doctrine\ODM\MongoDB\LockException;
9+
use Doctrine\ODM\MongoDB\Proxy\Factory\StaticProxyFactory;
10+
use Doctrine\ODM\MongoDB\Tests\BaseTest;
11+
use Documents\PaymentProvider;
12+
use MongoDB\Client;
13+
use MongoDB\Collection;
14+
use MongoDB\Database;
15+
use PHPUnit\Framework\MockObject\MockObject;
16+
17+
class StaticProxyFactoryTest extends BaseTest
18+
{
19+
/**
20+
* @var Client|MockObject
21+
*/
22+
private Client $client;
23+
24+
private StaticProxyFactory $proxyFactory;
25+
26+
public function setUp(): void
27+
{
28+
parent::setUp();
29+
30+
$this->proxyFactory = new StaticProxyFactory($this->dm);
31+
}
32+
33+
public function testProxyInitializeWithException()
34+
{
35+
$collection = $this->createMock(Collection::class);
36+
$database = $this->createMock(Database::class);
37+
38+
$this->client->expects($this->once())
39+
->method('selectDatabase')
40+
->willReturn($database);
41+
42+
$database->expects($this->once())
43+
->method('selectCollection')
44+
->willReturn($collection);
45+
46+
$collection->expects($this->once())
47+
->method('findOne')
48+
->willThrowException(LockException::lockFailed(null));
49+
50+
$uow = $this->dm->getUnitOfWork();
51+
52+
$metadata = $this->dm->getClassMetadata(PaymentProvider::class);
53+
54+
$proxy = $this->proxyFactory->getProxy($metadata, '123');
55+
$uow->registerManaged($proxy, '123', []);
56+
57+
try {
58+
$proxy->getTitle();
59+
} catch (LockException $exception) {
60+
// Expected exception. Ignoring
61+
}
62+
63+
$uow->computeChangeSets();
64+
65+
$this->assertFalse($uow->isScheduledForUpdate($proxy), 'Proxy should not be scheduled for update');
66+
$this->assertFalse($proxy->isProxyInitialized(), 'Proxy should not be initialized');
67+
}
68+
69+
public function tearDown(): void
70+
{
71+
}
72+
73+
protected function createTestDocumentManager(): DocumentManager
74+
{
75+
$config = $this->getConfiguration();
76+
77+
$this->client = $this->createMock(Client::class);
78+
79+
return DocumentManager::create($this->client, $config);
80+
}
81+
}

‎tests/Documents/PaymentProvider.php

+80
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Documents;
6+
7+
use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM;
8+
9+
/** @ODM\Document */
10+
class PaymentProvider
11+
{
12+
/**
13+
* @ODM\Id
14+
*
15+
* @var string|null
16+
*/
17+
public $id;
18+
19+
/**
20+
* @ODM\Field(type="string")
21+
*
22+
* @var string|null
23+
*/
24+
private $title;
25+
26+
/**
27+
* @ODM\Field(type="boolean")
28+
*
29+
* @var bool
30+
*/
31+
private $active = true;
32+
33+
/**
34+
* @ODM\Field(type="hash")
35+
*
36+
* @var array<string, string>
37+
*/
38+
private $configuration = [];
39+
40+
public function getId(): ?string
41+
{
42+
return $this->id;
43+
}
44+
45+
public function getTitle(): ?string
46+
{
47+
return $this->title;
48+
}
49+
50+
public function setTitle(string $title): void
51+
{
52+
$this->title = $title;
53+
}
54+
55+
public function isActive(): bool
56+
{
57+
return $this->active;
58+
}
59+
60+
public function setActive(bool $active): self
61+
{
62+
$this->active = $active;
63+
64+
return $this;
65+
}
66+
67+
/** @return array<string, string> */
68+
public function getConfiguration(): array
69+
{
70+
return $this->configuration;
71+
}
72+
73+
/** @param array<string, string> $configuration */
74+
public function setConfiguration(array $configuration): self
75+
{
76+
$this->configuration = $configuration;
77+
78+
return $this;
79+
}
80+
}

0 commit comments

Comments
 (0)
Please sign in to comment.