Skip to content
Permalink
Browse files

EZP-30057: Implemented Schema Exporter, Importer and Builder (#1)

* EZP-30057: Implemented Schema Exporter for custom Doctrine Schema format

* EZP-30057: [Tests] Implemented SchemaImporter tests

* EZP-30057: Implemented Schema Importer for custom Doctrine Schema format

* EZP-30057: [Tests] Implemented SchemaExporter tests

* EZP-30057: [Tests] Implemented SchemaBuilder test

* EZP-30057: Created DbPlatform Factory of AbstractPlatform instances

* EZP-30057: Created EventSubscriber for SQLite session init

* EZP-30057: [Bundle] Defined Extension alias and configuration

* EZP-30057: Implemented SchemaBuilder extensibility point

* [Doc] Updated README.md with brief description of available APIs

* Updated type-hinting for DbPlatformFactory

* Updated src/lib/Database/DbPlatformFactory.php

* Updated type-hinting for SchemaBuilder and impl. of DbPlatform

* Updated src/lib/API/Builder/SchemaBuilder.php

* Updated src/lib/Database/DbPlatform/PostgreSqlDbPlatform.php

* Updated src/lib/Database/DbPlatform/SqliteDbPlatform.php
  • Loading branch information...
alongosz committed Mar 6, 2019
1 parent 531a3e8 commit 7ee37ec860fb19fbb9256130860d8a7ae2bb1e98
Showing with 1,809 additions and 1 deletion.
  1. +76 −1 README.md
  2. +42 −0 src/bundle/DependencyInjection/Configuration.php
  3. +20 −0 src/bundle/DependencyInjection/DoctrineSchemaExtension.php
  4. +9 −0 src/bundle/DoctrineSchemaBundle.php
  5. +8 −0 src/bundle/Resources/config/api.yaml
  6. +25 −0 src/bundle/Resources/config/services.yaml
  7. +39 −0 src/lib/API/Builder/SchemaBuilder.php
  8. +28 −0 src/lib/API/DbPlatformFactory.php
  9. +46 −0 src/lib/API/Event/SchemaBuilderEvent.php
  10. +16 −0 src/lib/API/Event/SchemaBuilderEvents.php
  11. +20 −0 src/lib/API/Exception/InvalidConfigurationException.php
  12. +26 −0 src/lib/API/SchemaExporter.php
  13. +45 −0 src/lib/API/SchemaImporter.php
  14. +81 −0 src/lib/Builder/SchemaBuilder.php
  15. +24 −0 src/lib/Database/DbPlatform/DbPlatform.php
  16. +68 −0 src/lib/Database/DbPlatform/PostgreSqlDbPlatform.php
  17. +84 −0 src/lib/Database/DbPlatform/SqliteDbPlatform.php
  18. +36 −0 src/lib/Database/DbPlatformFactory.php
  19. +37 −0 src/lib/Event/Subscriber/SqliteSessionInit.php
  20. +54 −0 src/lib/Exporter/SchemaExporter.php
  21. +166 −0 src/lib/Exporter/Table/SchemaTableExporter.php
  22. +148 −0 src/lib/Importer/SchemaImporter.php
  23. +54 −0 tests/lib/Builder/SchemaBuilderTest.php
  24. +46 −0 tests/lib/Database/Builder/MySqlTestDatabaseBuilder.php
  25. +34 −0 tests/lib/Database/Builder/SqliteTestDatabaseBuilder.php
  26. +22 −0 tests/lib/Database/Builder/TestDatabaseBuilder.php
  27. +13 −0 tests/lib/Database/TestDatabaseConfigurationException.php
  28. +46 −0 tests/lib/Database/TestDatabaseFactory.php
  29. +152 −0 tests/lib/Exporter/SchemaExporterTest.php
  30. +6 −0 tests/lib/Exporter/_fixtures/input/mysql/composite_pk.sql
  31. +15 −0 tests/lib/Exporter/_fixtures/input/mysql/foreign_key.sql
  32. +5 −0 tests/lib/Exporter/_fixtures/input/mysql/simple_pk.sql
  33. +3 −0 tests/lib/Exporter/_fixtures/input/mysql/varchar_length.sql
  34. +6 −0 tests/lib/Exporter/_fixtures/input/sqlite/composite_pk.sql
  35. +15 −0 tests/lib/Exporter/_fixtures/input/sqlite/foreign_key.sql
  36. +4 −0 tests/lib/Exporter/_fixtures/input/sqlite/simple_pk.sql
  37. +3 −0 tests/lib/Exporter/_fixtures/input/sqlite/varchar_length.sql
  38. +7 −0 tests/lib/Exporter/_fixtures/output/composite_pk.yaml
  39. +15 −0 tests/lib/Exporter/_fixtures/output/foreign_key.yaml
  40. +6 −0 tests/lib/Exporter/_fixtures/output/simple_pk.yaml
  41. +4 −0 tests/lib/Exporter/_fixtures/output/varchar_length.yaml
  42. +205 −0 tests/lib/Importer/SchemaImporterTest.php
  43. +4 −0 tests/lib/Importer/_fixtures/00-simple_pk.yaml
  44. +7 −0 tests/lib/Importer/_fixtures/01-composite_pk.yaml
  45. +7 −0 tests/lib/Importer/_fixtures/02-composite_pk_with_ai.yaml
  46. +13 −0 tests/lib/Importer/_fixtures/03-foreign_key.yaml
  47. +4 −0 tests/lib/Importer/_fixtures/04-nullable_field.yaml
  48. +4 −0 tests/lib/Importer/_fixtures/05-varchar_length.yaml
  49. +11 −0 tests/lib/Importer/_fixtures/06-index.yaml
@@ -1,6 +1,81 @@
# Doctrine Schema Bundle

This package provides basic abstraction layer for cross-DBMS schema import.
This Symfony Bundle provides basic abstraction layer for cross-DBMS schema import.

It introduces custom Yaml format for schema definition and provides autowired APIs.

## Schema Builder

Provided by APIs defined on the `\EzSystems\DoctrineSchema\API\SchemaImporter` interface,
imports given Yaml source string or Yaml file into `\Doctrine\DBAL\Schema` object.

## Schema Exporter

Provided by APIs defined on the `\EzSystems\DoctrineSchema\API\SchemaExporter` interface,
exports given `\Doctrine\DBAL\Schema` object to the custom Yaml format.

## SchemaBuilder

Provided by APIs defined on the `\EzSystems\DoctrineSchema\API\Builder\SchemaBuilder` interface,
is an extensibility point to be used by Symfony-based projects.

The `SchemaBuilder` is event-driven. To hook into the process of building schema, a custom `EventSubscriber` is required, e.g.

```php
use EzSystems\DoctrineSchema\API\Event\SchemaBuilderEvent;
use EzSystems\DoctrineSchema\API\Event\SchemaBuilderEvents;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
class BuildSchemaSubscriber implements EventSubscriberInterface
{
/**
* @var string
*/
private $schemaFilePath;
public function __construct(string $schemaFilePath)
{
$this->schemaFilePath = $schemaFilePath;
}
/**
* Returns an array of events this subscriber wants to listen to.
*
* @return string[]
*/
public static function getSubscribedEvents()
{
return [
SchemaBuilderEvents::BUILD_SCHEMA => ['onBuildSchema', 200],
];
}
/**
* @param \EzSystems\DoctrineSchema\API\Builder\SchemaBuilderEvent $event
*/
public function onBuildSchema(SchemaBuilderEvent $event)
{
$event
->getSchemaBuilder()
->importSchemaFromFile($this->schemaFilePath);
}
}
```

Schema provided in this way can be imported into Schema object by e.g.:

```php
public function __construct(SchemaBuilder $schemaBuilder)
{
$this->schemaBuilder = $schemaBuilder;
}
public function importSchema()
{
$schema = $this->schemaBuilder->buildSchema();
// ...
}
```

## Copyright & License

@@ -0,0 +1,42 @@
<?php
/**
* @copyright Copyright (C) eZ Systems AS. All rights reserved.
* @license For full copyright and license information view LICENSE file distributed with this source code.
*/
declare(strict_types=1);
namespace EzSystems\DoctrineSchemaBundle\DependencyInjection;
use Symfony\Component\Config\Definition\Builder\TreeBuilder;
use Symfony\Component\Config\Definition\ConfigurationInterface;
/**
* Symfony extension configuration definition for ez_doctrine_schema extension.
*/
class Configuration implements ConfigurationInterface
{
/**
* {@inheritdoc}
*/
public function getConfigTreeBuilder(): TreeBuilder
{
$treeBuilder = new TreeBuilder();
$rootNode = $treeBuilder->root('ez_doctrine_schema');
$rootNode
->children()
->arrayNode('tables')
->children()
->arrayNode('options')
->scalarPrototype()
->end()
->end()
->end()
->end()
->end()
;
return $treeBuilder;
}
}
@@ -16,6 +16,16 @@
class DoctrineSchemaExtension extends Extension
{
/**
* Override default extension alias name to include eZ vendor in name.
*
* @return string
*/
public function getAlias(): string
{
return 'ez_doctrine_schema';
}
/**
* Load Doctrine Schema Extension config.
*
@@ -36,5 +46,15 @@ public function load(array $configs, ContainerBuilder $container)
$loader->load('api.yaml');
$container->addResource(new FileResource(__DIR__ . '/../Resources/config/api.yaml'));
$configuration = new Configuration();
$config = $this->processConfiguration($configuration, $configs);
if (isset($config['tables']['options'])) {
$container->setParameter(
'ez_doctrine_schema.default_table_options',
$config['tables']['options']
);
}
}
}
@@ -8,8 +8,17 @@
namespace EzSystems\DoctrineSchemaBundle;
use EzSystems\DoctrineSchemaBundle\DependencyInjection\DoctrineSchemaExtension;
use Symfony\Component\DependencyInjection\Extension\ExtensionInterface;
use Symfony\Component\HttpKernel\Bundle\Bundle;
class DoctrineSchemaBundle extends Bundle
{
/**
* {@inheritdoc}
*/
public function getContainerExtension(): ExtensionInterface
{
return new DoctrineSchemaExtension();
}
}
@@ -3,3 +3,11 @@ services:
autowire: true
autoconfigure: true
public: false

EzSystems\DoctrineSchema\API\SchemaExporter: '@EzSystems\DoctrineSchema\Exporter\SchemaExporter'

EzSystems\DoctrineSchema\API\SchemaImporter: '@EzSystems\DoctrineSchema\Importer\SchemaImporter'

EzSystems\DoctrineSchema\API\DbPlatformFactory: '@EzSystems\DoctrineSchema\Database\DbPlatformFactory'

EzSystems\DoctrineSchema\API\Builder\SchemaBuilder: '@EzSystems\DoctrineSchema\Builder\SchemaBuilder'
@@ -1,5 +1,30 @@
parameters:
ez_doctrine_schema.default_table_options: []

services:
_defaults:
autowire: true
autoconfigure: true
public: false
_instanceof:
EzSystems\DoctrineSchema\Database\DbPlatform\DbPlatform:
tags: ['doctrine.dbplatform']

EzSystems\DoctrineSchema\Exporter\:
resource: '../../../lib/Exporter/*'

EzSystems\DoctrineSchema\Importer\:
resource: '../../../lib/Importer/*'

EzSystems\DoctrineSchema\Database\DbPlatformFactory:
arguments:
$dbPlatforms: !tagged doctrine.dbplatform

EzSystems\DoctrineSchema\Database\DbPlatform\:
resource: '../../../lib/Database/DbPlatform/*'

EzSystems\DoctrineSchema\Builder\SchemaBuilder:
arguments:
$defaultTableOptions: '%ez_doctrine_schema.default_table_options%'

Doctrine\Common\EventManager: ~
@@ -0,0 +1,39 @@
<?php
/**
* @copyright Copyright (C) eZ Systems AS. All rights reserved.
* @license For full copyright and license information view LICENSE file distributed with this source code.
*/
declare(strict_types=1);
namespace EzSystems\DoctrineSchema\API\Builder;
use Doctrine\DBAL\Schema\Schema;
/**
* Doctrine\DBAL\Schema event-driven builder.
*/
interface SchemaBuilder
{
/**
* Build schema by dispatching the SchemaBuilderEvent event.
*
* To build schema you should implement EventSubscriber subscribing to SchemaBuilderEvents::BUILD_SCHEMA.
* The method handling this event accepts single argument of SchemaBuilderEvent type
*
* @see \EzSystems\DoctrineSchema\API\Event\SchemaBuilderEvent
* @see \EzSystems\DoctrineSchema\API\Event\SchemaBuilderEvents::BUILD_SCHEMA
*
* @return \Doctrine\DBAL\Schema\Schema
*/
public function buildSchema(): Schema;
/**
* Import Schema from Yaml schema definition file into Schema object.
*
* @param string $schemaFilePath
*
* @return \Doctrine\DBAL\Schema\Schema
*/
public function importSchemaFromFile(string $schemaFilePath): Schema;
}
@@ -0,0 +1,28 @@
<?php
/**
* @copyright Copyright (C) eZ Systems AS. All rights reserved.
* @license For full copyright and license information view LICENSE file distributed with this source code.
*/
declare(strict_types=1);
namespace EzSystems\DoctrineSchema\API;
use Doctrine\DBAL\Platforms\AbstractPlatform;
interface DbPlatformFactory
{
/**
* Create instance of Doctrine AbstractPlatform for the given driver name.
*
* Factory can return null, which means that the Driver should decide.
*
* @see \Doctrine\DBAL\Platforms\AbstractPlatform
* @see \Doctrine\DBAL\Driver
*
* @param string $driverName (e.g. 'pdo_mysql', 'pdo_pgsql', 'pdo_sqlite').
*
* @return \Doctrine\DBAL\Platforms\AbstractPlatform|null if null - let the Driver decide
*/
public function createDatabasePlatformFromDriverName(string $driverName): ?AbstractPlatform;
}
@@ -0,0 +1,46 @@
<?php
/**
* @copyright Copyright (C) eZ Systems AS. All rights reserved.
* @license For full copyright and license information view LICENSE file distributed with this source code.
*/
declare(strict_types=1);
namespace EzSystems\DoctrineSchema\API\Event;
use Doctrine\DBAL\Schema\Schema;
use EzSystems\DoctrineSchema\API\Builder\SchemaBuilder;
use Symfony\Component\EventDispatcher\Event;
class SchemaBuilderEvent extends Event
{
/**
* @var \EzSystems\DoctrineSchema\API\Builder\SchemaBuilder
*/
private $schemaBuilder;
/**
* @var \Doctrine\DBAL\Schema\Schema
*/
private $schema;
/**
* @param \EzSystems\DoctrineSchema\API\Builder\SchemaBuilder $schemaBuilder
* @param \Doctrine\DBAL\Schema\Schema $schema
*/
public function __construct(SchemaBuilder $schemaBuilder, Schema $schema)
{
$this->schemaBuilder = $schemaBuilder;
$this->schema = $schema;
}
public function getSchema(): Schema
{
return $this->schema;
}
public function getSchemaBuilder(): SchemaBuilder
{
return $this->schemaBuilder;
}
}
@@ -0,0 +1,16 @@
<?php
/**
* @copyright Copyright (C) eZ Systems AS. All rights reserved.
* @license For full copyright and license information view LICENSE file distributed with this source code.
*/
declare(strict_types=1);
namespace EzSystems\DoctrineSchema\API\Event;
use Symfony\Component\EventDispatcher\Event;
class SchemaBuilderEvents extends Event
{
const BUILD_SCHEMA = 'ez.schema.build_schema';
}
@@ -0,0 +1,20 @@
<?php
/**
* @copyright Copyright (C) eZ Systems AS. All rights reserved.
* @license For full copyright and license information view LICENSE file distributed with this source code.
*/
declare(strict_types=1);
namespace EzSystems\DoctrineSchema\API\Exception;
use Exception;
use Throwable;
class InvalidConfigurationException extends Exception
{
public function __construct(string $message = '', int $code = 1, Throwable $previous = null)
{
parent::__construct("Invalid schema configuration: {$message}", $code, $previous);
}
}

0 comments on commit 7ee37ec

Please sign in to comment.
You can’t perform that action at this time.