Started to integrate the new configuration system (still WIP/dirty)

This commit is contained in:
Kévin Gomez 2014-09-09 21:59:13 +01:00
parent 48b29243f3
commit 09e4da0c19
13 changed files with 53 additions and 413 deletions

View file

@ -75,11 +75,8 @@ abstract class AbstractCommand extends ContainerAwareCommand
// collect all schemas // collect all schemas
$this->copySchemas($kernel, $this->cacheDir); $this->copySchemas($kernel, $this->cacheDir);
// build.properties // propel.json
$this->createBuildPropertiesFile($kernel, $this->cacheDir.'/build.properties'); $this->createPropelConfigurationFile($this->cacheDir.'/propel.json');
// buildtime-conf.xml
$this->createBuildTimeFile($this->cacheDir.'/buildtime-conf.xml');
} }
/** /**
@ -126,7 +123,7 @@ abstract class AbstractCommand extends ContainerAwareCommand
} }
if ($this->input->hasOption('connection')) { if ($this->input->hasOption('connection')) {
$connections = $this->input->getOption('connection') ?: array($this->getContainer()->getParameter('propel.dbal.default_connection')); $connections = $this->input->getOption('connection') ?: array($this->getDefaultConnection());
if (!in_array((string) $database['name'], $connections)) { if (!in_array((string) $database['name'], $connections)) {
// we skip this schema because the connection name doesn't // we skip this schema because the connection name doesn't
@ -203,48 +200,15 @@ abstract class AbstractCommand extends ContainerAwareCommand
/* /*
* Create an XML file which represents propel.configuration * Create an XML file which represents propel.configuration
* *
* @param string $file Should be 'buildtime-conf.xml'. * @param string $file Should be 'propel.json'.
*/ */
protected function createBuildTimeFile($file) protected function createPropelConfigurationFile($file)
{ {
$xml = strtr(<<<EOT $config = array(
<?xml version="1.0"?> 'propel' => $this->getContainer()->getParameter('propel.configuration')
<config> );
<propel>
<datasources default="%default_connection%">
EOT file_put_contents($file, json_encode($config, JSON_PRETTY_PRINT));
, array('%default_connection%' => $this->getContainer()->getParameter('propel.dbal.default_connection')));
$datasources = $this->getContainer()->getParameter('propel.configuration');
foreach ($datasources as $name => $datasource) {
$xml .= strtr(<<<EOT
<datasource id="%name%">
<adapter>%adapter%</adapter>
<connection>
<dsn>%dsn%</dsn>
<user>%username%</user>
<password>%password%</password>
</connection>
</datasource>
EOT
, array(
'%name%' => $name,
'%adapter%' => $datasource['adapter'],
'%dsn%' => $datasource['connection']['dsn'],
'%username%' => $datasource['connection']['user'],
'%password%' => isset($datasource['connection']['password']) ? $datasource['connection']['password'] : '',
));
}
$xml .= <<<EOT
</datasources>
</propel>
</config>
EOT;
file_put_contents($file, $xml);
} }
/** /**
@ -274,11 +238,11 @@ EOT;
protected function getConnectionData($name) protected function getConnectionData($name)
{ {
$knownConnections = $this->getContainer()->getParameter('propel.configuration'); $knownConnections = $this->getContainer()->getParameter('propel.configuration');
if (!isset($knownConnections[$name])) { if (!isset($knownConnections['database']['connections'][$name])) {
throw new \InvalidArgumentException(sprintf('Unknown connection "%s"', $name)); throw new \InvalidArgumentException(sprintf('Unknown connection "%s"', $name));
} }
return $knownConnections[$name]; return $knownConnections['database']['connections'][$name];
} }
/** /**
@ -291,32 +255,8 @@ EOT;
protected function getDsn($connectionName) protected function getDsn($connectionName)
{ {
$connection = $this->getConnectionData($connectionName); $connection = $this->getConnectionData($connectionName);
$connectionData = $connection['connection'];
return sprintf('%s;user=%s;password=%s', $connectionData['dsn'], $connectionData['user'], $connectionData['password']); return $connection['dsn'];
}
/**
* Create a 'build.properties' file.
*
* @param KernelInterface $kernel The application kernel.
* @param string $file Should be 'build.properties'.
*/
protected function createBuildPropertiesFile(KernelInterface $kernel, $file)
{
$fs = new Filesystem();
$buildProperties = $this->getContainer()->getParameter('propel.build_properties');
$iniFile = $kernel->getRootDir().'/config/propel.ini';
if ($fs->exists($iniFile)) {
$buildProperties = array_merge(
parse_ini_file($iniFile),
$buildProperties
);
}
$fs->dumpFile($file, $this->arrayToIni($buildProperties));
} }
/** /**
@ -374,24 +314,6 @@ EOT;
return $this->cacheDir; return $this->cacheDir;
} }
/**
* Converts an array to its INI equivalent
*
* @param array $data The array to convert.
*
* @return string The INI formatted array.
*/
protected function arrayToIni(array $data)
{
$lines = array();
foreach ($data as $key => $value) {
$lines[] = $key . ' =' . (!empty($value) ? ' ' . $value : '');
}
return implode(PHP_EOL, $lines);
}
/** /**
* Extract the database name from a given DSN * Extract the database name from a given DSN
* *
@ -409,4 +331,16 @@ EOT;
// e.g. SQLite // e.g. SQLite
return null; return null;
} }
/**
* Returns the name of the default connection.
*
* @return string
*/
protected function getDefaultConnection()
{
$config = $this->getContainer()->getParameter('propel.configuration');
return $config['generator']['defaultConnection'];
}
} }

View file

@ -44,9 +44,9 @@ class DatabaseCreateCommand extends AbstractCommand
*/ */
protected function execute(InputInterface $input, OutputInterface $output) protected function execute(InputInterface $input, OutputInterface $output)
{ {
$connectionName = $input->getOption('connection') ?: $this->getContainer()->getParameter('propel.dbal.default_connection'); $connectionName = $input->getOption('connection') ?: $this->getDefaultConnection();
$config = $this->getConnectionData($connectionName); $config = $this->getConnectionData($connectionName);
$dbName = $this->parseDbName($config['connection']['dsn']); $dbName = $this->parseDbName($config['dsn']);
if (null === $dbName) { if (null === $dbName) {
return $output->writeln('<error>No database name found.</error>'); return $output->writeln('<error>No database name found.</error>');
@ -56,7 +56,7 @@ class DatabaseCreateCommand extends AbstractCommand
try { try {
$manager = new ConnectionManagerSingle(); $manager = new ConnectionManagerSingle();
$manager->setConfiguration($this->getTemporaryConfiguration($config['connection'])); $manager->setConfiguration($this->getTemporaryConfiguration($config));
$serviceContainer = Propel::getServiceContainer(); $serviceContainer = Propel::getServiceContainer();
$serviceContainer->setAdapterClass($connectionName, $config['adapter']); $serviceContainer->setAdapterClass($connectionName, $config['adapter']);

View file

@ -68,10 +68,10 @@ EOT
} }
} }
$connectionName = $input->getOption('connection') ?: $this->getContainer()->getParameter('propel.dbal.default_connection'); $connectionName = $input->getOption('connection') ?: $this->getDefaultConnection();
$config = $this->getConnectionData($connectionName); $config = $this->getConnectionData($connectionName);
$connection = Propel::getConnection($connectionName); $connection = Propel::getConnection($connectionName);
$dbName = $this->parseDbName($config['connection']['dsn']); $dbName = $this->parseDbName($config['dsn']);
if (null === $dbName) { if (null === $dbName) {
return $output->writeln('<error>No database name found.</error>'); return $output->writeln('<error>No database name found.</error>');

View file

@ -12,7 +12,6 @@ namespace Propel\PropelBundle\Command;
use Propel\Generator\Config\GeneratorConfig; use Propel\Generator\Config\GeneratorConfig;
use Propel\Generator\Command\ModelBuildCommand as BaseModelBuildCommand; use Propel\Generator\Command\ModelBuildCommand as BaseModelBuildCommand;
use Propel\Generator\Command\AbstractCommand as BaseCommand;
use Propel\Generator\Model\Database; use Propel\Generator\Model\Database;
use Propel\Generator\Model\Table; use Propel\Generator\Model\Table;
use Propel\Generator\Manager\ModelManager; use Propel\Generator\Manager\ModelManager;
@ -42,7 +41,7 @@ class FormGenerateCommand extends AbstractCommand
->setDescription('Generate Form types stubs based on the schema.xml') ->setDescription('Generate Form types stubs based on the schema.xml')
->addOption('force', 'f', InputOption::VALUE_NONE, 'Overwrite existing Form types') ->addOption('force', 'f', InputOption::VALUE_NONE, 'Overwrite existing Form types')
->addOption('platform', null, InputOption::VALUE_REQUIRED, 'The platform', BaseCommand::DEFAULT_PLATFORM) ->addOption('platform', null, InputOption::VALUE_REQUIRED, 'The platform')
->addArgument('bundle', InputArgument::REQUIRED, 'The bundle to use to generate Form types (Ex: @AcmeDemoBundle)') ->addArgument('bundle', InputArgument::REQUIRED, 'The bundle to use to generate Form types (Ex: @AcmeDemoBundle)')
->addArgument('models', InputArgument::IS_ARRAY, 'Model classes to generate Form Types from') ->addArgument('models', InputArgument::IS_ARRAY, 'Model classes to generate Form Types from')

View file

@ -33,7 +33,7 @@ class MigrationDiffCommand extends WrappedCommand
->addOption('connection', null, InputOption::VALUE_IS_ARRAY | InputOption::VALUE_OPTIONAL, 'Connection to use. Example: default, bookstore') ->addOption('connection', null, InputOption::VALUE_IS_ARRAY | InputOption::VALUE_OPTIONAL, 'Connection to use. Example: default, bookstore')
->addOption('output-dir', null, InputOption::VALUE_OPTIONAL, 'The output directory') ->addOption('output-dir', null, InputOption::VALUE_OPTIONAL, 'The output directory')
->addOption('migration-table', null, InputOption::VALUE_REQUIRED, 'Migration table name', BaseMigrationCommand::DEFAULT_MIGRATION_TABLE) ->addOption('migration-table', null, InputOption::VALUE_REQUIRED, 'Migration table name', null)
->addOption('table-renaming', null, InputOption::VALUE_NONE, 'Detect table renaming', null) ->addOption('table-renaming', null, InputOption::VALUE_NONE, 'Detect table renaming', null)
->addOption('editor', null, InputOption::VALUE_OPTIONAL, 'The text editor to use to open diff files', null) ->addOption('editor', null, InputOption::VALUE_OPTIONAL, 'The text editor to use to open diff files', null)
->addOption('skip-removed-table', null, InputOption::VALUE_NONE, 'Option to skip removed table from the migration') ->addOption('skip-removed-table', null, InputOption::VALUE_NONE, 'Option to skip removed table from the migration')

View file

@ -10,8 +10,6 @@
namespace Propel\PropelBundle\Command; namespace Propel\PropelBundle\Command;
use Propel\Generator\Command\AbstractCommand as BaseCommand;
use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Output\OutputInterface;
@ -41,7 +39,7 @@ abstract class WrappedCommand extends AbstractCommand
protected function configure() protected function configure()
{ {
$this $this
->addOption('platform', null, InputOption::VALUE_REQUIRED, 'The platform', BaseCommand::DEFAULT_PLATFORM) ->addOption('platform', null, InputOption::VALUE_OPTIONAL, 'The platform')
; ;
} }

View file

@ -33,7 +33,6 @@ class PanelController extends ContainerAware
array( array(
'propel_version' => Propel::VERSION, 'propel_version' => Propel::VERSION,
'configuration' => $this->container->getParameter('propel.configuration'), 'configuration' => $this->container->getParameter('propel.configuration'),
'default_connection' => $this->container->getParameter('propel.dbal.default_connection'),
'logging' => $this->container->getParameter('propel.logging'), 'logging' => $this->container->getParameter('propel.logging'),
) )
); );

View file

@ -10,237 +10,11 @@
namespace Propel\PropelBundle\DependencyInjection; namespace Propel\PropelBundle\DependencyInjection;
use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; use Propel\Common\Config\PropelConfiguration;
use Symfony\Component\Config\Definition\Builder\TreeBuilder;
use Symfony\Component\Config\Definition\ConfigurationInterface;
/** /**
* This class contains the configuration information for the bundle * This class contains the configuration information for the bundle
*
* This information is solely responsible for how the different configuration
* sections are normalized, and merged.
*
* @author William DURAND <william.durand1@gmail.com>
*/ */
class Configuration implements ConfigurationInterface class Configuration extends PropelConfiguration
{ {
private $debug;
/**
* Constructor
*
* @param Boolean $debug Wether to use the debug mode
*/
public function __construct($debug)
{
$this->debug = (Boolean) $debug;
}
/**
* Generates the configuration tree builder.
*
* @return \Symfony\Component\Config\Definition\Builder\TreeBuilder The tree builder
*/
public function getConfigTreeBuilder()
{
$treeBuilder = new TreeBuilder();
$rootNode = $treeBuilder->root('propel');
$this->addGeneralSection($rootNode);
$this->addDbalSection($rootNode);
return $treeBuilder;
}
/**
* Adds 'general' configuration.
*
* propel:
* logging: %kernel.debug%
* build_properties:
* xxxx.xxxx: xxxxxx
* ...
* behaviors:
* fooable: My\FooableBehavior
* barable: src.barable.BarableBehavior
*/
private function addGeneralSection(ArrayNodeDefinition $node)
{
$node
->children()
->scalarNode('logging')->defaultValue($this->debug)->end()
->arrayNode('build_properties')
->useAttributeAsKey('key')
->prototype('scalar')->end()
->end()
->arrayNode('behaviors')
->useAttributeAsKey('key')
->prototype('scalar')->end()
->end()
;
}
/**
* Adds 'dbal' configuration.
*
* propel:
* dbal:
* driver: mysql
* user: root
* password: null
* dsn: xxxxxxxx
* options: {}
* attributes: {}
* settings: {}
* default_connection: xxxxxx
*/
private function addDbalSection(ArrayNodeDefinition $node)
{
$node
->children()
->arrayNode('dbal')
->beforeNormalization()
->ifNull()
->then(function ($v) { return array ('connections' => array('default' => array())); })
->end()
->children()
->scalarNode('default_connection')->defaultValue('default')->end()
->scalarNode('driver')
->beforeNormalization()
->always()
->then(function ($v) { return str_replace('pdo_', '', $v); })
->end()
->defaultValue('mysql')
->end()
->scalarNode('user')->defaultValue('root')->end()
->scalarNode('password')->defaultValue('')->end()
->scalarNode('dsn')
->beforeNormalization()
->always()
->then(function ($v) { return str_replace('pdo_', '', $v); })
->end()
->defaultValue('')
->end()
->scalarNode('classname')->defaultValue($this->debug ? '\Propel\Runtime\Connection\DebugPDO' : '\Propel\Runtime\Connection\ConnectionWrapper')->end()
->end()
->fixXmlConfig('option')
->children()
->arrayNode('options')
->useAttributeAsKey('key')
->prototype('scalar')->end()
->end()
->end()
->fixXmlConfig('attribute')
->children()
->arrayNode('attributes')
->useAttributeAsKey('key')
->prototype('scalar')->end()
->end()
->end()
->fixXmlConfig('setting')
->children()
->arrayNode('settings')
->useAttributeAsKey('key')
->prototype('scalar')->end()
->end()
->end()
->fixXmlConfig('connection')
->append($this->getDbalConnectionsNode())
->end()
;
}
/**
* Returns a tree configuration for this part of configuration:
*
* connections:
* default:
* driver: mysql
* user: root
* password: null
* dsn: xxxxxxxx
* classname: PropelPDO
* options: {}
* attributes: {}
* settings: {}
*
* @return \Symfony\Component\Config\Definition\Builder\TreeBuilder The tree builder
*/
private function getDbalConnectionsNode()
{
$treeBuilder = new TreeBuilder();
$node = $treeBuilder->root('connections');
$node
->requiresAtLeastOneElement()
->useAttributeAsKey('name')
->prototype('array')
->children()
->scalarNode('driver')
->beforeNormalization()
->always()
->then(function ($v) { return str_replace('pdo_', '', $v); })
->end()
->defaultValue('mysql')
->end()
->scalarNode('user')->defaultValue('root')->end()
->scalarNode('password')->defaultValue('')->end()
->scalarNode('dsn')
->beforeNormalization()
->always()
->then(function ($v) { return str_replace('pdo_', '', $v); })
->end()
->defaultValue('')
->end()
->scalarNode('classname')->defaultValue($this->debug ? '\Propel\Runtime\Connection\DebugPDO' : '\Propel\Runtime\Connection\ConnectionWrapper')->end()
->arrayNode('slaves')
->useAttributeAsKey('name')
->prototype('array')
->children()
->scalarNode('driver')
->beforeNormalization()
->always()
->then(function ($v) { return str_replace('pdo_', '', $v); })
->end()
->defaultValue('mysql')
->end()
->scalarNode('user')->defaultValue('root')->end()
->scalarNode('password')->defaultValue('')->end()
->scalarNode('dsn')
->beforeNormalization()
->always()
->then(function ($v) { return str_replace('pdo_', '', $v); })
->end()
->defaultValue('')
->end()
->scalarNode('classname')->defaultValue($this->debug ? '\Propel\Runtime\Connection\DebugPDO' : '\Propel\Runtime\Connection\ConnectionWrapper')->end()
->end()
->end()
->end()
->end()
->fixXmlConfig('option')
->children()
->arrayNode('options')
->useAttributeAsKey('key')
->prototype('scalar')->end()
->end()
->end()
->fixXmlConfig('attribute')
->children()
->arrayNode('attributes')
->useAttributeAsKey('key')
->prototype('scalar')->end()
->end()
->end()
->fixXmlConfig('setting')
->children()
->arrayNode('settings')
->useAttributeAsKey('key')
->prototype('scalar')->end()
->end()
->end()
;
return $node;
}
} }

View file

@ -36,8 +36,9 @@ class PropelExtension extends Extension
$configuration = $this->getConfiguration($configs, $container); $configuration = $this->getConfiguration($configs, $container);
$config = $processor->processConfiguration($configuration, $configs); $config = $processor->processConfiguration($configuration, $configs);
$container->setParameter('propel.logging', $config['logging']); // @todo: restore
$container->setParameter('propel.configuration', array()); $container->setParameter('propel.logging', true); //$config['logging']);
$container->setParameter('propel.configuration', $config);
// Load services // Load services
if (!$container->hasDefinition('propel')) { if (!$container->hasDefinition('propel')) {
@ -46,69 +47,6 @@ class PropelExtension extends Extension
$loader->load('converters.xml'); $loader->load('converters.xml');
$loader->load('security.xml'); $loader->load('security.xml');
} }
// build properties
$buildProperties = $config['build_properties'];
// behaviors
if (isset($config['behaviors']) && is_array($config['behaviors'])) {
foreach ($config['behaviors'] as $name => $class) {
$buildProperties[sprintf('propel.behavior.%s.class', $name)] = $class;
}
}
$container->setParameter('propel.build_properties', $buildProperties);
if (!empty($config['dbal'])) {
$this->dbalLoad($config['dbal'], $container);
}
}
/**
* Loads the DBAL configuration.
*
* @param array $config An array of configuration settings
* @param ContainerBuilder $container A ContainerBuilder instance
*/
protected function dbalLoad(array $config, ContainerBuilder $container)
{
if (empty($config['default_connection'])) {
$keys = array_keys($config['connections']);
$config['default_connection'] = reset($keys);
}
$connectionName = $config['default_connection'];
$container->setParameter('propel.dbal.default_connection', $connectionName);
if (0 === count($config['connections'])) {
$config['connections'] = array($connectionName => $config);
}
$c = array();
foreach ($config['connections'] as $name => $conf) {
$c[$name]['adapter'] = $conf['driver'];
if (!empty($conf['slaves'])) {
$c[$name]['slaves']['connection'] = $conf['slaves'];
}
foreach (array('dsn', 'user', 'password', 'classname', 'options', 'attributes', 'settings', 'model_paths') as $att) {
if (array_key_exists($att, $conf)) {
$c[$name]['connection'][$att] = $conf[$att];
}
}
}
// Alias the default connection if not defined
if (!isset($c['default'])) {
$c['default'] = $c[$connectionName];
}
$container->setParameter('propel.configuration', $c);
}
public function getConfiguration(array $config, ContainerBuilder $container)
{
return new Configuration($container->getParameter('kernel.debug'));
} }
/** /**

View file

@ -47,14 +47,13 @@ class PropelBundle extends Bundle
protected function configureConnections() protected function configureConnections()
{ {
$connections_config = $this->container->getParameter('propel.configuration'); $config = $this->container->getParameter('propel.configuration');
$default_datasource = $this->container->getParameter('propel.dbal.default_connection');
$serviceContainer = Propel::getServiceContainer(); $serviceContainer = Propel::getServiceContainer();
$serviceContainer->setDefaultDatasource($default_datasource); $serviceContainer->setDefaultDatasource($config['runtime']['defaultConnection']);
foreach ($connections_config as $name => $config) { foreach ($config['database']['connections'] as $name => $config) {
if (isset($config['slaves'])) { if (!empty($config['slaves'])) {
$manager = new ConnectionManagerMasterSlave(); $manager = new ConnectionManagerMasterSlave();
// configure the master (write) connection // configure the master (write) connection
@ -63,7 +62,7 @@ class PropelBundle extends Bundle
$manager->setReadConfiguration($config['slaves']); $manager->setReadConfiguration($config['slaves']);
} else { } else {
$manager = new ConnectionManagerSingle(); $manager = new ConnectionManagerSingle();
$manager->setConfiguration($config['connection']); $manager->setConfiguration($config);
} }
$serviceContainer->setAdapterClass($name, $config['adapter']); $serviceContainer->setAdapterClass($name, $config['adapter']);

View file

@ -4,7 +4,6 @@ namespace Propel\PropelBundle\Request\ParamConverter;
use Propel\PropelBundle\Util\PropelInflector; use Propel\PropelBundle\Util\PropelInflector;
use Propel\Runtime\ActiveQuery\Criteria; use Propel\Runtime\ActiveQuery\Criteria;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ConfigurationInterface;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter; use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
use Sensio\Bundle\FrameworkExtraBundle\Request\ParamConverter\ParamConverterInterface; use Sensio\Bundle\FrameworkExtraBundle\Request\ParamConverter\ParamConverterInterface;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
@ -66,7 +65,7 @@ class PropelParamConverter implements ParamConverterInterface
/** /**
* @param Request $request * @param Request $request
* @param ConfigurationInterface $configuration * @param ParamConverter $configuration
* *
* @return bool * @return bool
* *
@ -74,7 +73,7 @@ class PropelParamConverter implements ParamConverterInterface
* @throws NotFoundHttpException * @throws NotFoundHttpException
* @throws \Exception * @throws \Exception
*/ */
public function apply(Request $request, ConfigurationInterface $configuration) public function apply(Request $request, ParamConverter $configuration)
{ {
$class = $configuration->getClass(); $class = $configuration->getClass();
$classQuery = $class . 'Query'; $classQuery = $class . 'Query';
@ -148,11 +147,11 @@ class PropelParamConverter implements ParamConverterInterface
} }
/** /**
* @param ConfigurationInterface $configuration * @param ParamConverter $configuration
* *
* @return bool * @return bool
*/ */
public function supports(ConfigurationInterface $configuration) public function supports(ParamConverter $configuration)
{ {
if (null === ($classname = $configuration->getClass())) { if (null === ($classname = $configuration->getClass())) {
return false; return false;

View file

@ -10,7 +10,7 @@
</tr> </tr>
<tr> <tr>
<th>Default connection</th> <th>Default connection</th>
<td>{{ default_connection }}</td> <td>{{ configuration.runtime.defaultConnection }}</td>
<tr> <tr>
<th>Logging</th> <th>Logging</th>
<td>{{ logging ? 'enabled' : 'disabled' }}</td> <td>{{ logging ? 'enabled' : 'disabled' }}</td>
@ -28,7 +28,7 @@
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{% for name, config in configuration %} {% for name, config in configuration.database.connections %}
<tr> <tr>
<th rowspan="5" style="vertical-align: top;"> <th rowspan="5" style="vertical-align: top;">
{{ name }} {{ name }}
@ -38,17 +38,17 @@
</tr> </tr>
<tr> <tr>
<th>DSN</th> <th>DSN</th>
<td>{{ config.connection.dsn }}</td> <td>{{ config.dsn }}</td>
</tr> </tr>
<tr> <tr>
<th>Class</th> <th>Class</th>
<td>{{ config.connection.classname }}</td> <td>{{ config.classname }}</td>
</tr> </tr>
<tr> <tr>
<th>Options</th> <th>Options</th>
<td> <td>
<ul> <ul>
{% for key, value in config.connection.options %} {% for key, value in config.options %}
<li>{{ key }} : {{ value }}</li> <li>{{ key }} : {{ value }}</li>
{% endfor %} {% endfor %}
</ul> </ul>
@ -58,7 +58,7 @@
<th>Attributes</th> <th>Attributes</th>
<td> <td>
<ul> <ul>
{% for key, value in config.connection.attributes %} {% for key, value in config.attributes %}
<li>{{ key }} : {{ value }}</li> <li>{{ key }} : {{ value }}</li>
{% endfor %} {% endfor %}
</ul> </ul>