Skip to content

Commit 7d73be0

Browse files
authored
Introduce TracingDriverForV32 for DBAL >= 3.2 (#723)
1 parent a39c362 commit 7d73be0

File tree

11 files changed

+247
-6
lines changed

11 files changed

+247
-6
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.*
@@ -41,12 +43,18 @@ 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
50+
doctrine-dbal: '^2.13'
4751
- php: '8.0'
4852
symfony-version: 6.*
4953
dependencies: lowest
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:

composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@
4242
"require-dev": {
4343
"doctrine/dbal": "^2.13||^3.0",
4444
"doctrine/doctrine-bundle": "^1.12||^2.5",
45-
"friendsofphp/php-cs-fixer": "^2.19||^3.6",
45+
"friendsofphp/php-cs-fixer": "^2.19||<=3.16.0",
4646
"jangregor/phpstan-prophecy": "^1.0",
4747
"monolog/monolog": "^1.3||^2.0",
4848
"phpspec/prophecy": "!=1.11.0",

phpstan-baseline.neon

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -231,7 +231,7 @@ parameters:
231231
path: src/Tracing/Doctrine/DBAL/TracingServerInfoAwareDriverConnection.php
232232

233233
-
234-
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\\.$#"
234+
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\\.$#"
235235
count: 1
236236
path: src/Tracing/Doctrine/DBAL/TracingStatementForV3.php
237237

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/TracingDriverForV32.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 TracingDriverForV32 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 Doctrine\DBAL\Exception\SchemaDoesNotExist;
78
use Doctrine\DBAL\Result;
89
use Sentry\SentryBundle\Tracing\Cache\TraceableCacheAdapter;
910
use Sentry\SentryBundle\Tracing\Cache\TraceableCacheAdapterForV2;
@@ -14,6 +15,7 @@
1415
use Sentry\SentryBundle\Tracing\Doctrine\DBAL\TracingDriver;
1516
use Sentry\SentryBundle\Tracing\Doctrine\DBAL\TracingDriverForV2;
1617
use Sentry\SentryBundle\Tracing\Doctrine\DBAL\TracingDriverForV3;
18+
use Sentry\SentryBundle\Tracing\Doctrine\DBAL\TracingDriverForV32;
1719
use Sentry\SentryBundle\Tracing\Doctrine\DBAL\TracingStatement;
1820
use Sentry\SentryBundle\Tracing\Doctrine\DBAL\TracingStatementForV2;
1921
use Sentry\SentryBundle\Tracing\Doctrine\DBAL\TracingStatementForV3;
@@ -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(SchemaDoesNotExist::class)) {
60+
class_alias(TracingDriverForV32::class, TracingDriver::class);
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: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
use Doctrine\Bundle\DoctrineBundle\DoctrineBundle;
88
use Doctrine\DBAL\Driver;
99
use Doctrine\DBAL\Driver\ResultStatement;
10+
use Doctrine\DBAL\Exception\SchemaDoesNotExist;
1011
use PHPUnit\Framework\TestCase;
1112

1213
abstract class DoctrineTestCase extends TestCase
@@ -28,6 +29,12 @@ protected static function isDoctrineDBALVersion3Installed(): bool
2829
&& !self::isDoctrineDBALVersion2Installed();
2930
}
3031

32+
protected static function isDoctrineDBALVersion32Installed(): bool
33+
{
34+
return self::isDoctrineDBALInstalled()
35+
&& class_exists(SchemaDoesNotExist::class);
36+
}
37+
3138
protected static function isDoctrineBundlePackageInstalled(): bool
3239
{
3340
return class_exists(DoctrineBundle::class);

tests/End2End/App/Command/MainCommand.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111

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

tests/Tracing/Doctrine/DBAL/TracingDriverForV3Test.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,8 @@ final class TracingDriverForV3Test extends DoctrineTestCase
2626

2727
public static function setUpBeforeClass(): void
2828
{
29-
if (!self::isDoctrineDBALVersion3Installed()) {
30-
self::markTestSkipped('This test requires the version of the "doctrine/dbal" Composer package to be >= 3.0.');
29+
if (!self::isDoctrineDBALVersion3Installed() || self::isDoctrineDBALVersion32Installed()) {
30+
self::markTestSkipped('This test requires the version of the "doctrine/dbal" Composer package to be >= 3.0 <= 3.2.');
3131
}
3232
}
3333

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)