Skip to content

Commit

Permalink
feature #21856 [LDAP] Allow adding and removing values to/from multi-…
Browse files Browse the repository at this point in the history
…valued attributes (jean-gui)

This PR was merged into the 4.1-dev branch.

Discussion
----------

[LDAP] Allow adding and removing values to/from multi-valued attributes

| Q             | A
| ------------- | ---
| Branch?       | master
| Bug fix?      | no
| New feature?  | yes
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| License       | MIT

`EntryManagerInterface::update(Entry $entry)` is extremely slow in some specific cases such as adding or removing members to or from huge groupOfNames if you also enable the memberOf overlay in OpenLDAP. Disabling memberOf does make things a lot better, but it is still slow compared to inserting/removing only the elements you want.

This PR adds two methods to Symfony\Component\Ldap\Adapter\ExtLdap\EntryManager taking advantage of ldap_mod_add and ldap_mod_del.

I thought about using them directly in the update method, but since you need to know what values to add and remove, it would be necessary to retrieve the old values from LDAP.

I'm also unsure whether these two methods should be in an interface. I think that adding them to EntryManagerInterface would break BC, but I could create another interface, similarly to RenameEntryInterface.

Commits
-------

fa9db29 Allow adding and removing values to/from multi-valued attributes
  • Loading branch information
fabpot committed Apr 4, 2018
2 parents fe6aa64 + fa9db29 commit 2a4d024
Show file tree
Hide file tree
Showing 3 changed files with 82 additions and 0 deletions.
30 changes: 30 additions & 0 deletions src/Symfony/Component/Ldap/Adapter/ExtLdap/EntryManager.php
Expand Up @@ -67,6 +67,36 @@ public function remove(Entry $entry)
}
}

/**
* Adds values to an entry's multi-valued attribute from the LDAP server.
*
* @throws NotBoundException
* @throws LdapException
*/
public function addAttributeValues(Entry $entry, string $attribute, array $values)
{
$con = $this->getConnectionResource();

if (!@ldap_mod_add($con, $entry->getDn(), array($attribute => $values))) {
throw new LdapException(sprintf('Could not add values to entry "%s", attribute %s: %s.', $entry->getDn(), $attribute, ldap_error($con)));
}
}

/**
* Removes values from an entry's multi-valued attribute from the LDAP server.
*
* @throws NotBoundException
* @throws LdapException
*/
public function removeAttributeValues(Entry $entry, string $attribute, array $values)
{
$con = $this->getConnectionResource();

if (!@ldap_mod_del($con, $entry->getDn(), array($attribute => $values))) {
throw new LdapException(sprintf('Could not remove values from entry "%s", attribute %s: %s.', $entry->getDn(), $attribute, ldap_error($con)));
}
}

/**
* {@inheritdoc}
*/
Expand Down
6 changes: 6 additions & 0 deletions src/Symfony/Component/Ldap/CHANGELOG.md
@@ -1,6 +1,12 @@
CHANGELOG
=========

4.1.0
-----

* Added support for adding values to multi-valued attributes
* Added support for removing values from multi-valued attributes

4.0.0
-----

Expand Down
Expand Up @@ -192,4 +192,50 @@ public function testLdapRenameWithoutRemovingOldRdn()

$this->executeSearchQuery(1);
}

public function testLdapAddRemoveAttributeValues()
{
$entryManager = $this->adapter->getEntryManager();

$result = $this->executeSearchQuery(1);
$entry = $result[0];

$entryManager->addAttributeValues($entry, 'mail', array('fabpot@example.org', 'fabpot2@example.org'));

$result = $this->executeSearchQuery(1);
$newEntry = $result[0];

$this->assertCount(4, $newEntry->getAttribute('mail'));

$entryManager->removeAttributeValues($newEntry, 'mail', array('fabpot@example.org', 'fabpot2@example.org'));

$result = $this->executeSearchQuery(1);
$newNewEntry = $result[0];

$this->assertCount(2, $newNewEntry->getAttribute('mail'));
}

public function testLdapRemoveAttributeValuesError()
{
$entryManager = $this->adapter->getEntryManager();

$result = $this->executeSearchQuery(1);
$entry = $result[0];

$this->{method_exists($this, $_ = 'expectException') ? $_ : 'setExpectedException'}(LdapException::class);

$entryManager->removeAttributeValues($entry, 'mail', array('fabpot@example.org'));
}

public function testLdapAddAttributeValuesError()
{
$entryManager = $this->adapter->getEntryManager();

$result = $this->executeSearchQuery(1);
$entry = $result[0];

$this->{method_exists($this, $_ = 'expectException') ? $_ : 'setExpectedException'}(LdapException::class);

$entryManager->addAttributeValues($entry, 'mail', $entry->getAttribute('mail'));
}
}

0 comments on commit 2a4d024

Please sign in to comment.