Skip to content

Commit

Permalink
add support for DBAL ^4.0 (#227)
Browse files Browse the repository at this point in the history
  • Loading branch information
dmaicher authored Oct 30, 2023
1 parent 42b840b commit ab6d425
Show file tree
Hide file tree
Showing 9 changed files with 217 additions and 118 deletions.
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
"require": {
"php": "^7.3 || ^8.0",
"ext-json": "*",
"doctrine/dbal": "^3.3",
"doctrine/dbal": "^3.3 || ^4.0",
"doctrine/doctrine-bundle": "^2.2.2",
"psr/cache": "^1.0 || ^2.0 || ^3.0",
"symfony/cache": "^5.4 || ^6.2 || ^7.0",
Expand Down
7 changes: 1 addition & 6 deletions phpstan.neon
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,8 @@ parameters:
- %currentWorkingDirectory%/src/DAMA/DoctrineTestBundle/DependencyInjection/Configuration.php
- %currentWorkingDirectory%/src/DAMA/DoctrineTestBundle/PHPUnit/PHPUnitListener.php
- %currentWorkingDirectory%/src/DAMA/DoctrineTestBundle/PHPUnit/PHPUnitExtension.php

- %currentWorkingDirectory%/src/DAMA/DoctrineTestBundle/Doctrine/DBAL/AbstractStaticDriverV2.php
- %currentWorkingDirectory%/src/DAMA/DoctrineTestBundle/Doctrine/DBAL/AbstractStaticDriverV3.php
- %currentWorkingDirectory%/src/DAMA/DoctrineTestBundle/Doctrine/DBAL/StaticDriver.php

- %currentWorkingDirectory%/src/DAMA/DoctrineTestBundle/Doctrine/DBAL/AbstractStaticConnectionV2.php
- %currentWorkingDirectory%/src/DAMA/DoctrineTestBundle/Doctrine/DBAL/AbstractStaticConnectionV3.php
- %currentWorkingDirectory%/src/DAMA/DoctrineTestBundle/Doctrine/DBAL/StaticConnection.php
- %currentWorkingDirectory%/tests/DAMA/DoctrineTestBundle/Doctrine/DBAL/MockDriver.php


92 changes: 34 additions & 58 deletions src/DAMA/DoctrineTestBundle/Doctrine/DBAL/StaticConnection.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,82 +2,58 @@

namespace DAMA\DoctrineTestBundle\Doctrine\DBAL;

use Doctrine\DBAL\Driver\Connection;
use Doctrine\DBAL\Connection;
use Doctrine\DBAL\Driver\Middleware\AbstractConnectionMiddleware;
use Doctrine\DBAL\Platforms\AbstractPlatform;

/**
* Wraps a real connection and makes sure the initial nested transaction is using a savepoint.
*/
class StaticConnection extends AbstractConnectionMiddleware
{
private const SAVEPOINT_NAME = 'DAMA_TEST';

/**
* @var Connection
*/
private $connection;
if (method_exists(Connection::class, 'getEventManager')) {
// DBAL < 4
class StaticConnection extends AbstractConnectionMiddleware
{
use StaticConnectionTrait;

/**
* @var AbstractPlatform
*/
private $platform;
public function beginTransaction(): bool
{
$this->doBeginTransaction();

/**
* @var bool
*/
private $nested = false;
return true;
}

public function __construct(Connection $connection, AbstractPlatform $platform)
{
parent::__construct($connection);
$this->connection = $connection;
$this->platform = $platform;
}
public function commit(): bool
{
$this->doCommit();

public function beginTransaction(): bool
{
if ($this->nested) {
throw new \BadMethodCallException(sprintf('Bad call to "%s". A savepoint is already in use for a nested transaction.', __METHOD__));
return true;
}

$this->exec($this->platform->createSavePoint(self::SAVEPOINT_NAME));

$this->nested = true;
public function rollBack(): bool
{
$this->doRollBack();

return true;
return true;
}
}

public function commit(): bool
} else {
// DBAL >= 4
class StaticConnection extends AbstractConnectionMiddleware
{
if (!$this->nested) {
throw new \BadMethodCallException(sprintf('Bad call to "%s". There is no savepoint for a nested transaction.', __METHOD__));
}
use StaticConnectionTrait;

if ($this->platform->supportsReleaseSavepoints()) {
$this->exec($this->platform->releaseSavePoint(self::SAVEPOINT_NAME));
public function beginTransaction(): void
{
$this->doBeginTransaction();
}

$this->nested = false;

return true;
}

public function rollBack(): bool
{
if (!$this->nested) {
throw new \BadMethodCallException(sprintf('Bad call to "%s". There is no savepoint for a nested transaction.', __METHOD__));
public function commit(): void
{
$this->doCommit();
}

$this->exec($this->platform->rollbackSavePoint(self::SAVEPOINT_NAME));

$this->nested = false;

return true;
}

public function getWrappedConnection(): Connection
{
return $this->connection;
public function rollBack(): void
{
$this->doRollBack();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
<?php

namespace DAMA\DoctrineTestBundle\Doctrine\DBAL;

use Doctrine\DBAL\Driver\Connection;
use Doctrine\DBAL\Platforms\AbstractPlatform;

/**
* @internal
*/
trait StaticConnectionTrait
{
/**
* @var Connection
*/
private $connection;

/**
* @var AbstractPlatform
*/
private $platform;

/**
* @var bool
*/
private $nested = false;

public function __construct(Connection $connection, AbstractPlatform $platform)
{
parent::__construct($connection);
$this->connection = $connection;
$this->platform = $platform;
}

private function doBeginTransaction(): void
{
if ($this->nested) {
throw new \BadMethodCallException(sprintf('Bad call to "%s". A savepoint is already in use for a nested transaction.', __METHOD__));
}

$this->exec($this->platform->createSavePoint('DAMA_TEST'));

$this->nested = true;
}

private function doCommit(): void
{
if (!$this->nested) {
throw new \BadMethodCallException(sprintf('Bad call to "%s". There is no savepoint for a nested transaction.', __METHOD__));
}

if ($this->platform->supportsReleaseSavepoints()) {
$this->exec($this->platform->releaseSavePoint('DAMA_TEST'));
}

$this->nested = false;
}

private function doRollBack(): void
{
if (!$this->nested) {
throw new \BadMethodCallException(sprintf('Bad call to "%s". There is no savepoint for a nested transaction.', __METHOD__));
}

$this->exec($this->platform->rollbackSavePoint('DAMA_TEST'));

$this->nested = false;
}

public function getWrappedConnection(): Connection
{
return $this->connection;
}
}
29 changes: 26 additions & 3 deletions src/DAMA/DoctrineTestBundle/Doctrine/DBAL/StaticDriver.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@

namespace DAMA\DoctrineTestBundle\Doctrine\DBAL;

use Doctrine\DBAL\Connection\StaticServerVersionProvider;
use Doctrine\DBAL\Driver;
use Doctrine\DBAL\Driver\Connection;
use Doctrine\DBAL\Platforms\AbstractPlatform;

class StaticDriver extends Driver\Middleware\AbstractDriverMiddleware
{
Expand Down Expand Up @@ -35,9 +37,7 @@ public function connect(array $params): Connection

$connection = self::$connections[$key];

$platform = $params['platform'] ?? (isset($params['serverVersion'])
? $this->createDatabasePlatformForVersion($params['serverVersion'])
: $this->getDatabasePlatform());
$platform = $this->getPlatform($connection, $params);

if (!$platform->supportsSavepoints()) {
throw new \RuntimeException('This bundle only works for database platforms that support savepoints.');
Expand Down Expand Up @@ -76,4 +76,27 @@ public static function commit(): void
$connection->commit();
}
}

private function getPlatform(Connection $connection, array $params): AbstractPlatform
{
if (isset($params['platform'])) {
return $params['platform'];
}

// DBAL 3
if (method_exists($this, 'createDatabasePlatformForVersion')) {
if (isset($params['serverVersion'])) {
return $this->createDatabasePlatformForVersion($params['serverVersion']);
}

return $this->getDatabasePlatform();
}

// DBAL 4
return $this->getDatabasePlatform(
isset($params['serverVersion'])
? new StaticServerVersionProvider($params['serverVersion'])
: $connection,
);
}
}
63 changes: 17 additions & 46 deletions tests/DAMA/DoctrineTestBundle/Doctrine/DBAL/MockDriver.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,59 +4,30 @@

use Doctrine\DBAL\Connection;
use Doctrine\DBAL\Driver;
use Doctrine\DBAL\Driver\API\ExceptionConverter;
use Doctrine\DBAL\Platforms\AbstractPlatform;
use Doctrine\DBAL\Platforms\MySQL80Platform;
use Doctrine\DBAL\Schema\AbstractSchemaManager;
use Doctrine\DBAL\ServerVersionProvider;

class MockDriver implements Driver
{
private $connection;
private $schemaManager;
private $exceptionConverter;

/**
* @param Driver\Connection $connection
* @param AbstractSchemaManager $schemaManager
* @param ExceptionConverter $exceptionConverter
*/
public function __construct(
$connection,
$schemaManager,
$exceptionConverter
) {
$this->connection = $connection;
$this->schemaManager = $schemaManager;
$this->exceptionConverter = $exceptionConverter;
}

public function connect(array $params): Driver\Connection
{
return clone $this->connection;
}

public function getDatabasePlatform(): AbstractPlatform
{
return new MySQL80Platform();
}

public function getSchemaManager(Connection $conn, AbstractPlatform $platform): AbstractSchemaManager
if (method_exists(Connection::class, 'getEventManager')) {
// DBAL < 4
class MockDriver implements Driver
{
return $this->schemaManager;
}
use MockDriverTrait;

public function getName(): string
{
return 'mock';
public function getDatabasePlatform(): AbstractPlatform
{
return new MySQL80Platform();
}
}

public function getDatabase(Connection $conn): string
} else {
// DBAL >= 4
class MockDriver implements Driver
{
return 'mock';
}
use MockDriverTrait;

public function getExceptionConverter(): ExceptionConverter
{
return $this->exceptionConverter;
public function getDatabasePlatform(ServerVersionProvider $versionProvider): AbstractPlatform
{
return new MySQL80Platform();
}
}
}
56 changes: 56 additions & 0 deletions tests/DAMA/DoctrineTestBundle/Doctrine/DBAL/MockDriverTrait.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
<?php

namespace Tests\DAMA\DoctrineTestBundle\Doctrine\DBAL;

use Doctrine\DBAL\Connection;
use Doctrine\DBAL\Driver;
use Doctrine\DBAL\Driver\API\ExceptionConverter;
use Doctrine\DBAL\Platforms\AbstractPlatform;
use Doctrine\DBAL\Schema\AbstractSchemaManager;

trait MockDriverTrait
{
private $connection;
private $schemaManager;
private $exceptionConverter;

/**
* @param Driver\Connection $connection
* @param AbstractSchemaManager $schemaManager
* @param ExceptionConverter $exceptionConverter
*/
public function __construct(
$connection,
$schemaManager,
$exceptionConverter
) {
$this->connection = $connection;
$this->schemaManager = $schemaManager;
$this->exceptionConverter = $exceptionConverter;
}

public function connect(array $params): Driver\Connection
{
return clone $this->connection;
}

public function getSchemaManager(Connection $conn, AbstractPlatform $platform): AbstractSchemaManager
{
return $this->schemaManager;
}

public function getName(): string
{
return 'mock';
}

public function getDatabase(Connection $conn): string
{
return 'mock';
}

public function getExceptionConverter(): ExceptionConverter
{
return $this->exceptionConverter;
}
}
Loading

0 comments on commit ab6d425

Please sign in to comment.