Move imple handling to Horde_Ajax_Imple::.
authorMichael M Slusarz <slusarz@curecanti.org>
Thu, 16 Jul 2009 19:22:28 +0000 (13:22 -0600)
committerMichael M Slusarz <slusarz@curecanti.org>
Thu, 16 Jul 2009 19:37:42 +0000 (13:37 -0600)
23 files changed:
imp/imple.php [deleted file]
imp/lib/Ajax/Imple/ContactAutoCompleter.php [new file with mode: 0644]
imp/lib/Ajax/Imple/SpellChecker.php [new file with mode: 0644]
imp/lib/Imple.php [deleted file]
imp/lib/Imple/ContactAutoCompleter.php [deleted file]
imp/lib/Imple/SpellChecker.php [deleted file]
imp/lib/UI/Compose.php
kronolith/attendees.php
kronolith/calendars/edit.php
kronolith/imple.php [deleted file]
kronolith/index.php
kronolith/js/src/tagactions.js
kronolith/lib/Ajax/Imple/ContactAutoCompleter.php [new file with mode: 0644]
kronolith/lib/Ajax/Imple/Embed.php [new file with mode: 0644]
kronolith/lib/Ajax/Imple/TagActions.php [new file with mode: 0644]
kronolith/lib/Ajax/Imple/TagAutoCompleter.php [new file with mode: 0644]
kronolith/lib/Imple.php [deleted file]
kronolith/lib/Imple/ContactAutoCompleter.php [deleted file]
kronolith/lib/Imple/Embed.php [deleted file]
kronolith/lib/Imple/TagActions.php [deleted file]
kronolith/lib/Imple/TagAutoCompleter.php [deleted file]
kronolith/templates/edit/edit.inc
kronolith/templates/panel.inc

diff --git a/imp/imple.php b/imp/imple.php
deleted file mode 100644 (file)
index b1c37d7..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-<?php
-/**
- * Copyright 2005-2009 The Horde Project (http://www.horde.org/)
- *
- * See the enclosed file COPYING for license information (GPL). If you
- * did not receive this file, see http://www.fsf.org/copyleft/gpl.html.
- *
- * @author  Michael Slusarz <slusarz@horde.org>
- * @package IMP
- */
-
-// As of right now, imples don't need read/write session access.
-$session_control = 'readonly';
-$session_timeout = 'none';
-
-$authentication = 'horde';
-require_once dirname(__FILE__) . '/lib/base.php';
-
-$viewmode = $_SESSION['imp']['view'];
-
-if (!($path = Horde_Util::getFormData('imple'))) {
-    if ($viewmode == 'dimp') {
-        Horde::sendHTTPResponse(new stdClass(), 'json');
-    }
-    exit;
-}
-
-if ($path[0] == '/') {
-    $path = substr($path, 1);
-}
-
-$path = explode('/', $path);
-$impleName = reset($path);
-
-if (!($imple = IMP_Imple::factory($impleName))) {
-    if ($viewmode == 'dimp') {
-        Horde::sendHTTPResponse(new stdClass(), 'json');
-    }
-    exit;
-}
-
-$args = array();
-foreach ($path as $pair) {
-    if (strpos($pair, '=') === false) {
-        $args[$pair] = true;
-    } else {
-        list($name, $val) = explode('=', $pair);
-        $args[$name] = $val;
-    }
-}
-
-$result = $imple->handle($args);
-
-$ct = empty($_SERVER['Content-Type'])
-    ? (is_string($result) ? 'plain' : 'json')
-    : $_SERVER['Content-Type'];
-
-Horde::sendHTTPResponse($result, $ct);
diff --git a/imp/lib/Ajax/Imple/ContactAutoCompleter.php b/imp/lib/Ajax/Imple/ContactAutoCompleter.php
new file mode 100644 (file)
index 0000000..edadd24
--- /dev/null
@@ -0,0 +1,133 @@
+<?php
+/**
+ * Attach the contact auto completer to a javascript element.
+ *
+ * Copyright 2005-2009 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file COPYING for license information (GPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/gpl.html.
+ *
+ * @author  Michael Slusarz <slusarz@horde.org>
+ * @package IMP
+ */
+class IMP_Ajax_Imple_ContactAutoCompleter extends Horde_Ajax_Imple_Base
+{
+    /**
+     * The URL to use in attach().
+     *
+     * @var string
+     */
+    protected $_url;
+
+    /**
+     * Has the address book been output to the browser?
+     *
+     * @var boolean
+     */
+    static protected $_listOutput = false;
+
+    /**
+     * Constructor.
+     *
+     * @param array $params  Configuration parameters.
+     * <pre>
+     * 'triggerId' => TODO (optional)
+     * 'resultsId' => TODO (optional)
+     * </pre>
+     */
+    public function __construct($params)
+    {
+        if (empty($params['triggerId'])) {
+            $params['triggerId'] = $this->_randomid();
+        }
+        if (empty($params['resultsId'])) {
+            $params['resultsId'] = $params['triggerId'] . '_results';
+        }
+
+        parent::__construct($params);
+    }
+
+    /**
+     * Attach the object to a javascript event.
+     */
+    public function attach()
+    {
+        Horde::addScriptFile('prototype.js', 'horde', true);
+        Horde::addScriptFile('effects.js', 'horde', true);
+        Horde::addScriptFile('autocomplete.js', 'horde', true);
+
+        $params = array(
+            '"' . $this->_params['triggerId'] . '"',
+            '"' . $this->_params['resultsId'] . '"'
+        );
+
+        $js_params = array(
+            'tokens: [",", ";"]',
+            'indicator: "' . $this->_params['triggerId'] . '_loading_img"',
+            'afterUpdateElement: function(f, t) { if (!f.value.endsWith(";")) { f.value += ","; } f.value += " "; }'
+        );
+        $ac_browser = empty($GLOBALS['conf']['compose']['ac_browser']) ? 0 : $GLOBALS['conf']['compose']['ac_browser'];
+
+        if ($ac_browser && !isset($_SESSION['imp']['cache']['ac_ajax'])) {
+            $success = $use_ajax = true;
+            $sparams = IMP_Compose::getAddressSearchParams();
+            foreach ($sparams['fields'] as $val) {
+                array_map('strtolower', $val);
+                sort($val);
+                if ($val != array('email', 'name')) {
+                    $success = false;
+                    break;
+                }
+            }
+            if ($success) {
+                $addrlist = IMP_Compose::getAddressList();
+                $use_ajax = count($addrlist) > $ac_browser;
+            }
+            $_SESSION['imp']['cache']['ac_ajax'] = $use_ajax;
+        }
+
+        if (!$ac_browser || $_SESSION['imp']['cache']['ac_ajax']) {
+            $func = 'Ajax.Autocompleter';
+            if (empty($this->_url)) {
+                $this->_url = $this->_getUrl('ContactAutoCompleter', 'imp', array('input' => $this->_params['triggerId']));
+            }
+            $params[] = '"' . $this->_url . '"';
+
+            $js_params[] = 'minChars: ' . intval($GLOBALS['conf']['compose']['ac_threshold'] ? $GLOBALS['conf']['compose']['ac_threshold'] : 1);
+        } else {
+            if (!self::$_listOutput) {
+                if (!isset($addrlist)) {
+                    $addrlist = IMP_Compose::getAddressList();
+                }
+                IMP::addInlineScript('if (!IMP) { var IMP = {}; } IMP.ac_list = '. Horde_Serialize::serialize(array_map('htmlspecialchars', $addrlist), Horde_Serialize::JSON, Horde_Nls::getCharset()));
+                self::$_listOutput = true;
+            }
+            $func = 'Autocompleter.Local';
+            $params[] = 'IMP.ac_list';
+            $js_params[] = 'partialSearch: true';
+            $js_params[] = 'fullSearch: true';
+        }
+
+        $params[] = '{' . implode(',', $js_params) . '}';
+        IMP::addInlineScript('new ' . $func . '(' . implode(',', $params) . ')', 'dom');
+    }
+
+    /**
+     * Perform the address search.
+     *
+     * @param array $args  Array with 1 key: 'input'.
+     *
+     * @return array  The data to send to the autocompleter JS code.
+     */
+    public function handle($args)
+    {
+        // Avoid errors if 'input' isn't set and short-circuit empty searches.
+        if (empty($args['input']) ||
+            !($input = Horde_Util::getPost($args['input']))) {
+            return array();
+        }
+
+        return array_map('htmlspecialchars', IMP_Compose::expandAddresses($input));
+    }
+
+}
diff --git a/imp/lib/Ajax/Imple/SpellChecker.php b/imp/lib/Ajax/Imple/SpellChecker.php
new file mode 100644 (file)
index 0000000..d0b1494
--- /dev/null
@@ -0,0 +1,110 @@
+<?php
+/**
+ * Attach the spellchecker to a javascript element.
+ *
+ * Copyright 2005-2009 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file COPYING for license information (GPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/gpl.html.
+ *
+ * @author  Michael Slusarz <slusarz@horde.org>
+ * @package IMP
+ */
+class IMP_Ajax_Imple_SpellChecker extends Horde_Ajax_Imple_Base
+{
+    /**
+     * Constructor.
+     *
+     * @param array $params  Configuration parameters.
+     * <pre>
+     * 'id' => TODO (optional)
+     * 'locales' => TODO (optional)
+     * 'states' => TODO (optional)
+     * 'targetId' => TODO (optional)
+     * 'triggerId' => TODO (optional)
+     * </pre>
+     */
+    public function __construct($params = array())
+    {
+        if (empty($params['id'])) {
+            $params['id'] = $this->_randomid();
+        }
+        if (empty($params['targetId'])) {
+            $params['targetId'] = $this->_randomid();
+        }
+        if (empty($params['triggerId'])) {
+            $params['triggerId'] = $params['targetId'] . '_trigger';
+        }
+        if (empty($params['states'])) {
+            $params['states'] = '""';
+        } else {
+            $params['states'] = Horde_Serialize::serialize($params['states'], Horde_Serialize::JSON, Horde_Nls::getCharset());
+        }
+        if (empty($params['locales'])) {
+            $params['locales'] = array();
+            foreach (array_keys(Horde_Nls::$config['spelling']) as $lcode) {
+                $params['locales'][$lcode] = Horde_Nls::$config['languages'][$lcode];
+            }
+        }
+        asort($params['locales'], SORT_LOCALE_STRING);
+        $params['locales'] = Horde_Serialize::serialize($params['locales'], Horde_Serialize::JSON, Horde_Nls::getCharset());
+
+        parent::__construct($params);
+    }
+
+    /**
+     */
+    public function attach()
+    {
+        Horde::addScriptFile('prototype.js', 'horde', true);
+        Horde::addScriptFile('effects.js', 'horde', true);
+        Horde::addScriptFile('KeyNavList.js', 'imp', true);
+        Horde::addScriptFile('SpellChecker.js', 'imp', true);
+
+        $url = $this->_getUrl('SpellChecker', 'imp', array('input' => $this->_params['targetId']));
+
+        IMP::addInlineScript($this->_params['id'] . ' = new SpellChecker("' . $url . '", "' . $this->_params['targetId'] . '", "' . $this->_params['triggerId'] . '", ' . $this->_params['states'] . ', ' . $this->_params['locales'] . ', \'widget\');', 'dom');
+    }
+
+    /**
+     */
+    public function handle($args)
+    {
+        $spellArgs = array();
+
+        if (!empty($GLOBALS['conf']['spell']['params'])) {
+            $spellArgs = $GLOBALS['conf']['spell']['params'];
+        }
+
+        if (isset($args['locale'])) {
+            $spellArgs['locale'] = $args['locale'];
+        } elseif (isset($GLOBALS['language'])) {
+            $spellArgs['locale'] = $GLOBALS['language'];
+        }
+
+        /* Add local dictionary words. */
+        try {
+            $result = Horde::loadConfiguration('spelling.php', 'ignore_list', 'horde');
+            $spellArgs['localDict'] = $result;
+        } catch (Horde_Exception $e) {}
+
+        if (!empty($args['html'])) {
+            $spellArgs['html'] = true;
+        }
+
+        try {
+            $speller = Horde_SpellChecker::getInstance($GLOBALS['conf']['spell']['driver'], $spellArgs);
+        } catch (Horde_Exception $e) {
+            Horde::logMessage($e, __FILE__, __LINE__, PEAR_LOG_ERR);
+            return array();
+        }
+
+        try {
+            return $speller->spellCheck(Horde_Util::getPost($args['input']));
+        } catch (Horde_Exception $e) {
+            Horde::logMessage($e, __FILE__, __LINE__, PEAR_LOG_ERR);
+            return array('bad' => array(), 'suggestions' => array());
+        }
+    }
+
+}
diff --git a/imp/lib/Imple.php b/imp/lib/Imple.php
deleted file mode 100644 (file)
index a2ce17e..0000000
+++ /dev/null
@@ -1,98 +0,0 @@
-<?php
-/**
- * TODO
- *
- * Copyright 2005-2009 The Horde Project (http://www.horde.org/)
- *
- * See the enclosed file COPYING for license information (GPL). If you
- * did not receive this file, see http://www.fsf.org/copyleft/gpl.html.
- *
- * @author  Michael Slusarz <slusarz@horde.org>
- * @package IMP
- */
-class IMP_Imple
-{
-    /**
-     * Parameters needed by the subclasses.
-     *
-     * @var array
-     */
-    protected $_params = array();
-
-    /**
-     * Attempts to return a concrete IMP_Imple instance based on $imple.
-     *
-     * @param string $imple  The type of concrete subclass to return based
-     *                       on the imple type indicated. The code is
-     *                       dynamically included.
-     * @param array $params  The configuration parameter array.
-     *
-     * @return mixed  The newly created concrete instance, or false on error.
-     */
-    static public function factory($imple, $params = array())
-    {
-        $imple = basename($imple);
-        if (!$imple) {
-            return false;
-        }
-
-        $class = 'IMP_Imple_' . $imple;
-        if (!class_exists($class)) {
-            include_once dirname(__FILE__) . '/Imple/' . $imple . '.php';
-            if (!class_exists($class)) {
-                return false;
-            }
-        }
-
-        return new $class($params);
-    }
-
-    /**
-     * Constructor.
-     *
-     * @param array $params  Any parameters needed by the class.
-     */
-    function __construct($params)
-    {
-        $this->_params = $params;
-        $this->attach();
-    }
-
-    /**
-     * Attach the object to a javascript event.
-     */
-    public function attach()
-    {
-        Horde::addScriptFile('prototype.js', 'horde', true);
-        Horde::addScriptFile('effects.js', 'horde', true);
-    }
-
-    /**
-     * TODO
-     *
-     * @param TODO
-     */
-    public function handle($args)
-    {
-    }
-
-    /**
-     * Return the rendered HTML code.
-     *
-     * @return string  The HTML code.
-     */
-    public function html()
-    {
-    }
-
-    /**
-     * Generate a random ID string.
-     *
-     * @return string  The random ID string.
-     */
-    protected function _randomid()
-    {
-        return 'imple_' . uniqid(mt_rand());
-    }
-
-}
diff --git a/imp/lib/Imple/ContactAutoCompleter.php b/imp/lib/Imple/ContactAutoCompleter.php
deleted file mode 100644 (file)
index 3960b3c..0000000
+++ /dev/null
@@ -1,130 +0,0 @@
-<?php
-/**
- * Copyright 2005-2009 The Horde Project (http://www.horde.org/)
- *
- * See the enclosed file COPYING for license information (GPL). If you
- * did not receive this file, see http://www.fsf.org/copyleft/gpl.html.
- *
- * @author  Michael Slusarz <slusarz@horde.org>
- * @package IMP
- */
-class IMP_Imple_ContactAutoCompleter extends IMP_Imple
-{
-    /**
-     * The URL to use in attach().
-     *
-     * @var string
-     */
-    protected $_url;
-
-    /**
-     * Has the address book been output to the browser?
-     *
-     * @var boolean
-     */
-    static protected $_listOutput = false;
-
-    /**
-     * Constructor.
-     *
-     * @param array $params  Configuration parameters.
-     * <pre>
-     * 'triggerId' => TODO (optional)
-     * 'resultsId' => TODO (optional)
-     * </pre>
-     */
-    function __construct($params)
-    {
-        if (empty($params['triggerId'])) {
-            $params['triggerId'] = $this->_randomid();
-        }
-        if (empty($params['resultsId'])) {
-            $params['resultsId'] = $params['triggerId'] . '_results';
-        }
-
-        parent::__construct($params);
-    }
-
-    /**
-     * Attach the object to a javascript event.
-     */
-    public function attach()
-    {
-        parent::attach();
-        Horde::addScriptFile('autocomplete.js', 'horde', true);
-
-        $params = array(
-            '"' . $this->_params['triggerId'] . '"',
-            '"' . $this->_params['resultsId'] . '"'
-        );
-
-        $js_params = array(
-            'tokens: [",", ";"]',
-            'indicator: "' . $this->_params['triggerId'] . '_loading_img"',
-            'afterUpdateElement: function(f, t) { if (!f.value.endsWith(";")) { f.value += ","; } f.value += " "; }'
-        );
-        $ac_browser = empty($GLOBALS['conf']['compose']['ac_browser']) ? 0 : $GLOBALS['conf']['compose']['ac_browser'];
-
-        if ($ac_browser && !isset($_SESSION['imp']['cache']['ac_ajax'])) {
-            $success = $use_ajax = true;
-            $sparams = IMP_Compose::getAddressSearchParams();
-            foreach ($sparams['fields'] as $val) {
-                array_map('strtolower', $val);
-                sort($val);
-                if ($val != array('email', 'name')) {
-                    $success = false;
-                    break;
-                }
-            }
-            if ($success) {
-                $addrlist = IMP_Compose::getAddressList();
-                $use_ajax = count($addrlist) > $ac_browser;
-            }
-            $_SESSION['imp']['cache']['ac_ajax'] = $use_ajax;
-        }
-
-        if (!$ac_browser || $_SESSION['imp']['cache']['ac_ajax']) {
-            $func = 'Ajax.Autocompleter';
-            if (empty($this->_url)) {
-                $this->_url = Horde::url($GLOBALS['registry']->get('webroot', 'imp') . '/imple.php?imple=ContactAutoCompleter/input=' . rawurlencode($this->_params['triggerId']), true);
-            }
-            $params[] = '"' . $this->_url . '"';
-
-            $js_params[] = 'minChars: ' . intval($GLOBALS['conf']['compose']['ac_threshold'] ? $GLOBALS['conf']['compose']['ac_threshold'] : 1);
-        } else {
-            if (!self::$_listOutput) {
-                if (!isset($addrlist)) {
-                    $addrlist = IMP_Compose::getAddressList();
-                }
-                IMP::addInlineScript('if (!IMP) { var IMP = {}; } IMP.ac_list = '. Horde_Serialize::serialize(array_map('htmlspecialchars', $addrlist), Horde_Serialize::JSON, Horde_Nls::getCharset()));
-                self::$_listOutput = true;
-            }
-            $func = 'Autocompleter.Local';
-            $params[] = 'IMP.ac_list';
-            $js_params[] = 'partialSearch: true';
-            $js_params[] = 'fullSearch: true';
-        }
-
-        $params[] = '{' . implode(',', $js_params) . '}';
-        IMP::addInlineScript('new ' . $func . '(' . implode(',', $params) . ')', 'dom');
-    }
-
-    /**
-     * Perform the address search.
-     *
-     * @param array $args  Array with 1 key: 'input'.
-     *
-     * @return array  The data to send to the autocompleter JS code.
-     */
-    public function handle($args)
-    {
-        // Avoid errors if 'input' isn't set and short-circuit empty searches.
-        if (empty($args['input']) ||
-            !($input = Horde_Util::getPost($args['input']))) {
-            return array();
-        }
-
-        return array_map('htmlspecialchars', IMP_Compose::expandAddresses($input));
-    }
-
-}
diff --git a/imp/lib/Imple/SpellChecker.php b/imp/lib/Imple/SpellChecker.php
deleted file mode 100644 (file)
index 9dc4211..0000000
+++ /dev/null
@@ -1,105 +0,0 @@
-<?php
-/**
- * Copyright 2005-2009 The Horde Project (http://www.horde.org/)
- *
- * See the enclosed file COPYING for license information (GPL). If you
- * did not receive this file, see http://www.fsf.org/copyleft/gpl.html.
- *
- * @author  Michael Slusarz <slusarz@horde.org>
- * @package IMP
- */
-class IMP_Imple_SpellChecker extends IMP_Imple
-{
-    /**
-     * Constructor.
-     *
-     * @param array $params  Configuration parameters.
-     * <pre>
-     * 'id' => TODO (optional)
-     * 'locales' => TODO (optional)
-     * 'states' => TODO (optional)
-     * 'targetId' => TODO (optional)
-     * 'triggerId' => TODO (optional)
-     * </pre>
-     */
-    function __construct($params = array())
-    {
-        if (empty($params['id'])) {
-            $params['id'] = $this->_randomid();
-        }
-        if (empty($params['targetId'])) {
-            $params['targetId'] = $this->_randomid();
-        }
-        if (empty($params['triggerId'])) {
-            $params['triggerId'] = $params['targetId'] . '_trigger';
-        }
-        if (empty($params['states'])) {
-            $params['states'] = '""';
-        } else {
-            $params['states'] = Horde_Serialize::serialize($params['states'], Horde_Serialize::JSON, Horde_Nls::getCharset());
-        }
-        if (empty($params['locales'])) {
-            $params['locales'] = array();
-            foreach (array_keys(Horde_Nls::$config['spelling']) as $lcode) {
-                $params['locales'][$lcode] = Horde_Nls::$config['languages'][$lcode];
-            }
-        }
-        asort($params['locales'], SORT_LOCALE_STRING);
-        $params['locales'] = Horde_Serialize::serialize($params['locales'], Horde_Serialize::JSON, Horde_Nls::getCharset());
-
-        parent::__construct($params);
-    }
-
-    /**
-     */
-    public function attach()
-    {
-        parent::attach();
-        Horde::addScriptFile('KeyNavList.js', 'imp', true);
-        Horde::addScriptFile('SpellChecker.js', 'imp', true);
-        $url = Horde::url($GLOBALS['registry']->get('webroot', 'imp') . '/imple.php?imple=SpellChecker/input=' . rawurlencode($this->_params['targetId']), true);
-        IMP::addInlineScript($this->_params['id'] . ' = new SpellChecker("' . $url . '", "' . $this->_params['targetId'] . '", "' . $this->_params['triggerId'] . '", ' . $this->_params['states'] . ', ' . $this->_params['locales'] . ', \'widget\');', 'dom');
-    }
-
-    /**
-     */
-    public function handle($args)
-    {
-        $spellArgs = array();
-
-        if (!empty($GLOBALS['conf']['spell']['params'])) {
-            $spellArgs = $GLOBALS['conf']['spell']['params'];
-        }
-
-        if (isset($args['locale'])) {
-            $spellArgs['locale'] = $args['locale'];
-        } elseif (isset($GLOBALS['language'])) {
-            $spellArgs['locale'] = $GLOBALS['language'];
-        }
-
-        /* Add local dictionary words. */
-        try {
-            $result = Horde::loadConfiguration('spelling.php', 'ignore_list', 'horde');
-            $spellArgs['localDict'] = $result;
-        } catch (Horde_Exception $e) {}
-
-        if (!empty($args['html'])) {
-            $spellArgs['html'] = true;
-        }
-
-        try {
-            $speller = Horde_SpellChecker::getInstance($GLOBALS['conf']['spell']['driver'], $spellArgs);
-        } catch (Horde_Exception $e) {
-            Horde::logMessage($e, __FILE__, __LINE__, PEAR_LOG_ERR);
-            return array();
-        }
-
-        try {
-            return $speller->spellCheck(Horde_Util::getPost($args['input']));
-        } catch (Horde_Exception $e) {
-            Horde::logMessage($e, __FILE__, __LINE__, PEAR_LOG_ERR);
-            return array('bad' => array(), 'suggestions' => array());
-        }
-    }
-
-}
index 793525c..6f2cd6c 100644 (file)
@@ -99,7 +99,8 @@ class IMP_UI_Compose
     {
         /* Attach autocompleters to the compose form elements. */
         foreach ($fields as $val) {
-            call_user_func_array(array('IMP_Imple', 'factory'), array('ContactAutoCompleter', array('triggerId' => $val)));
+            $imple = Horde_Ajax_Imple::getInstance(array('imp', 'ContactAutoCompleter'), array('triggerId' => $val));
+            $imple->attach();
         }
     }
 
@@ -122,7 +123,9 @@ class IMP_UI_Compose
                 'Error' => $spell_img . $br . _("Spell Check Failed")
             )
         );
-        call_user_func_array(array('IMP_Imple', 'factory'), array('SpellChecker', $args));
+
+        $imple = Horde_Ajax_Imple::getInstance(array('imp', 'SpellChecker'), $args);
+        $imple->attach();
     }
 
     /**
index 12c9054..e4c0c6a 100644 (file)
@@ -248,7 +248,7 @@ $date = new Horde_Date($date);
 $vfb_html = $attendee_view->render($date);
 
 // Add the ContactAutoCompleter
-Kronolith_Imple::factory('ContactAutoCompleter', array('triggerId' => 'newAttendees'));
+Horde_Ajax_Imple::getInstance(array('kronolith', 'ContactAutoCompleter'), array('triggerId' => 'newAttendees'));
 
 $title = _("Edit attendees");
 require KRONOLITH_TEMPLATES . '/common-header.inc';
index a88023a..f87c51b 100644 (file)
@@ -58,4 +58,4 @@ require KRONOLITH_TEMPLATES . '/common-header.inc';
 require KRONOLITH_TEMPLATES . '/menu.inc';
 echo $form->renderActive($form->getRenderer(), $vars, 'edit.php', 'post');
 require $registry->get('templates', 'horde') . '/common-footer.inc';
-Kronolith_Imple::factory('TagAutoCompleter', array('triggerId' => 'tags', 'id'));
+Horde_Ajax_Imple::getInstance(array('kronolith', 'TagAutoCompleter'), array('triggerId' => 'tags', 'id'));
diff --git a/kronolith/imple.php b/kronolith/imple.php
deleted file mode 100644 (file)
index 10a0593..0000000
+++ /dev/null
@@ -1,63 +0,0 @@
-<?php
-/**
- * Copyright 2005-2009 The Horde Project (http://www.horde.org/)
- *
- * See the enclosed file COPYING for license information (GPL). If you
- * did not receive this file, see http://www.fsf.org/copyleft/gpl.html.
- *
- * @author Michael Slusarz <slusarz@horde.org>
- */
-
-require_once dirname(__FILE__) . '/lib/base.php';
-
-$path = Horde_Util::getFormData('imple');
-if (!$path) {
-    exit;
-}
-if ($path[0] == '/') {
-    $path = substr($path, 1);
-}
-$path = explode('/', $path);
-$impleName = array_shift($path);
-
-$imple = Kronolith_Imple::factory($impleName);
-if (!$imple) {
-    exit;
-}
-$args = array();
-foreach ($path as $pair) {
-    if (strpos($pair, '=') === false) {
-        $args[$pair] = true;
-    } else {
-        list($name, $val) = explode('=', $pair);
-        $args[$name] = $val;
-    }
-}
-
-$result = $imple->handle($args);
-
-if (!empty($_SERVER['Content-Type'])) {
-    $ct = $_SERVER['Content-Type'];
-} else {
-    $ct = is_string($result) ? 'plain' : 'json';
-}
-
-switch ($ct) {
-case 'json':
-    header('Content-Type: application/json');
-    echo Horde_Serialize::serialize($result, Horde_Serialize::JSON, Horde_Nls::getCharset());
-    break;
-
-case 'plain':
-    header('Content-Type: text/plain');
-    echo $result;
-    break;
-
-case 'html':
-    header('Content-Type: text/html');
-    echo $result;
-    break;
-
-default:
-    echo $result;
-}
index 284582f..89976e1 100644 (file)
@@ -65,5 +65,5 @@ require KRONOLITH_TEMPLATES . '/index/index.inc';
 Kronolith::includeScriptFiles();
 Kronolith::outputInlineScript();
 $notification->notify(array('listeners' => array('javascript')));
-Kronolith_Imple::factory('TagAutoCompleter', array('triggerId' => 'kronolithEventTags', 'pretty' => true));
+Horde_Ajax_Imple::getInstance(array('kronolith', 'TagAutoCompleter'), array('triggerId' => 'kronolithEventTags', 'pretty' => true));
 echo "</body>\n</html>";
index ed66515..237597c 100644 (file)
@@ -2,7 +2,7 @@ function addTag(resource, type, endpoint)
 {
     if (!$('newtags-input_' + resource).value.blank()) {
         var params = new Object();
-        params.imple="TagActions/action=add/resource=" + resource + "/type=" + type + "/tags=" + $('newtags-input_' + resource).value;
+        params.imple="/action=add/resource=" + resource + "/type=" + type + "/tags=" + $('newtags-input_' + resource).value;
         new Ajax.Updater({success:'tags_' + resource},
                          endpoint,
                          {
@@ -19,7 +19,7 @@ function addTag(resource, type, endpoint)
 function removeTag(resource, type, tagid, endpoint)
 {
     var params = new Object();
-    params.imple = "TagActions/action=remove/resource=" + resource + "/type=" + type + "/tags=" + tagid;
+    params.imple = "/action=remove/resource=" + resource + "/type=" + type + "/tags=" + tagid;
     new Ajax.Updater({success:'tags_' + resource},
                      endpoint,
                      {
@@ -29,4 +29,4 @@ function removeTag(resource, type, tagid, endpoint)
     );
     
     return true;
-}
\ No newline at end of file
+}
diff --git a/kronolith/lib/Ajax/Imple/ContactAutoCompleter.php b/kronolith/lib/Ajax/Imple/ContactAutoCompleter.php
new file mode 100644 (file)
index 0000000..2f58934
--- /dev/null
@@ -0,0 +1,156 @@
+<?php
+/**
+ * Attach the contact auto completer to a javascript element.
+ *
+ * Copyright 2005-2009 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file COPYING for license information (GPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/gpl.html.
+ *
+ * @author  Michael Slusarz <slusarz@horde.org>
+ * @package Kronolith
+ */
+class Kronolith_Ajax_Imple_ContactAutoCompleter extends Horde_Ajax_Imple_Base
+{
+    /**
+     * Constructor.
+     *
+     * @param array $params  Configuration parameters.
+     * <pre>
+     * 'triggerId' => TODO (optional)
+     * 'resultsId' => TODO (optional)
+     * </pre>
+     */
+    public function __construct($params)
+    {
+        if (empty($params['triggerId'])) {
+            $params['triggerId'] = $this->_randomid();
+        }
+        if (empty($params['resultsId'])) {
+            $params['resultsId'] = $params['triggerId'] . '_results';
+        }
+
+        parent::__construct($params);
+    }
+
+    /**
+     * Attach the Imple object to a javascript event.
+     */
+    public function attach()
+    {
+        Horde::addScriptFile('prototype.js', 'horde', true);
+        Horde::addScriptFile('effects.js', 'horde', true);
+        Horde::addScriptFile('autocomplete.js', 'horde', true);
+
+        $params = array(
+            '"' . $this->_params['triggerId'] . '"',
+            '"' . $this->_params['resultsId'] . '"',
+            '"' . $this->_getUrl('ContactAutoCompleter', 'kronolith', array('input' => $this->_params['triggerId'])) . '"'
+        );
+
+        $js_params = array(
+            'tokens: [",", ";"]',
+            'indicator: "' . $this->_params['triggerId'] . '_loading_img"',
+            'afterUpdateElement: function(f, t) { if (!f.value.endsWith(";")) { f.value += ","; } f.value += " "; }'
+        );
+
+        $params[] = '{' . implode(',', $js_params) . '}';
+
+        Kronolith::addInlineScript('new Ajax.Autocompleter(' . implode(',', $params) . ')', 'dom');
+    }
+
+    /**
+     * TODO
+     *
+     * @param array $args  TODO
+     *
+     * @return string  TODO
+     */
+    public function handle($args)
+    {
+        // Avoid errors if 'input' isn't set and short-circuit empty searches.
+        if (empty($args['input']) ||
+            !($input = Horde_Util::getFormData($args['input']))) {
+            return array();
+        }
+
+        return array_map('htmlspecialchars', $this->_expandAddresses($input));
+    }
+
+    /**
+     * Uses the Registry to expand names and return error information for
+     * any address that is either not valid or fails to expand. This function
+     * will not search if the address string is empty.
+     *
+     * @param string $addrString  The name(s) or address(es) to expand.
+     *
+     * @return array  All matching addresses.
+     */
+    protected function _expandAddresses($addrString)
+    {
+        return preg_match('|[^\s]|', $addrString)
+            ? $this->getAddressList(reset(array_filter(array_map('trim', Horde_Mime_Address::explode($addrString, ',;')))))
+            : '';
+    }
+
+    /**
+     * Uses the Registry to expand names and return error information for
+     * any address that is either not valid or fails to expand.
+     *
+     * @param string $search  The term to search by.
+     *
+     * @return array  All matching addresses.
+     */
+    static public function getAddressList($search = '')
+    {
+        $src = explode("\t", $GLOBALS['prefs']->getValue('search_sources'));
+        if ((count($src) == 1) && empty($src[0])) {
+            $src = array();
+        }
+
+        $fields = array();
+        if (($val = $GLOBALS['prefs']->getValue('search_fields'))) {
+            $field_arr = explode("\n", $val);
+            foreach ($field_arr as $field) {
+                $field = trim($field);
+                if (!empty($field)) {
+                    $tmp = explode("\t", $field);
+                    if (count($tmp) > 1) {
+                        $source = array_splice($tmp, 0, 1);
+                        $fields[$source[0]] = $tmp;
+                    }
+                }
+            }
+        }
+
+        try {
+            $res = $GLOBALS['registry']->call('contacts/search', array($search, $src, $fields, true));
+        } catch (Horde_Exception $e) {
+            Horde::logMessage($e, __FILE__, __LINE__, PEAR_LOG_ERR);
+            return array();
+        }
+
+        if (!count($res)) {
+            return array();
+        }
+
+        /* The first key of the result will be the search term. The matching
+         * entries are stored underneath this key. */
+        $search = array();
+        foreach (reset($res) as $val) {
+            if (!empty($val['email'])) {
+                if (strpos($val['email'], ',') !== false) {
+                    $search[] = Horde_Mime_Address::encode($val['name'], 'personal') . ': ' . $val['email'] . ';';
+                } else {
+                    $mbox_host = explode('@', $val['email']);
+                    if (isset($mbox_host[1])) {
+                        $search[] = Horde_Mime_Address::writeAddress($mbox_host[0], $mbox_host[1], $val['name']);
+                    }
+                }
+            }
+        }
+
+        return $search;
+    }
+
+}
diff --git a/kronolith/lib/Ajax/Imple/Embed.php b/kronolith/lib/Ajax/Imple/Embed.php
new file mode 100644 (file)
index 0000000..b830167
--- /dev/null
@@ -0,0 +1,122 @@
+<?php
+/**
+ * Kronolith_Ajax_Imple_Embed:: will allow embedding calendar widgets in
+ * external websites. Meant to be called via a single script tag, therefore
+ * this will always return nothing but valid javascript.
+ *
+ * Copyright 2008-2009 The Horde Project (http://www.horde.org/)
+ *
+ * @author  Michael J. Rubinsky <mrubinsk@horde.org>
+ * @package Kronolith
+ */
+class Kronolith_Ajax_Imple_Embed extends Horde_Ajax_Imple_Base
+{
+    /**
+     */
+    public function attach()
+    {
+    }
+
+    /**
+     * Handles the output of the embedded widget. This must always be valid
+     * javascript.
+     * <pre>
+     * The following arguments are required:
+     *   view      => the view (block) we want
+     *   container => the DOM node to populate with the widget
+     *   calendar  => the share_name for the requested calendar
+     *
+     * The following are optional (and are not used for all views)
+     *   months     => the number of months to include
+     *   maxevents     => the maximum number of events to show
+     *
+     * @param array $args  Arguments for this view.
+     */
+    public function handle($args)
+    {
+        /* First, determine the type of view we are asking for */
+        $view = $args['view'];
+
+        /* The DOM container to put the HTML in on the remote site */
+        $container = $args['container'];
+
+        /* The share_name of the calendar to display */
+        $calendar = $args['calendar'];
+
+        /* Deault to showing only 1 month when we have a choice */
+        $count_month = (!empty($args['months']) ? $args['months'] : 1);
+
+        /* Default to no limit for the number of events */
+        $max_events = (!empty($args['maxevents']) ? $args['maxevents'] : 0);
+
+        /* Default to one week */
+        $count_days = (!empty($args['days']) ? $args['days'] : 7);
+
+        if (!empty($args['css']) && $args['css'] == 'none') {
+            $nocss = true;
+        }
+
+        /* Load the registry with no session control */
+        $registry = Horde_Registry::singleton(Horde_Registry::SESSION_NONE);
+
+
+        /* Build the block parameters */
+        $params = array(
+            'calendar' => $calendar,
+            'maxevents' => $max_events,
+            'months' => $count_month,
+            'days' => $count_days
+        );
+
+        /* Call the Horde_Block api to get the calendar HTML */
+        $title = $registry->call('horde/blockTitle', array('kronolith', $view, $params));
+        $results = $registry->call('horde/blockContent', array('kronolith', $view, $params));
+
+        /* Some needed paths */
+        $js_path = $registry->get('jsuri', 'kronolith');
+
+        /* Local js */
+        $jsurl = Horde::url($js_path . '/embed.js', true);
+
+        /* Horde's js */
+        $hjs_path = $registry->get('jsuri', 'horde');
+        $hjsurl = Horde::url($hjs_path . '/horde-embed.js', true);
+        $pturl = Horde::url($hjs_path . '/prototype.js', true);
+
+        /* CSS */
+        if (empty($nocss)) {
+            $cssurl = Horde::url($registry->get('themesuri', 'kronolith') . '/embed.css', true);
+            $hcssurl = Horde::url($registry->get('themesuri', 'horde') . '/embed.css', true);
+        } else {
+            $cssurl= '';
+        }
+
+        /* Escape the text and put together the javascript to send back */
+        $results = addslashes('<div class="kronolith_embedded"><div class="title">' . $title . '</div>' . $results . '</div>');
+        $html = <<<EOT
+        //<![CDATA[
+        if (typeof kronolith == 'undefined') {
+            if (typeof Horde_ToolTips == 'undefined') {
+                document.write('<script type="text/javascript" src="$hjsurl"></script>');
+                document.write('<link type="text/css" rel="stylesheet" href="$hcssurl" />');
+            }
+            if (typeof Prototype == 'undefined') {
+                document.write('<script type="text/javascript" src="$pturl"></script>');
+            }
+            kronolith = new Object();
+            kronolithNodes = new Array();
+            document.write('<script type="text/javascript" src="$jsurl"></script>');
+            document.write('<link type="text/css" rel="stylesheet" href="$cssurl" />');
+        }
+        kronolithNodes[kronolithNodes.length] = '$container';
+        kronolith['$container'] = "$results";
+        //]]>
+EOT;
+
+        /* Send it */
+        header('Content-Type: text/javascript');
+        echo $html;
+        exit;
+    }
+
+}
diff --git a/kronolith/lib/Ajax/Imple/TagActions.php b/kronolith/lib/Ajax/Imple/TagActions.php
new file mode 100644 (file)
index 0000000..b4bb3e8
--- /dev/null
@@ -0,0 +1,106 @@
+<?php
+/**
+ * Kronolith_Ajax_Imple_TagActions:: handles ajax requests for adding and
+ * removing tags from kronolith objects.
+ *
+ * Copyright 2009 The Horde Project (http://www.horde.org)
+ *
+ * @author  Michael J. Rubinsky <mrubinsk@horde.org>
+ * @package Kronolith
+ */
+class Kronolith_Ajax_Imple_TagActions extends Horde_Ajax_Imple_Base
+{
+    /**
+     */
+    public function attach()
+    {
+        Horde::addScriptFile('tagactions.js');
+        $dom_id = $this->_params['triggerId'];
+        $action = $this->_params['action'];
+        $content_id = $this->_params['resource'];
+        $content_type = $this->_params['type'];
+        $tag_id = !empty($this->_params['tagId']) ? $this->_params['tagId'] : null;
+        $endpoint = $this->_getUrl('TagActions', 'kronolith');
+
+        if ($action == 'add') {
+            $js = "Event.observe('" . $dom_id . "_" . $content_id . "', 'click', function(event) {addTag('" . $content_id . "', '" . $content_type . "', '" . $endpoint . "'); Event.stop(event)});";
+        } elseif ($action == 'delete') {
+            $js = "Event.observe('" . $dom_id . "', 'click', function(event) {removeTag('" . $content_id . "', '" . $content_type . "', " . $tag_id . ", '" . $endpoint . "'); Event.stop(event)});";
+        }
+        Kronolith::addInlineScript($js, 'window');
+    }
+
+    /**
+     * Handle the tag related action.
+     *
+     * If removing a tag, needs a 'resource' which is the local identifier of
+     * the kronolith object, a 'type' which should be the string reprentation of
+     * the type of object (event/calendar) and 'tags' should be the integer
+     * tag_id of the tag to remove.
+     */
+    public function handle($args)
+    {
+        global $ansel_storage;
+
+        $request = $args['action'];
+        $content = array('id' => $args['resource'], 'type' => $args['type']);
+        $tags = $args['tags'];
+
+        // Check perms
+        if ($args['type'] == 'calendar') {
+            $cal = $GLOBALS['kronolith_shares']->getShare($args['resource']);
+            $perm = $cal->hasPermission(Horde_Auth::getAuth(), PERMS_EDIT);
+        } elseif($args['type'] == 'event') {
+            $event = Kronolith::getDriver()->getByUID($args['resource']);
+            $perm = $event->hasPermission(PERMS_EDIT, Horde_Auth::getAuth());
+        }
+
+        if ($perm) {
+            /* Get the resource owner */
+            $tagger = Kronolith::getTagger();
+            switch ($request) {
+            case 'add':
+                $tagger->tag($args['resource'], $tags, $args['type']);
+                break;
+            case 'remove':
+                $tagger->untag($args['resource'], (int)$tags, $args['type']);
+                break;
+            }
+        }
+        return $this->_getTagHtml($tagger, $args['resource'], $args['type']);
+
+    }
+
+    /**
+     * Generate the HTML for the tag lists to send back to the browser.
+     *
+     * TODO: This should be made a view helper when we move to using Horde_View
+     *
+     * @param Kronolith_Tagger $tagger  The tagger object
+     * @param string $id                The identifier (share name or event uid)
+     * @param string $type              The type of resource (calendar/event)
+     *
+     * @return string  The HTML
+     */
+    private function _getTagHtml($tagger, $id, $type)
+    {
+        $tags = $tagger->getTags($id, 'calendar');
+        $js = '';
+        $html = '';
+
+        if ($type == 'calendar') {
+            $cal = $GLOBALS['kronolith_shares']->getShare($id);
+            $hasEdit = $cal->hasPermission(Horde_Auth::getAuth(), PERMS_EDIT);
+        } elseif ($type == 'event') {
+            $event = Kronolith::getDriver()->getByUID($id);
+            $hasEdit = $event->hasPermission(PERMS_EDIT, Horde_Auth::getAuth());
+        }
+
+        foreach ($tags as $tag_id => $tag) {
+            $html .= '<li class="panel-tags">' .  $tag . ($hasEdit ? '<a href="#" onclick="removeTag(\'' . $id . '\', \'' . $type . '\',' . $tag_id . ', \'' . Horde::url('imple.php', true) . '\'); Event.stop(event)" id="remove' . md5($id . $tag_id) . '">' . Horde::img('delete-small.png', _("Remove Tag"), '', $GLOBALS['registry']->getImageDir('horde')) . '</a>' : '') . '</li>';
+        }
+
+        return $html;
+    }
+
+}
diff --git a/kronolith/lib/Ajax/Imple/TagAutoCompleter.php b/kronolith/lib/Ajax/Imple/TagAutoCompleter.php
new file mode 100644 (file)
index 0000000..d17fd9b
--- /dev/null
@@ -0,0 +1,126 @@
+<?php
+/**
+ * Copyright 2009 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file COPYING for license information (GPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/gpl.html.
+ *
+ * @author  Michael Slusarz <slusarz@horde.org>
+ * @package Kronolith
+ */
+class Kronolith_Ajax_Imple_TagAutoCompleter extends Horde_Ajax_Imple_Base
+{
+    /**
+     * Constructor.
+     *
+     * @param array $params  Configuration parameters.
+     * <pre>
+     * 'triggerId' => TODO (optional)
+     * 'resultsId' => TODO (optional)
+     * </pre>
+     */
+    public function __construct($params)
+    {
+        if (!count($params)) {
+            return;
+        }
+        if (empty($params['resultsId'])) {
+            $params['resultsId'] = $params['triggerId'] . '_results';
+        }
+
+        parent::__construct($params);
+    }
+
+    /**
+     * Attach the Imple object to a javascript event.
+     * If the 'pretty' parameter is empty then we want a
+     * traditional autocompleter, otherwise we get a spiffy pretty one.
+     *
+     */
+    public function attach()
+    {
+        Horde::addScriptFile('prototype.js', 'horde', true);
+        Horde::addScriptFile('effects.js', 'horde', true);
+        Horde::addScriptFile('autocomplete.js', 'horde', true);
+
+        $registry = Horde_Registry::singleton();
+
+        if ($pretty = !empty($this->_params['pretty'])) {
+            Horde::addScriptFile('prettyautocomplete.js', 'horde', true);
+            $this->_params['uri'] = $this->_getUrl('TagAutoCompleter', 'kronolith');
+        } else {
+            $this->_params['uri'] = $this->_getUrl('TagAutoCompleter', 'kronolith', array('input' => $this->_params['triggerId']));
+        }
+
+        if (!$pretty) {
+            $params = array(
+                '"' . $this->_params['triggerId'] . '"',
+                '"' . $this->_params['resultsId'] . '"',
+                '"' . $this->_params['uri'] . '"'
+            );
+        }
+
+        $js_params = array(
+            'tokens: [","]',
+            'indicator: "' . $this->_params['triggerId'] . '_loading_img"'
+        );
+
+        // The pretty version needs to set this callback itself...
+        if (!$pretty && !empty($this->_params['updateElement'])) {
+            $js_params[] = 'updateElement: ' . $this->_params['updateElement'];
+        }
+
+        $params[] = '{' . implode(',', $js_params) . '}';
+
+        if ($pretty) {
+            $js_vars = array('boxClass' => 'hordeACBox kronolithLongField',
+                             'uri' => $this->_params['uri'],
+                             'trigger' => $this->_params['triggerId'],
+                             'URI_IMG_HORDE' => $registry->getImageDir('horde'),
+                             'params' => $params);
+
+            if (!empty($this->_params['existing'])) {
+                $js_vars['existing'] = $this->_params['existing'];
+            }
+
+            $script = array('new PrettyAutocompleter(' . Horde_Serialize::serialize($js_vars, Horde_Serialize::JSON, Horde_Nls::getCharset()) . ')');
+        } else {
+            $script = array('new Ajax.Autocompleter(' . implode(',', $params) . ')');
+        }
+
+        Kronolith::addInlineScript($script, 'dom');
+    }
+
+    /**
+     * TODO
+     *
+     * @param array $args  TODO
+     *
+     * @return string  TODO
+     */
+    public function handle($args)
+    {
+        // Avoid errors if 'input' isn't set and short-circuit empty searches.
+        if (empty($args['input']) ||
+            !($input = Horde_Util::getFormData($args['input']))) {
+            return array();
+        }
+        return array_map('htmlspecialchars', $this->getTagList($input));
+    }
+
+    /**
+     * Get a list of existing, used tags that match the search term.
+     *
+     * @param string $search  The term to search by.
+     *
+     * @return array  All matching tags.
+     */
+    public function getTagList($search = '')
+    {
+        $tagger = Kronolith::getTagger();
+        $tags = $tagger->listTags($search);
+
+        return array_values($tags);
+    }
+
+}
diff --git a/kronolith/lib/Imple.php b/kronolith/lib/Imple.php
deleted file mode 100644 (file)
index 50062f8..0000000
+++ /dev/null
@@ -1,100 +0,0 @@
-<?php
-/**
- * Copyright 2005-2009 The Horde Project (http://www.horde.org/)
- *
- * See the enclosed file COPYING for license information (GPL). If you
- * did not receive this file, see http://www.fsf.org/copyleft/gpl.html.
- *
- * @author  Michael Slusarz <slusarz@horde.org>
- * @package Kronolith
- */
-class Kronolith_Imple
-{
-
-    /**
-     * Parameters needed by the subclasses.
-     *
-     * @var array
-     */
-    protected $_params = array();
-
-    /**
-     * Attempts to return a concrete Imple instance based on $imple.
-     *
-     * @param string $imple  The type of concrete Imple subclass to return
-     *                       return, based on the imple type indicated. The
-     *                       code is dynamically included.
-     * @param array $params  The configuration parameter array.
-     *
-     * @return mixed  The newly created concrete Imple instance, or false on
-     *                error.
-     */
-    public static function factory($imple, $params = array())
-    {
-        $imple = basename($imple);
-        if (!$imple) {
-            return false;
-        }
-
-        $class = 'Kronolith_Imple_' . $imple;
-        if (!class_exists($class)) {
-            include_once dirname(__FILE__) . '/Imple/' . $imple . '.php';
-            if (!class_exists($class)) {
-                return false;
-            }
-        }
-
-        return new $class($params);
-    }
-
-    /**
-     * Constructor.
-     *
-     * @param array $params  Any parameters needed by the class.
-     */
-    public function __construct($params)
-    {
-        $this->_params = $params;
-        $this->attach();
-    }
-
-    /**
-     * Attach the Imple object to a javascript event.
-     */
-    public function attach()
-    {
-        Horde::addScriptFile('prototype.js', 'horde', true);
-        Horde::addScriptFile('effects.js', 'horde', true);
-    }
-
-    /**
-     * TODO
-     *
-     * @param TODO
-     */
-    public function handle($args)
-    {
-    }
-
-    /**
-     * Return the rendered HTML code.
-     *
-     * @return string  The HTML code.
-     */
-    public function html()
-    {
-    }
-
-    /**
-     * Generate a random ID string.
-     *
-     * @access private
-     *
-     * @return string  The random ID string.
-     */
-    public function _randomid()
-    {
-        return 'imple_' . uniqid(mt_rand());
-    }
-
-}
diff --git a/kronolith/lib/Imple/ContactAutoCompleter.php b/kronolith/lib/Imple/ContactAutoCompleter.php
deleted file mode 100644 (file)
index 598a0b6..0000000
+++ /dev/null
@@ -1,153 +0,0 @@
-<?php
-/**
- * Copyright 2005-2009 The Horde Project (http://www.horde.org/)
- *
- * See the enclosed file COPYING for license information (GPL). If you
- * did not receive this file, see http://www.fsf.org/copyleft/gpl.html.
- *
- * @author  Michael Slusarz <slusarz@horde.org>
- * @package Kronolith
- */
-class Kronolith_Imple_ContactAutoCompleter extends Kronolith_Imple
-{
-    /**
-     * Constructor.
-     *
-     * @param array $params  Configuration parameters.
-     * <pre>
-     * 'triggerId' => TODO (optional)
-     * 'resultsId' => TODO (optional)
-     * </pre>
-     */
-    public function __construct($params)
-    {
-        if (empty($params['triggerId'])) {
-            $params['triggerId'] = $this->_randomid();
-        }
-        if (empty($params['resultsId'])) {
-            $params['resultsId'] = $params['triggerId'] . '_results';
-        }
-
-        parent::__construct($params);
-    }
-
-    /**
-     * Attach the Imple object to a javascript event.
-     */
-    public function attach()
-    {
-        parent::attach();
-        Horde::addScriptFile('autocomplete.js', 'horde', true);
-
-        $params = array(
-            '"' . $this->_params['triggerId'] . '"',
-            '"' . $this->_params['resultsId'] . '"',
-            '"' . Horde::url($GLOBALS['registry']->get('webroot', 'kronolith') . '/imple.php?imple=ContactAutoCompleter/input=' . rawurlencode($this->_params['triggerId']), true) . '"'
-        );
-
-        $js_params = array(
-            'tokens: [",", ";"]',
-            'indicator: "' . $this->_params['triggerId'] . '_loading_img"',
-            'afterUpdateElement: function(f, t) { if (!f.value.endsWith(";")) { f.value += ","; } f.value += " "; }'
-        );
-
-        $params[] = '{' . implode(',', $js_params) . '}';
-
-        Kronolith::addInlineScript('new Ajax.Autocompleter(' . implode(',', $params) . ')', 'dom');
-    }
-
-    /**
-     * TODO
-     *
-     * @param array $args  TODO
-     *
-     * @return string  TODO
-     */
-    public function handle($args)
-    {
-        // Avoid errors if 'input' isn't set and short-circuit empty searches.
-        if (empty($args['input']) ||
-            !($input = Horde_Util::getFormData($args['input']))) {
-            return array();
-        }
-
-        return array_map('htmlspecialchars', $this->_expandAddresses($input));
-    }
-
-    /**
-     * Uses the Registry to expand names and return error information for
-     * any address that is either not valid or fails to expand. This function
-     * will not search if the address string is empty.
-     *
-     * @param string $addrString  The name(s) or address(es) to expand.
-     *
-     * @return array  All matching addresses.
-     */
-    protected function _expandAddresses($addrString)
-    {
-        return preg_match('|[^\s]|', $addrString)
-            ? $this->getAddressList(reset(array_filter(array_map('trim', Horde_Mime_Address::explode($addrString, ',;')))))
-            : '';
-    }
-
-    /**
-     * Uses the Registry to expand names and return error information for
-     * any address that is either not valid or fails to expand.
-     *
-     * @param string $search  The term to search by.
-     *
-     * @return array  All matching addresses.
-     */
-    static public function getAddressList($search = '')
-    {
-        $src = explode("\t", $GLOBALS['prefs']->getValue('search_sources'));
-        if ((count($src) == 1) && empty($src[0])) {
-            $src = array();
-        }
-
-        $fields = array();
-        if (($val = $GLOBALS['prefs']->getValue('search_fields'))) {
-            $field_arr = explode("\n", $val);
-            foreach ($field_arr as $field) {
-                $field = trim($field);
-                if (!empty($field)) {
-                    $tmp = explode("\t", $field);
-                    if (count($tmp) > 1) {
-                        $source = array_splice($tmp, 0, 1);
-                        $fields[$source[0]] = $tmp;
-                    }
-                }
-            }
-        }
-
-        try {
-            $res = $GLOBALS['registry']->call('contacts/search', array($search, $src, $fields, true));
-        } catch (Horde_Exception $e) {
-            Horde::logMessage($e, __FILE__, __LINE__, PEAR_LOG_ERR);
-            return array();
-        }
-
-        if (!count($res)) {
-            return array();
-        }
-
-        /* The first key of the result will be the search term. The matching
-         * entries are stored underneath this key. */
-        $search = array();
-        foreach (reset($res) as $val) {
-            if (!empty($val['email'])) {
-                if (strpos($val['email'], ',') !== false) {
-                    $search[] = Horde_Mime_Address::encode($val['name'], 'personal') . ': ' . $val['email'] . ';';
-                } else {
-                    $mbox_host = explode('@', $val['email']);
-                    if (isset($mbox_host[1])) {
-                        $search[] = Horde_Mime_Address::writeAddress($mbox_host[0], $mbox_host[1], $val['name']);
-                    }
-                }
-            }
-        }
-
-        return $search;
-    }
-
-}
diff --git a/kronolith/lib/Imple/Embed.php b/kronolith/lib/Imple/Embed.php
deleted file mode 100644 (file)
index d284a6b..0000000
+++ /dev/null
@@ -1,125 +0,0 @@
-<?php
-/**
- * Kronolith_Imple_Embed:: Class for embedding calendar widgets in external
- * websites. Meant to be called via a single script tag, therefore this will
- * always return nothing but valid javascript.
- *
- * Copyright 2008-2009 The Horde Project (http://www.horde.org/)
- *
- * @author Michael J. Rubinsky <mrubinsk@horde.org>
- *
- * @package Kronolith
- */
-class Kronolith_Imple_Embed extends Kronolith_Imple {
-
-    /**
-     * Override the parent method since it uses Horde::addScriptFile()
-     *
-     */
-    function attach()
-    {
-        //noop
-    }
-
-
-    /**
-     * Handles the output of the embedded widget. This must always be valid
-     * javascript.
-     * <pre>
-     * The following arguments are required:
-     *   view      => the view (block) we want
-     *   container => the DOM node to populate with the widget
-     *   calendar  => the share_name for the requested calendar
-     *
-     * The following are optional (and are not used for all views)
-     *   months     => the number of months to include
-     *   maxevents     => the maximum number of events to show
-     *
-     * @param array $args  Arguments for this view.
-     */
-    function handle($args)
-    {
-        /* First, determine the type of view we are asking for */
-        $view = $args['view'];
-
-        /* The DOM container to put the HTML in on the remote site */
-        $container = $args['container'];
-
-        /* The share_name of the calendar to display */
-        $calendar = $args['calendar'];
-
-        /* Deault to showing only 1 month when we have a choice */
-        $count_month = (!empty($args['months']) ? $args['months'] : 1);
-
-        /* Default to no limit for the number of events */
-        $max_events = (!empty($args['maxevents']) ? $args['maxevents'] : 0);
-
-        /* Default to one week */
-        $count_days = (!empty($args['days']) ? $args['days'] : 7);
-
-        if (!empty($args['css']) && $args['css'] == 'none') {
-            $nocss = true;
-        }
-
-        /* Load the registry with no session control */
-        $registry = Horde_Registry::singleton(Horde_Registry::SESSION_NONE);
-
-
-        /* Build the block parameters */
-        $params = array('calendar' => $calendar,
-                        'maxevents' => $max_events,
-                        'months' => $count_month,
-                        'days' => $count_days);
-
-        /* Call the Horde_Block api to get the calendar HTML */
-        $title = $registry->call('horde/blockTitle', array('kronolith', $view, $params));
-        $results = $registry->call('horde/blockContent', array('kronolith', $view, $params));
-
-        /* Some needed paths */
-        $js_path = $registry->get('jsuri', 'kronolith');
-
-        /* Local js */
-        $jsurl = Horde::url($js_path . '/embed.js', true);
-
-        /* Horde's js */
-        $hjs_path = $registry->get('jsuri', 'horde');
-        $hjsurl = Horde::url($hjs_path . '/horde-embed.js', true);
-        $pturl = Horde::url($hjs_path . '/prototype.js', true);
-
-        /* CSS */
-        if (empty($nocss)) {
-            $cssurl = Horde::url($registry->get('themesuri', 'kronolith') . '/embed.css', true);
-            $hcssurl = Horde::url($registry->get('themesuri', 'horde') . '/embed.css', true);
-        } else {
-            $cssurl= '';
-        }
-
-        /* Escape the text and put together the javascript to send back */
-        $results = addslashes('<div class="kronolith_embedded"><div class="title">' . $title . '</div>' . $results . '</div>');
-        $html = <<<EOT
-        //<![CDATA[
-        if (typeof kronolith == 'undefined') {
-            if (typeof Horde_ToolTips == 'undefined') {
-                document.write('<script type="text/javascript" src="$hjsurl"></script>');
-                document.write('<link type="text/css" rel="stylesheet" href="$hcssurl" />');
-            }
-            if (typeof Prototype == 'undefined') {
-                document.write('<script type="text/javascript" src="$pturl"></script>');
-            }
-            kronolith = new Object();
-            kronolithNodes = new Array();
-            document.write('<script type="text/javascript" src="$jsurl"></script>');
-            document.write('<link type="text/css" rel="stylesheet" href="$cssurl" />');
-        }
-        kronolithNodes[kronolithNodes.length] = '$container';
-        kronolith['$container'] = "$results";
-        //]]>
-EOT;
-
-        /* Send it */
-        header('Content-Type: text/javascript');
-        echo $html;
-        exit;
-    }
-
-}
diff --git a/kronolith/lib/Imple/TagActions.php b/kronolith/lib/Imple/TagActions.php
deleted file mode 100644 (file)
index baa82fa..0000000
+++ /dev/null
@@ -1,110 +0,0 @@
-<?php
-/**
- * Kronolith_Imple_TagActions:: Class to handle ajax requests for adding and
- * removing tags from kronolith objects.
- *
- * Copyright 2009 The Horde Project (http://www.horde.org)
- *
- * @author Michael J. Rubinsky <mrubinsk@horde.org>
- *
- * @package Kronolith
- */
-class Kronolith_Imple_TagActions extends Kronolith_Imple
-{
-    public function attach()
-    {
-        // TODO: HACK! attach is called in the contructor which means that even
-        // if we are only handling the request, we try to attach().
-        if (count($this->_params) == 0) {
-            return;
-        }
-        Horde::addScriptFile('tagactions.js');
-        $dom_id = $this->_params['triggerId'];
-        $action = $this->_params['action'];
-        $content_id = $this->_params['resource'];
-        $content_type = $this->_params['type'];
-        $tag_id = !empty($this->_params['tagId']) ? $this->_params['tagId'] : null;
-        $endpoint = Horde::url('imple.php', true);
-
-        if ($action == 'add') {
-            $js = "Event.observe('" . $dom_id . "_" . $content_id . "', 'click', function(event) {addTag('" . $content_id . "', '" . $content_type . "', '" . $endpoint . "'); Event.stop(event)});";
-        } elseif ($action == 'delete') {
-            $js = "Event.observe('" . $dom_id . "', 'click', function(event) {removeTag('" . $content_id . "', '" . $content_type . "', " . $tag_id . ", '" . $endpoint . "'); Event.stop(event)});";
-        }
-        Kronolith::addInlineScript($js, 'window');
-    }
-
-    /**
-     * Handle the tag related action.
-     *
-     * If removing a tag, needs a 'resource' which is the local identifier of
-     * the kronolith object, a 'type' which should be the string reprentation of
-     * the type of object (event/calendar) and 'tags' should be the integer
-     * tag_id of the tag to remove.
-     */
-    public function handle($args)
-    {
-        global $ansel_storage;
-
-        $request = $args['action'];
-        $content = array('id' => $args['resource'], 'type' => $args['type']);
-        $tags = $args['tags'];
-
-        // Check perms
-        if ($args['type'] == 'calendar') {
-            $cal = $GLOBALS['kronolith_shares']->getShare($args['resource']);
-            $perm = $cal->hasPermission(Horde_Auth::getAuth(), PERMS_EDIT);
-        } elseif($args['type'] == 'event') {
-            $event = Kronolith::getDriver()->getByUID($args['resource']);
-            $perm = $event->hasPermission(PERMS_EDIT, Horde_Auth::getAuth());
-        }
-
-        if ($perm) {
-            /* Get the resource owner */
-            $tagger = Kronolith::getTagger();
-            switch ($request) {
-            case 'add':
-                $tagger->tag($args['resource'], $tags, $args['type']);
-                break;
-            case 'remove':
-                $tagger->untag($args['resource'], (int)$tags, $args['type']);
-                break;
-            }
-        }
-        return $this->_getTagHtml($tagger, $args['resource'], $args['type']);
-
-    }
-
-    /**
-     * Generate the HTML for the tag lists to send back to the browser.
-     *
-     * TODO: This should be made a view helper when we move to using Horde_View
-     *
-     * @param Kronolith_Tagger $tagger  The tagger object
-     * @param string $id                The identifier (share name or event uid)
-     * @param string $type              The type of resource (calendar/event)
-     *
-     * @return string  The HTML
-     */
-    private function _getTagHtml($tagger, $id, $type)
-    {
-        $tags = $tagger->getTags($id, 'calendar');
-        $js = '';
-        $html = '';
-
-        if ($type == 'calendar') {
-            $cal = $GLOBALS['kronolith_shares']->getShare($id);
-            $hasEdit = $cal->hasPermission(Horde_Auth::getAuth(), PERMS_EDIT);
-        } elseif ($type == 'event') {
-            $event = Kronolith::getDriver()->getByUID($id);
-            $hasEdit = $event->hasPermission(PERMS_EDIT, Horde_Auth::getAuth());
-        }
-
-        foreach ($tags as $tag_id => $tag) {
-            $html .= '<li class="panel-tags">' .  $tag . ($hasEdit ? '<a href="#" onclick="removeTag(\'' . $id . '\', \'' . $type . '\',' . $tag_id . ', \'' . Horde::url('imple.php', true) . '\'); Event.stop(event)" id="remove' . md5($id . $tag_id) . '">' . Horde::img('delete-small.png', _("Remove Tag"), '', $GLOBALS['registry']->getImageDir('horde')) . '</a>' : '') . '</li>';
-        }
-
-        return $html;
-    }
-
-}
diff --git a/kronolith/lib/Imple/TagAutoCompleter.php b/kronolith/lib/Imple/TagAutoCompleter.php
deleted file mode 100644 (file)
index e10bfd5..0000000
+++ /dev/null
@@ -1,124 +0,0 @@
-<?php
-/**
- * Copyright 2009 The Horde Project (http://www.horde.org/)
- *
- * See the enclosed file COPYING for license information (GPL). If you
- * did not receive this file, see http://www.fsf.org/copyleft/gpl.html.
- *
- * @author  Michael Slusarz <slusarz@horde.org>
- * @package Kronolith
- */
-class Kronolith_Imple_TagAutoCompleter extends Kronolith_Imple
-{
-    /**
-     * Constructor.
-     *
-     * @param array $params  Configuration parameters.
-     * <pre>
-     * 'triggerId' => TODO (optional)
-     * 'resultsId' => TODO (optional)
-     * </pre>
-     */
-    public function __construct($params)
-    {
-        if (!count($params)) {
-            return;
-        }
-        if (empty($params['resultsId'])) {
-            $params['resultsId'] = $params['triggerId'] . '_results';
-        }
-
-        parent::__construct($params);
-    }
-
-    /**
-     * Attach the Imple object to a javascript event.
-     * If the 'pretty' parameter is empty then we want a
-     * traditional autocompleter, otherwise we get a spiffy pretty one.
-     *
-     */
-    public function attach()
-    {
-        global $registry;
-        parent::attach();
-        Horde::addScriptFile('autocomplete.js', 'horde', true);
-
-        if ($pretty = !empty($this->_params['pretty'])) {
-            Horde::addScriptFile('prettyautocomplete.js', 'horde', true);
-            $this->_params['uri'] =  Horde::url($GLOBALS['registry']->get('webroot', 'kronolith') . '/imple.php?imple=TagAutoCompleter', true);
-        } else {
-            $this->_params['uri'] =  Horde::url($GLOBALS['registry']->get('webroot', 'kronolith') . '/imple.php?imple=TagAutoCompleter/input=' . rawurlencode($this->_params['triggerId']), true);
-        }
-
-        if (!$pretty) {
-            $params = array(
-                '"' . $this->_params['triggerId'] . '"',
-                '"' . $this->_params['resultsId'] . '"',
-                '"' . $this->_params['uri'] . '"'
-            );
-        }
-
-        $js_params = array(
-            'tokens: [","]',
-            'indicator: "' . $this->_params['triggerId'] . '_loading_img"'
-        );
-
-        // The pretty version needs to set this callback itself...
-        if (!$pretty && !empty($this->_params['updateElement'])) {
-            $js_params[] = 'updateElement: ' . $this->_params['updateElement'];
-        }
-
-        $params[] = '{' . implode(',', $js_params) . '}';
-
-        if ($pretty) {
-            $js_vars = array('boxClass' => 'hordeACBox kronolithLongField',
-                             'uri' => $this->_params['uri'],
-                             'trigger' => $this->_params['triggerId'],
-                             'URI_IMG_HORDE' => $registry->getImageDir('horde'),
-                             'params' => $params);
-
-            if (!empty($this->_params['existing'])) {
-                $js_vars['existing'] = $this->_params['existing'];
-            }
-
-            $script = array('new PrettyAutocompleter(' . Horde_Serialize::serialize($js_vars, Horde_Serialize::JSON, Horde_Nls::getCharset()) . ')');
-        } else {
-            $script = array('new Ajax.Autocompleter(' . implode(',', $params) . ')');
-        }
-
-        Kronolith::addInlineScript($script, 'dom');
-    }
-
-    /**
-     * TODO
-     *
-     * @param array $args  TODO
-     *
-     * @return string  TODO
-     */
-    public function handle($args)
-    {
-        // Avoid errors if 'input' isn't set and short-circuit empty searches.
-        if (empty($args['input']) ||
-            !($input = Horde_Util::getFormData($args['input']))) {
-            return array();
-        }
-        return array_map('htmlspecialchars', $this->getTagList($input));
-    }
-
-    /**
-     * Get a list of existing, used tags that match the search term.
-     *
-     * @param string $search  The term to search by.
-     *
-     * @return array  All matching tags.
-     */
-    static public function getTagList($search = '')
-    {
-        $tagger = Kronolith::getTagger();
-        $tags = $tagger->listTags($search);
-
-        return array_values($tags);
-    }
-
-}
index 3992470..4e6c891 100644 (file)
@@ -379,7 +379,7 @@ endif;
    <input type="text" name="tags" id="tags" value="<?php echo (!empty($tags) ? htmlspecialchars($tags) : '')?>" size="40" />
    <div id="tags_results" name="tags_results" class="autocomplete"></div>
    <span id="tags_loading_img" style="display:none;"><?php echo Horde::img('loading.gif', _("Loading...")) ?></span>
-   <?php Kronolith_Imple::factory('TagAutoCompleter', array('triggerId' => 'tags', 'id' => $event->getUID())); ?>
+   <?php Horde_Ajax_Imple::getInstance(array('kronolith', 'TagAutoCompleter'), array('triggerId' => 'tags', 'id' => $event->getUID())); ?>
  </td>
 </tr>
 <!-- spacer -->
index 4b60cfb..f9c0de5 100644 (file)
@@ -66,7 +66,7 @@ if ($cal->hasPermission(Horde_Auth::getAuth(), PERMS_EDIT)) {
         . Horde::img('delete-small.png', _("Remove Tag"), '', $registry->getImageDir('horde'))
         . '</a>';
 }
-Kronolith_Imple::factory('TagActions', array('triggerId' => 'remove' . md5($id . $tag_id),
+Horde_Ajax_Imple::getInstance(array('kronolith', 'TagActions'), array('triggerId' => 'remove' . md5($id . $tag_id),
                                              'action' => 'delete',
                                              'resource' => $id,
                                              'type' => 'calendar',
@@ -80,8 +80,8 @@ Kronolith_Imple::factory('TagActions', array('triggerId' => 'remove' . md5($id .
       <div id="newtags-input_<?php echo $id?>_results" class="autocomplete"></div>
       <span id="newtags-input_<?php echo $id?>_loading_img" style="display:none;"><?php echo Horde::img('loading.gif', _("Loading...")) ?></span>
      <?php
-      Kronolith_Imple::factory('TagAutoCompleter', array('triggerId' => 'newtags-input_' . $id, 'id' => $id));
-      Kronolith_Imple::factory('TagActions', array('triggerId' => 'newtags-button',
+      Horde_Ajax_Imple::getInstance(array('kronolith', 'TagAutoCompleter'), array('triggerId' => 'newtags-input_' . $id, 'id' => $id));
+      Horde_Ajax_Imple::getInstance(array('kronolith', 'TagActions'), array('triggerId' => 'newtags-button',
                                                    'resource' => $id,
                                                    'type' => 'calendar',
                                                    'action' => 'add'));