Skip to content

Commit

Permalink
Merge pull request #107 from Slamdunk/schema-asserts-filter
Browse files Browse the repository at this point in the history
[Feature] Define schema assets filter in configuration
  • Loading branch information
Slamdunk authored Oct 27, 2023
2 parents b4995df + f626370 commit bd60ff1
Show file tree
Hide file tree
Showing 3 changed files with 110 additions and 4 deletions.
18 changes: 18 additions & 0 deletions example/full-config.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
use Doctrine\Common\Cache\XcacheCache;
use Doctrine\Common\Cache\ZendDataCache;
use Doctrine\DBAL\Driver\PDOMySql\Driver;
use Doctrine\DBAL\Schema\AbstractAsset;
use Doctrine\Migrations\Configuration\Migration\ConfigurationLoader;
use Doctrine\Migrations\DependencyFactory;
use Doctrine\Migrations\Tools\Console\Command;
Expand Down Expand Up @@ -63,6 +64,7 @@
'app.foo.middleware', // Will be looked up in the container.
'app.bar.middleware', // Will be looked up in the container.
],
'schema_assets_filter' => 'my_schema_assets_filter',
],
],
'connection' => [
Expand Down Expand Up @@ -193,6 +195,22 @@

DependencyFactory::class => DependencyFactoryFactory::class,
ConfigurationLoader::class => ConfigurationLoaderFactory::class,

'my_schema_assets_filter' => static function (): callable {
/**
* Filter out assets (table, sequence) by name from Schema
* because ones have no mapping and this cause unwanted create|drop statements in migration
* generated with migrations:diff command when compare ORM schema and schema introspected from database
*/
return static fn (AbstractAsset|string $asset): bool => ! in_array(
$asset instanceof AbstractAsset ? $asset->getName() : $asset,
[
'sequence_to_generate_value',
'table_without_doctrine_mapping',
],
true,
);
},
],
],
];
5 changes: 5 additions & 0 deletions src/ConfigurationFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,10 @@ protected function createWithConfig(ContainerInterface $container, string $confi
$configuration->setEntityListenerResolver($config['entity_listener_resolver']);
}

if (is_string($config['schema_assets_filter'])) {
$configuration->setSchemaAssetsFilter($container->get($config['schema_assets_filter']));
}

if ($config['default_repository_class_name'] !== null) {
$configuration->setDefaultRepositoryClassName($config['default_repository_class_name']);
}
Expand Down Expand Up @@ -214,6 +218,7 @@ protected function getDefaultConfig(string $configKey): array
'repository_factory' => null,
'class_metadata_factory_name' => null,
'entity_listener_resolver' => null,
'schema_assets_filter' => null,
'second_level_cache' => [
'enabled' => false,
'default_lifetime' => 3600,
Expand Down
91 changes: 87 additions & 4 deletions test/ConfigurationFactoryTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
use Psr\Container\ContainerInterface;
use ReflectionProperty;
use Roave\PsrContainerDoctrine\ConfigurationFactory;
use TypeError;

use function in_array;

Expand Down Expand Up @@ -130,12 +131,94 @@ static function (string $id): bool {
self::assertSame([$middlewareFoo, $middlewareBar], $configuration->getMiddlewares());
}

public function testWillSetSchemaAssetsFilterByContainerId(): void
{
$testFilter = static fn (): bool => true;
$config = [
'doctrine' => [
'configuration' => [
'orm_default' => ['schema_assets_filter' => 'testFilterContainerId'],
],
],
];

$container = $this->createStub(ContainerInterface::class);

$container
->method('has')
->willReturnCallback(
static fn (string $id) => in_array(
$id,
[
'config',
'doctrine.driver.orm_default',
'testFilterContainerId',
],
true,
),
);

$container
->method('get')
->willReturnMap(
[
['config', $config],
['doctrine.driver.orm_default', $this->createStub(MappingDriver::class)],
['testFilterContainerId', $testFilter],
],
);

$configuration = (new ConfigurationFactory())($container);

self::assertSame($testFilter, $configuration->getSchemaAssetsFilter());
}

public function testMistypeInSchemaAssetsFilterResolvedContainerId(): void
{
$testFilter = ['misconfig' => 'resolved service is not callable'];
$config = [
'doctrine' => [
'configuration' => [
'orm_default' => ['schema_assets_filter' => 'testFilterContainerId'],
],
],
];

$container = $this->createStub(ContainerInterface::class);

$container
->method('has')
->willReturnCallback(
static fn (string $id) => in_array(
$id,
[
'config',
'doctrine.driver.orm_default',
'testFilterContainerId',
],
true,
),
);

$container
->method('get')
->willReturnMap(
[
['config', $config],
['doctrine.driver.orm_default', $this->createStub(MappingDriver::class)],
['testFilterContainerId', $testFilter],
],
);

$this->expectException(TypeError::class);
$this->expectExceptionMessage('Doctrine\DBAL\Configuration::setSchemaAssetsFilter(): Argument #1 ($callable) must be of type ?callable, array given');

(new ConfigurationFactory())($container);
}

/** @param non-empty-string $propertyName */
private function exctractPropertyValue(object $object, string $propertyName): mixed
{
$property = new ReflectionProperty($object, $propertyName);
$property->setAccessible(true);

return $property->getValue($object);
return (new ReflectionProperty($object, $propertyName))->getValue($object);
}
}

0 comments on commit bd60ff1

Please sign in to comment.