From e1fe30ada9683206c72fa162713bf418b68fb700 Mon Sep 17 00:00:00 2001 From: Gunnar Wrobel
Date: Mon, 6 Apr 2009 11:44:39 +0200 Subject: [PATCH] Correct how we derive attributes. This is not completed yet and does not catch all possible conditions (e.g. multiple attribute values, value caching). --- .../Kolab_Server/lib/Horde/Kolab/Server/Object.php | 114 ++++++++++++++++++--- .../lib/Horde/Kolab/Server/Object/Person.php | 64 ++++++------ 2 files changed, 134 insertions(+), 44 deletions(-) diff --git a/framework/Kolab_Server/lib/Horde/Kolab/Server/Object.php b/framework/Kolab_Server/lib/Horde/Kolab/Server/Object.php index e9af97305..3bef6390a 100644 --- a/framework/Kolab_Server/lib/Horde/Kolab/Server/Object.php +++ b/framework/Kolab_Server/lib/Horde/Kolab/Server/Object.php @@ -72,6 +72,14 @@ class Horde_Kolab_Server_Object private $_cache = false; /** + * Cache for derived values. This may not be the same cache as the original + * value cache as some attributes may have the same name. + * + * @var array + */ + private $_derivative_cache = array(); + + /** * Does the object exist in the LDAP database? * * @var boolean @@ -335,31 +343,104 @@ class Horde_Kolab_Server_Object * * @return mixed The value of the attribute. */ - protected function derive($attr) + protected function derive($attr, $separator = '$') { switch ($attr) { case self::ATTRIBUTE_ID: return substr($this->uid, 0, strlen($this->uid) - strlen($this->server->getBaseUid()) - 1); + default: + $basekey = $this->attributes[$attr]['base']; + $base = $this->_get($basekey); + if (empty($base)) { + return; + } + $fields = explode($separator, $base); + //FIXME: Fill the cache here + return isset($fields[$this->attributes[$attr]['order']]) ? $fields[$this->attributes[$attr]['order']] : null; + } } /** * Collapse derived values back into the main attributes. * - * @param string $attr The attribute to collapse. - * @param array $info The information currently working on. + * @param string $key The attribute to collapse into. + * @param array $attributes The attribute to collapse. + * @param array $info The information currently working on. + * @param string $separator Separate the fields using this character. * - * @return mixed The value of the attribute. + * @return NULL. */ - protected function collapse($attr, &$info) + protected function collapse($key, $attributes, &$info, $separator = '$') { switch ($attr) { default: + /** + * Check how many empty entries we have at the end of the array. We + * may omit these together with their field separators. + */ + krsort($attributes); + $empty = count($attributes); + foreach ($attributes as $attribute) { + if (empty($info[$attribute])) { + $empty--; + } else { + break; + } + } + ksort($attributes); + $unset = $attributes; + $result = ''; + for ($i = 0; $i < $empty; $i++) { + $akey = array_shift($attributes); + //FIXME: We don't handle multiple values correctly here + $value = isset($info[$akey]) ? $info[$akey] : ''; + if (is_array($value)) { + $value = $value[0]; + } + $result .= $this->quote($value); + if ($i != ($empty - 1)) { + $result .= $separator; + } + } + foreach ($unset as $attribute) { + unset($info[$attribute]); + } + + $info[$key] = $result; } } /** + * Quote field separaotrs within a LDAP value. + * + * @param string $string The string that should be quoted. + * + * @return string The quoted string. + */ + protected function quote($string) + { + return str_replace(array('\\', '$',), + array('\\5c', '\\24',), + $string); + } + + /** + * Unquote a LDAP value. + * + * @param string $string The string that should be unquoted. + * + * @return string The unquoted string. + */ + protected function unquote($string) + { + return str_replace(array('\\5c', '\\24',), + array('\\', '$',), + $string); + } + + /** * Convert the object attributes to a hash. * * @param string $attrs The attributes to return. @@ -417,7 +498,9 @@ class Horde_Kolab_Server_Object * * @param array $info The information about the object. * - * @return boolean|PEAR_Error True on success. + * @return boolean True on success. + * + * @throws Horde_Kolab_Server_Exception If saving the data failed. */ public function save($info) { @@ -430,6 +513,19 @@ class Horde_Kolab_Server_Object } } + $collapse = array(); + foreach ($this->attribute_map['derived'] as $key) { + $attribute = $this->attributes[$key]; + if (isset($attribute['base']) + && isset($attribute['order'])) { + $collapse[$attribute['base']][$attribute['order']] = $key; + } + } + + foreach ($collapse as $key => $attributes) { + $this->collapse($key, $attributes, $info); + } + if (!$this->exists()) { foreach ($this->attribute_map['required'] as $key) { if (!in_array($key, array_keys($info)) || empty($info[$key])) { @@ -488,12 +584,6 @@ class Horde_Kolab_Server_Object } } - foreach ($this->attribute_map['derived'] as $attribute) { - if (isset($info[$attribute])) { - $this->collapse($attribute, $info); - } - } - $result = $this->server->save($this->uid, $info, $this->exists()); $this->_exists = true; diff --git a/framework/Kolab_Server/lib/Horde/Kolab/Server/Object/Person.php b/framework/Kolab_Server/lib/Horde/Kolab/Server/Object/Person.php index 365610614..204440405 100644 --- a/framework/Kolab_Server/lib/Horde/Kolab/Server/Object/Person.php +++ b/framework/Kolab_Server/lib/Horde/Kolab/Server/Object/Person.php @@ -30,6 +30,7 @@ class Horde_Kolab_Server_Object_Person extends Horde_Kolab_Server_Object const ATTRIBUTE_CN = 'cn'; const ATTRIBUTE_SN = 'sn'; + const ATTRIBUTE_SNSUFFIX = 'snsuffix'; const ATTRIBUTE_USERPASSWORD = 'userPassword'; const OBJECTCLASS_PERSON = 'person'; @@ -45,6 +46,16 @@ class Horde_Kolab_Server_Object_Person extends Horde_Kolab_Server_Object self::ATTRIBUTE_SN, self::ATTRIBUTE_USERPASSWORD, ), + 'derived' => array( + self::ATTRIBUTE_SN => array( + 'base' => self::ATTRIBUTE_SN, + 'order' => 0, + ), + self::ATTRIBUTE_SNSUFFIX => array( + 'base' => self::ATTRIBUTE_SN, + 'order' => 1, + ), + ), 'required' => array( self::ATTRIBUTE_CN, self::ATTRIBUTE_SN, @@ -55,51 +66,40 @@ class Horde_Kolab_Server_Object_Person extends Horde_Kolab_Server_Object ); /** - * Derive an attribute value. + * Generates an ID for the given information. * - * @param string $attr The attribute to derive. + * @param array $info The data of the object. * - * @return mixed The value of the attribute. + * @static + * + * @return string The ID. */ - protected function derive($attr) + public static function generateId($info) { - switch ($attr) { - case self::ATTRIBUTE_ID: - $result = split(',', $this->uid); - if (substr($result[0], 0, 3) == 'cn=') { - return substr($result[0], 3); - } else { - return $result[0]; - } - default: - return parent::derive($attr); + if (!empty($info[self::ATTRIBUTE_CN])) { + return self::ATTRIBUTE_CN . '=' . $info[self::ATTRIBUTE_CN]; } + return self::ATTRIBUTE_CN . '=' . $info[self::ATTRIBUTE_SN]; } /** - * Generates an ID for the given information. + * Saves object information. This may either create a new entry or modify an + * existing entry. * - * @param array $info The data of the object. + * Please note that fields with multiple allowed values require the callee + * to provide the full set of values for the field. Any old values that are + * not resubmitted will be considered to be deleted. * - * @static + * @param array $info The information about the object. * - * @return string|PEAR_Error The ID. + * @return boolean|PEAR_Error True on success. */ - public static function generateId($info) + public function save($info) { - $id_mapfields = array('givenName', 'sn'); - $id_format = '%s %s'; - - $fieldarray = array(); - foreach ($id_mapfields as $mapfield) { - if (isset($info[$mapfield])) { - $fieldarray[] = $info[$mapfield]; - } else { - $fieldarray[] = ''; - } + if (empty($info[self::ATTRIBUTE_CN]) + && !empty($info[self::ATTRIBUTE_SN])) { + $info[self::ATTRIBUTE_CN] = $info[self::ATTRIBUTE_SN]; } - - return trim(vsprintf($id_format, $fieldarray), " \t\n\r\0\x0B,"); + return parent::save($info); } - } \ No newline at end of file -- 2.11.0