Moved the ability to determine object attribtues into the core server
authorGunnar Wrobel <p@rdus.de>
Mon, 6 Apr 2009 05:20:33 +0000 (07:20 +0200)
committerGunnar Wrobel <p@rdus.de>
Mon, 6 Apr 2009 10:25:59 +0000 (12:25 +0200)
class as it is something required for all defined server types.

framework/Kolab_Server/lib/Horde/Kolab/Server.php
framework/Kolab_Server/lib/Horde/Kolab/Server/Ldap.php
framework/Kolab_Server/lib/Horde/Kolab/Server/Test.php

index f561b63..f894b82 100644 (file)
@@ -33,6 +33,9 @@ require_once 'Horde/Autoloader.php';
  */
 abstract class Horde_Kolab_Server
 {
+    /** Maximum accepted level for the object class hierarchy */
+    const MAX_HIERARCHY = 100;
+
     /**
      * Server parameters.
      *
@@ -55,13 +58,6 @@ abstract class Horde_Kolab_Server
     protected $searches;
 
     /**
-     * Does this server type support automatic schema analysis?
-     *
-     * @var boolean
-     */
-    public $schema_support = false;
-
-    /**
      * Construct a new Horde_Kolab_Server object.
      *
      * @param array $params Parameter array.
@@ -176,6 +172,24 @@ abstract class Horde_Kolab_Server
     }
 
     /**
+     * Stores the attribute definitions in the cache.
+     */
+    function shutdown()
+    {
+        if (isset($this->attributes)) {
+            if (!empty($GLOBALS['conf']['kolab']['server']['cache']['driver'])) {
+                $params = isset($GLOBALS['conf']['kolab']['server']['cache']['params'])
+                    ? $GLOBALS['conf']['kolab']['server']['cache']['params'] : null;
+                $cache = Horde_Cache::singleton($GLOBALS['conf']['kolab']['server']['cache']['driver'],
+                                                $params);
+                foreach ($this->attributes as $key => $value) {
+                    $cache->set('attributes_' . $key, @serialize($value));
+                }
+            }
+        }
+    }
+
+    /**
      * Fetch a Kolab object.
      *
      * This method will not retrieve any data from the server
@@ -325,6 +339,157 @@ abstract class Horde_Kolab_Server
     }
 
     /**
+     * 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)
+    {
+        static $cache = null;
+        static $lifetime;
+
+        if (!isset($this->attributes)) {
+            if (!empty($GLOBALS['conf']['kolab']['server']['cache']['driver'])) {
+                $params = isset($GLOBALS['conf']['kolab']['server']['cache']['params'])
+                    ? $GLOBALS['conf']['kolab']['server']['cache']['params'] : null;
+                $cache = Horde_Cache::singleton($GLOBALS['conf']['kolab']['server']['cache']['driver'],
+                                                $params);
+                register_shutdown_function(array($this, 'shutdown'));
+                $lifetime = isset($GLOBALS['conf']['kolab']['server']['cache']['lifetime'])
+                    ? $GLOBALS['conf']['kolab']['server']['cache']['lifetime'] : 300;
+            }
+        }
+
+        if (empty($this->attributes[$class])) {
+
+            if (!empty($cache)) {
+                $this->attributes[$class] = @unserialize($cache->get('attributes_' . $class, $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) {
+                    Horde::logMessage(sprintf('The maximal level of the object hierarchy has been exceeded for class \"%s\"!',
+                                              $class),
+                                      __FILE__, __LINE__, PEAR_LOG_ERROR);
+                }
+
+                /**
+                 * Collect attributes from bottom to top.
+                 */
+                $classes = array_reverse($classes);
+
+                $types = array('defined', 'required', 'derived', '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($GLOBALS['conf']['kolab']['server']['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) {
+                        $attrs[$attribute] = $this->getAttributeSchema($attribute);
+                    }
+                    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;
+
+                    $attrs = array_merge($attrs, $derived);
+
+                }
+                $this->attributes[$class] = array($attrs,
+                                                  array(
+                                                      'derived'  => array_keys($derived),
+                                                      '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.
+     */
+    protected function getObjectclassSchema($objectclass)
+    {
+        return array();
+    }
+
+    /**
+     * 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.
+     */
+    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.
index 591c4d0..fb25297 100644 (file)
@@ -28,9 +28,6 @@
  */
 class Horde_Kolab_Server_Ldap extends Horde_Kolab_Server
 {
-    /** Maximum accepted level for the object class hierarchy */
-    const MAX_HIERARCHY = 100;
-
     /**
      * LDAP connection handle.
      *
@@ -53,13 +50,6 @@ class Horde_Kolab_Server_Ldap extends Horde_Kolab_Server
     private $_base_dn;
 
     /**
-     * Does this server type support automatic schema analysis?
-     *
-     * @var boolean
-     */
-    public $schema_support = false;
-
-    /**
      * The LDAP schemas.
      *
      * @var Net_LDAP2_Schema
@@ -105,10 +95,6 @@ class Horde_Kolab_Server_Ldap extends Horde_Kolab_Server
 
         $this->_config = $config;
 
-        if (!empty($params['schema_support'])) {
-            $this->schema_support = true;
-        }
-
         $this->connect();
 
         parent::__construct($params);
@@ -310,168 +296,67 @@ class Horde_Kolab_Server_Ldap extends Horde_Kolab_Server
     }
 
     /**
-     * Return the attributes supported by the given object class.
+     * Return the ldap schema.
      *
-     * @param string $class Determine the attributes for this class.
+     * @return Net_LDAP2_Schema The LDAP schema.
      *
-     * @return array The supported attributes.
-     *
-     * @throws Horde_Kolab_Server_Exception If the schema analysis fails.
+     * @throws Horde_Kolab_Server_Exception If retrieval of the schema failed.
      */
-    public function &getAttributes($class)
+    private function _getSchema()
     {
-        static $cache = null;
-        static $lifetime;
-
-        if (!isset($this->attributes)) {
-            if (!empty($GLOBALS['conf']['kolab']['server']['cache']['driver'])) {
-                $params = isset($GLOBALS['conf']['kolab']['server']['cache']['params'])
-                    ? $GLOBALS['conf']['kolab']['server']['cache']['params'] : null;
-                $params['sub'] = 'attributes';
-                $cache = Horde_Cache::singleton($GLOBALS['conf']['kolab']['server']['cache']['driver'],
-                                                $params);
-                register_shutdown_function(array($this, 'shutdown'));
-                $lifetime = isset($GLOBALS['conf']['kolab']['server']['cache']['lifetime'])
-                    ? $GLOBALS['conf']['kolab']['server']['cache']['lifetime'] : 300;
+        if (!isset($this->_schema)) {
+            $result = $this->_ldap->schema();
+            if ($result instanceOf PEAR_Error) {
+                throw new Horde_Kolab_Server_Exception($result->getMessage());
             }
+            $this->_schema = &$result;
         }
+        return $this->_schema;
+    }
 
-        if (empty($this->attributes[$class])) {
-
-            if (!empty($cache)) {
-                $this->attributes[$class] = @unserialize($cache->get($class, $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) {
-                    Horde::logMessage(sprintf('The maximal level of the object hierarchy has been exceeded for class \"%s\"!',
-                                              $class),
-                                      __FILE__, __LINE__, PEAR_LOG_ERROR);
-                }
-
-                /**
-                 * Collect attributes from top to bottom.
-                 */
-                $classes = array_reverse($classes);
-
-                $derived        = array();
-                $defaults       = array();
-                $locked         = array();
-                $object_classes = array();
-
-                foreach ($classes as $childclass) {
-                    $vars = get_class_vars($childclass);
-                    if (isset($vars['init_attributes'])) {
-                        $derived = array_merge($derived,
-                                               $vars['init_attributes']['derived']);
-                        $defaults = array_merge($defaults,
-                                                $vars['init_attributes']['defaults']);
-                        $locked = array_merge($locked,
-                                              $vars['init_attributes']['locked']);
-                        $object_classes = array_merge($object_classes,
-                                                      $vars['init_attributes']['object_classes']);
-                    }
-                }
-
-                if ($this->schema_support === true) {
-                    if (!isset($this->_schema)) {
-                        $result = $this->_ldap->schema();
-                        if ($result instanceOf PEAR_Error) {
-                            throw new Horde_Kolab_Server_Exception($result->getMessage());
-                        }
-                        $this->_schema = &$result;
-                    }
-                    $supported = array();
-                    $required  = array();
-                    foreach ($object_classes as $object_class) {
-                        $info = $this->_schema->get('objectclass', $object_class);
-                        if ($info instanceOf PEAR_Error) {
-                            throw new Horde_Kolab_Server_Exception($info->getMessage());
-                        }
-                        if (isset($info['may'])) {
-                            $supported = array_merge($supported, $info['may']);
-                        }
-                        if (isset($info['must'])) {
-                            $supported = array_merge($supported, $info['must']);
-                            $required  = array_merge($required, $info['must']);
-                        }
-                    }
-                    if (empty($supported) && empty($required)) {
-                        return false;
-                    }
-                    foreach ($supported as $attribute) {
-                        $info = $this->_schema->get('attribute', $attribute);
-                        if ($info instanceOf PEAR_Error) {
-                            throw new Horde_Kolab_Server_Exception($info->getMessage());
-                        }
-                        $attrs[$attribute] = $info;
-                    }
-                    foreach ($required as $attribute) {
-                        $attrs[$attribute]['required'] = true;
-                    }
-                    foreach ($locked as $attribute) {
-                        $attrs[$attribute]['locked'] = true;
-                    }
-                    foreach ($defaults as $attribute) {
-                        $attrs[$attribute]['default'] = true;
-                    }
-                    $attrs[Horde_Kolab_Server_Object::ATTRIBUTE_OC]['default'] = $object_classes;
-
-                    $attrs = array_merge($attrs, $derived);
-
-                    $this->attributes[$class] = array($attrs,
-                                                      array(
-                                                          'derived'  => $derived,
-                                                          'locked'   => $locked,
-                                                          'required' => $required,
-                                                      ));
-                } else {
-                    $this->attributes[$class] = array(array(),
-                                                      array(
-                                                          'derived'  => array(),
-                                                          'locked'   => array(),
-                                                          'required' => array(),
-                                                      ));
-                }
+    /**
+     * 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.
+     */
+    protected function getObjectclassSchema($objectclass)
+    {
+        if (!empty($this->_config['schema_support'])) {
+            $schema = $this->_getSchema();
+            $info = $schema->get('objectclass', $object_class);
+            if ($info instanceOf PEAR_Error) {
+                throw new Horde_Kolab_Server_Exception($info->getMessage());
             }
+            return $info;
         }
-        return $this->attributes[$class];
+        return parent::getObjectclassSchema($objectclass);
     }
 
     /**
-     * Stores the attribute definitions in the cache.
+     * 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.
      */
-    function shutdown()
+    protected function getAttributeSchema($attribute)
     {
-        if (isset($this->attributes)) {
-            if (!empty($GLOBALS['conf']['kolab']['server']['cache']['driver'])) {
-                $params = isset($GLOBALS['conf']['kolab']['server']['cache']['params'])
-                    ? $GLOBALS['conf']['kolab']['server']['cache']['params'] : null;
-                $params['sub'] = 'attributes';
-                $cache = Horde_Cache::singleton($GLOBALS['conf']['kolab']['server']['cache']['driver'],
-                                                $params);
-                foreach ($this->attributes as $key => $value) {
-                    $cache->set($key, @serialize($value));
-                }
+        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->getMessage());
             }
         }
+        return parent::getAttributeSchema($attribute);
     }
 
-
     /**
      * Search for object data.
      *
index 6e8332d..1e18897 100644 (file)
@@ -534,18 +534,31 @@ class Horde_Kolab_Server_Test extends Horde_Kolab_Server_Kolab
     }
 
     /**
-     * Return the attributes of an entry.
+     * Return the schema for the given objectClass.
      *
-     * @param array $entry The LDAP entry.
+     * @param string $objectclass Fetch the schema for this objectClass.
      *
-     * @return array  The attributes of the entry.
+     * @return array The schema for the given objectClass.
+     *
+     * @throws Horde_Kolab_Server_Exception If retrieval of the schema failed.
      */
-    protected function getAttributes($entry)
+    public function getObjectclassSchema($objectclass)
     {
-        if (is_array($entry)) {
-            return $entry;
-        }
-        return false;
+        return array();
+    }
+
+    /**
+     * 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 array();
     }
 
     /**