Skip to content

Commit b1c1e28

Browse files
committed
Merge branch '5.4' into 6.0
* 5.4: fix SQLSRV throws for method_exists() [HttpKernel] Add basic support for language negotiation [Messenger] Add a middleware to log when transaction has been left open [HttpClient] Add method to set response factory in mock client Move array_merge calls out of loops to improve performance Remove references to DBALException [VarDumper] Fix handling of "new" in initializers on PHP 8.1
2 parents 85ee8d5 + 09fc1a7 commit b1c1e28

6 files changed

+124
-10
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@ CHANGELOG
66

77
* Remove `DoctrineTestHelper` and `TestRepositoryFactory`
88

9+
5.4
10+
---
11+
* Add a middleware to log when transaction has been left open `DoctrineOpenTransactionLoggerMiddleware`
12+
913
5.3
1014
---
1115

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Bridge\Doctrine\Messenger;
13+
14+
use Doctrine\ORM\EntityManagerInterface;
15+
use Doctrine\Persistence\ManagerRegistry;
16+
use Psr\Log\LoggerInterface;
17+
use Psr\Log\NullLogger;
18+
use Symfony\Component\Messenger\Envelope;
19+
use Symfony\Component\Messenger\Middleware\StackInterface;
20+
21+
/**
22+
* Middleware to log when transaction has been left open.
23+
*
24+
* @author Grégoire Pineau <[email protected]>
25+
*/
26+
class DoctrineOpenTransactionLoggerMiddleware extends AbstractDoctrineMiddleware
27+
{
28+
private $logger;
29+
30+
public function __construct(ManagerRegistry $managerRegistry, string $entityManagerName = null, LoggerInterface $logger = null)
31+
{
32+
parent::__construct($managerRegistry, $entityManagerName);
33+
34+
$this->logger = $logger ?? new NullLogger();
35+
}
36+
37+
protected function handleForManager(EntityManagerInterface $entityManager, Envelope $envelope, StackInterface $stack): Envelope
38+
{
39+
try {
40+
return $stack->next()->handle($envelope, $stack);
41+
} finally {
42+
if ($entityManager->getConnection()->isTransactionActive()) {
43+
$this->logger->error('A handler opened a transaction but did not close it.', [
44+
'message' => $envelope->getMessage(),
45+
]);
46+
}
47+
}
48+
}
49+
}

Messenger/DoctrinePingConnectionMiddleware.php

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,7 @@
1111

1212
namespace Symfony\Bridge\Doctrine\Messenger;
1313

14-
use Doctrine\DBAL\DBALException;
15-
use Doctrine\DBAL\Exception;
14+
use Doctrine\DBAL\Exception as DBALException;
1615
use Doctrine\ORM\EntityManagerInterface;
1716
use Symfony\Component\Messenger\Envelope;
1817
use Symfony\Component\Messenger\Middleware\StackInterface;
@@ -40,7 +39,7 @@ private function pingConnection(EntityManagerInterface $entityManager)
4039

4140
try {
4241
$connection->executeQuery($connection->getDatabasePlatform()->getDummySelectSQL());
43-
} catch (DBALException | Exception $e) {
42+
} catch (DBALException $e) {
4443
$connection->close();
4544
$connection->connect();
4645
}
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Bridge\Doctrine\Tests\Messenger;
13+
14+
use Doctrine\DBAL\Connection;
15+
use Doctrine\ORM\EntityManagerInterface;
16+
use Doctrine\Persistence\ManagerRegistry;
17+
use Psr\Log\AbstractLogger;
18+
use Symfony\Bridge\Doctrine\Messenger\DoctrineOpenTransactionLoggerMiddleware;
19+
use Symfony\Component\Messenger\Envelope;
20+
use Symfony\Component\Messenger\Test\Middleware\MiddlewareTestCase;
21+
22+
class DoctrineOpenTransactionLoggerMiddlewareTest extends MiddlewareTestCase
23+
{
24+
private $logger;
25+
private $connection;
26+
private $entityManager;
27+
private $middleware;
28+
29+
protected function setUp(): void
30+
{
31+
$this->logger = new class() extends AbstractLogger {
32+
public $logs = [];
33+
34+
public function log($level, $message, $context = []): void
35+
{
36+
$this->logs[$level][] = $message;
37+
}
38+
};
39+
40+
$this->connection = $this->createMock(Connection::class);
41+
42+
$this->entityManager = $this->createMock(EntityManagerInterface::class);
43+
$this->entityManager->method('getConnection')->willReturn($this->connection);
44+
45+
$managerRegistry = $this->createMock(ManagerRegistry::class);
46+
$managerRegistry->method('getManager')->willReturn($this->entityManager);
47+
48+
$this->middleware = new DoctrineOpenTransactionLoggerMiddleware($managerRegistry, null, $this->logger);
49+
}
50+
51+
public function testMiddlewareWrapsInTransactionAndFlushes()
52+
{
53+
$this->connection->expects($this->exactly(1))
54+
->method('isTransactionActive')
55+
->will($this->onConsecutiveCalls(true, true, false))
56+
;
57+
58+
$this->middleware->handle(new Envelope(new \stdClass()), $this->getStackMock());
59+
60+
$this->assertSame(['error' => ['A handler opened a transaction but did not close it.']], $this->logger->logs);
61+
}
62+
}

Tests/Messenger/DoctrinePingConnectionMiddlewareTest.php

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,7 @@
1212
namespace Symfony\Bridge\Doctrine\Tests\Messenger;
1313

1414
use Doctrine\DBAL\Connection;
15-
use Doctrine\DBAL\DBALException;
16-
use Doctrine\DBAL\Exception;
15+
use Doctrine\DBAL\Exception as DBALException;
1716
use Doctrine\ORM\EntityManagerInterface;
1817
use Doctrine\Persistence\ManagerRegistry;
1918
use Symfony\Bridge\Doctrine\Messenger\DoctrinePingConnectionMiddleware;
@@ -50,7 +49,7 @@ public function testMiddlewarePingOk()
5049
{
5150
$this->connection->expects($this->once())
5251
->method('getDatabasePlatform')
53-
->will($this->throwException(class_exists(Exception::class) ? new Exception() : new DBALException()));
52+
->will($this->throwException(new DBALException()));
5453

5554
$this->connection->expects($this->once())
5655
->method('close')
@@ -69,7 +68,7 @@ public function testMiddlewarePingResetEntityManager()
6968
{
7069
$this->connection->expects($this->once())
7170
->method('getDatabasePlatform')
72-
->will($this->throwException(class_exists(Exception::class) ? new Exception() : new DBALException()));
71+
->will($this->throwException(new DBALException()));
7372

7473
$this->entityManager->expects($this->once())
7574
->method('isOpen')

composer.json

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,11 +46,12 @@
4646
"doctrine/annotations": "^1.10.4",
4747
"doctrine/collections": "~1.0",
4848
"doctrine/data-fixtures": "^1.1",
49-
"doctrine/dbal": "^2.10|^3.0",
50-
"doctrine/orm": "^2.7.3"
49+
"doctrine/dbal": "^2.13|^3.0",
50+
"doctrine/orm": "^2.7.3",
51+
"psr/log": "^1|^2|^3"
5152
},
5253
"conflict": {
53-
"doctrine/dbal": "<2.10",
54+
"doctrine/dbal": "<2.13",
5455
"doctrine/orm": "<2.7.3",
5556
"phpunit/phpunit": "<5.4.3",
5657
"symfony/dependency-injection": "<5.4",

0 commit comments

Comments
 (0)