From 33c6f2e06b20b3282c2e615750f36c0597b604ba Mon Sep 17 00:00:00 2001 From: Johannes Meyer Date: Tue, 29 Sep 2015 09:47:30 +0200 Subject: [PATCH] LdapConnection: Support unfolding multi value attributes refs #9772 --- .../Icinga/Protocol/Ldap/LdapConnection.php | 72 +++++++++++++++++-- library/Icinga/Protocol/Ldap/LdapQuery.php | 30 ++++++++ 2 files changed, 95 insertions(+), 7 deletions(-) diff --git a/library/Icinga/Protocol/Ldap/LdapConnection.php b/library/Icinga/Protocol/Ldap/LdapConnection.php index ca83c4ff7..87516fd41 100644 --- a/library/Icinga/Protocol/Ldap/LdapConnection.php +++ b/library/Icinga/Protocol/Ldap/LdapConnection.php @@ -714,10 +714,29 @@ class LdapConnection implements Selectable, Inspectable do { $count += 1; if (! $serverSorting || $offset === 0 || $offset < $count) { - $entries[ldap_get_dn($ds, $entry)] = $this->cleanupAttributes( + $row = $this->cleanupAttributes( ldap_get_attributes($ds, $entry), - array_flip($fields) + array_flip($fields), + $query->getUnfoldAttribute() ); + + if (is_array($row)) { + // TODO: Register the DN the same way as a section name in the ArrayDatasource! + + $count -= 1; + foreach ($row as $additionalRow) { + $count += 1; + if (! $serverSorting || $offset === 0 || $offset < $count) { + $entries[] = $additionalRow; + } + + if ($serverSorting && $limit > 0 && $limit === count($entries)) { + break; + } + } + } else { + $entries[ldap_get_dn($ds, $entry)] = $row; + } } } while ((! $serverSorting || $limit === 0 || $limit !== count($entries)) && ($entry = ldap_next_entry($ds, $entry)) @@ -828,10 +847,29 @@ class LdapConnection implements Selectable, Inspectable do { $count += 1; if (! $serverSorting || $offset === 0 || $offset < $count) { - $entries[ldap_get_dn($ds, $entry)] = $this->cleanupAttributes( + $row = $this->cleanupAttributes( ldap_get_attributes($ds, $entry), - array_flip($fields) + array_flip($fields), + $query->getUnfoldAttribute() ); + + if (is_array($row)) { + // TODO: Register the DN the same way as a section name in the ArrayDatasource! + + $count -= 1; + foreach ($row as $additionalRow) { + $count += 1; + if (! $serverSorting || $offset === 0 || $offset < $count) { + $entries[] = $additionalRow; + } + + if ($serverSorting && $limit > 0 && $limit === count($entries)) { + break; + } + } + } else { + $entries[ldap_get_dn($ds, $entry)] = $row; + } } } while ( (! $serverSorting || $limit === 0 || $limit !== count($entries)) @@ -879,14 +917,16 @@ class LdapConnection implements Selectable, Inspectable /** * Clean up the given attributes and return them as simple object * - * Applies column aliases, aggregates multi-value attributes as array and sets null for each missing attribute. + * Applies column aliases, aggregates/unfolds multi-value attributes + * as array and sets null for each missing attribute. * * @param array $attributes * @param array $requestedFields + * @param string $unfoldAttribute * - * @return object + * @return object|array An array in case the object has been unfolded */ - public function cleanupAttributes($attributes, array $requestedFields) + public function cleanupAttributes($attributes, array $requestedFields, $unfoldAttribute = null) { // In case the result contains attributes with a differing case than the requested fields, it is // necessary to create another array to map attributes case insensitively to their requested counterparts. @@ -927,6 +967,24 @@ class LdapConnection implements Selectable, Inspectable } } + if ( + $unfoldAttribute !== null + && isset($cleanedAttributes[$unfoldAttribute]) + && is_array($cleanedAttributes[$unfoldAttribute]) + ) { + $values = $cleanedAttributes[$unfoldAttribute]; + unset($cleanedAttributes[$unfoldAttribute]); + $baseRow = (object) $cleanedAttributes; + $rows = array(); + foreach ($values as $value) { + $row = clone $baseRow; + $row->{$unfoldAttribute} = $value; + $rows[] = $row; + } + + return $rows; + } + return (object) $cleanedAttributes; } diff --git a/library/Icinga/Protocol/Ldap/LdapQuery.php b/library/Icinga/Protocol/Ldap/LdapQuery.php index 1af5467d7..6d76bb897 100644 --- a/library/Icinga/Protocol/Ldap/LdapQuery.php +++ b/library/Icinga/Protocol/Ldap/LdapQuery.php @@ -35,6 +35,13 @@ class LdapQuery extends SimpleQuery */ protected $usePagedResults; + /** + * The name of the attribute used to unfold the result + * + * @var string + */ + protected $unfoldAttribute; + /** * Initialize this query */ @@ -90,6 +97,29 @@ class LdapQuery extends SimpleQuery return $this->usePagedResults; } + /** + * Set the attribute to be used to unfold the result + * + * @param string $attributeName + * + * @return $this + */ + public function setUnfoldAttribute($attributeName) + { + $this->unfoldAttribute = $attributeName; + return $this; + } + + /** + * Return the attribute to use to unfold the result + * + * @return string + */ + public function getUnfoldAttribute() + { + return $this->unfoldAttribute; + } + /** * Choose an objectClass and the columns you are interested in *