Ldap\Connection: Re-organize some methods..

..and add some missing documentation.

refs #8954
This commit is contained in:
Johannes Meyer 2015-06-23 17:37:10 +02:00
parent 372ca8859e
commit f234b3b768
1 changed files with 204 additions and 175 deletions

View File

@ -217,6 +217,68 @@ class Connection implements Selectable
return $this->root;
}
/**
* Return the capabilities of the current connection
*
* @return Capability
*/
public function getCapabilities()
{
if ($this->capabilities === null) {
$this->connect(); // Populates $this->capabilities
}
return $this->capabilities;
}
/**
* Return whether discovery was successful or not
*
* @return bool true if the capabilities were successfully determined, false if the capabilities were guessed
*/
public function discoverySuccessful()
{
return $this->discoverySuccess;
}
/**
* Establish a connection
*
* @throws LdapException In case the connection could not be established
*/
public function connect()
{
if ($this->ds === null) {
$this->ds = $this->prepareNewConnection();
}
}
/**
* Perform a LDAP bind on the current connection
*
* @throws LdapException In case the LDAP bind was unsuccessful
*/
public function bind()
{
if ($this->bound) {
return;
}
$success = @ldap_bind($this->ds, $this->bindDn, $this->bindPw);
if (! $success) {
throw new LdapException(
'LDAP connection to %s:%s (%s / %s) failed: %s',
$this->hostname,
$this->port,
$this->bindDn,
'***' /* $this->bindPw */,
ldap_error($this->ds)
);
}
$this->bound = true;
}
/**
* Provide a query on this connection
*
@ -239,10 +301,61 @@ class Connection implements Selectable
return new ArrayIterator($this->fetchAll($query));
}
public function fetchOne($query, $fields = array())
/**
* Count all rows of the given query's result set
*
* @param Query $query The query returning the result set
*
* @return int
*/
public function count(Query $query)
{
$row = (array) $this->fetchRow($query, $fields);
return array_shift($row) ?: false;
$this->connect();
$this->bind();
$res = $this->runQuery($query, array());
return count($res);
}
/**
* Retrieve an array containing all rows of the result set
*
* @param Query $query The query returning the result set
* @param array $fields Request these attributes instead of the ones registered in the given query
*
* @return array
*/
public function fetchAll(Query $query, array $fields = null)
{
$this->connect();
$this->bind();
if (
$query->getUsePagedResults()
&& version_compare(PHP_VERSION, '5.4.0') >= 0
&& $this->getCapabilities()->hasPagedResult()
) {
return $this->runPagedQuery($query, $fields);
} else {
return $this->runQuery($query, $fields);
}
}
/**
* Fetch the first row of the result set
*
* @param Query $query The query returning the result set
* @param array $fields Request these attributes instead of the ones registered in the given query
*
* @return mixed
*/
public function fetchRow(Query $query, array $fields = null)
{
$clonedQuery = clone $query;
$clonedQuery->limit(1);
$clonedQuery->setUsePagedResults(false);
$results = $this->fetchAll($clonedQuery, $fields);
return array_shift($results) ?: false;
}
/**
@ -277,6 +390,20 @@ class Connection implements Selectable
return $values;
}
/**
* Fetch the first column of the first row of the result set
*
* @param Query $query The query returning the result set
* @param array $fields Request these attributes instead of the ones registered in the given query
*
* @return string
*/
public function fetchOne(Query $query, array $fields = null)
{
$row = (array) $this->fetchRow($query, $fields);
return array_shift($row) ?: false;
}
/**
* Fetch all rows of the result set as an array of key-value pairs
*
@ -325,6 +452,38 @@ class Connection implements Selectable
return $pairs;
}
/**
* Test the given LDAP credentials by establishing a connection and attempting a LDAP bind
*
* @param string $bindDn
* @param string $bindPw
*
* @return bool Whether the given credentials are valid
*
* @throws LdapException In case an error occured while establishing the connection or attempting the bind
*/
public function testCredentials($bindDn, $bindPw)
{
$this->connect();
$success = @ldap_bind($this->ds, $bindDn, $bindPw);
if (! $success) {
if (ldap_errno($this->ds) === self::LDAP_INVALID_CREDENTIALS) {
Logger::debug(
'Testing LDAP credentials (%s / %s) failed: %s',
$bindDn,
'***',
ldap_error($this->ds)
);
return false;
}
throw new LdapException(ldap_error($this->ds));
}
return true;
}
/**
* Return whether an entry identified by the given distinguished name exists
*
@ -417,52 +576,12 @@ class Connection implements Selectable
if (count($rows) > 1) {
throw new LdapException('Cannot fetch single DN for %s', $query);
}
return key($rows);
}
/**
* @param $query
* @param array $fields
*
* @return mixed
*/
public function fetchRow($query, $fields = array())
{
$query = clone $query;
$query->limit(1);
$query->setUsePagedResults(false);
$results = $this->fetchAll($query, $fields);
return array_shift($results) ?: false;
}
/**
* @param Query $query
*
* @return int
*/
public function count(Query $query)
{
$this->connect();
$this->bind();
// TODO: That's still not the best solution, this should probably not request any attributes
$res = $this->runQuery($query);
return count($res);
}
public function fetchAll(Query $query, $fields = array())
{
$this->connect();
$this->bind();
if ($this->pageControlAvailable($query)) {
return $this->runPagedQuery($query, $fields);
} else {
return $this->runQuery($query, $fields);
}
}
/**
* Execute the given LDAP query and return the resulting entries
*
* @param Query $query The query to execute
@ -539,16 +658,6 @@ class Connection implements Selectable
return $entries;
}
/**
* Returns whether requesting the page control is available
*/
protected function pageControlAvailable(Query $query)
{
return $this->capabilities->hasPagedResult() &&
$query->getUsePagedResults() &&
version_compare(PHP_VERSION, '5.4.0') >= 0;
}
/**
* Run the given LDAP query and return the resulting entries
*
@ -762,43 +871,8 @@ class Connection implements Selectable
return $seq;
}
public function testCredentials($username, $password)
{
$this->connect();
$success = @ldap_bind($this->ds, $username, $password);
if (! $success) {
if (ldap_errno($this->ds) === self::LDAP_INVALID_CREDENTIALS) {
Logger::debug(
'Testing LDAP credentials (%s / %s) failed: %s',
$username,
'***',
ldap_error($this->ds)
);
return false;
}
throw new LdapException(ldap_error($this->ds));
}
return true;
}
/**
* @param null $sub
*
* @return string
*/
protected function getConfigDir($sub = null)
{
$dir = Config::$configDir . '/ldap';
if ($sub !== null) {
$dir .= '/' . $sub;
}
return $dir;
}
/**
* Connect to the given ldap server and apply settings depending on the discovered capabilities
*
* @return resource A positive LDAP link identifier
@ -885,31 +959,7 @@ class Connection implements Selectable
}
/**
* Get the capabilities of the connected server
*
* @return Capability The capability object
*/
public function getCapabilities()
{
if ($this->capabilities === null) {
$this->connect(); // Populates $this->capabilities
}
return $this->capabilities;
}
/**
* Whether service discovery was successful
*
* @return boolean True when ldap settings were discovered, false when
* settings were guessed
*/
public function discoverySuccessful()
{
return $this->discoverySuccess;
}
/**
* Discover the capabilities of the given ldap-server
*
* @param resource $ds The link identifier of the current ldap connection
@ -959,88 +1009,67 @@ class Connection implements Selectable
}
/**
* Try to connect to the given ldap server
* Create an LDAP entry
*
* @throws LdapException When connecting is not possible
* @param string $dn The distinguished name to use
* @param array $attributes The entry's attributes
*
* @return bool Whether the operation was successful
*/
public function connect()
public function addEntry($dn, array $attributes)
{
if ($this->ds !== null) {
return;
}
$this->ds = $this->prepareNewConnection();
return ldap_add($this->ds, $dn, $attributes);
}
/**
* Try to bind to the current ldap domain using the provided bind_dn and bind_pw
* Modify an LDAP entry
*
* @throws LdapException When binding is not possible
* @param string $dn The distinguished name to use
* @param array $attributes The attributes to update the entry with
*
* @return bool Whether the operation was successful
*/
public function bind()
public function modifyEntry($dn, array $attributes)
{
if ($this->bound) {
return;
}
$r = @ldap_bind($this->ds, $this->bind_dn, $this->bind_pw);
if (! $r) {
throw new LdapException(
'LDAP connection to %s:%s (%s / %s) failed: %s',
$this->hostname,
$this->port,
$this->bind_dn,
'***' /* $this->bind_pw */,
ldap_error($this->ds)
);
}
$this->bound = true;
return ldap_modify($this->ds, $dn, $attributes);
}
/**
* Create an ldap entry
* Change the distinguished name of an LDAP entry
*
* @param string $dn DN to add
* @param array $entry Entry description
* @param string $dn The entry's current distinguished name
* @param string $newRdn The new relative distinguished name
* @param string $newParentDn The new parent or superior entry's distinguished name
*
* @return bool True on success
*/
public function addEntry($dn, array $entry)
{
return ldap_add($this->ds, $dn, $entry);
}
/**
* Modify a ldap entry
* @return resource The resulting search result identifier
*
* @param string $dn DN of the entry to change
* @param array $entry Change values
*
* @return bool True on success
*/
public function modifyEntry($dn, array $entry)
{
return ldap_modify($this->ds, $dn, $entry);
}
/**
* Move entry to a new DN
*
* @param string $dn DN of the object
* @param string $newRdn Relative DN identifier
* @param string $newParentDn Parent or superior entry
* @throws LdapException Thrown then rename failed
*
* @return bool True on success
* @throws LdapException In case an error occured
*/
public function moveEntry($dn, $newRdn, $newParentDn)
{
$returnValue = ldap_rename($this->ds, $dn, $newRdn, $newParentDn, false);
if ($returnValue === false) {
throw new LdapException('Could not move entry: ' . ldap_error($this->ds));
$result = ldap_rename($this->ds, $dn, $newRdn, $newParentDn, false);
if ($result === false) {
throw new LdapException('Could not move entry "%s" to "%s": %s', $dn, $newRdn, ldap_error($this->ds));
}
return $returnValue;
return $result;
}
/**
* Return the LDAP specific configuration directory with the given relative path being appended
*
* @param string $sub
*
* @return string
*/
protected function getConfigDir($sub = null)
{
$dir = Config::$configDir . '/ldap';
if ($sub !== null) {
$dir .= '/' . $sub;
}
return $dir;
}
/**