A very rough command line interface for koward.
authorGunnar Wrobel <p@rdus.de>
Tue, 28 Apr 2009 20:56:25 +0000 (22:56 +0200)
committerGunnar Wrobel <p@rdus.de>
Tue, 28 Apr 2009 20:56:25 +0000 (22:56 +0200)
koward/bin/koward.php [new file with mode: 0644]
koward/lib/Cli.php [new file with mode: 0644]

diff --git a/koward/bin/koward.php b/koward/bin/koward.php
new file mode 100644 (file)
index 0000000..9a4775a
--- /dev/null
@@ -0,0 +1,93 @@
+#!@php_bin@
+<?php
+
+define('AUTH_HANDLER', true);
+
+/**
+ * The Autoloader allows us to omit "require/include" statements.
+ */
+require_once 'Horde/Autoloader.php';
+
+/**
+ * FIXME START
+ *
+ * Simplify the Autoloader configuration so that the user needs no knowledge of
+ * the app root.
+ */
+
+$options = array(
+    new Horde_Argv_Option('-b', '--base', array('type' => 'string')),
+);
+$parser = new Horde_Argv_Parser(
+    array(
+        'allowUnknownArgs' => true,
+        'optionList' => $options
+    )
+);
+list($opts, $cmd) = $parser->parseArgs();
+
+if (!$opts->base) {
+    throw new InvalidArgumentException('The path to the application base has not been specified!');
+}
+
+/**
+ * Ensure that the base parameters (especially SERVER_NAME) get set for the
+ * command line.
+ */
+$cli = Horde_CLI::singleton();
+$cli->init();
+
+/**
+ * Hm, the fact that we need the registry at this point for identifying the
+ * location where we installed the application is not really satisfying. The
+ * whole "app" dir should probably be in "lib", too. That way we can install it
+ * in a defined location via PEAR.
+ */
+require_once $opts->base . '/lib/base.php';
+
+/** Configure the Autoloader */
+$app = 'koward';
+Horde_Autoloader::addClassPattern('/^Koward_/', $registry->get('fileroot', $app) . '/lib/');
+Horde_Autoloader::addClassPattern('/^Koward_/', $registry->get('fileroot', $app) . '/app/controllers/');
+
+/**
+ * FIXME END
+ */
+
+/** Initialize the command line handler */
+$request = new Koward_Cli();
+
+/**
+ * The following is an extract from rampage.php and only a rough draft. Calling
+ * Controller actions this way is still rather complicated on the command line
+ * this way. For one thing you need to provide the application installation base
+ * which is knowledge we'd rather hide from the user and the full path to the
+ * Controller action (including the path to the app identified by the registry)
+ * has to be provided. This should be handled via other CLI parameters.
+ */
+$mapper = new Horde_Routes_Mapper();
+
+$routeFile = $registry->get('fileroot', $app) . '/config/routes.php';
+if (!file_exists($routeFile)) {
+    throw new Horde_Controller_Exception('Not routable');
+}
+$mapper->prefix = $registry->get('webroot', 'horde') . '/' . $app;
+include $routeFile;
+
+$context = array(
+    'mapper' => $mapper,
+    'controllerDir' => $registry->get('fileroot', $app) . '/app/controllers',
+    'viewsDir' => $registry->get('fileroot', $app) . '/app/views',
+    // 'logger' => '',
+);
+
+try {
+    $dispatcher = Horde_Controller_Dispatcher::singleton($context);
+    $dispatcher->dispatch($request);
+} catch (Exception $e) {
+    // @TODO Make nicer
+    echo '<h1>' . $e->getMessage() . '</h1>';
+    echo '<pre>'; var_dump($e); echo '</pre>';
+}
+
+exit(0);
diff --git a/koward/lib/Cli.php b/koward/lib/Cli.php
new file mode 100644 (file)
index 0000000..43b31bc
--- /dev/null
@@ -0,0 +1,227 @@
+<?php
+/**
+ * Request helper for command line calls.
+ *
+ * PHP version 5
+ *
+ * @category Kolab
+ * @package  Koward
+ * @author   Gunnar Wrobel <wrobel@pardus.de>
+ * @license  http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link     http://pear.horde.org/index.php?package=Koward
+ */
+
+/**
+ * A base for the Koward command line requests.
+ *
+ * Copyright 2009 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  Koward
+ * @author   Gunnar Wrobel <wrobel@pardus.de>
+ * @license  http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link     http://pear.horde.org/index.php?package=Koward
+ */
+class Koward_Cli extends Horde_Controller_Request_Base
+{
+    /**
+     * Command line arguments
+     */
+    protected $_argv;
+
+    /**
+     * Command arguments
+     */
+    protected $_cmd_argv;
+
+   /**
+     */
+    public function __construct($options = array())
+    {
+        global $registry, $conf;
+
+        parent::__construct($options);
+
+        $options = array(
+            new Horde_Argv_Option('-b', '--base', array('type' => 'string')),
+            new Horde_Argv_Option('-u', '--user', array('type' => 'string')),
+            new Horde_Argv_Option('-p', '--pass', array('type' => 'string')),
+        );
+        $parser = new Horde_Argv_Parser(
+            array(
+                'allowUnknownArgs' => true,
+                'optionList' => $options,
+                'addHelpOption' => false,
+            )
+        );
+        list($this->_argv, $args) = $parser->parseArgs();
+        if (!count($args)) {
+            throw new Horde_Controller_Exception('unknown command: ' . implode(' ', $args));
+        }
+
+        /**
+         * FIXME: Workaround to fix the path so that the command line call
+         * really only needs the route.
+         */
+        $this->_path = $registry->get('webroot', 'koward') . '/' . $args[0];
+
+        $this->_cmd_argv = array();
+
+        /* Authenticate the user if possible. */
+        if ($this->_argv->user) {
+            require_once 'Horde/Auth.php';
+            $auth = &Auth::singleton($conf['auth']['driver']);
+            if (!$auth->authenticate($this->_argv->user,
+                                     array('password' => $this->_argv->pass))) {
+                throw new InvalidArgumentException('Failed to log in!');
+            }
+        }
+
+        /**
+         * A rough command line handler that allows us to map CLI requests into
+         * the web view of the system.
+         */
+        switch ($args[0]) {
+        case 'object/edit':
+            $this->_cmd_argv['formname'] = 'koward_form_object';
+
+            /** Has the object type been set? */
+            if ($this->_argv->type && is_array($this->_argv->type)
+                && count($this->_argv->type) == 1) {
+                $type = $this->_argv->type[0];
+
+                /**
+                 * FIXME: Editing on the command line does not work if we don't
+                 * specify the full set of form attributes. Yet another reason
+                 * for not using the Form.
+                 */
+                if ($this->_argv->id && is_array($this->_argv->id)
+                    && count($this->_argv->id) == 1) {
+                    $this->_cmd_argv['id'] = $this->_argv->id[0];
+                } else {
+                    $this->_cmd_argv['id'] = $this->_argv->id;
+                }
+
+                /**
+                 * Fake the selected type for the form handler and short circuit the
+                 * type selection machinery.
+                 */
+                $this->_cmd_argv['__old_type'] = $type;
+
+                /**
+                 * Fake the form token. Hm, it does not really make much sense
+                 * to use the standard form mechanisms via CLI. Think of some
+                 * alternatives here.
+                 */
+                $koward = &Koward_Koward::singleton();
+                $token = $koward->getRequestToken('cli');
+                $this->_cmd_argv['koward_form_object_formToken'] = $token;
+
+                /**
+                 * FIXME: Allow retrieving the form fields without specifying $vars.
+                 */
+                require_once 'Horde/Variables.php';
+                $object = null;
+                $form = new Koward_Form_Object(Variables::getDefaultVariables(), $object);
+
+                $fields = array_keys($form->getTypeFields($type));
+
+                /**
+                 * Now that we know the type of object that should be edited we
+                 * can restrict the amount of options we allow.
+                 */
+                $options = array(
+                    new Horde_Argv_Option('-b', '--base', array('type' => 'string')),
+                    new Horde_Argv_Option('-u', '--user', array('type' => 'string')),
+                    new Horde_Argv_Option('-p', '--pass', array('type' => 'string')),
+                    new Horde_Argv_Option('-t', '--type', array('type' => 'string')),
+                    new Horde_Argv_Option('-i', '--id', array('type' => 'string')),
+                );
+                foreach ($fields as $field) {
+                    $options[] = new Horde_Argv_Option(null, '--' . $field,
+                                                       array('type' => 'string'));
+                }
+                $parser = new Horde_Argv_Parser(
+                    array(
+                        'allowUnknownArgs' => false,
+                        'optionList' => $options,
+                        'addHelpOption' => true,
+                    )
+                );
+                list($cmd_argv, $cmd) = $parser->parseArgs();
+                foreach ($cmd_argv as $field => $value) {
+                    if ($field == 'userPassword') {
+                        /**
+                         * FIXME: Obvious hack and probably another reason why
+                         * mixing forms and CLI does not make that much
+                         * sense.
+                         */
+                        $this->_cmd_argv['object']['userPassword']['original'] = $value;
+                        $this->_cmd_argv['object']['userPassword']['confirm'] = $value;
+                    } else if (in_array($field, $fields) && $value !== null) {
+                        $this->_cmd_argv['object'][$field] = $value;
+                    }
+                }
+            }
+            break;
+        case 'object/delete':
+            if ($this->_argv->id && is_array($this->_argv->id)
+                && count($this->_argv->id) == 1) {
+                $this->_cmd_argv['id'] = $this->_argv->id[0];
+            } else {
+                $this->_cmd_argv['id'] = $this->_argv->id;
+            }
+
+            /**
+             * Provide a token for immediate deletion.
+             */
+            $koward = &Koward_Koward::singleton();
+            $this->_cmd_argv['token'] = $koward->getRequestToken('object.delete');
+
+            break;
+        }
+    }
+
+    public function getUri()
+    {
+        return $this->getPath();
+    }
+
+    public function getPath()
+    {
+        return $this->_path;
+    }
+
+    public function getArguments()
+    {
+        return $this->_argv;
+    }
+
+    /**
+     * Get all command line parameters.
+     * some wacky loops to make sure that nested values in one
+     * param list don't overwrite other nested values
+     *
+     * @return  array
+     */
+    public function getParameters()
+    {
+        $allParams = array();
+        $paramArrays = array($this->_pathParams, $this->_argv, $this->_cmd_argv);
+
+        foreach ($paramArrays as $params) {
+            foreach ((array)$params as $key => $value) {
+                if (!is_array($value) || !isset($allParams[$key])) {
+                    $allParams[$key] = $value;
+                } else {
+                    $allParams[$key] = array_merge($allParams[$key], $value);
+                }
+            }
+        }
+        return $allParams;
+    }
+
+}
\ No newline at end of file