Finish the module provider and complete the module definition.
authorGunnar Wrobel <p@rdus.de>
Wed, 15 Dec 2010 20:14:11 +0000 (21:14 +0100)
committerGunnar Wrobel <p@rdus.de>
Thu, 16 Dec 2010 07:07:02 +0000 (08:07 +0100)
framework/Cli_Modular/lib/Horde/Cli/Modular.php
framework/Cli_Modular/lib/Horde/Cli/Modular/Module.php
framework/Cli_Modular/lib/Horde/Cli/Modular/ModuleProvider.php
framework/Cli_Modular/package.xml
framework/Cli_Modular/test/Horde/Cli/Modular/Autoload.php
framework/Cli_Modular/test/Horde/Cli/Modular/Stub/Module/One.php
framework/Cli_Modular/test/Horde/Cli/Modular/Stub/Provider.php [new file with mode: 0644]
framework/Cli_Modular/test/Horde/Cli/Modular/Unit/ModularTest.php
framework/Cli_Modular/test/Horde/Cli/Modular/Unit/ModuleProviderTest.php

index ad81c31..1124725 100644 (file)
@@ -42,6 +42,13 @@ class Horde_Cli_Modular
     private $_modules;
 
     /**
+     * Module provider.
+     *
+     * @var Horde_Cli_Modular_ModuleProvider
+     */
+    private $_provider;
+
+    /**
      * Constructor.
      *
      * @param array $parameters Options for this instance.
@@ -56,6 +63,11 @@ class Horde_Cli_Modular
      *                        See Horde_Cli_Modular_Modules::__construct()
      *               (string) A class name.
      *               (object) An instance of Horde_Cli_Modular_Modules
+     *  - provider:  Determines the module provider. Can be one of:
+     *               (array)  A parameter array.
+     *                        See Horde_Cli_Modular_ModuleProvider::__construct()
+     *               (string) A class name.
+     *               (object) An instance of Horde_Cli_Modular_ModuleProvider
      * </pre>
      */
     public function __construct(array $parameters = null)
@@ -90,7 +102,7 @@ class Horde_Cli_Modular
             $usage = $this->_parameters['cli']['parser']['usage'];
         }
         foreach ($this->getModules() as $module) {
-            $usage .= '';
+            $usage .= $this->getProvider()->getModule($module)->getUsage();
         }
         return $usage;
     }
@@ -103,15 +115,33 @@ class Horde_Cli_Modular
     public function createParser()
     {
         $parser_class = $this->getParserClass();
-        return new $parser_class(
+        $parser = new $parser_class(
             array(
                 'usage' => '%prog ' . $this->getUsage()
             )
         );
+        foreach ($this->getModules() as $module_name) {
+            $module = $this->getProvider()->getModule($module_name);
+            foreach ($module->getBaseOptions() as $option) {
+                $parser->addOption($option);
+            }
+            if ($module->hasOptionGroup()) {
+                $group = new Horde_Argv_OptionGroup(
+                    $parser,
+                    $module->getOptionGroupTitle(),
+                    $module->getOptionGroupDescription()
+                );
+                foreach ($module->getOptionGroupOptions() as $option) {
+                    $group->addOption($option);
+                }
+                $parser->addOptionGroup($group);
+            }
+        }
+        return $parser;
     }
 
     /**
-     * Create the module handler.
+     * Return the module handler.
      *
      * @return Horde_Cli_Modular_Modules The module handler.
      */
@@ -148,4 +178,43 @@ class Horde_Cli_Modular
             );
         }
     }
+
+    /**
+     * Return the module provider.
+     *
+     * @return Horde_Cli_Modular_ModuleProvider The module provider.
+     */
+    public function getProvider()
+    {
+        if ($this->_provider === null) {
+            $this->_provider = $this->_createProvider();
+        }
+        return $this->_provider;
+    }
+
+    /**
+     * Create the module provider.
+     *
+     * @return Horde_Cli_Modular_ModuleProvider The module provider.
+     */
+    private function _createProvider()
+    {
+        if (is_array($this->_parameters['provider'])) {
+            return new Horde_Cli_Modular_ModuleProvider(
+                $this->_parameters['provider']
+            );
+        } else if ($this->_parameters['provider'] instanceOf Horde_Cli_Modular_ModuleProvider) {
+            return $this->_parameters['provider'];
+        } else if (is_string($this->_parameters['provider'])) {
+            return new $this->_parameters['provider']();
+        } else if (empty($this->_parameters['provider'])) {
+            throw new Horde_Cli_Modular_Exception(
+                'Missing "provider" parameter!'
+            );
+        } else {
+            throw new Horde_Cli_Modular_Exception(
+                'Invalid "provider" parameter!'
+            );
+        }
+    }
 }
\ No newline at end of file
index 1b4837a..d722a87 100644 (file)
@@ -32,5 +32,41 @@ interface Horde_Cli_Modular_Module
      *
      * @return string The description.
      */
-    static public function getUsage();
+    public function getUsage();
+
+    /**
+     * Get a set of base options that this module adds to the CLI argument
+     * parser.
+     *
+     * @return array The options.
+     */
+    public function getBaseOptions();
+
+    /**
+     * Indicate if the module provides an option group.
+     *
+     * @return boolean True if an option group should be added.
+     */
+    public function hasOptionGroup();
+
+    /**
+     * Return the title for the option group representing this module.
+     *
+     * @return string The group title.
+     */
+    public function getOptionGroupTitle();
+
+    /**
+     * Return the description for the option group representing this module.
+     *
+     * @return string The group description.
+     */
+    public function getOptionGroupDescription();
+
+    /**
+     * Return the options for this module.
+     *
+     * @return array The group options.
+     */
+    public function getOptionGroupOptions();
 }
\ No newline at end of file
index 78949e7..7b27b14 100644 (file)
@@ -37,11 +37,27 @@ class Horde_Cli_Modular_ModuleProvider
     private $_prefix;
 
     /**
+     * Constructor argument for CLI modules. Likely to be a Horde_Injector
+     * instance.
+     *
+     * @var mixed
+     */
+    private $_dependencies;
+
+    /**
+     * A cache for initialized module instances.
+     *
+     * @var array
+     */
+    private $_instances;
+
+    /**
      * Constructor.
      *
      * @param array $parameters Options for this instance.
      * <pre>
-     *  - 
+     *  - prefix: The module class name prefix.
+     *  - dependencies: Constructor argument for CLI modules.
      * </pre>
      */
     public function __construct(array $parameters = null)
@@ -52,29 +68,47 @@ class Horde_Cli_Modular_ModuleProvider
             );
         }
         $this->_prefix = $parameters['prefix'];
+        if (isset($parameters['dependencies'])) {
+            $this->_dependencies = $parameters['dependencies'];
+        }
+    }
+
+    /**
+     * Return the specified module.
+     *
+     * @param string $module The desired module.
+     *
+     * @return Horde_Cli_Modular_Module The module instance.
+     *
+     * @throws Horde_Cli_Modular_Exception In case the specified module does not
+     * exist.
+     */
+    public function getModule($module)
+    {
+        if (!isset($this->_instances[$module])) {
+            $this->_instances[$module] = $this->createModule($module);
+        }
+        return $this->_instances[$module];
     }
 
     /**
-     * Get the usage string for the specified module.
+     * Create the specified module.
      *
      * @param string $module The desired module.
      *
-     * @return string The usage description for this module.
+     * @return Horde_Cli_Modular_Module The module instance.
      *
      * @throws Horde_Cli_Modular_Exception In case the specified module does not
      * exist.
      */
-    public function getUsage($module)
+    protected function createModule($module)
     {
-        if (!class_exists($this->_prefix . $module)) {
+        $class = $this->_prefix . $module;
+        if (!class_exists($class)) {
             throw new Horde_Cli_Modular_Exception(
-                sprintf(
-                    'Invalid module %s!', $this->_prefix . $module
-                )
+                sprintf('Invalid module %s!', $class)
             );
         }
-        return call_user_func_array(
-            array($this->_prefix . $module, 'getUsage'), array()
-        );
+        return new $class();
     }
 }
\ No newline at end of file
index ea46cb3..f810662 100644 (file)
    <pearinstaller>
     <min>1.9.0</min>
    </pearinstaller>
+   <package>
+    <name>Argv</name>
+    <channel>pear.horde.org</channel>
+   </package>
   </required>
+  <optional>
+   <package>
+    <name>Test</name>
+    <channel>pear.horde.org</channel>
+   </package>
+  </optional>
  </dependencies>
  <phprelease>
   <filelist>
index a5290b2..1d77a74 100644 (file)
@@ -27,4 +27,5 @@ require_once dirname(__FILE__) . '/TestCase.php';
 
 /** Load stub classes */
 require_once dirname(__FILE__) . '/Stub/Modules.php';
+require_once dirname(__FILE__) . '/Stub/Provider.php';
 require_once dirname(__FILE__) . '/Stub/Module/One.php';
\ No newline at end of file
index 2ad1a0a..d853c9c 100644 (file)
@@ -3,8 +3,77 @@
 class Horde_Cli_Modular_Stub_Module_One
 implements Horde_Cli_Modular_Module
 {
-    static public function getUsage()
+    public function getUsage()
     {
         return 'Use One';
     }
+
+    /**
+     * Get a set of base options that this module adds to the CLI argument
+     * parser.
+     *
+     * @return array The options.
+     */
+    public function getBaseOptions()
+    {
+        return array(
+            new Horde_Argv_Option(
+                '-s',
+                '--something',
+                array(
+                    'action' => 'store',
+                    'help'   => 'Base option'
+                )
+            ),
+        );
+    }
+
+    /**
+     * Indicate if the module provides an option group.
+     *
+     * @return boolean True if an option group should be added.
+     */
+    public function hasOptionGroup()
+    {
+        return true;
+    }
+
+    /**
+     * Return the title for the option group representing this module.
+     *
+     * @return string The group title.
+     */
+    public function getOptionGroupTitle()
+    {
+        return 'Test Group Title';
+    }
+
+    /**
+     * Return the description for the option group representing this module.
+     *
+     * @return string The group description.
+     */
+    public function getOptionGroupDescription()
+    {
+        return 'Test Group Description';
+    }
+
+    /**
+     * Return the options for this module.
+     *
+     * @return array The group options.
+     */
+    public function getOptionGroupOptions()
+    {
+        return array(
+            new Horde_Argv_Option(
+                '-g',
+                '--group',
+                array(
+                    'action' => 'store',
+                    'help'   => 'Group option'
+                )
+            ),
+        );
+    }
 }
\ No newline at end of file
diff --git a/framework/Cli_Modular/test/Horde/Cli/Modular/Stub/Provider.php b/framework/Cli_Modular/test/Horde/Cli/Modular/Stub/Provider.php
new file mode 100644 (file)
index 0000000..c5c14ab
--- /dev/null
@@ -0,0 +1,9 @@
+<?php
+
+class Horde_Cli_Modular_Stub_Provider
+extends Horde_Cli_Modular_ModuleProvider
+{
+    public function __construct()
+    {
+    }
+}
index 4f1ce01..919145a 100644 (file)
@@ -40,7 +40,10 @@ extends Horde_Cli_Modular_TestCase
         $modular = new Horde_Cli_Modular(
             array(
                 'modules' => array(
-                    'directory' => dirname(__FILE__) . '/../fixtures/Module'
+                    'directory' => dirname(__FILE__) . '/../Stub/Module'
+                ),
+                'provider' => array(
+                    'prefix' => 'Horde_Cli_Modular_Stub_Module_'
                 ),
             )
         );
@@ -49,18 +52,7 @@ extends Horde_Cli_Modular_TestCase
 
     public function testCustomParser()
     {
-        $modular = new Horde_Cli_Modular(
-            array(
-                'cli' => array(
-                    'parser' => array(
-                        'class' => 'Horde_Test_Stub_Parser'
-                    )
-                ),
-                'modules' => array(
-                    'directory' => dirname(__FILE__) . '/../fixtures/Module'
-                ),
-            )
-        );
+        $modular = $this->_getDefault();
         $this->assertInstanceOf('Horde_Test_Stub_Parser', $modular->createParser());
     }
 
@@ -70,7 +62,7 @@ extends Horde_Cli_Modular_TestCase
     public function testMissingModules()
     {
         $modular = new Horde_Cli_Modular();
-        $this->assertInstanceOf('Horde_Cli_Modular_Modules', $modular->getModules());
+        $modular->getModules();
     }
 
     /**
@@ -79,7 +71,7 @@ extends Horde_Cli_Modular_TestCase
     public function testInvalidModules()
     {
         $modular = new Horde_Cli_Modular(array('modules' => 1.0));
-        $this->assertInstanceOf('Horde_Cli_Modular_Modules', $modular->getModules());
+        $modular->getModules();
     }
 
     public function testObjectModules()
@@ -117,4 +109,121 @@ extends Horde_Cli_Modular_TestCase
         $this->assertInstanceOf('Horde_Cli_Modular_Modules', $modular->getModules());
     }
 
+    /**
+     * @expectedException Horde_Cli_Modular_Exception
+     */
+    public function testMissingProviders()
+    {
+        $modular = new Horde_Cli_Modular();
+        $modular->getProvider();
+    }
+
+    /**
+     * @expectedException Horde_Cli_Modular_Exception
+     */
+    public function testInvalidProviders()
+    {
+        $modular = new Horde_Cli_Modular(array('provider' => 1.0));
+        $modular->getProvider();
+    }
+
+    public function testObjectProviders()
+    {
+        $modular = new Horde_Cli_Modular(
+            array('provider' => new Horde_Cli_Modular_ModuleProvider(
+                      array('prefix' => 'Test')
+                  )
+            )
+        );
+        $this->assertInstanceOf(
+            'Horde_Cli_Modular_ModuleProvider', $modular->getProvider()
+        );
+    }
+
+    public function testStringProviders()
+    {
+        $modular = new Horde_Cli_Modular(
+            array(
+                'provider' => 'Horde_Cli_Modular_Stub_Provider'
+            )
+        );
+        $this->assertInstanceOf(
+            'Horde_Cli_Modular_ModuleProvider', $modular->getProvider()
+        );
+    }
+
+    public function testArrayProviders()
+    {
+        $modular = new Horde_Cli_Modular(
+            array(
+                'provider' => array(
+                    'prefix' => 'Test'
+                ),
+            )
+        );
+        $this->assertInstanceOf(
+            'Horde_Cli_Modular_ModuleProvider', $modular->getProvider()
+        );
+    }
+
+    public function testGeneralUsage()
+    {
+        $modular = $this->_getDefault();
+        $this->assertContains(
+            'GLOBAL USAGE', $modular->createParser()->formatHelp()
+        );
+    }
+
+    public function testBaseOption()
+    {
+        $modular = $this->_getDefault();
+        $this->assertContains(
+            '--something=SOMETHING', $modular->createParser()->formatHelp()
+        );
+    }
+
+    public function testGroupTitle()
+    {
+        $modular = $this->_getDefault();
+        $this->assertContains(
+            'Test Group Title', $modular->createParser()->formatHelp()
+        );
+    }
+
+    public function testGroupDescription()
+    {
+        $modular = $this->_getDefault();
+        $this->assertContains(
+            'Test Group Description', $modular->createParser()->formatHelp()
+        );
+    }
+
+    public function testGroupOption()
+    {
+        $modular = $this->_getDefault();
+        $this->assertContains(
+            '--group=GROUP', $modular->createParser()->formatHelp()
+        );
+    }
+
+    private function _getDefault()
+    {
+        return new Horde_Cli_Modular(
+            array(
+                'cli' => array(
+                    'parser' => array(
+                        'class' => 'Horde_Test_Stub_Parser',
+                        'usage' => 'GLOBAL USAGE'
+                        
+                    )
+                ),
+                'modules' => array(
+                    'directory' => dirname(__FILE__) . '/../Stub/Module'
+                ),
+                'provider' => array(
+                    'prefix' => 'Horde_Cli_Modular_Stub_Module_'
+                ),
+            )
+        );
+    }
 }
index d010982..993368f 100644 (file)
@@ -51,14 +51,19 @@ extends Horde_Cli_Modular_TestCase
         $provider = new Horde_Cli_Modular_ModuleProvider(
             array('prefix' => 'INVALID')
         );
-        $provider->getUsage('One');
+        $provider->getModule('One')->getUsage('One');
     }
 
     public function testUsage()
     {
         $provider = new Horde_Cli_Modular_ModuleProvider(
-            array('prefix' => 'Horde_Cli_Modular_Stub_Module_')
+            array(
+                'prefix' => 'Horde_Cli_Modular_Stub_Module_',
+                'dependencies' => new stdClass,
+            )
+        );
+        $this->assertEquals(
+            'Use One', $provider->getModule('One')->getUsage('One')
         );
-        $this->assertEquals('Use One', $provider->getUsage('One'));
     }
 }