Skip to content

Commit 2223335

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 a39c362 commit 2223335

File tree

6 files changed

+235
-5
lines changed

6 files changed

+235
-5
lines changed

.github/workflows/tests.yaml

Lines changed: 12 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.*
@@ -47,6 +49,12 @@ jobs:
4749
- php: '8.0'
4850
symfony-version: 6.*
4951
dependencies: lowest
52+
- php: '8.0'
53+
symfony-version: 6.*
54+
doctrine-dbal: '^2.13'
55+
- php: '8.0'
56+
symfony-version: 6.*
57+
doctrine-dbal: '<3.2'
5058

5159
steps:
5260
- name: Checkout
@@ -68,6 +76,10 @@ jobs:
6876
run: composer require --dev phpunit/phpunit ^9.3.9 --no-update
6977
if: matrix.php == '8.0' && matrix.dependencies == 'lowest'
7078

79+
- name: Update Doctrine DBAL
80+
run: composer require --dev doctrine/dbal "${{ matrix.doctrine-dbal }}" --no-update
81+
if: matrix.doctrine-dbal != 'highest'
82+
7183
- name: Install dependencies
7284
uses: ramsey/composer-install@v1
7385
with:
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
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+
use Doctrine\DBAL\VersionAwarePlatformDriver;
13+
14+
/**
15+
* This is a simple implementation of the {@see Driver} interface that decorates
16+
* an existing driver to support distributed tracing capabilities. This implementation
17+
* is compatible with all versions of Doctrine DBAL >= 3.2.
18+
*
19+
* @internal
20+
*
21+
* @phpstan-import-type Params from \Doctrine\DBAL\DriverManager as ConnectionParams
22+
*/
23+
final class TracingDriverForV3Point2 implements Driver
24+
{
25+
/**
26+
* @var TracingDriverConnectionFactoryInterface The connection factory
27+
*/
28+
private $connectionFactory;
29+
30+
/**
31+
* @var Driver|VersionAwarePlatformDriver The instance of the decorated driver
32+
*/
33+
private $decoratedDriver;
34+
35+
/**
36+
* Constructor.
37+
*
38+
* @param TracingDriverConnectionFactoryInterface $connectionFactory The connection factory
39+
* @param Driver $decoratedDriver The instance of the driver to decorate
40+
*/
41+
public function __construct(TracingDriverConnectionFactoryInterface $connectionFactory, Driver $decoratedDriver)
42+
{
43+
$this->connectionFactory = $connectionFactory;
44+
$this->decoratedDriver = $decoratedDriver;
45+
}
46+
47+
/**
48+
* {@inheritdoc}
49+
*
50+
* @phpstan-param ConnectionParams $params
51+
*/
52+
public function connect(array $params): TracingDriverConnectionInterface
53+
{
54+
return $this->connectionFactory->create(
55+
$this->decoratedDriver->connect($params),
56+
$this->decoratedDriver->getDatabasePlatform(),
57+
$params
58+
);
59+
}
60+
61+
/**
62+
* {@inheritdoc}
63+
*/
64+
public function getDatabasePlatform(): AbstractPlatform
65+
{
66+
return $this->decoratedDriver->getDatabasePlatform();
67+
}
68+
69+
/**
70+
* {@inheritdoc}
71+
*
72+
* @phpstan-template T of AbstractPlatform
73+
*
74+
* @phpstan-param T $platform
75+
*
76+
* @phpstan-return AbstractSchemaManager<T>
77+
*/
78+
public function getSchemaManager(Connection $conn, AbstractPlatform $platform): AbstractSchemaManager
79+
{
80+
return $this->decoratedDriver->getSchemaManager($conn, $platform);
81+
}
82+
83+
/**
84+
* {@inheritdoc}
85+
*/
86+
public function getExceptionConverter(): ExceptionConverter
87+
{
88+
return $this->decoratedDriver->getExceptionConverter();
89+
}
90+
}

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: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
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+
public function testGetSchemaManager(): void
81+
{
82+
$connection = $this->createMock(Connection::class);
83+
$databasePlatform = $this->createMock(AbstractPlatform::class);
84+
$schemaManager = $this->createMock(AbstractSchemaManager::class);
85+
86+
$decoratedDriver = $this->createMock(DriverInterface::class);
87+
$decoratedDriver->expects($this->once())
88+
->method('getSchemaManager')
89+
->with($connection, $databasePlatform)
90+
->willReturn($schemaManager);
91+
92+
$driver = new TracingDriverForV3Point2($this->connectionFactory, $decoratedDriver);
93+
94+
$this->assertSame($schemaManager, $driver->getSchemaManager($connection, $databasePlatform));
95+
}
96+
97+
public function testGetExceptionConverter(): void
98+
{
99+
$exceptionConverter = $this->createMock(ExceptionConverter::class);
100+
101+
$decoratedDriver = $this->createMock(DriverInterface::class);
102+
$decoratedDriver->expects($this->once())
103+
->method('getExceptionConverter')
104+
->willReturn($exceptionConverter);
105+
106+
$driver = new TracingDriverForV3Point2($this->connectionFactory, $decoratedDriver);
107+
108+
$this->assertSame($exceptionConverter, $driver->getExceptionConverter());
109+
}
110+
}

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

0 commit comments

Comments
 (0)