Skip to content

Commit

Permalink
Add support for --complete
Browse files Browse the repository at this point in the history
When using orm:schema-tool:update together with --complete, all assets
not described by the current metadata is dropped.

This is an issue when using doctrine/migrations, because not using that
option is deprecated, and because when it is used, the table that holds
the migrations is dropped as well since it is not described by ORM
metadata.

A solution to that is configuring an asset filter that filters out the
metadata table except when running commands inside the migrations
namespace.
  • Loading branch information
greg0ire committed Mar 14, 2024
1 parent f7a8d12 commit 2cfbb72
Show file tree
Hide file tree
Showing 3 changed files with 104 additions and 0 deletions.
51 changes: 51 additions & 0 deletions EventListener/SchemaFilterListener.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
<?php

declare(strict_types=1);

namespace Doctrine\Bundle\MigrationsBundle\EventListener;

use Doctrine\DBAL\Schema\AbstractAsset;
use Doctrine\Migrations\Metadata\Storage\TableMetadataStorageConfiguration;
use Doctrine\Migrations\Tools\Console\Command\DoctrineCommand;
use Symfony\Component\Console\Event\ConsoleCommandEvent;

/**
* Acts as a schema filter able that hides the migration metadata table except
* when the execution context is that of command inside the migrations
* namespace.
*/
final class SchemaFilterListener
{
/** @var bool */
private $enabled = true;

/** @param AbstractAsset|string $asset */
public function __invoke($asset): bool
{
if (! $this->enabled) {
return true;
}

if ($asset instanceof AbstractAsset) {
$asset = $asset->getName();
}

return $asset !== (new TableMetadataStorageConfiguration())->getTableName();
}

public function disable(): void
{
$this->enabled = false;
}

public function onConsoleCommand(ConsoleCommandEvent $event): void
{
$command = $event->getCommand();

if (! $command instanceof DoctrineCommand) {
return;

Check warning on line 46 in EventListener/SchemaFilterListener.php

View check run for this annotation

Codecov / codecov/patch

EventListener/SchemaFilterListener.php#L46

Added line #L46 was not covered by tests
}

$this->disable();
}
}
5 changes: 5 additions & 0 deletions Resources/config/services.xml
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,11 @@
<tag name="console.command" command="doctrine:migrations:version" />
</service>

<service id="doctrine_migrations.schema_filter_listener" class="Doctrine\Migrations\EventListener\SchemaFilterListener">
<tag name="kernel.event_listener" event="console.command" method="onConsoleCommand" />
<tag name="doctrine.dbal.schema_filter" />
</service>

</services>

</container>
48 changes: 48 additions & 0 deletions Tests/Collector/EventListener/SchemaFilterListenerTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
<?php

declare(strict_types=1);

namespace Doctrine\Bundle\MigrationsBundle\Tests\Collector\EventListener;

use Doctrine\Bundle\MigrationsBundle\EventListener\SchemaFilterListener;
use Doctrine\DBAL\Schema\Table;
use Doctrine\Migrations\Tools\Console\Command\DoctrineCommand;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Console\Event\ConsoleCommandEvent;
use Symfony\Component\Console\Input\ArrayInput;
use Symfony\Component\Console\Output\NullOutput;

class SchemaFilterListenerTest extends TestCase
{
public function testItFiltersOutMigrationMetadataTableByDefault(): void
{
$listener = new SchemaFilterListener();

self::assertFalse($listener(new Table('doctrine_migration_versions')));
self::assertTrue($listener(new Table('some_other_table')));
}

public function testItFiltersNothingWhenDisabled(): void
{
$listener = new SchemaFilterListener();
$listener->disable();

self::assertTrue($listener(new Table('doctrine_migration_versions')));
self::assertTrue($listener(new Table('some_other_table')));
}

public function testItDisablesItselfWhenTheCurrentCommandIsAMigrationsCommand(): void
{
$listener = new SchemaFilterListener();
$migrationsCommand = new class extends DoctrineCommand {
};

$listener->onConsoleCommand(new ConsoleCommandEvent(
$migrationsCommand,
new ArrayInput([]),
new NullOutput()
));

self::assertTrue($listener(new Table('doctrine_migration_versions')));
}
}

0 comments on commit 2cfbb72

Please sign in to comment.