Refactored Doctrine Bundle dbalLoad() to make use of config merging.
This commit is contained in:
parent
4909987e23
commit
c7e3b2381a
@ -29,20 +29,6 @@ use Symfony\Bundle\DoctrineAbstractBundle\DependencyInjection\AbstractDoctrineEx
|
||||
*/
|
||||
class DoctrineExtension extends AbstractDoctrineExtension
|
||||
{
|
||||
public function dbalLoad(array $configs, ContainerBuilder $container)
|
||||
{
|
||||
foreach ($configs as $config) {
|
||||
$this->doDbalLoad($config, $container);
|
||||
}
|
||||
}
|
||||
|
||||
public function ormLoad(array $configs, ContainerBuilder $container)
|
||||
{
|
||||
foreach ($configs as $config) {
|
||||
$this->doOrmLoad($config, $container);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the DBAL configuration.
|
||||
*
|
||||
@ -53,10 +39,174 @@ class DoctrineExtension extends AbstractDoctrineExtension
|
||||
* @param array $config An array of configuration settings
|
||||
* @param ContainerBuilder $container A ContainerBuilder instance
|
||||
*/
|
||||
protected function doDbalLoad($config, ContainerBuilder $container)
|
||||
public function dbalLoad(array $configs, ContainerBuilder $container)
|
||||
{
|
||||
$this->loadDbalDefaults($config, $container);
|
||||
$this->loadDbalConnections($config, $container);
|
||||
$config = $this->mergeDbalConfig($configs);
|
||||
|
||||
$loader = new XmlFileLoader($container, __DIR__.'/../Resources/config');
|
||||
$loader->load('dbal.xml');
|
||||
|
||||
$container->setAlias('database_connection', sprintf('doctrine.dbal.%s_connection', $config['default_connection']));
|
||||
$container->setParameter('doctrine.dbal.default_connection', $config['default_connection']);
|
||||
|
||||
foreach ($config['connections'] as $name => $connection) {
|
||||
$this->loadDbalConnection($connection, $container);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Merges a set of exclusive independent DBAL configurations into another.
|
||||
*
|
||||
* Beginning from the default settings this method acts as incremental merge
|
||||
* of all the configurations that are passed through multiple environment
|
||||
* and fallbacks for example config.yml + config_dev.yml
|
||||
*
|
||||
* @param array $configs
|
||||
* @return array
|
||||
*/
|
||||
protected function mergeDbalConfig(array $configs)
|
||||
{
|
||||
$supportedConnectionParams = array(
|
||||
'dbname' => 'dbname',
|
||||
'host' => 'host',
|
||||
'port' => 'port',
|
||||
'user' => 'user',
|
||||
'password' => 'password',
|
||||
'driver' => 'driver',
|
||||
'driver-class' => 'driverClass', // doctrine conv.
|
||||
'options' => 'driverOptions', // doctrine conv.
|
||||
'path' => 'path',
|
||||
'unix-socket' => 'unix_socket',
|
||||
'memory' => 'memory',
|
||||
'driver_class' => 'driverClass', // doctrine conv.
|
||||
'unix_socket' => 'unix_socket',
|
||||
'wrapper_class' => 'wrapperClass', // doctrine conv.
|
||||
'wrapper-class' => 'wrapperClass', // doctrine conv.
|
||||
'charset' => 'charset',
|
||||
);
|
||||
$supportedConfigParams = array(
|
||||
'configuration-class' => 'configuration_class',
|
||||
'platform-service' => 'platform_service',
|
||||
'configuration_class' => 'configuration_class',
|
||||
'platform_service' => 'platform_service'
|
||||
);
|
||||
$mergedConfig = array(
|
||||
'default_connection' => 'default',
|
||||
);
|
||||
$connectionDefaults = array(
|
||||
'driver' => array(
|
||||
'host' => 'localhost',
|
||||
'driver' => 'pdo_mysql',
|
||||
'driverOptions' => array(),
|
||||
'user' => 'root',
|
||||
'password' => null,
|
||||
'port' => null,
|
||||
),
|
||||
'container' => array(
|
||||
'configuration_class' => 'Doctrine\DBAL\Configuration',
|
||||
'wrapper_class' => null,
|
||||
),
|
||||
);
|
||||
|
||||
foreach ($configs AS $config) {
|
||||
if (isset($config['default-connection'])) {
|
||||
$mergedConfig['default_connection'] = $config['default-connection'];
|
||||
} else if (isset($config['default_connection'])) {
|
||||
$mergedConfig['default_connection'] = $config['default_connection'];
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($configs AS $config) {
|
||||
if (isset($config['connections'])) {
|
||||
$configConnections = $config['connections'];
|
||||
if (isset($config['connections']['connection']) && isset($config['connections']['connection'][0])) {
|
||||
$configConnections = $config['connections']['connection'];
|
||||
}
|
||||
} else {
|
||||
$configConnections[$mergedConfig['default_connection']] = $config;
|
||||
}
|
||||
|
||||
foreach ($configConnections as $name => $connection) {
|
||||
$connectionName = isset($connection['id']) ? $connection['id'] : $name;
|
||||
if (!isset($mergedConfig['connections'][$connectionName])) {
|
||||
$mergedConfig['connections'][$connectionName] = $connectionDefaults;
|
||||
}
|
||||
$mergedConfig['connections'][$connectionName]['name'] = $connectionName;
|
||||
|
||||
foreach ($connection AS $k => $v) {
|
||||
if (isset($supportedConnectionParams[$k])) {
|
||||
$mergedConfig['connections'][$connectionName]['driver'][$supportedConnectionParams[$k]] = $v;
|
||||
} else if (isset($supportedConfigParams[$k])) {
|
||||
$mergedConfig['connections'][$connectionName]['container'][$supportedConfigParams[$k]] = $v;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $mergedConfig;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads a configured DBAL connection.
|
||||
*
|
||||
* @param array $connection A dbal connection configuration.
|
||||
* @param ContainerBuilder $container A ContainerBuilder instance
|
||||
*/
|
||||
protected function loadDbalConnection(array $connection, ContainerBuilder $container)
|
||||
{
|
||||
$containerDef = new Definition($connection['container']['configuration_class']);
|
||||
$containerDef->setPublic(false);
|
||||
$containerDef->addMethodCall('setSQLLogger', array(new Reference('doctrine.dbal.logger')));
|
||||
$container->setDefinition(sprintf('doctrine.dbal.%s_connection.configuration', $connection['name']), $containerDef);
|
||||
|
||||
$driverOptions = $connection['driver'];
|
||||
|
||||
$driverDef = new Definition('Doctrine\DBAL\DriverManager');
|
||||
$driverDef->setFactoryMethod('getConnection');
|
||||
$container->setDefinition(sprintf('doctrine.dbal.%s_connection', $connection['name']), $driverDef);
|
||||
|
||||
// event manager
|
||||
$eventManagerId = sprintf('doctrine.dbal.%s_connection.event_manager', $connection['name']);
|
||||
$eventManagerDef = new Definition('%doctrine.dbal.event_manager_class%');
|
||||
$eventManagerDef->setPublic(false);
|
||||
$container->setDefinition($eventManagerId, $eventManagerDef);
|
||||
|
||||
if ($container->getParameter('doctrine.dbal.default_connection') == $connection['name']) {
|
||||
$container->setAlias('doctrine.dbal.event_manager', new Alias(sprintf('doctrine.dbal.%s_connection.event_manager', $connection['name']), false));
|
||||
}
|
||||
|
||||
if (isset($driverOptions['charset'])) {
|
||||
if ( (isset($driverOptions['driver']) && stripos($driverOptions['driver'], 'mysql') !== false) ||
|
||||
(isset($driverOptions['driverClass']) && stripos($driverOptions['driverClass'], 'mysql') !== false)) {
|
||||
$mysqlSessionInit = new Definition('%doctrine.dbal.events.mysql_session_init.class%');
|
||||
$mysqlSessionInit->setArguments(array($driverOptions['charset']));
|
||||
$mysqlSessionInit->setPublic(false);
|
||||
$mysqlSessionInit->addTag(sprintf('doctrine.dbal.%s_event_subscriber', $connection['name']));
|
||||
|
||||
$container->setDefinition(
|
||||
sprintf('doctrine.dbal.%s_connection.events.mysqlsessioninit', $connection['name']),
|
||||
$mysqlSessionInit
|
||||
);
|
||||
unset($driverOptions['charset']);
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($connection['container']['platform_service'])) {
|
||||
$driverOptions['platform'] = new Reference($connection['container']['platform_service']);
|
||||
}
|
||||
|
||||
$driverDef->setArguments(array(
|
||||
$driverOptions,
|
||||
new Reference(sprintf('doctrine.dbal.%s_connection.configuration', $connection['name'])),
|
||||
new Reference(sprintf('doctrine.dbal.%s_connection.event_manager', $connection['name']))
|
||||
));
|
||||
}
|
||||
|
||||
public function ormLoad(array $configs, ContainerBuilder $container)
|
||||
{
|
||||
foreach ($configs as $config) {
|
||||
$this->doOrmLoad($config, $container);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -75,175 +225,6 @@ class DoctrineExtension extends AbstractDoctrineExtension
|
||||
$this->loadOrmEntityManagers($config, $container);
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the DBAL configuration defaults.
|
||||
*
|
||||
* @param array $config An array of configuration settings
|
||||
* @param ContainerBuilder $container A ContainerBuilder instance
|
||||
*/
|
||||
protected function loadDbalDefaults(array $config, ContainerBuilder $container)
|
||||
{
|
||||
// arbitrary service that is always part of the "dbal" services. Its used to check if the
|
||||
// defaults have to applied (first time run) or ignored (second or n-th run due to imports)
|
||||
if (!$container->hasDefinition('doctrine.dbal.logger')) {
|
||||
$loader = new XmlFileLoader($container, __DIR__.'/../Resources/config');
|
||||
$loader->load('dbal.xml');
|
||||
}
|
||||
|
||||
$defaultConnectionName = isset($config['default-connection']) ? $config['default-connection'] : (isset($config['default_connection']) ? $config['default_connection'] : $container->getParameter('doctrine.dbal.default_connection'));
|
||||
$container->setAlias('database_connection', sprintf('doctrine.dbal.%s_connection', $defaultConnectionName));
|
||||
$container->setParameter('doctrine.dbal.default_connection', $defaultConnectionName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the configured DBAL connections.
|
||||
*
|
||||
* @param array $config An array of configuration settings
|
||||
* @param ContainerBuilder $container A ContainerBuilder instance
|
||||
*/
|
||||
protected function loadDbalConnections(array $config, ContainerBuilder $container)
|
||||
{
|
||||
$connections = $this->getDbalConnections($config, $container);
|
||||
foreach ($connections as $name => $connection) {
|
||||
$connection['name'] = $name;
|
||||
$this->loadDbalConnection($connection, $container);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads a configured DBAL connection.
|
||||
*
|
||||
* @param array $connection A dbal connection configuration.
|
||||
* @param ContainerBuilder $container A ContainerBuilder instance
|
||||
*/
|
||||
protected function loadDbalConnection(array $connection, ContainerBuilder $container)
|
||||
{
|
||||
// previously registered?
|
||||
if ($container->hasDefinition(sprintf('doctrine.dbal.%s_connection', $connection['name']))) {
|
||||
$driverDef = $container->getDefinition(sprintf('doctrine.dbal.%s_connection', $connection['name']));
|
||||
$arguments = $driverDef->getArguments();
|
||||
$driverOptions = $arguments[0];
|
||||
} else {
|
||||
$containerClass = isset($connection['configuration-class']) ? $connection['configuration-class'] : (isset($connection['configuration_class']) ? $connection['configuration_class'] : 'Doctrine\DBAL\Configuration');
|
||||
$containerDef = new Definition($containerClass);
|
||||
$containerDef->setPublic(false);
|
||||
$containerDef->addMethodCall('setSqlLogger', array(new Reference('doctrine.dbal.logger')));
|
||||
$container->setDefinition(sprintf('doctrine.dbal.%s_connection.configuration', $connection['name']), $containerDef);
|
||||
|
||||
$driverOptions = array();
|
||||
$driverDef = new Definition('Doctrine\DBAL\DriverManager');
|
||||
$driverDef->setFactoryMethod('getConnection');
|
||||
$container->setDefinition(sprintf('doctrine.dbal.%s_connection', $connection['name']), $driverDef);
|
||||
}
|
||||
|
||||
if (isset($connection['driver'])) {
|
||||
$driverOptions['driver'] = $connection['driver'];
|
||||
}
|
||||
if (isset($connection['driver-class'])) {
|
||||
$driverOptions['driverClass'] = $connection['driver-class'];
|
||||
}
|
||||
if (isset($connection['driver_class'])) {
|
||||
$driverOptions['driverClass'] = $connection['driver_class'];
|
||||
}
|
||||
if (isset($connection['wrapper-class'])) {
|
||||
$driverOptions['wrapperClass'] = $connection['wrapper-class'];
|
||||
}
|
||||
if (isset($connection['wrapper_class'])) {
|
||||
$driverOptions['wrapperClass'] = $connection['wrapper_class'];
|
||||
}
|
||||
if (isset($connection['options'])) {
|
||||
$driverOptions['driverOptions'] = $connection['options'];
|
||||
}
|
||||
foreach (array('dbname', 'host', 'user', 'password', 'path', 'memory', 'port', 'unix_socket', 'charset') as $key) {
|
||||
if (isset($connection[$key])) {
|
||||
$driverOptions[$key] = $connection[$key];
|
||||
}
|
||||
|
||||
$nKey = str_replace('_', '-', $key);
|
||||
if (isset($connection[$nKey])) {
|
||||
$driverOptions[$key] = $connection[$nKey];
|
||||
}
|
||||
}
|
||||
|
||||
// event manager
|
||||
$eventManagerName = isset($connection['event_manager']) ? $connection['event_manager'] : $connection['name'];
|
||||
$eventManagerId = sprintf('doctrine.dbal.%s_connection.event_manager', $eventManagerName);
|
||||
if (!$container->hasDefinition($eventManagerId)) {
|
||||
$eventManagerDef = new Definition('%doctrine.dbal.event_manager_class%');
|
||||
$eventManagerDef->setPublic(false);
|
||||
$container->setDefinition($eventManagerId, $eventManagerDef);
|
||||
}
|
||||
|
||||
if ($container->getParameter('doctrine.dbal.default_connection') == $connection['name']) {
|
||||
$container->setAlias('doctrine.dbal.event_manager', new Alias(sprintf('doctrine.dbal.%s_connection.event_manager', $connection['name']), false));
|
||||
}
|
||||
|
||||
if (isset($driverOptions['charset'])) {
|
||||
if ( (isset($driverOptions['driver']) && stripos($driverOptions['driver'], 'mysql') !== false) ||
|
||||
(isset($driverOptions['driverClass']) && stripos($driverOptions['driverClass'], 'mysql') !== false)) {
|
||||
$mysqlSessionInit = new Definition('%doctrine.dbal.events.mysql_session_init.class%');
|
||||
$mysqlSessionInit->setArguments(array($driverOptions['charset']));
|
||||
$mysqlSessionInit->setPublic(false);
|
||||
$mysqlSessionInit->addTag(sprintf('doctrine.dbal.%s_event_subscriber', $eventManagerName));
|
||||
|
||||
$container->setDefinition(
|
||||
sprintf('doctrine.dbal.%s_connection.events.mysqlsessioninit', $connection['name']),
|
||||
$mysqlSessionInit
|
||||
);
|
||||
unset($driverOptions['charset']);
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($connection['platform-service'])) {
|
||||
$driverOptions['platform'] = new Reference($connection['platform-service']);
|
||||
}
|
||||
if (isset($connection['platform_service'])) {
|
||||
$driverOptions['platform'] = new Reference($connection['platform_service']);
|
||||
}
|
||||
|
||||
$driverDef->setArguments(array(
|
||||
$driverOptions,
|
||||
new Reference(sprintf('doctrine.dbal.%s_connection.configuration', $connection['name'])),
|
||||
new Reference(sprintf('doctrine.dbal.%s_connection.event_manager', $connection['name']))
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the configured DBAL connections.
|
||||
*
|
||||
* @param array $config An array of configuration settings
|
||||
* @param ContainerBuilder $container A ContainerBuilder instance
|
||||
*/
|
||||
protected function getDbalConnections(array $config, ContainerBuilder $container)
|
||||
{
|
||||
$defaultConnectionName = $container->getParameter('doctrine.dbal.default_connection');
|
||||
$defaultConnection = array(
|
||||
'driver' => 'pdo_mysql',
|
||||
'user' => 'root',
|
||||
'password' => null,
|
||||
'host' => 'localhost',
|
||||
'port' => null,
|
||||
'event_manager_class' => 'Doctrine\Common\EventManager',
|
||||
'configuration_class' => 'Doctrine\DBAL\Configuration',
|
||||
'wrapper_class' => null,
|
||||
'options' => array()
|
||||
);
|
||||
$connections = array();
|
||||
if (isset($config['connections'])) {
|
||||
$configConnections = $config['connections'];
|
||||
if (isset($config['connections']['connection']) && isset($config['connections']['connection'][0])) {
|
||||
// Multiple connections
|
||||
$configConnections = $config['connections']['connection'];
|
||||
}
|
||||
foreach ($configConnections as $name => $connection) {
|
||||
$connections[isset($connection['id']) ? $connection['id'] : $name] = array_merge($defaultConnection, $connection);
|
||||
}
|
||||
} else {
|
||||
$connections = array($defaultConnectionName => array_merge($defaultConnection, $config));
|
||||
}
|
||||
return $connections;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the ORM default configuration.
|
||||
*
|
||||
|
@ -25,6 +25,9 @@
|
||||
<xsd:attribute name="unix-socket" type="xsd:string" />
|
||||
<xsd:attribute name="memory" type="xsd:boolean" />
|
||||
<xsd:attribute name="charset" type="xsd:string" />
|
||||
<xsd:attribute name="configuration-class" type="xsd:string" />
|
||||
<xsd:attribute name="event-manager-class" type="xsd:string" />
|
||||
<xsd:attribute name="wrapper-class" type="xsd:string" />
|
||||
<xsd:attribute name="platform-service" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
|
||||
|
@ -23,25 +23,25 @@ abstract class AbstractDoctrineExtensionTest extends TestCase
|
||||
{
|
||||
abstract protected function loadFromFile(ContainerBuilder $container, $file);
|
||||
|
||||
public function testDbalLoad()
|
||||
public function testDbalOverrideDefaultConnection()
|
||||
{
|
||||
$container = $this->getContainer();
|
||||
$loader = new DoctrineExtension();
|
||||
|
||||
$loader->dbalLoad(array(array()), $container);
|
||||
$this->assertEquals('Symfony\\Bundle\\DoctrineBundle\\DataCollector\\DoctrineDataCollector', $container->getParameter('doctrine.data_collector.class'), '->dbalLoad() loads the dbal.xml file if not already loaded');
|
||||
$loader->dbalLoad(array(array(), array('default_connection' => 'foo'), array()), $container);
|
||||
|
||||
// doctrine.dbal.default_connection
|
||||
$this->assertEquals('default', $container->getParameter('doctrine.dbal.default_connection'), '->dbalLoad() overrides existing configuration options');
|
||||
$loader->dbalLoad(array(array('default_connection' => 'foo')), $container);
|
||||
$this->assertEquals('foo', $container->getParameter('doctrine.dbal.default_connection'), '->dbalLoad() overrides existing configuration options');
|
||||
$loader->dbalLoad(array(array()), $container);
|
||||
$this->assertEquals('foo', $container->getParameter('doctrine.dbal.default_connection'), '->dbalLoad() overrides existing configuration options');
|
||||
}
|
||||
|
||||
public function testDbalLoad()
|
||||
{
|
||||
$container = $this->getContainer();
|
||||
$loader = new DoctrineExtension();
|
||||
$loader->dbalLoad(array(array('password' => 'foo')), $container);
|
||||
|
||||
$loader->dbalLoad(array(array(), array('default_connection' => 'foo'), array()), $container);
|
||||
|
||||
$arguments = $container->getDefinition('doctrine.dbal.default_connection')->getArguments();
|
||||
$config = $arguments[0];
|
||||
|
||||
@ -229,10 +229,12 @@ abstract class AbstractDoctrineExtensionTest extends TestCase
|
||||
|
||||
$this->assertDICConstructorArguments($definition, array(
|
||||
array(
|
||||
'host' => 'localhost',
|
||||
'driver' => 'pdo_mysql',
|
||||
'driverOptions' => array(),
|
||||
'host' => 'localhost',
|
||||
'user' => 'root',
|
||||
'password' => null,
|
||||
'port' => null,
|
||||
),
|
||||
new Reference('doctrine.dbal.default_connection.configuration'),
|
||||
new Reference('doctrine.dbal.default_connection.event_manager')
|
||||
@ -265,12 +267,13 @@ abstract class AbstractDoctrineExtensionTest extends TestCase
|
||||
|
||||
$this->assertDICConstructorArguments($definition, array(
|
||||
array(
|
||||
'host' => 'localhost',
|
||||
'driver' => 'pdo_sqlite',
|
||||
'driverOptions' => array(),
|
||||
'dbname' => 'sqlite_db',
|
||||
'host' => 'localhost',
|
||||
'user' => 'sqlite_user',
|
||||
'port' => null,
|
||||
'password' => 'sqlite_s3cr3t',
|
||||
'dbname' => 'sqlite_db',
|
||||
'memory' => true,
|
||||
),
|
||||
new Reference('doctrine.dbal.default_connection.configuration'),
|
||||
|
Reference in New Issue
Block a user