From 9eb9b37518b35d2b1ba6e1a2814f93dbe88da7e5 Mon Sep 17 00:00:00 2001
From: Gunnar Wrobel
Date: Wed, 30 Jun 2010 21:40:46 +0200
Subject: [PATCH] Working option parser.
---
.../Horde/Kolab/Config/ConfigStoryTestCase.php | 4 +-
framework/Qc/lib/Horde/Qc.php | 45 ++++++++
framework/Qc/lib/Horde/Qc/Config.php | 61 +++++++++-
framework/Qc/lib/Horde/Qc/Config/Cli.php | 81 +++++++++++--
framework/Qc/lib/Horde/Qc/Module.php | 23 +---
.../Qc/lib/Horde/Qc/Module/PearPackageXml.php | 34 +++++-
framework/Qc/lib/Horde/Qc/Modules.php | 128 +++++++++++++++++++++
framework/Qc/package.xml | 14 ++-
framework/Qc/test/Horde/Qc/AllTests.php | 24 +++-
framework/Qc/test/Horde/Qc/Autoload.php | 41 +++++++
framework/Qc/test/Horde/Qc/Integration/QcTest.php | 67 +++++++++++
framework/Qc/test/Horde/Qc/StoryTestCase.php | 113 ++++++++++++++++++
framework/Qc/test/Horde/Qc/Stub/Parser.php | 10 ++
framework/Qc/test/Horde/Qc/phpunit.xml | 8 ++
14 files changed, 611 insertions(+), 42 deletions(-)
create mode 100644 framework/Qc/lib/Horde/Qc.php
create mode 100644 framework/Qc/lib/Horde/Qc/Modules.php
create mode 100644 framework/Qc/test/Horde/Qc/Autoload.php
create mode 100644 framework/Qc/test/Horde/Qc/Integration/QcTest.php
create mode 100644 framework/Qc/test/Horde/Qc/StoryTestCase.php
create mode 100644 framework/Qc/test/Horde/Qc/Stub/Parser.php
create mode 100644 framework/Qc/test/Horde/Qc/phpunit.xml
diff --git a/framework/Kolab_Config/test/Horde/Kolab/Config/ConfigStoryTestCase.php b/framework/Kolab_Config/test/Horde/Kolab/Config/ConfigStoryTestCase.php
index 6fc7150cd..d84295f9a 100644
--- a/framework/Kolab_Config/test/Horde/Kolab/Config/ConfigStoryTestCase.php
+++ b/framework/Kolab_Config/test/Horde/Kolab/Config/ConfigStoryTestCase.php
@@ -1,6 +1,6 @@
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Qc
+ */
+
+/**
+ * The Horde_Qc:: class is the entry point for the various quality control /
+ * packaging actions provided by the package.
+ *
+ * Copyright 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 Horde
+ * @package Qc
+ * @author Gunnar Wrobel
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Qc
+ */
+class Horde_Qc
+{
+ static public function main($parameters = array())
+ {
+ $modules = new Horde_Qc_Modules();
+ if (!isset($parameters['config'])) {
+ $parameters['config'] = array();
+ }
+ $config = new Horde_Qc_Config($parameters['config']);
+ $modules->addModulesFromDirectory(dirname(__FILE__) . '/Qc/Module');
+ $config->handleModules($modules);
+ foreach ($modules as $module) {
+ $module->handle($config->getOptions());
+ }
+ }
+}
\ No newline at end of file
diff --git a/framework/Qc/lib/Horde/Qc/Config.php b/framework/Qc/lib/Horde/Qc/Config.php
index e4b6d76ec..923199b5f 100644
--- a/framework/Qc/lib/Horde/Qc/Config.php
+++ b/framework/Qc/lib/Horde/Qc/Config.php
@@ -26,15 +26,68 @@
* @author Gunnar Wrobel
* @license http://www.fsf.org/copyleft/lgpl.html LGPL
* @link http://pear.horde.org/index.php?package=Qc
-erver
*/
class Horde_Qc_Config
{
- private $configs;
+ /**
+ * The different configuration handlers.
+ *
+ * @var array
+ */
+ private $_configs;
- public function __construct(Horde_Qc_Modules $modules)
+ /**
+ * Constructor.
+ *
+ * @param array $parameters A list of named configuration parameters.
+ *
+ * 'cli' - (array) See Horde_Qc_Config_Cli.
+ *
+ */
+ public function __construct(
+ $parameters = array()
+ ) {
+ if (!isset($parameters['cli'])) {
+ $parameters['cli'] = array();
+ }
+ $this->_configs = array();
+ $this->_configs[] = new Horde_Qc_Config_Cli(
+ $parameters['cli']
+ );
+ }
+
+ /**
+ * Provide each configuration handler with the list of supported modules.
+ *
+ * @param Horde_Qc_Modules $modules A list of modules.
+ * @return NULL
+ */
+ public function handleModules(Horde_Qc_Modules $modules)
+ {
+ foreach ($this->_configs as $config) {
+ $config->handleModules($modules);
+ }
+ }
+
+ /**
+ * Return the options provided by the configuration hadnlers.
+ *
+ * @return array An array of options.
+ */
+ public function getOptions()
{
- $this->configs[] = new Horde_Qc_Config_Cli($modules);
+ $options = array();
+ foreach ($this->_configs as $config) {
+ if (count($config->getOptions()) !== 0) {
+ $config_options = array();
+ foreach ($config->getOptions() as $name => $option) {
+ $config_options[$name] = $option;
+ }
+ $options = array_merge($options, $config_options);
+ }
+ }
+ return $options;
}
+
}
\ No newline at end of file
diff --git a/framework/Qc/lib/Horde/Qc/Config/Cli.php b/framework/Qc/lib/Horde/Qc/Config/Cli.php
index 3e4c72314..3a1158581 100644
--- a/framework/Qc/lib/Horde/Qc/Config/Cli.php
+++ b/framework/Qc/lib/Horde/Qc/Config/Cli.php
@@ -26,31 +26,98 @@
* @author Gunnar Wrobel
* @license http://www.fsf.org/copyleft/lgpl.html LGPL
* @link http://pear.horde.org/index.php?package=Qc
-erver
*/
class Horde_Qc_Config_Cli
{
+ /**
+ * The command line argument parser.
+ *
+ * @var Horde_Argv_Parser
+ */
+ private $_parser;
+
+ /**
+ * The options parsed from the command line.
+ *
+ * @var array
+ */
private $_opts;
+ /**
+ * Any additional arguments parsed from the command line.
+ *
+ * @var array
+ */
private $_args;
/**
* Constructor.
*
- * @param Horde_Qc_Modules $modules A list of modules.
+ * @param array $parameters A list of named configuration parameters.
+ *
+ * 'parser' - (array) Parser configuration parameters.
+ * 'class' - (string) The class name of the parser to use.
+ *
*/
- public function __construct(Horde_Qc_Modules $modules)
- {
- $parser = new Horde_Argv_Parser(
+ public function __construct(
+ $parameters = array()
+ ) {
+ if (empty($parameters['parser']['class'])) {
+ $parser_class = 'Horde_Argv_Parser';
+ } else {
+ $parser_class = $parameters['parser']['class'];
+ }
+ $this->_parser = new $parser_class(
array(
'usage' => '%prog ' . _("[options] PACKAGE_PATH")
)
);
+ }
+
+ /**
+ * Load the options for the list of supported modules.
+ *
+ * @param Horde_Qc_Modules $modules A list of modules.
+ * @return NULL
+ */
+ public function handleModules(Horde_Qc_Modules $modules)
+ {
foreach ($modules as $module) {
- $parser->addOptionGroup($module->getOptions());
+ $this->_addOptionsFromModule($this->_parser, $module);
}
- list($this->_opts, $this->_args) = $parser->parseArgs();
+ list($this->_opts, $this->_args) = $this->_parser->parseArgs();
+ }
+
+ /**
+ * Return the options parsed from the command line.
+ *
+ * @return array An array of options.
+ */
+ public function getOptions()
+ {
+ return $this->_opts;
+ }
+
+ /**
+ * Add an option group from the provided module to the parser.
+ *
+ * @param Horde_Argv_Parser $parser The parser.
+ * @param Horde_Qc_Module $module The module providing the option group.
+ *
+ * @return NULL
+ */
+ private function _addOptionsFromModule($parser, $module)
+ {
+ $group = new Horde_Argv_OptionGroup(
+ $parser,
+ $module->getOptionGroupTitle(),
+ $module->getOptionGroupDescription()
+ );
+ foreach ($module->getOptionGroupOptions() as $option) {
+ $group->addOption($option);
+ }
+ $parser->addOptionGroup($group);
}
}
diff --git a/framework/Qc/lib/Horde/Qc/Module.php b/framework/Qc/lib/Horde/Qc/Module.php
index feb6cf282..14beed8bb 100644
--- a/framework/Qc/lib/Horde/Qc/Module.php
+++ b/framework/Qc/lib/Horde/Qc/Module.php
@@ -24,27 +24,16 @@
* @author Gunnar Wrobel
* @license http://www.fsf.org/copyleft/lgpl.html LGPL
* @link http://pear.horde.org/index.php?package=Qc
-erver
*/
-abstract class Horde_Qc_Module
+interface Horde_Qc_Module
{
- /**
- * The parent module.
- *
- * @var Horde_Qc_Module
- */
- private $_parent;
+ public function getOptionGroupTitle();
- public function __construct(Horde_Qc_Module $parent = null)
- {
- $this->_parent = $parent;
- }
+ public function getOptionGroupDescription();
- abstract public function getOptions();
+ public function getOptionGroupOptions();
- abstract public function validateOptions();
+ public function handle(array $config);
- abstract public function setup();
-
- abstract public function run();
+ public function run();
}
\ No newline at end of file
diff --git a/framework/Qc/lib/Horde/Qc/Module/PearPackageXml.php b/framework/Qc/lib/Horde/Qc/Module/PearPackageXml.php
index 225102b24..ea7d5a758 100644
--- a/framework/Qc/lib/Horde/Qc/Module/PearPackageXml.php
+++ b/framework/Qc/lib/Horde/Qc/Module/PearPackageXml.php
@@ -26,19 +26,45 @@
* @link http://pear.horde.org/index.php?package=Qc
*/
class Horde_Qc_Module_PearPackageXml
-extends Horde_Qc_Module
+implements Horde_Qc_Module
{
- public function getOptions()
+ public function getOptionGroupTitle()
+ {
+ return 'Pear Package Xml';
+ }
+
+ public function getOptionGroupDescription()
+ {
+ return 'This module allows manipulation of the package.xml.';
+ }
+
+ public function getOptionGroupOptions()
{
return array(
new Horde_Argv_Option(
'-u',
- '--update-packagexml',
- array('action' => 'store_true')
+ '--updatexml',
+ array(
+ 'action' => 'store_true',
+ 'help' => 'update the package.xml for the package'
+ )
+ ),
+ new Horde_Argv_Option(
+ '-p',
+ '--packagexml',
+ array(
+ 'action' => 'store_true',
+ 'help' => 'display an up-to-date package.xml for the package'
+ )
)
+
);
}
+ public function handle(array $config)
+ {
+ }
+
public function run()
{
diff --git a/framework/Qc/lib/Horde/Qc/Modules.php b/framework/Qc/lib/Horde/Qc/Modules.php
new file mode 100644
index 000000000..f52d0d6ba
--- /dev/null
+++ b/framework/Qc/lib/Horde/Qc/Modules.php
@@ -0,0 +1,128 @@
+
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Qc
+ */
+
+/**
+ * The Horde_Qc_Modules:: class handles a set of Qc modules.
+ *
+ * Copyright 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 Horde
+ * @package Qc
+ * @author Gunnar Wrobel
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Qc
+ */
+class Horde_Qc_Modules
+implements Iterator, Countable
+{
+ /**
+ * The available modules.
+ *
+ * @var array
+ */
+ private $_modules;
+
+ /**
+ * Constructor.
+ */
+ public function __construct()
+ {
+ $this->_modules = array();
+ }
+
+ /**
+ * Add all modules found in the specified directory.
+ *
+ * @param string $module_directory Load the modules from this dirrectory.
+ *
+ * @return NULL
+ */
+ public function addModulesFromDirectory(
+ $module_directory,
+ $base = 'Horde_Qc_Module_'
+ ) {
+ foreach (new RecursiveIteratorIterator(new RecursiveDirectoryIterator($module_directory)) as $file) {
+ if ($file->isFile() && preg_match('/.php$/', $file->getFilename())) {
+ $class = $base . preg_replace("/^(.*)\.php/", '\\1', $file->getFilename());
+ if (!class_exists($class)) {
+ require $file->getPathname();
+ }
+ $this->_modules[$class] = new $class();
+ }
+ }
+ }
+
+ /**
+ * Implementation of the Iterator rewind() method. Reqinds the module list.
+ *
+ * return NULL
+ */
+ public function rewind()
+ {
+ reset($this->_modules);
+ }
+
+ /**
+ * Implementation of the Iterator current(). Returns the current module.
+ *
+ * @return mixed The current module.
+ */
+ public function current()
+ {
+ return current($this->_modules);
+ }
+
+ /**
+ * Implementation of the Iterator key() method. Returns the key of the current module.
+ *
+ * @return mixed The class name of the current module.
+ */
+ public function key()
+ {
+ return key($this->_modules);
+ }
+
+ /**
+ * Implementation of the Iterator next() method. Returns the next module.
+ *
+ * @return Horde_Qc_Module|null The next module or null if there are no more
+ * modules.
+ */
+ public function next()
+ {
+ return next($this->_modules);
+ }
+
+ /**
+ * Implementation of the Iterator valid() method. Indicates if the current element is a valid element.
+ *
+ * @return boolean Whether the current element is valid
+ */
+ public function valid()
+ {
+ return key($this->_modules) !== null;
+ }
+
+ /**
+ * Implementation of Countable count() method. Returns the number of modules.
+ *
+ * @return integer Number of modules.
+ */
+ public function count()
+ {
+ return count($this->_modules);
+ }
+}
\ No newline at end of file
diff --git a/framework/Qc/package.xml b/framework/Qc/package.xml
index 4d41851ab..b3dce269a 100644
--- a/framework/Qc/package.xml
+++ b/framework/Qc/package.xml
@@ -46,9 +46,15 @@
-
+
+
+
+
+
+
+
@@ -83,9 +89,13 @@
+
+
-
+
+
+
diff --git a/framework/Qc/test/Horde/Qc/AllTests.php b/framework/Qc/test/Horde/Qc/AllTests.php
index ad3f9c508..49a919fa9 100644
--- a/framework/Qc/test/Horde/Qc/AllTests.php
+++ b/framework/Qc/test/Horde/Qc/AllTests.php
@@ -4,11 +4,12 @@
*
* PHP version 5
*
- * @category Horde
- * @package Qc
- * @author Gunnar Wrobel
- * @license http://www.fsf.org/copyleft/lgpl.html LGPL
- * @link http://pear.horde.org/index.php?package=Qc
+ * @category Horde
+ * @package Qc
+ * @subpackage UnitTests
+ * @author Gunnar Wrobel
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Qc
*/
/**
@@ -24,8 +25,19 @@ if (!defined('PHPUnit_MAIN_METHOD')) {
require_once 'Horde/Test/AllTests.php';
/**
- * @package Horde_Qc
+ * Combine the tests for this package.
+ *
+ * Copyright 2007-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 Horde
+ * @package Qc
* @subpackage UnitTests
+ * @author Gunnar Wrobel
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Qc
*/
class Horde_Qc_AllTests extends Horde_Test_AllTests
{
diff --git a/framework/Qc/test/Horde/Qc/Autoload.php b/framework/Qc/test/Horde/Qc/Autoload.php
new file mode 100644
index 000000000..f3bdae77f
--- /dev/null
+++ b/framework/Qc/test/Horde/Qc/Autoload.php
@@ -0,0 +1,41 @@
+
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Qc
+ */
+
+if (!spl_autoload_functions()) {
+ spl_autoload_register(
+ create_function(
+ '$class',
+ '$filename = str_replace(array(\'::\', \'_\'), \'/\', $class);'
+ . '$err_mask = E_ALL ^ E_WARNING;'
+ . '$oldErrorReporting = error_reporting($err_mask);'
+ . 'include "$filename.php";'
+ . 'error_reporting($oldErrorReporting);'
+ )
+ );
+}
+
+/** Catch strict standards */
+error_reporting(E_ALL | E_STRICT);
+
+
+/** Load the basic test definition */
+require_once dirname(__FILE__) . '/StoryTestCase.php';
+
+/** Load stubs */
+require_once dirname(__FILE__) . '/Stub/Parser.php';
diff --git a/framework/Qc/test/Horde/Qc/Integration/QcTest.php b/framework/Qc/test/Horde/Qc/Integration/QcTest.php
new file mode 100644
index 000000000..93e10defb
--- /dev/null
+++ b/framework/Qc/test/Horde/Qc/Integration/QcTest.php
@@ -0,0 +1,67 @@
+
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Qc
+ */
+
+/**
+ * Prepare the test setup.
+ */
+require_once dirname(__FILE__) . '/../Autoload.php';
+
+/**
+ * Test the Qc package.
+ *
+ * Copyright 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 Horde
+ * @package Qc
+ * @subpackage UnitTests
+ * @author Gunnar Wrobel
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Qc
+ */
+class Horde_Qc_Integration_QcTest
+extends Horde_Qc_StoryTestCase
+{
+ /**
+ * @scenario
+ */
+ public function theHelpOptionResultsInHelpOutput()
+ {
+ $this->given('the default QC package setup')
+ ->when('calling the package with the help option')
+ ->then('the help will be displayed');
+ }
+
+ /**
+ * @scenario
+ */
+ public function thePearpackagexmlModuleAddsThePOptionInTheHelpOutput()
+ {
+ $this->given('the default QC package setup')
+ ->when('calling the package with the help option')
+ ->then('the help will contain the "p" option.');
+ }
+
+ /**
+ * @scenario
+ */
+ public function thePearpackagexmlModuleAddsTheUOptionInTheHelpOutput()
+ {
+ $this->given('the default QC package setup')
+ ->when('calling the package with the help option')
+ ->then('the help will contain the "u" option.');
+ }
+}
\ No newline at end of file
diff --git a/framework/Qc/test/Horde/Qc/StoryTestCase.php b/framework/Qc/test/Horde/Qc/StoryTestCase.php
new file mode 100644
index 000000000..8649540c2
--- /dev/null
+++ b/framework/Qc/test/Horde/Qc/StoryTestCase.php
@@ -0,0 +1,113 @@
+
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Qc
+ */
+
+/**
+ * Base for story based package testing.
+ *
+ * Copyright 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 Horde
+ * @package Qc
+ * @subpackage UnitTests
+ * @author Gunnar Wrobel
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Qc
+ */
+class Horde_Qc_StoryTestCase
+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 'the default QC package setup':
+ 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 'calling the package with the help option':
+ $_SERVER['argv'] = array('hqc', '--help', '--packagexml');
+ ob_start();
+ $parameters = array();
+ $parameters['config']['cli']['parser']['class'] = 'Horde_Qc_Stub_Parser';
+ Horde_Qc::main($parameters);
+ $world['output'] = ob_get_contents();
+ ob_end_clean();
+ 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 help will be displayed':
+ $this->assertRegExp(
+ '/-h,[ ]*--help[ ]*show this help message and exit/',
+ $world['output']
+ );
+ break;
+ case 'the help will contain the "p" option.':
+ $this->assertRegExp(
+ '/-p,\s*--packagexml/m',
+ $world['output']
+ );
+ break;
+ case 'the help will contain the "u" option.':
+ $this->assertRegExp(
+ '/-u,\s*--updatexml/',
+ $world['output']
+ );
+ break;
+ default:
+ return $this->notImplemented($action);
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/framework/Qc/test/Horde/Qc/Stub/Parser.php b/framework/Qc/test/Horde/Qc/Stub/Parser.php
new file mode 100644
index 000000000..44303cd29
--- /dev/null
+++ b/framework/Qc/test/Horde/Qc/Stub/Parser.php
@@ -0,0 +1,10 @@
+
+
+
+
+ ../../../lib
+
+
+
--
2.11.0