Skip to content

Commit cb92a10

Browse files
committed
Introduce TracingDriverForV3Point2
This driver does not implement the deprecated `VersionAwarePlatformDriver`. It's automatically picked when `doctrine/dbal` version `3.2.0` or higher is installed. Fixes #579
1 parent 7f19baf commit cb92a10

File tree

9 files changed

+259
-5
lines changed

9 files changed

+259
-5
lines changed

.github/workflows/tests.yaml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ jobs:
3030
- 6.*
3131
dependencies:
3232
- highest
33+
doctrine-dbal:
34+
- highest
3335
exclude:
3436
- php: '7.2'
3537
symfony-version: 6.*
@@ -41,12 +43,16 @@ jobs:
4143
- php: '7.2'
4244
symfony-version: 4.4.*
4345
dependencies: lowest
46+
doctrine-dbal: '^2.13'
4447
- php: '7.2'
4548
symfony-version: 5.*
4649
dependencies: lowest
4750
- php: '8.0'
4851
symfony-version: 6.*
4952
dependencies: lowest
53+
- php: '8.0'
54+
symfony-version: 6.*
55+
doctrine-dbal: '<3.2'
5056

5157
steps:
5258
- name: Checkout
@@ -68,6 +74,10 @@ jobs:
6874
run: composer require --dev phpunit/phpunit ^9.3.9 --no-update
6975
if: matrix.php == '8.0' && matrix.dependencies == 'lowest'
7076

77+
- name: Update Doctrine DBAL
78+
run: composer require --dev doctrine/dbal "${{ matrix.doctrine-dbal }}" --no-update
79+
if: matrix.doctrine-dbal != 'highest'
80+
7181
- name: Install dependencies
7282
uses: ramsey/composer-install@v1
7383
with:

phpstan-baseline.neon

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,16 @@ parameters:
240240
count: 1
241241
path: src/Tracing/Doctrine/DBAL/TracingStatementForV3.php
242242

243+
-
244+
message: "#^Parameter \\#2 \\$callback of method Sentry\\\\SentryBundle\\\\Tracing\\\\Doctrine\\\\DBAL\\\\AbstractTracingStatement\\:\\:traceFunction\\(\\) expects callable\\(\\.\\.\\.mixed\\)\\: Doctrine\\\\DBAL\\\\Driver\\\\Result, array\\{Doctrine\\\\DBAL\\\\Driver\\\\Statement, 'execute'\\} given\\.$#"
245+
count: 1
246+
path: src/Tracing/Doctrine/DBAL/TracingStatementForV3Point2.php
247+
248+
-
249+
message: "#^Parameter \\#4 \\$length of method Doctrine\\\\DBAL\\\\Driver\\\\Statement\\:\\:bindParam\\(\\) expects int\\|null, mixed given\\.$#"
250+
count: 1
251+
path: src/Tracing/Doctrine/DBAL/TracingStatementForV3Point2.php
252+
243253
-
244254
message: "#^Method Sentry\\\\SentryBundle\\\\Tracing\\\\HttpClient\\\\AbstractTraceableHttpClient\\:\\:request\\(\\) has parameter \\$options with no value type specified in iterable type array\\.$#"
245255
count: 1

psalm-baseline.xml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,17 @@
5050
<code>$params</code>
5151
</MoreSpecificImplementedParamType>
5252
</file>
53+
<file src="src/Tracing/Doctrine/DBAL/TracingDriverForV3Point2.php">
54+
<InvalidReturnStatement occurrences="1">
55+
<code>$this-&gt;decoratedDriver-&gt;getSchemaManager($conn, $platform)</code>
56+
</InvalidReturnStatement>
57+
<InvalidReturnType occurrences="1">
58+
<code>AbstractSchemaManager&lt;T&gt;</code>
59+
</InvalidReturnType>
60+
<MoreSpecificImplementedParamType occurrences="1">
61+
<code>$params</code>
62+
</MoreSpecificImplementedParamType>
63+
</file>
5364
<file src="src/Tracing/HttpClient/TraceableResponseForV5.php">
5465
<UndefinedInterfaceMethod occurrences="1">
5566
<code>toStream</code>
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Sentry\SentryBundle\Tracing\Doctrine\DBAL;
6+
7+
use Doctrine\DBAL\Connection;
8+
use Doctrine\DBAL\Driver;
9+
use Doctrine\DBAL\Driver\API\ExceptionConverter;
10+
use Doctrine\DBAL\Platforms\AbstractPlatform;
11+
use Doctrine\DBAL\Schema\AbstractSchemaManager;
12+
13+
/**
14+
* This is a simple implementation of the {@see Driver} interface that decorates
15+
* an existing driver to support distributed tracing capabilities. This implementation
16+
* is compatible with all versions of Doctrine DBAL >= 3.2.
17+
*
18+
* @internal
19+
*
20+
* @phpstan-import-type Params from \Doctrine\DBAL\DriverManager as ConnectionParams
21+
*/
22+
final class TracingDriverForV3Point2 implements Driver
23+
{
24+
/**
25+
* @var TracingDriverConnectionFactoryInterface The connection factory
26+
*/
27+
private $connectionFactory;
28+
29+
/**
30+
* @var Driver The instance of the decorated driver
31+
*/
32+
private $decoratedDriver;
33+
34+
/**
35+
* Constructor.
36+
*
37+
* @param TracingDriverConnectionFactoryInterface $connectionFactory The connection factory
38+
* @param Driver $decoratedDriver The instance of the driver to decorate
39+
*/
40+
public function __construct(TracingDriverConnectionFactoryInterface $connectionFactory, Driver $decoratedDriver)
41+
{
42+
$this->connectionFactory = $connectionFactory;
43+
$this->decoratedDriver = $decoratedDriver;
44+
}
45+
46+
/**
47+
* {@inheritdoc}
48+
*
49+
* @phpstan-param ConnectionParams $params
50+
*/
51+
public function connect(array $params): TracingDriverConnectionInterface
52+
{
53+
return $this->connectionFactory->create(
54+
$this->decoratedDriver->connect($params),
55+
$this->decoratedDriver->getDatabasePlatform(),
56+
$params
57+
);
58+
}
59+
60+
/**
61+
* {@inheritdoc}
62+
*/
63+
public function getDatabasePlatform(): AbstractPlatform
64+
{
65+
return $this->decoratedDriver->getDatabasePlatform();
66+
}
67+
68+
/**
69+
* {@inheritdoc}
70+
*
71+
* @phpstan-template T of AbstractPlatform
72+
*
73+
* @phpstan-param T $platform
74+
*
75+
* @phpstan-return AbstractSchemaManager<T>
76+
*/
77+
public function getSchemaManager(Connection $conn, AbstractPlatform $platform): AbstractSchemaManager
78+
{
79+
return $this->decoratedDriver->getSchemaManager($conn, $platform);
80+
}
81+
82+
/**
83+
* {@inheritdoc}
84+
*/
85+
public function getExceptionConverter(): ExceptionConverter
86+
{
87+
return $this->decoratedDriver->getExceptionConverter();
88+
}
89+
}

src/aliases.php

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
namespace Sentry\SentryBundle;
66

7+
use Composer\InstalledVersions;
78
use Doctrine\DBAL\Result;
89
use Sentry\SentryBundle\Tracing\Cache\TraceableCacheAdapter;
910
use Sentry\SentryBundle\Tracing\Cache\TraceableCacheAdapterForV2;
@@ -15,6 +16,7 @@
1516
use Sentry\SentryBundle\Tracing\Doctrine\DBAL\TracingDriverForV2;
1617
use Sentry\SentryBundle\Tracing\Doctrine\DBAL\TracingDriverForV3;
1718
use Sentry\SentryBundle\Tracing\Doctrine\DBAL\TracingStatement;
19+
use Sentry\SentryBundle\Tracing\Doctrine\DBAL\TracingDriverForV3Point2;
1820
use Sentry\SentryBundle\Tracing\Doctrine\DBAL\TracingStatementForV2;
1921
use Sentry\SentryBundle\Tracing\Doctrine\DBAL\TracingStatementForV3;
2022
use Sentry\SentryBundle\Tracing\HttpClient\TraceableHttpClient;
@@ -53,7 +55,12 @@ class_alias(TraceableTagAwareCacheAdapterForV2::class, TraceableTagAwareCacheAda
5355
if (!class_exists(TracingStatement::class)) {
5456
if (class_exists(Result::class)) {
5557
class_alias(TracingStatementForV3::class, TracingStatement::class);
56-
class_alias(TracingDriverForV3::class, TracingDriver::class);
58+
59+
if (class_exists(InstalledVersions::class) && version_compare(InstalledVersions::getVersion('doctrine/dbal') ?? '0', '3.2', '>=')) {
60+
class_alias(TracingDriverForV3Point2::class, 'Sentry\\SentryBundle\\Tracing\\Doctrine\\DBAL\\TracingDriver');
61+
} else {
62+
class_alias(TracingDriverForV3::class, TracingDriver::class);
63+
}
5764
} elseif (interface_exists(Result::class)) {
5865
class_alias(TracingStatementForV2::class, TracingStatement::class);
5966
class_alias(TracingDriverForV2::class, TracingDriver::class);

tests/DoctrineTestCase.php

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
namespace Sentry\SentryBundle\Tests;
66

7+
use Composer\InstalledVersions;
78
use Doctrine\Bundle\DoctrineBundle\DoctrineBundle;
89
use Doctrine\DBAL\Driver;
910
use Doctrine\DBAL\Driver\ResultStatement;
@@ -13,23 +14,29 @@ abstract class DoctrineTestCase extends TestCase
1314
{
1415
protected static function isDoctrineDBALInstalled(): bool
1516
{
16-
return interface_exists(Driver::class);
17+
return InstalledVersions::isInstalled('doctrine/dbal');
1718
}
1819

1920
protected static function isDoctrineDBALVersion2Installed(): bool
2021
{
2122
return self::isDoctrineDBALInstalled()
22-
&& interface_exists(ResultStatement::class);
23+
&& version_compare(InstalledVersions::getVersion('doctrine/dbal') ?? '0', '3.0', '<');
2324
}
2425

2526
protected static function isDoctrineDBALVersion3Installed(): bool
2627
{
2728
return self::isDoctrineDBALInstalled()
28-
&& !self::isDoctrineDBALVersion2Installed();
29+
&& version_compare(InstalledVersions::getVersion('doctrine/dbal') ?? '0', '3.0', '>=');
30+
}
31+
32+
protected static function isDoctrineDBALVersion3Point2Installed(): bool
33+
{
34+
return self::isDoctrineDBALInstalled()
35+
&& version_compare(InstalledVersions::getVersion('doctrine/dbal') ?? '0', '3.2', '>=');
2936
}
3037

3138
protected static function isDoctrineBundlePackageInstalled(): bool
3239
{
33-
return class_exists(DoctrineBundle::class);
40+
return InstalledVersions::isInstalled('doctrine/doctrine-bundle');
3441
}
3542
}
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Sentry\SentryBundle\Tests\Tracing\Doctrine\DBAL;
6+
7+
use Doctrine\DBAL\Connection;
8+
use Doctrine\DBAL\Driver as DriverInterface;
9+
use Doctrine\DBAL\Driver\API\ExceptionConverter;
10+
use Doctrine\DBAL\Driver\Connection as DriverConnectionInterface;
11+
use Doctrine\DBAL\Platforms\AbstractPlatform;
12+
use Doctrine\DBAL\Schema\AbstractSchemaManager;
13+
use Doctrine\DBAL\VersionAwarePlatformDriver as VersionAwarePlatformDriverInterface;
14+
use PHPUnit\Framework\MockObject\MockObject;
15+
use Sentry\SentryBundle\Tests\DoctrineTestCase;
16+
use Sentry\SentryBundle\Tracing\Doctrine\DBAL\TracingDriverConnectionFactoryInterface;
17+
use Sentry\SentryBundle\Tracing\Doctrine\DBAL\TracingDriverConnectionInterface;
18+
use Sentry\SentryBundle\Tracing\Doctrine\DBAL\TracingDriverForV3Point2;
19+
20+
final class TracingDriverForV3Point2Test extends DoctrineTestCase
21+
{
22+
/**
23+
* @var MockObject&TracingDriverConnectionFactoryInterface
24+
*/
25+
private $connectionFactory;
26+
27+
public static function setUpBeforeClass(): void
28+
{
29+
if (!self::isDoctrineDBALVersion3Point2Installed()) {
30+
self::markTestSkipped('This test requires the version of the "doctrine/dbal" Composer package to be >= 3.2.');
31+
}
32+
}
33+
34+
protected function setUp(): void
35+
{
36+
$this->connectionFactory = $this->createMock(TracingDriverConnectionFactoryInterface::class);
37+
}
38+
39+
public function testConnect(): void
40+
{
41+
$params = ['host' => 'localhost'];
42+
$databasePlatform = $this->createMock(AbstractPlatform::class);
43+
$driverConnection = $this->createMock(DriverConnectionInterface::class);
44+
$tracingDriverConnection = $this->createMock(TracingDriverConnectionInterface::class);
45+
$decoratedDriver = $this->createMock(DriverInterface::class);
46+
47+
$decoratedDriver->expects($this->once())
48+
->method('connect')
49+
->with($params)
50+
->willReturn($driverConnection);
51+
52+
$decoratedDriver->expects($this->once())
53+
->method('getDatabasePlatform')
54+
->willReturn($databasePlatform);
55+
56+
$this->connectionFactory->expects($this->once())
57+
->method('create')
58+
->with($driverConnection, $databasePlatform, $params)
59+
->willReturn($tracingDriverConnection);
60+
61+
$driver = new TracingDriverForV3Point2($this->connectionFactory, $decoratedDriver);
62+
63+
$this->assertSame($tracingDriverConnection, $driver->connect($params));
64+
}
65+
66+
public function testGetDatabasePlatform(): void
67+
{
68+
$databasePlatform = $this->createMock(AbstractPlatform::class);
69+
70+
$decoratedDriver = $this->createMock(DriverInterface::class);
71+
$decoratedDriver->expects($this->once())
72+
->method('getDatabasePlatform')
73+
->willReturn($databasePlatform);
74+
75+
$driver = new TracingDriverForV3Point2($this->connectionFactory, $decoratedDriver);
76+
77+
$this->assertSame($databasePlatform, $driver->getDatabasePlatform());
78+
}
79+
80+
/**
81+
* @group legacy
82+
*/
83+
public function testGetSchemaManager(): void
84+
{
85+
$connection = $this->createMock(Connection::class);
86+
$databasePlatform = $this->createMock(AbstractPlatform::class);
87+
$schemaManager = $this->createMock(AbstractSchemaManager::class);
88+
89+
$decoratedDriver = $this->createMock(DriverInterface::class);
90+
$decoratedDriver->expects($this->once())
91+
->method('getSchemaManager')
92+
->with($connection, $databasePlatform)
93+
->willReturn($schemaManager);
94+
95+
$driver = new TracingDriverForV3Point2($this->connectionFactory, $decoratedDriver);
96+
97+
$this->assertSame($schemaManager, $driver->getSchemaManager($connection, $databasePlatform));
98+
}
99+
100+
public function testGetExceptionConverter(): void
101+
{
102+
$exceptionConverter = $this->createMock(ExceptionConverter::class);
103+
104+
$decoratedDriver = $this->createMock(DriverInterface::class);
105+
$decoratedDriver->expects($this->once())
106+
->method('getExceptionConverter')
107+
->willReturn($exceptionConverter);
108+
109+
$driver = new TracingDriverForV3Point2($this->connectionFactory, $decoratedDriver);
110+
111+
$this->assertSame($exceptionConverter, $driver->getExceptionConverter());
112+
}
113+
}

tests/Tracing/Doctrine/DBAL/TracingDriverForV3Test.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,10 @@ public static function setUpBeforeClass(): void
2929
if (!self::isDoctrineDBALVersion3Installed()) {
3030
self::markTestSkipped('This test requires the version of the "doctrine/dbal" Composer package to be >= 3.0.');
3131
}
32+
33+
if (self::isDoctrineDBALVersion3Point2Installed()) {
34+
self::markTestSkipped('This test requires the version of the "doctrine/dbal" Composer package to be >= 3.0 <= 3.0.');
35+
}
3236
}
3337

3438
protected function setUp(): void

tests/Tracing/Doctrine/DBAL/TracingStatementForV3Test.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,9 @@ public function testBindValue(): void
5555
$this->assertTrue($this->statement->bindValue('foo', 'bar', ParameterType::INTEGER));
5656
}
5757

58+
/**
59+
* @group legacy
60+
*/
5861
public function testBindParam(): void
5962
{
6063
$variable = 'bar';

0 commit comments

Comments
 (0)