_db = $db; $this->_base = is_null($base) ? $this->base() : $base; } /** * Handles pass-through to database methods. Calls to query methods * (query, get, insert, update) are not allowed. Query builder methods * are chainable. * * @param string $method Method name * @param array $args Method arguments * @return mixed */ public function __call($method,array $args) { if (in_array($method,Database_LDAP_Search::$_properties)) { /* // @todo To Implement if ($method === 'validation') { if ( ! isset($this->_validation)) { // Initialize the validation object $this->_validation(); } } */ // Return the property return $this->{'_'.$method}; } elseif (in_array($method,Database_LDAP_Search::$_db_methods)) { // Add pending database call which is executed after query type is determined $this->_db_pending[] = array('name' => $method,'args' => $args); return $this; } elseif (in_array($method,Database_LDAP_Search::$_orm_ignore_methods)) { return $this; } else { throw new Kohana_Exception('Invalid method :method called in :class (:args)', array(':method' => $method,':class' => get_class($this),':args'=>print_r($args,TRUE))); } } private function _build() { $search = new Database_LDAP_Search_Builder_Query(); // Process pending database method calls foreach ($this->_db_pending as $method) { $name = $method['name']; $args = $method['args']; $this->_db_applied[$name] = $name; switch ($name) { case 'limit': $this->_size_limit = $args[0]; break; default: call_user_func_array(array($search,$name),$args); } } return $search; } public function as_assoc() { $this->_as_object = FALSE; $this->_object_params = array(); return $this; } /** * Figure out the bases */ public function base(array $base=NULL) { if (! is_null($base)) $this->_base = $base; if ($this->_base) return $this->_base; // If the base is set in the configuration file, then just return that. if (! is_null($x=Kohana::$config->load('database.default.connection.database'))) return $x; $x = LDAP::factory('auth'); $u = $x->search(array('')) ->scope('base') ->execute(); // Quick validation if ($u['']->count() > 1) throw HTTP_Exception::factory(501,'We got more than 1 null DN?'); return isset($u['']['']['namingcontexts']) ? $u['']['']['namingcontexts'] : array(); } /** * Enables the query to be cached for a specified amount of time. * * @param integer $lifetime number of seconds to cache, 0 deletes it from the cache * @param boolean whether or not to execute the query during a cache hit * @return $this * @uses Kohana::$cache_life */ public function cached($lifetime=NULL,$force=FALSE) { if ($lifetime === NULL) { // Use the global setting $lifetime = Kohana::$cache_life; } $this->_force_execute = $force; $this->_lifetime = $lifetime; return $this; } public function deref($val) { $this->_deref = $val; return $this; } /** * Search the LDAP database */ public function execute($db=NULL,$as_object=FALSE,$object_params=NULL) { $query = array(); if (! is_object($this->_db)) throw new Kohana_Exception('db must be an object'); // We'll override the DB if we have been given one if (is_object($db)) $this->_db = $db; if ($as_object === NULL) $as_object = $this->_as_object; if ($object_params === NULL) $object_params = $this->_object_params; // Query Defaults $attrs_only = 0; // Compile our query if ($this->_db_pending) $this->_filter = $this->_build(); // Validation that we are connected, no point contining if we are not. $this->_db->connect(); if (! $this->_db->connection()) throw HTTP_Exception::factory(501,'Cant run a search without a connection (:type,:filter)',array(':type'=>$this->_db,':filter'=>$this->_filter)); $result = new Database_LDAP_Search_Result; foreach ($this->_base as $base) { if ($this->_lifetime !== NULL AND $this->_db->caching()) { // Set the cache key based on the database instance name and SQL $cache_key = 'Database::query("'.$this->_db.'","'.$base.'","'.$this->_scope.'","'.$this->_filter.'")'; // Read the cache first to delete a possible hit with lifetime <= 0 if (($search = Kohana::cache($cache_key, NULL, $this->_lifetime)) !== NULL AND ! $this->_force_execute) { // Return a cached result $result[$base] = new Database_LDAP_Result_Cached($search, array('b'=>$base,'s'=>$this->_scope,'f'=>$this->_filter), $as_object, $object_params); } } // Search is not cached, OR caching is disabled, so we'll query if (! isset($result[$base])) { try { switch ($this->_scope) { case 'base': $search = ldap_read($this->_db->connection(),$base,$this->_filter,$this->_attrs,$attrs_only,$this->_size_limit,$this->_time_limit,$this->_deref); break; case 'one': $search = ldap_list($this->_db->connection(),$base,$this->_filter,$this->_attrs,$attrs_only,$this->_size_limit,$this->_time_limit,$this->_deref); break; case 'sub': default: $search = ldap_search($this->_db->connection(),$base,$this->_filter,$this->_attrs,$attrs_only,$this->_size_limit,$this->_time_limit,$this->_deref); break; } } catch (Exception $e) { throw HTTP_Exception::factory(501,'Error running a query (SCOPE::scope,BASE::base,TYPE::type,FILTER::filter,ATTRS::attrs) [:error]', array(':base'=>$base,':scope'=>$this->_scope,':type'=>$this->_db,':filter'=>$this->_filter,':attrs'=>join('|',$this->_attrs),':error'=>$e->getMessage())); } $result[$base] = new Database_LDAP_Result(array('l'=>$this->_db->connection(),'r'=>$search),array('b'=>$base,'s'=>$this->_scope,'f'=>$this->_filter),$as_object,$object_params); // Cache the result array if (isset($cache_key) AND $this->_lifetime > 0) Kohana::cache($cache_key,$result[$base]->as_array(),$this->_lifetime); } } return $result; } public function size_limit($val) { $this->_size_limit = $val; return $this; } public function scope($val) { switch ($val) { case 'base': case 'sub': case 'one': $this->_scope = $val; break; default: throw new Kohana_Exception('Unknown search scope :scope',array(':scope',$val)); } return $this; } public function time_limit($val) { $this->_time_limit = $val; return $this; } } ?>