Skip to content

Commit

Permalink
Compatibility with ORM 3 and DBAL 4 (#1363)
Browse files Browse the repository at this point in the history
  • Loading branch information
derrabus authored Oct 29, 2023
1 parent 8022851 commit 4e633c7
Show file tree
Hide file tree
Showing 15 changed files with 139 additions and 128 deletions.
12 changes: 11 additions & 1 deletion .github/workflows/continuous-integration.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,19 @@ jobs:
- "8.2"
dependencies:
- "highest"
stability:
- "default"
include:
- dependencies: "lowest"
stability: "default"
php-version: "8.1"
- dependencies: "highest"
stability: "dev"
php-version: "8.2"

steps:
- name: "Checkout"
uses: "actions/checkout@v3"
uses: "actions/checkout@v4"

- name: "Install PHP"
uses: "shivammathur/setup-php@v2"
Expand All @@ -53,6 +59,10 @@ jobs:
- name: "Download box"
run: "./download-box.sh"

- name: "Allow dev dependencies"
if: "matrix.stability == 'dev'"
run: "composer config minimum-stability dev"

- name: "Install dependencies with Composer"
uses: "ramsey/composer-install@v2"
with:
Expand Down
6 changes: 3 additions & 3 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
"require": {
"php": "^8.1",
"composer-runtime-api": "^2",
"doctrine/dbal": "^3.5.1",
"doctrine/dbal": "^3.5.1 || ^4",
"doctrine/deprecations": "^0.5.3 || ^1",
"doctrine/event-manager": "^1.2 || ^2.0",
"psr/log": "^1.1.3 || ^2 || ^3",
Expand All @@ -37,7 +37,7 @@
"require-dev": {
"ext-pdo_sqlite": "*",
"doctrine/coding-standard": "^12",
"doctrine/orm": "^2.13",
"doctrine/orm": "^2.13 || ^3",
"doctrine/persistence": "^2 || ^3",
"doctrine/sql-formatter": "^1.0",
"phpstan/phpstan": "^1.10",
Expand All @@ -51,7 +51,7 @@
"symfony/yaml": "^5.4 || ^6.0 || ^7.0"
},
"conflict": {
"doctrine/orm": "<2.12"
"doctrine/orm": "<2.12 || >=4"
},
"suggest": {
"doctrine/sql-formatter": "Allows to generate formatted SQL with the diff command.",
Expand Down
32 changes: 24 additions & 8 deletions lib/Doctrine/Migrations/DependencyFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

namespace Doctrine\Migrations;

use Doctrine\Common\EventManager;
use Doctrine\DBAL\Connection;
use Doctrine\Migrations\Configuration\Configuration;
use Doctrine\Migrations\Configuration\Connection\ConnectionLoader;
Expand Down Expand Up @@ -51,6 +52,7 @@

use function array_key_exists;
use function call_user_func;
use function method_exists;
use function preg_quote;
use function sprintf;

Expand All @@ -67,16 +69,12 @@ class DependencyFactory
/** @var object[]|callable[] */
private array $dependencies = [];

private Connection|null $connection = null;

private Connection|null $connection = null;
private EntityManagerInterface|null $em = null;

private bool $frozen = false;

private EventManager|null $eventManager = null;
private bool $frozen = false;
private ConfigurationLoader $configurationLoader;

private ConnectionLoader $connectionLoader;

private EntityManagerLoader|null $emLoader = null;

/** @var callable[] */
Expand Down Expand Up @@ -193,7 +191,7 @@ public function getEventDispatcher(): EventDispatcher
{
return $this->getDependency(EventDispatcher::class, fn (): EventDispatcher => new EventDispatcher(
$this->getConnection(),
$this->getConnection()->getEventManager(),
$this->getEventManager(),
));
}

Expand Down Expand Up @@ -446,4 +444,22 @@ public function setDefinition(string $id, callable $service): void
$this->assertNotFrozen();
$this->factories[$id] = $service;
}

private function getEventManager(): EventManager
{
if ($this->eventManager !== null) {
return $this->eventManager;
}

if ($this->hasEntityManager()) {
return $this->eventManager = $this->getEntityManager()->getEventManager();
}

if (method_exists(Connection::class, 'getEventManager')) {
// DBAL < 4
return $this->eventManager = $this->getConnection()->getEventManager();
}

return $this->eventManager = new EventManager();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ public function complete(ExecutionResult $result): void
$this->configuration->getExecutionTimeColumnName() => $result->getTime() === null ? null : (int) round($result->getTime() * 1000),
], [
Types::STRING,
Types::DATETIME_MUTABLE,
Types::DATETIME_IMMUTABLE,
Types::INTEGER,
]);
}
Expand Down
2 changes: 1 addition & 1 deletion lib/Doctrine/Migrations/SchemaDumper.php
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ public function dump(
$up[] = $upCode;
}

$downSql = [$this->platform->getDropTableSQL($table)];
$downSql = [$this->platform->getDropTableSQL($table->getQuotedName($this->platform))];

$downCode = $this->migrationSqlGenerator->generate(
$downSql,
Expand Down
13 changes: 13 additions & 0 deletions phpstan.neon.dist
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,26 @@ parameters:
"""
count: 1
path: tests/Doctrine/Migrations/Tests/Tools/Console/legacy-config-orm/cli-config.php
-
message: """
#^Fetching class constant class of deprecated class Doctrine\\\\ORM\\\\Tools\\\\Console\\\\Helper\\\\EntityManagerHelper\\:
This class will be removed in ORM 3\\.0 without replacement\\.$#
"""
count: 1
path: tests/Doctrine/Migrations/Tests/Tools/Console/ConsoleRunnerTest.php

# TODO: deprecate using the connection event manager and expose
# our own event manager instead.
-
message: '~^Call to deprecated method getEventManager\(\) of class Doctrine\\DBAL\\Connection\.$~'
path: lib/Doctrine/Migrations/DependencyFactory.php

# DBAL 4 forward compatibility
- '~^Call to function method_exists\(\) with ''Doctrine\\\\DBAL\\\\Connection'' and ''getEventManager'' will always evaluate to true\.$~'
- '~^Class Doctrine\\DBAL\\Platforms\\SQLitePlatform not found\.$~'
- '~^Instantiated class Doctrine\\DBAL\\Platforms\\SQLitePlatform not found\.$~'
- '~^Access to constant class on an unknown class Doctrine\\DBAL\\Platforms\\SQLitePlatform\.$~'
- '~expects Doctrine\\DBAL\\Platforms\\AbstractPlatform, Doctrine\\DBAL\\Platforms\\SQLitePlatform given\.$~'
symfony:
console_application_loader: tests/Doctrine/Migrations/Tests/doctrine-migrations-phpstan-app.php
includes:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
namespace Doctrine\Migrations\Tests\Configuration\Connection;

use Doctrine\DBAL\Connection;
use Doctrine\DBAL\Platforms\SqlitePlatform;
use Doctrine\DBAL\Platforms\SQLitePlatform;
use Doctrine\Migrations\Configuration\Connection\ConfigurationFile;
use Doctrine\Migrations\Configuration\Connection\Exception\FileNotFound;
use Doctrine\Migrations\Configuration\Connection\Exception\InvalidConfiguration;
Expand Down Expand Up @@ -39,15 +39,15 @@ public function testArrayConnectionConfigurationLoader(): void
$loader = new ConfigurationFile(__DIR__ . '/_files/sqlite-connection.php');
$conn = $loader->getConnection();

self::assertInstanceOf(SqlitePlatform::class, $conn->getDatabasePlatform());
self::assertInstanceOf(SQLitePlatform::class, $conn->getDatabasePlatform());
}

public function testArrayConnectionConfigurationLoaderWithConnectionInstance(): void
{
$loader = new ConfigurationFile(__DIR__ . '/_files/sqlite-connection-instance.php');
$conn = $loader->getConnection();

self::assertInstanceOf(SqlitePlatform::class, $conn->getDatabasePlatform());
self::assertInstanceOf(SQLitePlatform::class, $conn->getDatabasePlatform());
}

public function testArrayConnectionConfigurationLoaderInvalid(): void
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

namespace Doctrine\Migrations\Tests\Configuration\EntityManager;

use Doctrine\DBAL\Platforms\SqlitePlatform;
use Doctrine\DBAL\Platforms\SQLitePlatform;
use Doctrine\Migrations\Configuration\EntityManager\ConfigurationFile;
use Doctrine\Migrations\Configuration\EntityManager\Exception\FileNotFound;
use Doctrine\Migrations\Configuration\EntityManager\Exception\InvalidConfiguration;
Expand Down Expand Up @@ -39,15 +39,15 @@ public function testArrayEntityManagerConfigurationLoader(): void
$loader = new ConfigurationFile(__DIR__ . '/_files/em-loader.php');
$em = $loader->getEntityManager();

self::assertInstanceOf(SqlitePlatform::class, $em->getConnection()->getDatabasePlatform());
self::assertInstanceOf(SQLitePlatform::class, $em->getConnection()->getDatabasePlatform());
}

public function testArrayEntityManagerConfigurationLoaderWithEntityManagerInstance(): void
{
$loader = new ConfigurationFile(__DIR__ . '/_files/migrations-em.php');
$em = $loader->getEntityManager();

self::assertInstanceOf(SqlitePlatform::class, $em->getConnection()->getDatabasePlatform());
self::assertInstanceOf(SQLitePlatform::class, $em->getConnection()->getDatabasePlatform());
}

public function testArrayEntityManagerConfigurationLoaderInvalid(): void
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
namespace Doctrine\Migrations\Tests\Event\Listeners;

use Doctrine\DBAL\Connection;
use Doctrine\DBAL\Driver\Connection as DriverConnection;
use Doctrine\Migrations\Event\Listeners\AutoCommitListener;
use Doctrine\Migrations\Event\MigrationsEventArgs;
use Doctrine\Migrations\Metadata\MigrationPlanList;
Expand All @@ -16,9 +15,7 @@

class AutoCommitListenerTest extends MigrationTestCase
{
/** @var Connection&MockObject */
private Connection $conn;

private Connection&MockObject $conn;
private AutoCommitListener $listener;

public function testListenerDoesNothingDuringADryRun(): void
Expand Down Expand Up @@ -51,10 +48,7 @@ public function testListenerDoesFinalCommitWhenAutoCommitIsOff(): void

protected function setUp(): void
{
$this->conn = $this->createMock(Connection::class);
$driverConnection = self::createStub(DriverConnection::class);
$this->conn->method('getWrappedConnection')->willReturn($driverConnection);

$this->conn = $this->createMock(Connection::class);
$this->listener = new AutoCommitListener();
}

Expand Down
76 changes: 29 additions & 47 deletions tests/Doctrine/Migrations/Tests/Generator/DiffGeneratorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,28 +20,17 @@

class DiffGeneratorTest extends TestCase
{
/** @var DBALConfiguration&MockObject */
private DBALConfiguration $dbalConfiguration;
private DBALConfiguration&MockObject $dbalConfiguration;

/** @var AbstractSchemaManager<AbstractPlatform>&MockObject */
private AbstractSchemaManager $schemaManager;

/** @var SchemaProvider&MockObject */
private SchemaProvider $schemaProvider;

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

/** @var Generator&MockObject */
private Generator $migrationGenerator;

/** @var SqlGenerator&MockObject */
private SqlGenerator $migrationSqlGenerator;
private AbstractSchemaManager&MockObject $schemaManager;

private SchemaProvider&MockObject $schemaProvider;
private AbstractPlatform&MockObject $platform;
private Generator&MockObject $migrationGenerator;
private SqlGenerator&MockObject $migrationSqlGenerator;
private DiffGenerator $migrationDiffGenerator;

/** @var SchemaProvider&MockObject */
private SchemaProvider $emptySchemaProvider;
private SchemaProvider&MockObject $emptySchemaProvider;

public function testGenerate(): void
{
Expand Down Expand Up @@ -89,7 +78,7 @@ public function testGenerate(): void

$toSchema->expects(self::exactly(2))
->method('dropTable')
->willReturnOnConsecutiveCalls('schema.table_name2', 'schema.table_name3');
->willReturnSelf();

$schemaDiff = self::createStub(SchemaDiff::class);

Expand All @@ -102,19 +91,7 @@ public function testGenerate(): void
return ['UPDATE table SET value = 1'];
});

// regular mocks cannot be used here, because the method is static
$comparator = new class extends Comparator {
public static SchemaDiff $schemaDiff;

public static function compareSchemas(
Schema $fromSchema,
Schema $toSchema,
): SchemaDiff {
return self::$schemaDiff;
}
};

$comparator::$schemaDiff = $schemaDiff;
$comparator = $this->mockComparator($schemaDiff);

$this->schemaManager->expects(self::once())
->method('createComparator')
Expand Down Expand Up @@ -151,10 +128,10 @@ public function testGenerateFromEmptySchema(): void

$this->dbalConfiguration->expects(self::once())
->method('getSchemaAssetsFilter')
->willReturn(null);
->willReturn(static fn () => true);

$toSchema->expects(self::never())
->method('getTables');
$toSchema->method('getTables')
->willReturn([new Table('table_name')]);

$this->emptySchemaProvider->expects(self::once())
->method('createSchema')
Expand All @@ -181,18 +158,7 @@ public function testGenerateFromEmptySchema(): void
});

// regular mocks cannot be used here, because the method is static
$comparator = new class extends Comparator {
public static SchemaDiff $schemaDiff;

public static function compareSchemas(
Schema $fromSchema,
Schema $toSchema,
): SchemaDiff {
return self::$schemaDiff;
}
};

$comparator::$schemaDiff = $schemaDiff;
$comparator = $this->mockComparator($schemaDiff);

$this->schemaManager->expects(self::once())
->method('createComparator')
Expand Down Expand Up @@ -233,4 +199,20 @@ protected function setUp(): void
$this->emptySchemaProvider,
);
}

private function mockComparator(SchemaDiff $schemaDiff): Comparator
{
$comparator = new class (self::createStub(AbstractPlatform::class)) extends Comparator {
public static SchemaDiff $schemaDiff;

public function compareSchemas(Schema $oldSchema, Schema $newSchema): SchemaDiff
{
return self::$schemaDiff;
}
};

$comparator::$schemaDiff = $schemaDiff;

return $comparator;
}
}
Loading

0 comments on commit 4e633c7

Please sign in to comment.