Initial commit of LDAP plugin

This commit is contained in:
Andy Miller
2018-05-07 05:40:25 -06:00
parent cef5268e09
commit d4d885a874
90 changed files with 7961 additions and 1 deletions

3
vendor/symfony/ldap/.gitignore vendored Normal file
View File

@@ -0,0 +1,3 @@
vendor/
composer.lock
phpunit.xml

View File

@@ -0,0 +1,63 @@
<?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\OptionsResolver\Options;
use Symfony\Component\OptionsResolver\OptionsResolver;
/**
* @author Charles Sarrazin <charles@sarraz.in>
*/
abstract class AbstractConnection implements ConnectionInterface
{
protected $config;
public function __construct(array $config = array())
{
$resolver = new OptionsResolver();
$this->configureOptions($resolver);
$this->config = $resolver->resolve($config);
}
/**
* Configures the adapter's options.
*
* @param OptionsResolver $resolver An OptionsResolver instance
*/
protected function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'host' => 'localhost',
'version' => 3,
'connection_string' => null,
'encryption' => 'none',
'options' => array(),
));
$resolver->setDefault('port', function (Options $options) {
return 'ssl' === $options['encryption'] ? 636 : 389;
});
$resolver->setDefault('connection_string', function (Options $options) {
return sprintf('ldap%s://%s:%s', 'ssl' === $options['encryption'] ? 's' : '', $options['host'], $options['port']);
});
$resolver->setAllowedTypes('host', 'string');
$resolver->setAllowedTypes('port', 'numeric');
$resolver->setAllowedTypes('connection_string', 'string');
$resolver->setAllowedTypes('version', 'numeric');
$resolver->setAllowedValues('encryption', array('none', 'ssl', 'tls'));
$resolver->setAllowedTypes('options', 'array');
}
}

View File

@@ -0,0 +1,51 @@
<?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\OptionsResolver\Options;
use Symfony\Component\OptionsResolver\OptionsResolver;
/**
* @author Charles Sarrazin <charles@sarraz.in>
*/
abstract class AbstractQuery implements QueryInterface
{
protected $connection;
protected $dn;
protected $query;
protected $options;
public function __construct(ConnectionInterface $connection, $dn, $query, array $options = array())
{
$resolver = new OptionsResolver();
$resolver->setDefaults(array(
'filter' => '*',
'maxItems' => 0,
'sizeLimit' => 0,
'timeout' => 0,
'deref' => static::DEREF_NEVER,
'attrsOnly' => 0,
'scope' => static::SCOPE_SUB,
));
$resolver->setAllowedValues('deref', array(static::DEREF_ALWAYS, static::DEREF_NEVER, static::DEREF_FINDING, static::DEREF_SEARCHING));
$resolver->setAllowedValues('scope', array(static::SCOPE_BASE, static::SCOPE_ONE, static::SCOPE_SUB));
$resolver->setNormalizer('filter', function (Options $options, $value) {
return is_array($value) ? $value : array($value);
});
$this->connection = $connection;
$this->dn = $dn;
$this->query = $query;
$this->options = $resolver->resolve($options);
}
}

View File

@@ -0,0 +1,54 @@
<?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;
/**
* @author Charles Sarrazin <charles@sarraz.in>
*/
interface AdapterInterface
{
/**
* Returns the current connection.
*
* @return ConnectionInterface
*/
public function getConnection();
/**
* Creates a new Query.
*
* @param string $dn
* @param string $query
* @param array $options
*
* @return QueryInterface
*/
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.
*
* @param string $subject
* @param string $ignore
* @param int $flags
*
* @return string
*/
public function escape($subject, $ignore = '', $flags = 0);
}

View File

@@ -0,0 +1,25 @@
<?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;
/**
* @author Charles Sarrazin <charles@sarraz.in>
*/
interface CollectionInterface extends \Countable, \IteratorAggregate, \ArrayAccess
{
/**
* @return Entry[]
*/
public function toArray();
}

View File

@@ -0,0 +1,33 @@
<?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;
/**
* @author Charles Sarrazin <charles@sarraz.in>
*/
interface ConnectionInterface
{
/**
* Checks whether the connection was already bound or not.
*
* @return bool
*/
public function isBound();
/**
* Binds the connection against a DN and password.
*
* @param string $dn The user's DN
* @param string $password The associated password
*/
public function bind($dn = null, $password = null);
}

View File

@@ -0,0 +1,55 @@
<?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;
use Symfony\Component\Ldap\Exception\LdapException;
use Symfony\Component\Ldap\Exception\NotBoundException;
/**
* Entry manager interface.
*
* @author Charles Sarrazin <charles@sarraz.in>
* @author Bob van de Vijver <bobvandevijver@hotmail.com>
*/
interface EntryManagerInterface
{
/**
* Adds a new entry in the Ldap server.
*
* @param Entry $entry
*
* @throws NotBoundException
* @throws LdapException
*/
public function add(Entry $entry);
/**
* Updates an entry from the Ldap server.
*
* @param Entry $entry
*
* @throws NotBoundException
* @throws LdapException
*/
public function update(Entry $entry);
/**
* Removes an entry from the Ldap server.
*
* @param Entry $entry
*
* @throws NotBoundException
* @throws LdapException
*/
public function remove(Entry $entry);
}

View File

@@ -0,0 +1,87 @@
<?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\AdapterInterface;
use Symfony\Component\Ldap\Exception\LdapException;
/**
* @author Charles Sarrazin <charles@sarraz.in>
*/
class Adapter implements AdapterInterface
{
private $config;
private $connection;
private $entryManager;
public function __construct(array $config = array())
{
if (!extension_loaded('ldap')) {
throw new LdapException('The LDAP PHP extension is not enabled.');
}
$this->config = $config;
}
/**
* {@inheritdoc}
*/
public function getConnection()
{
if (null === $this->connection) {
$this->connection = new Connection($this->config);
}
return $this->connection;
}
/**
* {@inheritdoc}
*/
public function getEntryManager()
{
if (null === $this->entryManager) {
$this->entryManager = new EntryManager($this->getConnection());
}
return $this->entryManager;
}
/**
* {@inheritdoc}
*/
public function createQuery($dn, $query, array $options = array())
{
return new Query($this->getConnection(), $dn, $query, $options);
}
/**
* {@inheritdoc}
*/
public function escape($subject, $ignore = '', $flags = 0)
{
$value = ldap_escape($subject, $ignore, $flags);
// Per RFC 4514, leading/trailing spaces should be encoded in DNs, as well as carriage returns.
if ((int) $flags & LDAP_ESCAPE_DN) {
if (!empty($value) && ' ' === $value[0]) {
$value = '\\20'.substr($value, 1);
}
if (!empty($value) && ' ' === $value[strlen($value) - 1]) {
$value = substr($value, 0, -1).'\\20';
}
$value = str_replace("\r", '\0d', $value);
}
return $value;
}
}

View File

@@ -0,0 +1,134 @@
<?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\CollectionInterface;
use Symfony\Component\Ldap\Entry;
use Symfony\Component\Ldap\Exception\LdapException;
/**
* @author Charles Sarrazin <charles@sarraz.in>
*/
class Collection implements CollectionInterface
{
private $connection;
private $search;
private $entries;
public function __construct(Connection $connection, Query $search)
{
$this->connection = $connection;
$this->search = $search;
}
/**
* {@inheritdoc}
*/
public function toArray()
{
if (null === $this->entries) {
$this->entries = iterator_to_array($this->getIterator(), false);
}
return $this->entries;
}
public function count()
{
if (false !== $count = ldap_count_entries($this->connection->getResource(), $this->search->getResource())) {
return $count;
}
throw new LdapException(sprintf('Error while retrieving entry count: %s.', ldap_error($this->connection->getResource())));
}
public function getIterator()
{
$con = $this->connection->getResource();
$search = $this->search->getResource();
$current = ldap_first_entry($con, $search);
if (0 === $this->count()) {
return;
}
if (false === $current) {
throw new LdapException(sprintf('Could not rewind entries array: %s.', ldap_error($con)));
}
yield $this->getSingleEntry($con, $current);
while (false !== $current = ldap_next_entry($con, $current)) {
yield $this->getSingleEntry($con, $current);
}
}
public function offsetExists($offset)
{
$this->toArray();
return isset($this->entries[$offset]);
}
public function offsetGet($offset)
{
$this->toArray();
return isset($this->entries[$offset]) ? $this->entries[$offset] : null;
}
public function offsetSet($offset, $value)
{
$this->toArray();
$this->entries[$offset] = $value;
}
public function offsetUnset($offset)
{
$this->toArray();
unset($this->entries[$offset]);
}
private function getSingleEntry($con, $current)
{
$attributes = ldap_get_attributes($con, $current);
if (false === $attributes) {
throw new LdapException(sprintf('Could not fetch attributes: %s.', ldap_error($con)));
}
$attributes = $this->cleanupAttributes($attributes);
$dn = ldap_get_dn($con, $current);
if (false === $dn) {
throw new LdapException(sprintf('Could not fetch DN: %s.', ldap_error($con)));
}
return new Entry($dn, $attributes);
}
private function cleanupAttributes(array $entry)
{
$attributes = array_diff_key($entry, array_flip(range(0, $entry['count'] - 1)) + array(
'count' => null,
'dn' => null,
));
array_walk($attributes, function (&$value) {
unset($value['count']);
});
return $attributes;
}
}

View File

@@ -0,0 +1,154 @@
<?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\AbstractConnection;
use Symfony\Component\Ldap\Exception\ConnectionException;
use Symfony\Component\Ldap\Exception\LdapException;
use Symfony\Component\OptionsResolver\Options;
use Symfony\Component\OptionsResolver\OptionsResolver;
/**
* @author Charles Sarrazin <charles@sarraz.in>
*/
class Connection extends AbstractConnection
{
/** @var bool */
private $bound = false;
/** @var resource */
private $connection;
public function __destruct()
{
$this->disconnect();
}
/**
* {@inheritdoc}
*/
public function isBound()
{
return $this->bound;
}
/**
* {@inheritdoc}
*/
public function bind($dn = null, $password = null)
{
if (!$this->connection) {
$this->connect();
}
if (false === @ldap_bind($this->connection, $dn, $password)) {
throw new ConnectionException(ldap_error($this->connection));
}
$this->bound = true;
}
/**
* Returns a link resource.
*
* @return resource
*
* @internal
*/
public function getResource()
{
return $this->connection;
}
public function setOption($name, $value)
{
if (!@ldap_set_option($this->connection, ConnectionOptions::getOption($name), $value)) {
throw new LdapException(sprintf('Could not set value "%s" for option "%s".', $value, $name));
}
}
public function getOption($name)
{
if (!@ldap_get_option($this->connection, ConnectionOptions::getOption($name), $ret)) {
throw new LdapException(sprintf('Could not retrieve value for option "%s".', $name));
}
return $ret;
}
protected function configureOptions(OptionsResolver $resolver)
{
parent::configureOptions($resolver);
$resolver->setDefault('debug', false);
$resolver->setAllowedTypes('debug', 'bool');
$resolver->setDefault('referrals', false);
$resolver->setAllowedTypes('referrals', 'bool');
$resolver->setNormalizer('options', function (Options $options, $value) {
if (true === $options['debug']) {
$value['debug_level'] = 7;
}
if (!isset($value['protocol_version'])) {
$value['protocol_version'] = $options['version'];
}
if (!isset($value['referrals'])) {
$value['referrals'] = $options['referrals'];
}
return $value;
});
$resolver->setAllowedValues('options', function (array $values) {
foreach ($values as $name => $value) {
if (!ConnectionOptions::isOption($name)) {
return false;
}
}
return true;
});
}
private function connect()
{
if ($this->connection) {
return;
}
$this->connection = ldap_connect($this->config['connection_string']);
foreach ($this->config['options'] as $name => $value) {
$this->setOption($name, $value);
}
if (false === $this->connection) {
throw new LdapException(sprintf('Could not connect to Ldap server: %s.', ldap_error($this->connection)));
}
if ('tls' === $this->config['encryption'] && false === ldap_start_tls($this->connection)) {
throw new LdapException(sprintf('Could not initiate TLS connection: %s.', ldap_error($this->connection)));
}
}
private function disconnect()
{
if ($this->connection && is_resource($this->connection)) {
ldap_close($this->connection);
}
$this->connection = null;
$this->bound = false;
}
}

View File

@@ -0,0 +1,78 @@
<?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\Exception\LdapException;
/**
* A class representing the Ldap extension's options, which can be used with
* ldap_set_option or ldap_get_option.
*
* @author Charles Sarrazin <charles@sarraz.in>
*
* @internal
*/
final class ConnectionOptions
{
const API_INFO = 0x00;
const DEREF = 0x02;
const SIZELIMIT = 0x03;
const TIMELIMIT = 0x04;
const REFERRALS = 0x08;
const RESTART = 0x09;
const PROTOCOL_VERSION = 0x11;
const SERVER_CONTROLS = 0x12;
const CLIENT_CONTROLS = 0x13;
const API_FEATURE_INFO = 0x15;
const HOST_NAME = 0x30;
const ERROR_NUMBER = 0x31;
const ERROR_STRING = 0x32;
const MATCHED_DN = 0x33;
const DEBUG_LEVEL = 0x5001;
const NETWORK_TIMEOUT = 0x5005;
const X_SASL_MECH = 0x6100;
const X_SASL_REALM = 0x6101;
const X_SASL_AUTHCID = 0x6102;
const X_SASL_AUTHZID = 0x6103;
public static function getOptionName($name)
{
return sprintf('%s::%s', self::class, strtoupper($name));
}
/**
* Fetches an option's corresponding constant value from an option name.
* The option name can either be in snake or camel case.
*
* @param string $name
*
* @return int
*
* @throws LdapException
*/
public static function getOption($name)
{
// Convert
$constantName = self::getOptionName($name);
if (!defined($constantName)) {
throw new LdapException(sprintf('Unknown option "%s".', $name));
}
return constant($constantName);
}
public static function isOption($name)
{
return defined(self::getOptionName($name));
}
}

View File

@@ -0,0 +1,95 @@
<?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\Adapter\RenameEntryInterface;
use Symfony\Component\Ldap\Entry;
use Symfony\Component\Ldap\Exception\LdapException;
use Symfony\Component\Ldap\Exception\NotBoundException;
/**
* @author Charles Sarrazin <charles@sarraz.in>
* @author Bob van de Vijver <bobvandevijver@hotmail.com>
*/
class EntryManager implements EntryManagerInterface, RenameEntryInterface
{
private $connection;
public function __construct(Connection $connection)
{
$this->connection = $connection;
}
/**
* {@inheritdoc}
*/
public function add(Entry $entry)
{
$con = $this->getConnectionResource();
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->getConnectionResource();
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->getConnectionResource();
if (!@ldap_delete($con, $entry->getDn())) {
throw new LdapException(sprintf('Could not remove entry "%s": %s.', $entry->getDn(), ldap_error($con)));
}
}
/**
* {@inheritdoc}
*/
public function rename(Entry $entry, $newRdn, $removeOldRdn = true)
{
$con = $this->getConnectionResource();
if (!@ldap_rename($con, $entry->getDn(), $newRdn, null, $removeOldRdn)) {
throw new LdapException(sprintf('Could not rename entry "%s" to "%s": %s.', $entry->getDn(), $newRdn, ldap_error($con)));
}
}
/**
* Get the connection resource, but first check if the connection is bound.
*/
private function getConnectionResource()
{
// If the connection is not bound, throw an exception. Users should use an explicit bind call first.
if (!$this->connection->isBound()) {
throw new NotBoundException('Query execution is not possible without binding the connection first.');
}
return $this->connection->getResource();
}
}

View File

@@ -0,0 +1,109 @@
<?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\AbstractQuery;
use Symfony\Component\Ldap\Exception\LdapException;
use Symfony\Component\Ldap\Exception\NotBoundException;
/**
* @author Charles Sarrazin <charles@sarraz.in>
* @author Bob van de Vijver <bobvandevijver@hotmail.com>
*/
class Query extends AbstractQuery
{
/** @var Connection */
protected $connection;
/** @var resource */
private $search;
public function __construct(Connection $connection, $dn, $query, array $options = array())
{
parent::__construct($connection, $dn, $query, $options);
}
public function __destruct()
{
$con = $this->connection->getResource();
$this->connection = null;
if (null === $this->search || false === $this->search) {
return;
}
$success = ldap_free_result($this->search);
$this->search = null;
if (!$success) {
throw new LdapException(sprintf('Could not free results: %s.', ldap_error($con)));
}
}
/**
* {@inheritdoc}
*/
public function execute()
{
if (null === $this->search) {
// If the connection is not bound, throw an exception. Users should use an explicit bind call first.
if (!$this->connection->isBound()) {
throw new NotBoundException('Query execution is not possible without binding the connection first.');
}
$con = $this->connection->getResource();
switch ($this->options['scope']) {
case static::SCOPE_BASE:
$func = 'ldap_read';
break;
case static::SCOPE_ONE:
$func = 'ldap_list';
break;
case static::SCOPE_SUB:
$func = 'ldap_search';
break;
default:
throw new LdapException(sprintf('Could not search in scope "%s".', $this->options['scope']));
}
$this->search = @$func(
$con,
$this->dn,
$this->query,
$this->options['filter'],
$this->options['attrsOnly'],
$this->options['maxItems'],
$this->options['timeout'],
$this->options['deref']
);
}
if (false === $this->search) {
throw new LdapException(sprintf('Could not complete search with dn "%s", query "%s" and filters "%s".', $this->dn, $this->query, implode(',', $this->options['filter'])));
}
return new Collection($this->connection, $this);
}
/**
* Returns a LDAP search resource.
*
* @return resource
*
* @internal
*/
public function getResource()
{
return $this->search;
}
}

View File

@@ -0,0 +1,42 @@
<?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;
use Symfony\Component\Ldap\Exception\LdapException;
use Symfony\Component\Ldap\Exception\NotBoundException;
/**
* @author Charles Sarrazin <charles@sarraz.in>
* @author Bob van de Vijver <bobvandevijver@hotmail.com>
*/
interface QueryInterface
{
const DEREF_NEVER = 0x00;
const DEREF_SEARCHING = 0x01;
const DEREF_FINDING = 0x02;
const DEREF_ALWAYS = 0x03;
const SCOPE_BASE = 'base';
const SCOPE_ONE = 'one';
const SCOPE_SUB = 'sub';
/**
* Executes a query and returns the list of Ldap entries.
*
* @return CollectionInterface|Entry[]
*
* @throws NotBoundException
* @throws LdapException
*/
public function execute();
}

View File

@@ -0,0 +1,22 @@
<?php
namespace Symfony\Component\Ldap\Adapter;
use Symfony\Component\Ldap\Entry;
/**
* @author Kevin Schuurmans <kevin.schuurmans@freshheads.com>
*
* @deprecated since version 3.3, will be merged with {@link EntryManagerInterface} in 4.0.
*/
interface RenameEntryInterface
{
/**
* Renames an entry on the Ldap server.
*
* @param Entry $entry
* @param string $newRdn
* @param bool $removeOldRdn
*/
public function rename(Entry $entry, $newRdn, $removeOldRdn = true);
}

12
vendor/symfony/ldap/CHANGELOG.md vendored Normal file
View File

@@ -0,0 +1,12 @@
CHANGELOG
=========
3.3.0
-----
* The `RenameEntryInterface` inferface is deprecated, and will be merged with `EntryManagerInterface` in 4.0.
3.1.0
-----
* The `LdapClient` class is deprecated. Use the `Ldap` class instead.

95
vendor/symfony/ldap/Entry.php vendored Normal file
View File

@@ -0,0 +1,95 @@
<?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;
/**
* @author Charles Sarrazin <charles@sarraz.in>
*/
class Entry
{
private $dn;
private $attributes;
public function __construct($dn, array $attributes = array())
{
$this->dn = $dn;
$this->attributes = $attributes;
}
/**
* Returns the entry's DN.
*
* @return string
*/
public function getDn()
{
return $this->dn;
}
/**
* Returns whether an attribute exists.
*
* @param $name string The name of the attribute
*
* @return bool
*/
public function hasAttribute($name)
{
return isset($this->attributes[$name]);
}
/**
* Returns a specific attribute's value.
*
* As LDAP can return multiple values for a single attribute,
* this value is returned as an array.
*
* @param $name string The name of the attribute
*
* @return null|array
*/
public function getAttribute($name)
{
return isset($this->attributes[$name]) ? $this->attributes[$name] : null;
}
/**
* Returns the complete list of attributes.
*
* @return array
*/
public function getAttributes()
{
return $this->attributes;
}
/**
* Sets a value for the given attribute.
*
* @param string $name
* @param array $value
*/
public function setAttribute($name, array $value)
{
$this->attributes[$name] = $value;
}
/**
* Removes a given attribute.
*
* @param string $name
*/
public function removeAttribute($name)
{
unset($this->attributes[$name]);
}
}

View File

@@ -0,0 +1,21 @@
<?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\Exception;
/**
* ConnectionException is throw if binding to ldap can not be established.
*
* @author Grégoire Pineau <lyrixx@lyrixx.info>
*/
class ConnectionException extends \RuntimeException implements ExceptionInterface
{
}

View File

@@ -0,0 +1,21 @@
<?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\Exception;
/**
* LdapException is throw if php ldap module is not loaded.
*
* @author Charles Sarrazin <charles@sarraz.in>
*/
class DriverNotFoundException extends \RuntimeException implements ExceptionInterface
{
}

View File

@@ -0,0 +1,21 @@
<?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\Exception;
/**
* Base ExceptionInterface for the Ldap component.
*
* @author Charles Sarrazin <charles@sarraz.in>
*/
interface ExceptionInterface
{
}

View File

@@ -0,0 +1,21 @@
<?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\Exception;
/**
* LdapException is throw if php ldap module is not loaded.
*
* @author Grégoire Pineau <lyrixx@lyrixx.info>
*/
class LdapException extends \RuntimeException implements ExceptionInterface
{
}

View File

@@ -0,0 +1,21 @@
<?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\Exception;
/**
* NotBoundException is thrown if the connection with the LDAP server is not yet bound.
*
* @author Bob van de Vijver <bobvandevijver@hotmail.com>
*/
class NotBoundException extends \RuntimeException implements ExceptionInterface
{
}

19
vendor/symfony/ldap/LICENSE vendored Normal file
View File

@@ -0,0 +1,19 @@
Copyright (c) 2004-2018 Fabien Potencier
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

87
vendor/symfony/ldap/Ldap.php vendored Normal file
View File

@@ -0,0 +1,87 @@
<?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;
use Symfony\Component\Ldap\Adapter\AdapterInterface;
use Symfony\Component\Ldap\Exception\DriverNotFoundException;
/**
* @author Charles Sarrazin <charles@sarraz.in>
*/
final class Ldap implements LdapInterface
{
private $adapter;
private static $adapterMap = array(
'ext_ldap' => 'Symfony\Component\Ldap\Adapter\ExtLdap\Adapter',
);
public function __construct(AdapterInterface $adapter)
{
$this->adapter = $adapter;
}
/**
* {@inheritdoc}
*/
public function bind($dn = null, $password = null)
{
$this->adapter->getConnection()->bind($dn, $password);
}
/**
* {@inheritdoc}
*/
public function query($dn, $query, array $options = array())
{
return $this->adapter->createQuery($dn, $query, $options);
}
/**
* {@inheritdoc}
*/
public function getEntryManager()
{
return $this->adapter->getEntryManager();
}
/**
* {@inheritdoc}
*/
public function escape($subject, $ignore = '', $flags = 0)
{
return $this->adapter->escape($subject, $ignore, $flags);
}
/**
* Creates a new Ldap instance.
*
* @param string $adapter The adapter name
* @param array $config The adapter's configuration
*
* @return static
*/
public static function create($adapter, array $config = array())
{
if (!isset(self::$adapterMap[$adapter])) {
throw new DriverNotFoundException(sprintf(
'Adapter "%s" not found. You should use one of: %s',
$adapter,
implode(', ', self::$adapterMap)
));
}
$class = self::$adapterMap[$adapter];
return new self(new $class($config));
}
}

127
vendor/symfony/ldap/LdapClient.php vendored Normal file
View File

@@ -0,0 +1,127 @@
<?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;
@trigger_error('The '.__NAMESPACE__.'\LdapClient class is deprecated since Symfony 3.1 and will be removed in 4.0. Use the Ldap class directly instead.', E_USER_DEPRECATED);
/**
* @author Grégoire Pineau <lyrixx@lyrixx.info>
* @author Francis Besset <francis.besset@gmail.com>
* @author Charles Sarrazin <charles@sarraz.in>
*
* @deprecated since version 3.1, to be removed in 4.0. Use the Ldap class instead.
*/
final class LdapClient implements LdapClientInterface
{
private $ldap;
public function __construct($host = null, $port = 389, $version = 3, $useSsl = false, $useStartTls = false, $optReferrals = false, LdapInterface $ldap = null)
{
$config = $this->normalizeConfig($host, $port, $version, $useSsl, $useStartTls, $optReferrals);
$this->ldap = null !== $ldap ? $ldap : Ldap::create('ext_ldap', $config);
}
/**
* {@inheritdoc}
*/
public function bind($dn = null, $password = null)
{
$this->ldap->bind($dn, $password);
}
/**
* {@inheritdoc}
*/
public function query($dn, $query, array $options = array())
{
return $this->ldap->query($dn, $query, $options);
}
/**
* {@inheritdoc}
*/
public function getEntryManager()
{
return $this->ldap->getEntryManager();
}
/**
* {@inheritdoc}
*/
public function find($dn, $query, $filter = '*')
{
@trigger_error('The "find" method is deprecated since Symfony 3.1 and will be removed in 4.0. Use the "query" method instead.', E_USER_DEPRECATED);
$query = $this->ldap->query($dn, $query, array('filter' => $filter));
$entries = $query->execute();
$result = array(
'count' => 0,
);
foreach ($entries as $entry) {
$resultEntry = array();
foreach ($entry->getAttributes() as $attribute => $values) {
$resultAttribute = array(
'count' => count($values),
);
foreach ($values as $val) {
$resultAttribute[] = $val;
}
$attributeName = strtolower($attribute);
$resultAttribute['count'] = count($values);
$resultEntry[$attributeName] = $resultAttribute;
$resultEntry[] = $attributeName;
}
$resultEntry['count'] = count($resultEntry) / 2;
$resultEntry['dn'] = $entry->getDn();
$result[] = $resultEntry;
}
$result['count'] = count($result) - 1;
return $result;
}
/**
* {@inheritdoc}
*/
public function escape($subject, $ignore = '', $flags = 0)
{
return $this->ldap->escape($subject, $ignore, $flags);
}
private function normalizeConfig($host, $port, $version, $useSsl, $useStartTls, $optReferrals)
{
if ((bool) $useSsl) {
$encryption = 'ssl';
} elseif ((bool) $useStartTls) {
$encryption = 'tls';
} else {
$encryption = 'none';
}
return array(
'host' => $host,
'port' => $port,
'encryption' => $encryption,
'options' => array(
'protocol_version' => $version,
'referrals' => (bool) $optReferrals,
),
);
}
}

View File

@@ -0,0 +1,36 @@
<?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;
/**
* Ldap interface.
*
* This interface is used for the BC layer with branch 2.8 and 3.0.
*
* @author Grégoire Pineau <lyrixx@lyrixx.info>
* @author Charles Sarrazin <charles@sarraz.in>
*
* @deprecated since version 3.1, to be removed in 4.0. Use the LdapInterface instead.
*/
interface LdapClientInterface extends LdapInterface
{
/**
* Find a username into ldap connection.
*
* @param string $dn
* @param string $query
* @param mixed $filter
*
* @return array|null
*/
public function find($dn, $query, $filter = '*');
}

64
vendor/symfony/ldap/LdapInterface.php vendored Normal file
View File

@@ -0,0 +1,64 @@
<?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;
use Symfony\Component\Ldap\Adapter\EntryManagerInterface;
use Symfony\Component\Ldap\Adapter\QueryInterface;
use Symfony\Component\Ldap\Exception\ConnectionException;
/**
* Ldap interface.
*
* @author Charles Sarrazin <charles@sarraz.in>
*/
interface LdapInterface
{
const ESCAPE_FILTER = 0x01;
const ESCAPE_DN = 0x02;
/**
* Return a connection bound to the ldap.
*
* @param string $dn A LDAP dn
* @param string $password A password
*
* @throws ConnectionException if dn / password could not be bound
*/
public function bind($dn = null, $password = null);
/**
* Queries a ldap server for entries matching the given criteria.
*
* @param string $dn
* @param string $query
* @param array $options
*
* @return QueryInterface
*/
public function query($dn, $query, array $options = array());
/**
* @return EntryManagerInterface
*/
public function getEntryManager();
/**
* Escape a string for use in an LDAP filter or DN.
*
* @param string $subject
* @param string $ignore
* @param int $flags
*
* @return string
*/
public function escape($subject, $ignore = '', $flags = 0);
}

21
vendor/symfony/ldap/README.md vendored Normal file
View File

@@ -0,0 +1,21 @@
Ldap Component
==============
A Ldap client for PHP on top of PHP's ldap extension.
Disclaimer
----------
This component is only stable since Symfony 3.1. Earlier versions
have been marked as internal as they still needed some work.
Breaking changes were introduced in Symfony 3.1, so code relying on
previous version of the component will break with this version.
Resources
---------
* [Documentation](https://symfony.com/doc/current/components/ldap)
* [Contributing](https://symfony.com/doc/current/contributing/index.html)
* [Report issues](https://github.com/symfony/symfony/issues) and
[send Pull Requests](https://github.com/symfony/symfony/pulls)
in the [main Symfony repository](https://github.com/symfony/symfony)

View File

@@ -0,0 +1,114 @@
<?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\Adapter\ExtLdap\Query;
use Symfony\Component\Ldap\Entry;
use Symfony\Component\Ldap\Exception\NotBoundException;
use Symfony\Component\Ldap\LdapInterface;
/**
* @requires extension ldap
*/
class AdapterTest extends LdapTestCase
{
public function testLdapEscape()
{
$ldap = new Adapter();
$this->assertEquals('\20foo\3dbar\0d(baz)*\20', $ldap->escape(" foo=bar\r(baz)* ", null, LdapInterface::ESCAPE_DN));
}
/**
* @group functional
*/
public function testLdapQuery()
{
$ldap = new Adapter($this->getLdapConfig());
$ldap->getConnection()->bind('cn=admin,dc=symfony,dc=com', 'symfony');
$query = $ldap->createQuery('dc=symfony,dc=com', '(&(objectclass=person)(ou=Maintainers))', array());
$result = $query->execute();
$this->assertInstanceOf(Collection::class, $result);
$this->assertCount(1, $result);
$entry = $result[0];
$this->assertInstanceOf(Entry::class, $entry);
$this->assertEquals(array('Fabien Potencier'), $entry->getAttribute('cn'));
$this->assertEquals(array('fabpot@symfony.com', 'fabien@potencier.com'), $entry->getAttribute('mail'));
}
/**
* @group functional
*/
public function testLdapQueryIterator()
{
$ldap = new Adapter($this->getLdapConfig());
$ldap->getConnection()->bind('cn=admin,dc=symfony,dc=com', 'symfony');
$query = $ldap->createQuery('dc=symfony,dc=com', '(&(objectclass=person)(ou=Maintainers))', array());
$result = $query->execute();
$iterator = $result->getIterator();
$iterator->rewind();
$entry = $iterator->current();
$this->assertInstanceOf(Entry::class, $entry);
$this->assertEquals(array('Fabien Potencier'), $entry->getAttribute('cn'));
$this->assertEquals(array('fabpot@symfony.com', 'fabien@potencier.com'), $entry->getAttribute('mail'));
}
/**
* @group functional
*/
public function testLdapQueryWithoutBind()
{
$ldap = new Adapter($this->getLdapConfig());
$this->{method_exists($this, $_ = 'expectException') ? $_ : 'setExpectedException'}(NotBoundException::class);
$query = $ldap->createQuery('dc=symfony,dc=com', '(&(objectclass=person)(ou=Maintainers))', array());
$query->execute();
}
public function testLdapQueryScopeBase()
{
$ldap = new Adapter($this->getLdapConfig());
$ldap->getConnection()->bind('cn=admin,dc=symfony,dc=com', 'symfony');
$query = $ldap->createQuery('cn=Fabien Potencier,dc=symfony,dc=com', '(objectclass=*)', array(
'scope' => Query::SCOPE_BASE,
));
$result = $query->execute();
$entry = $result[0];
$this->assertEquals($result->count(), 1);
$this->assertEquals(array('Fabien Potencier'), $entry->getAttribute('cn'));
}
public function testLdapQueryScopeOneLevel()
{
$ldap = new Adapter($this->getLdapConfig());
$ldap->getConnection()->bind('cn=admin,dc=symfony,dc=com', 'symfony');
$one_level_result = $ldap->createQuery('ou=Components,dc=symfony,dc=com', '(objectclass=*)', array(
'scope' => Query::SCOPE_ONE,
))->execute();
$subtree_count = $ldap->createQuery('ou=Components,dc=symfony,dc=com', '(objectclass=*)')->execute()->count();
$this->assertNotEquals($one_level_result->count(), $subtree_count);
$this->assertEquals($one_level_result->count(), 1);
$this->assertEquals($one_level_result[0]->getAttribute('ou'), array('Ldap'));
}
}

View File

@@ -0,0 +1,195 @@
<?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;
use Symfony\Component\Ldap\Exception\NotBoundException;
/**
* @requires extension ldap
*/
class LdapManagerTest extends LdapTestCase
{
/** @var Adapter */
private $adapter;
protected function setUp()
{
$this->adapter = new Adapter($this->getLdapConfig());
$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->{method_exists($this, $_ = 'expectException') ? $_ : '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'));
}
/**
* @group functional
*/
public function testLdapUnboundAdd()
{
$this->adapter = new Adapter($this->getLdapConfig());
$this->{method_exists($this, $_ = 'expectException') ? $_ : 'setExpectedException'}(NotBoundException::class);
$em = $this->adapter->getEntryManager();
$em->add(new Entry(''));
}
/**
* @group functional
*/
public function testLdapUnboundRemove()
{
$this->adapter = new Adapter($this->getLdapConfig());
$this->{method_exists($this, $_ = 'expectException') ? $_ : 'setExpectedException'}(NotBoundException::class);
$em = $this->adapter->getEntryManager();
$em->remove(new Entry(''));
}
/**
* @group functional
*/
public function testLdapUnboundUpdate()
{
$this->adapter = new Adapter($this->getLdapConfig());
$this->{method_exists($this, $_ = 'expectException') ? $_ : 'setExpectedException'}(NotBoundException::class);
$em = $this->adapter->getEntryManager();
$em->update(new Entry(''));
}
/**
* @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;
}
/**
* @group functional
*/
public function testLdapRename()
{
$result = $this->executeSearchQuery(1);
$entry = $result[0];
$entryManager = $this->adapter->getEntryManager();
$entryManager->rename($entry, 'cn=Kevin');
$result = $this->executeSearchQuery(1);
$renamedEntry = $result[0];
$this->assertEquals($renamedEntry->getAttribute('cn')[0], 'Kevin');
$oldRdn = $entry->getAttribute('cn')[0];
$entryManager->rename($renamedEntry, 'cn='.$oldRdn);
$this->executeSearchQuery(1);
}
/**
* @group functional
*/
public function testLdapRenameWithoutRemovingOldRdn()
{
$result = $this->executeSearchQuery(1);
$entry = $result[0];
$entryManager = $this->adapter->getEntryManager();
$entryManager->rename($entry, 'cn=Kevin', false);
$result = $this->executeSearchQuery(1);
$newEntry = $result[0];
$originalCN = $entry->getAttribute('cn')[0];
$this->assertContains($originalCN, $newEntry->getAttribute('cn'));
$entryManager->rename($newEntry, 'cn='.$originalCN);
$this->executeSearchQuery(1);
}
}

View File

@@ -0,0 +1,17 @@
# See slapd.conf(5) for details on configuration options.
include /etc/ldap/schema/core.schema
include /etc/ldap/schema/cosine.schema
include /etc/ldap/schema/inetorgperson.schema
include /etc/ldap/schema/nis.schema
pidfile /tmp/slapd/slapd.pid
argsfile /tmp/slapd/slapd.args
modulepath /usr/lib/openldap
database ldif
directory /tmp/slapd
suffix "dc=symfony,dc=com"
rootdn "cn=admin,dc=symfony,dc=com"
rootpw {SSHA}btWUi971ytYpVMbZLkaQ2A6ETh3VA0lL

View File

@@ -0,0 +1,4 @@
dn: dc=symfony,dc=com
objectClass: dcObject
objectClass: organizationalUnit
ou: Organization

View File

@@ -0,0 +1,26 @@
dn: cn=Fabien Potencier,dc=symfony,dc=com
objectClass: inetOrgPerson
objectClass: organizationalPerson
objectClass: person
objectClass: top
cn: Fabien Potencier
sn: fabpot
mail: fabpot@symfony.com
mail: fabien@potencier.com
ou: People
ou: Maintainers
ou: Founder
givenName: Fabien Potencier
description: Founder and project lead @Symfony
dn: ou=Components,dc=symfony,dc=com
objectclass: organizationalunit
ou: Components
dn: ou=Ldap,ou=Components,dc=symfony,dc=com
objectclass: organizationalunit
ou: Ldap
dn: ou=Ldap scoping,ou=Ldap,ou=Components,dc=symfony,dc=com
objectclass: organizationalunit
ou: Ldap scoping

View File

@@ -0,0 +1,229 @@
<?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\CollectionInterface;
use Symfony\Component\Ldap\Adapter\QueryInterface;
use Symfony\Component\Ldap\Entry;
use Symfony\Component\Ldap\LdapClient;
use Symfony\Component\Ldap\LdapInterface;
/**
* @group legacy
*/
class LdapClientTest extends LdapTestCase
{
/** @var LdapClient */
private $client;
/** @var \PHPUnit_Framework_MockObject_MockObject */
private $ldap;
protected function setUp()
{
$this->ldap = $this->getMockBuilder(LdapInterface::class)->getMock();
$this->client = new LdapClient(null, 389, 3, false, false, false, $this->ldap);
}
public function testLdapBind()
{
$this->ldap
->expects($this->once())
->method('bind')
->with('foo', 'bar')
;
$this->client->bind('foo', 'bar');
}
public function testLdapEscape()
{
$this->ldap
->expects($this->once())
->method('escape')
->with('foo', 'bar', 'baz')
;
$this->client->escape('foo', 'bar', 'baz');
}
public function testLdapQuery()
{
$this->ldap
->expects($this->once())
->method('query')
->with('foo', 'bar', array('baz'))
;
$this->client->query('foo', 'bar', array('baz'));
}
public function testLdapFind()
{
$collection = $this->getMockBuilder(CollectionInterface::class)->getMock();
$collection
->expects($this->once())
->method('getIterator')
->will($this->returnValue(new \ArrayIterator(array(
new Entry('cn=qux,dc=foo,dc=com', array(
'cn' => array('qux'),
'dc' => array('com', 'foo'),
'givenName' => array('Qux'),
)),
new Entry('cn=baz,dc=foo,dc=com', array(
'cn' => array('baz'),
'dc' => array('com', 'foo'),
'givenName' => array('Baz'),
)),
))))
;
$query = $this->getMockBuilder(QueryInterface::class)->getMock();
$query
->expects($this->once())
->method('execute')
->will($this->returnValue($collection))
;
$this->ldap
->expects($this->once())
->method('query')
->with('dc=foo,dc=com', 'bar', array('filter' => 'baz'))
->willReturn($query)
;
$expected = array(
'count' => 2,
0 => array(
'count' => 3,
0 => 'cn',
'cn' => array(
'count' => 1,
0 => 'qux',
),
1 => 'dc',
'dc' => array(
'count' => 2,
0 => 'com',
1 => 'foo',
),
2 => 'givenname',
'givenname' => array(
'count' => 1,
0 => 'Qux',
),
'dn' => 'cn=qux,dc=foo,dc=com',
),
1 => array(
'count' => 3,
0 => 'cn',
'cn' => array(
'count' => 1,
0 => 'baz',
),
1 => 'dc',
'dc' => array(
'count' => 2,
0 => 'com',
1 => 'foo',
),
2 => 'givenname',
'givenname' => array(
'count' => 1,
0 => 'Baz',
),
'dn' => 'cn=baz,dc=foo,dc=com',
),
);
$this->assertEquals($expected, $this->client->find('dc=foo,dc=com', 'bar', 'baz'));
}
/**
* @dataProvider provideConfig
*/
public function testLdapClientConfig($args, $expected)
{
$reflObj = new \ReflectionObject($this->client);
$reflMethod = $reflObj->getMethod('normalizeConfig');
$reflMethod->setAccessible(true);
array_unshift($args, $this->client);
$this->assertEquals($expected, call_user_func_array(array($reflMethod, 'invoke'), $args));
}
/**
* @group functional
* @requires extension ldap
*/
public function testLdapClientFunctional()
{
$config = $this->getLdapConfig();
$ldap = new LdapClient($config['host'], $config['port']);
$ldap->bind('cn=admin,dc=symfony,dc=com', 'symfony');
$result = $ldap->find('dc=symfony,dc=com', '(&(objectclass=person)(ou=Maintainers))');
$con = @ldap_connect($config['host'], $config['port']);
@ldap_bind($con, 'cn=admin,dc=symfony,dc=com', 'symfony');
$search = @ldap_search($con, 'dc=symfony,dc=com', '(&(objectclass=person)(ou=Maintainers))', array('*'));
$expected = @ldap_get_entries($con, $search);
$this->assertSame($expected, $result);
}
public function provideConfig()
{
return array(
array(
array('localhost', 389, 3, true, false, false),
array(
'host' => 'localhost',
'port' => 389,
'encryption' => 'ssl',
'options' => array(
'protocol_version' => 3,
'referrals' => false,
),
),
),
array(
array('localhost', 389, 3, false, true, false),
array(
'host' => 'localhost',
'port' => 389,
'encryption' => 'tls',
'options' => array(
'protocol_version' => 3,
'referrals' => false,
),
),
),
array(
array('localhost', 389, 3, false, false, false),
array(
'host' => 'localhost',
'port' => 389,
'encryption' => 'none',
'options' => array(
'protocol_version' => 3,
'referrals' => false,
),
),
),
array(
array('localhost', 389, 3, false, false, false),
array(
'host' => 'localhost',
'port' => 389,
'encryption' => 'none',
'options' => array(
'protocol_version' => 3,
'referrals' => false,
),
),
),
);
}
}

84
vendor/symfony/ldap/Tests/LdapTest.php vendored Normal file
View File

@@ -0,0 +1,84 @@
<?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 PHPUnit\Framework\TestCase;
use Symfony\Component\Ldap\Adapter\AdapterInterface;
use Symfony\Component\Ldap\Adapter\ConnectionInterface;
use Symfony\Component\Ldap\Exception\DriverNotFoundException;
use Symfony\Component\Ldap\Ldap;
class LdapTest extends TestCase
{
/** @var \PHPUnit_Framework_MockObject_MockObject */
private $adapter;
/** @var Ldap */
private $ldap;
protected function setUp()
{
$this->adapter = $this->getMockBuilder(AdapterInterface::class)->getMock();
$this->ldap = new Ldap($this->adapter);
}
public function testLdapBind()
{
$connection = $this->getMockBuilder(ConnectionInterface::class)->getMock();
$connection
->expects($this->once())
->method('bind')
->with('foo', 'bar')
;
$this->adapter
->expects($this->once())
->method('getConnection')
->will($this->returnValue($connection))
;
$this->ldap->bind('foo', 'bar');
}
public function testLdapEscape()
{
$this->adapter
->expects($this->once())
->method('escape')
->with('foo', 'bar', 'baz')
;
$this->ldap->escape('foo', 'bar', 'baz');
}
public function testLdapQuery()
{
$this->adapter
->expects($this->once())
->method('createQuery')
->with('foo', 'bar', array('baz'))
;
$this->ldap->query('foo', 'bar', array('baz'));
}
/**
* @requires extension ldap
*/
public function testLdapCreate()
{
$ldap = Ldap::create('ext_ldap');
$this->assertInstanceOf(Ldap::class, $ldap);
}
public function testCreateWithInvalidAdapterName()
{
$this->{method_exists($this, $_ = 'expectException') ? $_ : 'setExpectedException'}(DriverNotFoundException::class);
Ldap::create('foo');
}
}

View File

@@ -0,0 +1,16 @@
<?php
namespace Symfony\Component\Ldap\Tests;
use PHPUnit\Framework\TestCase;
class LdapTestCase extends TestCase
{
protected function getLdapConfig()
{
return array(
'host' => getenv('LDAP_HOST'),
'port' => getenv('LDAP_PORT'),
);
}
}

36
vendor/symfony/ldap/composer.json vendored Normal file
View File

@@ -0,0 +1,36 @@
{
"name": "symfony/ldap",
"type": "library",
"description": "An abstraction in front of PHP's LDAP functions, compatible with PHP 5.3.9 onwards.",
"keywords": ["ldap", "active directory"],
"homepage": "https://symfony.com",
"license": "MIT",
"authors": [
{
"name": "Charles Sarrazin",
"email": "charles@sarraz.in"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"require": {
"php": "^5.5.9|>=7.0.8",
"symfony/polyfill-php56": "~1.0",
"symfony/options-resolver": "~2.8|~3.0|~4.0",
"ext-ldap": "*"
},
"autoload": {
"psr-4": { "Symfony\\Component\\Ldap\\": "" },
"exclude-from-classmap": [
"/Tests/"
]
},
"minimum-stability": "dev",
"extra": {
"branch-alias": {
"dev-master": "3.4-dev"
}
}
}

32
vendor/symfony/ldap/phpunit.xml.dist vendored Normal file
View File

@@ -0,0 +1,32 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://schema.phpunit.de/4.1/phpunit.xsd"
backupGlobals="false"
colors="true"
bootstrap="vendor/autoload.php"
failOnRisky="true"
failOnWarning="true"
>
<php>
<ini name="error_reporting" value="-1" />
<env name="LDAP_HOST" value="127.0.0.1" />
<env name="LDAP_PORT" value="3389" />
</php>
<testsuites>
<testsuite name="Symfony Ldap Component Test Suite">
<directory>./Tests/</directory>
</testsuite>
</testsuites>
<filter>
<whitelist>
<directory>./</directory>
<exclude>
<directory>./Tests</directory>
<directory>./vendor</directory>
</exclude>
</whitelist>
</filter>
</phpunit>

View File

@@ -0,0 +1,3 @@
vendor/
composer.lock
phpunit.xml

View File

@@ -0,0 +1,52 @@
CHANGELOG
=========
3.4.0
-----
* added `OptionsResolverIntrospector` to inspect options definitions inside an `OptionsResolver` instance
* added array of types support in allowed types (e.g int[])
2.6.0
-----
* deprecated OptionsResolverInterface
* [BC BREAK] removed "array" type hint from OptionsResolverInterface methods
setRequired(), setAllowedValues(), addAllowedValues(), setAllowedTypes() and
addAllowedTypes()
* added OptionsResolver::setDefault()
* added OptionsResolver::hasDefault()
* added OptionsResolver::setNormalizer()
* added OptionsResolver::isRequired()
* added OptionsResolver::getRequiredOptions()
* added OptionsResolver::isMissing()
* added OptionsResolver::getMissingOptions()
* added OptionsResolver::setDefined()
* added OptionsResolver::isDefined()
* added OptionsResolver::getDefinedOptions()
* added OptionsResolver::remove()
* added OptionsResolver::clear()
* deprecated OptionsResolver::replaceDefaults()
* deprecated OptionsResolver::setOptional() in favor of setDefined()
* deprecated OptionsResolver::isKnown() in favor of isDefined()
* [BC BREAK] OptionsResolver::isRequired() returns true now if a required
option has a default value set
* [BC BREAK] merged Options into OptionsResolver and turned Options into an
interface
* deprecated Options::overload() (now in OptionsResolver)
* deprecated Options::set() (now in OptionsResolver)
* deprecated Options::get() (now in OptionsResolver)
* deprecated Options::has() (now in OptionsResolver)
* deprecated Options::replace() (now in OptionsResolver)
* [BC BREAK] Options::get() (now in OptionsResolver) can only be used within
lazy option/normalizer closures now
* [BC BREAK] removed Traversable interface from Options since using within
lazy option/normalizer closures resulted in exceptions
* [BC BREAK] removed Options::all() since using within lazy option/normalizer
closures resulted in exceptions
* [BC BREAK] OptionDefinitionException now extends LogicException instead of
RuntimeException
* [BC BREAK] normalizers are not executed anymore for unset options
* normalizers are executed after validating the options now
* [BC BREAK] an UndefinedOptionsException is now thrown instead of an
InvalidOptionsException when non-existing options are passed

View File

@@ -0,0 +1,102 @@
<?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\OptionsResolver\Debug;
use Symfony\Component\OptionsResolver\Exception\NoConfigurationException;
use Symfony\Component\OptionsResolver\Exception\UndefinedOptionsException;
use Symfony\Component\OptionsResolver\OptionsResolver;
/**
* @author Maxime Steinhausser <maxime.steinhausser@gmail.com>
*
* @final
*/
class OptionsResolverIntrospector
{
private $get;
public function __construct(OptionsResolver $optionsResolver)
{
$this->get = \Closure::bind(function ($property, $option, $message) {
/** @var OptionsResolver $this */
if (!$this->isDefined($option)) {
throw new UndefinedOptionsException(sprintf('The option "%s" does not exist.', $option));
}
if (!array_key_exists($option, $this->{$property})) {
throw new NoConfigurationException($message);
}
return $this->{$property}[$option];
}, $optionsResolver, $optionsResolver);
}
/**
* @param string $option
*
* @return mixed
*
* @throws NoConfigurationException on no configured value
*/
public function getDefault($option)
{
return call_user_func($this->get, 'defaults', $option, sprintf('No default value was set for the "%s" option.', $option));
}
/**
* @param string $option
*
* @return \Closure[]
*
* @throws NoConfigurationException on no configured closures
*/
public function getLazyClosures($option)
{
return call_user_func($this->get, 'lazy', $option, sprintf('No lazy closures were set for the "%s" option.', $option));
}
/**
* @param string $option
*
* @return string[]
*
* @throws NoConfigurationException on no configured types
*/
public function getAllowedTypes($option)
{
return call_user_func($this->get, 'allowedTypes', $option, sprintf('No allowed types were set for the "%s" option.', $option));
}
/**
* @param string $option
*
* @return mixed[]
*
* @throws NoConfigurationException on no configured values
*/
public function getAllowedValues($option)
{
return call_user_func($this->get, 'allowedValues', $option, sprintf('No allowed values were set for the "%s" option.', $option));
}
/**
* @param string $option
*
* @return \Closure
*
* @throws NoConfigurationException on no configured normalizer
*/
public function getNormalizer($option)
{
return call_user_func($this->get, 'normalizers', $option, sprintf('No normalizer was set for the "%s" option.', $option));
}
}

View File

@@ -0,0 +1,22 @@
<?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\OptionsResolver\Exception;
/**
* Thrown when trying to read an option outside of or write it inside of
* {@link \Symfony\Component\OptionsResolver\Options::resolve()}.
*
* @author Bernhard Schussek <bschussek@gmail.com>
*/
class AccessException extends \LogicException implements ExceptionInterface
{
}

View File

@@ -0,0 +1,21 @@
<?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\OptionsResolver\Exception;
/**
* Marker interface for all exceptions thrown by the OptionsResolver component.
*
* @author Bernhard Schussek <bschussek@gmail.com>
*/
interface ExceptionInterface
{
}

View File

@@ -0,0 +1,21 @@
<?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\OptionsResolver\Exception;
/**
* Thrown when an argument is invalid.
*
* @author Bernhard Schussek <bschussek@gmail.com>
*/
class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface
{
}

View File

@@ -0,0 +1,23 @@
<?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\OptionsResolver\Exception;
/**
* Thrown when the value of an option does not match its validation rules.
*
* You should make sure a valid value is passed to the option.
*
* @author Bernhard Schussek <bschussek@gmail.com>
*/
class InvalidOptionsException extends InvalidArgumentException
{
}

View File

@@ -0,0 +1,23 @@
<?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\OptionsResolver\Exception;
/**
* Exception thrown when a required option is missing.
*
* Add the option to the passed options array.
*
* @author Bernhard Schussek <bschussek@gmail.com>
*/
class MissingOptionsException extends InvalidArgumentException
{
}

View File

@@ -0,0 +1,26 @@
<?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\OptionsResolver\Exception;
use Symfony\Component\OptionsResolver\Debug\OptionsResolverIntrospector;
/**
* Thrown when trying to introspect an option definition property
* for which no value was configured inside the OptionsResolver instance.
*
* @see OptionsResolverIntrospector
*
* @author Maxime Steinhausser <maxime.steinhausser@gmail.com>
*/
class NoConfigurationException extends \RuntimeException implements ExceptionInterface
{
}

View File

@@ -0,0 +1,26 @@
<?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\OptionsResolver\Exception;
/**
* Thrown when trying to read an option that has no value set.
*
* When accessing optional options from within a lazy option or normalizer you should first
* check whether the optional option is set. You can do this with `isset($options['optional'])`.
* In contrast to the {@link UndefinedOptionsException}, this is a runtime exception that can
* occur when evaluating lazy options.
*
* @author Tobias Schultze <http://tobion.de>
*/
class NoSuchOptionException extends \OutOfBoundsException implements ExceptionInterface
{
}

View File

@@ -0,0 +1,21 @@
<?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\OptionsResolver\Exception;
/**
* Thrown when two lazy options have a cyclic dependency.
*
* @author Bernhard Schussek <bschussek@gmail.com>
*/
class OptionDefinitionException extends \LogicException implements ExceptionInterface
{
}

View File

@@ -0,0 +1,24 @@
<?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\OptionsResolver\Exception;
/**
* Exception thrown when an undefined option is passed.
*
* You should remove the options in question from your code or define them
* beforehand.
*
* @author Bernhard Schussek <bschussek@gmail.com>
*/
class UndefinedOptionsException extends InvalidArgumentException
{
}

19
vendor/symfony/options-resolver/LICENSE vendored Normal file
View File

@@ -0,0 +1,19 @@
Copyright (c) 2004-2018 Fabien Potencier
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

View File

@@ -0,0 +1,22 @@
<?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\OptionsResolver;
/**
* Contains resolved option values.
*
* @author Bernhard Schussek <bschussek@gmail.com>
* @author Tobias Schultze <http://tobion.de>
*/
interface Options extends \ArrayAccess, \Countable
{
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,15 @@
OptionsResolver Component
=========================
The OptionsResolver component is `array_replace` on steroids. It allows you to
create an options system with required options, defaults, validation (type,
value), normalization and more.
Resources
---------
* [Documentation](https://symfony.com/doc/current/components/options_resolver.html)
* [Contributing](https://symfony.com/doc/current/contributing/index.html)
* [Report issues](https://github.com/symfony/symfony/issues) and
[send Pull Requests](https://github.com/symfony/symfony/pulls)
in the [main Symfony repository](https://github.com/symfony/symfony)

View File

@@ -0,0 +1,203 @@
<?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\OptionsResolver\Tests\Debug;
use PHPUnit\Framework\TestCase;
use Symfony\Component\OptionsResolver\Debug\OptionsResolverIntrospector;
use Symfony\Component\OptionsResolver\Options;
use Symfony\Component\OptionsResolver\OptionsResolver;
class OptionsResolverIntrospectorTest extends TestCase
{
public function testGetDefault()
{
$resolver = new OptionsResolver();
$resolver->setDefault($option = 'foo', 'bar');
$debug = new OptionsResolverIntrospector($resolver);
$this->assertSame('bar', $debug->getDefault($option));
}
public function testGetDefaultNull()
{
$resolver = new OptionsResolver();
$resolver->setDefault($option = 'foo', null);
$debug = new OptionsResolverIntrospector($resolver);
$this->assertNull($debug->getDefault($option));
}
/**
* @expectedException \Symfony\Component\OptionsResolver\Exception\NoConfigurationException
* @expectedExceptionMessage No default value was set for the "foo" option.
*/
public function testGetDefaultThrowsOnNoConfiguredValue()
{
$resolver = new OptionsResolver();
$resolver->setDefined($option = 'foo');
$debug = new OptionsResolverIntrospector($resolver);
$this->assertSame('bar', $debug->getDefault($option));
}
/**
* @expectedException \Symfony\Component\OptionsResolver\Exception\UndefinedOptionsException
* @expectedExceptionMessage The option "foo" does not exist.
*/
public function testGetDefaultThrowsOnNotDefinedOption()
{
$resolver = new OptionsResolver();
$debug = new OptionsResolverIntrospector($resolver);
$this->assertSame('bar', $debug->getDefault('foo'));
}
public function testGetLazyClosures()
{
$resolver = new OptionsResolver();
$closures = array();
$resolver->setDefault($option = 'foo', $closures[] = function (Options $options) {});
$debug = new OptionsResolverIntrospector($resolver);
$this->assertSame($closures, $debug->getLazyClosures($option));
}
/**
* @expectedException \Symfony\Component\OptionsResolver\Exception\NoConfigurationException
* @expectedExceptionMessage No lazy closures were set for the "foo" option.
*/
public function testGetLazyClosuresThrowsOnNoConfiguredValue()
{
$resolver = new OptionsResolver();
$resolver->setDefined($option = 'foo');
$debug = new OptionsResolverIntrospector($resolver);
$this->assertSame('bar', $debug->getLazyClosures($option));
}
/**
* @expectedException \Symfony\Component\OptionsResolver\Exception\UndefinedOptionsException
* @expectedExceptionMessage The option "foo" does not exist.
*/
public function testGetLazyClosuresThrowsOnNotDefinedOption()
{
$resolver = new OptionsResolver();
$debug = new OptionsResolverIntrospector($resolver);
$this->assertSame('bar', $debug->getLazyClosures('foo'));
}
public function testGetAllowedTypes()
{
$resolver = new OptionsResolver();
$resolver->setDefined($option = 'foo');
$resolver->setAllowedTypes($option = 'foo', $allowedTypes = array('string', 'bool'));
$debug = new OptionsResolverIntrospector($resolver);
$this->assertSame($allowedTypes, $debug->getAllowedTypes($option));
}
/**
* @expectedException \Symfony\Component\OptionsResolver\Exception\NoConfigurationException
* @expectedExceptionMessage No allowed types were set for the "foo" option.
*/
public function testGetAllowedTypesThrowsOnNoConfiguredValue()
{
$resolver = new OptionsResolver();
$resolver->setDefined($option = 'foo');
$debug = new OptionsResolverIntrospector($resolver);
$this->assertSame('bar', $debug->getAllowedTypes($option));
}
/**
* @expectedException \Symfony\Component\OptionsResolver\Exception\UndefinedOptionsException
* @expectedExceptionMessage The option "foo" does not exist.
*/
public function testGetAllowedTypesThrowsOnNotDefinedOption()
{
$resolver = new OptionsResolver();
$debug = new OptionsResolverIntrospector($resolver);
$this->assertSame('bar', $debug->getAllowedTypes('foo'));
}
public function testGetAllowedValues()
{
$resolver = new OptionsResolver();
$resolver->setDefined($option = 'foo');
$resolver->setAllowedValues($option = 'foo', $allowedValues = array('bar', 'baz'));
$debug = new OptionsResolverIntrospector($resolver);
$this->assertSame($allowedValues, $debug->getAllowedValues($option));
}
/**
* @expectedException \Symfony\Component\OptionsResolver\Exception\NoConfigurationException
* @expectedExceptionMessage No allowed values were set for the "foo" option.
*/
public function testGetAllowedValuesThrowsOnNoConfiguredValue()
{
$resolver = new OptionsResolver();
$resolver->setDefined($option = 'foo');
$debug = new OptionsResolverIntrospector($resolver);
$this->assertSame('bar', $debug->getAllowedValues($option));
}
/**
* @expectedException \Symfony\Component\OptionsResolver\Exception\UndefinedOptionsException
* @expectedExceptionMessage The option "foo" does not exist.
*/
public function testGetAllowedValuesThrowsOnNotDefinedOption()
{
$resolver = new OptionsResolver();
$debug = new OptionsResolverIntrospector($resolver);
$this->assertSame('bar', $debug->getAllowedValues('foo'));
}
public function testGetNormalizer()
{
$resolver = new OptionsResolver();
$resolver->setDefined($option = 'foo');
$resolver->setNormalizer($option = 'foo', $normalizer = function () {});
$debug = new OptionsResolverIntrospector($resolver);
$this->assertSame($normalizer, $debug->getNormalizer($option));
}
/**
* @expectedException \Symfony\Component\OptionsResolver\Exception\NoConfigurationException
* @expectedExceptionMessage No normalizer was set for the "foo" option.
*/
public function testGetNormalizerThrowsOnNoConfiguredValue()
{
$resolver = new OptionsResolver();
$resolver->setDefined($option = 'foo');
$debug = new OptionsResolverIntrospector($resolver);
$this->assertSame('bar', $debug->getNormalizer($option));
}
/**
* @expectedException \Symfony\Component\OptionsResolver\Exception\UndefinedOptionsException
* @expectedExceptionMessage The option "foo" does not exist.
*/
public function testGetNormalizerThrowsOnNotDefinedOption()
{
$resolver = new OptionsResolver();
$debug = new OptionsResolverIntrospector($resolver);
$this->assertSame('bar', $debug->getNormalizer('foo'));
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,33 @@
{
"name": "symfony/options-resolver",
"type": "library",
"description": "Symfony OptionsResolver Component",
"keywords": ["options", "config", "configuration"],
"homepage": "https://symfony.com",
"license": "MIT",
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"require": {
"php": "^5.5.9|>=7.0.8"
},
"autoload": {
"psr-4": { "Symfony\\Component\\OptionsResolver\\": "" },
"exclude-from-classmap": [
"/Tests/"
]
},
"minimum-stability": "dev",
"extra": {
"branch-alias": {
"dev-master": "3.4-dev"
}
}
}

View File

@@ -0,0 +1,31 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://schema.phpunit.de/4.1/phpunit.xsd"
backupGlobals="false"
colors="true"
bootstrap="vendor/autoload.php"
failOnRisky="true"
failOnWarning="true"
>
<php>
<ini name="error_reporting" value="-1" />
</php>
<testsuites>
<testsuite name="Symfony OptionsResolver Component Test Suite">
<directory>./Tests/</directory>
</testsuite>
</testsuites>
<filter>
<whitelist>
<directory>./</directory>
<exclude>
<directory>./Resources</directory>
<directory>./Tests</directory>
<directory>./vendor</directory>
</exclude>
</whitelist>
</filter>
</phpunit>

19
vendor/symfony/polyfill-php56/LICENSE vendored Normal file
View File

@@ -0,0 +1,19 @@
Copyright (c) 2015-2018 Fabien Potencier
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

138
vendor/symfony/polyfill-php56/Php56.php vendored Normal file
View File

@@ -0,0 +1,138 @@
<?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\Polyfill\Php56;
use Symfony\Polyfill\Util\Binary;
/**
* @internal
*/
final class Php56
{
const LDAP_ESCAPE_FILTER = 1;
const LDAP_ESCAPE_DN = 2;
public static function hash_equals($knownString, $userInput)
{
if (!\is_string($knownString)) {
trigger_error('Expected known_string to be a string, '.gettype($knownString).' given', E_USER_WARNING);
return false;
}
if (!\is_string($userInput)) {
trigger_error('Expected user_input to be a string, '.gettype($userInput).' given', E_USER_WARNING);
return false;
}
$knownLen = Binary::strlen($knownString);
$userLen = Binary::strlen($userInput);
if ($knownLen !== $userLen) {
return false;
}
$result = 0;
for ($i = 0; $i < $knownLen; ++$i) {
$result |= \ord($knownString[$i]) ^ \ord($userInput[$i]);
}
return 0 === $result;
}
/**
* Stub implementation of the {@link ldap_escape()} function of the ldap
* extension.
*
* Escape strings for safe use in LDAP filters and DNs.
*
* @author Chris Wright <ldapi@daverandom.com>
*
* @param string $subject
* @param string $ignore
* @param int $flags
*
* @return string
*
* @see http://stackoverflow.com/a/8561604
*/
public static function ldap_escape($subject, $ignore = '', $flags = 0)
{
static $charMaps = null;
if (null === $charMaps) {
$charMaps = array(
self::LDAP_ESCAPE_FILTER => array('\\', '*', '(', ')', "\x00"),
self::LDAP_ESCAPE_DN => array('\\', ',', '=', '+', '<', '>', ';', '"', '#', "\r"),
);
$charMaps[0] = array();
for ($i = 0; $i < 256; ++$i) {
$charMaps[0][\chr($i)] = sprintf('\\%02x', $i);
}
for ($i = 0, $l = \count($charMaps[self::LDAP_ESCAPE_FILTER]); $i < $l; ++$i) {
$chr = $charMaps[self::LDAP_ESCAPE_FILTER][$i];
unset($charMaps[self::LDAP_ESCAPE_FILTER][$i]);
$charMaps[self::LDAP_ESCAPE_FILTER][$chr] = $charMaps[0][$chr];
}
for ($i = 0, $l = \count($charMaps[self::LDAP_ESCAPE_DN]); $i < $l; ++$i) {
$chr = $charMaps[self::LDAP_ESCAPE_DN][$i];
unset($charMaps[self::LDAP_ESCAPE_DN][$i]);
$charMaps[self::LDAP_ESCAPE_DN][$chr] = $charMaps[0][$chr];
}
}
// Create the base char map to escape
$flags = (int) $flags;
$charMap = array();
if ($flags & self::LDAP_ESCAPE_FILTER) {
$charMap += $charMaps[self::LDAP_ESCAPE_FILTER];
}
if ($flags & self::LDAP_ESCAPE_DN) {
$charMap += $charMaps[self::LDAP_ESCAPE_DN];
}
if (!$charMap) {
$charMap = $charMaps[0];
}
// Remove any chars to ignore from the list
$ignore = (string) $ignore;
for ($i = 0, $l = \strlen($ignore); $i < $l; ++$i) {
unset($charMap[$ignore[$i]]);
}
// Do the main replacement
$result = strtr($subject, $charMap);
// Encode leading/trailing spaces if self::LDAP_ESCAPE_DN is passed
if ($flags & self::LDAP_ESCAPE_DN) {
if ($result[0] === ' ') {
$result = '\\20'.substr($result, 1);
}
if ($result[\strlen($result) - 1] === ' ') {
$result = substr($result, 0, -1).'\\20';
}
}
return $result;
}
}

15
vendor/symfony/polyfill-php56/README.md vendored Normal file
View File

@@ -0,0 +1,15 @@
Symfony Polyfill / Php56
========================
This component provides functions unavailable in releases prior to PHP 5.6:
- [`hash_equals`](http://php.net/hash_equals) (part of [hash](http://php.net/hash) extension)
- [`ldap_escape`](http://php.net/ldap_escape) (part of [ldap](http://php.net/ldap) extension)
More information can be found in the
[main Polyfill README](https://github.com/symfony/polyfill/blob/master/README.md).
License
=======
This library is released under the [MIT license](LICENSE).

View File

@@ -0,0 +1,38 @@
<?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.
*/
use Symfony\Polyfill\Php56 as p;
if (PHP_VERSION_ID < 50600) {
if (!function_exists('hash_equals')) {
function hash_equals($knownString, $userInput) { return p\Php56::hash_equals($knownString, $userInput); }
}
if (extension_loaded('ldap') && !function_exists('ldap_escape')) {
define('LDAP_ESCAPE_FILTER', 1);
define('LDAP_ESCAPE_DN', 2);
function ldap_escape($subject, $ignore = '', $flags = 0) { return p\Php56::ldap_escape($subject, $ignore, $flags); }
}
if (50509 === PHP_VERSION_ID && 4 === PHP_INT_SIZE) {
// Missing functions in PHP 5.5.9 - affects 32 bit builds of Ubuntu 14.04LTS
// See https://bugs.launchpad.net/ubuntu/+source/php5/+bug/1315888
if (!function_exists('gzopen') && function_exists('gzopen64')) {
function gzopen($filename, $mode, $use_include_path = 0) { return gzopen64($filename, $mode, $use_include_path); }
}
if (!function_exists('gzseek') && function_exists('gzseek64')) {
function gzseek($zp, $offset, $whence = SEEK_SET) { return gzseek64($zp, $offset, $whence); }
}
if (!function_exists('gztell') && function_exists('gztell64')) {
function gztell($zp) { return gztell64($zp); }
}
}
}

View File

@@ -0,0 +1,32 @@
{
"name": "symfony/polyfill-php56",
"type": "library",
"description": "Symfony polyfill backporting some PHP 5.6+ features to lower PHP versions",
"keywords": ["polyfill", "shim", "compatibility", "portable"],
"homepage": "https://symfony.com",
"license": "MIT",
"authors": [
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"require": {
"php": ">=5.3.3",
"symfony/polyfill-util": "~1.0"
},
"autoload": {
"psr-4": { "Symfony\\Polyfill\\Php56\\": "" },
"files": [ "bootstrap.php" ]
},
"minimum-stability": "dev",
"extra": {
"branch-alias": {
"dev-master": "1.8-dev"
}
}
}

18
vendor/symfony/polyfill-util/Binary.php vendored Normal file
View File

@@ -0,0 +1,18 @@
<?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\Polyfill\Util;
if (extension_loaded('mbstring')) {
class Binary extends BinaryOnFuncOverload {}
} else {
class Binary extends BinaryNoFuncOverload {}
}

View File

@@ -0,0 +1,65 @@
<?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\Polyfill\Util;
/**
* @author Nicolas Grekas <p@tchwork.com>
*
* @internal
*/
class BinaryNoFuncOverload
{
public static function strlen($s)
{
return \strlen($s);
}
public static function strpos($haystack, $needle, $offset = 0)
{
return strpos($haystack, $needle, $offset);
}
public static function strrpos($haystack, $needle, $offset = 0)
{
return strrpos($haystack, $needle, $offset);
}
public static function substr($string, $start, $length = PHP_INT_MAX)
{
return substr($string, $start, $length);
}
public static function stripos($s, $needle, $offset = 0)
{
return stripos($s, $needle, $offset);
}
public static function stristr($s, $needle, $part = false)
{
return stristr($s, $needle, $part);
}
public static function strrchr($s, $needle, $part = false)
{
return strrchr($s, $needle, $part);
}
public static function strripos($s, $needle, $offset = 0)
{
return strripos($s, $needle, $offset);
}
public static function strstr($s, $needle, $part = false)
{
return strstr($s, $needle, $part);
}
}

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\Polyfill\Util;
/**
* Binary safe version of string functions overloaded when MB_OVERLOAD_STRING is enabled.
*
* @author Nicolas Grekas <p@tchwork.com>
*
* @internal
*/
class BinaryOnFuncOverload
{
public static function strlen($s)
{
return mb_strlen($s, '8bit');
}
public static function strpos($haystack, $needle, $offset = 0)
{
return mb_strpos($haystack, $needle, $offset, '8bit');
}
public static function strrpos($haystack, $needle, $offset = 0)
{
return mb_strrpos($haystack, $needle, $offset, '8bit');
}
public static function substr($string, $start, $length = 2147483647)
{
return mb_substr($string, $start, $length, '8bit');
}
public static function stripos($s, $needle, $offset = 0)
{
return mb_stripos($s, $needle, $offset, '8bit');
}
public static function stristr($s, $needle, $part = false)
{
return mb_stristr($s, $needle, $part, '8bit');
}
public static function strrchr($s, $needle, $part = false)
{
return mb_strrchr($s, $needle, $part, '8bit');
}
public static function strripos($s, $needle, $offset = 0)
{
return mb_strripos($s, $needle, $offset, '8bit');
}
public static function strstr($s, $needle, $part = false)
{
return mb_strstr($s, $needle, $part, '8bit');
}
}

19
vendor/symfony/polyfill-util/LICENSE vendored Normal file
View File

@@ -0,0 +1,19 @@
Copyright (c) 2015-2018 Fabien Potencier
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

View File

@@ -0,0 +1,84 @@
<?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\Polyfill\Util;
/**
* @author Nicolas Grekas <p@tchwork.com>
*/
class LegacyTestListener extends \PHPUnit_Framework_TestSuite implements \PHPUnit_Framework_TestListener
{
private $suite;
private $trait;
public function __construct(\PHPUnit_Framework_TestSuite $suite = null)
{
if ($suite) {
$this->suite = $suite;
$this->setName($suite->getName().' with polyfills enabled');
$this->addTest($suite);
}
$this->trait = new TestListenerTrait();
}
public function startTestSuite(\PHPUnit_Framework_TestSuite $suite)
{
$this->trait->startTestSuite($suite);
}
protected function setUp()
{
TestListenerTrait::$enabledPolyfills = $this->suite->getName();
}
protected function tearDown()
{
TestListenerTrait::$enabledPolyfills = false;
}
public function addError(\PHPUnit_Framework_Test $test, \Exception $e, $time)
{
$this->trait->addError($test, $e, $time);
}
public function addWarning(\PHPUnit_Framework_Test $test, \PHPUnit_Framework_Warning $e, $time)
{
}
public function addFailure(\PHPUnit_Framework_Test $test, \PHPUnit_Framework_AssertionFailedError $e, $time)
{
$this->trait->addError($test, $e, $time);
}
public function addIncompleteTest(\PHPUnit_Framework_Test $test, \Exception $e, $time)
{
}
public function addRiskyTest(\PHPUnit_Framework_Test $test, \Exception $e, $time)
{
}
public function addSkippedTest(\PHPUnit_Framework_Test $test, \Exception $e, $time)
{
}
public function endTestSuite(\PHPUnit_Framework_TestSuite $suite)
{
}
public function startTest(\PHPUnit_Framework_Test $test)
{
}
public function endTest(\PHPUnit_Framework_Test $test, $time)
{
}
}

13
vendor/symfony/polyfill-util/README.md vendored Normal file
View File

@@ -0,0 +1,13 @@
Symfony Polyfill / Util
=======================
This component provides binary-safe string functions, using the
[mbstring](https://php.net/mbstring) extension when available.
More information can be found in the
[main Polyfill README](https://github.com/symfony/polyfill/blob/master/README.md).
License
=======
This library is released under the [MIT license](LICENSE).

View File

@@ -0,0 +1,96 @@
<?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\Polyfill\Util;
use PHPUnit\Framework\AssertionFailedError;
use PHPUnit\Framework\TestListener as TestListenerInterface;
use PHPUnit\Framework\Test;
use PHPUnit\Framework\TestSuite;
use PHPUnit\Framework\Warning;
if (class_exists('PHPUnit_Runner_Version') && version_compare(\PHPUnit_Runner_Version::id(), '6.0.0', '<')) {
class_alias('Symfony\Polyfill\Util\LegacyTestListener', 'Symfony\Polyfill\Util\TestListener');
// Using an early return instead of a else does not work when using the PHPUnit phar due to some weird PHP behavior (the class
// gets defined without executing the code before it and so the definition is not properly conditional)
} else {
/**
* @author Nicolas Grekas <p@tchwork.com>
*/
class TestListener extends TestSuite implements TestListenerInterface
{
private $suite;
private $trait;
public function __construct(TestSuite $suite = null)
{
if ($suite) {
$this->suite = $suite;
$this->setName($suite->getName().' with polyfills enabled');
$this->addTest($suite);
}
$this->trait = new TestListenerTrait();
}
public function startTestSuite(TestSuite $suite)
{
$this->trait->startTestSuite($suite);
}
protected function setUp()
{
TestListenerTrait::$enabledPolyfills = $this->suite->getName();
}
protected function tearDown()
{
TestListenerTrait::$enabledPolyfills = false;
}
public function addError(Test $test, \Exception $e, $time)
{
$this->trait->addError($test, $e, $time);
}
public function addWarning(Test $test, Warning $e, $time)
{
}
public function addFailure(Test $test, AssertionFailedError $e, $time)
{
$this->trait->addError($test, $e, $time);
}
public function addIncompleteTest(Test $test, \Exception $e, $time)
{
}
public function addRiskyTest(Test $test, \Exception $e, $time)
{
}
public function addSkippedTest(Test $test, \Exception $e, $time)
{
}
public function endTestSuite(TestSuite $suite)
{
}
public function startTest(Test $test)
{
}
public function endTest(Test $test, $time)
{
}
}
}

View File

@@ -0,0 +1,107 @@
<?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\Polyfill\Util;
/**
* @author Nicolas Grekas <p@tchwork.com>
*/
class TestListenerTrait
{
public static $enabledPolyfills;
public function startTestSuite($mainSuite)
{
if (null !== self::$enabledPolyfills) {
return;
}
self::$enabledPolyfills = false;
$SkippedTestError = class_exists('PHPUnit\Framework\SkippedTestError') ? 'PHPUnit\Framework\SkippedTestError' : 'PHPUnit_Framework_SkippedTestError';
$TestListener = class_exists('Symfony\Polyfill\Util\TestListener', false) ? 'Symfony\Polyfill\Util\TestListener' : 'Symfony\Polyfill\Util\LegacyTestListener';
foreach ($mainSuite->tests() as $suite) {
$testClass = $suite->getName();
if (!$tests = $suite->tests()) {
continue;
}
if (!preg_match('/^(.+)\\\\Tests(\\\\.*)Test$/', $testClass, $m)) {
$mainSuite->addTest($TestListener::warning('Unknown naming convention for '.$testClass));
continue;
}
if (!class_exists($m[1].$m[2])) {
continue;
}
$testedClass = new \ReflectionClass($m[1].$m[2]);
$bootstrap = new \SplFileObject(dirname($testedClass->getFileName()).'/bootstrap.php');
$warnings = array();
$defLine = null;
foreach (new \RegexIterator($bootstrap, '/return p\\\\'.$testedClass->getShortName().'::/') as $defLine) {
if (!preg_match('/^\s*function (?P<name>[^\(]++)(?P<signature>\([^\)]*+\)) \{ (?<return>return p\\\\'.$testedClass->getShortName().'::[^\(]++)(?P<args>\([^\)]*+\)); \}$/', $defLine, $f)) {
$warnings[] = $TestListener::warning('Invalid line in bootstrap.php: '.trim($defLine));
continue;
}
$testNamespace = substr($testClass, 0, strrpos($testClass, '\\'));
if (function_exists($testNamespace.'\\'.$f['name'])) {
continue;
}
try {
$r = new \ReflectionFunction($f['name']);
if ($r->isUserDefined()) {
throw new \ReflectionException();
}
if (false !== strpos($f['signature'], '&')) {
$defLine = sprintf('return \\%s%s', $f['name'], $f['args']);
} else {
$defLine = sprintf("return \\call_user_func_array('%s', func_get_args())", $f['name']);
}
} catch (\ReflectionException $e) {
$defLine = sprintf("throw new \\{$SkippedTestError}('Internal function not found: %s')", $f['name']);
}
eval(<<<EOPHP
namespace {$testNamespace};
use Symfony\Polyfill\Util\TestListenerTrait;
use {$testedClass->getNamespaceName()} as p;
function {$f['name']}{$f['signature']}
{
if ('{$testClass}' === TestListenerTrait::\$enabledPolyfills) {
{$f['return']}{$f['args']};
}
{$defLine};
}
EOPHP
);
}
if (!$warnings && null === $defLine) {
$warnings[] = new $SkippedTestError('No Polyfills found in bootstrap.php for '.$testClass);
} else {
$mainSuite->addTest(new $TestListener($suite));
}
}
foreach ($warnings as $w) {
$mainSuite->addTest($w);
}
}
public function addError($test, \Exception $e, $time)
{
if (false !== self::$enabledPolyfills) {
$r = new \ReflectionProperty('Exception', 'message');
$r->setAccessible(true);
$r->setValue($e, 'Polyfills enabled, '.$r->getValue($e));
}
}
}

View File

@@ -0,0 +1,30 @@
{
"name": "symfony/polyfill-util",
"type": "library",
"description": "Symfony utilities for portability of PHP codes",
"keywords": ["polyfill", "shim", "compat", "compatibility"],
"homepage": "https://symfony.com",
"license": "MIT",
"authors": [
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"require": {
"php": ">=5.3.3"
},
"autoload": {
"psr-4": { "Symfony\\Polyfill\\Util\\": "" }
},
"minimum-stability": "dev",
"extra": {
"branch-alias": {
"dev-master": "1.8-dev"
}
}
}