feature #17817 [Ldap] Add write support for the Ldap component (csarrazi)

This PR was merged into the 3.1-dev branch.

Discussion
----------

[Ldap] Add write support for the Ldap component

| Q             | A
| ------------- | ---
| Bug fix?      | no
| New feature?  | yes
| BC breaks?    | yes
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets | #17679
| License       | MIT
| Doc PR        | no

This PR implements write support for the Ldap component.

Commits
-------

dfd04ff Added support for adding / removing / updating Ldap entries
This commit is contained in:
Fabien Potencier 2016-02-18 08:20:51 +01:00
commit e837b34c34
8 changed files with 281 additions and 0 deletions

View File

@ -34,6 +34,13 @@ interface AdapterInterface
*/
public function createQuery($dn, $query, array $options = array());
/**
* Fetches the entry manager instance.
*
* @return EntryManagerInterface
*/
public function getEntryManager();
/**
* Escape a string for use in an LDAP filter or DN.
*

View File

@ -0,0 +1,43 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Ldap\Adapter;
use Symfony\Component\Ldap\Entry;
/**
* Entry manager interface.
*
* @author Charles Sarrazin <charles@sarraz.in>
*/
interface EntryManagerInterface
{
/**
* Adds a new entry in the Ldap server.
*
* @param Entry $entry
*/
public function add(Entry $entry);
/**
* Updates an entry from the Ldap server.
*
* @param Entry $entry
*/
public function update(Entry $entry);
/**
* Removes an entry from the Ldap server.
*
* @param Entry $entry
*/
public function remove(Entry $entry);
}

View File

@ -21,6 +21,7 @@ class Adapter implements AdapterInterface
{
private $config;
private $connection;
private $entryManager;
public function __construct(array $config = array())
{
@ -43,6 +44,18 @@ class Adapter implements AdapterInterface
return $this->connection;
}
/**
* {@inheritdoc}
*/
public function getEntryManager()
{
if (null === $this->entryManager) {
$this->entryManager = new EntryManager($this->connection);
}
return $this->entryManager;
}
/**
* {@inheritdoc}
*/

View File

@ -0,0 +1,67 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Ldap\Adapter\ExtLdap;
use Symfony\Component\Ldap\Adapter\EntryManagerInterface;
use Symfony\Component\Ldap\Entry;
use Symfony\Component\Ldap\Exception\LdapException;
/**
* @author Charles Sarrazin <charles@sarraz.in>
*/
class EntryManager implements EntryManagerInterface
{
private $connection;
public function __construct(Connection $connection)
{
$this->connection = $connection;
}
/**
* {@inheritdoc}
*/
public function add(Entry $entry)
{
$con = $this->connection->getResource();
if (!@ldap_add($con, $entry->getDn(), $entry->getAttributes())) {
throw new LdapException(sprintf('Could not add entry "%s": %s', $entry->getDn(), ldap_error($con)));
}
return $this;
}
/**
* {@inheritdoc}
*/
public function update(Entry $entry)
{
$con = $this->connection->getResource();
if (!@ldap_modify($con, $entry->getDn(), $entry->getAttributes())) {
throw new LdapException(sprintf('Could not update entry "%s": %s', $entry->getDn(), ldap_error($con)));
}
}
/**
* {@inheritdoc}
*/
public function remove(Entry $entry)
{
$con = $this->connection->getResource();
if (!@ldap_delete($con, $entry->getDn())) {
throw new LdapException(sprintf('Could not remove entry "%s": %s', $entry->getDn(), ldap_error($con)));
}
}
}

View File

@ -59,4 +59,25 @@ class Entry
{
return $this->attributes;
}
/**
* Sets a value for the given attribute.
*
* @param $name
* @param array $value
*/
public function setAttribute($name, array $value)
{
$this->attributes[$name] = $value;
}
/**
* Removes a given attribute.
*
* @param $name
*/
public function removeAttribute($name)
{
unset($this->attributes[$name]);
}
}

View File

@ -46,6 +46,14 @@ final class Ldap implements LdapInterface
return $this->adapter->createQuery($dn, $query, $options);
}
/**
* {@inheritdoc}
*/
public function getEntryManager()
{
return $this->adapter->getEntryManager();
}
/**
* {@inheritdoc}
*/

View File

@ -11,6 +11,7 @@
namespace Symfony\Component\Ldap;
use Symfony\Component\Ldap\Adapter\EntryManagerInterface;
use Symfony\Component\Ldap\Adapter\QueryInterface;
/**
@ -33,4 +34,9 @@ interface LdapInterface extends BaseLdapInterface
* @return QueryInterface
*/
public function query($dn, $query, array $options = array());
/**
* @return EntryManagerInterface
*/
public function getEntryManager();
}

View File

@ -0,0 +1,116 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Ldap\Tests;
use Symfony\Component\Ldap\Adapter\ExtLdap\Adapter;
use Symfony\Component\Ldap\Adapter\ExtLdap\Collection;
use Symfony\Component\Ldap\Entry;
use Symfony\Component\Ldap\Exception\LdapException;
/**
* @requires extension ldap
*/
class LdapManagerTest extends \PHPUnit_Framework_TestCase
{
/** @var Adapter */
private $adapter;
protected function setUp()
{
$this->adapter = new Adapter(array('host' => 'localhost', 'port' => 3389));
$this->adapter->getConnection()->bind('cn=admin,dc=symfony,dc=com', 'symfony');
}
/**
* @group functional
*/
public function testLdapAddAndRemove()
{
$this->executeSearchQuery(1);
$entry = new Entry('cn=Charles Sarrazin,dc=symfony,dc=com', array(
'sn' => array('csarrazi'),
'objectclass' => array(
'inetOrgPerson',
),
));
$em = $this->adapter->getEntryManager();
$em->add($entry);
$this->executeSearchQuery(2);
$em->remove($entry);
$this->executeSearchQuery(1);
}
/**
* @group functional
*/
public function testLdapAddInvalidEntry()
{
$this->setExpectedException(LdapException::class);
$this->executeSearchQuery(1);
// The entry is missing a subject name
$entry = new Entry('cn=Charles Sarrazin,dc=symfony,dc=com', array(
'objectclass' => array(
'inetOrgPerson',
),
));
$em = $this->adapter->getEntryManager();
$em->add($entry);
}
/**
* @group functional
*/
public function testLdapUpdate()
{
$result = $this->executeSearchQuery(1);
$entry = $result[0];
$this->assertNull($entry->getAttribute('email'));
$em = $this->adapter->getEntryManager();
$em->update($entry);
$result = $this->executeSearchQuery(1);
$entry = $result[0];
$this->assertNull($entry->getAttribute('email'));
$entry->removeAttribute('email');
$em->update($entry);
$result = $this->executeSearchQuery(1);
$entry = $result[0];
$this->assertNull($entry->getAttribute('email'));
}
/**
* @return Collection|Entry[]
*/
private function executeSearchQuery($expectedResults = 1)
{
$results = $this
->adapter
->createQuery('dc=symfony,dc=com', '(objectclass=person)')
->execute()
;
$this->assertCount($expectedResults, $results);
return $results;
}
}