From e655699917a473c464215798d3316741c4fd2bcd Mon Sep 17 00:00:00 2001 From: "Alexander A. Klimov" Date: Thu, 3 Nov 2016 14:35:18 +0100 Subject: [PATCH 01/12] Repository: add support for per-table datasources refs #13034 --- library/Icinga/Repository/Repository.php | 6 ++++-- library/Icinga/Repository/RepositoryQuery.php | 4 ++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/library/Icinga/Repository/Repository.php b/library/Icinga/Repository/Repository.php index 379614f22..5e2b61b14 100644 --- a/library/Icinga/Repository/Repository.php +++ b/library/Icinga/Repository/Repository.php @@ -263,11 +263,13 @@ abstract class Repository implements Selectable } /** - * Return the datasource being used + * Return the datasource being used for the table $table + * + * @param string $table * * @return Selectable */ - public function getDataSource() + public function getDataSource($table = null) { return $this->ds; } diff --git a/library/Icinga/Repository/RepositoryQuery.php b/library/Icinga/Repository/RepositoryQuery.php index 586403873..4f42fa7c2 100644 --- a/library/Icinga/Repository/RepositoryQuery.php +++ b/library/Icinga/Repository/RepositoryQuery.php @@ -109,7 +109,7 @@ class RepositoryQuery implements QueryInterface, SortRules, FilterColumns, Itera */ public function from($target, array $columns = null) { - $this->query = $this->repository->getDataSource()->select(); + $this->query = $this->repository->getDataSource($target)->select(); $this->query->from($this->repository->requireTable($target, $this)); $this->query->columns($this->prepareQueryColumns($target, $columns)); $this->target = $target; @@ -716,7 +716,7 @@ class RepositoryQuery implements QueryInterface, SortRules, FilterColumns, Itera if ($this->query instanceof Traversable) { $iterator = $this->query; } else { - $iterator = $this->repository->getDataSource()->query($this->query); + $iterator = $this->repository->getDataSource($this->target)->query($this->query); } if ($iterator instanceof IteratorAggregate) { From fb3f3ed788daec80a36e2fc8081647f449d67b5c Mon Sep 17 00:00:00 2001 From: "Alexander A. Klimov" Date: Thu, 3 Nov 2016 15:06:37 +0100 Subject: [PATCH 02/12] IniRepository: add support for per-table datasources refs #13034 --- library/Icinga/Repository/IniRepository.php | 45 ++++++++++++--------- 1 file changed, 27 insertions(+), 18 deletions(-) diff --git a/library/Icinga/Repository/IniRepository.php b/library/Icinga/Repository/IniRepository.php index 7413971a1..1df35d7e1 100644 --- a/library/Icinga/Repository/IniRepository.php +++ b/library/Icinga/Repository/IniRepository.php @@ -25,11 +25,11 @@ use Icinga\Exception\StatementException; abstract class IniRepository extends Repository implements Extensible, Updatable, Reducible { /** - * The datasource being used + * Per-table datasources * - * @var Config + * @var Config[string] */ - protected $ds; + protected $datasources = array(); /** * The tables for which triggers are available when inserting, updating or deleting rows @@ -179,16 +179,16 @@ abstract class IniRepository extends Repository implements Extensible, Updatable { $newData = $this->requireStatementColumns($target, $data); $config = $this->onInsert($target, new ConfigObject($newData)); - $section = $this->extractSectionName($config); + $section = $this->extractSectionName($config, $target); - if ($this->ds->hasSection($section)) { + if ($this->getDataSource($target)->hasSection($section)) { throw new StatementException(t('Cannot insert. Section "%s" does already exist'), $section); } - $this->ds->setSection($section, $config); + $this->getDataSource($target)->setSection($section, $config); try { - $this->ds->saveIni(); + $this->getDataSource($target)->saveIni(); } catch (Exception $e) { throw new StatementException(t('Failed to insert. An error occurred: %s'), $e->getMessage()); } @@ -206,7 +206,7 @@ abstract class IniRepository extends Repository implements Extensible, Updatable public function update($target, array $data, Filter $filter = null) { $newData = $this->requireStatementColumns($target, $data); - $keyColumn = $this->ds->getConfigObject()->getKeyColumn(); + $keyColumn = $this->getDataSource($target)->getConfigObject()->getKeyColumn(); if ($filter === null && isset($newData[$keyColumn])) { throw new StatementException( t('Cannot update. Column "%s" holds a section\'s name which must be unique'), @@ -214,7 +214,7 @@ abstract class IniRepository extends Repository implements Extensible, Updatable ); } - $query = $this->ds->select(); + $query = $this->getDataSource($target)->select(); if ($filter !== null) { $query->addFilter($this->requireFilter($target, $filter)); } @@ -242,16 +242,16 @@ abstract class IniRepository extends Repository implements Extensible, Updatable unset($newConfig->$keyColumn); if ($newSection) { - if ($this->ds->hasSection($newSection)) { + if ($this->getDataSource($target)->hasSection($newSection)) { throw new StatementException(t('Cannot update. Section "%s" does already exist'), $newSection); } - $this->ds->removeSection($section)->setSection( + $this->getDataSource($target)->removeSection($section)->setSection( $newSection, $this->onUpdate($target, $config, $newConfig) ); } else { - $this->ds->setSection( + $this->getDataSource($target)->setSection( $section, $this->onUpdate($target, $config, $newConfig) ); @@ -259,7 +259,7 @@ abstract class IniRepository extends Repository implements Extensible, Updatable } try { - $this->ds->saveIni(); + $this->getDataSource($target)->saveIni(); } catch (Exception $e) { throw new StatementException(t('Failed to update. An error occurred: %s'), $e->getMessage()); } @@ -275,19 +275,19 @@ abstract class IniRepository extends Repository implements Extensible, Updatable */ public function delete($target, Filter $filter = null) { - $query = $this->ds->select(); + $query = $this->getDataSource($target)->select(); if ($filter !== null) { $query->addFilter($this->requireFilter($target, $filter)); } /** @var ConfigObject $config */ foreach ($query as $section => $config) { - $this->ds->removeSection($section); + $this->getDataSource($target)->removeSection($section); $this->onDelete($target, $config); } try { - $this->ds->saveIni(); + $this->getDataSource($target)->saveIni(); } catch (Exception $e) { throw new StatementException(t('Failed to delete. An error occurred: %s'), $e->getMessage()); } @@ -297,14 +297,15 @@ abstract class IniRepository extends Repository implements Extensible, Updatable * Extract and return the section name off of the given $config * * @param array|ConfigObject $config + * @param string $target The table whose datasource to get the key column from * * @return string * * @throws ProgrammingError In case no valid section name is available */ - protected function extractSectionName( & $config) + protected function extractSectionName( & $config, $target) { - $keyColumn = $this->ds->getConfigObject()->getKeyColumn(); + $keyColumn = $this->getDataSource($target)->getConfigObject()->getKeyColumn(); if (! is_array($config) && !$config instanceof ConfigObject) { throw new ProgrammingError('$config is neither an array nor a ConfigObject'); } elseif (! isset($config[$keyColumn])) { @@ -315,4 +316,12 @@ abstract class IniRepository extends Repository implements Extensible, Updatable unset($config[$keyColumn]); return $section; } + + /** + * {@inheritDoc} + */ + public function getDataSource($table = null) + { + return isset($this->datasources[$table]) ? $this->datasources[$table] : parent::getDataSource($table); + } } From e5b24eb467c3956c63635afc3b93d13f0003a629 Mon Sep 17 00:00:00 2001 From: "Alexander A. Klimov" Date: Thu, 3 Nov 2016 16:00:20 +0100 Subject: [PATCH 03/12] IniRepository: fix doc and method order refs #13034 --- library/Icinga/Repository/IniRepository.php | 24 +++++++++++++-------- library/Icinga/Repository/Repository.php | 2 +- 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/library/Icinga/Repository/IniRepository.php b/library/Icinga/Repository/IniRepository.php index 1df35d7e1..ec9b4b1cf 100644 --- a/library/Icinga/Repository/IniRepository.php +++ b/library/Icinga/Repository/IniRepository.php @@ -27,7 +27,13 @@ abstract class IniRepository extends Repository implements Extensible, Updatable /** * Per-table datasources * - * @var Config[string] + * + * array( + * $table => $datasource + * ) + * + * + * @var Config[] */ protected $datasources = array(); @@ -60,6 +66,14 @@ abstract class IniRepository extends Repository implements Extensible, Updatable } } + /** + * {@inheritDoc} + */ + public function getDataSource($table = null) + { + return isset($this->datasources[$table]) ? $this->datasources[$table] : parent::getDataSource($table); + } + /** * Return the tables for which triggers are available when inserting, updating or deleting rows * @@ -316,12 +330,4 @@ abstract class IniRepository extends Repository implements Extensible, Updatable unset($config[$keyColumn]); return $section; } - - /** - * {@inheritDoc} - */ - public function getDataSource($table = null) - { - return isset($this->datasources[$table]) ? $this->datasources[$table] : parent::getDataSource($table); - } } diff --git a/library/Icinga/Repository/Repository.php b/library/Icinga/Repository/Repository.php index 5e2b61b14..1d111b4d7 100644 --- a/library/Icinga/Repository/Repository.php +++ b/library/Icinga/Repository/Repository.php @@ -263,7 +263,7 @@ abstract class Repository implements Selectable } /** - * Return the datasource being used for the table $table + * Return the datasource being used for the given table * * @param string $table * From 38602379be8ed8de7f367c0fa4b258c5593baacf Mon Sep 17 00:00:00 2001 From: "Alexander A. Klimov" Date: Thu, 3 Nov 2016 16:12:09 +0100 Subject: [PATCH 04/12] Repository: allow not to provide a datasource for all tables refs #13034 --- library/Icinga/Repository/Repository.php | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/library/Icinga/Repository/Repository.php b/library/Icinga/Repository/Repository.php index 1d111b4d7..73721c003 100644 --- a/library/Icinga/Repository/Repository.php +++ b/library/Icinga/Repository/Repository.php @@ -214,9 +214,10 @@ abstract class Repository implements Selectable /** * Create a new repository object * - * @param Selectable $ds The datasource to use + * @param Selectable|null $ds The datasource to use. + * Only pass null if you have overridden {@link getDataSource()}! */ - public function __construct(Selectable $ds) + public function __construct(Selectable $ds = null) { $this->ds = $ds; $this->aliasTableMap = array(); @@ -271,6 +272,9 @@ abstract class Repository implements Selectable */ public function getDataSource($table = null) { + if ($this->ds === null) { + throw new ProgrammingError('No data source available'); + } return $this->ds; } From bd7851d15c4412eefda411f524969e123cce8c49 Mon Sep 17 00:00:00 2001 From: "Alexander A. Klimov" Date: Thu, 3 Nov 2016 18:05:05 +0100 Subject: [PATCH 05/12] IniRepository: improve initialization of per-table datasources refs #13034 --- library/Icinga/Repository/IniRepository.php | 79 ++++++++++++++++++--- 1 file changed, 71 insertions(+), 8 deletions(-) diff --git a/library/Icinga/Repository/IniRepository.php b/library/Icinga/Repository/IniRepository.php index ec9b4b1cf..e17bbaa42 100644 --- a/library/Icinga/Repository/IniRepository.php +++ b/library/Icinga/Repository/IniRepository.php @@ -25,17 +25,22 @@ use Icinga\Exception\StatementException; abstract class IniRepository extends Repository implements Extensible, Updatable, Reducible { /** - * Per-table datasources + * Per-table configs * + * Example: * * array( - * $table => $datasource + * 'event-type' => array( + * 'module' => 'elasticsearch', + * 'path' => 'event-types', + * 'keyColumn' => 'name' + * ) * ) * * - * @var Config[] + * @var array */ - protected $datasources = array(); + protected $configs = null; /** * The tables for which triggers are available when inserting, updating or deleting rows @@ -53,15 +58,15 @@ abstract class IniRepository extends Repository implements Extensible, Updatable /** * Create a new INI repository object * - * @param Config $ds The data source to use + * @param Config|null $ds The data source to use * * @throws ProgrammingError In case the given data source does not provide a valid key column */ - public function __construct(Config $ds) + public function __construct(Config $ds = null) { parent::__construct($ds); // First! Due to init(). - if (! $ds->getConfigObject()->getKeyColumn()) { + if (! ($ds === null || $ds->getConfigObject()->getKeyColumn())) { throw new ProgrammingError('INI repositories require their data source to provide a valid key column'); } } @@ -71,7 +76,56 @@ abstract class IniRepository extends Repository implements Extensible, Updatable */ public function getDataSource($table = null) { - return isset($this->datasources[$table]) ? $this->datasources[$table] : parent::getDataSource($table); + if ($this->ds === null) { + if ($table === null) { + $table = $this->getBaseTable(); + } + + if ($this->configs === null) { + $this->configs = $this->initializeConfigs(); + if ($this->configs === null) { + throw new ProgrammingError('Per-table configs missing'); + } + } + + if (! isset($this->configs[$table])) { + throw new ProgrammingError('Config for table "%s" missing', $table); + } + + $config = $this->configs[$table]; + if ($config instanceof Config) { + if (! $config->getConfigObject()->getKeyColumn()) { + throw new ProgrammingError( + 'INI repositories require their data source to provide a valid key column' + ); + } + } elseif (is_array($config)) { + if (! isset($config['path'])) { + throw new ProgrammingError('Path to config for table "%s" missing', $table); + } + if (! isset($config['keyColumn'])) { + throw new ProgrammingError( + 'INI repositories require their data source to provide a valid key column' + ); + } + + $newConfig = isset($config['module']) + ? Config::module($config['module'], $config['path']) + : Config::app($config['path']); + $newConfig->getConfigObject()->setKeyColumn($config['keyColumn']); + $this->configs[$table] = $config = $newConfig; + } else { + throw new ProgrammingError( + 'Config for table "%s" is a %s, expected either Icinga\Application\Config or an associative array', + $table, + is_object($config) ? get_class($config) : gettype($config) + ); + } + + return $config; + } else { + return parent::getDataSource($table); + } } /** @@ -100,6 +154,15 @@ abstract class IniRepository extends Repository implements Extensible, Updatable return array(); } + /** + * Overwrite this in your INI repository implementation in case you need to initialize the configs lazily + * + * @return array + */ + protected function initializeConfigs() + { + } + /** * Run a trigger for the given table and row which is about to be inserted * From df4702679230ddb711d6f96071ac9ec2f837c622 Mon Sep 17 00:00:00 2001 From: Johannes Meyer Date: Fri, 4 Nov 2016 09:56:53 +0100 Subject: [PATCH 06/12] Repository: Fix documentation of method getDataSource refs #13034 --- library/Icinga/Repository/Repository.php | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/library/Icinga/Repository/Repository.php b/library/Icinga/Repository/Repository.php index 73721c003..541719058 100644 --- a/library/Icinga/Repository/Repository.php +++ b/library/Icinga/Repository/Repository.php @@ -269,12 +269,18 @@ abstract class Repository implements Selectable * @param string $table * * @return Selectable + * + * @throws ProgrammingError In case no datasource is available */ public function getDataSource($table = null) { if ($this->ds === null) { - throw new ProgrammingError('No data source available'); + throw new ProgrammingError( + 'No data source available. It is required to either pass it' + . ' at initialization time or by overriding this method.' + ); } + return $this->ds; } From ca689bc9441170908ee464bc9b6213fe0cb3c26f Mon Sep 17 00:00:00 2001 From: Johannes Meyer Date: Fri, 4 Nov 2016 09:57:56 +0100 Subject: [PATCH 07/12] IniRepository: Improve documentation of attribute $configs refs #13034 --- library/Icinga/Repository/IniRepository.php | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/library/Icinga/Repository/IniRepository.php b/library/Icinga/Repository/IniRepository.php index e17bbaa42..08d721326 100644 --- a/library/Icinga/Repository/IniRepository.php +++ b/library/Icinga/Repository/IniRepository.php @@ -20,27 +20,28 @@ use Icinga\Exception\StatementException; *
    *
  • Insert, update and delete capabilities
  • *
  • Triggers for inserts, updates and deletions
  • + *
  • Lazy initialization of table specific configs
  • *
*/ abstract class IniRepository extends Repository implements Extensible, Updatable, Reducible { /** - * Per-table configs + * The configuration files used as table specific datasources * - * Example: + * This must be initialized by concrete repository implementations, in the following format * * array( - * 'event-type' => array( - * 'module' => 'elasticsearch', - * 'path' => 'event-types', - * 'keyColumn' => 'name' + * 'table_name' => array( + * 'config' => 'name_of_the_ini_file_without_extension', + * 'keyColumn' => 'the_name_of_the_column_to_use_as_key_column', + * ['module' => 'the_name_of_the_module_if_any'] * ) * ) * * * @var array */ - protected $configs = null; + protected $configs; /** * The tables for which triggers are available when inserting, updating or deleting rows From ac3e182f0d4a2420ede171aca53c9273d344b5e8 Mon Sep 17 00:00:00 2001 From: Johannes Meyer Date: Fri, 4 Nov 2016 09:59:37 +0100 Subject: [PATCH 08/12] IniRepository: Make key column validation in the constructor more readable refs #13034 --- library/Icinga/Repository/IniRepository.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/Icinga/Repository/IniRepository.php b/library/Icinga/Repository/IniRepository.php index 08d721326..da1a57c45 100644 --- a/library/Icinga/Repository/IniRepository.php +++ b/library/Icinga/Repository/IniRepository.php @@ -67,7 +67,7 @@ abstract class IniRepository extends Repository implements Extensible, Updatable { parent::__construct($ds); // First! Due to init(). - if (! ($ds === null || $ds->getConfigObject()->getKeyColumn())) { + if ($ds !== null && !$ds->getConfigObject()->getKeyColumn()) { throw new ProgrammingError('INI repositories require their data source to provide a valid key column'); } } From 3c5fe76cc0addeaa098ffeb4b0239fb46b838847 Mon Sep 17 00:00:00 2001 From: Johannes Meyer Date: Fri, 4 Nov 2016 10:04:42 +0100 Subject: [PATCH 09/12] IniRepository: Directly pass the key column to method extractSectionName refs #13034 --- library/Icinga/Repository/IniRepository.php | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/library/Icinga/Repository/IniRepository.php b/library/Icinga/Repository/IniRepository.php index da1a57c45..725c6df55 100644 --- a/library/Icinga/Repository/IniRepository.php +++ b/library/Icinga/Repository/IniRepository.php @@ -257,7 +257,7 @@ abstract class IniRepository extends Repository implements Extensible, Updatable { $newData = $this->requireStatementColumns($target, $data); $config = $this->onInsert($target, new ConfigObject($newData)); - $section = $this->extractSectionName($config, $target); + $section = $this->extractSectionName($config, $this->getDataSource($target)->getConfigObject()->getKeyColumn()); if ($this->getDataSource($target)->hasSection($section)) { throw new StatementException(t('Cannot insert. Section "%s" does already exist'), $section); @@ -375,15 +375,14 @@ abstract class IniRepository extends Repository implements Extensible, Updatable * Extract and return the section name off of the given $config * * @param array|ConfigObject $config - * @param string $target The table whose datasource to get the key column from + * @param string $keyColumn * * @return string * * @throws ProgrammingError In case no valid section name is available */ - protected function extractSectionName( & $config, $target) + protected function extractSectionName( & $config, $keyColumn) { - $keyColumn = $this->getDataSource($target)->getConfigObject()->getKeyColumn(); if (! is_array($config) && !$config instanceof ConfigObject) { throw new ProgrammingError('$config is neither an array nor a ConfigObject'); } elseif (! isset($config[$keyColumn])) { From a0db5bea879308e19b1f13283fffd6146528a8e6 Mon Sep 17 00:00:00 2001 From: Johannes Meyer Date: Fri, 4 Nov 2016 10:15:56 +0100 Subject: [PATCH 10/12] IniRepository: Don't call getDataSource over and over again refs #13034 --- library/Icinga/Repository/IniRepository.php | 34 ++++++++++++--------- 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/library/Icinga/Repository/IniRepository.php b/library/Icinga/Repository/IniRepository.php index 725c6df55..74fe72154 100644 --- a/library/Icinga/Repository/IniRepository.php +++ b/library/Icinga/Repository/IniRepository.php @@ -255,18 +255,20 @@ abstract class IniRepository extends Repository implements Extensible, Updatable */ public function insert($target, array $data) { + $ds = $this->getDataSource($target); $newData = $this->requireStatementColumns($target, $data); - $config = $this->onInsert($target, new ConfigObject($newData)); - $section = $this->extractSectionName($config, $this->getDataSource($target)->getConfigObject()->getKeyColumn()); - if ($this->getDataSource($target)->hasSection($section)) { + $config = $this->onInsert($target, new ConfigObject($newData)); + $section = $this->extractSectionName($config, $ds->getConfigObject()->getKeyColumn()); + + if ($ds->hasSection($section)) { throw new StatementException(t('Cannot insert. Section "%s" does already exist'), $section); } - $this->getDataSource($target)->setSection($section, $config); + $ds->setSection($section, $config); try { - $this->getDataSource($target)->saveIni(); + $ds->saveIni(); } catch (Exception $e) { throw new StatementException(t('Failed to insert. An error occurred: %s'), $e->getMessage()); } @@ -283,8 +285,10 @@ abstract class IniRepository extends Repository implements Extensible, Updatable */ public function update($target, array $data, Filter $filter = null) { + $ds = $this->getDataSource($target); $newData = $this->requireStatementColumns($target, $data); - $keyColumn = $this->getDataSource($target)->getConfigObject()->getKeyColumn(); + + $keyColumn = $ds->getConfigObject()->getKeyColumn(); if ($filter === null && isset($newData[$keyColumn])) { throw new StatementException( t('Cannot update. Column "%s" holds a section\'s name which must be unique'), @@ -292,7 +296,7 @@ abstract class IniRepository extends Repository implements Extensible, Updatable ); } - $query = $this->getDataSource($target)->select(); + $query = $ds->select(); if ($filter !== null) { $query->addFilter($this->requireFilter($target, $filter)); } @@ -320,16 +324,16 @@ abstract class IniRepository extends Repository implements Extensible, Updatable unset($newConfig->$keyColumn); if ($newSection) { - if ($this->getDataSource($target)->hasSection($newSection)) { + if ($ds->hasSection($newSection)) { throw new StatementException(t('Cannot update. Section "%s" does already exist'), $newSection); } - $this->getDataSource($target)->removeSection($section)->setSection( + $ds->removeSection($section)->setSection( $newSection, $this->onUpdate($target, $config, $newConfig) ); } else { - $this->getDataSource($target)->setSection( + $ds->setSection( $section, $this->onUpdate($target, $config, $newConfig) ); @@ -337,7 +341,7 @@ abstract class IniRepository extends Repository implements Extensible, Updatable } try { - $this->getDataSource($target)->saveIni(); + $ds->saveIni(); } catch (Exception $e) { throw new StatementException(t('Failed to update. An error occurred: %s'), $e->getMessage()); } @@ -353,19 +357,21 @@ abstract class IniRepository extends Repository implements Extensible, Updatable */ public function delete($target, Filter $filter = null) { - $query = $this->getDataSource($target)->select(); + $ds = $this->getDataSource($target); + + $query = $ds->select(); if ($filter !== null) { $query->addFilter($this->requireFilter($target, $filter)); } /** @var ConfigObject $config */ foreach ($query as $section => $config) { - $this->getDataSource($target)->removeSection($section); + $ds->removeSection($section); $this->onDelete($target, $config); } try { - $this->getDataSource($target)->saveIni(); + $ds->saveIni(); } catch (Exception $e) { throw new StatementException(t('Failed to delete. An error occurred: %s'), $e->getMessage()); } From c44e164de92052f5cd56bec697e993522d83359d Mon Sep 17 00:00:00 2001 From: Johannes Meyer Date: Fri, 4 Nov 2016 10:16:45 +0100 Subject: [PATCH 11/12] IniRepository: Introduce method createConfig refs #13034 --- library/Icinga/Repository/IniRepository.php | 28 +++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/library/Icinga/Repository/IniRepository.php b/library/Icinga/Repository/IniRepository.php index 74fe72154..200513049 100644 --- a/library/Icinga/Repository/IniRepository.php +++ b/library/Icinga/Repository/IniRepository.php @@ -377,6 +377,34 @@ abstract class IniRepository extends Repository implements Extensible, Updatable } } + /** + * Create and return a Config for the given meta and table + * + * @param array $meta + * @param string $table + * + * @return Config + * + * @throws ProgrammingError In case the given meta is invalid + */ + protected function createConfig(array $meta, $table) + { + if (! isset($meta['name'])) { + throw new ProgrammingError('Config file name missing for table "%s"', $table); + } elseif (! isset($meta['keyColumn'])) { + throw new ProgrammingError('Config key column name missing for table "%s"', $table); + } + + if (isset($meta['module'])) { + $config = Config::module($meta['module'], $meta['name']); + } else { + $config = Config::app($meta['name']); + } + + $config->getConfigObject()->setKeyColumn($meta['keyColumn']); + return $config; + } + /** * Extract and return the section name off of the given $config * From ad79e675508b6e39ddac45414f7dc770eac008de Mon Sep 17 00:00:00 2001 From: Johannes Meyer Date: Fri, 4 Nov 2016 10:17:37 +0100 Subject: [PATCH 12/12] IniRepository: Reduce complexity of method getDataSource refs #13034 --- library/Icinga/Repository/IniRepository.php | 102 +++++++++----------- 1 file changed, 45 insertions(+), 57 deletions(-) diff --git a/library/Icinga/Repository/IniRepository.php b/library/Icinga/Repository/IniRepository.php index 200513049..3c30a5e8d 100644 --- a/library/Icinga/Repository/IniRepository.php +++ b/library/Icinga/Repository/IniRepository.php @@ -74,59 +74,56 @@ abstract class IniRepository extends Repository implements Extensible, Updatable /** * {@inheritDoc} + * + * @return Config */ public function getDataSource($table = null) { - if ($this->ds === null) { - if ($table === null) { - $table = $this->getBaseTable(); - } - - if ($this->configs === null) { - $this->configs = $this->initializeConfigs(); - if ($this->configs === null) { - throw new ProgrammingError('Per-table configs missing'); - } - } - - if (! isset($this->configs[$table])) { - throw new ProgrammingError('Config for table "%s" missing', $table); - } - - $config = $this->configs[$table]; - if ($config instanceof Config) { - if (! $config->getConfigObject()->getKeyColumn()) { - throw new ProgrammingError( - 'INI repositories require their data source to provide a valid key column' - ); - } - } elseif (is_array($config)) { - if (! isset($config['path'])) { - throw new ProgrammingError('Path to config for table "%s" missing', $table); - } - if (! isset($config['keyColumn'])) { - throw new ProgrammingError( - 'INI repositories require their data source to provide a valid key column' - ); - } - - $newConfig = isset($config['module']) - ? Config::module($config['module'], $config['path']) - : Config::app($config['path']); - $newConfig->getConfigObject()->setKeyColumn($config['keyColumn']); - $this->configs[$table] = $config = $newConfig; - } else { - throw new ProgrammingError( - 'Config for table "%s" is a %s, expected either Icinga\Application\Config or an associative array', - $table, - is_object($config) ? get_class($config) : gettype($config) - ); - } - - return $config; - } else { + if ($this->ds !== null) { return parent::getDataSource($table); } + + $table = $table ?: $this->getBaseTable(); + $configs = $this->getConfigs(); + if (! isset($configs[$table])) { + throw new ProgrammingError('Config for table "%s" missing', $table); + } elseif (! $configs[$table] instanceof Config) { + $configs[$table] = $this->createConfig($configs[$table], $table); + } + + if (! $configs[$table]->getConfigObject()->getKeyColumn()) { + throw new ProgrammingError( + 'INI repositories require their data source to provide a valid key column' + ); + } + + return $configs[$table]; + } + + /** + * Return the configuration files used as table specific datasources + * + * Calls $this->initializeConfigs() in case $this->configs is null. + * + * @return array + */ + public function getConfigs() + { + if ($this->configs === null) { + $this->configs = $this->initializeConfigs(); + } + + return $this->configs; + } + + /** + * Overwrite this in your repository implementation in case you need to initialize the configs lazily + * + * @return array + */ + protected function initializeConfigs() + { + return array(); } /** @@ -155,15 +152,6 @@ abstract class IniRepository extends Repository implements Extensible, Updatable return array(); } - /** - * Overwrite this in your INI repository implementation in case you need to initialize the configs lazily - * - * @return array - */ - protected function initializeConfigs() - { - } - /** * Run a trigger for the given table and row which is about to be inserted *