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 1dd4290 commit 656c9ee
Show file tree
Hide file tree
Showing 5 changed files with 106 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')));
}
}
1 change: 1 addition & 0 deletions phpstan.neon.dist
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ parameters:
phpVersion: 80200
paths:
- %currentWorkingDirectory%/DependencyInjection
- %currentWorkingDirectory%/EventListener
- %currentWorkingDirectory%/Tests

ignoreErrors:
Expand Down
1 change: 1 addition & 0 deletions psalm.xml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
>
<projectFiles>
<directory name="DependencyInjection" />
<directory name="EventListener" />
<directory name="Tests" />
<file name="DoctrineMigrationsBundle.php" />
<ignoreFiles>
Expand Down

0 comments on commit 656c9ee

Please sign in to comment.