From: Gunnar Wrobel
Date: Sat, 10 Oct 2009 21:12:06 +0000 (+0200)
Subject: Intermediate step in refactoring Kolab_Server.
X-Git-Url: https://git.internetallee.de/?a=commitdiff_plain;h=b0a6bf08d2387ca6175c83c8d1e0a8757942624b;p=horde.git
Intermediate step in refactoring Kolab_Server.
---
diff --git a/framework/Kolab_Server/lib/Horde/Kolab/Server.php b/framework/Kolab_Server/lib/Horde/Kolab/Server.php
index 47f327d35..facd7fe44 100644
--- a/framework/Kolab_Server/lib/Horde/Kolab/Server.php
+++ b/framework/Kolab_Server/lib/Horde/Kolab/Server.php
@@ -12,18 +12,7 @@
*/
/**
- * The Autoloader allows us to omit "require/include" statements.
- */
-require_once 'Horde/Autoloader.php';
-
-/**
- * We need Log.php for the Log constants
- */
-require_once 'Log.php';
-
-/**
- * This class provides methods to deal with Kolab objects stored in
- * the Kolab object db.
+ * This class defines the interface of a generic Kolab user database.
*
* Copyright 2008-2009 The Horde Project (http://www.horde.org/)
*
@@ -36,715 +25,142 @@ require_once 'Log.php';
* @license http://www.fsf.org/copyleft/lgpl.html LGPL
* @link http://pear.horde.org/index.php?package=Kolab_Server
*/
-abstract class Horde_Kolab_Server
+interface Horde_Kolab_Server
{
- /** Maximum accepted level for the object class hierarchy */
- const MAX_HIERARCHY = 100;
-
- /**
- * Server parameters.
- *
- * @var array
- */
- public $params = array();
-
- /**
- * The UID of the current user.
- *
- * @var string
- */
- public $uid;
-
- /**
- * The search methods offered by the object defined for this server.
- *
- * @var array
- */
- protected $searches;
-
- /**
- * The structure handler for this server.
- *
- * @var Horde_Kolab_Server_Structure
- */
- public $structure;
-
- /**
- * A cache for object attribute definitions.
- *
- * @var array
- */
- protected $attributes;
-
- /**
- * The data cache.
- *
- * @var Horde_Cache
- */
- protected $cache;
-
- /**
- * The log handler.
- *
- * @var Horde_Log_Logger
- */
- protected $logger;
-
- /**
- * Construct a new Horde_Kolab_Server object.
- *
- * @param array $params Parameter array.
- */
- public function __construct(Horde_Kolab_Server_Structure $structure,
- $params = array())
- {
- $structure->setServer($this);
- $this->structure = $structure;
- $this->params = $params;
-
- if (!isset($this->params['cache_lifetime'])) {
- $this->params['cache_lifetime'] = 300;
- }
-
- if (isset($params['uid'])) {
- $this->uid = $params['uid'];
- }
-
- /** Initialize the search operations supported by this server. */
- $this->searches = $this->getSearchOperations();
- }
-
- /**
- * Set the optional log handler.
- *
- * @param Horde_Log_Logger $logger The log handler.
- *
- * @return NULL
- */
- public function setLogger(Horde_Log_Logger $logger)
- {
- $this->logger = $logger;
- }
-
- /**
- * Set the optional cache handler.
- *
- * @param Horde_Cache $cache The cache handler.
- *
- * @return NULL
- */
- public function setCache(Horde_Cache $cache)
- {
- $this->cache = $cache;
- }
-
- /**
- * Attempts to return a reference to a concrete Horde_Kolab_Server
- * instance based on $driver. It will only create a new instance
- * if no Horde_Kolab_Server instance with the same parameters currently
- * exists.
- *
- * This method must be invoked as:
- * $var = &Horde_Kolab_Server::singleton()
- *
- * @param array $params An array of optional login parameters. May
- * contain "uid" (for the login uid), "user"
- * (if the uid is not yet known), and "pass"
- * (for a password).
- *
- * @return Horde_Kolab_Server The concrete Horde_Kolab_Server reference.
- *
- * @throws Horde_Kolab_Server_Exception If the driver configuration is
- * missing or the given user could not
- * be identified.
- */
- static public function &singleton($params = array())
- {
- global $conf;
-
- static $instances = array();
-
- $provider = new stdClass;
-
- $sparam = $params;
- $sparam['pass'] = isset($sparam['pass'])
- ? hash('sha256', $sparam['pass']) : '';
- ksort($sparam);
- $signature = serialize($sparam);
-
- if (empty($instances[$signature])) {
-
- $user_pass = '';
-
- if (!empty($params['driver'])) {
- $provider->kolab_server_driver = $params['driver'];
- unset($params['driver']);
- } else if (isset($conf['kolab']['server']['driver'])) {
- $provider->kolab_server_driver = $conf['kolab']['server']['driver'];
- if (isset($conf['kolab']['server']['params'])) {
- if (!is_array($params)) {
- $params = $conf['kolab']['server']['params'];
- } else {
- if (isset($params['user']) && isset($params['pass'])) {
- $user_pass = $params['pass'];
- unset($params['pass']);
- }
- $params = array_merge($conf['kolab']['server']['params'],
- $params);
- }
- }
- } else {
- throw new Horde_Kolab_Server_Exception(
- 'The configuration for the Kolab server driver is missing!');
- }
-
- /* Provide caching */
- if (!empty($params['cache']['driver']) && class_exists('Horde_Cache')) {
- $provider->cache = Horde_Cache::singleton($params['cache']['driver'],
- isset($params['cache']['params'])
- ? $params['cache']['params'] : null);
- }
-
- /* Provide the structure */
- $structure = isset($params['structure']['driver'])
- ? $params['structure']['driver'] : 'kolab';
- $structure_params = isset($params['structure']['params'])
- ? $params['structure']['params'] : array();
-
- $provider->kolab_server_structure = &Horde_Kolab_Server_Structure::factory($structure,
- $structure_params);
-
- if (isset($params['user'])) {
-
- $provider->kolab_server_params = $params;
-
- $tmp_server = &Horde_Kolab_Server_Factory::getServer($provider);
-
- try {
- $uid = $tmp_server->uidForIdOrMail($params['user']);
- } catch (Horde_Kolab_Server_Exception $e) {
- throw new Horde_Kolab_Server_Exception(
- sprintf(_("Failed identifying the UID of the Kolab user %s. Error was: %s"),
- $params['user'],
- $e->getMessage()));
- }
- if ($uid === false) {
- throw new Horde_Kolab_Server_MissingObjectException(
- sprintf(_("Failed identifying the UID of the Kolab user %s. No such user."),
- $params['user']));
- }
- $params['uid'] = $uid;
- unset($params['user']);
- $params['pass'] = $user_pass;
- }
-
- if (!empty($params['write']) && isset($params['host_master'])) {
- $params['host'] = $params['host_master'];
- }
-
- $provider->kolab_server_params = $params;
-
- $instances[$signature] = &Horde_Kolab_Server_Factory::getServer($provider);
- }
-
- return $instances[$signature];
- }
-
- /**
- * Get the connection to the master server for write access.
- *
- * @return Horde_Kolab_Server The Horde_Kolab_Server reference to the master
- * server.
- */
- function &getMaster()
- {
- if (!isset($this->params['host_master'])
- || !empty($this->params['write'])
- || $this->params['host_master'] == $this->params['host']) {
- return $this;
- }
- $params = $this->params;
- $params['write'] = true;
- return Horde_Kolab_Server::singleton($params);
- }
-
/**
- * Stores the attribute definitions in the cache.
+ * Connect to the server.
*
- * @return Horde_Kolab_Server The concrete Horde_Kolab_Server reference.
- */
- function shutdown()
- {
- if (isset($this->attributes)) {
- if (isset($this->cache)) {
- foreach ($this->attributes as $key => $value) {
- $this->cache->set('attributes_' . $key, @serialize($value));
- }
- }
- }
- }
-
- /**
- * Fetch a Kolab object.
- *
- * This method will not retrieve any data from the server
- * immediately. Instead it will simply generate a new instance for the
- * desired object.
- *
- * The server data will only be accessed once you start reading the object
- * data.
- *
- * This method can also be used in order to fetch non-existing objects that
- * will be saved later. This is however not recommended and you should
- * rather use the add($info) method for that.
+ * @param string $guid The global unique id of the user.
+ * @param string $pass The password.
*
- * If you do not provide the object type the server will try to determine it
- * automatically based on the uid. As this requires reading data from the
- * server it is recommended to specify the object type whenever it is known.
- *
- * If you do not specify a uid the object corresponding to the user bound to
- * the server will be returned.
- *
- * @param string $uid The UID of the object to fetch.
- * @param string $type The type of the object to fetch.
- *
- * @return Kolab_Object The corresponding Kolab object.
+ * @return NULL.
*
- * @throws Horde_Kolab_Server_Exception
+ * @throws Horde_Kolab_Server_Exception If the connection failed.
*/
- public function &fetch($uid = null, $type = null)
- {
- if (!isset($uid)) {
- $uid = $this->uid;
- }
- if (empty($type)) {
- $type = $this->determineType($uid);
- }
-
- $object = &Horde_Kolab_Server_Object::factory($type, $uid, $this);
- return $object;
- }
+ public function connectGuid($guid = null, $pass = null);
/**
- * Add a Kolab object.
- *
- * @param array $info The object to store.
+ * Low level access to reading object data.
*
- * @return Kolab_Object The newly created Kolab object.
+ * This function provides direct access to the Server data.
*
- * @throws Horde_Kolab_Server_Exception If the type of the object to add has
- * been left undefined or the object
- * already exists.
- */
- public function &add($info)
- {
- if (!isset($info['type'])) {
- throw new Horde_Kolab_Server_Exception(
- 'The type of a new object must be specified!');
- }
-
- $type = $info['type'];
- unset($info['type']);
- $object = &Horde_Kolab_Server_Object::factory($type, null, $this, $info);
- if ($object->exists()) {
- throw new Horde_Kolab_Server_Exception(
- sprintf(_("The object with the uid \"%s\" does already exist!"),
- $object->get(Horde_Kolab_Server_Object::ATTRIBUTE_UID)));
- }
- $object->save();
- return $object;
- }
-
- /**
- * Generate a hash representation for a list of objects.
+ * Usually you should use
*
- * The approach taken here is somewhat slow as the server data gets fetched
- * into objects first which are then converted to hashes again. Since a
- * server search will usually deliver the result as a hash the intermediate
- * object conversion is inefficient.
+ *
+ * $object = $server->fetch('a server uid');
+ * $variable = $object['attribute']
+ *
*
- * But as the object classes are able to treat the attributes returned from
- * the server with custom parsing, this is currently the preferred
- * method. Especially for large result sets it would be better if this
- * method would call a static object class function that operate on the
- * result array returned from the server without using objects.
+ * to access object attributes. This is slower but takes special object
+ * handling into account (e.g. custom attribute parsing).
*
- * @param string $type The type of the objects to be listed
- * @param array $params Additional parameters.
+ * @param string $guid The object to retrieve.
*
- * @return array An array of Kolab objects.
+ * @return array An array of attributes.
*
* @throws Horde_Kolab_Server_Exception
- *
- * @todo The LDAP driver needs a more efficient version of this call as it
- * is not required to generate objects before returning data as a
- * hash. It can be derived directly from the LDAP result.
*/
- public function listHash($type, $params = null)
- {
- $list = $this->listObjects($type, $params);
-
- if (isset($params['attributes'])) {
- $attributes = $params['attributes'];
- } else {
- $attributes = null;
- }
-
- $hash = array();
- foreach ($list as $uid => $entry) {
- $hash[$uid] = $entry->toHash($attributes);
- }
-
- return $hash;
- }
-
- /**
- * Returns the set of objects supported by this server.
- *
- * @return array An array of supported objects.
- */
- public function getSupportedObjects()
- {
- return $this->structure->getSupportedObjects();
- }
-
- /**
- * Determine the type of an object by its tree position and other
- * parameters.
- *
- * @param string $uid The UID of the object to examine.
- *
- * @return string The class name of the corresponding object type.
- *
- * @throws Horde_Kolab_Server_Exception If the object type is unknown.
- */
- public function determineType($uid)
- {
- return $this->structure->determineType($uid);
- }
+ public function read($guid);
/**
- * Generates a UID for the given information.
+ * Low level access to reading some object attributes.
*
- * @param string $type The class name of the object to create.
- * @param string $id The id of the object.
- * @param array $info Any additional information about the object to create.
+ * @param string $guid The object to retrieve.
+ * @param string $attrs Restrict to these attributes.
*
- * @return string The UID.
+ * @return array An array of attributes.
*
* @throws Horde_Kolab_Server_Exception
- */
- public function generateServerUid($type, $id, $info)
- {
- return $this->structure->generateServerUid($type, $id, $info);
- }
-
- /**
- * Return the attributes supported by the given object class.
- *
- * @param string $class Determine the attributes for this class.
- *
- * @return array The supported attributes.
- *
- * @throws Horde_Kolab_Server_Exception If the schema analysis fails.
- */
- public function &getAttributes($class)
- {
- if (!isset($this->attributes)) {
- if (isset($this->cache)) {
- register_shutdown_function(array($this, 'shutdown'));
- }
- }
- if (empty($this->attributes[$class])) {
-
- if (isset($this->cache)) {
- $this->attributes[$class] = @unserialize($cache->get('attributes_' . $class,
- $this->params['cache_lifetime']));
- }
-
- if (empty($this->attributes[$class])) {
-
- $childclass = $class;
- $classes = array();
- $level = 0;
- while ($childclass != 'Horde_Kolab_Server_Object'
- && $level < self::MAX_HIERARCHY) {
- $classes[] = $childclass;
- $childclass = get_parent_class($childclass);
- $level++;
- }
-
- /** Finally add the basic object class */
- $classes[] = $childclass;
-
- if ($level == self::MAX_HIERARCHY) {
- if (isset($this->logger)) {
- $logger->err(sprintf('The maximal level of the object hierarchy has been exceeded for class \"%s\"!',
- $class));
- }
- }
-
- /**
- * Collect attributes from bottom to top.
- */
- $classes = array_reverse($classes);
-
- $types = array('defined', 'required', 'derived', 'collapsed',
- 'defaults', 'locked', 'object_classes');
- foreach ($types as $type) {
- $$type = array();
- }
-
- foreach ($classes as $childclass) {
- $vars = get_class_vars($childclass);
- if (isset($vars['init_attributes'])) {
- foreach ($types as $type) {
- /**
- * If the user wishes to adhere to the schema
- * information from the server we will skip the
- * attributes defined within the object class here.
- */
- if (!empty($this->params['schema_override'])
- && in_array($type, 'defined', 'required')) {
- continue;
- }
- if (isset($vars['init_attributes'][$type])) {
- $$type = array_merge($$type,
- $vars['init_attributes'][$type]);
- }
- }
- }
- }
-
- $attrs = array();
-
- foreach ($object_classes as $object_class) {
- $info = $this->getObjectclassSchema($object_class);
- if (isset($info['may'])) {
- $defined = array_merge($defined, $info['may']);
- }
- if (isset($info['must'])) {
- $defined = array_merge($defined, $info['must']);
- $required = array_merge($required, $info['must']);
- }
- foreach ($defined as $attribute) {
- try {
- $attrs[$attribute] = $this->getAttributeSchema($attribute);
- } catch (Horde_Kolab_Server_Exception $e) {
- /**
- * If the server considers the attribute to be
- * invalid we mark it.
- */
- $attrs[$attribute] = array('invalid' => true);
- }
- }
- foreach ($required as $attribute) {
- $attrs[$attribute]['required'] = true;
- }
- foreach ($locked as $attribute) {
- $attrs[$attribute]['locked'] = true;
- }
- foreach ($defaults as $attribute => $default) {
- $attrs[$attribute]['default'] = $default;
- }
- $attrs[Horde_Kolab_Server_Object::ATTRIBUTE_OC]['default'] = $object_classes;
- }
- foreach ($derived as $key => $attributes) {
- $supported = true;
- if (isset($attributes['base'])) {
- foreach ($attributes['base'] as $attribute) {
- /**
- * Usually derived attribute are determined on basis
- * of one or more attributes. If any of these is not
- * supported the derived attribute should not be
- * included into the set of supported attributes.
- */
- if (!isset($attrs[$attribute])) {
- unset($derived[$attribute]);
- $supported = false;
- break;
- }
- }
- }
- if ($supported) {
- $attrs[$key] = $attributes;
- }
- }
- $check_collapsed = $collapsed;
- foreach ($check_collapsed as $key => $attributes) {
- if (isset($attributes['base'])) {
- foreach ($attributes['base'] as $attribute) {
- /**
- * Usually collapsed attribute are determined on basis
- * of one or more attributes. If any of these is not
- * supported the collapsed attribute should not be
- * included into the set of supported attributes.
- */
- if (!isset($attrs[$attribute])) {
- unset($collapsed[$attribute]);
- }
- }
- }
- }
- $this->attributes[$class] = array($attrs,
- array(
- 'derived' => array_keys($derived),
- 'collapsed' => $collapsed,
- 'locked' => $locked,
- 'required' => $required));
- }
- }
- return $this->attributes[$class];
- }
-
- /**
- * Return the schema for the given objectClass.
- *
- * @param string $objectclass Fetch the schema for this objectClass.
- *
- * @return array The schema for the given objectClass.
*
- * @throws Horde_Kolab_Server_Exception If retrieval of the schema failed.
+ * @see Horde_Kolab_Server::read
*/
- protected function getObjectclassSchema($objectclass)
- {
- return array();
- }
+ public function readAttributes($guid, array $attrs);
/**
- * Return the schema for the given attribute.
- *
- * @param string $attribute Fetch the schema for this attribute.
+ * Finds object data matching a given set of criteria.
*
- * @return array The schema for the given attribute.
+ * @param Horde_Kolab_Server_Query $query The criteria for the search.
+ * @param array $params Additional search parameters.
*
- * @throws Horde_Kolab_Server_Exception If retrieval of the schema failed.
- */
- protected function getAttributeSchema($attribute)
- {
- return array();
- }
-
- /**
- * Returns the set of search operations supported by this server type.
- *
- * @return array An array of supported search operations.
- */
- public function getSearchOperations()
- {
- $server_searches = array();
- foreach ($this->getSupportedObjects() as $sobj) {
- if (in_array('getSearchOperations', get_class_methods($sobj))) {
- $searches = call_user_func(array($sobj, 'getSearchOperations'));
- foreach ($searches as $search) {
- $server_searches[$search] = array('class' => $sobj);
- }
- }
- }
- return $server_searches;
- }
-
- /**
- * Capture undefined calls.
- *
- * @param string $method The name of the called method.
- * @param array $args Arguments of the call.
- *
- * @return NULL.
+ * @return Horde_Kolab_Server_Result The result object.
*
* @throws Horde_Kolab_Server_Exception
*/
- public function __call($method, $args)
- {
- if (in_array($method, array_keys($this->searches))) {
- array_unshift($args, $this);
- if (isset($this->searches[$method])) {
- return call_user_func_array(array($this->searches[$method]['class'],
- $method), $args);
- }
- }
- throw new Horde_Kolab_Server_Exception(
- sprintf("The server type \"%s\" does not support method \"%s\"!",
- get_class($this), $method));
- }
+ public function find(
+ Horde_Kolab_Server_Query $query,
+ array $params = array()
+ );
/**
- * Stub for reading object data.
+ * Finds all object data below a parent matching a given set of criteria.
*
- * @param string $uid The object to retrieve.
- * @param string $attrs Restrict to these attributes.
+ * @param Horde_Kolab_Server_Query $query The criteria for the search.
+ * @param string $parent The parent to search below.
+ * @param array $params Additional search parameters.
*
- * @return array An array of attributes.
+ * @return Horde_Kolab_Server_Result The result object.
*
* @throws Horde_Kolab_Server_Exception
*/
- abstract public function read($uid, $attrs = null);
+ public function findBelow(
+ Horde_Kolab_Server_Query $query,
+ $parent,
+ array $params = array()
+ );
/**
- * Find object data matching a given set of criteria.
+ * Modify existing object data.
*
- * @param array $criteria The criteria for the search.
- * @param string $params Additional search parameters.
+ * @param string $guid The GUID of the object to be added.
+ * @param array $data The attributes of the object to be stored.
*
- * @return array The result array.
+ * @return NULL
*
* @throws Horde_Kolab_Server_Exception
*/
- abstract public function find($criteria, $params = array());
+ public function save($guid, array $data);
/**
- * Stub for saving object data.
+ * Add new object data.
*
- * @param string $uid The UID of the object to be added.
- * @param array $data The attributes of the object to be added.
- * @param boolean $exists Does the object already exist on the server?
+ * @param string $guid The GUID of the object to be added.
+ * @param array $data The attributes of the object to be added.
*
- * @return boolean True if saving succeeded.
+ * @return NULL
*
* @throws Horde_Kolab_Server_Exception
*/
- abstract public function save($uid, $data, $exists = false);
+ public function add($guid, array $data);
/**
- * Stub for deleting an object.
+ * Delete an object.
*
- * @param string $uid The UID of the object to be deleted.
+ * @param string $guid The GUID of the object to be deleted.
*
- * @return boolean True if deleting the object succeeded.
+ * @return NULL
*
* @throws Horde_Kolab_Server_Exception
*/
- abstract public function delete($uid);
+ public function delete($guid);
/**
- * Stub for renaming an object.
+ * Rename an object.
*
- * @param string $uid The UID of the object to be renamed.
- * @param string $new The new UID of the object.
+ * @param string $guid The GUID of the object to be renamed.
+ * @param string $new The new GUID of the object.
*
- * @return boolean True if renaming succeeded.
+ * @return NULL
*
* @throws Horde_Kolab_Server_Exception
*/
- abstract public function rename($uid, $new);
+ public function rename($guid, $new);
/**
- * List all objects of a specific type
- *
- * @param string $type The type of the objects to be listed
- * @param array $params Additional parameters.
+ * Return the database schema description.
*
- * @return array An array of Kolab objects.
- *
- * @throws Horde_Kolab_Server_Exception
- */
- abstract public function listObjects($type, $params = null);
-
- /**
- * Return the root of the UID values on this server.
+ * @return array The schema.
*
- * @return string The base UID on this server (base DN on ldap).
+ * @throws Horde_Kolab_Server_Exception If retrieval of the schema failed.
*/
- abstract public function getBaseUid();
-
-}
+ public function getSchema();
+}
\ No newline at end of file
diff --git a/framework/Kolab_Server/lib/Horde/Kolab/Server/Base.php b/framework/Kolab_Server/lib/Horde/Kolab/Server/Base.php
new file mode 100644
index 000000000..6f244cefe
--- /dev/null
+++ b/framework/Kolab_Server/lib/Horde/Kolab/Server/Base.php
@@ -0,0 +1,327 @@
+
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Kolab_Server
+ */
+
+/**
+ * This class provides methods to deal with Kolab objects stored in
+ * the Kolab object db.
+ *
+ * Copyright 2008-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 Kolab_Server
+ * @author Gunnar Wrobel
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Kolab_Server
+ */
+abstract class Horde_Kolab_Server_Base implements Horde_Kolab_Server,
+ Horde_Kolab_Server_Objects,
+ Horde_Kolab_Server_Schema,
+ Horde_Kolab_Server_Search,
+ Horde_Kolab_Server_Structure
+{
+ /**
+ * Server parameters.
+ *
+ * @var array
+ */
+ protected $params = array();
+
+ /**
+ * The user name of the current user.
+ *
+ * @var string
+ */
+ private $_user = null;
+
+ /**
+ * The structure handler for this server.
+ *
+ * @var Horde_Kolab_Server_Structure
+ */
+ protected $structure;
+
+ /**
+ * The search handler for this server.
+ *
+ * @var Horde_Kolab_Server_Search
+ */
+ protected $search;
+
+ /**
+ * The object handler for this server.
+ *
+ * @var Horde_Kolab_Server_Objects
+ */
+ protected $objects;
+
+ /**
+ * The data cache.
+ *
+ * @var mixed
+ */
+ protected $cache = null;
+
+ /**
+ * Construct a new Horde_Kolab_Server object.
+ *
+ * @param array $params Parameter array.
+ */
+ public function __construct(
+ Horde_Kolab_Server_Objects $objects,
+ Horde_Kolab_Server_Structure $structure,
+ Horde_Kolab_Server_Search $search,
+ Horde_Kolab_Server_Schema $schema
+ ) {
+ $objects->setServer($this);
+ $structure->setServer($this);
+ $search->setServer($this);
+ $schema->setServer($this);
+
+ $this->objects = $objects;
+ $this->structure = $structure;
+ $this->search = $search;
+ $this->schema = $schema;
+ }
+
+ /**
+ * Set configuration parameters.
+ *
+ * @param array $params The parameters.
+ *
+ * @return NULL
+ */
+ public function setParams(array $params)
+ {
+ $this->params = array_merge($this->params, $params);
+
+ if (isset($this->params['uid'])) {
+ $this->uid = $this->params['uid'];
+ }
+ }
+
+ /**
+ * Set the cache handler.
+ *
+ * @param mixed $cache The cache handler.
+ *
+ * @return NULL
+ */
+ public function setCache($cache)
+ {
+ $this->cache = $cache;
+ }
+
+ /**
+ * Connect to the server.
+ *
+ * @param string $user The user name.
+ * @param string $pass The password.
+ *
+ * @return NULL.
+ *
+ * @throws Horde_Kolab_Server_Exception If the connection failed.
+ */
+ public function connect($user = null, $pass = null)
+ {
+ /** Do we need to switch the user? */
+ if ($user !== $this->_current_user) {
+ $this->user = $this->_connect($user, $pass);
+ }
+ }
+
+ /**
+ * Connect to the server.
+ *
+ * @param string $uid The unique id of the user.
+ * @param string $pass The password.
+ *
+ * @return NULL.
+ *
+ * @throws Horde_Kolab_Server_Exception If the connection failed.
+ */
+ public function connectUid($uid = null, $pass = null)
+ {
+ }
+
+ /**
+ * Add a Kolab object.
+ *
+ * @param array $info The object to store.
+ *
+ * @return Kolab_Object The newly created Kolab object.
+ *
+ * @throws Horde_Kolab_Server_Exception If the type of the object to add has
+ * been left undefined or the object
+ * already exists.
+ */
+ public function add(array $info)
+ {
+ return $this->objects->add($info);
+ }
+
+ /**
+ * Fetch a Kolab object.
+ *
+ * @param string $uid The UID of the object to fetch.
+ * @param string $type The type of the object to fetch.
+ *
+ * @return Kolab_Object The corresponding Kolab object.
+ *
+ * @throws Horde_Kolab_Server_Exception
+ */
+ public function fetch($uid = null, $type = null)
+ {
+ return $this->objects->fetch($uid = null, $type = null);
+ }
+
+ /**
+ * List all objects of a specific type
+ *
+ * @param string $type The type of the objects to be listed
+ * @param array $params Additional parameters.
+ *
+ * @return array An array of Kolab objects.
+ *
+ * @throws Horde_Kolab_Server_Exception
+ */
+ public function listObjects($type, $params = null)
+ {
+ return $this->objects->listObjects($type, $params = null);
+ }
+
+ /**
+ * Generate a hash representation for a list of objects.
+ *
+ * @param string $type The type of the objects to be listed
+ * @param array $params Additional parameters.
+ *
+ * @return array An array of Kolab objects.
+ *
+ * @throws Horde_Kolab_Server_Exception
+ */
+ public function listHash($type, $params = null)
+ {
+ return $this->objects->listHash($type, $params = null);
+ }
+
+ /**
+ * Returns the set of objects supported by this server.
+ *
+ * @return array An array of supported objects.
+ */
+ public function getSupportedObjects()
+ {
+ return $this->structure->getSupportedObjects();
+ }
+
+ /**
+ * Determine the type of an object by its tree position and other
+ * parameters.
+ *
+ * @param string $uid The UID of the object to examine.
+ *
+ * @return string The class name of the corresponding object type.
+ *
+ * @throws Horde_Kolab_Server_Exception If the object type is unknown.
+ */
+ public function determineType($uid)
+ {
+ return $this->structure->determineType($uid);
+ }
+
+ /**
+ * Generates a UID for the given information.
+ *
+ * @param string $type The class name of the object to create.
+ * @param string $id The id of the object.
+ * @param array $info Any additional information about the object to create.
+ *
+ * @return string The UID.
+ *
+ * @throws Horde_Kolab_Server_Exception
+ */
+ public function generateServerUid($type, $id, $info)
+ {
+ return $this->structure->generateServerUid($type, $id, $info);
+ }
+
+ /**
+ * Return the schema for the given objectClass.
+ *
+ * @param string $objectclass Fetch the schema for this objectClass.
+ *
+ * @return array The schema for the given objectClass.
+ *
+ * @throws Horde_Kolab_Server_Exception If retrieval of the schema failed.
+ */
+ public function getObjectclassSchema($objectclass)
+ {
+ return $this->schema->getObjectclassSchema($objectclass);
+ }
+
+ /**
+ * Return the schema for the given attribute.
+ *
+ * @param string $attribute Fetch the schema for this attribute.
+ *
+ * @return array The schema for the given attribute.
+ *
+ * @throws Horde_Kolab_Server_Exception If retrieval of the schema failed.
+ */
+ public function getAttributeSchema($attribute)
+ {
+ return $this->schema->getAttributeSchema($attribute);
+ }
+
+ /**
+ * Return the attributes supported by the given object class.
+ *
+ * @param string $class Determine the attributes for this class.
+ *
+ * @return array The supported attributes.
+ *
+ * @throws Horde_Kolab_Server_Exception If the schema analysis fails.
+ */
+ public function &getAttributes($class)
+ {
+ return $this->schema->getAttributes($class);
+ }
+
+ /**
+ * Returns the set of search operations supported by this server type.
+ *
+ * @return array An array of supported search operations.
+ */
+ public function getSearchOperations()
+ {
+ return $this->search->getSearchOperations();
+ }
+
+ /**
+ * Capture undefined calls and assume they refer to a search operation.
+ *
+ * @param string $method The name of the called method.
+ * @param array $args Arguments of the call.
+ *
+ * @return NULL.
+ *
+ * @throws Horde_Kolab_Server_Exception
+ */
+ public function __call($method, $args)
+ {
+ return $this->search->__call($method, $args);
+ }
+}
diff --git a/framework/Kolab_Server/lib/Horde/Kolab/Server/Connection.php b/framework/Kolab_Server/lib/Horde/Kolab/Server/Connection.php
new file mode 100644
index 000000000..2da34a2fe
--- /dev/null
+++ b/framework/Kolab_Server/lib/Horde/Kolab/Server/Connection.php
@@ -0,0 +1,43 @@
+
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Kolab_Server
+ */
+
+/**
+ * Interface for connection handling.
+ *
+ * Copyright 2008-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 Kolab_Server
+ * @author Gunnar Wrobel
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Kolab_Server
+ */
+interface Horde_Kolab_Server_Connection
+{
+ /**
+ * Get the server read connection.
+ *
+ * @return mixed The connection for reading data.
+ */
+ public function getRead();
+
+ /**
+ * Get the server write connection.
+ *
+ * @return mixed The connection for writing data.
+ */
+ public function getWrite();
+}
\ No newline at end of file
diff --git a/framework/Kolab_Server/lib/Horde/Kolab/Server/Connection/Simpleldap.php b/framework/Kolab_Server/lib/Horde/Kolab/Server/Connection/Simpleldap.php
new file mode 100644
index 000000000..73c903f20
--- /dev/null
+++ b/framework/Kolab_Server/lib/Horde/Kolab/Server/Connection/Simpleldap.php
@@ -0,0 +1,67 @@
+
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Kolab_Server
+ */
+
+/**
+ * A simple LDAP setup without read-only slaves.
+ *
+ * Copyright 2008-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 Kolab_Server
+ * @author Gunnar Wrobel
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Kolab_Server
+ */
+class Horde_Kolab_Server_Connection_Simpleldap
+implements Horde_Kolab_Server_Connection
+{
+ /**
+ * The LDAP connection handle.
+ *
+ * @var Net_LDAP2
+ */
+ private $_ldap;
+
+ /**
+ * Constructor
+ *
+ * @param Net_LDAP2 $ldap The ldap connection.
+ */
+ public function __construct(Net_LDAP2 $ldap)
+ {
+ $this->_ldap = $ldap;
+ }
+
+ /**
+ * Get the server read connection.
+ *
+ * @return mixed The connection for reading data.
+ */
+ public function getRead()
+ {
+ return $this->_ldap;
+ }
+
+ /**
+ * Get the server write connection.
+ *
+ * @return mixed The connection for writing data.
+ */
+ public function getWrite()
+ {
+ return $this->_ldap;
+ }
+}
\ No newline at end of file
diff --git a/framework/Kolab_Server/lib/Horde/Kolab/Server/Connection/Splittedldap.php b/framework/Kolab_Server/lib/Horde/Kolab/Server/Connection/Splittedldap.php
new file mode 100644
index 000000000..b5781a7f1
--- /dev/null
+++ b/framework/Kolab_Server/lib/Horde/Kolab/Server/Connection/Splittedldap.php
@@ -0,0 +1,78 @@
+
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Kolab_Server
+ */
+
+/**
+ * A connection to a LDAP master/slave setup.
+ *
+ * Copyright 2008-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 Kolab_Server
+ * @author Gunnar Wrobel
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Kolab_Server
+ */
+class Horde_Kolab_Server_Connection_Splittedldap
+implements Horde_Kolab_Server_Connection
+{
+ /**
+ * LDAP read connection handle.
+ *
+ * @var Net_LDAP2
+ */
+ private $_ldap_read;
+
+ /**
+ * LDAP write connection handle.
+ *
+ * @var Net_LDAP2
+ */
+ private $_ldap_write;
+
+ /**
+ * Constructor
+ *
+ * @param Net_LDAP2 $ldap_read The ldap_read connection.
+ * @param Net_LDAP2 $ldap_write The ldap_write connection.
+ */
+ public function __construct(
+ Net_LDAP2 $ldap_read,
+ Net_LDAP2 $ldap_write
+ ) {
+ $this->_ldap_read = $ldap_read;
+ $this->_ldap_write = $ldap_write;
+ }
+
+ /**
+ * Get the server read connection.
+ *
+ * @return mixed The connection for reading data.
+ */
+ public function getRead()
+ {
+ return $this->_ldap_read;
+ }
+
+ /**
+ * Get the server write connection.
+ *
+ * @return mixed The connection for writing data.
+ */
+ public function getWrite()
+ {
+ return $this->_ldap_write;
+ }
+}
\ No newline at end of file
diff --git a/framework/Kolab_Server/lib/Horde/Kolab/Server/Exception.php b/framework/Kolab_Server/lib/Horde/Kolab/Server/Exception.php
index dfc1cfedc..44260dddc 100644
--- a/framework/Kolab_Server/lib/Horde/Kolab/Server/Exception.php
+++ b/framework/Kolab_Server/lib/Horde/Kolab/Server/Exception.php
@@ -30,45 +30,20 @@ class Horde_Kolab_Server_Exception extends Horde_Exception
/**
* Constants to define the error type.
*/
- const SYSTEM = 1;
- const EMPTY_RESULT = 2;
- const INVALID_INFORMATION = 3;
- /**
- * The array of available error messages. These are connected to the error
- * codes used above and might be used to differentiate between what we show
- * the user in the frontend and what we actually log in the backend.
- *
- * @var array
- */
- protected $messages;
+ /** Unknown error type */
+ const SYSTEM = 1;
- /**
- * Exception constructor
- *
- * @param mixed $message The exception message, a PEAR_Error object, or an
- * Exception object.
- * @param mixed $code A numeric error code, or
- * an array from error_get_last().
- */
- public function __construct($message = null, $code = null)
- {
- $this->setMessages();
+ /** The LDAP extension is missing */
+ const MISSING_LDAP_EXTENSION = 2;
- parent::__construct($message, $code);
- }
+ /** Binding to the LDAP server failed */
+ const BIND_FAILED = 3;
+
+ const EMPTY_RESULT = 4;
+
+ const INVALID_INFORMATION = 5;
+
+ const INVALID_QUERY = 6;
- /**
- * Initialize the messages handled by this exception.
- *
- * @return NULL
- */
- protected function setMessages()
- {
- $this->messages = array(
- self::SYSTEM => _("An internal error occured."),
- self::EMPTY_RESULT => _("No result was found."),
- self::INVALID_INFORMATION => _("The information provided is invalid."),
- );
- }
}
diff --git a/framework/Kolab_Server/lib/Horde/Kolab/Server/Factory.php b/framework/Kolab_Server/lib/Horde/Kolab/Server/Factory.php
index 06d8e5843..a9938ccd6 100644
--- a/framework/Kolab_Server/lib/Horde/Kolab/Server/Factory.php
+++ b/framework/Kolab_Server/lib/Horde/Kolab/Server/Factory.php
@@ -12,11 +12,6 @@
*/
/**
- * The Autoloader allows us to omit "require/include" statements.
- */
-require_once 'Horde/Autoloader.php';
-
-/**
* A factory for Kolab server objects.
*
* Copyright 2008-2009 The Horde Project (http://www.horde.org/)
@@ -33,90 +28,297 @@ require_once 'Horde/Autoloader.php';
class Horde_Kolab_Server_Factory
{
/**
- * Attempts to return a concrete Horde_Kolab_Server instance.
+ * Singleton instances.
*
- * @param Horde_Injector $injector The object providing our dependencies.
+ * @var array
+ */
+ static private $_instances = array();
+
+ /**
+ * Setup the machinery to create Horde_Kolab_Server objects.
*
- * @return Horde_Kolab_Server The newly created concrete Horde_Kolab_Server
- * instance.
+ * @param array $configuration The parameters required to create
+ * the desired Horde_Kolab_Server object.
+ * @param Horde_Injector $injector The object providing our dependencies.
*
- * @throws Horde_Kolab_Server_Exception If the requested Horde_Kolab_Server
- * subclass could not be found.
+ * @return NULL
*/
- static public function &getServer(Horde_Injector $injector)
+ static public function setup(array $configuration, Horde_Injector $injector)
{
- $driver = 'Horde_Kolab_Server_Ldap';
- $params = array();
+ self::setupObjects($injector);
+ self::setupSearch($injector);
+ self::setupSchema($injector);
- try {
- $config = $injector->getInstance('Horde_Kolab_Server_Config');
+ self::setupStructure(
+ isset($configuration['structure'])
+ ? $configuration['structure'] : array(),
+ $injector
+ );
+ unset($configuration['structure']);
- if (isset($config->driver)) {
- $driver = $config->driver;
- }
- if (isset($config->params)) {
- $params = $config->params;
- }
- } catch (ReflectionException $e) {
- }
+ self::setupCache(
+ $injector,
+ isset($configuration['cache'])
+ ? $configuration['cache'] : null
+ );
+ unset($configuration['cache']);
- $class = 'Horde_Kolab_Server_' . ucfirst(basename($driver));
- if (!class_exists($class)) {
- throw new Horde_Kolab_Server_Exception('Server type definition "' . $class . '" missing.');
- }
+ self::setupLogger(
+ $injector,
+ isset($configuration['logger'])
+ ? $configuration['logger'] : null
+ );
+ unset($configuration['logger']);
- $server = new $class($injector->getInstance('Horde_Kolab_Server_Structure'),
- $params);
+ self::setupServer($configuration, $injector);
+ }
+
+ /**
+ * Setup the machinery to create a Horde_Kolab_Server_Objects handler.
+ *
+ * @param Horde_Injector $injector The object providing our dependencies.
+ *
+ * @return NULL
+ */
+ static protected function setupObjects(Horde_Injector $injector)
+ {
+ $injector->bindImplementation(
+ 'Horde_Kolab_Server_Objects',
+ 'Horde_Kolab_Server_Objects_Base'
+ );
+ }
- try {
- $server->setCache($injector->getInstance('Horde_Kolab_Server_Cache'));
- } catch (ReflectionException $e) {
+ /**
+ * Setup the machinery to create a Horde_Kolab_Server_Structure handler.
+ *
+ * @param array $configuration The parameters required to create
+ * the desired
+ * Horde_Kolab_Server_Structure handler.
+ * @param Horde_Injector $injector The object providing our dependencies.
+ *
+ * @return NULL
+ */
+ static protected function setupStructure(
+ array $configuration,
+ Horde_Injector $injector
+ ) {
+ if (!isset($configuration['driver'])) {
+ $configuration['driver'] = 'Horde_Kolab_Server_Structure_Kolab';
}
- try {
- $server->setLogger($injector->getInstance('Horde_Kolab_Server_Logger'));
- } catch (ReflectionException $e) {
+ switch (ucfirst(strtolower($configuration['driver']))) {
+ case 'Ldap':
+ case 'Kolab':
+ $driver = 'Horde_Kolab_Server_Structure_'
+ . ucfirst(strtolower($configuration['driver']));
+ break;
+ default:
+ $driver = $configuration['driver'];
+ break;
}
- return $server;
+ $injector->bindImplementation('Horde_Kolab_Server_Structure', $driver);
}
/**
- * Attempts to return a concrete Horde_Kolab_Server_Structure instance.
+ * Setup the machinery to create a Horde_Kolab_Server_Search handler.
*
* @param Horde_Injector $injector The object providing our dependencies.
*
- * @return Horde_Kolab_Server_Structure The newly created concrete
- * Horde_Kolab_Server_Structure
- * instance.
+ * @return NULL
+ */
+ static protected function setupSearch(Horde_Injector $injector)
+ {
+ $injector->bindImplementation(
+ 'Horde_Kolab_Server_Search',
+ 'Horde_Kolab_Server_Search_Base'
+ );
+ }
+
+ /**
+ * Setup the machinery to create a Horde_Kolab_Server_Schema handler.
+ *
+ * @param Horde_Injector $injector The object providing our dependencies.
*
- * @throws Horde_Kolab_Server_Exception If the requested
- * Horde_Kolab_Server_Structure
- * subclass could not be found.
+ * @return NULL
*/
- static public function &getStructure(Horde_Injector $injector)
+ static protected function setupSchema(Horde_Injector $injector)
{
- $driver = 'Horde_Kolab_Server_Structure_Kolab';
- $params = array();
+ $injector->bindImplementation(
+ 'Horde_Kolab_Server_Schema',
+ 'Horde_Kolab_Server_Schema_Base'
+ );
+ }
- try {
- $config = $injector->getInstance('Horde_Kolab_Server_Structure_Config');
+ /**
+ * Provide a cache handler for Horde_Kolab_Server.
+ *
+ * @param Horde_Injector $injector The object providing our dependencies.
+ * @param mixed $instance The cache handler or empty if it
+ * should be created.
+ *
+ * @return NULL
+ */
+ static protected function setupCache(
+ Horde_Injector $injector,
+ $instance = null
+ ) {
+ if (empty($instance)) {
+ $instance = new Horde_Cache_Null();
+ }
+ $injector->setInstance('Horde_Kolab_Server_Cache', $instance);
+ }
- if (isset($config->driver)) {
- $driver = $config->driver;
- }
- if (isset($config->params)) {
- $params = $config->params;
+ /**
+ * Provide a log handler for Horde_Kolab_Server.
+ *
+ * @param Horde_Injector $injector The object providing our dependencies.
+ * @param mixed $instance The log handler or empty if it
+ * should be created.
+ *
+ * @return NULL
+ */
+ static protected function setupLogger(
+ Horde_Injector $injector,
+ $instance = null
+ ) {
+ if (empty($instance)) {
+ $instance = new Horde_Log_Logger(new Horde_Log_Handler_Null());
+ }
+ $injector->setInstance('Horde_Kolab_Server_Logger', $instance);
+ }
+
+ if (empty($this->_ldap_read)) {
+ $this->handleError(
+ Net_LDAP2::checkLDAPExtension(),
+ Horde_Kolab_Server_Exception::MISSING_LDAP_EXTENSION
+ );
+
+ $this->_ldap_read = new Net_LDAP2($this->params);
+
+ if (isset($this->params['host_master'])
+ && $this->params['host_master'] == $this->params['host']
+ ) {
+
+ $params = $this->params;
+ $params['host'] = $this->params['host_master'];
+
+ $this->_ldap_write = new Net_LDAP2($params);
+ } else {
+ $this->_ldap_write = $this->_ldap_read;
}
- } catch (ReflectionException $e) {
}
- //@todo: either we use driver names or real class names.
- //$class = 'Horde_Kolab_Server_Structure_' . ucfirst(basename($driver));
- if (!class_exists($driver)) {
- throw new Horde_Kolab_Server_Exception('Structure type definition "' . $driver . '" missing.');
+ if ($write) {
+ return $this->_ldap_write;
+ } else {
+ return $this->_ldap_read;
+ }
+
+ /**
+ * Setup the machinery to create a Horde_Kolab_Server.
+ *
+ * @param array $configuration The parameters required to create
+ * the desired Horde_Kolab_Server.
+ * @param Horde_Injector $injector The object providing our dependencies.
+ *
+ * @return NULL
+ */
+ static protected function setupServer(
+ array $configuration,
+ Horde_Injector $injector
+ ) {
+ if (empty($configuration['driver'])) {
+ $configuration['driver'] = 'Horde_Kolab_Server_Ldap';
+ }
+
+ $config = new stdClass;
+
+ switch (ucfirst(strtolower($configuration['driver']))) {
+ case 'Ldap':
+ case 'Test':
+ case 'File':
+ $config->driver = 'Horde_Kolab_Server_'
+ . ucfirst(strtolower($configuration['driver']));
+ break;
+ default:
+ $config->driver = $configuration['driver'];
+ break;
+ }
+
+ $config->params = isset($configuration['params'])
+ ? $configuration['params'] : array();
+
+ $injector->setInstance('Horde_Kolab_Server_Config', $config);
+
+ $injector->bindFactory(
+ 'Horde_Kolab_Server',
+ 'Horde_Kolab_Server_Factory',
+ 'getServer'
+ );
+ }
+
+ /**
+ * Attempts to return a concrete Horde_Kolab_Server instance.
+ *
+ * @param Horde_Injector $injector The object providing our dependencies.
+ *
+ * @return Horde_Kolab_Server The newly created concrete Horde_Kolab_Server
+ * instance.
+ */
+ static public function &getServer(Horde_Injector $injector)
+ {
+ $config = $injector->getInstance('Horde_Kolab_Server_Config');
+ $driver = $config->driver;
+ $server = new $driver(
+ $injector->getInstance('Horde_Kolab_Server_Objects'),
+ $injector->getInstance('Horde_Kolab_Server_Structure'),
+ $injector->getInstance('Horde_Kolab_Server_Search'),
+ $injector->getInstance('Horde_Kolab_Server_Schema')
+ );
+ $server->setParams($config->params);
+ $server->setCache($injector->getInstance('Horde_Kolab_Server_Cache'));
+ $server->setLogger($injector->getInstance('Horde_Kolab_Server_Logger'));
+
+ return $server;
+ }
+
+ /**
+ * Attempts to return a reference to a concrete Horde_Kolab_Server
+ * instance based on $driver. It will only create a new instance
+ * if no Horde_Kolab_Server instance with the same parameters currently
+ * exists.
+ *
+ * This method must be invoked as:
+ *
+ * $var = &Horde_Kolab_Server::singleton()
+ *
+ *
+ * @param array $params An array of parameters.
+ *
+ * @return Horde_Kolab_Server The concrete Horde_Kolab_Server reference.
+ */
+ static public function &singleton($params = array())
+ {
+ $signature = hash('md5', serialize(ksort($params)));
+
+ if (!isset(self::$_instances[$signature])) {
+ $params['cache'] = Horde_Cache::singleton(
+ $GLOBALS['conf']['cache']['driver'],
+ //@todo: Can we omit Horde:: here?
+ Horde::getDriverConfig(
+ 'cache',
+ $GLOBALS['conf']['cache']['driver']
+ )
+ );
+ $params['logger'] = Horde::getLogger();
+ $injector = new Horde_Injector(new Horde_Injector_TopLevel());
+ self::setup($params, $injector);
+ self::$_instances[$signature] = $injector->getInstance(
+ 'Horde_Kolab_Server'
+ );
}
- $structure = new $driver($params);
- return $structure;
+
+ return self::$_instances[$signature];
}
}
\ No newline at end of file
diff --git a/framework/Kolab_Server/lib/Horde/Kolab/Server/File.php b/framework/Kolab_Server/lib/Horde/Kolab/Server/File.php
index 5cb63b7d0..ba69a17f2 100644
--- a/framework/Kolab_Server/lib/Horde/Kolab/Server/File.php
+++ b/framework/Kolab_Server/lib/Horde/Kolab/Server/File.php
@@ -37,21 +37,33 @@ class Horde_Kolab_Server_File extends Horde_Kolab_Server_Test
private $_file;
/**
- * Construct a new Horde_Kolab_Server object.
+ * Set configuration parameters.
*
- * @param array $params Parameter array.
+ * @param array $params The parameters.
+ *
+ * @return NULL
*/
- public function __construct(Horde_Kolab_Server_Structure $structure,
- $params = array())
+ public function setParams(array $params)
{
if (isset($params['file'])) {
$this->_file = $params['file'];
- } else {
- throw new Horde_Kolab_Server_Exception('The file based driver requires a \'file\' parameter.');
}
- parent::__construct($structure, $params);
+
+ parent::setParams($params);
}
+ /**
+ * Get the file parameter.
+ *
+ * @return NULL
+ */
+ private function _getFile()
+ {
+ if (empty($this->_file)) {
+ throw new Horde_Kolab_Server_Exception('The file based driver requires a \'file\' parameter.');
+ }
+ return $this->_file;
+ }
/**
* Load the current state of the database.
@@ -60,7 +72,7 @@ class Horde_Kolab_Server_File extends Horde_Kolab_Server_Test
*/
protected function load()
{
- $raw_data = file_get_contents($this->_file);
+ $raw_data = file_get_contents($this->_getFile());
if (!$raw_data === false) {
$data = @unserialize($raw_data);
if ($data !== false) {
@@ -69,7 +81,7 @@ class Horde_Kolab_Server_File extends Horde_Kolab_Server_Test
$error = error_get_last();
if (isset($this->logger)) {
$this->logger->warn(sprintf('Horde_Kolab_Server_file failed to read the database from %s. Error was: %s',
- $this->_file, $error['message']));
+ $this->_getFile(), $error['message']));
}
$this->data = array();
}
@@ -84,12 +96,12 @@ class Horde_Kolab_Server_File extends Horde_Kolab_Server_Test
protected function store()
{
$raw_data = serialize($this->data);
- $result = @file_put_contents($this->_file, $raw_data);
+ $result = @file_put_contents($this->_getFile(), $raw_data);
if ($result === false) {
$error = error_get_last();
if (isset($this->logger)) {
$this->logger->warn(sprintf('Horde_Kolab_Server_file failed to store the database in %s. Error was: %s',
- $this->_file, $error['message']));
+ $this->_getFile(), $error['message']));
}
}
}
@@ -101,7 +113,7 @@ class Horde_Kolab_Server_File extends Horde_Kolab_Server_Test
*/
public function clean()
{
- unlink($this->_file);
+ unlink($this->_getFile());
$this->data = array();
$this->store();
}
@@ -111,8 +123,8 @@ class Horde_Kolab_Server_File extends Horde_Kolab_Server_Test
*
* @return string The path to the database.
*/
- public function getStoragePAth()
+ public function getStoragePath()
{
- return $this->_file;
+ return $this->_getFile();
}
}
diff --git a/framework/Kolab_Server/lib/Horde/Kolab/Server/Filtered.php b/framework/Kolab_Server/lib/Horde/Kolab/Server/Filtered.php
new file mode 100644
index 000000000..ab77cbede
--- /dev/null
+++ b/framework/Kolab_Server/lib/Horde/Kolab/Server/Filtered.php
@@ -0,0 +1,75 @@
+
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Kolab_Server
+ */
+
+/**
+ * This class provides methods to deal with objects stored in
+ * a filtered LDAP db.
+ *
+ * Copyright 2008-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 Kolab_Server
+ * @author Gunnar Wrobel
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Kolab_Server
+ */
+class Horde_Kolab_Server_Filtered extends Horde_Kolab_Server_Ldap
+{
+ /**
+ * A global filter to add to each query.
+ *
+ * @var string
+ */
+ private $_filter;
+
+ /**
+ * Constructor.
+ *
+ * @param Horde_Kolab_Server_Connection $connection The LDAP connection.
+ * @param string $base_dn The LDAP server base DN.
+ * @param string $filter A global filter to add
+ * to all queries.
+ */
+ public function __construct(
+ Horde_Kolab_Server_Connection $connection,
+ $base_dn,
+ $filter = null
+ ) {
+ parent::__construct($connection, $base_dn);
+ $this->_filter = $filter;
+ }
+
+ /**
+ * Finds all object data below a parent matching a given set of criteria.
+ *
+ * @param array $criteria The criteria for the search.
+ * @param string $parent The parent to search below.
+ * @param array $params Additional search parameters.
+ *
+ * @return Horde_Kolab_Server_Result The result object.
+ *
+ * @throws Horde_Kolab_Server_Exception
+ */
+ public function findBelow(array $criteria, $parent, array $params = array())
+ {
+ $query = new Horde_Kolab_Server_Query_Ldap($criteria);
+ $query_string = (string) $query;
+ if (!empty($this->_filter)) {
+ $query_string = '(&(' . $this->_filter . ')' . $query_string . ')';
+ }
+ return $this->_search($query_string, $params, $parent);
+ }
+}
diff --git a/framework/Kolab_Server/lib/Horde/Kolab/Server/Ldap.php b/framework/Kolab_Server/lib/Horde/Kolab/Server/Ldap.php
index 61aad377c..8294e2e9b 100644
--- a/framework/Kolab_Server/lib/Horde/Kolab/Server/Ldap.php
+++ b/framework/Kolab_Server/lib/Horde/Kolab/Server/Ldap.php
@@ -26,21 +26,21 @@
* @license http://www.fsf.org/copyleft/lgpl.html LGPL
* @link http://pear.horde.org/index.php?package=Kolab_Server
*/
-class Horde_Kolab_Server_Ldap extends Horde_Kolab_Server
+abstract class Horde_Kolab_Server_Ldap implements Horde_Kolab_Server
{
/**
- * LDAP connection handle.
+ * The GUID of the current user.
*
- * @var Net_LDAP2
+ * @var string
*/
- private $_ldap;
+ private $_guid;
/**
- * The configuration for connection to the LDAP server.
+ * LDAP connection handle.
*
- * @var array
+ * @var Horde_Kolab_Server_Connection
*/
- private $_config;
+ private $_conn;
/**
* Base DN of the LDAP server.
@@ -50,449 +50,242 @@ class Horde_Kolab_Server_Ldap extends Horde_Kolab_Server
private $_base_dn;
/**
- * The LDAP schemas.
- *
- * @var Net_LDAP2_Schema
- */
- private $_schema;
-
- /**
- * The last search result. This can be used to retrieve additional
- * information about the LDAP search result (e.g. if the size
- * limit for the search has been exceeded).
- *
- * @var Net_LDAP2_Search
- */
- public $lastSearch;
-
- /**
- * Construct a new Horde_Kolab_Server_ldap object.
+ * Constructor.
*
- * @param array $params Parameter array.
+ * @param Horde_Kolab_Server_Connection $connection The LDAP connection.
+ * @param string $base_dn The LDAP server base DN.
+ * @param string $filter A global filter to add
+ * to all queries.
*/
- public function __construct(Horde_Kolab_Server_Structure $structure,
- $params = array())
- {
- if (!isset($params['charset'])) {
- $params['charset'] = 'UTF-8';
- }
-
- $base_config = array('host' => 'localhost',
- 'port' => 389,
- 'version' => 3,
- 'starttls' => false,
- 'uid' => '',
- 'pass' => '',
- 'basedn' => '',
- 'charset' => '',
- 'options' => array(),
- 'auto_reconnect' => true);
-
- $config = array_merge($base_config, $params);
-
- $this->_base_dn = $config['basedn'];
-
- $config['binddn'] = $config['uid'];
- $config['bindpw'] = $config['pass'];
-
- $this->_config = $config;
-
- $this->connect();
-
- parent::__construct($structure, $params);
+ public function __construct(
+ Horde_Kolab_Server_Connection $connection,
+ $base_dn,
+ $filter = null
+ ) {
+ $this->_conn = $connection;
+ $this->_base_dn = $base_dn;
}
-
/**
- * Connect to the LDAP server.
+ * Connect to the server.
+ *
+ * @param string $guid The global unique id of the user.
+ * @param string $pass The password.
*
* @return NULL.
*
* @throws Horde_Kolab_Server_Exception If the connection failed.
*/
- protected function connect()
+ public function connectGuid($guid = null, $pass = null)
{
- $this->_ldap = Net_LDAP2::connect($this->_config);
- if (is_a($this->_ldap, 'PEAR_Error')) {
- throw new Horde_Kolab_Server_Exception($this->_ldap,
- Horde_Kolab_Server_Exception::SYSTEM);
+ /** Do we need to switch the user? */
+ if ((empty($guid) && empty($this->_guid))
+ || $guid !== $this->_guid
+ ) {
+ $this->_handleError(
+ $this->_conn->getRead()->bind($guid, $pass),
+ Horde_Kolab_Server_Exception::BIND_FAILED
+ );
+ $this->_guid = $guid;
}
}
/**
- * Map attributes defined within this library their their real world
- * counterparts.
- *
- * @param array $data The data that has been read and needs to be mapped.
- *
- * @return NULL
- */
- protected function unmapAttributes(&$data)
- {
- if (!empty($this->params['map'])) {
- foreach ($this->params['map'] as $attribute => $map) {
- if (isset($data[$map])) {
- $data[$attribute] = $data[$map];
- unset($data[$map]);
- }
- }
- }
- }
-
- /**
- * Map attributes defined within this library into their real world
- * counterparts.
- *
- * @param array $data The data to be written.
+ * Low level access to reading object data.
*
- * @return NULL
- */
- protected function mapAttributes(&$data)
- {
- if (!empty($this->params['map'])) {
- foreach ($this->params['map'] as $attribute => $map) {
- if (isset($data[$attribute])) {
- $data[$map] = $data[$attribute];
- unset($data[$attribute]);
- }
- }
- }
- }
-
- /**
- * Map attribute keys defined within this library into their real world
- * counterparts.
+ * @param string $guid The object to retrieve.
*
- * @param array $keys The attribute keys.
+ * @return array An array of attributes.
*
- * @return NULL
+ * @throws Horde_Kolab_Server_Exception If the search operation hit an error
+ * or returned no result.
*/
- protected function mapKeys(&$keys)
+ public function read($guid)
{
- if (!empty($this->params['map'])) {
- foreach ($this->params['map'] as $attribute => $map) {
- $key = array_search($attribute, $keys);
- if ($key !== false) {
- $keys[$key] = $map;
- }
- }
- }
- }
-
- /**
- * Map a single attribute key defined within this library into its real
- * world counterpart.
- *
- * @param array $field The attribute name.
- *
- * @return The real name of this attribute on the server we connect to.
- */
- protected function mapField($field)
- {
- if (!empty($this->params['map'])
- && isset($this->params['map'][$field])) {
- return $this->params['map'][$field];
- }
- return $field;
+ $params = array('scope' => 'base');
+ $data = $this->_search(null, $params, $guid)->asArray();
+ if ($data->count() == 0) {
+ throw new Horde_Kolab_Server_Exception(
+ 'Empty result!',
+ Horde_Kolab_Server_Exception::EMPTY_RESULT
+ );
+ }
+ return array_pop($data->asArray());
}
/**
- * Low level access to reading object data.
- *
- * This function provides fast access to the Server data.
- *
- * Usually you should use
- *
- * $object = $server->fetch('a server uid');
- * $variable = $object['attribute']
- *
- * to access object attributes. This is slower but takes special object
- * handling into account (e.g. custom attribute parsing).
+ * Low level access to reading some object attributes.
*
- * @param string $uid The object to retrieve.
+ * @param string $guid The object to retrieve.
* @param string $attrs Restrict to these attributes.
*
- * @return array|boolean An array of attributes or false if the specified
- * object was not found.
+ * @return array An array of attributes.
*
- * @throws Horde_Kolab_Server_Exception If the search operation retrieved a
- * problematic result.
+ * @throws Horde_Kolab_Server_Exception If the search operation hit an error
+ * or returned no result.
*/
- public function read($uid, $attrs = null)
+ public function readAttributes($guid, array $attrs)
{
- $params = array('scope' => 'base');
- if (!empty($attrs)) {
- $params['attributes'] = $attrs;
- }
-
- $data = $this->search(null, $params, $uid);
- if (empty($data)) {
- throw new Horde_Kolab_Server_Exception(_("Empty result!"),
- Horde_Kolab_Server_Exception::EMPTY_RESULT);
+ $params = array(
+ 'scope' => 'base',
+ 'attributes' => $attrs
+ );
+ $data = $this->_search(null, $params, $guid);
+ if ($data->count() == 0) {
+ throw new Horde_Kolab_Server_Exception(
+ 'Empty result!',
+ Horde_Kolab_Server_Exception::EMPTY_RESULT
+ );
}
-
- return array_pop($data);
+ return array_pop($data->asArray());
}
/**
- * Save an object.
+ * Finds object data matching a given set of criteria.
+ *
+ * @param Horde_Kolab_Server_Query $query The criteria for the search.
+ * @param array $params Additional search parameters.
*
- * @param string $uid The UID of the object to be added.
- * @param array $data The attributes of the object to be changed.
- * @param boolean $exists Does the object already exist on the server?
+ * @return Horde_Kolab_Server_Result The result object.
*
- * @return boolean True if saving succeeded.
+ * @throws Horde_Kolab_Server_Exception
*/
- public function save($uid, $data, $exists = false)
- {
- $this->mapAttributes($data);
-
- if ($exists === false) {
- $entry = Net_LDAP2_Entry::createFresh($uid, $data['add']);
- $result = $this->_ldap->add($entry);
- if ($result instanceOf PEAR_Error) {
- throw new Horde_Kolab_Server_Exception($result,
- Horde_Kolab_Server_Exception::SYSTEM);
- }
- } else {
- $entry = $this->_ldap->getEntry($uid, $data['attributes']);
- $result = $this->_ldap->modify($entry, $data);
- if ($result instanceOf PEAR_Error) {
- throw new Horde_Kolab_Server_Exception($result,
- Horde_Kolab_Server_Exception::SYSTEM);
- }
- }
- if (isset($this->logger)) {
- $this->logger->debug(sprintf('The object \"%s\" has been successfully saved!',
- $uid));
- }
- return true;
+ public function find(
+ Horde_Kolab_Server_Query $query,
+ array $params = array()
+ ) {
+ $this->findBelow($query, $this->_base_dn, $params);
}
/**
- * Delete an object.
+ * Finds all object data below a parent matching a given set of criteria.
*
- * @param string $uid The UID of the object to be deleted.
+ * @param Horde_Kolab_Server_Query $query The criteria for the search.
+ * @param string $parent The parent to search below.
+ * @param array $params Additional search parameters.
*
- * @return boolean True if saving succeeded.
+ * @return Horde_Kolab_Server_Result The result object.
*
* @throws Horde_Kolab_Server_Exception
*/
- public function delete($uid)
- {
- $result = $this->_ldap->delete($uid);
- if ($result instanceOf PEAR_Error) {
- throw new Horde_Kolab_Server_Exception($result,
- Horde_Kolab_Server_Exception::SYSTEM);
- }
- if (isset($this->logger)) {
- $this->logger(sprintf('The object \"%s\" has been successfully deleted!',
- $uid));
- }
- return true;
- }
+ abstract public function findBelow(
+ Horde_Kolab_Server_Query $query,
+ $parent,
+ array $params = array()
+ );
/**
- * Rename an object.
+ * Modify existing object data.
*
- * @param string $uid The UID of the object to be renamed.
- * @param string $new The new UID of the object.
+ * @param string $guid The GUID of the object to be added.
+ * @param array $data The attributes of the object to be stored.
*
- * @return boolean True if renaming succeeded.
+ * @return NULL
*
* @throws Horde_Kolab_Server_Exception
*/
- public function rename($uid, $new)
+ public function save($guid, array $data)
{
- /* Net_LDAP modifies the variable */
- $old = $uid;
- $result = $this->_ldap->move($old, $new);
- if ($result instanceOf PEAR_Error) {
- throw new Horde_Kolab_Server_Exception($result,
- Horde_Kolab_Server_Exception::SYSTEM);
- }
- if (isset($this->logger)) {
- $this->logger->debug(sprintf('The object \"%s\" has been successfully renamed to \"%s\"!',
- $uid, $new));
- }
- return true;
+ $entry = $this->_conn->getWrite()->getEntry($guid, $data['attributes']);
+ $this->_handleError(
+ $this->_conn->getWrite()->modify($entry, $data),
+ Horde_Kolab_Server_Exception::SYSTEM
+ );
}
/**
- * List all objects of a specific type.
+ * Add new object data.
*
- * @param string $type The type of the objects to be listed
- * @param array $params Additional parameters.
+ * @param string $guid The GUID of the object to be added.
+ * @param array $data The attributes of the object to be added.
*
- * @return array An array of Kolab objects.
+ * @return NULL
*
* @throws Horde_Kolab_Server_Exception
- *
- * @todo Sorting
*/
- public function listObjects($type, $params = null)
+ public function add($guid, array $data)
{
- if (empty($params['base_dn'])) {
- $base = $this->_base_dn;
- } else {
- $base = $params['base_dn'];
- }
-
- $result = Horde_Kolab_Server_Object::loadClass($type);
- $vars = get_class_vars($type);
- $criteria = call_user_func(array($type, 'getFilter'));
- $filter = $this->searchQuery($criteria);
- $sort = $vars['sort_by'];
-
- if (isset($params['sort'])) {
- $sort = $params['sort'];
- }
-
- $options = array('scope' => 'sub');
- if (isset($params['attributes'])) {
- $options['attributes'] = $params['attributes'];
- } else {
- $options['attributes'] = $this->getAttributes($type);
- }
-
- $data = $this->search($filter, $options, $base);
- if (empty($data)) {
- return array();
- }
-
- if ($sort) {
- /* FIXME */
- /* $data = $result->as_sorted_struct(); */
- /*$this->sort($result, $sort); */
- }
-
- if (isset($params['from'])) {
- $from = $params['from'];
- } else {
- $from = -1;
- }
-
- if (isset($params['to'])) {
- $sort = $params['to'];
- } else {
- $to = -1;
- }
-
- if (!empty($vars['required_group'])) {
- $required_group = new Horde_Kolab_Server_Object_Kolabgroupofnames($this,
- null,
- $vars['required_group']);
- }
-
- $objects = array();
- foreach ($data as $uid => $entry) {
- if (!empty($vars['required_group'])) {
- if (!$required_group->exists() || !$required_group->isMember($uid)) {
- continue;
- }
- }
- $objects[$uid] = &Horde_Kolab_Server_Object::factory($type, $uid,
- $this, $entry);
- }
- return $objects;
+ $entry = Net_LDAP2_Entry::createFresh($guid, $data);
+ $this->_handleError($entry, Horde_Kolab_Server_Exception::SYSTEM);
+ $this->_handleError(
+ $this->_conn->getWrite()->add($entry),
+ Horde_Kolab_Server_Exception::SYSTEM
+ );
}
/**
- * Return the root of the UID values on this server.
+ * Delete an object.
*
- * @return string The base UID on this server (base DN on ldap).
- */
- public function getBaseUid()
- {
- return $this->_base_dn;
- }
-
- /**
- * Return the ldap schema.
+ * @param string $guid The UID of the object to be deleted.
*
- * @return Net_LDAP2_Schema The LDAP schema.
+ * @return NULL
*
- * @throws Horde_Kolab_Server_Exception If retrieval of the schema failed.
+ * @throws Horde_Kolab_Server_Exception
*/
- private function _getSchema()
+ public function delete($guid)
{
- if (!isset($this->_schema)) {
- $result = $this->_ldap->schema();
- if ($result instanceOf PEAR_Error) {
- throw new Horde_Kolab_Server_Exception($result,
- Horde_Kolab_Server_Exception::SYSTEM);
- }
- $this->_schema = &$result;
- }
- return $this->_schema;
+ $this->_handleError(
+ $this->_conn->getWrite()->delete($guid),
+ Horde_Kolab_Server_Exception::SYSTEM
+ );
}
/**
- * Return the schema for the given objectClass.
+ * Rename an object.
*
- * @param string $objectclass Fetch the schema for this objectClass.
+ * @param string $guid The UID of the object to be renamed.
+ * @param string $new The new UID of the object.
*
- * @return array The schema for the given objectClass.
+ * @return NULL
*
- * @throws Horde_Kolab_Server_Exception If retrieval of the schema failed.
+ * @throws Horde_Kolab_Server_Exception
*/
- protected function getObjectclassSchema($objectclass)
+ public function rename($guid, $new)
{
- if (!empty($this->_config['schema_support'])) {
- $schema = $this->_getSchema();
- $info = $schema->get('objectclass', $objectclass);
- if ($info instanceOf PEAR_Error) {
- throw new Horde_Kolab_Server_Exception($info,
- Horde_Kolab_Server_Exception::SYSTEM);
- }
- return $info;
- }
- return parent::getObjectclassSchema($objectclass);
+ $this->_handleError(
+ $this->_conn->getWrite()->move($old, $new),
+ Horde_Kolab_Server_Exception::SYSTEM
+ );
}
/**
- * Return the schema for the given attribute.
- *
- * @param string $attribute Fetch the schema for this attribute.
+ * Return the ldap schema.
*
- * @return array The schema for the given attribute.
+ * @return Net_LDAP2_Schema The LDAP schema.
*
* @throws Horde_Kolab_Server_Exception If retrieval of the schema failed.
*/
- protected function getAttributeSchema($attribute)
+ public function getSchema()
{
- if (!empty($this->_config['schema_support'])) {
- $schema = $this->_getSchema();
- $info = $schema->get('attribute', $attribute);
- if ($info instanceOf PEAR_Error) {
- throw new Horde_Kolab_Server_Exception($info,
- Horde_Kolab_Server_Exception::SYSTEM);
- }
- return $info;
- }
- return parent::getAttributeSchema($attribute);
+ $result = $this->_conn->getRead()->schema();
+ $this->_handleError($result, Horde_Kolab_Server_Exception::SYSTEM);
+ return $result;
}
/**
- * Find object data matching a given set of criteria.
+ * Check for a PEAR Error and convert it to an exception if necessary.
*
- * @param array $criteria The criteria for the search.
- * @param string $params Additional search parameters.
+ * @param mixed $result The result to be tested.
+ * @param code $code The error code to use in case the result is an error.
*
- * @return array The result array.
+ * @return NULL.
*
- * @throws Horde_Kolab_Server_Exception
+ * @throws Horde_Kolab_Server_Exception If the connection failed.
*/
- public function find($criteria, $params = array())
- {
- return $this->search($this->searchQuery($criteria), $params);
+ private function _handleError(
+ $result,
+ $code = Horde_Kolab_Server_Exception::SYSTEM
+ ) {
+ if (is_a($result, 'PEAR_Error')) {
+ throw new Horde_Kolab_Server_Exception($result, $code);
+ }
}
/**
* Search for object data.
*
* @param string $filter The LDAP search filter.
- * @param string $params Additional search parameters.
+ * @param array $params Additional search parameters.
* @param string $base The search base
*
* @return array The result array.
@@ -500,153 +293,14 @@ class Horde_Kolab_Server_Ldap extends Horde_Kolab_Server
* @throws Horde_Kolab_Server_Exception If the search operation encountered
* a problem.
*/
- public function search($filter = null, $params = array(), $base = null)
- {
- if (isset($params['attributes'])) {
- $this->mapKeys($params['attributes']);
- }
-
- if (!isset($base)) {
- $base = $this->_base_dn;
- }
- $this->lastSearch = &$this->_ldap->search($base, $filter, $params);
- if (is_a($this->lastSearch, 'PEAR_Error')) {
- throw new Horde_Kolab_Server_Exception($this->lastSearch,
- Horde_Kolab_Server_Exception::SYSTEM);
- }
- $data = $this->lastSearch->as_struct();
- if (is_a($data, 'PEAR_Error')) {
- throw new Horde_Kolab_Server_Exception($data,
- Horde_Kolab_Server_Exception::SYSTEM);
- }
- $this->unmapAttributes($data);
- return $data;
- }
-
- /**
- * Get the LDAP object classes for the given DN.
- *
- * @param string $uid DN of the object.
- *
- * @return array An array of object classes.
- *
- * @throws Horde_Kolab_Server_Exception If the object has no
- * object classes.
- */
- public function getObjectClasses($uid)
- {
- $object = $this->read($uid, array(Horde_Kolab_Server_Object::ATTRIBUTE_OC));
- if (!isset($object[Horde_Kolab_Server_Object::ATTRIBUTE_OC])) {
- throw new Horde_Kolab_Server_Exception(sprintf("The object %s has no %s attribute!",
- $uid, Horde_Kolab_Server_Object::ATTRIBUTE_OC),
- Horde_Kolab_Server_Exception::SYSTEM);
- }
- $result = array_map('strtolower',
- $object[Horde_Kolab_Server_Object::ATTRIBUTE_OC]);
- return $result;
- }
-
- /**
- * Build a search query.
- *
- * Taken from the Turba LDAP driver.
- *
- * @param array $criteria The array of criteria.
- *
- * @return string An LDAP query filter.
- */
- public function searchQuery($criteria)
- {
- /* Accept everything. */
- $filter = '(' . strtolower(Horde_Kolab_Server_Object::ATTRIBUTE_OC) . '=*)';
-
- /* Build the LDAP filter. */
- if (count($criteria)) {
- $f = $this->buildSearchQuery($criteria);
- if ($f instanceOf Net_LDAP2_Filter) {
- $filter = $f->asString();
- }
- }
-
- /* Add source-wide filters, which are _always_ AND-ed. */
- if (!empty($this->params['filter'])) {
- $filter = '(&' . '(' . $this->params['filter'] . ')' . $filter . ')';
- }
- return $filter;
- }
-
- /**
- * Build a piece of a search query.
- *
- * Taken from the Turba LDAP driver.
- *
- * @param array $criteria The array of criteria.
- *
- * @return string An LDAP query fragment.
- */
- protected function &buildSearchQuery($criteria)
+ private function _search($filter, array $params, $base)
{
- if (!is_array($criteria)) {
- throw new Horde_Kolab_Server_Exception(sprintf("Invalid search criteria \"%s\"!",
- $criteria),
- Horde_Kolab_Server_Exception::SYSTEM);
- }
- if (isset($criteria['field'])) {
- $rhs = isset($criteria['test']) ? $criteria['test'] : '';
- /* Keep this in for reference as we did not really test servers with different encoding yet */
- // require_once 'Horde/Nls.php';
- //$rhs = Horde_String::convertCharset($criteria['test'], Horde_Nls::getCharset(), $this->params['charset']);
- switch ($criteria['op']) {
- case '=':
- $op = 'equals';
- break;
- default:
- $op = $criteria['op'];
- }
- return Net_LDAP2_Filter::create($this->mapField($criteria['field']),
- $op, $rhs);
- }
- foreach ($criteria as $key => $vals) {
- if (!empty($vals['OR'])
- || !empty($vals['AND'])
- || !empty($vals['NOT'])) {
- $parts = $this->buildSearchQuery($vals);
- if (count($parts) > 1) {
- if (!empty($vals['OR'])) {
- $operator = '|';
- } else if (!empty($vals['NOT'])) {
- $operator = '!';
- } else {
- $operator = '&';
- }
- return Net_LDAP2_Filter::combine($operator, $parts);
- } else {
- return $parts[0];
- }
- } else {
- $parts = array();
- foreach ($vals as $test) {
- $parts[] = &$this->buildSearchQuery($test);
- }
- switch ($key) {
- case 'OR':
- $operator = '|';
- break;
- case 'AND':
- $operator = '&';
- break;
- case 'NOT':
- $operator = '!';
- break;
- }
- if (count($parts) > 1) {
- return Net_LDAP2_Filter::combine($operator, $parts);
- } else if ($operator == '!') {
- return Net_LDAP2_Filter::combine($operator, $parts[0]);
- } else {
- return $parts[0];
- }
- }
- }
+ $this->_lastSearch = &$this->_conn->getRead()->search(
+ $base, $filter, $params
+ );
+ $this->_handleError(
+ $this->_lastSearch, Horde_Kolab_Server_Exception::SYSTEM
+ );
+ return new Horde_Kolab_Server_Result_Ldap($this->_lastSearch);
}
}
diff --git a/framework/Kolab_Server/lib/Horde/Kolab/Server/List.php b/framework/Kolab_Server/lib/Horde/Kolab/Server/List.php
new file mode 100644
index 000000000..7a9ad87d6
--- /dev/null
+++ b/framework/Kolab_Server/lib/Horde/Kolab/Server/List.php
@@ -0,0 +1,43 @@
+
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Kolab_Server
+ */
+
+/**
+ * Interface for server lists.
+ *
+ * Copyright 2008-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 Kolab_Server
+ * @author Gunnar Wrobel
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Kolab_Server
+ */
+interface Horde_Kolab_Server_List
+{
+ /**
+ * List all objects of a specific type.
+ *
+ * @param string $type The type of the objects to be listed
+ * @param array $params Additional parameters.
+ *
+ * @return array An array of Kolab objects.
+ *
+ * @throws Horde_Kolab_Server_Exception
+ *
+ * @todo Sorting
+ */
+ public function listObjects($type, $params = null);
+}
\ No newline at end of file
diff --git a/framework/Kolab_Server/lib/Horde/Kolab/Server/List/Base.php b/framework/Kolab_Server/lib/Horde/Kolab/Server/List/Base.php
new file mode 100644
index 000000000..2c5785650
--- /dev/null
+++ b/framework/Kolab_Server/lib/Horde/Kolab/Server/List/Base.php
@@ -0,0 +1,105 @@
+
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Kolab_Server
+ */
+
+/**
+ * A server list implementation.
+ *
+ * Copyright 2008-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 Kolab_Server
+ * @author Gunnar Wrobel
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Kolab_Server
+ */
+class Horde_Kolab_Server_List_Base implements Horde_Kolab_Server_List
+{
+ /**
+ * List all objects of a specific type.
+ *
+ * @param string $type The type of the objects to be listed
+ * @param array $params Additional parameters.
+ *
+ * @return array An array of Kolab objects.
+ *
+ * @throws Horde_Kolab_Server_Exception
+ *
+ * @todo Sorting
+ */
+ public function listObjects($type, $params = null)
+ {
+ $result = Horde_Kolab_Server_Object::loadClass($type);
+ $vars = get_class_vars($type);
+ $criteria = call_user_func(array($type, 'getFilter'));
+ $filter = $this->searchQuery($criteria);
+ $sort = $vars['sort_by'];
+
+ if (isset($params['sort'])) {
+ $sort = $params['sort'];
+ }
+
+ $options = array('scope' => 'sub');
+ if (isset($params['attributes'])) {
+ $options['attributes'] = $params['attributes'];
+ } else {
+ $options['attributes'] = $this->getAttributes($type);
+ }
+
+ $data = $this->search($filter, $options, $base);
+ if (empty($data)) {
+ return array();
+ }
+
+ if ($sort) {
+ /* FIXME */
+ /* $data = $result->as_sorted_struct(); */
+ /*$this->sort($result, $sort); */
+ }
+
+ if (isset($params['from'])) {
+ $from = $params['from'];
+ } else {
+ $from = -1;
+ }
+
+ if (isset($params['to'])) {
+ $sort = $params['to'];
+ } else {
+ $to = -1;
+ }
+
+ if (!empty($vars['required_group'])) {
+ $required_group = new Horde_Kolab_Server_Object_Kolabgroupofnames(
+ $this,
+ null,
+ $vars['required_group']
+ );
+ }
+
+ $objects = array();
+ foreach ($data as $uid => $entry) {
+ if (!empty($vars['required_group'])) {
+ if (!$required_group->exists() || !$required_group->isMember($uid)) {
+ continue;
+ }
+ }
+ $objects[$uid] = &Horde_Kolab_Server_Object::factory(
+ $type, $uid, $this, $entry
+ );
+ }
+ return $objects;
+ }
+}
\ No newline at end of file
diff --git a/framework/Kolab_Server/lib/Horde/Kolab/Server/Logged.php b/framework/Kolab_Server/lib/Horde/Kolab/Server/Logged.php
new file mode 100644
index 000000000..072642bc1
--- /dev/null
+++ b/framework/Kolab_Server/lib/Horde/Kolab/Server/Logged.php
@@ -0,0 +1,227 @@
+
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Kolab_Server
+ */
+
+/**
+ * A server delegation that logs server access via Horde_Log_Logger.
+ *
+ * Copyright 2008-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 Kolab_Server
+ * @author Gunnar Wrobel
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Kolab_Server
+ */
+class Horde_Kolab_Server_Logged implements Horde_Kolab_Server
+{
+ /**
+ * The server we delegate to.
+ *
+ * @var Horde_Kolab_Server
+ */
+ private $_server;
+
+ /**
+ * The log handler.
+ *
+ * @var Horde_Log_Logger
+ */
+ private $_logger;
+
+ /**
+ * Constructor.
+ *
+ * @param Horde_Kolab_Server $server The base server connection.
+ * @param Horde_Log_Logger $logger THe log handler.
+ */
+ public function __construct(
+ Horde_Kolab_Server $server,
+ Horde_Log_Logger $logger
+ ) {
+ $this->_server = $server;
+ $this->_logger = $logger;
+ }
+
+ /**
+ * Connect to the server.
+ *
+ * @param string $guid The global unique id of the user.
+ * @param string $pass The password.
+ *
+ * @return NULL.
+ *
+ * @throws Horde_Kolab_Server_Exception If the connection failed.
+ */
+ public function connectGuid($guid = null, $pass = null)
+ {
+ $this->_server->connectGuid($guid, $pass);
+ }
+
+ /**
+ * Low level access to reading object data.
+ *
+ * @param string $guid The object to retrieve.
+ * @param array $attrs Restrict to these attributes.
+ *
+ * @return array An array of attributes.
+ *
+ * @throws Horde_Kolab_Server_Exception If the search operation hit an error
+ * or returned no result.
+ */
+ public function read($guid, array $attrs = array())
+ {
+ return $this->_server->read($guid);
+ }
+
+ /**
+ * Low level access to reading some object attributes.
+ *
+ * @param string $guid The object to retrieve.
+ * @param string $attrs Restrict to these attributes.
+ *
+ * @return array An array of attributes.
+ *
+ * @throws Horde_Kolab_Server_Exception
+ *
+ * @see Horde_Kolab_Server::read
+ */
+ public function readAttributes($guid, array $attrs)
+ {
+ return $this->_server->readAttributes($guid, $attrs);
+ }
+
+ /**
+ * Finds object data matching a given set of criteria.
+ *
+ * @param Horde_Kolab_Server_Query $query The criteria for the search.
+ * @param array $params Additional search parameters.
+ *
+ * @return Horde_Kolab_Server_Result The result object.
+ *
+ * @throws Horde_Kolab_Server_Exception
+ */
+ public function find(
+ Horde_Kolab_Server_Query $query,
+ array $params = array()
+ ) {
+ return $this->_server->find($query, $params);
+ }
+
+ /**
+ * Finds all object data below a parent matching a given set of criteria.
+ *
+ * @param Horde_Kolab_Server_Query $query The criteria for the search.
+ * @param string $parent The parent to search below.
+ * @param array $params Additional search parameters.
+ *
+ * @return Horde_Kolab_Server_Result The result object.
+ *
+ * @throws Horde_Kolab_Server_Exception
+ */
+ public function findBelow(
+ Horde_Kolab_Server_Query $query,
+ $parent,
+ array $params = array()
+ ) {
+ return $this->_server->findBelow($query, $parent, $params);
+ }
+
+ /**
+ * Modify existing object data.
+ *
+ * @param string $guid The GUID of the object to be added.
+ * @param array $data The attributes of the object to be added.
+ *
+ * @return NULL
+ *
+ * @throws Horde_Kolab_Server_Exception
+ */
+ public function save($guid, array $data)
+ {
+ $this->_server->save($guid, $data);
+ $this->_logger->info(
+ sprintf("The object \"%s\" has been successfully saved!", $guid)
+ );
+ }
+
+ /**
+ * Add new object data.
+ *
+ * @param string $guid The GUID of the object to be added.
+ * @param array $data The attributes of the object to be added.
+ *
+ * @return NULL
+ *
+ * @throws Horde_Kolab_Server_Exception
+ */
+ public function add($guid, array $data)
+ {
+ $this->_server->add($guid, $data);
+ $this->_logger->info(
+ sprintf("The object \"%s\" has been successfully added!", $guid)
+ );
+ }
+
+ /**
+ * Delete an object.
+ *
+ * @param string $guid The GUID of the object to be deleted.
+ *
+ * @return NULL
+ *
+ * @throws Horde_Kolab_Server_Exception
+ */
+ public function delete($guid)
+ {
+ $this->_server->delete($guid);
+ $this->_logger->info(
+ sprintf("The object \"%s\" has been successfully deleted!", $guid)
+ );
+ }
+
+ /**
+ * Rename an object.
+ *
+ * @param string $guid The GUID of the object to be renamed.
+ * @param string $new The new GUID of the object.
+ *
+ * @return NULL
+ *
+ * @throws Horde_Kolab_Server_Exception
+ */
+ public function rename($guid, $new)
+ {
+ $this->_server->rename($guid, $new);
+ $this->_logger->info(
+ sprintf(
+ "The object \"%s\" has been successfully renamed to \"%s\"!",
+ $guid, $new
+ )
+ );
+ }
+
+ /**
+ * Return the ldap schema.
+ *
+ * @return Net_LDAP2_Schema The LDAP schema.
+ *
+ * @throws Horde_Kolab_Server_Exception If retrieval of the schema failed.
+ */
+ public function getSchema()
+ {
+ return $this->_server->getSchema();
+ }
+}
diff --git a/framework/Kolab_Server/lib/Horde/Kolab/Server/Mapped.php b/framework/Kolab_Server/lib/Horde/Kolab/Server/Mapped.php
new file mode 100644
index 000000000..5287b592d
--- /dev/null
+++ b/framework/Kolab_Server/lib/Horde/Kolab/Server/Mapped.php
@@ -0,0 +1,309 @@
+
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Kolab_Server
+ */
+
+/**
+ * A server delegation that maps object attributes.
+ *
+ * Copyright 2008-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 Kolab_Server
+ * @author Gunnar Wrobel
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Kolab_Server
+ */
+class Horde_Kolab_Server_Mapped implements Horde_Kolab_Server
+{
+ /**
+ * The server we delegate to.
+ *
+ * @var Horde_Kolab_Server
+ */
+ private $_server;
+
+ /**
+ * The attribute mapping.
+ *
+ * @var array
+ */
+ private $_mapping;
+
+ /**
+ * Constructor.
+ *
+ * @param Horde_Kolab_Server $server The base server connection.
+ * @param array $mapping The attribute mapping.
+ */
+ public function __construct(Horde_Kolab_Server $server, array $mapping)
+ {
+ $this->_server = $server;
+ $this->_mapping = $mapping;
+ }
+
+ /**
+ * Connect to the server. Use this method if the user name you can provide
+ * does not match a GUID. In this case it will be required to map this user
+ * name first.
+ *
+ * @param string $user The user name.
+ * @param string $pass The password.
+ *
+ * @return NULL.
+ *
+ * @throws Horde_Kolab_Server_Exception If the connection failed.
+ */
+ public function connect($user = null, $pass = null)
+ {
+ $this->_server->connect($user, $pass);
+ }
+
+ /**
+ * Connect to the server.
+ *
+ * @param string $guid The global unique id of the user.
+ * @param string $pass The password.
+ *
+ * @return NULL.
+ *
+ * @throws Horde_Kolab_Server_Exception If the connection failed.
+ */
+ public function connectGuid($guid = null, $pass = null)
+ {
+ $this->_server->connectGuid($guid, $pass);
+ }
+
+ /**
+ * Low level access to reading object data.
+ *
+ * @param string $guid The object to retrieve.
+ * @param array $attrs Restrict to these attributes.
+ *
+ * @return array An array of attributes.
+ *
+ * @throws Horde_Kolab_Server_Exception If the search operation hit an error
+ * or returned no result.
+ */
+ public function read($guid, array $attrs = array())
+ {
+ $data = $this->_server->read($guid);
+ $this->unmapAttributes($data);
+ return $data;
+ }
+
+ /**
+ * Low level access to reading some object attributes.
+ *
+ * @param string $guid The object to retrieve.
+ * @param string $attrs Restrict to these attributes.
+ *
+ * @return array An array of attributes.
+ *
+ * @throws Horde_Kolab_Server_Exception
+ *
+ * @see Horde_Kolab_Server::read
+ */
+ public function readAttributes($guid, array $attrs)
+ {
+ $this->mapKeys($attrs);
+ $data = $this->_server->readAttributes($guid, $attrs);
+ $this->unmapAttributes($data);
+ return $data;
+ }
+
+ /**
+ * Finds object data matching a given set of criteria.
+ *
+ * @param array $criteria The criteria for the search.
+ * @param array $params Additional search parameters.
+ *
+ * @return array The result array.
+ *
+ * @throws Horde_Kolab_Server_Exception
+ */
+ public function find(array $criteria, array $params = array())
+ {
+ $criteria = new Horde_Kolab_Server_Query_Element_Mapped($criteria, $this);
+ $data = $this->_server->find($criteria, $params);
+ $this->unmapAttributes($data);
+ return $data;
+ }
+
+ /**
+ * Finds all object data below a parent matching a given set of criteria.
+ *
+ * @param array $criteria The criteria for the search.
+ * @param string $parent The parent to search below.
+ * @param array $params Additional search parameters.
+ *
+ * @return array The result array.
+ *
+ * @throws Horde_Kolab_Server_Exception
+ */
+ public function findBelow(array $criteria, $parent, array $params = array())
+ {
+ $criteria = new Horde_Kolab_Server_Query_Element_Mapped($criteria, $this);
+ $data = $this->_server->findBelow($criteria, $parent, $params);
+ $this->unmapAttributes($data);
+ return $data;
+ }
+
+
+ /**
+ * Modify existing object data.
+ *
+ * @param string $guid The GUID of the object to be added.
+ * @param array $data The attributes of the object to be added.
+ *
+ * @return NULL
+ *
+ * @throws Horde_Kolab_Server_Exception
+ */
+ public function save($guid, array $data)
+ {
+ $this->mapAttributes($data);
+ $this->_server->save($guid, $data);
+ }
+
+ /**
+ * Add new object data.
+ *
+ * @param string $guid The GUID of the object to be added.
+ * @param array $data The attributes of the object to be added.
+ *
+ * @return NULL
+ *
+ * @throws Horde_Kolab_Server_Exception
+ */
+ public function add($guid, array $data)
+ {
+ $this->mapAttributes($data);
+ $this->_server->add($guid, $data);
+ }
+
+ /**
+ * Delete an object.
+ *
+ * @param string $guid The GUID of the object to be deleted.
+ *
+ * @return NULL
+ *
+ * @throws Horde_Kolab_Server_Exception
+ */
+ public function delete($guid)
+ {
+ $this->_server->delete($guid);
+ }
+
+ /**
+ * Rename an object.
+ *
+ * @param string $guid The GUID of the object to be renamed.
+ * @param string $new The new GUID of the object.
+ *
+ * @return NULL
+ *
+ * @throws Horde_Kolab_Server_Exception
+ */
+ public function rename($guid, $new)
+ {
+ $this->_server->rename($guid, $new);
+ }
+
+ /**
+ * Return the ldap schema.
+ *
+ * @return Net_LDAP2_Schema The LDAP schema.
+ *
+ * @throws Horde_Kolab_Server_Exception If retrieval of the schema failed.
+ */
+ public function getSchema()
+ {
+ return $this->_server->getSchema();
+ }
+
+
+ /**
+ * Map attributes defined within this library to their real world
+ * counterparts.
+ *
+ * @param array &$data The data that has been read and needs to be mapped.
+ *
+ * @return NULL
+ */
+ protected function unmapAttributes(&$data)
+ {
+ foreach ($data as &$element) {
+ foreach ($this->mapping as $attribute => $map) {
+ if (isset($element[$map])) {
+ $element[$attribute] = $element[$map];
+ unset($element[$map]);
+ }
+ }
+ }
+ }
+
+ /**
+ * Map attributes defined within this library into their real world
+ * counterparts.
+ *
+ * @param array &$data The data to be written.
+ *
+ * @return NULL
+ */
+ protected function mapAttributes(&$data)
+ {
+ foreach ($this->mapping as $attribute => $map) {
+ if (isset($data[$attribute])) {
+ $data[$map] = $data[$attribute];
+ unset($data[$attribute]);
+ }
+ }
+ }
+
+ /**
+ * Map attribute keys defined within this library into their real world
+ * counterparts.
+ *
+ * @param array &$keys The attribute keys.
+ *
+ * @return NULL
+ */
+ protected function mapKeys(&$keys)
+ {
+ foreach ($this->mapping as $attribute => $map) {
+ $key = array_search($attribute, $keys);
+ if ($key !== false) {
+ $keys[$key] = $map;
+ }
+ }
+ }
+
+ /**
+ * Map a single attribute key defined within this library into its real
+ * world counterpart.
+ *
+ * @param array $field The attribute name.
+ *
+ * @return The real name of this attribute on the server we connect to.
+ */
+ public function mapField($field)
+ {
+ if (isset($this->mapping[$field])) {
+ return $this->mapping[$field];
+ }
+ return $field;
+ }
+}
diff --git a/framework/Kolab_Server/lib/Horde/Kolab/Server/Object.php b/framework/Kolab_Server/lib/Horde/Kolab/Server/Object.php
index c2a5a7167..193c4cac9 100644
--- a/framework/Kolab_Server/lib/Horde/Kolab/Server/Object.php
+++ b/framework/Kolab_Server/lib/Horde/Kolab/Server/Object.php
@@ -916,6 +916,8 @@ class Horde_Kolab_Server_Object
*/
public function prepareChanges($info)
{
+ $changes = array();
+
if (!empty($this->attributes)) {
foreach ($info as $key => $value) {
if (!in_array($key, array_keys($this->attributes))) {
@@ -1020,7 +1022,7 @@ class Horde_Kolab_Server_Object
* meet the expectations.
*/
static protected function uidFromResult($result,
- $restrict = Horde_Kolab_Server::RESULT_SINGLE)
+ $restrict = Horde_Kolab_Server_Object::RESULT_SINGLE)
{
if (empty($result)) {
return false;
@@ -1053,7 +1055,7 @@ class Horde_Kolab_Server_Object
* meet the expectations.
*/
static protected function attrsFromResult($result, $attrs,
- $restrict = Horde_Kolab_Server::RESULT_SINGLE)
+ $restrict = Horde_Kolab_Server_Object::RESULT_SINGLE)
{
switch ($restrict) {
case self::RESULT_STRICT:
@@ -1101,7 +1103,7 @@ class Horde_Kolab_Server_Object
* @throws Horde_Kolab_Server_Exception
*/
static public function basicUidForSearch($server, $criteria,
- $restrict = Horde_Kolab_Server::RESULT_SINGLE)
+ $restrict = Horde_Kolab_Server_Object::RESULT_SINGLE)
{
$params = array('attributes' => self::ATTRIBUTE_UID);
$filter = $server->searchQuery($criteria);
@@ -1123,7 +1125,7 @@ class Horde_Kolab_Server_Object
* @throws Horde_Kolab_Server_Exception
*/
static public function attrsForSearch($server, $criteria, $attrs,
- $restrict = Horde_Kolab_Server::RESULT_SINGLE)
+ $restrict = Horde_Kolab_Server_Object::RESULT_SINGLE)
{
$params = array('attributes' => $attrs);
$filter = $server->searchQuery($criteria);
diff --git a/framework/Kolab_Server/lib/Horde/Kolab/Server/Object/Kolabgroupofnames.php b/framework/Kolab_Server/lib/Horde/Kolab/Server/Object/Kolabgroupofnames.php
index 1fd13d465..8604e8922 100644
--- a/framework/Kolab_Server/lib/Horde/Kolab/Server/Object/Kolabgroupofnames.php
+++ b/framework/Kolab_Server/lib/Horde/Kolab/Server/Object/Kolabgroupofnames.php
@@ -89,7 +89,7 @@ class Horde_Kolab_Server_Object_Kolabgroupofnames extends Horde_Kolab_Server_Obj
{
switch ($attr) {
case self::ATTRIBUTE_VISIBILITY:
- //FIXME: This needs structural knowledge and should be in a
+ //@todo This needs structural knowledge and should be in a
//structural class.
return strpos($this->uid, 'cn=internal') === false;
default:
diff --git a/framework/Kolab_Server/lib/Horde/Kolab/Server/Objects.php b/framework/Kolab_Server/lib/Horde/Kolab/Server/Objects.php
new file mode 100644
index 000000000..92aa7ce66
--- /dev/null
+++ b/framework/Kolab_Server/lib/Horde/Kolab/Server/Objects.php
@@ -0,0 +1,112 @@
+
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Kolab_Server
+ */
+
+/**
+ * Interface for a server object list.
+ *
+ * Copyright 2008-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 Kolab_Server
+ * @author Gunnar Wrobel
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Kolab_Server
+ */
+interface Horde_Kolab_Server_Objects
+{
+ /**
+ * Add a Kolab object.
+ *
+ * @param array $info The object to store.
+ *
+ * @return Kolab_Object The newly created Kolab object.
+ *
+ * @throws Horde_Kolab_Server_Exception If the type of the object to add has
+ * been left undefined or the object
+ * already exists.
+ */
+ public function add(array $info);
+
+ /**
+ * Fetch a Kolab object.
+ *
+ * This method will not retrieve any data from the server
+ * immediately. Instead it will simply generate a new instance for the
+ * desired object.
+ *
+ * The server data will only be accessed once you start reading the object
+ * data.
+ *
+ * This method can also be used in order to fetch non-existing objects that
+ * will be saved later. This is however not recommended and you should
+ * rather use the add($info) method for that.
+ *
+ * If you do not provide the object type the server will try to determine it
+ * automatically based on the uid. As this requires reading data from the
+ * server it is recommended to specify the object type whenever it is known.
+ *
+ * If you do not specify a uid the object corresponding to the user bound to
+ * the server will be returned.
+ *
+ * @param string $uid The UID of the object to fetch.
+ * @param string $type The type of the object to fetch.
+ *
+ * @return Kolab_Object The corresponding Kolab object.
+ *
+ * @throws Horde_Kolab_Server_Exception
+ */
+ public function fetch($uid = null, $type = null);
+
+ /**
+ * List all objects of a specific type
+ *
+ * @param string $type The type of the objects to be listed
+ * @param array $params Additional parameters.
+ *
+ * @return array An array of Kolab objects.
+ *
+ * @throws Horde_Kolab_Server_Exception
+ */
+ public function listObjects($type, $params = null);
+
+ /**
+ * Generate a hash representation for a list of objects.
+ *
+ * The approach taken here is somewhat slow as the server data gets fetched
+ * into objects first which are then converted to hashes again. Since a
+ * server search will usually deliver the result as a hash the intermediate
+ * object conversion is inefficient.
+ *
+ * But as the object classes are able to treat the attributes returned from
+ * the server with custom parsing, this is currently the preferred
+ * method. Especially for large result sets it would be better if this
+ * method would call a static object class function that operate on the
+ * result array returned from the server without using objects.
+ *
+ * @param string $type The type of the objects to be listed
+ * @param array $params Additional parameters.
+ *
+ * @return array An array of Kolab objects.
+ *
+ * @throws Horde_Kolab_Server_Exception
+ *
+ * @todo The LDAP driver needs a more efficient version of this call as it
+ * is not required to generate objects before returning data as a
+ * hash. It can be derived directly from the LDAP result.
+ */
+ public function listHash($type, $params = null);
+
+}
\ No newline at end of file
diff --git a/framework/Kolab_Server/lib/Horde/Kolab/Server/Objects/Base.php b/framework/Kolab_Server/lib/Horde/Kolab/Server/Objects/Base.php
new file mode 100644
index 000000000..63636e547
--- /dev/null
+++ b/framework/Kolab_Server/lib/Horde/Kolab/Server/Objects/Base.php
@@ -0,0 +1,243 @@
+
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Kolab_Server
+ */
+
+/**
+ * This class provides methods to deal with Kolab objects stored in
+ * the Kolab object db.
+ *
+ * Copyright 2008-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 Kolab_Server
+ * @author Gunnar Wrobel
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Kolab_Server
+ */
+class Horde_Kolab_Server_Objects_Base implements Horde_Kolab_Server_Objects
+{
+ /**
+ * A link to the server handler.
+ *
+ * @var Horde_Kolab_Server
+ */
+ protected $server;
+
+ /**
+ * Set the server reference for this object.
+ *
+ * @param Horde_Kolab_Server &$server A link to the server handler.
+ */
+ public function setServer($server)
+ {
+ $this->server = $server;
+ }
+
+ /**
+ * Fetch a Kolab object.
+ *
+ * This method will not retrieve any data from the server
+ * immediately. Instead it will simply generate a new instance for the
+ * desired object.
+ *
+ * The server data will only be accessed once you start reading the object
+ * data.
+ *
+ * This method can also be used in order to fetch non-existing objects that
+ * will be saved later. This is however not recommended and you should
+ * rather use the add($info) method for that.
+ *
+ * If you do not provide the object type the server will try to determine it
+ * automatically based on the uid. As this requires reading data from the
+ * server it is recommended to specify the object type whenever it is known.
+ *
+ * If you do not specify a uid the object corresponding to the user bound to
+ * the server will be returned.
+ *
+ * @param string $uid The UID of the object to fetch.
+ * @param string $type The type of the object to fetch.
+ *
+ * @return Kolab_Object The corresponding Kolab object.
+ *
+ * @throws Horde_Kolab_Server_Exception
+ */
+ public function fetch($uid = null, $type = null)
+ {
+ if (!isset($uid)) {
+ $uid = $this->uid;
+ }
+ if (empty($type)) {
+ $type = $this->determineType($uid);
+ }
+
+ $object = &Horde_Kolab_Server_Object::factory($type, $uid, $this);
+ return $object;
+ }
+
+ /**
+ * Add a Kolab object.
+ *
+ * @param array $info The object to store.
+ *
+ * @return Kolab_Object The newly created Kolab object.
+ *
+ * @throws Horde_Kolab_Server_Exception If the type of the object to add has
+ * been left undefined or the object
+ * already exists.
+ */
+ public function add(array $info)
+ {
+ if (!isset($info['type'])) {
+ throw new Horde_Kolab_Server_Exception(
+ 'The type of a new object must be specified!');
+ }
+
+ $type = $info['type'];
+ unset($info['type']);
+ $object = &Horde_Kolab_Server_Object::factory($type, null, $this, $info);
+ if ($object->exists()) {
+ throw new Horde_Kolab_Server_Exception(
+ sprintf(_("The object with the uid \"%s\" does already exist!"),
+ $object->get(Horde_Kolab_Server_Object::ATTRIBUTE_UID)));
+ }
+ $object->save();
+ return $object;
+ }
+
+ /**
+ * Generate a hash representation for a list of objects.
+ *
+ * The approach taken here is somewhat slow as the server data gets fetched
+ * into objects first which are then converted to hashes again. Since a
+ * server search will usually deliver the result as a hash the intermediate
+ * object conversion is inefficient.
+ *
+ * But as the object classes are able to treat the attributes returned from
+ * the server with custom parsing, this is currently the preferred
+ * method. Especially for large result sets it would be better if this
+ * method would call a static object class function that operate on the
+ * result array returned from the server without using objects.
+ *
+ * @param string $type The type of the objects to be listed
+ * @param array $params Additional parameters.
+ *
+ * @return array An array of Kolab objects.
+ *
+ * @throws Horde_Kolab_Server_Exception
+ *
+ * @todo The LDAP driver needs a more efficient version of this call as it
+ * is not required to generate objects before returning data as a
+ * hash. It can be derived directly from the LDAP result.
+ */
+ public function listHash($type, $params = null)
+ {
+ $list = $this->listObjects($type, $params);
+
+ if (isset($params['attributes'])) {
+ $attributes = $params['attributes'];
+ } else {
+ $attributes = null;
+ }
+
+ $hash = array();
+ foreach ($list as $uid => $entry) {
+ $hash[$uid] = $entry->toHash($attributes);
+ }
+
+ return $hash;
+ }
+
+
+ /**
+ * List all objects of a specific type.
+ *
+ * @param string $type The type of the objects to be listed
+ * @param array $params Additional parameters.
+ *
+ * @return array An array of Kolab objects.
+ *
+ * @throws Horde_Kolab_Server_Exception
+ *
+ * @todo Sorting
+ * @todo Is this LDAP specific?
+ */
+ public function listObjects($type, $params = null)
+ {
+ if (empty($params['base_dn'])) {
+ $base = $this->_base_dn;
+ } else {
+ $base = $params['base_dn'];
+ }
+
+ $result = Horde_Kolab_Server_Object::loadClass($type);
+ $vars = get_class_vars($type);
+ $criteria = call_user_func(array($type, 'getFilter'));
+ $filter = $this->searchQuery($criteria);
+ $sort = $vars['sort_by'];
+
+ if (isset($params['sort'])) {
+ $sort = $params['sort'];
+ }
+
+ $options = array('scope' => 'sub');
+ if (isset($params['attributes'])) {
+ $options['attributes'] = $params['attributes'];
+ } else {
+ $options['attributes'] = $this->getAttributes($type);
+ }
+
+ $data = $this->search($filter, $options, $base);
+ if (empty($data)) {
+ return array();
+ }
+
+ if ($sort) {
+ /* FIXME */
+ /* $data = $result->as_sorted_struct(); */
+ /*$this->sort($result, $sort); */
+ }
+
+ if (isset($params['from'])) {
+ $from = $params['from'];
+ } else {
+ $from = -1;
+ }
+
+ if (isset($params['to'])) {
+ $sort = $params['to'];
+ } else {
+ $to = -1;
+ }
+
+ if (!empty($vars['required_group'])) {
+ $required_group = new Horde_Kolab_Server_Object_Kolabgroupofnames($this,
+ null,
+ $vars['required_group']);
+ }
+
+ $objects = array();
+ foreach ($data as $uid => $entry) {
+ if (!empty($vars['required_group'])) {
+ if (!$required_group->exists() || !$required_group->isMember($uid)) {
+ continue;
+ }
+ }
+ $objects[$uid] = &Horde_Kolab_Server_Object::factory($type, $uid,
+ $this, $entry);
+ }
+ return $objects;
+ }
+
+}
\ No newline at end of file
diff --git a/framework/Kolab_Server/lib/Horde/Kolab/Server/Query.php b/framework/Kolab_Server/lib/Horde/Kolab/Server/Query.php
new file mode 100644
index 000000000..706e2ebd1
--- /dev/null
+++ b/framework/Kolab_Server/lib/Horde/Kolab/Server/Query.php
@@ -0,0 +1,126 @@
+
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Kolab_Server
+ */
+
+/**
+ * Interface for server queries.
+ *
+ * Copyright 2008-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 Kolab_Server
+ * @author Gunnar Wrobel
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Kolab_Server
+ */
+interface Horde_Kolab_Server_Query
+{
+ /**
+ * Return the query as a string.
+ *
+ * @return string The query in string format.
+ */
+ public function __toString();
+
+ /**
+ * Convert the equals element to query format.
+ *
+ * @param Horde_Kolab_Server_Query_Element_Single $single The element to convert.
+ *
+ * @return mixed The query element in query format.
+ */
+ public function convertEquals(Horde_Kolab_Server_Query_Element_Equals $equals);
+
+ /**
+ * Convert the begins element to query format.
+ *
+ * @param Horde_Kolab_Server_Query_Element_Single $single The element to convert.
+ *
+ * @return mixed The query element in query format.
+ */
+ public function convertBegins(Horde_Kolab_Server_Query_Element_Begins $begins);
+
+ /**
+ * Convert the ends element to query format.
+ *
+ * @param Horde_Kolab_Server_Query_Element_Single $single The element to convert.
+ *
+ * @return mixed The query element in query format.
+ */
+ public function convertEnds(Horde_Kolab_Server_Query_Element_Ends $ends);
+
+ /**
+ * Convert the contains element to query format.
+ *
+ * @param Horde_Kolab_Server_Query_Element_Single $single The element to convert.
+ *
+ * @return mixed The query element in query format.
+ */
+ public function convertContains(Horde_Kolab_Server_Query_Element_Contains $contains);
+
+ /**
+ * Convert the less element to query format.
+ *
+ * @param Horde_Kolab_Server_Query_Element_Single $single The element to convert.
+ *
+ * @return mixed The query element in query format.
+ */
+ public function convertLess(Horde_Kolab_Server_Query_Element_Less $less);
+
+ /**
+ * Convert the greater element to query format.
+ *
+ * @param Horde_Kolab_Server_Query_Element_Single $single The element to convert.
+ *
+ * @return mixed The query element in query format.
+ */
+ public function convertGreater(Horde_Kolab_Server_Query_Element_Greater $greater);
+
+ /**
+ * Convert the approx element to query format.
+ *
+ * @param Horde_Kolab_Server_Query_Element_Single $single The element to convert.
+ *
+ * @return mixed The query element in query format.
+ */
+ public function convertApprox(Horde_Kolab_Server_Query_Element_Approx $approx);
+
+ /**
+ * Convert the not element to query format.
+ *
+ * @param Horde_Kolab_Server_Query_Element_Group $group The element to convert.
+ *
+ * @return mixed The query element in query format.
+ */
+ public function convertNot(Horde_Kolab_Server_Query_Element_Not $not);
+
+ /**
+ * Convert the and element to query format.
+ *
+ * @param Horde_Kolab_Server_Query_Element_Group $group The element to convert.
+ *
+ * @return mixed The query element in query format.
+ */
+ public function convertAnd(Horde_Kolab_Server_Query_Element_And $and);
+
+ /**
+ * Convert the or element to query format.
+ *
+ * @param Horde_Kolab_Server_Query_Element_Group $group The element to convert.
+ *
+ * @return mixed The query element in query format.
+ */
+ public function convertOr(Horde_Kolab_Server_Query_Element_Group $or);
+}
\ No newline at end of file
diff --git a/framework/Kolab_Server/lib/Horde/Kolab/Server/Query/Element.php b/framework/Kolab_Server/lib/Horde/Kolab/Server/Query/Element.php
new file mode 100644
index 000000000..3071c6a96
--- /dev/null
+++ b/framework/Kolab_Server/lib/Horde/Kolab/Server/Query/Element.php
@@ -0,0 +1,58 @@
+
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Kolab_Server
+ */
+
+/**
+ * Interface for server query elements.
+ *
+ * Copyright 2008-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 Kolab_Server
+ * @author Gunnar Wrobel
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Kolab_Server
+ */
+interface Horde_Kolab_Server_Query_Element
+{
+ /**
+ * Return the query element name.
+ *
+ * @return string The name of the query element.
+ */
+ public function getName();
+
+ /**
+ * Return the value of this element.
+ *
+ * @return mixed The query value.
+ */
+ public function getValue();
+
+ /**
+ * Return the elements of this group.
+ *
+ * @return mixed The group elements.
+ */
+ public function getElements();
+
+ /**
+ * Convert this element to a query element.
+ *
+ * @return mixedd The element as query.
+ */
+ public function convert(Horde_Kolab_Server_Query $writer);
+
+}
\ No newline at end of file
diff --git a/framework/Kolab_Server/lib/Horde/Kolab/Server/Query/Element/And.php b/framework/Kolab_Server/lib/Horde/Kolab/Server/Query/Element/And.php
new file mode 100644
index 000000000..abe52bacd
--- /dev/null
+++ b/framework/Kolab_Server/lib/Horde/Kolab/Server/Query/Element/And.php
@@ -0,0 +1,40 @@
+
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Kolab_Server
+ */
+
+/**
+ * An element grouping by and.
+ *
+ * Copyright 2008-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 Kolab_Server
+ * @author Gunnar Wrobel
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Kolab_Server
+ */
+class Horde_Kolab_Server_Query_Element_And
+extends Horde_Kolab_Server_Query_Element_Group
+{
+ /**
+ * Convert this element to a query element.
+ *
+ * @return mixed The element as query.
+ */
+ public function convert(Horde_Kolab_Server_Query $writer)
+ {
+ return $writer->convertAnd($this);
+ }
+}
\ No newline at end of file
diff --git a/framework/Kolab_Server/lib/Horde/Kolab/Server/Query/Element/Approx.php b/framework/Kolab_Server/lib/Horde/Kolab/Server/Query/Element/Approx.php
new file mode 100644
index 000000000..486ce564c
--- /dev/null
+++ b/framework/Kolab_Server/lib/Horde/Kolab/Server/Query/Element/Approx.php
@@ -0,0 +1,40 @@
+
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Kolab_Server
+ */
+
+/**
+ * An element expressing an 'approx' match.
+ *
+ * Copyright 2008-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 Kolab_Server
+ * @author Gunnar Wrobel
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Kolab_Server
+ */
+class Horde_Kolab_Server_Query_Element_Approx
+extends Horde_Kolab_Server_Query_Element_Single
+{
+ /**
+ * Convert this element to a query element.
+ *
+ * @return mixed The element as query.
+ */
+ public function convert(Horde_Kolab_Server_Query $writer)
+ {
+ return $writer->convertApprox($this);
+ }
+}
\ No newline at end of file
diff --git a/framework/Kolab_Server/lib/Horde/Kolab/Server/Query/Element/Begins.php b/framework/Kolab_Server/lib/Horde/Kolab/Server/Query/Element/Begins.php
new file mode 100644
index 000000000..3686bc373
--- /dev/null
+++ b/framework/Kolab_Server/lib/Horde/Kolab/Server/Query/Element/Begins.php
@@ -0,0 +1,40 @@
+
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Kolab_Server
+ */
+
+/**
+ * An element expressing an 'begins' match.
+ *
+ * Copyright 2008-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 Kolab_Server
+ * @author Gunnar Wrobel
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Kolab_Server
+ */
+class Horde_Kolab_Server_Query_Element_Begins
+extends Horde_Kolab_Server_Query_Element_Single
+{
+ /**
+ * Convert this element to a query element.
+ *
+ * @return mixed The element as query.
+ */
+ public function convert(Horde_Kolab_Server_Query $writer)
+ {
+ return $writer->convertBegins($this);
+ }
+}
\ No newline at end of file
diff --git a/framework/Kolab_Server/lib/Horde/Kolab/Server/Query/Element/Contains.php b/framework/Kolab_Server/lib/Horde/Kolab/Server/Query/Element/Contains.php
new file mode 100644
index 000000000..224d187f6
--- /dev/null
+++ b/framework/Kolab_Server/lib/Horde/Kolab/Server/Query/Element/Contains.php
@@ -0,0 +1,40 @@
+
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Kolab_Server
+ */
+
+/**
+ * An element expressing an 'contains' match.
+ *
+ * Copyright 2008-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 Kolab_Server
+ * @author Gunnar Wrobel
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Kolab_Server
+ */
+class Horde_Kolab_Server_Query_Element_Contains
+extends Horde_Kolab_Server_Query_Element_Single
+{
+ /**
+ * Convert this element to a query element.
+ *
+ * @return mixed The element as query.
+ */
+ public function convert(Horde_Kolab_Server_Query $writer)
+ {
+ return $writer->convertContains($this);
+ }
+}
\ No newline at end of file
diff --git a/framework/Kolab_Server/lib/Horde/Kolab/Server/Query/Element/Ends.php b/framework/Kolab_Server/lib/Horde/Kolab/Server/Query/Element/Ends.php
new file mode 100644
index 000000000..742f9ba68
--- /dev/null
+++ b/framework/Kolab_Server/lib/Horde/Kolab/Server/Query/Element/Ends.php
@@ -0,0 +1,40 @@
+
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Kolab_Server
+ */
+
+/**
+ * An element expressing an 'ends' match.
+ *
+ * Copyright 2008-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 Kolab_Server
+ * @author Gunnar Wrobel
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Kolab_Server
+ */
+class Horde_Kolab_Server_Query_Element_Ends
+extends Horde_Kolab_Server_Query_Element_Single
+{
+ /**
+ * Convert this element to a query element.
+ *
+ * @return mixed The element as query.
+ */
+ public function convert(Horde_Kolab_Server_Query $writer)
+ {
+ return $writer->convertEnds($this);
+ }
+}
\ No newline at end of file
diff --git a/framework/Kolab_Server/lib/Horde/Kolab/Server/Query/Element/Equals.php b/framework/Kolab_Server/lib/Horde/Kolab/Server/Query/Element/Equals.php
new file mode 100644
index 000000000..c8164ae67
--- /dev/null
+++ b/framework/Kolab_Server/lib/Horde/Kolab/Server/Query/Element/Equals.php
@@ -0,0 +1,40 @@
+
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Kolab_Server
+ */
+
+/**
+ * An element expressing an 'equals' match.
+ *
+ * Copyright 2008-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 Kolab_Server
+ * @author Gunnar Wrobel
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Kolab_Server
+ */
+class Horde_Kolab_Server_Query_Element_Equals
+extends Horde_Kolab_Server_Query_Element_Single
+{
+ /**
+ * Convert this element to a query element.
+ *
+ * @return mixed The element as query.
+ */
+ public function convert(Horde_Kolab_Server_Query $writer)
+ {
+ return $writer->convertEquals($this);
+ }
+}
\ No newline at end of file
diff --git a/framework/Kolab_Server/lib/Horde/Kolab/Server/Query/Element/Greater.php b/framework/Kolab_Server/lib/Horde/Kolab/Server/Query/Element/Greater.php
new file mode 100644
index 000000000..a7f843cbd
--- /dev/null
+++ b/framework/Kolab_Server/lib/Horde/Kolab/Server/Query/Element/Greater.php
@@ -0,0 +1,40 @@
+
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Kolab_Server
+ */
+
+/**
+ * An element expressing an 'greater' match.
+ *
+ * Copyright 2008-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 Kolab_Server
+ * @author Gunnar Wrobel
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Kolab_Server
+ */
+class Horde_Kolab_Server_Query_Element_Greater
+extends Horde_Kolab_Server_Query_Element_Single
+{
+ /**
+ * Convert this element to a query element.
+ *
+ * @return mixed The element as query.
+ */
+ public function convert(Horde_Kolab_Server_Query $writer)
+ {
+ return $writer->convertGreater($this);
+ }
+}
\ No newline at end of file
diff --git a/framework/Kolab_Server/lib/Horde/Kolab/Server/Query/Element/Group.php b/framework/Kolab_Server/lib/Horde/Kolab/Server/Query/Element/Group.php
new file mode 100644
index 000000000..d861d1a61
--- /dev/null
+++ b/framework/Kolab_Server/lib/Horde/Kolab/Server/Query/Element/Group.php
@@ -0,0 +1,81 @@
+
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Kolab_Server
+ */
+
+/**
+ * A grouped query element.
+ *
+ * Copyright 2008-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 Kolab_Server
+ * @author Gunnar Wrobel
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Kolab_Server
+ */
+abstract class Horde_Kolab_Server_Query_Element_Group
+implements Horde_Kolab_Server_Query_Element
+{
+ /**
+ * The group elements.
+ *
+ * @var array
+ */
+ protected $_elements;
+
+ /**
+ * Constructor.
+ *
+ * @param array $elements The group elements.
+ */
+ public function __construct(array $elements)
+ {
+ $this->_elements = $elements;
+ }
+
+ /**
+ * Return the query element name.
+ *
+ * This should never be called for group elements.
+ *
+ * @return string The name of the query element.
+ */
+ public function getName()
+ {
+ throw new Exception('Not supported!');
+ }
+
+ /**
+ * Return the value of this element.
+ *
+ * This should never be called for group elements.
+ *
+ * @return mixed The query value.
+ */
+ public function getValue()
+ {
+ throw new Exception('Not supported!');
+ }
+
+ /**
+ * Return the elements of this group.
+ *
+ * @return mixed The group elements.
+ */
+ public function getElements()
+ {
+ return $this->_elements;
+ }
+}
\ No newline at end of file
diff --git a/framework/Kolab_Server/lib/Horde/Kolab/Server/Query/Element/Less.php b/framework/Kolab_Server/lib/Horde/Kolab/Server/Query/Element/Less.php
new file mode 100644
index 000000000..00df41fb2
--- /dev/null
+++ b/framework/Kolab_Server/lib/Horde/Kolab/Server/Query/Element/Less.php
@@ -0,0 +1,40 @@
+
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Kolab_Server
+ */
+
+/**
+ * An element expressing an 'less' match.
+ *
+ * Copyright 2008-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 Kolab_Server
+ * @author Gunnar Wrobel
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Kolab_Server
+ */
+class Horde_Kolab_Server_Query_Element_Less
+extends Horde_Kolab_Server_Query_Element_Single
+{
+ /**
+ * Convert this element to a query element.
+ *
+ * @return mixed The element as query.
+ */
+ public function convert(Horde_Kolab_Server_Query $writer)
+ {
+ return $writer->convertLess($this);
+ }
+}
\ No newline at end of file
diff --git a/framework/Kolab_Server/lib/Horde/Kolab/Server/Query/Element/Mapped.php b/framework/Kolab_Server/lib/Horde/Kolab/Server/Query/Element/Mapped.php
new file mode 100644
index 000000000..2cd6123f8
--- /dev/null
+++ b/framework/Kolab_Server/lib/Horde/Kolab/Server/Query/Element/Mapped.php
@@ -0,0 +1,104 @@
+
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Kolab_Server
+ */
+
+/**
+ * A mapped query element.
+ *
+ * Copyright 2008-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 Kolab_Server
+ * @author Gunnar Wrobel
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Kolab_Server
+ */
+class Horde_Kolab_Server_Query_Element_Mapped
+implements Horde_Kolab_Server_Query_Element
+{
+ /**
+ * Delegated element.
+ *
+ * @var Horde_Kolab_Server_Query_Element
+ */
+ private $_element;
+
+ /**
+ * Name mapper.
+ *
+ * @var Horde_Kolab_Server_Mapped
+ */
+ private $_mapper;
+
+ /**
+ * Constructor.
+ *
+ * @param Horde_Kolab_Server_Query_Element $element The mapped element.
+ * @param Horde_Kolab_Server_Mapped $mapper The mapping handler.
+ */
+ public function __construct(
+ Horde_Kolab_Server_Query_Element $element,
+ Horde_Kolab_Server_Mapped $mapper
+ ) {
+ $this->_element = $element;
+ $this->_mapper = $mapper;
+ }
+
+ /**
+ * Return the query element name.
+ *
+ * @return string The name of the query element.
+ */
+ public function getName()
+ {
+ return $this->_mapper->mapField($this->_element->getName());
+ }
+
+ /**
+ * Return the value of this element.
+ *
+ * @return mixed The query value.
+ */
+ public function getValue()
+ {
+ return $this->_element->getValue();
+ }
+
+ /**
+ * Return the elements of this group.
+ *
+ * @return mixed The group elements.
+ */
+ public function getElements()
+ {
+ $elements = array();
+ foreach ($this->_element->getElements() as $element) {
+ $elements[] = new Horde_Kolab_Server_Query_Element_Mapped(
+ $element, $this->_mapper
+ );
+ }
+ return $elements;
+ }
+
+ /**
+ * Convert this element to a string.
+ *
+ * @return string The query string of the element.
+ */
+ public function convert(Horde_Kolab_Server_Query $writer)
+ {
+ return $this->_element->convert($writer);
+ }
+}
\ No newline at end of file
diff --git a/framework/Kolab_Server/lib/Horde/Kolab/Server/Query/Element/Not.php b/framework/Kolab_Server/lib/Horde/Kolab/Server/Query/Element/Not.php
new file mode 100644
index 000000000..2f7340de5
--- /dev/null
+++ b/framework/Kolab_Server/lib/Horde/Kolab/Server/Query/Element/Not.php
@@ -0,0 +1,49 @@
+
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Kolab_Server
+ */
+
+/**
+ * A negating element.
+ *
+ * Copyright 2008-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 Kolab_Server
+ * @author Gunnar Wrobel
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Kolab_Server
+ */
+class Horde_Kolab_Server_Query_Element_Not
+extends Horde_Kolab_Server_Query_Element_Group
+{
+ /**
+ * Constructor.
+ *
+ * @param array $elements The group elements.
+ */
+ public function __construct(Horde_Kolab_Server_Query_Element $element) {
+ parent::__construct(array($element));
+ }
+
+ /**
+ * Convert this element to a query element.
+ *
+ * @return mixed The element as query.
+ */
+ public function convert(Horde_Kolab_Server_Query $writer)
+ {
+ return $writer->convertNot($this);
+ }
+}
\ No newline at end of file
diff --git a/framework/Kolab_Server/lib/Horde/Kolab/Server/Query/Element/Or.php b/framework/Kolab_Server/lib/Horde/Kolab/Server/Query/Element/Or.php
new file mode 100644
index 000000000..6e89b2892
--- /dev/null
+++ b/framework/Kolab_Server/lib/Horde/Kolab/Server/Query/Element/Or.php
@@ -0,0 +1,40 @@
+
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Kolab_Server
+ */
+
+/**
+ * An element grouping by or.
+ *
+ * Copyright 2008-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 Kolab_Server
+ * @author Gunnar Wrobel
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Kolab_Server
+ */
+class Horde_Kolab_Server_Query_Element_Or
+extends Horde_Kolab_Server_Query_Element_Group
+{
+ /**
+ * Convert this element to a query element.
+ *
+ * @return mixed The element as query.
+ */
+ public function convert(Horde_Kolab_Server_Query $writer)
+ {
+ return $writer->convertOr($this);
+ }
+}
\ No newline at end of file
diff --git a/framework/Kolab_Server/lib/Horde/Kolab/Server/Query/Element/Single.php b/framework/Kolab_Server/lib/Horde/Kolab/Server/Query/Element/Single.php
new file mode 100644
index 000000000..59b6cc576
--- /dev/null
+++ b/framework/Kolab_Server/lib/Horde/Kolab/Server/Query/Element/Single.php
@@ -0,0 +1,88 @@
+
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Kolab_Server
+ */
+
+/**
+ * A single query element.
+ *
+ * Copyright 2008-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 Kolab_Server
+ * @author Gunnar Wrobel
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Kolab_Server
+ */
+abstract class Horde_Kolab_Server_Query_Element_Single
+implements Horde_Kolab_Server_Query_Element
+{
+ /**
+ * The element name.
+ *
+ * @var string
+ */
+ protected $_name;
+
+ /**
+ * The comparison value.
+ *
+ * @var mixed
+ */
+ protected $_value;
+
+ /**
+ * Constructor.
+ *
+ * @param string $name The element name.
+ * @param mixed $value The comparison value.
+ */
+ public function __construct($name, $value)
+ {
+ $this->_name = $name;
+ $this->_value = $value;
+ }
+
+ /**
+ * Return the query element name.
+ *
+ * @return string The name of the query element.
+ */
+ public function getName()
+ {
+ return $this->_name;
+ }
+
+ /**
+ * Return the value of this element.
+ *
+ * @return mixed The query value.
+ */
+ public function getValue()
+ {
+ return $this->_value;
+ }
+
+ /**
+ * Return the elements of this group.
+ *
+ * This should never be called for single elements.
+ *
+ * @return mixed The group elements.
+ */
+ public function getElements()
+ {
+ throw new Exception('Not supported!');
+ }
+}
\ No newline at end of file
diff --git a/framework/Kolab_Server/lib/Horde/Kolab/Server/Query/Ldap.php b/framework/Kolab_Server/lib/Horde/Kolab/Server/Query/Ldap.php
new file mode 100644
index 000000000..e90f995ec
--- /dev/null
+++ b/framework/Kolab_Server/lib/Horde/Kolab/Server/Query/Ldap.php
@@ -0,0 +1,268 @@
+
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Kolab_Server
+ */
+
+/**
+ * Handler for LDAP server queries.
+ *
+ * Copyright 2008-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 Kolab_Server
+ * @author Gunnar Wrobel
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Kolab_Server
+ */
+class Horde_Kolab_Server_Query_Ldap implements Horde_Kolab_Server_Query
+{
+ /**
+ * The query criteria.
+ *
+ * @var Horde_Kolab_Server_Query_Element
+ */
+ private $_criteria;
+
+ /**
+ * Constructor.
+ *
+ * @param array $criteria The query criteria.
+ */
+ public function __construct(Horde_Kolab_Server_Query_Element $criteria)
+ {
+ $this->_criteria = $criteria;
+ }
+
+ /**
+ * Return the query as a string.
+ *
+ * @return string The query in string format.
+ *
+ * @throws Horde_Kolab_Server_Exception If the query is malformed.
+ */
+ public function __toString()
+ {
+ $filter = $this->_criteria->convert($this);
+ return $filter->asString();
+ }
+
+ /**
+ * Convert the equals element to query format.
+ *
+ * @param Horde_Kolab_Server_Query_Element_Equals $equals The element to convert.
+ *
+ * @return mixed The query element in query format.
+ *
+ * @throws Horde_Kolab_Server_Exception If the query is malformed.
+ */
+ public function convertEquals(Horde_Kolab_Server_Query_Element_Equals $equals)
+ {
+ return $this->_convertSingle($equals, 'equals');
+ }
+
+ /**
+ * Convert the begins element to query format.
+ *
+ * @param Horde_Kolab_Server_Query_Element_Begins $begins The element to convert.
+ *
+ * @return mixed The query element in query format.
+ *
+ * @throws Horde_Kolab_Server_Exception If the query is malformed.
+ */
+ public function convertBegins(Horde_Kolab_Server_Query_Element_Begins $begins)
+ {
+ return $this->_convertSingle($begins, 'begins');
+ }
+
+ /**
+ * Convert the ends element to query format.
+ *
+ * @param Horde_Kolab_Server_Query_Element_Ends $ends The element to convert.
+ *
+ * @return mixed The query element in query format.
+ *
+ * @throws Horde_Kolab_Server_Exception If the query is malformed.
+ */
+ public function convertEnds(Horde_Kolab_Server_Query_Element_Ends $ends)
+ {
+ return $this->_convertSingle($ends, 'ends');
+ }
+
+ /**
+ * Convert the contains element to query format.
+ *
+ * @param Horde_Kolab_Server_Query_Element_Contains $contains The element to convert.
+ *
+ * @return mixed The query element in query format.
+ *
+ * @throws Horde_Kolab_Server_Exception If the query is malformed.
+ */
+ public function convertContains(Horde_Kolab_Server_Query_Element_Contains $contains)
+ {
+ return $this->_convertSingle($contains, 'contains');
+ }
+
+ /**
+ * Convert the less element to query format.
+ *
+ * @param Horde_Kolab_Server_Query_Element_Less $less The element to convert.
+ *
+ * @return mixed The query element in query format.
+ *
+ * @throws Horde_Kolab_Server_Exception If the query is malformed.
+ */
+ public function convertLess(Horde_Kolab_Server_Query_Element_Less $less)
+ {
+ return $this->_convertSingle($less, 'less');
+ }
+
+ /**
+ * Convert the greater element to query format.
+ *
+ * @param Horde_Kolab_Server_Query_Element_Grater $grater The element to convert.
+ *
+ * @return mixed The query element in query format.
+ *
+ * @throws Horde_Kolab_Server_Exception If the query is malformed.
+ */
+ public function convertGreater(Horde_Kolab_Server_Query_Element_Greater $greater)
+ {
+ return $this->_convertSingle($greater, 'greater');
+ }
+
+ /**
+ * Convert the approx element to query format.
+ *
+ * @param Horde_Kolab_Server_Query_Element_Approx $approx The element to convert.
+ *
+ * @return mixed The query element in query format.
+ *
+ * @throws Horde_Kolab_Server_Exception If the query is malformed.
+ */
+ public function convertApprox(Horde_Kolab_Server_Query_Element_Approx $approx)
+ {
+ return $this->_convertSingle($approx, 'approx');
+ }
+
+ /**
+ * Convert the single element to query format.
+ *
+ * @param Horde_Kolab_Server_Query_Element_Single $single The element to convert.
+ * @param string $operator The element operation.
+ *
+ * @return mixed The query element in query format.
+ *
+ * @throws Horde_Kolab_Server_Exception If the query is malformed.
+ */
+ private function _convertSingle(
+ Horde_Kolab_Server_Query_Element_Single $single,
+ $operator
+ ) {
+ $result = Net_LDAP2_Filter::create(
+ $single->getName(), $operator, $single->getValue()
+ );
+ $this->_handleError($result);
+ return $result;
+ }
+
+ /**
+ * Convert the not element to query format.
+ *
+ * @param Horde_Kolab_Server_Query_Element_Group $group The element to convert.
+ *
+ * @return mixed The query element in query format.
+ *
+ * @throws Horde_Kolab_Server_Exception If the query is malformed.
+ */
+ public function convertNot(Horde_Kolab_Server_Query_Element_Not $not)
+ {
+ $elements = $not->getElements();
+ $result = Net_LDAP2_Filter::combine('!', $elements[0]->convert($this));
+ $this->_handleError($result);
+ return $result;
+ }
+
+ /**
+ * Convert the and element to query format.
+ *
+ * @param Horde_Kolab_Server_Query_Element_Group $group The element to convert.
+ *
+ * @return mixed The query element in query format.
+ *
+ * @throws Horde_Kolab_Server_Exception If the query is malformed.
+ */
+ public function convertAnd(Horde_Kolab_Server_Query_Element_And $and)
+ {
+ return $this->_convertGroup($and, '&');
+ }
+
+ /**
+ * Convert the or element to query format.
+ *
+ * @param Horde_Kolab_Server_Query_Element_Group $group The element to convert.
+ *
+ * @return mixed The query element in query format.
+ *
+ * @throws Horde_Kolab_Server_Exception If the query is malformed.
+ */
+ public function convertOr(Horde_Kolab_Server_Query_Element_Group $or)
+ {
+ return $this->_convertGroup($or, '|');
+ }
+
+ /**
+ * Convert the group element to query format.
+ *
+ * @param Horde_Kolab_Server_Query_Element_Group $group The element to convert.
+ * @param string $operator The element operation.
+ *
+ * @return mixed The query element in query format.
+ *
+ * @throws Horde_Kolab_Server_Exception If the query is malformed.
+ */
+ public function _convertGroup(
+ Horde_Kolab_Server_Query_Element_Group $group,
+ $operator
+ ) {
+ $filters = array();
+ foreach ($group->getElements() as $element) {
+ $filters[] = $element->convert($this);
+ }
+ $result = Net_LDAP2_Filter::combine($operator, $filters);
+ $this->_handleError($result);
+ return $result;
+ }
+
+ /**
+ * Check for a PEAR Error and convert it to an exception if necessary.
+ *
+ * @param mixed $result The result to be tested.
+ * @param code $code The error code to use in case the result is an error.
+ *
+ * @return NULL.
+ *
+ * @throws Horde_Kolab_Server_Exception If the connection failed.
+ *
+ * @throws Horde_Kolab_Server_Exception If the query is malformed.
+ */
+ private function _handleError(
+ $result,
+ $code = Horde_Kolab_Server_Exception::INVALID_QUERY
+ ) {
+ if (is_a($result, 'PEAR_Error')) {
+ throw new Horde_Kolab_Server_Exception($result, $code);
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/framework/Kolab_Server/lib/Horde/Kolab/Server/Result.php b/framework/Kolab_Server/lib/Horde/Kolab/Server/Result.php
new file mode 100644
index 000000000..bf365fdce
--- /dev/null
+++ b/framework/Kolab_Server/lib/Horde/Kolab/Server/Result.php
@@ -0,0 +1,50 @@
+
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Kolab_Server
+ */
+
+/**
+ * Interface for query results.
+ *
+ * Copyright 2008-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 Kolab_Server
+ * @author Gunnar Wrobel
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Kolab_Server
+ */
+interface Horde_Kolab_Server_Result
+{
+ /**
+ * The number of result entries.
+ *
+ * @return int The number of elements.
+ */
+ public function count();
+
+ /**
+ * Test if the last search exceeded the size limit.
+ *
+ * @return boolean True if the last search exceeded the size limit.
+ */
+ public function sizeLimitExceeded();
+
+ /**
+ * Return the result as an array.
+ *
+ * @return array The resulting array.
+ */
+ public function asArray();
+}
\ No newline at end of file
diff --git a/framework/Kolab_Server/lib/Horde/Kolab/Server/Result/Ldap.php b/framework/Kolab_Server/lib/Horde/Kolab/Server/Result/Ldap.php
new file mode 100644
index 000000000..273a0c0ff
--- /dev/null
+++ b/framework/Kolab_Server/lib/Horde/Kolab/Server/Result/Ldap.php
@@ -0,0 +1,76 @@
+
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Kolab_Server
+ */
+
+/**
+ * Handler for LDAP query results.
+ *
+ * Copyright 2008-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 Kolab_Server
+ * @author Gunnar Wrobel
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Kolab_Server
+ */
+class Horde_Kolab_Server_Result_Ldap implements Horde_Kolab_Server_Result
+{
+ /**
+ * The search result.
+ *
+ * @var Net_LDAP2_Search
+ */
+ private $_search;
+
+ /**
+ * Constructor.
+ *
+ * @param Net_LDAP2_Search $search The LDAP search result.
+ */
+ public function __construct(Net_LDAP2_Search $search)
+ {
+ $this->_search = $search;
+ }
+
+ /**
+ * The number of result entries.
+ *
+ * @return int The number of elements.
+ */
+ public function count()
+ {
+ return $this->_search->count();
+ }
+
+ /**
+ * Test if the last search exceeded the size limit.
+ *
+ * @return boolean True if the last search exceeded the size limit.
+ */
+ public function sizeLimitExceeded()
+ {
+ return $this->_search->sizeLimitExceeded();
+ }
+
+ /**
+ * Return the result as an array.
+ *
+ * @return array The resulting array.
+ */
+ public function asArray()
+ {
+ return $this->_search->as_struct();
+ }
+}
\ No newline at end of file
diff --git a/framework/Kolab_Server/lib/Horde/Kolab/Server/Schema.php b/framework/Kolab_Server/lib/Horde/Kolab/Server/Schema.php
new file mode 100644
index 000000000..07792a217
--- /dev/null
+++ b/framework/Kolab_Server/lib/Horde/Kolab/Server/Schema.php
@@ -0,0 +1,62 @@
+
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Kolab_Server
+ */
+
+/**
+ * Interface for the structural handler of a Kolab database.
+ *
+ * Copyright 2008-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 Kolab_Server
+ * @author Gunnar Wrobel
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Kolab_Server
+ */
+interface Horde_Kolab_Server_Schema
+{
+ /**
+ * Return the schema for the given objectClass.
+ *
+ * @param string $objectclass Fetch the schema for this objectClass.
+ *
+ * @return array The schema for the given objectClass.
+ *
+ * @throws Horde_Kolab_Server_Exception If retrieval of the schema failed.
+ */
+ public function getObjectclassSchema($objectclass);
+
+ /**
+ * Return the schema for the given attribute.
+ *
+ * @param string $attribute Fetch the schema for this attribute.
+ *
+ * @return array The schema for the given attribute.
+ *
+ * @throws Horde_Kolab_Server_Exception If retrieval of the schema failed.
+ */
+ public function getAttributeSchema($attribute);
+
+ /**
+ * Return the attributes supported by the given object class.
+ *
+ * @param string $class Determine the attributes for this class.
+ *
+ * @return array The supported attributes.
+ *
+ * @throws Horde_Kolab_Server_Exception If the schema analysis fails.
+ */
+ public function &getAttributes($class);
+}
\ No newline at end of file
diff --git a/framework/Kolab_Server/lib/Horde/Kolab/Server/Schema/Base.php b/framework/Kolab_Server/lib/Horde/Kolab/Server/Schema/Base.php
new file mode 100644
index 000000000..9ed27a7f4
--- /dev/null
+++ b/framework/Kolab_Server/lib/Horde/Kolab/Server/Schema/Base.php
@@ -0,0 +1,273 @@
+
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Kolab_Server
+ */
+
+/**
+ * This class provides methods to deal with Kolab objects stored in
+ * the Kolab object db.
+ *
+ * Copyright 2008-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 Kolab_Server
+ * @author Gunnar Wrobel
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Kolab_Server
+ */
+class Horde_Kolab_Server_Schema_Base implements Horde_Kolab_Server_Schema
+{
+ /** Maximum accepted level for the object class hierarchy */
+ const MAX_HIERARCHY = 100;
+
+ /**
+ * A cache for object attribute definitions.
+ *
+ * @var array
+ */
+ protected $attributes;
+
+ /**
+ * A link to the server handler.
+ *
+ * @var Horde_Kolab_Server
+ */
+ protected $server;
+
+ /**
+ * Set the server reference for this object.
+ *
+ * @param Horde_Kolab_Server &$server A link to the server handler.
+ */
+ public function setServer($server)
+ {
+ $this->server = $server;
+ }
+
+ /**
+ * Return the schema for the given objectClass.
+ *
+ * @param string $objectclass Fetch the schema for this objectClass.
+ *
+ * @return array The schema for the given objectClass.
+ *
+ * @throws Horde_Kolab_Server_Exception If retrieval of the schema failed.
+ */
+ public function getObjectclassSchema($objectclass)
+ {
+ if (!empty($this->_config['schema_support'])) {
+ $schema = $this->_getSchema();
+ $info = $schema->get('objectclass', $objectclass);
+ $this->_handleError($info, Horde_Kolab_Server_Exception::SYSTEM);
+ return $info;
+ }
+ return parent::getObjectclassSchema($objectclass);
+ }
+
+ /**
+ * Return the schema for the given attribute.
+ *
+ * @param string $attribute Fetch the schema for this attribute.
+ *
+ * @return array The schema for the given attribute.
+ *
+ * @throws Horde_Kolab_Server_Exception If retrieval of the schema failed.
+ */
+ public function getAttributeSchema($attribute)
+ {
+ if (!empty($this->_config['schema_support'])) {
+ $schema = $this->_getSchema();
+ $info = $schema->get('attribute', $attribute);
+ $this->_handleError($info, Horde_Kolab_Server_Exception::SYSTEM);
+ return $info;
+ }
+ return parent::getAttributeSchema($attribute);
+ }
+
+ /**
+ * Return the attributes supported by the given object class.
+ *
+ * @param string $class Determine the attributes for this class.
+ *
+ * @return array The supported attributes.
+ *
+ * @throws Horde_Kolab_Server_Exception If the schema analysis fails.
+ */
+ public function &getAttributes($class)
+ {
+ if (!isset($this->attributes)) {
+ if (isset($this->cache)) {
+ register_shutdown_function(array($this, 'shutdown'));
+ }
+ }
+ if (empty($this->attributes[$class])) {
+
+ if (isset($this->cache)) {
+ $this->attributes[$class] = @unserialize($cache->get('attributes_' . $class,
+ $this->params['cache_lifetime']));
+ }
+
+ if (empty($this->attributes[$class])) {
+
+ $childclass = $class;
+ $classes = array();
+ $level = 0;
+ while ($childclass != 'Horde_Kolab_Server_Object'
+ && $level < self::MAX_HIERARCHY) {
+ $classes[] = $childclass;
+ $childclass = get_parent_class($childclass);
+ $level++;
+ }
+
+ /** Finally add the basic object class */
+ $classes[] = $childclass;
+
+ if ($level == self::MAX_HIERARCHY) {
+ if (isset($this->logger)) {
+ $logger->err(sprintf('The maximal level of the object hierarchy has been exceeded for class \"%s\"!',
+ $class));
+ }
+ }
+
+ /**
+ * Collect attributes from bottom to top.
+ */
+ $classes = array_reverse($classes);
+
+ $types = array('defined', 'required', 'derived', 'collapsed',
+ 'defaults', 'locked', 'object_classes');
+ foreach ($types as $type) {
+ $$type = array();
+ }
+
+ foreach ($classes as $childclass) {
+ $vars = get_class_vars($childclass);
+ if (isset($vars['init_attributes'])) {
+ foreach ($types as $type) {
+ /**
+ * If the user wishes to adhere to the schema
+ * information from the server we will skip the
+ * attributes defined within the object class here.
+ */
+ if (!empty($this->params['schema_override'])
+ && in_array($type, 'defined', 'required')) {
+ continue;
+ }
+ if (isset($vars['init_attributes'][$type])) {
+ $$type = array_merge($$type,
+ $vars['init_attributes'][$type]);
+ }
+ }
+ }
+ }
+
+ $attrs = array();
+
+ foreach ($object_classes as $object_class) {
+ $info = $this->getObjectclassSchema($object_class);
+ if (isset($info['may'])) {
+ $defined = array_merge($defined, $info['may']);
+ }
+ if (isset($info['must'])) {
+ $defined = array_merge($defined, $info['must']);
+ $required = array_merge($required, $info['must']);
+ }
+ foreach ($defined as $attribute) {
+ try {
+ $attrs[$attribute] = $this->getAttributeSchema($attribute);
+ } catch (Horde_Kolab_Server_Exception $e) {
+ /**
+ * If the server considers the attribute to be
+ * invalid we mark it.
+ */
+ $attrs[$attribute] = array('invalid' => true);
+ }
+ }
+ foreach ($required as $attribute) {
+ $attrs[$attribute]['required'] = true;
+ }
+ foreach ($locked as $attribute) {
+ $attrs[$attribute]['locked'] = true;
+ }
+ foreach ($defaults as $attribute => $default) {
+ $attrs[$attribute]['default'] = $default;
+ }
+ $attrs[Horde_Kolab_Server_Object::ATTRIBUTE_OC]['default'] = $object_classes;
+ }
+ foreach ($derived as $key => $attributes) {
+ $supported = true;
+ if (isset($attributes['base'])) {
+ foreach ($attributes['base'] as $attribute) {
+ /**
+ * Usually derived attribute are determined on basis
+ * of one or more attributes. If any of these is not
+ * supported the derived attribute should not be
+ * included into the set of supported attributes.
+ */
+ if (!isset($attrs[$attribute])) {
+ unset($derived[$attribute]);
+ $supported = false;
+ break;
+ }
+ }
+ }
+ if ($supported) {
+ $attrs[$key] = $attributes;
+ }
+ }
+ $check_collapsed = $collapsed;
+ foreach ($check_collapsed as $key => $attributes) {
+ if (isset($attributes['base'])) {
+ foreach ($attributes['base'] as $attribute) {
+ /**
+ * Usually collapsed attribute are determined on basis
+ * of one or more attributes. If any of these is not
+ * supported the collapsed attribute should not be
+ * included into the set of supported attributes.
+ */
+ if (!isset($attrs[$attribute])) {
+ unset($collapsed[$attribute]);
+ }
+ }
+ }
+ }
+ $this->attributes[$class] = array($attrs,
+ array(
+ 'derived' => array_keys($derived),
+ 'collapsed' => $collapsed,
+ 'locked' => $locked,
+ 'required' => $required));
+ }
+ }
+ return $this->attributes[$class];
+ }
+
+ /**
+ * Stores the attribute definitions in the cache.
+ *
+ * @return Horde_Kolab_Server The concrete Horde_Kolab_Server reference.
+ */
+ public function shutdown()
+ {
+ if (isset($this->attributes)) {
+ if (isset($this->cache)) {
+ foreach ($this->attributes as $key => $value) {
+ $this->cache->set('attributes_' . $key, @serialize($value));
+ }
+ }
+ }
+ }
+
+
+}
\ No newline at end of file
diff --git a/framework/Kolab_Server/lib/Horde/Kolab/Server/Search.php b/framework/Kolab_Server/lib/Horde/Kolab/Server/Search.php
new file mode 100644
index 000000000..6f72f7bf0
--- /dev/null
+++ b/framework/Kolab_Server/lib/Horde/Kolab/Server/Search.php
@@ -0,0 +1,48 @@
+
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Kolab_Server
+ */
+
+/**
+ * Defines the interface of the search handler for a Kolab Server.
+ *
+ * Copyright 2008-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 Kolab_Server
+ * @author Gunnar Wrobel
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Kolab_Server
+ */
+interface Horde_Kolab_Server_Search
+{
+ /**
+ * Returns the set of search operations supported by this server type.
+ *
+ * @return array An array of supported search operations.
+ */
+ public function getSearchOperations();
+
+ /**
+ * Capture undefined calls.
+ *
+ * @param string $method The name of the called method.
+ * @param array $args Arguments of the call.
+ *
+ * @return NULL.
+ *
+ * @throws Horde_Kolab_Server_Exception
+ */
+ public function __call($method, $args);
+}
\ No newline at end of file
diff --git a/framework/Kolab_Server/lib/Horde/Kolab/Server/Search/Base.php b/framework/Kolab_Server/lib/Horde/Kolab/Server/Search/Base.php
new file mode 100644
index 000000000..caf111f67
--- /dev/null
+++ b/framework/Kolab_Server/lib/Horde/Kolab/Server/Search/Base.php
@@ -0,0 +1,103 @@
+
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Kolab_Server
+ */
+
+/**
+ * This class provides methods to deal with Kolab objects stored in
+ * the Kolab object db.
+ *
+ * Copyright 2008-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 Kolab_Server
+ * @author Gunnar Wrobel
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Kolab_Server
+ */
+class Horde_Kolab_Server_Search_Base implements Horde_Kolab_Server_Search
+{
+ /**
+ * A link to the server handler.
+ *
+ * @var Horde_Kolab_Server
+ */
+ protected $server;
+
+ /**
+ * Set the server reference for this object.
+ *
+ * @param Horde_Kolab_Server &$server A link to the server handler.
+ */
+ public function setServer($server)
+ {
+ $this->server = $server;
+ }
+
+ /**
+ * The search methods offered by the object defined for this server.
+ *
+ * @var array
+ */
+ protected $searches;
+
+ /*__construct
+ /** Initialize the search operations supported by this server. *
+ $this->searches = $this->getSearchOperations();
+ */
+
+ /**
+ * Returns the set of search operations supported by this server type.
+ *
+ * @return array An array of supported search operations.
+ */
+ public function getSearchOperations()
+ {
+ $server_searches = array();
+ foreach ($this->getSupportedObjects() as $sobj) {
+ if (in_array('getSearchOperations', get_class_methods($sobj))) {
+ $searches = call_user_func(array($sobj, 'getSearchOperations'));
+ foreach ($searches as $search) {
+ $server_searches[$search] = array('class' => $sobj);
+ }
+ }
+ }
+ return $server_searches;
+ }
+
+ /**
+ * Capture undefined calls and assume they refer to a search operation.
+ *
+ * @param string $method The name of the called method.
+ * @param array $args Arguments of the call.
+ *
+ * @return NULL.
+ *
+ * @throws Horde_Kolab_Server_Exception
+ */
+ public function __call($method, $args)
+ {
+ if (in_array($method, array_keys($this->searches))) {
+ array_unshift($args, $this);
+ if (isset($this->searches[$method])) {
+ return call_user_func_array(array($this->searches[$method]['class'],
+ $method), $args);
+ }
+ }
+ throw new Horde_Kolab_Server_Exception(
+ sprintf("The server type \"%s\" does not support method \"%s\"!",
+ get_class($this), $method));
+ }
+
+}
\ No newline at end of file
diff --git a/framework/Kolab_Server/lib/Horde/Kolab/Server/Standard.php b/framework/Kolab_Server/lib/Horde/Kolab/Server/Standard.php
new file mode 100644
index 000000000..d4e94370e
--- /dev/null
+++ b/framework/Kolab_Server/lib/Horde/Kolab/Server/Standard.php
@@ -0,0 +1,47 @@
+
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Kolab_Server
+ */
+
+/**
+ * This class provides methods to deal with objects stored in
+ * a standard LDAP db.
+ *
+ * Copyright 2008-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 Kolab_Server
+ * @author Gunnar Wrobel
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Kolab_Server
+ */
+class Horde_Kolab_Server_Standard extends Horde_Kolab_Server_Ldap
+{
+ /**
+ * Finds all object data below a parent matching a given set of criteria.
+ *
+ * @param array $criteria The criteria for the search.
+ * @param string $parent The parent to search below.
+ * @param array $params Additional search parameters.
+ *
+ * @return Horde_Kolab_Server_Result The result object.
+ *
+ * @throws Horde_Kolab_Server_Exception
+ */
+ public function findBelow(array $criteria, $parent, array $params = array())
+ {
+ $query = new Horde_Kolab_Server_Query_Ldap($criteria);
+ return $this->_search((string) $query, $params, $parent);
+ }
+}
diff --git a/framework/Kolab_Server/lib/Horde/Kolab/Server/Structure.php b/framework/Kolab_Server/lib/Horde/Kolab/Server/Structure.php
index 17c6fb917..68f854046 100644
--- a/framework/Kolab_Server/lib/Horde/Kolab/Server/Structure.php
+++ b/framework/Kolab_Server/lib/Horde/Kolab/Server/Structure.php
@@ -12,7 +12,8 @@
*/
/**
- * An abstract class definiing methods to deal with an object tree structure.
+ * The interface definition for the handlers dealing with the Kolab Server
+ * object tree structure.
*
* Copyright 2009 The Horde Project (http://www.horde.org/)
*
@@ -25,48 +26,14 @@
* @license http://www.fsf.org/copyleft/lgpl.html LGPL
* @link http://pear.horde.org/index.php?package=Kolab_Server
*/
-abstract class Horde_Kolab_Server_Structure
+interface Horde_Kolab_Server_Structure
{
/**
- * A link to the server handler.
- *
- * @var Horde_Kolab_Server
- */
- protected $server;
-
- /**
- * Structure parameters.
- *
- * @var array
- */
- protected $params = array();
-
- /**
- * Construct a new Horde_Kolab_Server_Structure object.
- *
- * @param array $params Parameter array.
- */
- public function __construct($params = array())
- {
- $this->params = $params;
- }
-
- /**
- * Set the server reference for this object.
- *
- * @param Horde_Kolab_Server &$server A link to the server handler.
- */
- public function setServer($server)
- {
- $this->server = $server;
- }
-
- /**
* Returns the set of objects supported by this structure.
*
* @return array An array of supported objects.
*/
- abstract public function getSupportedObjects();
+ public function getSupportedObjects();
/**
* Determine the type of an object by its tree position and other
@@ -78,7 +45,7 @@ abstract class Horde_Kolab_Server_Structure
*
* @throws Horde_Kolab_Server_Exception If the object type is unknown.
*/
- abstract public function determineType($uid);
+ public function determineType($uid);
/**
* Generates a UID for the given information.
@@ -91,23 +58,5 @@ abstract class Horde_Kolab_Server_Structure
*
* @throws Horde_Kolab_Server_Exception If the given type is unknown.
*/
- abstract public function generateServerUid($type, $id, $info);
-
- /**
- * Quote an UID part.
- *
- * @param string $id The UID part.
- *
- * @return string The quoted part.
- */
- abstract public function quoteForUid($id);
-
- /**
- * Quote an filter part.
- *
- * @param string $part The filter part.
- *
- * @return string The quoted part.
- */
- abstract public function quoteForFilter($part);
+ public function generateServerUid($type, $id, $info);
}
diff --git a/framework/Kolab_Server/lib/Horde/Kolab/Server/Structure/Base.php b/framework/Kolab_Server/lib/Horde/Kolab/Server/Structure/Base.php
new file mode 100644
index 000000000..bf58f7406
--- /dev/null
+++ b/framework/Kolab_Server/lib/Horde/Kolab/Server/Structure/Base.php
@@ -0,0 +1,139 @@
+
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Kolab_Server
+ */
+
+/**
+ * An abstract class definiing methods to deal with an object tree structure.
+ *
+ * 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 Kolab_Server
+ * @author Gunnar Wrobel
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Kolab_Server
+ */
+abstract class Horde_Kolab_Server_Structure_Base implements Horde_Kolab_Server_Structure
+{
+ /**
+ * A link to the server handler.
+ *
+ * @var Horde_Kolab_Server
+ */
+ protected $server;
+
+ /**
+ * Set the server reference for this object.
+ *
+ * @param Horde_Kolab_Server &$server A link to the server handler.
+ */
+ public function setServer($server)
+ {
+ $this->server = $server;
+ }
+
+ /**
+ * Returns the set of objects supported by this structure.
+ *
+ * @return array An array of supported objects.
+ */
+ public function getSupportedObjects()
+ {
+ }
+
+ /**
+ * Determine the type of an object by its tree position and other
+ * parameters.
+ *
+ * @param string $uid The UID of the object to examine.
+ *
+ * @return string The class name of the corresponding object type.
+ *
+ * @throws Horde_Kolab_Server_Exception If the object type is unknown.
+ */
+ public function determineType($uid)
+ {
+ }
+
+ /**
+ * Generates a UID for the given information.
+ *
+ * @param string $type The class name of the object to create.
+ * @param string $id The id of the object.
+ * @param array $info Any additional information about the object to create.
+ *
+ * @return string The UID.
+ *
+ * @throws Horde_Kolab_Server_Exception If the given type is unknown.
+ */
+ public function generateServerUid($type, $id, $info)
+ {
+ }
+
+ /**
+ * Get the LDAP object classes for the given DN.
+ *
+ * This is meant to be a shortcut for the structure handler. It should be
+ * used when determining the object type.
+ *
+ * @param string $uid DN of the object.
+ *
+ * @return array An array of object classes.
+ *
+ * @throws Horde_Kolab_Server_Exception If the object has no
+ * object classes.
+ */
+ public function getObjectClasses($uid)
+ {
+ $object = $this->read($uid, array(Horde_Kolab_Server_Object::ATTRIBUTE_OC));
+ if (!isset($object[Horde_Kolab_Server_Object::ATTRIBUTE_OC])) {
+ throw new Horde_Kolab_Server_Exception(
+ sprintf(
+ "The object %s has no %s attribute!",
+ $uid, Horde_Kolab_Server_Object::ATTRIBUTE_OC
+ ),
+ Horde_Kolab_Server_Exception::SYSTEM
+ );
+ }
+ $result = array_map(
+ 'strtolower',
+ $object[Horde_Kolab_Server_Object::ATTRIBUTE_OC]
+ );
+ return $result;
+ }
+
+ /**
+ * Connect to the server. Use this method if the user name you can provide
+ * does not match a DN. In this case it will be required to map this user
+ * name first.
+ *
+ * @param string $user The user name.
+ * @param string $pass The password.
+ *
+ * @return NULL.
+ *
+ * @throws Horde_Kolab_Server_Exception If the connection failed.
+ */
+ protected function _connect($user = null, $pass = null)
+ {
+ /** Bind anonymously first. */
+ $this->connectUid();
+ $guid = $this->structure->getGuidForUser($user);
+ $this->connectUid($guid, $pass);
+ return $this->structure->getUserForUser($user);
+ }
+
+
+}
diff --git a/framework/Kolab_Server/lib/Horde/Kolab/Server/Structure/Ldap.php b/framework/Kolab_Server/lib/Horde/Kolab/Server/Structure/Ldap.php
index 7c0d6c366..382815ffc 100644
--- a/framework/Kolab_Server/lib/Horde/Kolab/Server/Structure/Ldap.php
+++ b/framework/Kolab_Server/lib/Horde/Kolab/Server/Structure/Ldap.php
@@ -25,7 +25,7 @@
* @license http://www.fsf.org/copyleft/lgpl.html LGPL
* @link http://pear.horde.org/index.php?package=Kolab_Server
*/
-class Horde_Kolab_Server_Structure_Ldap extends Horde_Kolab_Server_Structure
+class Horde_Kolab_Server_Structure_Ldap extends Horde_Kolab_Server_Structure_Base
{
/**
* Returns the set of objects supported by this structure.
@@ -90,29 +90,4 @@ class Horde_Kolab_Server_Structure_Ldap extends Horde_Kolab_Server_Structure
return sprintf('%s,%s', $id, $this->server->getBaseUid());
}
- /**
- * Quote an UID part.
- *
- * @param string $id The UID part.
- *
- * @return string The UID part.
- */
- public function quoteForUid($id)
- {
- $id = Net_LDAP2_Util::escape_dn_value($id);
- return $id[0];
- }
-
- /**
- * Quote an filter part.
- *
- * @param string $part The filter part.
- *
- * @return string The quoted part.
- */
- public function quoteForFilter($part)
- {
- $part = Net_LDAP2_Util::escape_filter_value($part);
- return $part[0];
- }
}
diff --git a/framework/Kolab_Server/lib/Horde/Kolab/Server/Test.php b/framework/Kolab_Server/lib/Horde/Kolab/Server/Test.php
index c04e43722..461ccc17f 100644
--- a/framework/Kolab_Server/lib/Horde/Kolab/Server/Test.php
+++ b/framework/Kolab_Server/lib/Horde/Kolab/Server/Test.php
@@ -85,14 +85,17 @@ class Horde_Kolab_Server_Test extends Horde_Kolab_Server_Ldap
private $_current_index;
/**
- * Construct a new Horde_Kolab_Server object.
+ * Set configuration parameters.
*
- * @param array $params Parameter array.
+ * @param array $params The parameters.
+ *
+ * @return NULL
*/
- public function __construct(Horde_Kolab_Server_Structure $structure,
- $params = array())
+ public function setParams(array $params)
{
- $this->load();
+ //@todo Load when connecting
+ //$this->load();
+
if (isset($params['data'])) {
$this->data = $params['data'];
} else {
@@ -101,8 +104,6 @@ class Horde_Kolab_Server_Test extends Horde_Kolab_Server_Ldap
}
}
- parent::__construct($structure, $params);
-
if (isset($this->params['admin'])
&& isset($this->params['admin']['type'])) {
$type = $this->params['admin']['type'];
@@ -114,18 +115,25 @@ class Horde_Kolab_Server_Test extends Horde_Kolab_Server_Ldap
}
}
- $this->store();
+ //@todo Load when connecting
+ //$this->store();
+
+ parent::setParams($params);
}
/**
- * Connect to the server.
+ * Connect to the LDAP server.
+ *
+ * @param string $uid The unique id of the user.
+ * @param string $pass The password.
*
* @return NULL.
*
* @throws Horde_Kolab_Server_Exception If the connection failed.
*/
- protected function connect()
+ protected function _connectUid($uid = null, $pass = null)
{
+ //@todo
}
/**
@@ -135,6 +143,7 @@ class Horde_Kolab_Server_Test extends Horde_Kolab_Server_Ldap
*/
protected function load()
{
+ //@todo: remove the global
if (isset($GLOBALS['KOLAB_SERVER_TEST_DATA'])) {
$this->data = $GLOBALS['KOLAB_SERVER_TEST_DATA'];
} else {
@@ -483,7 +492,7 @@ class Horde_Kolab_Server_Test extends Horde_Kolab_Server_Ldap
*
* @throws Horde_Kolab_Server_Exception If the object does not exist.
*/
- public function read($dn, $attrs = null)
+ public function read($uid, array $attrs = array())
{
if (!$this->bound) {
$result = $this->bind();
@@ -522,9 +531,9 @@ class Horde_Kolab_Server_Test extends Horde_Kolab_Server_Ldap
* @param array $data The attributes of the object to be added/replaced.
* @param boolean $exists Does the object already exist on the server?
*
- * @return boolean True if saving succeeded.
+ * @return NULL
*/
- public function save($uid, $data, $exists = false)
+ public function save($uid, array $data, $exists = false)
{
if (!$this->bound) {
$result = $this->bind();
@@ -597,8 +606,8 @@ class Horde_Kolab_Server_Test extends Horde_Kolab_Server_Ldap
$this->store();
if (isset($this->logger)) {
- $logger->debug(sprintf('The object \"%s\" has been successfully saved!',
- $uid));
+ $this->logger->debug(sprintf('The object \"%s\" has been successfully saved!',
+ $uid));
}
}
@@ -628,7 +637,7 @@ class Horde_Kolab_Server_Test extends Horde_Kolab_Server_Ldap
*
* @param string $uid The UID of the object to be deleted.
*
- * @return boolean True if saving succeeded.
+ * @return NULL
*
* @throws Horde_Kolab_Server_Exception
*/
@@ -642,10 +651,9 @@ class Horde_Kolab_Server_Test extends Horde_Kolab_Server_Ldap
}
$this->store();
if (isset($this->logger)) {
- $logger->debug(sprintf('The object \"%s\" has been successfully deleted!',
- $uid));
+ $this->logger->debug(sprintf('The object \"%s\" has been successfully deleted!',
+ $uid));
}
- return true;
}
/**
@@ -654,7 +662,7 @@ class Horde_Kolab_Server_Test extends Horde_Kolab_Server_Ldap
* @param string $uid The UID of the object to be renamed.
* @param string $new The new UID of the object.
*
- * @return boolean True if renaming succeeded.
+ * @return NULL
*
* @throws Horde_Kolab_Server_Exception
*/
@@ -666,10 +674,9 @@ class Horde_Kolab_Server_Test extends Horde_Kolab_Server_Ldap
}
$this->store();
if (isset($this->logger)) {
- $logger->debug(sprintf('The object \"%s\" has been successfully renamed to \"%s\"!',
- $uid, $new));
+ $this->logger->debug(sprintf('The object \"%s\" has been successfully renamed to \"%s\"!',
+ $uid, $new));
}
- return true;
}
/**
diff --git a/framework/Kolab_Server/package.xml b/framework/Kolab_Server/package.xml
index 848b24d61..7f25d3b8c 100644
--- a/framework/Kolab_Server/package.xml
+++ b/framework/Kolab_Server/package.xml
@@ -61,11 +61,17 @@ http://pear.php.net/dtd/package-2.0.xsd">
+
+
+
+
+
+
-
+
@@ -88,8 +94,45 @@ http://pear.php.net/dtd/package-2.0.xsd">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -104,7 +147,13 @@ http://pear.php.net/dtd/package-2.0.xsd">
-
+
+
+
+
+
+
+
@@ -118,6 +167,9 @@ http://pear.php.net/dtd/package-2.0.xsd">
+
+
+
@@ -136,34 +188,18 @@ http://pear.php.net/dtd/package-2.0.xsd">
1.4.0b1
- Net_LDAP2
- pear.php.net
-
-
- Autoloader
- pear.horde.org
-
-
- Horde_Framework
+ Exception
pear.horde.org
- Horde_LDAP
- pear.horde.org
-
-
- Horde_Cache
- pear.horde.org
-
-
Date
pear.horde.org
- PHPUnit
- pear.phpunit.de
+ Net_LDAP2
+ pear.php.net
ldap
@@ -173,11 +209,15 @@ http://pear.php.net/dtd/package-2.0.xsd">
+
+
+
+
-
+
@@ -196,7 +236,32 @@ http://pear.php.net/dtd/package-2.0.xsd">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -204,6 +269,8 @@ http://pear.php.net/dtd/package-2.0.xsd">
+
+
@@ -217,6 +284,7 @@ http://pear.php.net/dtd/package-2.0.xsd">
+
diff --git a/framework/Kolab_Server/test/Horde/Kolab/Server/AdminTest.php b/framework/Kolab_Server/test/Horde/Kolab/Server/AdminTest.php
index c22c42003..e77ef4e00 100644
--- a/framework/Kolab_Server/test/Horde/Kolab/Server/AdminTest.php
+++ b/framework/Kolab_Server/test/Horde/Kolab/Server/AdminTest.php
@@ -40,6 +40,8 @@ class Horde_Kolab_Server_AdminTest extends Horde_Kolab_Server_Scenario
*/
protected function setUp()
{
+ parent::setUp();
+
$this->server = $this->getKolabMockServer();
}
diff --git a/framework/Kolab_Server/test/Horde/Kolab/Server/Autoload.php b/framework/Kolab_Server/test/Horde/Kolab/Server/Autoload.php
index 3b29921aa..edb1ce807 100644
--- a/framework/Kolab_Server/test/Horde/Kolab/Server/Autoload.php
+++ b/framework/Kolab_Server/test/Horde/Kolab/Server/Autoload.php
@@ -11,23 +11,24 @@
* @link http://pear.horde.org/index.php?package=Kolab_Server
*/
-if (!defined('HORE_KOLAB_SERVER_TESTS')) {
- /**
- * The Autoloader allows us to omit "require/include" statements.
- */
- require_once 'Horde/Autoloader.php';
+/**
+ * The Autoloader allows us to omit "require/include" statements.
+ */
+require_once 'Horde/Autoloader.php';
+
+if (!defined('HORDE_KOLAB_SERVER_TESTS')) {
$test_dir = '@test_dir@/Kolab_Server';
- if (substr($test_dir, 0, 1) == '@') {
+ if (strpos($test_dir, '@test_dir') === 0) {
/**
* Assume we are working in development mode and this package resides in
* 'framework'.
*/
- define('HORE_KOLAB_SERVER_TESTS', dirname(__FILE__) . '/../../..');
+ define('HORDE_KOLAB_SERVER_TESTS', dirname(__FILE__) . '/../../..');
} else {
- define('HORE_KOLAB_SERVER_TESTS', $test_dir);
+ define('HORDE_KOLAB_SERVER_TESTS', $test_dir);
}
- Horde_Autoloader::addClassPath(HORE_KOLAB_SERVER_TESTS);
+ Horde_Autoloader::addClassPath(HORDE_KOLAB_SERVER_TESTS);
}
\ No newline at end of file
diff --git a/framework/Kolab_Server/test/Horde/Kolab/Server/Connection/SimpleldapTest.php b/framework/Kolab_Server/test/Horde/Kolab/Server/Connection/SimpleldapTest.php
new file mode 100644
index 000000000..cff61dc29
--- /dev/null
+++ b/framework/Kolab_Server/test/Horde/Kolab/Server/Connection/SimpleldapTest.php
@@ -0,0 +1,72 @@
+
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Kolab_Server
+ */
+
+/**
+ * Prepare the test setup.
+ */
+require_once dirname(__FILE__) . '/../Autoload.php';
+
+/**
+ * Test the handler for a simple LDAP setup without read-only slaves.
+ *
+ * Copyright 2008-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 Kolab_Server
+ * @author Gunnar Wrobel
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Kolab_Server
+ */
+class Horde_Kolab_Server_Connection_SimpleldapTest extends PHPUnit_Framework_TestCase
+{
+ public function setUp()
+ {
+ if (!extension_loaded('ldap') && !@dl('ldap.' . PHP_SHLIB_SUFFIX)) {
+ $this->markTestSuiteSkipped('Ldap extension is missing!');
+ };
+
+ if (!class_exists('Net_LDAP2')) {
+ $this->markTestSuiteSkipped('PEAR package Net_LDAP2 is not installed!');
+ }
+ }
+
+ public function testMethodConstructHasParameterNetldap2Connection()
+ {
+ $ldap = $this->getMock('Net_LDAP2');
+ $conn = new Horde_Kolab_Server_Connection_Simpleldap($ldap);
+ }
+
+ public function testMethodConstructHasPostconditionThatTheGivenServerWasStored()
+ {
+ $ldap = $this->getMock('Net_LDAP2');
+ $conn = new Horde_Kolab_Server_Connection_Simpleldap($ldap);
+ $this->assertSame($ldap, $conn->getRead());
+ }
+
+ public function testMethodGetreadHasResultNetldap2TheHandledConnection()
+ {
+ $ldap = $this->getMock('Net_LDAP2');
+ $conn = new Horde_Kolab_Server_Connection_Simpleldap($ldap);
+ $this->assertType('Net_LDAP2', $conn->getRead());
+ }
+
+ public function testMethodGetwriteHasResultNetldap2TheHandledConnection()
+ {
+ $ldap = $this->getMock('Net_LDAP2');
+ $conn = new Horde_Kolab_Server_Connection_Simpleldap($ldap);
+ $this->assertSame($conn->getWrite(), $conn->getRead());
+ }
+}
diff --git a/framework/Kolab_Server/test/Horde/Kolab/Server/Connection/SplittedldapTest.php b/framework/Kolab_Server/test/Horde/Kolab/Server/Connection/SplittedldapTest.php
new file mode 100644
index 000000000..e5901316f
--- /dev/null
+++ b/framework/Kolab_Server/test/Horde/Kolab/Server/Connection/SplittedldapTest.php
@@ -0,0 +1,78 @@
+
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Kolab_Server
+ */
+
+/**
+ * Prepare the test setup.
+ */
+require_once dirname(__FILE__) . '/../Autoload.php';
+
+/**
+ * Test the handler for a LDAP master/slave setup.
+ *
+ * Copyright 2008-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 Kolab_Server
+ * @author Gunnar Wrobel
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Kolab_Server
+ */
+class Horde_Kolab_Server_Connection_SplittedTest extends PHPUnit_Framework_TestCase
+{
+ public function setUp()
+ {
+ if (!extension_loaded('ldap') && !@dl('ldap.' . PHP_SHLIB_SUFFIX)) {
+ $this->markTestSuiteSkipped('Ldap extension is missing!');
+ };
+
+ if (!class_exists('Net_LDAP2')) {
+ $this->markTestSuiteSkipped('PEAR package Net_LDAP2 is not installed!');
+ }
+ }
+
+ public function testMethodConstructHasParameterNetldap2ReadConnectionAndParameterNetldap2WriteConnection()
+ {
+ $ldap_read = $this->getMock('Net_LDAP2');
+ $ldap_write = $this->getMock('Net_LDAP2');
+ $conn = new Horde_Kolab_Server_Connection_Splittedldap($ldap_read, $ldap_write);
+ }
+
+ public function testMethodConstructHasPostconditionThatTheGivenServersWereStored()
+ {
+ $ldap_read = $this->getMock('Net_LDAP2');
+ $ldap_write = $this->getMock('Net_LDAP2');
+ $conn = new Horde_Kolab_Server_Connection_Splittedldap($ldap_read, $ldap_write);
+ $this->assertSame($ldap_read, $conn->getRead());
+ $this->assertSame($ldap_write, $conn->getWrite());
+ }
+
+ public function testMethodGetreadHasResultNetldap2TheHandledConnection()
+ {
+ $ldap_read = $this->getMock('Net_LDAP2');
+ $ldap_write = $this->getMock('Net_LDAP2');
+ $conn = new Horde_Kolab_Server_Connection_Splittedldap($ldap_read, $ldap_write);
+ $this->assertType('Net_LDAP2', $conn->getRead());
+ $this->assertType('Net_LDAP2', $conn->getWrite());
+ }
+
+ public function testMethodGetwriteHasResultNetldap2TheHandledConnection()
+ {
+ $ldap_read = $this->getMock('Net_LDAP2');
+ $ldap_write = $this->getMock('Net_LDAP2');
+ $conn = new Horde_Kolab_Server_Connection_Splittedldap($ldap_read, $ldap_write);
+ $this->assertFalse($conn->getWrite() === $conn->getRead());
+ }
+}
diff --git a/framework/Kolab_Server/test/Horde/Kolab/Server/GroupTest.php b/framework/Kolab_Server/test/Horde/Kolab/Server/GroupTest.php
index c69a8f53d..36af340d0 100644
--- a/framework/Kolab_Server/test/Horde/Kolab/Server/GroupTest.php
+++ b/framework/Kolab_Server/test/Horde/Kolab/Server/GroupTest.php
@@ -40,6 +40,8 @@ class Horde_Kolab_Server_GroupTest extends Horde_Kolab_Server_Scenario
*/
protected function setUp()
{
+ parent::setUp();
+
$this->ldap = $this->getKolabMockServer();
}
@@ -121,8 +123,6 @@ class Horde_Kolab_Server_GroupTest extends Horde_Kolab_Server_Scenario
*/
public function testListingGroups()
{
- $this->assertEquals(0, count($GLOBALS['KOLAB_SERVER_TEST_DATA']));
-
$result = $this->ldap->search(
'(&(!(cn=domains))(objectClass=kolabGroupOfNames))',
array(),
diff --git a/framework/Kolab_Server/test/Horde/Kolab/Server/InetorgpersonTest.php b/framework/Kolab_Server/test/Horde/Kolab/Server/InetorgpersonTest.php
index d54367725..7ff3debcd 100644
--- a/framework/Kolab_Server/test/Horde/Kolab/Server/InetorgpersonTest.php
+++ b/framework/Kolab_Server/test/Horde/Kolab/Server/InetorgpersonTest.php
@@ -68,6 +68,8 @@ class Horde_Kolab_Server_InetorgpersonTest extends Horde_Kolab_Server_Scenario
*/
protected function setUp()
{
+ parent::setUp();
+
$this->initializeEnvironments();
$this->servers = $this->getKolabServers();
}
diff --git a/framework/Kolab_Server/test/Horde/Kolab/Server/KolabgermanbankarrangementTest.php b/framework/Kolab_Server/test/Horde/Kolab/Server/KolabgermanbankarrangementTest.php
index 7eff469bc..57bf376b6 100644
--- a/framework/Kolab_Server/test/Horde/Kolab/Server/KolabgermanbankarrangementTest.php
+++ b/framework/Kolab_Server/test/Horde/Kolab/Server/KolabgermanbankarrangementTest.php
@@ -60,6 +60,8 @@ class Horde_Kolab_Server_KolabgermanbankarrangementTest extends Horde_Kolab_Serv
*/
protected function setUp()
{
+ parent::setUp();
+
$this->initializeEnvironments();
$this->servers = $this->getKolabServers();
}
diff --git a/framework/Kolab_Server/test/Horde/Kolab/Server/KolabinetorgpersonTest.php b/framework/Kolab_Server/test/Horde/Kolab/Server/KolabinetorgpersonTest.php
index 75410d924..3b616d74c 100644
--- a/framework/Kolab_Server/test/Horde/Kolab/Server/KolabinetorgpersonTest.php
+++ b/framework/Kolab_Server/test/Horde/Kolab/Server/KolabinetorgpersonTest.php
@@ -60,6 +60,8 @@ class Horde_Kolab_Server_KolabinetorgpersonTest extends Horde_Kolab_Server_Scena
*/
protected function setUp()
{
+ parent::setUp();
+
$this->initializeEnvironments();
$this->servers = $this->getKolabServers();
}
diff --git a/framework/Kolab_Server/test/Horde/Kolab/Server/Kolabpop3accountTest.php b/framework/Kolab_Server/test/Horde/Kolab/Server/Kolabpop3accountTest.php
index 157abd080..646f3630c 100644
--- a/framework/Kolab_Server/test/Horde/Kolab/Server/Kolabpop3accountTest.php
+++ b/framework/Kolab_Server/test/Horde/Kolab/Server/Kolabpop3accountTest.php
@@ -62,6 +62,8 @@ class Horde_Kolab_Server_Kolabpop3accountTest extends Horde_Kolab_Server_Scenari
*/
protected function setUp()
{
+ parent::setUp();
+
$this->initializeEnvironments();
$this->servers = $this->getKolabServers();
}
@@ -183,27 +185,23 @@ class Horde_Kolab_Server_Kolabpop3accountTest extends Horde_Kolab_Server_Scenari
$account_data = $this->objects[1];
$account_data[Horde_Kolab_Server_Object_Kolabpop3account::ATTRIBUTE_OWNERUID] = $person->getUid();
$account = $server->add($account_data);
- $this->assertNoError($account);
-
$account = $server->fetch($account->getUid());
- $this->assertNoError($account);
$this->assertEquals($this->objects[1][Horde_Kolab_Server_Object_Kolabpop3account::ATTRIBUTE_SERVER],
$account->get(Horde_Kolab_Server_Object_Kolabpop3account::ATTRIBUTE_SERVER));
$result = $account->save(array(Horde_Kolab_Server_Object_Kolabpop3account::ATTRIBUTE_SERVER => 'pop3s.example.com'));
- $this->assertNoError($result);
$account = $server->fetch($account->getUid());
- $this->assertNoError($account);
- $this->assertEquals($account->get(Horde_Kolab_Server_Object_Kolabpop3account::ATTRIBUTE_SERVER),
- 'pop3s.example.com');
+ $this->assertContains(
+ 'pop3s.example.com',
+ $account->get(Horde_Kolab_Server_Object_Kolabpop3account::ATTRIBUTE_SERVER, false)
+ );
$this->assertContains('frank@example.com', $account->getUid());
$result = $server->delete($account->getUid());
- $this->assertNoError($result);
}
}
}
diff --git a/framework/Kolab_Server/test/Horde/Kolab/Server/LdapBase.php b/framework/Kolab_Server/test/Horde/Kolab/Server/LdapBase.php
new file mode 100644
index 000000000..1af198444
--- /dev/null
+++ b/framework/Kolab_Server/test/Horde/Kolab/Server/LdapBase.php
@@ -0,0 +1,45 @@
+
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Kolab_Server
+ */
+
+/**
+ * Prepare the test setup.
+ */
+require_once dirname(__FILE__) . '/Autoload.php';
+
+/**
+ * Skip LDAP based tests if we don't have ldap or Net_LDAP2.
+ *
+ * Copyright 2008-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 Kolab_Server
+ * @author Gunnar Wrobel
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Kolab_Server
+ */
+class Horde_Kolab_Server_LdapBase extends PHPUnit_Framework_TestCase
+{
+ public function setUp()
+ {
+ if (!extension_loaded('ldap') && !@dl('ldap.' . PHP_SHLIB_SUFFIX)) {
+ $this->markTestSuiteSkipped('Ldap extension is missing!');
+ };
+
+ if (!class_exists('Net_LDAP2')) {
+ $this->markTestSuiteSkipped('PEAR package Net_LDAP2 is not installed!');
+ }
+ }
+}
\ No newline at end of file
diff --git a/framework/Kolab_Server/test/Horde/Kolab/Server/ObjectTest.php b/framework/Kolab_Server/test/Horde/Kolab/Server/ObjectTest.php
index 0b830e9b2..4ac9bcea0 100644
--- a/framework/Kolab_Server/test/Horde/Kolab/Server/ObjectTest.php
+++ b/framework/Kolab_Server/test/Horde/Kolab/Server/ObjectTest.php
@@ -42,6 +42,8 @@ class Horde_Kolab_Server_ObjectTest extends Horde_Kolab_Server_Scenario
*/
protected function setUp()
{
+ parent::setUp();
+
$this->_dummydb = new DummyDB();
}
diff --git a/framework/Kolab_Server/test/Horde/Kolab/Server/OrgPersonTest.php b/framework/Kolab_Server/test/Horde/Kolab/Server/OrgPersonTest.php
index 667ccb188..c720ce067 100644
--- a/framework/Kolab_Server/test/Horde/Kolab/Server/OrgPersonTest.php
+++ b/framework/Kolab_Server/test/Horde/Kolab/Server/OrgPersonTest.php
@@ -60,6 +60,8 @@ class Horde_Kolab_Server_OrgPersonTest extends Horde_Kolab_Server_Scenario
*/
protected function setUp()
{
+ parent::setUp();
+
$this->initializeEnvironments();
$this->servers = $this->getKolabServers();
}
diff --git a/framework/Kolab_Server/test/Horde/Kolab/Server/PersonTest.php b/framework/Kolab_Server/test/Horde/Kolab/Server/PersonTest.php
index 90016e36c..de1b0b644 100644
--- a/framework/Kolab_Server/test/Horde/Kolab/Server/PersonTest.php
+++ b/framework/Kolab_Server/test/Horde/Kolab/Server/PersonTest.php
@@ -114,6 +114,8 @@ class Horde_Kolab_Server_PersonTest extends Horde_Kolab_Server_Scenario
*/
protected function setUp()
{
+ parent::setUp();
+
$this->initializeEnvironments();
$this->servers = $this->getKolabServers();
}
diff --git a/framework/Kolab_Server/test/Horde/Kolab/Server/Query/ElementTest.php b/framework/Kolab_Server/test/Horde/Kolab/Server/Query/ElementTest.php
new file mode 100644
index 000000000..01f45783f
--- /dev/null
+++ b/framework/Kolab_Server/test/Horde/Kolab/Server/Query/ElementTest.php
@@ -0,0 +1,212 @@
+
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Kolab_Server
+ */
+
+/**
+ * Require our basic test case definition
+ */
+require_once dirname(__FILE__) . '/../Autoload.php';
+
+/**
+ * Test the LDAP query elements.
+ *
+ * Copyright 2008-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 Kolab_Server
+ * @author Gunnar Wrobel
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Kolab_Server
+ */
+class Horde_Kolab_Server_Query_ElementTest extends PHPUnit_Framework_TestCase
+{
+ public function setUp()
+ {
+ $this->writer = $this->getMock(
+ 'Horde_Kolab_Server_Query_Ldap', array(), array(), '', false
+ );
+ }
+
+ public function testClassAndMethodConvertHasResultMixedTheConvertedElement()
+ {
+ $this->writer->expects($this->exactly(1))
+ ->method('convertAnd')
+ ->will($this->returnValue('converted'));
+ $and = new Horde_Kolab_Server_Query_Element_And(array());
+ $this->assertEquals('converted', $and->convert($this->writer));
+ }
+
+ public function testClassApproxMethodConvertHasResultMixedTheConvertedElement()
+ {
+ $this->writer->expects($this->exactly(1))
+ ->method('convertApprox')
+ ->will($this->returnValue('converted'));
+ $approx = new Horde_Kolab_Server_Query_Element_Approx('', '');
+ $this->assertEquals('converted', $approx->convert($this->writer));
+ }
+
+ public function testClassBeginsMethodConvertHasResultMixedTheConvertedElement()
+ {
+ $this->writer->expects($this->exactly(1))
+ ->method('convertBegins')
+ ->will($this->returnValue('converted'));
+ $begins = new Horde_Kolab_Server_Query_Element_Begins('', '');
+ $this->assertEquals('converted', $begins->convert($this->writer));
+ }
+
+ public function testClassContainsMethodConvertHasResultMixedTheConvertedElement()
+ {
+ $this->writer->expects($this->exactly(1))
+ ->method('convertContains')
+ ->will($this->returnValue('converted'));
+ $contains = new Horde_Kolab_Server_Query_Element_Contains('', '');
+ $this->assertEquals('converted', $contains->convert($this->writer));
+ }
+
+ public function testClassEndsMethodConvertHasResultMixedTheConvertedElement()
+ {
+ $this->writer->expects($this->exactly(1))
+ ->method('convertEnds')
+ ->will($this->returnValue('converted'));
+ $ends = new Horde_Kolab_Server_Query_Element_Ends('', '');
+ $this->assertEquals('converted', $ends->convert($this->writer));
+ }
+
+ public function testClassEqualsMethodConvertHasResultMixedTheConvertedElement()
+ {
+ $this->writer->expects($this->exactly(1))
+ ->method('convertEquals')
+ ->will($this->returnValue('converted'));
+ $Equals = new Horde_Kolab_Server_Query_Element_Equals('', '');
+ $this->assertEquals('converted', $Equals->convert($this->writer));
+ }
+
+ public function testClassGreaterMethodConvertHasResultMixedTheConvertedElement()
+ {
+ $this->writer->expects($this->exactly(1))
+ ->method('convertGreater')
+ ->will($this->returnValue('converted'));
+ $Greater = new Horde_Kolab_Server_Query_Element_Greater('', '');
+ $this->assertEquals('converted', $Greater->convert($this->writer));
+ }
+
+ public function testClassLessMethodConvertHasResultMixedTheConvertedElement()
+ {
+ $this->writer->expects($this->exactly(1))
+ ->method('convertLess')
+ ->will($this->returnValue('converted'));
+ $less = new Horde_Kolab_Server_Query_Element_Less('', '');
+ $this->assertEquals('converted', $less->convert($this->writer));
+ }
+
+ public function testClassNotMethodConstructHasPostconditionThatTheElementWasSavedAsArray()
+ {
+ $less = new Horde_Kolab_Server_Query_Element_Less('', '');
+ $not = new Horde_Kolab_Server_Query_Element_Not($less);
+ $this->assertType('array', $not->getElements());
+ }
+
+ public function testClassNotMethodConvertHasResultMixedTheConvertedElement()
+ {
+ $this->writer->expects($this->exactly(1))
+ ->method('convertNot')
+ ->will($this->returnValue('converted'));
+ $less = new Horde_Kolab_Server_Query_Element_Less('', '');
+ $not = new Horde_Kolab_Server_Query_Element_Not($less);
+ $this->assertEquals('converted', $not->convert($this->writer));
+ }
+
+ public function testClassOrMethodConvertHasResultMixedTheConvertedElement()
+ {
+ $this->writer->expects($this->exactly(1))
+ ->method('convertOr')
+ ->will($this->returnValue('converted'));
+ $or = new Horde_Kolab_Server_Query_Element_Or(array());
+ $this->assertEquals('converted', $or->convert($this->writer));
+ }
+
+ public function testClassGroupMethodConstructHasParameterArrayElements()
+ {
+ $or = new Horde_Kolab_Server_Query_Element_Or(array());
+ }
+
+ public function testClassGroupMethodConstructHasPostconditionThatTheElementsWereSaved()
+ {
+ $or = new Horde_Kolab_Server_Query_Element_Or(array());
+ $this->assertEquals(array(), $or->getElements());
+ }
+
+ /**
+ * @expectedException Exception
+ */
+ public function testClassGroupMethodGetnameThrowsException()
+ {
+ $or = new Horde_Kolab_Server_Query_Element_Or(array());
+ $or->getName();
+ }
+
+ /**
+ * @expectedException Exception
+ */
+ public function testClassGroupMethodGetvalueThrowsException()
+ {
+ $or = new Horde_Kolab_Server_Query_Element_Or(array());
+ $or->getValue();
+ }
+
+ public function testClassGroupMethodGetelementsHasResultArrayTheGroupElements()
+ {
+ $or = new Horde_Kolab_Server_Query_Element_Or(array());
+ $this->assertEquals(array(), $or->getElements());
+ }
+
+ public function testClassSingleMethodConstructHasParameterStringName()
+ {
+ $equals = new Horde_Kolab_Server_Query_Element_Equals('name', '');
+ }
+
+ public function testClassSingleMethodConstructHasParameterStringValue()
+ {
+ $equals = new Horde_Kolab_Server_Query_Element_Equals('', 'value');
+ }
+
+ public function testClassSingleMethodConstructHasPostconditionThatNameAndValueWereSaved()
+ {
+ $equals = new Horde_Kolab_Server_Query_Element_Equals('name', 'value');
+ $this->assertEquals('name', $equals->getName());
+ $this->assertEquals('value', $equals->getValue());
+ }
+
+ public function testClassSingleMethodGetnameHasResultStringTheName()
+ {
+ $equals = new Horde_Kolab_Server_Query_Element_Equals('name', '');
+ $this->assertEquals('name', $equals->getName());
+ }
+
+ public function testClassSingleMethodGetvalueHasResultStringTheValue()
+ {
+ $equals = new Horde_Kolab_Server_Query_Element_Equals('', 'value');
+ $this->assertEquals('value', $equals->getValue());
+ }
+
+ /**
+ * @expectedException Exception
+ */
+ public function testClassSingleMethodGetelementsThrowsException()
+ {
+ $equals = new Horde_Kolab_Server_Query_Element_Equals('', '');
+ $equals->getElements();
+ }
+}
diff --git a/framework/Kolab_Server/test/Horde/Kolab/Server/Query/LdapTest.php b/framework/Kolab_Server/test/Horde/Kolab/Server/Query/LdapTest.php
new file mode 100644
index 000000000..85e44baae
--- /dev/null
+++ b/framework/Kolab_Server/test/Horde/Kolab/Server/Query/LdapTest.php
@@ -0,0 +1,181 @@
+
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Kolab_Server
+ */
+
+/**
+ * Require our basic test case definition
+ */
+require_once dirname(__FILE__) . '/../LdapBase.php';
+
+/**
+ * Test the LDAP query handler.
+ *
+ * Copyright 2008-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 Kolab_Server
+ * @author Gunnar Wrobel
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Kolab_Server
+ */
+class Horde_Kolab_Server_Query_LdapTest extends Horde_Kolab_Server_LdapBase
+{
+
+ public function testMethodConstructHasParameterQueryelementTheQueryCriteria()
+ {
+ $equals = new Horde_Kolab_Server_Query_Element_Equals('equals', 'equals');
+ $query = new Horde_Kolab_Server_Query_Ldap($equals);
+ }
+
+ public function testMethodConstructHasPostconditionThatTheQueryCriteriaWereSaved()
+ {
+ $equals = new Horde_Kolab_Server_Query_Element_Equals('equals', 'equals');
+ $query = new Horde_Kolab_Server_Query_Ldap($equals);
+ $this->assertEquals(
+ '(equals=equals)',
+ (string) $query
+ );
+ }
+
+ public function testMethodTostringHasResultStringTheQuery()
+ {
+ $equals = new Horde_Kolab_Server_Query_Element_Equals('equals', 'equals');
+ $contains = new Horde_Kolab_Server_Query_Element_Equals('contains', 'contains');
+ $or = new Horde_Kolab_Server_Query_Element_Or(array($equals, $contains));
+ $query = new Horde_Kolab_Server_Query_Ldap($or);
+ $this->assertEquals(
+ '(|(equals=equals)(contains=contains))',
+ (string) $query
+ );
+ }
+
+ public function testMethodConvertequealsHasResultNetldapfilter()
+ {
+ $equals = new Horde_Kolab_Server_Query_Element_Equals('equals', 'equals');
+ $query = new Horde_Kolab_Server_Query_Ldap($equals);
+ $this->assertEquals(
+ '(equals=equals)',
+ $query->convertEquals($equals)->asString()
+ );
+ }
+
+ public function testMethodConvertbeginsHasResultNetldapfilter()
+ {
+ $begins = new Horde_Kolab_Server_Query_Element_Begins('begins', 'begins');
+ $query = new Horde_Kolab_Server_Query_Ldap($begins);
+ $this->assertEquals(
+ '(begins=begins*)',
+ $query->convertBegins($begins)->asString()
+ );
+ }
+
+ public function testMethodConvertendsHasResultNetldapfilter()
+ {
+ $ends = new Horde_Kolab_Server_Query_Element_Ends('ends', 'ends');
+ $query = new Horde_Kolab_Server_Query_Ldap($ends);
+ $this->assertEquals(
+ '(ends=*ends)',
+ $query->convertEnds($ends)->asString()
+ );
+ }
+
+ public function testMethodConvertcontainsHasResultNetldapfilter()
+ {
+ $contains = new Horde_Kolab_Server_Query_Element_Contains('contains', 'contains');
+ $query = new Horde_Kolab_Server_Query_Ldap($contains);
+ $this->assertEquals(
+ '(contains=*contains*)',
+ $query->convertContains($contains)->asString()
+ );
+ }
+
+ public function testMethodConvertlessHasResultNetldapfilter()
+ {
+ $less = new Horde_Kolab_Server_Query_Element_Less('less', 'less');
+ $query = new Horde_Kolab_Server_Query_Ldap($less);
+ $this->assertEquals(
+ '(lessconvertLess($less)->asString()
+ );
+ }
+
+ public function testMethodConvertgreaterHasResultNetldapfilter()
+ {
+ $greater = new Horde_Kolab_Server_Query_Element_Greater('greater', 'greater');
+ $query = new Horde_Kolab_Server_Query_Ldap($greater);
+ $this->assertEquals(
+ '(greater>greater)',
+ $query->convertGreater($greater)->asString()
+ );
+ }
+
+ public function testMethodConvertapproxHasResultNetldapfilter()
+ {
+ $approx = new Horde_Kolab_Server_Query_Element_Approx('approx', 'approx');
+ $query = new Horde_Kolab_Server_Query_Ldap($approx);
+ $this->assertEquals(
+ '(approx~=approx)',
+ $query->convertApprox($approx)->asString()
+ );
+ }
+
+ public function testMethodConvertnotHasResultNetldapfilter()
+ {
+ $equals = new Horde_Kolab_Server_Query_Element_Equals('equals', 'equals');
+ $not = new Horde_Kolab_Server_Query_Element_Not($equals);
+ $query = new Horde_Kolab_Server_Query_Ldap($not);
+ $this->assertEquals(
+ '(!(equals=equals))',
+ $query->convertNot($not)->asString()
+ );
+ }
+
+ public function testMethodConvertandHasResultNetldapfilter()
+ {
+ $equals = new Horde_Kolab_Server_Query_Element_Equals('equals', 'equals');
+ $contains = new Horde_Kolab_Server_Query_Element_Equals('contains', 'contains');
+ $and = new Horde_Kolab_Server_Query_Element_And(array($equals, $contains));
+ $query = new Horde_Kolab_Server_Query_Ldap($and);
+ $this->assertEquals(
+ '(&(equals=equals)(contains=contains))',
+ $query->convertAnd($and)->asString()
+ );
+ }
+
+ public function testMethodConvertorHasResultNetldapfilter()
+ {
+ $equals = new Horde_Kolab_Server_Query_Element_Equals('equals', 'equals');
+ $contains = new Horde_Kolab_Server_Query_Element_Equals('contains', 'contains');
+ $or = new Horde_Kolab_Server_Query_Element_Or(array($equals, $contains));
+ $query = new Horde_Kolab_Server_Query_Ldap($or);
+ $this->assertEquals(
+ '(|(equals=equals)(contains=contains))',
+ $query->convertOr($or)->asString()
+ );
+ }
+
+ public function testMethodConvertorThrowsExceptionIfLessThanTwoElementsWereProvided()
+ {
+ $equals = new Horde_Kolab_Server_Query_Element_Equals('equals', 'equals');
+ $or = new Horde_Kolab_Server_Query_Element_Or(array($equals));
+ $query = new Horde_Kolab_Server_Query_Ldap($or);
+ try {
+ $query->convertOr($or)->asString();
+ $this->fail('No exception!');
+ } catch (Horde_Kolab_Server_Exception $e) {
+ $this->assertEquals(Horde_Kolab_Server_Exception::INVALID_QUERY, $e->getCode());
+ }
+ }
+}
diff --git a/framework/Kolab_Server/test/Horde/Kolab/Server/Result/LdapTest.php b/framework/Kolab_Server/test/Horde/Kolab/Server/Result/LdapTest.php
new file mode 100644
index 000000000..4da773a7b
--- /dev/null
+++ b/framework/Kolab_Server/test/Horde/Kolab/Server/Result/LdapTest.php
@@ -0,0 +1,90 @@
+
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Kolab_Server
+ */
+
+/**
+ * Prepare the test setup.
+ */
+require_once dirname(__FILE__) . '/../Autoload.php';
+
+/**
+ * Test the LDAP result handler.
+ *
+ * Copyright 2008-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 Kolab_Server
+ * @author Gunnar Wrobel
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Kolab_Server
+ */
+class Horde_Kolab_Server_Result_LdapTest extends PHPUnit_Framework_TestCase
+{
+ public function setUp()
+ {
+ if (!extension_loaded('ldap') && !@dl('ldap.' . PHP_SHLIB_SUFFIX)) {
+ $this->markTestSuiteSkipped('Ldap extension is missing!');
+ };
+
+ if (!class_exists('Net_LDAP2')) {
+ $this->markTestSuiteSkipped('PEAR package Net_LDAP2 is not installed!');
+ }
+ }
+
+ public function testMethodConstructHasParameterNetldap2searchSearchResult()
+ {
+ $search = $this->getMock(
+ 'Net_LDAP2_Search', array(), array(), '', false
+ );
+ $result = new Horde_Kolab_Server_Result_Ldap($search);
+ }
+
+
+ public function testMethodCountHasResultIntTheNumberOfElementsFound()
+ {
+ $search = $this->getMock(
+ 'Net_LDAP2_Search', array('count'), array(), '', false
+ );
+ $search->expects($this->exactly(1))
+ ->method('count')
+ ->will($this->returnValue(1));
+ $result = new Horde_Kolab_Server_Result_Ldap($search);
+ $this->assertEquals(1, $result->count());
+ }
+
+ public function testMethodSizelimitexceededHasResultBooleanIndicatingIfTheSearchSizeLimitWasHit()
+ {
+ $search = $this->getMock(
+ 'Net_LDAP2_Search', array('sizeLimitExceeded'), array(), '', false
+ );
+ $search->expects($this->exactly(1))
+ ->method('sizeLimitExceeded')
+ ->will($this->returnValue(true));
+ $result = new Horde_Kolab_Server_Result_Ldap($search);
+ $this->assertTrue($result->sizeLimitExceeded());
+ }
+
+ public function testMethodAsarrayHasResultArrayWithTheSearchResults()
+ {
+ $search = $this->getMock(
+ 'Net_LDAP2_Search', array('as_struct'), array(), '', false
+ );
+ $search->expects($this->exactly(1))
+ ->method('as_struct')
+ ->will($this->returnValue(array('a' => 'a')));
+ $result = new Horde_Kolab_Server_Result_Ldap($search);
+ $this->assertEquals(array('a' => 'a'), $result->asArray());
+ }
+}
diff --git a/framework/Kolab_Server/test/Horde/Kolab/Server/Scenario.php b/framework/Kolab_Server/test/Horde/Kolab/Server/Scenario.php
index f2f62b033..b8c8df11c 100644
--- a/framework/Kolab_Server/test/Horde/Kolab/Server/Scenario.php
+++ b/framework/Kolab_Server/test/Horde/Kolab/Server/Scenario.php
@@ -65,12 +65,6 @@ class Horde_Kolab_Server_Scenario extends PHPUnit_Extensions_Story_TestCase
}
break;
case 'several Kolab servers':
- foreach ($this->getEnvironments() as $environment) {
- $this->prepareInjector($environment);
- $this->prepareKolabServerConfiguration($environment);
- $this->prepareKolabServer($environment);
- }
- break;
case 'the test environments':
$this->initializeEnvironments();
break;
@@ -338,6 +332,23 @@ class Horde_Kolab_Server_Scenario extends PHPUnit_Extensions_Story_TestCase
}
/**
+ * Prepare the log handler for the given environment.
+ *
+ * @param string $environment The name of the environment.
+ *
+ * @return NULL
+ */
+ public function prepareLogger($environment)
+ {
+ $logger = new Horde_Log_Logger();
+ $handler = new Horde_Log_Handler_Mock();
+ $logger->addHandler($handler);
+
+ $this->world['injector'][$environment]->setInstance('Horde_Log_Logger',
+ $logger);
+ }
+
+ /**
* Prepare the server configuration for the given environment.
*
* @param string $environment The name of the environment.
@@ -401,6 +412,7 @@ class Horde_Kolab_Server_Scenario extends PHPUnit_Extensions_Story_TestCase
public function initializeEnvironment($environment)
{
$this->prepareInjector($environment);
+ $this->prepareLogger($environment);
$this->prepareKolabServerConfiguration($environment);
$this->prepareKolabServer($environment);
}
@@ -1045,11 +1057,21 @@ class Horde_Kolab_Server_Scenario extends PHPUnit_Extensions_Story_TestCase
}
/**
+ * Setup function.
+ *
+ * @return NULL.
+ */
+ protected function setUp()
+ {
+ $this->added = array();
+ }
+
+ /**
* Cleanup function.
*
* @return NULL.
*/
- public function tearDown()
+ protected function tearDown()
{
if (isset($this->added)) {
$added = array_reverse($this->added);
diff --git a/framework/Kolab_Server/test/Horde/Kolab/Server/Server/FactoryTest.php b/framework/Kolab_Server/test/Horde/Kolab/Server/Server/FactoryTest.php
new file mode 100644
index 000000000..4289a9eee
--- /dev/null
+++ b/framework/Kolab_Server/test/Horde/Kolab/Server/Server/FactoryTest.php
@@ -0,0 +1,120 @@
+
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Kolab_Server
+ */
+
+/**
+ * Prepare the test setup.
+ */
+require_once dirname(__FILE__) . '/../Autoload.php';
+
+/**
+ * Test the server factory interface.
+ *
+ * Copyright 2008-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 Kolab_Server
+ * @author Gunnar Wrobel
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Kolab_Server
+ */
+class Horde_Kolab_Server_Server_FactoryTest extends Horde_Kolab_Server_Scenario
+{
+ public function testMethodSetupHasPostconditionThatAObjectHandlerOfTypeBaseIsBoundToObjects()
+ {
+ $injector = new Horde_Injector(new Horde_Injector_TopLevel());
+ Horde_Kolab_Server_Factory::setup(array(), $injector);
+ $this->assertType(
+ 'Horde_Kolab_Server_Objects_Base',
+ $injector->getInstance('Horde_Kolab_Server_Objects')
+ );
+ }
+
+ public function testMethodSetupHasPostconditionThatASchemaHandlerOfTypeBaseIsBoundToSchema()
+ {
+ $injector = new Horde_Injector(new Horde_Injector_TopLevel());
+ Horde_Kolab_Server_Factory::setup(array(), $injector);
+ $this->assertType(
+ 'Horde_Kolab_Server_Schema_Base',
+ $injector->getInstance('Horde_Kolab_Server_Schema')
+ );
+ }
+
+ public function testMethodSetupHasPostconditionThatASearchHandlerOfTypeBaseIsBoundToSearch()
+ {
+ $injector = new Horde_Injector(new Horde_Injector_TopLevel());
+ Horde_Kolab_Server_Factory::setup(array(), $injector);
+ $this->assertType(
+ 'Horde_Kolab_Server_Search_Base',
+ $injector->getInstance('Horde_Kolab_Server_Search')
+ );
+ }
+
+ public function testMethodSetupHasPostconditionThatAStructureOfTypeBaseIsBoundToStructure()
+ {
+ $injector = new Horde_Injector(new Horde_Injector_TopLevel());
+ Horde_Kolab_Server_Factory::setup(array(), $injector);
+ $this->assertType(
+ 'Horde_Kolab_Server_Structure_Kolab',
+ $injector->getInstance('Horde_Kolab_Server_Structure')
+ );
+ }
+
+ public function testMethodSetupHasPostconditionThatAStructureHandlerOfTypeLdapIsBoundToStructureIfConfiguredThatWay()
+ {
+ $injector = new Horde_Injector(new Horde_Injector_TopLevel());
+ Horde_Kolab_Server_Factory::setup(
+ array('structure' => array('driver' => 'ldap')),
+ $injector
+ );
+ $this->assertType(
+ 'Horde_Kolab_Server_Structure_Ldap',
+ $injector->getInstance('Horde_Kolab_Server_Structure')
+ );
+ }
+
+ public function testMethodSetupHasPostconditionThatAServerOfTypeLdapIsBoundToServer()
+ {
+ $injector = new Horde_Injector(new Horde_Injector_TopLevel());
+ Horde_Kolab_Server_Factory::setup(array(), $injector);
+ $this->assertType(
+ 'Horde_Kolab_Server_Ldap',
+ $injector->getInstance('Horde_Kolab_Server')
+ );
+ }
+
+ public function testMethodSetupHasPostconditionThatAServerOfTypeLdapIsBoundToServerIfConfiguredThatWay()
+ {
+ $injector = new Horde_Injector(new Horde_Injector_TopLevel());
+ Horde_Kolab_Server_Factory::setup(
+ array('driver' => 'file', 'params' => array('file' => '/tmp/nix')),
+ $injector
+ );
+ $this->assertType(
+ 'Horde_Kolab_Server_File',
+ $injector->getInstance('Horde_Kolab_Server')
+ );
+ }
+
+ public function testMethodSingletonReturnsTheSameInstanceWithTheSameParameters()
+ {
+ Horde_Kolab_Server_Factory::singleton();
+ }
+
+ public function testMethodSingletonReturnsDifferentInstancesWithDifferentParameters()
+ {
+ Horde_Kolab_Server_Factory::singleton();
+ }
+}
\ No newline at end of file
diff --git a/framework/Kolab_Server/test/Horde/Kolab/Server/Server/InterfaceTest.php b/framework/Kolab_Server/test/Horde/Kolab/Server/Server/InterfaceTest.php
new file mode 100644
index 000000000..c8fe1649a
--- /dev/null
+++ b/framework/Kolab_Server/test/Horde/Kolab/Server/Server/InterfaceTest.php
@@ -0,0 +1,36 @@
+
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Kolab_Server
+ */
+
+/**
+ * Prepare the test setup.
+ */
+require_once dirname(__FILE__) . '/../Autoload.php';
+
+/**
+ * Test the server interface.
+ *
+ * Copyright 2008-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 Kolab_Server
+ * @author Gunnar Wrobel
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Kolab_Server
+ */
+class Horde_Kolab_Server_Server_InterfaceTest extends Horde_Kolab_Server_Scenario
+{
+
+}
\ No newline at end of file
diff --git a/framework/Kolab_Server/test/Horde/Kolab/Server/Server/LdapTest.php b/framework/Kolab_Server/test/Horde/Kolab/Server/Server/LdapTest.php
new file mode 100644
index 000000000..c4e070ccb
--- /dev/null
+++ b/framework/Kolab_Server/test/Horde/Kolab/Server/Server/LdapTest.php
@@ -0,0 +1,363 @@
+
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Kolab_Server
+ */
+
+/**
+ * Require our basic test case definition
+ */
+require_once dirname(__FILE__) . '/../LdapBase.php';
+
+/**
+ * Test the LDAP backend.
+ *
+ * Copyright 2008-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 Kolab_Server
+ * @author Gunnar Wrobel
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Kolab_Server
+ */
+class Horde_Kolab_Server_Server_LdapTest extends Horde_Kolab_Server_LdapBase
+{
+ public function setUp()
+ {
+ parent::setUp();
+
+ $this->logger = new Horde_Log_Handler_Mock();
+
+ $injector = new Horde_Injector(new Horde_Injector_TopLevel());
+ Horde_Kolab_Server_Factory::setup(
+ array('logger' => new Horde_Log_Logger($this->logger)), $injector
+ );
+ $this->server = $injector->getInstance('Horde_Kolab_Server');
+ }
+
+ public function testMethodConnectuidHasPostconditionThatTheUidIsSetIfTheConnectionWasSuccessful()
+ {
+ $ldap = $this->getMock('Net_LDAP2', array('bind'));
+ $ldap->expects($this->exactly(1))
+ ->method('bind')
+ ->will($this->returnValue(true));
+ $this->server->setLdap($ldap);
+ $this->server->connectUid('test', 'test');
+ $this->assertEquals('test', $this->server->uid);
+ }
+
+ public function testMethodConnectuidThrowsExceptionIfTheConnectionFailed()
+ {
+ $ldap = $this->getMock('Net_LDAP2', array('bind'));
+ $ldap->expects($this->exactly(1))
+ ->method('bind')
+ ->will($this->returnValue(PEAR::raiseError('Bind failed!')));
+ $this->server->setLdap($ldap);
+ try {
+ $this->server->connectUid('test', 'test');
+ $this->fail('No exception!');
+ } catch (Exception $e) {
+ $this->assertEquals('Bind failed!', $e->getMessage());
+ $this->assertEquals(Horde_Kolab_Server_Exception::BIND_FAILED, $e->getCode());
+ }
+ }
+
+ public function testMethodSearchHasPostconditionThatItIsPossibleToTestTheLastResultForAnExceededSearchSizeLimit()
+ {
+ $ldap = $this->getMock('Net_LDAP2', array('search'));
+ $ldap->expects($this->exactly(1))
+ ->method('search')
+ ->will($this->returnValue(new Search_Mock(array(array('dn' => 'test')), true)));
+ $this->server->setLdap($ldap);
+ $this->server->search('filter');
+ $this->assertTrue($this->server->sizeLimitExceeded());
+ }
+
+ public function testMethodSearchReturnsArraySearchResult()
+ {
+ $ldap = $this->getMock('Net_LDAP2', array('search'));
+ $ldap->expects($this->exactly(1))
+ ->method('search')
+ ->will($this->returnValue(new Search_Mock(array(array('dn' => 'test')))));
+ $this->server->setLdap($ldap);
+ $this->assertEquals(array(array('dn' => 'test')), $this->server->search('filter'));
+ }
+
+ public function testMethodSearchReturnsArrayMappedSearchResultIfMappingIsActivated()
+ {
+ $ldap = $this->getMock('Net_LDAP2', array('search'));
+ $ldap->expects($this->exactly(1))
+ ->method('search')
+ ->will($this->returnValue(new Search_Mock(array(array('dn2' => 'test')))));
+ $this->server->setLdap($ldap);
+ $this->server->setParams(array('map' => array('dn' => 'dn2')));
+ $this->assertEquals(
+ array(array('dn' => 'test')),
+ $this->server->search(
+ 'filter',
+ array('attributes' => array('dn'))
+ )
+ );
+ }
+
+ public function testMethodSearchThrowsExceptionIfTheSearchFailed()
+ {
+ $ldap = $this->getMock('Net_LDAP2', array('search'));
+ $ldap->expects($this->exactly(1))
+ ->method('search')
+ ->will($this->returnValue(PEAR::raiseError('Search failed!')));
+ $this->server->setLdap($ldap);
+ try {
+ $this->assertEquals(array('dn' => 'test'), $this->server->search('filter'));
+ $this->fail('No exception!');
+ } catch (Exception $e) {
+ $this->assertEquals('Search failed!', $e->getMessage());
+ $this->assertEquals(Horde_Kolab_Server_Exception::SYSTEM, $e->getCode());
+ }
+ }
+
+ public function testMethodReadReturnsArrayReadResult()
+ {
+ $ldap = $this->getMock('Net_LDAP2', array('search'));
+ $ldap->expects($this->exactly(1))
+ ->method('search')
+ ->will($this->returnValue(new Search_Mock(array(array('dn' => 'test')))));
+ $this->server->setLdap($ldap);
+ $this->assertEquals(array('dn' => 'test'), $this->server->read('test'));
+ }
+
+ public function testMethodReadThrowsExceptionIfTheObjectWasNotFound()
+ {
+ $ldap = $this->getMock('Net_LDAP2', array('search'));
+ $ldap->expects($this->exactly(1))
+ ->method('search')
+ ->will($this->returnValue(new Search_Mock(array())));
+ $this->server->setLdap($ldap);
+ try {
+ $this->assertEquals(array(), $this->server->read('test', array('dn')));
+ $this->fail('No exception!');
+ } catch (Exception $e) {
+ $this->assertEquals('Empty result!', $e->getMessage());
+ $this->assertEquals(Horde_Kolab_Server_Exception::EMPTY_RESULT, $e->getCode());
+ }
+ }
+
+ public function testMethodSaveHasPostconditionThatTheEntryWasSaved()
+ {
+ $ldap = $this->getMock('Net_LDAP2', array('add'));
+ $ldap->expects($this->exactly(1))
+ ->method('add')
+ ->with(new PHPUnit_Framework_Constraint_IsInstanceOf('Net_LDAP2_Entry'));
+ $this->server->setLdap($ldap);
+ $this->server->save('test', array('add' => array('dn' => 'test')));
+ }
+
+ public function testMethodSaveThrowsExceptionIfDataToSaveIsNoArray()
+ {
+ $ldap = $this->getMock('Net_LDAP2', array('add'));
+ $this->server->setLdap($ldap);
+ try {
+ $this->server->save('test', array('add' => 'hello'));
+ $this->fail('No exception!');
+ } catch (Exception $e) {
+ $this->assertEquals('Unable to create fresh entry: Parameter $attrs needs to be an array!', $e->getMessage());
+ $this->assertEquals(Horde_Kolab_Server_Exception::SYSTEM, $e->getCode());
+ }
+
+ }
+
+ public function testMethodSaveThrowsExceptionIfSavingDataFailed()
+ {
+ $ldap = $this->getMock('Net_LDAP2', array('add'));
+ $ldap->expects($this->exactly(1))
+ ->method('add')
+ ->will($this->returnValue(PEAR::raiseError('Saving failed!')));
+ $this->server->setLdap($ldap);
+ try {
+ $this->server->save('test', array('add' => array('dn' => 'test')));
+ $this->fail('No exception!');
+ } catch (Exception $e) {
+ $this->assertEquals('Saving failed!', $e->getMessage());
+ $this->assertEquals(Horde_Kolab_Server_Exception::SYSTEM, $e->getCode());
+ }
+ }
+
+ public function testMethodDeleteHasPostconditionThatTheEntryWasDeleted()
+ {
+ $ldap = $this->getMock('Net_LDAP2', array('delete'));
+ $ldap->expects($this->exactly(1))
+ ->method('delete')
+ ->with('test');
+ $this->server->setLdap($ldap);
+ $this->server->delete('test');
+ }
+
+ public function testMethodDeleteThrowsExceptionIfDeletingDataFailed()
+ {
+ $ldap = $this->getMock('Net_LDAP2', array('delete'));
+ $ldap->expects($this->exactly(1))
+ ->method('delete')
+ ->will($this->returnValue(PEAR::raiseError('Deleting failed!')));
+ $this->server->setLdap($ldap);
+ try {
+ $this->server->delete('test');
+ $this->fail('No exception!');
+ } catch (Exception $e) {
+ $this->assertEquals('Deleting failed!', $e->getMessage());
+ $this->assertEquals(Horde_Kolab_Server_Exception::SYSTEM, $e->getCode());
+ }
+ }
+
+ public function testMethodRenameHasPostconditionThatTheEntryWasRenamed()
+ {
+ $ldap = $this->getMock('Net_LDAP2', array('move'));
+ $ldap->expects($this->exactly(1))
+ ->method('move')
+ ->with('test', 'new');
+ $this->server->setLdap($ldap);
+ $this->server->rename('test', 'new');
+ }
+
+ public function testMethodRenameThrowsExceptionIfRenamingDataFailed()
+ {
+ $ldap = $this->getMock('Net_LDAP2', array('move'));
+ $ldap->expects($this->exactly(1))
+ ->method('move')
+ ->will($this->returnValue(PEAR::raiseError('Renaming failed!')));
+ $this->server->setLdap($ldap);
+ try {
+ $this->server->rename('test', 'new');
+ $this->fail('No exception!');
+ } catch (Exception $e) {
+ $this->assertEquals('Renaming failed!', $e->getMessage());
+ $this->assertEquals(Horde_Kolab_Server_Exception::SYSTEM, $e->getCode());
+ }
+ }
+
+ public function testMethodGetobjectclassesHasResultArrayWithLowerCaseObjectclassNames()
+ {
+ $ldap = $this->getMock('Net_LDAP2', array('search'));
+ $ldap->expects($this->exactly(1))
+ ->method('search')
+ ->will($this->returnValue(new Search_Mock(array(array(Horde_Kolab_Server_Object::ATTRIBUTE_OC => array('test', 'PERSON', 'Last'))))));
+ $this->server->setLdap($ldap);
+ $this->assertEquals(
+ array('test', 'person', 'last'),
+ $this->server->getObjectClasses('test')
+ );
+ }
+
+ public function testMethodGetobjectclassesThrowsExceptionIfTheObjectHasNoAttributeObjectclass()
+ {
+ $ldap = $this->getMock('Net_LDAP2', array('search'));
+ $ldap->expects($this->exactly(1))
+ ->method('search')
+ ->will($this->returnValue(new Search_Mock(array(array('dummy' => array('test', 'PERSON', 'Last'))))));
+ $this->server->setLdap($ldap);
+ try {
+ $this->server->getObjectClasses('test');
+ $this->fail('No exception!');
+ } catch (Exception $e) {
+ $this->assertEquals('The object test has no objectClass attribute!', $e->getMessage());
+ $this->assertEquals(Horde_Kolab_Server_Exception::SYSTEM, $e->getCode());
+ }
+ }
+
+ public function testMethodGetschemaReturnsArrayWithADescriptionOfAllObjectClasses()
+ {
+ $ldap = $this->getMock('Net_LDAP2', array('schema'));
+ $ldap->expects($this->exactly(1))
+ ->method('schema')
+ ->will($this->returnValue(array('schema' => 'dummy')));
+ $this->server->setLdap($ldap);
+ $this->assertEquals(
+ array('schema' => 'dummy'),
+ $this->server->getSchema()
+ );
+ }
+
+ public function testMethodGetschemaThrowsExceptionIfTheSchemaRetrievalFailed()
+ {
+ $ldap = $this->getMock('Net_LDAP2', array('schema'));
+ $ldap->expects($this->exactly(1))
+ ->method('schema')
+ ->will($this->returnValue(PEAR::raiseError('Schema failed!')));
+ $this->server->setLdap($ldap);
+ try {
+ $this->server->getSchema();
+ $this->fail('No exception!');
+ } catch (Exception $e) {
+ $this->assertEquals('Schema failed!', $e->getMessage());
+ $this->assertEquals(Horde_Kolab_Server_Exception::SYSTEM, $e->getCode());
+ }
+ }
+
+ /**
+ * Test handling of object classes.
+ *
+ * @return NULL
+ */
+/* public function testGetObjectClasses() */
+/* { */
+/* $ldap = $this->getMock('Horde_Kolab_Server_ldap', array('read')); */
+/* $ldap->expects($this->any()) */
+/* ->method('read') */
+/* ->will($this->returnValue(array ( */
+/* 'objectClass' => */
+/* array ( */
+/* 'count' => 4, */
+/* 0 => 'top', */
+/* 1 => 'inetOrgPerson', */
+/* 2 => 'kolabInetOrgPerson', */
+/* 3 => 'hordePerson', */
+/* ), */
+/* 0 => 'objectClass', */
+/* 'count' => 1))); */
+
+/* $classes = $ldap->getObjectClasses('cn=Gunnar Wrobel,dc=example,dc=org'); */
+/* if ($classes instanceOf PEAR_Error) { */
+/* $this->assertEquals('', $classes->getMessage()); */
+/* } */
+/* $this->assertContains('top', $classes); */
+/* $this->assertContains('kolabinetorgperson', $classes); */
+/* $this->assertContains('hordeperson', $classes); */
+
+/* $ldap = $this->getMock('Horde_Kolab_Server_ldap', array('read')); */
+/* $ldap->expects($this->any()) */
+/* ->method('read') */
+/* ->will($this->returnValue(PEAR::raiseError('LDAP Error: No such object: cn=DOES NOT EXIST,dc=example,dc=org: No such object'))); */
+
+/* $classes = $ldap->getObjectClasses('cn=DOES NOT EXIST,dc=example,dc=org'); */
+/* $this->assertEquals('LDAP Error: No such object: cn=DOES NOT EXIST,dc=example,dc=org: No such object', */
+/* $classes->message); */
+/* } */
+
+}
+
+
+class Search_Mock
+{
+ public function __construct($result, $limit = false)
+ {
+ $this->result = $result;
+ $this->limit = $limit;
+ }
+ public function as_struct()
+ {
+ return $this->result;
+ }
+ public function sizeLimitExceeded()
+ {
+ return $this->limit;
+ }
+}
\ No newline at end of file
diff --git a/framework/Kolab_Server/test/Horde/Kolab/Server/Server/LoggedTest.php b/framework/Kolab_Server/test/Horde/Kolab/Server/Server/LoggedTest.php
new file mode 100644
index 000000000..1957bb2a6
--- /dev/null
+++ b/framework/Kolab_Server/test/Horde/Kolab/Server/Server/LoggedTest.php
@@ -0,0 +1,167 @@
+
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Kolab_Server
+ */
+
+/**
+ * Require our basic test case definition
+ */
+require_once dirname(__FILE__) . '/../LdapBase.php';
+
+/**
+ * Test the LDAP backend.
+ *
+ * Copyright 2008-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 Kolab_Server
+ * @author Gunnar Wrobel
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Kolab_Server
+ */
+class Horde_Kolab_Server_Server_LoggedTest extends Horde_Kolab_Server_LdapBase
+{
+ public function setUp()
+ {
+ parent::setUp();
+
+ $this->logger = new Horde_Log_Handler_Mock();
+ $this->server = $this->getMock('Horde_Kolab_Server');
+ $this->logged = new Horde_Kolab_Server_Logged(
+ $this->server,
+ new Horde_Log_Logger($this->logger)
+ );
+ }
+
+ public function testMethodConnectguidDelegatesToServer()
+ {
+ $this->server->expects($this->exactly(1))
+ ->method('connectGuid')
+ ->with('user', 'pass');
+ $this->logged->connectGuid('user', 'pass');
+ }
+
+ public function testMethodReadDelegatesToServer()
+ {
+ $this->server->expects($this->exactly(1))
+ ->method('read')
+ ->with('guid');
+ $this->logged->read('guid');
+ }
+
+ public function testMethodReadattributesDelegatesToServer()
+ {
+ $this->server->expects($this->exactly(1))
+ ->method('readAttributes')
+ ->with('guid', array('a'));
+ $this->logged->readAttributes('guid', array('a'));
+ }
+
+ public function testMethodFindDelegatesToServer()
+ {
+ $query = $this->getMock(
+ 'Horde_Kolab_Server_Query', array(), array(), '', false
+ );
+ $this->server->expects($this->exactly(1))
+ ->method('find')
+ ->with($query);
+ $this->logged->find($query);
+ }
+
+ public function testMethodFindbelowDelegatesToServer()
+ {
+ $query = $this->getMock(
+ 'Horde_Kolab_Server_Query', array(), array(), '', false
+ );
+ $this->server->expects($this->exactly(1))
+ ->method('findBelow')
+ ->with($query, 'none');
+ $this->logged->findBelow($query, 'none');
+ }
+
+ public function testMethodSaveDelegatesToServer()
+ {
+ $this->server->expects($this->exactly(1))
+ ->method('save')
+ ->with('a', array('a' => 'a'));
+ $this->logged->save('a', array('a' => 'a'));
+ }
+
+ public function testMethodAddDelegatesToServer()
+ {
+ $this->server->expects($this->exactly(1))
+ ->method('add')
+ ->with('a', array('a' => 'a'));
+ $this->logged->add('a', array('a' => 'a'));
+ }
+
+ public function testMethodDeleteDelegatesToServer()
+ {
+ $this->server->expects($this->exactly(1))
+ ->method('delete')
+ ->with('a');
+ $this->logged->delete('a');
+ }
+
+ public function testMethodRenameDelegatesToServer()
+ {
+ $this->server->expects($this->exactly(1))
+ ->method('rename')
+ ->with('a', 'b');
+ $this->logged->rename('a', 'b');
+ }
+
+ public function testMethodGetschemaDelegatesToServer()
+ {
+ $this->server->expects($this->exactly(1))
+ ->method('getSchema');
+ $this->logged->getSchema();
+ }
+
+ public function testMethodSaveHasPostconditionThatTheEventWasLogged()
+ {
+ $this->logged->save('a', array('a' => 'a'));
+ $this->assertEquals(
+ $this->logger->events[0]['message'],
+ 'The object "a" has been successfully saved!'
+ );
+ }
+
+ public function testMethodAddHasPostconditionThatTheEventWasLogged()
+ {
+ $this->logged->add('a', array('a' => 'a'));
+ $this->assertEquals(
+ $this->logger->events[0]['message'],
+ 'The object "a" has been successfully added!'
+ );
+ }
+
+ public function testMethodDeleteHasPostconditionThatTheEventWasLogged()
+ {
+ $this->logged->delete('a');
+ $this->assertEquals(
+ $this->logger->events[0]['message'],
+ 'The object "a" has been successfully deleted!'
+ );
+ }
+
+ public function testMethodRenameHasPostconditionThatTheEventWasLogged()
+ {
+ $this->logged->rename('a', 'b');
+ $this->assertEquals(
+ $this->logger->events[0]['message'],
+ 'The object "a" has been successfully renamed to "b"!'
+ );
+ }
+}
\ No newline at end of file
diff --git a/framework/Kolab_Server/test/Horde/Kolab/Server/Server/SearchTest.php b/framework/Kolab_Server/test/Horde/Kolab/Server/Server/SearchTest.php
new file mode 100644
index 000000000..398029620
--- /dev/null
+++ b/framework/Kolab_Server/test/Horde/Kolab/Server/Server/SearchTest.php
@@ -0,0 +1,221 @@
+
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Kolab_Server
+ */
+
+/**
+ * Prepare the test setup.
+ */
+require_once dirname(__FILE__) . '/../Autoload.php';
+
+/**
+ * Test the search handler.
+ *
+ * Copyright 2008-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 Kolab_Server
+ * @author Gunnar Wrobel
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Kolab_Server
+ */
+class Horde_Kolab_Server_Server_SearchTest extends PHPUnit_Framework_TestCase
+{
+ public function setUp()
+ {
+ if (!extension_loaded('ldap') && !@dl('ldap.' . PHP_SHLIB_SUFFIX)) {
+ $this->markTestSuiteSkipped('Ldap extension is missing!');
+ };
+
+ if (!class_exists('Net_LDAP2')) {
+ $this->markTestSuiteSkipped('PEAR package Net_LDAP2 is not installed!');
+ }
+
+ $injector = new Horde_Injector(new Horde_Injector_TopLevel());
+ Horde_Kolab_Server_Factory::setup(array(), $injector);
+ $this->server = $injector->getInstance('Horde_Kolab_Server');
+ }
+
+ /**
+ * Test retrieving a primary mail for a mail or uid.
+ *
+ * @return NULL
+ */
+/* public function testMailForUidOrMail() */
+/* { */
+/* $ldap = $this->getMock('Horde_Kolab_Server_ldap', array('getAttributes', */
+/* 'search', 'count', */
+/* 'firstEntry')); */
+/* $ldap->expects($this->any()) */
+/* ->method('_getAttributes') */
+/* ->will($this->returnValue(array ( */
+/* 'mail' => */
+/* array ( */
+/* 'count' => 1, */
+/* 0 => 'wrobel@example.org', */
+/* ), */
+/* 0 => 'mail', */
+/* 'count' => 1))); */
+/* $ldap->expects($this->any()) */
+/* ->method('_search') */
+/* ->will($this->returnValue('cn=Gunnar Wrobel,dc=example,dc=org')); */
+/* $ldap->expects($this->any()) */
+/* ->method('_count') */
+/* ->will($this->returnValue(1)); */
+/* $ldap->expects($this->any()) */
+/* ->method('_firstEntry') */
+/* ->will($this->returnValue(1)); */
+
+/* $mail = $ldap->mailForIdOrMail('wrobel'); */
+/* $this->assertEquals('wrobel@example.org', $mail); */
+
+/* $ldap = $this->getMock('Horde_Kolab_Server_ldap', array('_getAttributes', */
+/* '_search', */
+/* '_count', */
+/* '_firstEntry', */
+/* '_errno', */
+/* '_error')); */
+/* $ldap->expects($this->any()) */
+/* ->method('_getAttributes') */
+/* ->will($this->returnValue(false)); */
+/* $ldap->expects($this->any()) */
+/* ->method('_search') */
+/* ->will($this->returnValue('cn=Gunnar Wrobel,dc=example,dc=org')); */
+/* $ldap->expects($this->any()) */
+/* ->method('_count') */
+/* ->will($this->returnValue(1)); */
+/* $ldap->expects($this->any()) */
+/* ->method('_firstEntry') */
+/* ->will($this->returnValue(1)); */
+/* $ldap->expects($this->any()) */
+/* ->method('_errno') */
+/* ->will($this->returnValue(1)); */
+/* $ldap->expects($this->any()) */
+/* ->method('_error') */
+/* ->will($this->returnValue('cn=DOES NOT EXIST,dc=example,dc=org: No such object')); */
+
+/* $mail = $ldap->mailForIdOrMail('wrobel'); */
+/* $this->assertEquals('Retrieving attributes failed. Error was: cn=DOES NOT EXIST,dc=example,dc=org: No such object', */
+/* $mail->message); */
+
+/* $ldap = $this->getMock('Horde_Kolab_Server_ldap', array('_getAttributes', */
+/* '_search', */
+/* '_count')); */
+/* $ldap->expects($this->any()) */
+/* ->method('_getAttributes') */
+/* ->will($this->returnValue(false)); */
+/* $ldap->expects($this->any()) */
+/* ->method('_search') */
+/* ->will($this->returnValue('cn=Gunnar Wrobel,dc=example,dc=org')); */
+/* $ldap->expects($this->any()) */
+/* ->method('_count') */
+/* ->will($this->returnValue(4)); */
+
+/* $mail = $ldap->mailForIdOrMail('wrobel'); */
+/* $this->assertEquals('Found 4 results when expecting only one!', */
+/* $mail->message); */
+/* } */
+
+/* /\** */
+/* * Test retrieving a DN for a mail or uid. */
+/* * */
+/* * @return NULL */
+/* *\/ */
+/* public function testDnForUidOrMail() */
+/* { */
+/* $ldap = $this->getMock('Horde_Kolab_Server_ldap', array('_getDn', */
+/* '_search', '_count', */
+/* '_firstEntry')); */
+/* $ldap->expects($this->any()) */
+/* ->method('_getDn') */
+/* ->will($this->returnValue('cn=Gunnar Wrobel,dc=example,dc=org')); */
+/* $ldap->expects($this->any()) */
+/* ->method('_search') */
+/* ->will($this->returnValue('cn=Gunnar Wrobel,dc=example,dc=org')); */
+/* $ldap->expects($this->any()) */
+/* ->method('_count') */
+/* ->will($this->returnValue(1)); */
+/* $ldap->expects($this->any()) */
+/* ->method('_firstEntry') */
+/* ->will($this->returnValue(1)); */
+
+/* $dn = $ldap->uidForIdOrMail('wrobel'); */
+/* $this->assertEquals('cn=Gunnar Wrobel,dc=example,dc=org', $dn); */
+
+/* $ldap = $this->getMock('Horde_Kolab_Server_ldap', array('_getDn', */
+/* '_search', */
+/* '_count', */
+/* '_firstEntry', */
+/* '_errno', */
+/* '_error')); */
+/* $ldap->expects($this->any()) */
+/* ->method('_getDn') */
+/* ->will($this->returnValue(false)); */
+/* $ldap->expects($this->any()) */
+/* ->method('_search') */
+/* ->will($this->returnValue('cn=Gunnar Wrobel,dc=example,dc=org')); */
+/* $ldap->expects($this->any()) */
+/* ->method('_count') */
+/* ->will($this->returnValue(1)); */
+/* $ldap->expects($this->any()) */
+/* ->method('_firstEntry') */
+/* ->will($this->returnValue(1)); */
+/* $ldap->expects($this->any()) */
+/* ->method('_errno') */
+/* ->will($this->returnValue(1)); */
+/* $ldap->expects($this->any()) */
+/* ->method('_error') */
+/* ->will($this->returnValue('cn=DOES NOT EXIST,dc=example,dc=org: No such object')); */
+
+/* $dn = $ldap->uidForIdOrMail('wrobel'); */
+/* $this->assertEquals('Retrieving DN failed. Error was: cn=DOES NOT EXIST,dc=example,dc=org: No such object', */
+/* $dn->message); */
+
+/* $ldap = $this->getMock('Horde_Kolab_Server_ldap', array('_getDn', */
+/* '_search', */
+/* '_count')); */
+/* $ldap->expects($this->any()) */
+/* ->method('_getDn') */
+/* ->will($this->returnValue(false)); */
+/* $ldap->expects($this->any()) */
+/* ->method('_search') */
+/* ->will($this->returnValue('cn=Gunnar Wrobel,dc=example,dc=org')); */
+/* $ldap->expects($this->any()) */
+/* ->method('_count') */
+/* ->will($this->returnValue(4)); */
+
+/* $dn = $ldap->uidForIdOrMail('wrobel'); */
+/* $this->assertEquals('Found 4 results when expecting only one!', */
+/* $dn->message); */
+/* } */
+
+}
+
+
+class Search_Mock
+{
+ public function __construct($result, $limit = false)
+ {
+ $this->result = $result;
+ $this->limit = $limit;
+ }
+ public function as_struct()
+ {
+ return $this->result;
+ }
+ public function sizeLimitExceeded()
+ {
+ return $this->limit;
+ }
+}
\ No newline at end of file
diff --git a/framework/Kolab_Server/test/Horde/Kolab/Server/Server/ServerTest.php b/framework/Kolab_Server/test/Horde/Kolab/Server/Server/ServerTest.php
new file mode 100644
index 000000000..b879a14fc
--- /dev/null
+++ b/framework/Kolab_Server/test/Horde/Kolab/Server/Server/ServerTest.php
@@ -0,0 +1,329 @@
+
+
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Kolab_Server
+ */
+
+/**
+ * Prepare the test setup.
+ */
+require_once dirname(__FILE__) . '/../Autoload.php';
+
+/**
+ * Tests for the main server class.
+ *
+ * Copyright 2008-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 Kolab_Server
+ * @author Gunnar Wrobel
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Kolab_Server
+ */
+class Horde_Kolab_Server_Server_ServerTest extends PHPUnit_Framework_TestCase
+{
+ /**
+ * Provide a mock server.
+ *
+ * @return Horde_Kolab_Server The mock server.
+ */
+ protected function getMockServer()
+ {
+ $injector = new Horde_Injector(new Horde_Injector_TopLevel());
+ $config = new stdClass;
+ $config->driver = 'none';
+ $injector->setInstance('Horde_Kolab_Server_Config', $config);
+ $injector->bindFactory('Horde_Kolab_Server_Structure',
+ 'Horde_Kolab_Server_Factory',
+ 'getStructure');
+ $injector->bindFactory('Horde_Kolab_Server',
+ 'Horde_Kolab_Server_Factory',
+ 'getServer');
+ return $injector->getInstance('Horde_Kolab_Server');
+ }
+
+ /**
+ * The generating a uid for an object.
+ *
+ * @return NULL
+ */
+ public function testGenerateUid()
+ {
+ $ks = $this->getMockServer();
+ $user = new Horde_Kolab_Server_Object($ks, null, null);
+ $this->assertEquals(preg_replace('/[0-9a-f]*/', '', $user->get(Horde_Kolab_Server_Object::ATTRIBUTE_UID)), '');
+ }
+
+ /**
+ * Test creating the server object.
+ *
+ * @return NULL
+ */
+ public function testCreation()
+ {
+ try {
+ $injector = new Horde_Injector(new Horde_Injector_TopLevel());
+ $config = new stdClass;
+ $config->driver = 'dummy';
+ $injector->setInstance('Horde_Kolab_Server_Config', $config);
+ $injector->bindFactory('Horde_Kolab_Server_Structure',
+ 'Horde_Kolab_Server_Factory',
+ 'getStructure');
+ $injector->bindFactory('Horde_Kolab_Server',
+ 'Horde_Kolab_Server_Factory',
+ 'getServer');
+ Horde_Kolab_Server_Factory::getServer($injector);
+ $this->assertFail('No error!');
+ } catch (Horde_Kolab_Server_Exception $e) {
+ $this->assertEquals('Server type definition "Horde_Kolab_Server_Dummy" missing.',
+ $e->getMessage());
+ }
+ }
+
+ /**
+ * The base class provides no abilities for reading data. So it
+ * should mainly return error. But it should be capable of
+ * returning a dummy Kolab user object.
+ *
+ * @return NULL
+ */
+ public function testFetch()
+ {
+ $ks = $this->getMockServer();
+ $user = $ks->fetch('test');
+ $this->assertEquals('Horde_Kolab_Server_Object_Kolab_User', get_class($user));
+
+ $ks = $this->getMockServer();
+ $user = $ks->fetch();
+ $this->assertEquals('Horde_Kolab_Server_Object_Kolab_User', get_class($user));
+ }
+
+ /**
+ * Test listing objects.
+ *
+ * @return NULL
+ */
+ public function testList()
+ {
+ $ks = $this->getMockServer();
+ $hash = $ks->listHash('Horde_Kolab_Server_Object');
+ $this->assertEquals($hash, array());
+
+ $ks = $this->getMockServer();
+ $hash = $ks->listHash('Horde_Kolab_Server_Object');
+ $this->assertEquals($hash, array());
+ }
+
+}
+
+/**
+ * A dummy class to test the original abstract class.
+ *
+ * Copyright 2008-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 Kolab_Server
+ * @author Gunnar Wrobel
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Kolab_Server
+ */
+class Horde_Kolab_Server_None extends Horde_Kolab_Server
+{
+ /**
+ * Stub for reading object data.
+ *
+ * @param string $uid The object to retrieve.
+ * @param string $attrs Restrict to these attributes.
+ *
+ * @return array|PEAR_Error An array of attributes.
+ */
+ public function read($uid, $attrs = null)
+ {
+ return false;
+ }
+
+ /**
+ * Stub for saving object data.
+ *
+ * @param string $uid The object to retrieve.
+ * @param string $attrs Restrict to these attributes.
+ *
+ * @return array|PEAR_Error An array of attributes.
+ */
+ public function save($uid, $data, $exists = false)
+ {
+ throw new Horde_Kolab_Server_Exception('Not implemented!');
+ }
+
+ /**
+ * Stub for deleting an object.
+ *
+ * @param string $uid The UID of the object to be deleted.
+ *
+ * @return boolean True if saving succeeded.
+ *
+ * @throws Horde_Kolab_Server_Exception
+ */
+ public function delete($uid)
+ {
+ throw new Horde_Kolab_Server_Exception('Not implemented!');
+ }
+
+ /**
+ * Stub for renaming an object.
+ *
+ * @param string $uid The UID of the object to be renamed.
+ * @param string $new The new UID of the object.
+ *
+ * @return boolean True if renaming succeeded.
+ *
+ * @throws Horde_Kolab_Server_Exception
+ */
+ public function rename($uid, $new)
+ {
+ throw new Horde_Kolab_Server_Exception('Not implemented!');
+ }
+
+ /**
+ * Determine the type of a Kolab object.
+ *
+ * @param string $uid The UID of the object to examine.
+ *
+ * @return string The corresponding Kolab object type.
+ */
+ public function determineType($uid)
+ {
+ return 'Horde_Kolab_Server_Object_Kolab_User';
+ }
+
+ /**
+ * List all objects of a specific type
+ *
+ * @param string $type The type of the objects to be listed
+ * @param array $params Additional parameters.
+ *
+ * @return array|PEAR_Error An array of Kolab objects.
+ */
+ public function listObjects($type, $params = null)
+ {
+ return array();
+ }
+
+ /**
+ * Generates a UID for the given information.
+ *
+ * @param string $type The type of the object to create.
+ * @param string $id The id of the object.
+ * @param array $info Any additional information about the object to create.
+ *
+ * @return string|PEAR_Error The UID.
+ */
+ public function generateServerUid($type, $id, $info)
+ {
+ return $id;
+ }
+
+ /**
+ * Return the root of the UID values on this server.
+ *
+ * @return string The base UID on this server (base DN on ldap).
+ */
+ public function getBaseUid()
+ {
+ return '';
+ }
+
+ /**
+ * Identify the UID for the first object found using the specified
+ * search criteria.
+ *
+ * @param array $criteria The search parameters as array.
+ * @param int $restrict A Horde_Kolab_Server::RESULT_* result restriction.
+ *
+ * @return boolean|string|array The UID(s) or false if there was no result.
+ *
+ * @throws Horde_Kolab_Server_Exception
+ */
+ public function uidForSearch($criteria,
+ $restrict = Horde_Kolab_Server::RESULT_SINGLE)
+ {
+ /* In the default class we just return false */
+ return false;
+ }
+
+ /**
+ * Identify the GID for the first group found using the specified
+ * search criteria
+ *
+ * @param array $criteria The search parameters as array.
+ * @param int $restrict A Horde_Kolab_Server::RESULT_* result restriction.
+ *
+ * @return boolean|string|array The GID(s) or false if there was no result.
+ *
+ * @throws Horde_Kolab_Server_Exception
+ */
+ public function gidForSearch($criteria,
+ $restrict = Horde_Kolab_Server::RESULT_SINGLE)
+ {
+ /* In the default class we just return false */
+ return false;
+ }
+
+ /**
+ * Identify attributes for the objects found using a filter.
+ *
+ * @param array $criteria The search parameters as array.
+ * @param array $attrs The attributes to retrieve.
+ * @param int $restrict A Horde_Kolab_Server::RESULT_* result restriction.
+ *
+ * @return array The results.
+ *
+ * @throws Horde_Kolab_Server_Exception
+ */
+ public function attrsForSearch($criteria, $attrs,
+ $restrict = Horde_Kolab_Server::RESULT_SINGLE)
+ {
+ /* In the default class we just return an empty array */
+ return array();
+ }
+
+ /**
+ * Find object data matching a given set of criteria.
+ *
+ * @param array $criteria The criteria for the search.
+ * @param string $params Additional search parameters.
+ *
+ * @return array The result array.
+ *
+ * @throws Horde_Kolab_Server_Exception
+ */
+ public function find($criteria, $params = array())
+ {
+ /* In the default class we just return an empty array */
+ return array();
+ }
+
+ /**
+ * Returns the set of objects supported by this server.
+ *
+ * @return array An array of supported objects.
+ */
+ public function getSupportedObjects()
+ {
+ return array('Horde_Kolab_Server_Object');
+ }
+}
diff --git a/framework/Kolab_Server/test/Horde/Kolab/Server/Server/TestTest.php b/framework/Kolab_Server/test/Horde/Kolab/Server/Server/TestTest.php
new file mode 100644
index 000000000..312352671
--- /dev/null
+++ b/framework/Kolab_Server/test/Horde/Kolab/Server/Server/TestTest.php
@@ -0,0 +1,626 @@
+
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Kolab_Server
+ */
+
+/**
+ * Prepare the test setup.
+ */
+require_once dirname(__FILE__) . '/../Autoload.php';
+
+/**
+ * Test the test backend.
+ *
+ * Copyright 2008-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 Kolab_Server
+ * @author Gunnar Wrobel
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Kolab_Server
+ */
+class Horde_Kolab_Server_Server_TestTest extends Horde_Kolab_Server_Scenario
+{
+
+ /** The file based mock environment */
+ const ENVIRONMENT_FILE = 'file';
+
+ /**
+ * The environments we provide to the test.
+ *
+ * @var array
+ */
+ protected $_environments = array(
+ self::ENVIRONMENT_MOCK,
+ self::ENVIRONMENT_FILE
+ );
+
+ /**
+ * Prepare the server configuration for the given environment.
+ *
+ * @param string $environment The name of the environment.
+ *
+ * @return NULL
+ */
+ public function prepareKolabServerConfiguration($environment)
+ {
+ switch ($environment) {
+ case self::ENVIRONMENT_FILE:
+ /** Prepare a Kolab test server */
+ $config = new stdClass;
+ $config->driver = 'file';
+ $config->params = array(
+ 'file' => Horde::getTempFile('fileTest'),
+ 'basedn' => 'dc=example,dc=org',
+ 'hashtype' => 'plain'
+ );
+ $this->world['injector'][$environment]->setInstance('Horde_Kolab_Server_Config', $config);
+ break;
+ default:
+ return parent::prepareKolabServerConfiguration($environment);
+ }
+ }
+
+ /**
+ * Set up testing.
+ *
+ * @return NULL
+ */
+ protected function setUp()
+ {
+ parent::setUp();
+
+ $this->initializeEnvironments();
+ $this->servers = $this->getKolabServers();
+ foreach ($this->servers as $server) {
+ $this->addBasicUsersToServer($server);
+ }
+ }
+
+ /**
+ * Test search base.
+ *
+ * @return NULL
+ */
+ public function testSearchBase()
+ {
+ foreach ($this->servers as $server) {
+ $result = $server->search(
+ '(' . Horde_Kolab_Server_Object::ATTRIBUTE_OC
+ . '=' . Horde_Kolab_Server_Object::OBJECTCLASS_TOP . ')',
+ array(Horde_Kolab_Server_Object::ATTRIBUTE_OC));
+ $this->assertEquals(13, count($result));
+
+ $result = $server->search(
+ '(' . Horde_Kolab_Server_Object::ATTRIBUTE_OC
+ . '=' . Horde_Kolab_Server_Object::OBJECTCLASS_TOP . ')',
+ array(Horde_Kolab_Server_Object::ATTRIBUTE_OC),
+ 'cn=internal,dc=example,dc=org');
+ $this->assertEquals(4, count($result));
+ }
+ }
+
+ /**
+ * Test sorting.
+ *
+ * @return NULL
+ */
+ public function testSorting()
+ {
+ foreach ($this->servers as $server) {
+
+/* $result = $server->search('(mail=*)', array('mail')); */
+/* $this->assertEquals(5, count($result)); */
+/* $server->sort($result, 'mail'); */
+/* foreach ($result as $object) { */
+/* if (isset($object['data']['dn'])) { */
+/* switch ($object['data']['dn']) { */
+/* case 'cn=Test Address,cn=external,dc=example,dc=org': */
+/* $this->assertContains('address@example.org', $object['data']['mail']); */
+/* break; */
+/* case '': */
+/* $this->assertContains('address@example.org', $object['data']['mail']); */
+/* break; */
+/* } */
+/* } */
+/* } */
+ }
+ }
+
+ /**
+ * Test listing objects.
+ *
+ * @return NULL
+ */
+ public function testListObjects()
+ {
+ foreach ($this->servers as $server) {
+ $filter = '(&(objectClass=kolabInetOrgPerson)(uid=*)(mail=*)(sn=*))';
+ $attributes = array(
+ Horde_Kolab_Server_Object_Kolabinetorgperson::ATTRIBUTE_SN,
+ Horde_Kolab_Server_Object_Kolabinetorgperson::ATTRIBUTE_CN,
+ Horde_Kolab_Server_Object_Kolabinetorgperson::ATTRIBUTE_UID,
+ Horde_Kolab_Server_Object_Kolabinetorgperson::ATTRIBUTE_MAIL,
+ Horde_Kolab_Server_Object_Kolabinetorgperson::ATTRIBUTE_DELETED,
+ );
+
+ $sort = Horde_Kolab_Server_Object_Kolabinetorgperson::ATTRIBUTE_SN;
+ $result = $server->search($filter);
+ $this->assertEquals(2, count($result));
+
+ $result = $server->listObjects('Horde_Kolab_Server_Object_Kolab_User');
+ $this->assertEquals('Horde_Kolab_Server_Object_Kolab_User', get_class(array_shift($result)));
+
+ $result = $server->listObjects('Horde_Kolab_Server_Object_Kolabsharedfolder');
+ $this->assertEquals(1, count($result));
+ $this->assertEquals('Horde_Kolab_Server_Object_Kolabsharedfolder', get_class(array_shift($result)));
+ }
+ }
+
+ /**
+ * Test handling of object classes.
+ *
+ * @return NULL
+ */
+ public function testGetObjectClasses()
+ {
+ foreach ($this->servers as $server) {
+ $classes = $server->getObjectClasses('cn=Gunnar Wrobel,dc=example,dc=org');
+ $this->assertContains('top', $classes);
+ $this->assertContains('kolabinetorgperson', $classes);
+
+ try {
+ $classes = $server->getObjectClasses('cn=DOES NOT EXIST,dc=example,dc=org');
+ } catch (Horde_Kolab_Server_Exception $classes) {
+ }
+ $this->assertError($classes,
+ 'No such object: cn=DOES NOT EXIST,dc=example,dc=org');
+
+ $classes = $server->getObjectClasses('cn=The Administrator,dc=example,dc=org');
+ $this->assertContains('kolabinetorgperson', $classes);
+ }
+ }
+
+ /**
+ * Test handling of object types.
+ *
+ * @return NULL
+ */
+ public function testDetermineType()
+ {
+ foreach ($this->servers as $server) {
+ $type = $server->determineType('cn=empty.group@example.org,dc=example,dc=org');
+ $this->assertEquals('Horde_Kolab_Server_Object_Kolabgroupofnames', $type);
+
+ $type = $server->determineType('cn=shared@example.org,dc=example,dc=org');
+ $this->assertEquals('Horde_Kolab_Server_Object_Kolabsharedfolder', $type);
+
+ $type = $server->determineType('cn=The Administrator,dc=example,dc=org');
+ $this->assertEquals('Horde_Kolab_Server_Object_Kolab_Administrator', $type);
+
+ $type = $server->determineType('cn=Main Tainer,dc=example,dc=org');
+ $this->assertEquals('Horde_Kolab_Server_Object_Kolab_Maintainer', $type);
+
+ $type = $server->determineType('cn=Domain Maintainer,dc=example,dc=org');
+ $this->assertEquals('Horde_Kolab_Server_Object_Kolab_Domainmaintainer', $type);
+
+ $type = $server->determineType('cn=Test Address,cn=external,dc=example,dc=org');
+ $this->assertEquals('Horde_Kolab_Server_Object_Kolab_Address', $type);
+
+ $type = $server->determineType('cn=Gunnar Wrobel,dc=example,dc=org');
+ $this->assertEquals('Horde_Kolab_Server_Object_Kolab_User', $type);
+ }
+ }
+
+ /**
+ * Test retrieving a primary mail for a mail or id.
+ *
+ * @return NULL
+ */
+ public function testMailForIdOrMail()
+ {
+ foreach ($this->servers as $server) {
+ $mail = $server->mailForIdOrMail('wrobel');
+ $this->assertEquals('wrobel@example.org', $mail);
+
+ $mail = $server->mailForIdOrMail('wrobel@example.org');
+ $this->assertEquals('wrobel@example.org', $mail);
+
+ $mail = $server->mailForIdOrMail('DOES NOT EXIST');
+ $this->assertSame(false, $mail);
+ }
+ }
+
+ /**
+ * Test retrieving a UID for a mail or id.
+ *
+ * @return NULL
+ */
+ public function testUidForIdOrMail()
+ {
+ foreach ($this->servers as $server) {
+ $uid = $server->uidForIdOrMail('wrobel');
+ $this->assertEquals('cn=Gunnar Wrobel,dc=example,dc=org', $uid);
+
+ $uid = $server->uidForIdOrMail('wrobel@example.org');
+ $this->assertEquals('cn=Gunnar Wrobel,dc=example,dc=org', $uid);
+
+ $uid = $server->uidForIdOrMail('DOES NOT EXIST');
+ $this->assertSame(false, $uid);
+ }
+ }
+
+ /**
+ * Test retrieving a UID for a mail or id.
+ *
+ * @return NULL
+ */
+ public function testUidForMailOrIdOrAlias()
+ {
+ foreach ($this->servers as $server) {
+ $uid = $server->uidForIdOrMailOrAlias('g.wrobel@example.org');
+ $this->assertEquals('cn=Gunnar Wrobel,dc=example,dc=org', $uid);
+
+ $uid = $server->uidForIdOrMailOrAlias('wrobel@example.org');
+ $this->assertEquals('cn=Gunnar Wrobel,dc=example,dc=org', $uid);
+
+ $uid = $server->uidForIdOrMailOrAlias('wrobel');
+ $this->assertEquals('cn=Gunnar Wrobel,dc=example,dc=org', $uid);
+
+ $uid = $server->uidForIdOrMailOrAlias('DOES NOT EXIST');
+ $this->assertSame(false, $uid);
+ }
+ }
+
+ /**
+ * Test retrieving all addresses for a mail or id.
+ *
+ * @return NULL
+ */
+ public function testAddrsForIdOrMail()
+ {
+ foreach ($this->servers as $server) {
+ $addrs = $server->addrsForIdOrMail('wrobel');
+
+ $testuser = $server->fetch('cn=Test Test,dc=example,dc=org');
+ $this->assertContains('wrobel@example.org',
+ $testuser->get(Horde_Kolab_Server_Object_Kolabinetorgperson::ATTRIBUTE_DELEGATE, false));
+
+ $this->assertContains('wrobel@example.org', $addrs);
+ $this->assertContains('test@example.org', $addrs);
+ $this->assertContains('t.test@example.org', $addrs);
+ $this->assertContains('g.wrobel@example.org', $addrs);
+ $this->assertContains('gunnar@example.org', $addrs);
+
+ $addrs = $server->addrsForIdOrMail('test@example.org');
+ $this->assertContains('test@example.org', $addrs);
+ $this->assertContains('t.test@example.org', $addrs);
+ }
+ }
+
+ /**
+ * Test retrieving a UID for a primary mail.
+ *
+ * @return NULL
+ */
+ public function testUidForMailAddress()
+ {
+ foreach ($this->servers as $server) {
+ $uid = $server->uidForIdOrMailOrAlias('wrobel@example.org');
+ $this->assertEquals('cn=Gunnar Wrobel,dc=example,dc=org', $uid);
+
+ $uid = $server->uidForIdOrMailOrAlias('test@example.org');
+ $this->assertEquals('cn=Test Test,dc=example,dc=org', $uid);
+
+ $uid = $server->uidForIdOrMailOrAlias('gunnar@example.org');
+ $this->assertEquals('cn=Gunnar Wrobel,dc=example,dc=org', $uid);
+
+ $uid = $server->uidForIdOrMailOrAlias('wrobel');
+ $this->assertEquals('cn=Gunnar Wrobel,dc=example,dc=org', $uid);
+ }
+ }
+
+ /**
+ * Test retrieving a UID for an attribute.
+ *
+ * @return NULL
+ */
+ public function testUidForAttr()
+ {
+ foreach ($this->servers as $server) {
+ $uid = $server->uidForSearch(array('AND' => array(array('field' => 'alias',
+ 'op' => '=',
+ 'test' => 'g.wrobel@example.org'))));
+ $this->assertEquals('cn=Gunnar Wrobel,dc=example,dc=org', $uid);
+ }
+ }
+
+ /**
+ * Test group membership testing.
+ *
+ * @return NULL
+ */
+ public function testMemberOfGroupAddress()
+ {
+ foreach ($this->servers as $server) {
+ $uid = $server->uidForIdOrMailOrAlias('g.wrobel@example.org');
+ $member = $server->memberOfGroupAddress($uid, 'group@example.org');
+ $this->assertTrue($member);
+
+ $member = $server->memberOfGroupAddress(
+ $server->uidForIdOrMailOrAlias('test@example.org'),
+ 'group@example.org');
+ $this->assertTrue($member);
+
+ $member = $server->memberOfGroupAddress(
+ $server->uidForIdOrMailOrAlias('somebody@example.org'),
+ 'group@example.org');
+ $this->assertFalse($member);
+ }
+ }
+
+ /**
+ * Test group fetching.
+ *
+ * @return NULL
+ */
+ public function testGetGroups()
+ {
+ foreach ($this->servers as $server) {
+ $filter = '(&(objectClass=kolabGroupOfNames)(member='
+ . Net_LDAP2_Util::escape_filter_value('cn=The Administrator,dc=example,dc=org') . '))';
+ $result = $server->search($filter, array());
+ $this->assertTrue(!empty($result));
+
+ /* $entry = $server->_firstEntry($result); */
+ /* $this->assertTrue(!empty($entry)); */
+
+ /* $uid = $server->_getDn($entry); */
+ /* $this->assertTrue(!empty($uid)); */
+
+ /* $entry = $server->_nextEntry($entry); */
+ /* $this->assertTrue(empty($entry)); */
+
+ /* $entries = $server->_getDns($result); */
+ /* $this->assertTrue(!empty($entries)); */
+
+ $groups = $server->getGroups('cn=The Administrator,dc=example,dc=org');
+ $this->assertTrue(!empty($groups));
+
+ $groups = $server->getGroups($server->uidForIdOrMailOrAlias('g.wrobel@example.org'));
+ $this->assertContains('cn=group@example.org,dc=example,dc=org', $groups);
+
+ $groups = $server->getGroupAddresses($server->uidForIdOrMailOrAlias('g.wrobel@example.org'));
+ $this->assertContains('group@example.org', $groups);
+
+ $groups = $server->getGroups($server->uidForIdOrMailOrAlias('test@example.org'));
+ $this->assertContains('cn=group@example.org,dc=example,dc=org', $groups);
+
+ $groups = $server->getGroupAddresses($server->uidForIdOrMailOrAlias('test@example.org'));
+ $this->assertContains('group@example.org', $groups);
+
+ $groups = $server->getGroups('nobody');
+ $this->assertTrue(empty($groups));
+ }
+ }
+
+ /**
+ * Test parsing of LDAP filters.
+ *
+ * @return NULL
+ */
+ public function testFilterParse()
+ {
+ $db = $this->getKolabMockServer();
+
+ $a = $db->parse('(a=b)');
+ $this->assertEquals(array('att' => 'a', 'log' => '=', 'val' => 'b'),
+ $a);
+
+ $a = $db->parse('(&(a=b)(c=d))');
+ $this->assertEquals(array('op' => '&', 'sub' => array(
+ array('att' => 'a', 'log' => '=', 'val' => 'b'),
+ array('att' => 'c', 'log' => '=', 'val' => 'd'),
+ )), $a);
+
+ $a = $db->parse('(&(a=1)(|(b=2)(c=3)))');
+ $this->assertEquals(array('op' => '&', 'sub' => array(
+ array('att' => 'a', 'log' => '=', 'val' => '1'),
+ array('op' => '|', 'sub' =>
+ array(
+ array('att' => 'b', 'log' => '=', 'val' => '2'),
+ array('att' => 'c', 'log' => '=', 'val' => '3'),
+ )))), $a);
+
+ $a = $db->parseSub('(!(x=2))(b=1)');
+ $this->assertEquals(array(array('op' => '!', 'sub' =>
+ array(
+ array('att' => 'x', 'log' => '=', 'val' => '2'),
+ )
+ ),
+ array('att' => 'b', 'log' => '=', 'val' => '1'),
+ ), $a);
+
+ $a = $db->parse('(&(!(x=2))(b=1))');
+ $this->assertEquals(array('op' => '&', 'sub' => array(
+ array('op' => '!', 'sub' =>
+ array(
+ array('att' => 'x', 'log' => '=', 'val' => '2'),
+ )
+ ),
+ array('att' => 'b', 'log' => '=', 'val' => '1'),
+ )), $a);
+
+ }
+
+ /**
+ * Test searching in the simulated LDAP data.
+ *
+ * @return NULL
+ */
+ public function testSearch()
+ {
+ $injector = new Horde_Injector(new Horde_Injector_TopLevel());
+ $config = new stdClass;
+ $config->driver = 'test';
+ $config->params = array(
+ 'data' =>
+ array(
+ 'cn=a' => array(
+ 'dn' => 'cn=a',
+ 'data' => array(
+ 'a' => '1',
+ 'b' => '1',
+ 'c' => '1',
+ )
+ ),
+ 'cn=b' => array(
+ 'dn' => 'cn=b',
+ 'data' => array(
+ 'a' => '1',
+ 'b' => '2',
+ 'c' => '2',
+ )
+ ),
+ 'cn=c' => array(
+ 'dn' => 'cn=c',
+ 'data' => array(
+ 'a' => '1',
+ 'b' => '2',
+ 'c' => '3',
+ )
+ ),
+ 'cn=d' => array(
+ 'dn' => 'cn=d',
+ 'data' => array(
+ 'a' => '2',
+ 'b' => '2',
+ 'c' => '1',
+ )
+ ),
+ )
+ );
+ $injector->setInstance('Horde_Kolab_Server_Config', $config);
+ $injector->bindFactory('Horde_Kolab_Server_Structure',
+ 'Horde_Kolab_Server_Factory',
+ 'getStructure');
+ $injector->bindFactory('Horde_Kolab_Server',
+ 'Horde_Kolab_Server_Factory',
+ 'getServer');
+ $db = $injector->getInstance('Horde_Kolab_Server');
+
+ $a = $db->search('(c=1)');
+ $this->assertEquals(
+ array(
+ 'cn=a' => array(
+ 'a' => '1',
+ 'b' => '1',
+ 'c' => '1',
+ 'dn' => 'cn=a',
+ ),
+ 'cn=d' => array(
+ 'a' => '2',
+ 'b' => '2',
+ 'c' => '1',
+ 'dn' => 'cn=d',
+ ),
+ ),
+ $a
+ );
+
+ $a = $db->search('(c=3)');
+ $this->assertEquals(
+ array(
+ 'cn=c' => array(
+ 'a' => '1',
+ 'b' => '2',
+ 'c' => '3',
+ 'dn' => 'cn=c',
+ ),
+ ),
+ $a
+ );
+
+ $a = $db->search('(c=3)', array('attributes' => array('a')));
+ $this->assertEquals(
+ array(
+ 'cn=c' => array(
+ 'a' => '1',
+ 'dn' => 'cn=c',
+ ),
+ ),
+ $a
+ );
+
+ $a = $db->search('(&(a=1)(b=2))', array('attributes' => array('a', 'b')));
+ $this->assertEquals(
+ array(
+ 'cn=b' => array(
+ 'a' => '1',
+ 'b' => '2',
+ 'dn' => 'cn=b',
+ ),
+ 'cn=c' => array(
+ 'a' => '1',
+ 'b' => '2',
+ 'dn' => 'cn=c',
+ ),
+ ),
+ $a
+ );
+
+ $a = $db->search('(&(b=2))', array('attributes' => array('b')));
+ $this->assertEquals(
+ array(
+ 'cn=b' => array(
+ 'b' => '2',
+ 'dn' => 'cn=b',
+ ),
+ 'cn=c' => array(
+ 'b' => '2',
+ 'dn' => 'cn=c',
+ ),
+ 'cn=d' => array(
+ 'b' => '2',
+ 'dn' => 'cn=d',
+ ),
+ ),
+ $a
+ );
+
+ $a = $db->search('(!(b=2))', array('attributes' => array('a', 'b')));
+ $this->assertEquals(
+ array(
+ 'cn=a' => array(
+ 'a' => '1',
+ 'b' => '1',
+ 'dn' => 'cn=a',
+ ),
+ ),
+ $a
+ );
+
+ $a = $db->search('(&(!(x=2))(b=1))', array('attributes' => array('b')));
+ $this->assertEquals(
+ array(
+ 'cn=a' => array(
+ 'b' => '1',
+ 'dn' => 'cn=a',
+ ),
+ ),
+ $a
+ );
+ }
+
+}
diff --git a/framework/Kolab_Server/test/Horde/Kolab/Server/UserTest.php b/framework/Kolab_Server/test/Horde/Kolab/Server/UserTest.php
index d23c7fd18..cd0e74739 100644
--- a/framework/Kolab_Server/test/Horde/Kolab/Server/UserTest.php
+++ b/framework/Kolab_Server/test/Horde/Kolab/Server/UserTest.php
@@ -40,6 +40,8 @@ class Horde_Kolab_Server_UserTest extends Horde_Kolab_Server_Scenario
*/
protected function setUp()
{
+ parent::setUp();
+
$this->server = $this->getKolabMockServer();
$users = $this->validUsers();
foreach ($users as $user) {