From 8db04d5dbc71180908279b3b701b770e5e5eb1a5 Mon Sep 17 00:00:00 2001
From: Gunnar Wrobel
Date: Mon, 28 Jun 2010 09:05:00 +0200
Subject: [PATCH] Initial implementation of the Kolab_Config package.
---
framework/Kolab_Config/lib/Horde/Kolab/Config.php | 214 +++++++++++++++++++++
.../lib/Horde/Kolab/Config/Exception.php | 31 +++
framework/Kolab_Config/package.xml | 32 ++-
.../test/Horde/Kolab/Config/AllTests.php | 47 +++++
.../test/Horde/Kolab/Config/Autoload.php | 21 +-
.../Horde/Kolab/Config/ConfigStoryTestCase.php | 133 +++++++++++++
.../Horde/Kolab/Config/Integration/ConfigTest.php | 107 +++++++++--
.../test/Horde/Kolab/Config/conf.php.dist | 2 +
.../Kolab/Config/fixture/empty/no_config_file | 1 +
.../Horde/Kolab/Config/fixture/global/globals.conf | 1 +
.../Horde/Kolab/Config/fixture/local/kolab.conf | 2 +
.../Horde/Kolab/Config/fixture/local/kolab.globals | 3 +
12 files changed, 568 insertions(+), 26 deletions(-)
create mode 100644 framework/Kolab_Config/lib/Horde/Kolab/Config.php
create mode 100644 framework/Kolab_Config/lib/Horde/Kolab/Config/Exception.php
create mode 100644 framework/Kolab_Config/test/Horde/Kolab/Config/ConfigStoryTestCase.php
create mode 100644 framework/Kolab_Config/test/Horde/Kolab/Config/conf.php.dist
create mode 100644 framework/Kolab_Config/test/Horde/Kolab/Config/fixture/empty/no_config_file
create mode 100644 framework/Kolab_Config/test/Horde/Kolab/Config/fixture/global/globals.conf
create mode 100644 framework/Kolab_Config/test/Horde/Kolab/Config/fixture/local/kolab.conf
create mode 100644 framework/Kolab_Config/test/Horde/Kolab/Config/fixture/local/kolab.globals
diff --git a/framework/Kolab_Config/lib/Horde/Kolab/Config.php b/framework/Kolab_Config/lib/Horde/Kolab/Config.php
new file mode 100644
index 000000000..85c75fb1c
--- /dev/null
+++ b/framework/Kolab_Config/lib/Horde/Kolab/Config.php
@@ -0,0 +1,214 @@
+
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Kolab_Config
+ */
+
+/**
+ * The Kolab Server configuration handler.
+ *
+ * Copyright 2010 Klarälvdalens Datakonsult AB
+ *
+ * See the enclosed file COPYING for license information (LGPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
+ *
+ * @category Kolab
+ * @package Kolab_Config
+ * @author Gunnar Wrobel
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Kolab_Config
+ */
+class Horde_Kolab_Config
+implements ArrayAccess
+{
+ /**
+ * The path to the directory holding the configuration files.
+ *
+ * @var string
+ */
+ private $_directory;
+
+ /**
+ * Name of the global configuration file.
+ *
+ * @var string
+ */
+ private $_global;
+
+ /**
+ * Name of the local configuration file.
+ *
+ * @var string
+ */
+ private $_local;
+
+ /**
+ * The configuration data.
+ *
+ * @var array
+ */
+ private $_data;
+
+ /**
+ * Constructor.
+ *
+ * @param string $directory The path to the directory holding the
+ * configuration files.
+ * @param string $global Name of the global configuration file.
+ * @param string $local Name of the local configuration file.
+ */
+ public function __construct(
+ $directory = '@kolab_server_dir@/etc/kolab',
+ $global = 'kolab.globals',
+ $local = 'kolab.conf'
+ ) {
+ if ($directory === '@kolab_server_dir@/etc/kolab') {
+ $this->_directory = '/kolab/etc/kolab';
+ } else {
+ $this->_directory = realpath($directory);
+ }
+ $this->_global = $global;
+ $this->_local = $local;
+ }
+
+ /**
+ * Read the configuration files.
+ *
+ * @return NULL
+ */
+ public function read()
+ {
+ if (!file_exists($this->_getGlobalConfigFilePath())
+ && !file_exists($this->_getLocalConfigFilePath())) {
+ throw new Horde_Kolab_Config_Exception(
+ 'No configuration files found in ' . $this->_directory . '.'
+ );
+ }
+
+ if (file_exists($this->_getGlobalConfigFilePath())) {
+ $this->_loadConfigurationFile(
+ $this->_getGlobalConfigFilePath()
+ );
+ }
+
+ if (file_exists($this->_getLocalConfigFilePath())) {
+ $this->_loadConfigurationFile(
+ $this->_getLocalConfigFilePath()
+ );
+ }
+ }
+
+ private function _loadConfigurationFile($path)
+ {
+ if ($this->_data === null) {
+ $this->_data = array();
+ }
+
+ $fh = fopen($path, 'r');
+
+ while (!feof($fh)) {
+ $line = trim(fgets($fh));
+ if ($line && preg_match('/^([^:#]+):(.*)/', $line, $matches)) {
+ $this->_data[trim($matches[1])] = trim($matches[2]);
+ }
+ }
+ fclose($fh);
+ }
+
+ /**
+ * Return the path to the global configuration file.
+ *
+ * @return NULL
+ */
+ private function _getGlobalConfigFilePath()
+ {
+ return $this->_directory . DIRECTORY_SEPARATOR . $this->_global;
+ }
+
+ /**
+ * Return the path to the local configuration file.
+ *
+ * @return NULL
+ */
+ private function _getLocalConfigFilePath()
+ {
+ return $this->_directory . DIRECTORY_SEPARATOR . $this->_local;
+ }
+
+ /**
+ * Initialize this object if this has not happened yet.
+ *
+ * @return NULL
+ */
+ private function _init()
+ {
+ if ($this->_data === null) {
+ $this->read();
+ }
+ }
+
+ /**
+ * Return the value for the given array key.
+ *
+ * @param string $key The key.
+ *
+ * @return mixed The value for the given key.
+ */
+ public function offsetGet($key)
+ {
+ if (!$this->offsetExists($key)) {
+ throw new Horde_Kolab_Config_Exception(
+ 'Parameter "' . $key . '" has no value!'
+ );
+ }
+ return $this->_data[$key];
+ }
+
+ /**
+ * Does the requested array value exist in the configuration?
+ *
+ * @param string $key The key.
+ *
+ * @return boolean True if the configuration value exists.
+ */
+ public function offsetExists($key)
+ {
+ $this->_init();
+ if (!is_string($key) || empty($key)) {
+ throw new InvalidArgumentException(
+ 'The key must be a non-empty string!'
+ );
+ }
+ return isset($this->_data[$key]);
+ }
+
+ /**
+ * Set the given key to the provided value.
+ *
+ * @param string $key The key.
+ * @param mixed $value The value that should be stored.
+ *
+ * @return NULL
+ */
+ public function offsetSet($key, $value)
+ {
+ }
+
+ /**
+ * Delete the value identified by the given key.
+ *
+ * @param string $key The key.
+ *
+ * @return NULL
+ */
+ public function offsetUnset($key)
+ {
+ }
+}
\ No newline at end of file
diff --git a/framework/Kolab_Config/lib/Horde/Kolab/Config/Exception.php b/framework/Kolab_Config/lib/Horde/Kolab/Config/Exception.php
new file mode 100644
index 000000000..8847f4d34
--- /dev/null
+++ b/framework/Kolab_Config/lib/Horde/Kolab/Config/Exception.php
@@ -0,0 +1,31 @@
+
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Kolab_Config
+ */
+
+/**
+ * This class provides the standard error class for the Kolab_Config package.
+ *
+ * Copyright 2010 Klarälvdalens Datakonsult AB
+ *
+ * See the enclosed file COPYING for license information (LGPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
+ *
+ * @category Kolab
+ * @package Kolab_Config
+ * @author Gunnar Wrobel
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Kolab_Config
+ */
+class Horde_Kolab_Config_Exception
+extends Exception
+{
+}
diff --git a/framework/Kolab_Config/package.xml b/framework/Kolab_Config/package.xml
index 408f33266..4ca386141 100644
--- a/framework/Kolab_Config/package.xml
+++ b/framework/Kolab_Config/package.xml
@@ -25,7 +25,7 @@
yes
2010-06-27
-
+
0.1.0
0.1.0
@@ -40,20 +40,36 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+
-
-
-
-
+
+
+
+
@@ -69,9 +85,13 @@
+
+
+
+
diff --git a/framework/Kolab_Config/test/Horde/Kolab/Config/AllTests.php b/framework/Kolab_Config/test/Horde/Kolab/Config/AllTests.php
index 231c1b853..92c822590 100644
--- a/framework/Kolab_Config/test/Horde/Kolab/Config/AllTests.php
+++ b/framework/Kolab_Config/test/Horde/Kolab/Config/AllTests.php
@@ -41,6 +41,53 @@ require_once 'Horde/Test/AllTests.php';
*/
class Horde_Kolab_Config_AllTests extends Horde_Test_AllTests
{
+ /**
+ * Main entry point for running the suite.
+ */
+ public static function main($package = null, $file = null)
+ {
+ if ($package) {
+ self::$_package = $package;
+ }
+ if ($file) {
+ self::$_file = $file;
+ }
+
+ PHPUnit_TextUI_TestRunner::run(self::suite());
+ }
+
+ /**
+ * Collect the unit tests of this directory into a new suite.
+ *
+ * @return PHPUnit_Framework_TestSuite The test suite.
+ */
+ public static function suite()
+ {
+ return self::detectTestFixture(Horde_Test_AllTests::suite());
+ }
+
+ /**
+ * Detect if test configuration is available for the server integration
+ * tests.
+ *
+ * @param PHPUnit_Framework_TestSuite $suite The current test suite.
+ */
+ public static function detectTestFixture(PHPUnit_Framework_TestSuite $suite)
+ {
+ $config = getenv('KOLAB_CONFIG_TEST_CONFIG');
+ if ($config === false) {
+ $config = dirname(__FILE__) . '/conf.php';
+ }
+ if (file_exists($config)) {
+ require $config;
+ if (isset($conf['kolab']['config']['test'])) {
+ $fixture = new stdClass;
+ $fixture->conf = $conf['kolab']['config']['test'];
+ $suite->setSharedFixture($fixture);
+ }
+ }
+ return $suite;
+ }
}
Horde_Kolab_Config_AllTests::init('Horde_Kolab_Config', __FILE__);
diff --git a/framework/Kolab_Config/test/Horde/Kolab/Config/Autoload.php b/framework/Kolab_Config/test/Horde/Kolab/Config/Autoload.php
index a82afdaff..0e91eaa6b 100644
--- a/framework/Kolab_Config/test/Horde/Kolab/Config/Autoload.php
+++ b/framework/Kolab_Config/test/Horde/Kolab/Config/Autoload.php
@@ -1,15 +1,20 @@
-
- * @license http://www.fsf.org/copyleft/lgpl.html LGPL
- * @link http://pear.horde.org/index.php?package=Kolab_Config
+ * Copyright 2009-2010 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file COPYING for license information (LGPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
+ *
+ * @category Kolab
+ * @package Kolab_Config
+ * @subpackage UnitTests
+ * @author Gunnar Wrobel
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Kolab_Config
*/
if (!spl_autoload_functions()) {
@@ -27,3 +32,7 @@ if (!spl_autoload_functions()) {
/** Catch strict standards */
error_reporting(E_ALL | E_STRICT);
+
+
+/** Load the basic test definition */
+require_once dirname(__FILE__) . '/ConfigStoryTestCase.php';
diff --git a/framework/Kolab_Config/test/Horde/Kolab/Config/ConfigStoryTestCase.php b/framework/Kolab_Config/test/Horde/Kolab/Config/ConfigStoryTestCase.php
new file mode 100644
index 000000000..6fc7150cd
--- /dev/null
+++ b/framework/Kolab_Config/test/Horde/Kolab/Config/ConfigStoryTestCase.php
@@ -0,0 +1,133 @@
+
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Kolab_Config
+ */
+
+/**
+ * Base for session testing.
+ *
+ * Copyright 2010 Klarälvdalens Datakonsult AB
+ *
+ * See the enclosed file COPYING for license information (LGPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
+ *
+ * @category Kolab
+ * @package Kolab_Config
+ * @subpackage UnitTests
+ * @author Gunnar Wrobel
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Kolab_Config
+ */
+class Horde_Kolab_Config_ConfigStoryTestCase
+extends PHPUnit_Extensions_Story_TestCase
+{
+ /**
+ * Handle a "given" step.
+ *
+ * @param array &$world Joined "world" of variables.
+ * @param string $action The description of the step.
+ * @param array $arguments Additional arguments to the step.
+ *
+ * @return mixed The outcome of the step.
+ */
+ public function runGiven(&$world, $action, $arguments)
+ {
+ switch($action) {
+ case 'that no Kolab server configuration file can be found':
+ $world['config'] = new Horde_Kolab_Config(
+ dirname(__FILE__) . '/fixture/empty'
+ );
+ break;
+ case 'that a global configuration file was specified as a combination of a directory path and a file name':
+ $world['config'] = new Horde_Kolab_Config(
+ dirname(__FILE__) . '/fixture/global',
+ 'globals.conf'
+ );
+ break;
+ case 'that the location of the configuration files were specified with a directory path':
+ $world['config'] = new Horde_Kolab_Config(
+ dirname(__FILE__) . '/fixture/local'
+ );
+ break;
+ default:
+ return $this->notImplemented($action);
+ }
+ }
+
+ /**
+ * Handle a "when" step.
+ *
+ * @param array &$world Joined "world" of variables.
+ * @param string $action The description of the step.
+ * @param array $arguments Additional arguments to the step.
+ *
+ * @return mixed The outcome of the step.
+ */
+ public function runWhen(&$world, $action, $arguments)
+ {
+ switch($action) {
+ case 'reading the configuration':
+ try {
+ $world['config']->read();
+ } catch (Horde_Kolab_Config_Exception $e) {
+ $world['result'] = $e;
+ }
+ break;
+ case 'reading the parameter':
+ try {
+ $world['result'] = $world['config'][$arguments[0]];
+ } catch (Exception $e) {
+ $world['result'] = $e;
+ }
+ break;
+ default:
+ return $this->notImplemented($action);
+ }
+ }
+
+ /**
+ * Handle a "then" step.
+ *
+ * @param array &$world Joined "world" of variables.
+ * @param string $action The description of the step.
+ * @param array $arguments Additional arguments to the step.
+ *
+ * @return mixed The outcome of the step.
+ */
+ public function runThen(&$world, $action, $arguments)
+ {
+ switch($action) {
+ case 'the Config Object will throw an exception of type':
+ $this->assertType(
+ $arguments[0], $world['result']
+ );
+ break;
+ case 'the exception has the message':
+ $this->assertEquals(
+ $arguments[0], $world['result']->getMessage()
+ );
+ break;
+ case 'the result will be':
+ if ($world['result'] instanceOf Exception) {
+ $this->assertEquals(
+ '', $world['result']->getMessage()
+ );
+ } else {
+ $this->assertEquals($arguments[0], $world['result']);
+ }
+ break;
+ default:
+ return $this->notImplemented($action);
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/framework/Kolab_Config/test/Horde/Kolab/Config/Integration/ConfigTest.php b/framework/Kolab_Config/test/Horde/Kolab/Config/Integration/ConfigTest.php
index a57e334ed..01d81b140 100644
--- a/framework/Kolab_Config/test/Horde/Kolab/Config/Integration/ConfigTest.php
+++ b/framework/Kolab_Config/test/Horde/Kolab/Config/Integration/ConfigTest.php
@@ -4,11 +4,12 @@
*
* PHP version 5
*
- * @category Kolab
- * @package Kolab_Config
- * @author Gunnar Wrobel
- * @license http://www.fsf.org/copyleft/lgpl.html LGPL
- * @link http://pear.horde.org/index.php?package=Kolab_Config
+ * @category Kolab
+ * @package Kolab_Config
+ * @subpackage UnitTests
+ * @author Gunnar Wrobel
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Kolab_Config
*/
/**
@@ -17,24 +18,102 @@
require_once dirname(__FILE__) . '/../Autoload.php';
/**
- * Test the Kolab session handler base implementation.
+ * Test the Kolab configuration handler.
*
- * Copyright 2009-2010 The Horde Project (http://www.horde.org/)
+ * Copyright 2010 Klarälvdalens Datakonsult AB
*
* See the enclosed file COPYING for license information (LGPL). If you
* did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
*
- * @category Kolab
- * @package Kolab_Config
- * @author Gunnar Wrobel
- * @license http://www.fsf.org/copyleft/lgpl.html LGPL
- * @link http://pear.horde.org/index.php?package=Kolab_Config
+ * @category Kolab
+ * @package Kolab_Config
+ * @subpackage UnitTests
+ * @author Gunnar Wrobel
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Kolab_Config
*/
class Horde_Kolab_Config_Integration_ConfigTest
-extends PHPUnit_Framework_TestCase
+extends Horde_Kolab_Config_ConfigStoryTestCase
{
+ /**
+ * @scenario
+ */
+ public function aMissingGlobalConfigurationFileThrowsAnException()
+ {
+ $this->given('that no Kolab server configuration file can be found')
+ ->when('reading the configuration')
+ ->then('the Config Object will throw an exception of type', 'Horde_Kolab_Config_Exception')
+ ->and('the exception has the message',
+ 'No configuration files found in '
+ . realpath(dirname(__FILE__) . '/../fixture/empty') . '.'
+ );
+ }
+
+ /**
+ * @scenario
+ */
+ public function theNameOfTheGlobalConfigurationDirectoryAndFileCanBeSpecified()
+ {
+ $this->given('that a global configuration file was specified as a combination of a directory path and a file name')
+ ->when('reading the parameter', 'global')
+ ->then('the result will be', 'global');
+ }
+
+ /**
+ * @scenario
+ */
+ public function theNameOfTheConfigurationDirectoryCanBeSpecified()
+ {
+ $this->given('that the location of the configuration files were specified with a directory path')
+ ->when('reading the parameter', 'local')
+ ->then('the result will be', 'local');
+ }
+
+ /**
+ * @scenario
+ */
+ public function readingAConfigurationYieldsTheGlobalConfigurationValueIfTheLocalOneIsMissing()
+ {
+ $this->given('that the location of the configuration files were specified with a directory path')
+ ->when('reading the parameter', 'only_global')
+ ->then('the result will be', 'global');
+ }
+
+ /**
+ * @scenario
+ */
+ public function readingAConfigurationYieldsTheLocalConfigurationValueIfItIsSetInBothConfigurationFiles()
+ {
+ $this->given('that the location of the configuration files were specified with a directory path')
+ ->when('reading the parameter', 'both')
+ ->then('the result will be', 'local');
+ }
+
+ /**
+ * @scenario
+ */
+ public function readingAConfigurationWithAnInvalidKeyThrowsAnException()
+ {
+ $this->given('that the location of the configuration files were specified with a directory path')
+ ->when('reading the parameter', array())
+ ->then('the Config Object will throw an exception of type', 'InvalidArgumentException')
+ ->and(
+ 'the exception has the message',
+ 'The key must be a non-empty string!'
+ );
+ }
- public function testSomething()
+ /**
+ * @scenario
+ */
+ public function tryingToReadAMissingConfigurationValueThrowsAnException()
{
+ $this->given('that the location of the configuration files were specified with a directory path')
+ ->when('reading the parameter', 'unknown')
+ ->then('the Config Object will throw an exception of type', 'Horde_Kolab_Config_Exception')
+ ->and(
+ 'the exception has the message',
+ 'Parameter "unknown" has no value!'
+ );
}
}
\ No newline at end of file
diff --git a/framework/Kolab_Config/test/Horde/Kolab/Config/conf.php.dist b/framework/Kolab_Config/test/Horde/Kolab/Config/conf.php.dist
new file mode 100644
index 000000000..16efc5334
--- /dev/null
+++ b/framework/Kolab_Config/test/Horde/Kolab/Config/conf.php.dist
@@ -0,0 +1,2 @@
+