Update Composer, update everything

This commit is contained in:
Oliver Davies 2018-11-23 12:29:20 +00:00
parent ea3e94409f
commit dda5c284b6
19527 changed files with 1135420 additions and 351004 deletions

View file

@ -0,0 +1,2 @@
composer.lock
vendor

View file

@ -0,0 +1,12 @@
language: php
php:
- 5.3.3
- 5.3
- 5.4
before_script:
- wget -nc http://getcomposer.org/composer.phar
- php composer.phar install --dev
script: phpunit --coverage-text --verbose

View file

@ -0,0 +1,19 @@
Copyright (c) 2012 Dragonfly Development Inc.
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,111 @@
# Dot Access Configuration
Given a deep data structure representing a configuration, access
configuration by dot notation.
This library combines [dflydev/dot-access-data](https://github.com/dflydev/dflydev-dot-access-data)
and [dflydev/placeholder-resolver](https://github.com/dflydev/dflydev-placeholder-resolver)
to provide a complete configuration solution.
## Requirements
* PHP (5.3+)
* [dflydev/dot-access-data](https://github.com/dflydev/dflydev-dot-access-data) (1.*)
* [dflydev/placeholder-resolver](https://github.com/dflydev/dflydev-placeholder-resolver) (1.*)
* [symfony/yaml](https://github.com/symfony/Yaml) (>2,<2.2) *(suggested)*
## Usage
Generally one will use an implementation of `ConfigurationBuilderInterface`
to build `ConfigurationInterface` instances. For example, to build a Configuration
out of a YAML file, one would use the `YamlFileConfigurationBuilder`:
```php
use Dflydev\DotAccessConfiguration\YamlFileConfigurationBuilder;
$configurationBuilder = new YamlFileConfigurationBuilder('config/config.yml');
$configuration = $configurationBuilder->build();
```
Once created, the Configuration instance behaves similarly to a Data
instance from [dflydev/dot-access-data](https://github.com/dflydev/dflydev-dot-access-data).
```php
$configuration->set('a.b.c', 'ABC');
$configuration->get('a.b.c');
$configuration->set('a.b.e', array('A', 'B', 'C'));
$configuration->append('a.b.e', 'D');
```
## Custom Configurations
Configuration Builders use Configuration Factories and Placeholder Resolver
Factories behind the scenes in order to build a working configuration.
Under normal circumstances one should not need to do anything with the
Placeholder Resolver Factory. However, one may wish to extend the
default `Configuration` class or use an entirely different implementation
altogether.
In order to build instances of custom `ConfigurationInterface` implementations
with the standard builders, one would need to implement
`ConfigurationFactoryInterface` and inject it into any
`ConfigurationBuilderInterface`.
If a Configuration is declared as follows:
```php
namespace MyProject;
use Dflydev\DotAccessConfiguration\Configuration;
class MyConf extends Configuration
{
public function someSpecialMethod()
{
// Whatever you want here.
}
}
```
Create the following factory:
```php
namespace MyProject;
use Dflydev\DotAccessConfiguration\ConfigurationFactoryInterface;
class MyConfFactory implements ConfigurationFactoryInterface
{
/**
* {@inheritdocs}
*/
public function create()
{
return new MyConf;
}
}
```
To use the factory with any builder, inject it as follows:
```php
use Dflydev\DotAccessConfiguration\YamlFileConfigurationBuilder;
use MyProject\MyConfFactory;
$configurationBuilder = new YamlFileConfigurationBuilder('config/config.yml');
// Inject your custom Configuration Factory
$configurationBuilder->setConfigurationFactory(new MyConfFactory);
// Will now build instances of MyConfFactory instead of
// the standard Configuration implementation.
$configuration = $configurationBuilder->build();
```
## License
This library is licensed under the New BSD License - see the LICENSE file
for details.
## Community
If you have questions or want to help out, join us in the
[#dflydev](irc://irc.freenode.net/#dflydev) channel on irc.freenode.net.

View file

@ -0,0 +1,41 @@
{
"name": "dflydev/dot-access-configuration",
"type": "library",
"description": "Given a deep data structure representing a configuration, access configuration by dot notation.",
"homepage": "https://github.com/dflydev/dflydev-dot-access-configuration",
"keywords": ["config", "configuration"],
"license": "MIT",
"authors": [
{
"name": "Dragonfly Development Inc.",
"email": "info@dflydev.com",
"homepage": "http://dflydev.com"
},
{
"name": "Beau Simensen",
"email": "beau@dflydev.com",
"homepage": "http://beausimensen.com"
}
],
"require": {
"php": ">=5.3.2",
"dflydev/dot-access-data": "1.*",
"dflydev/placeholder-resolver": "1.*"
},
"require-dev": {
"symfony/yaml": "~2.1"
},
"suggest": {
"symfony/yaml": "Required for using the YAML Configuration Builders"
},
"autoload": {
"psr-0": {
"Dflydev\\DotAccessConfiguration": "src"
}
},
"extra": {
"branch-alias": {
"dev-master": "1.0-dev"
}
}
}

View file

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit colors="true" bootstrap="tests/bootstrap.php">
<testsuites>
<testsuite name="Dot Access Configuration Test Suite">
<directory>./tests/Dflydev/DotAccessConfiguration</directory>
</testsuite>
</testsuites>
<filter>
<whitelist>
<directory>./src/Dflydev/DotAccessConfiguration/</directory>
</whitelist>
</filter>
</phpunit>

View file

@ -0,0 +1,188 @@
<?php
/*
* This file is a part of dflydev/dot-access-configuration.
*
* (c) Dragonfly Development Inc.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Dflydev\DotAccessConfiguration;
use Dflydev\DotAccessData\Data;
use Dflydev\PlaceholderResolver\PlaceholderResolverInterface;
use Dflydev\PlaceholderResolver\RegexPlaceholderResolver;
abstract class AbstractConfiguration implements ConfigurationInterface
{
private $placeholderResolver;
private $data;
private $exportIsDirty = true;
private $resolvedExport;
/**
* {@inheritdocs}
*/
public function getRaw($key)
{
return $this->data()->get($key);
}
/**
* {@inheritdocs}
*/
public function get($key)
{
$value = $this->getRaw($key);
if (is_object($value)) {
return $value;
}
$this->resolveValues($value);
return $value;
}
/**
* {@inheritdocs}
*/
public function set($key, $value = null)
{
$this->exportIsDirty = true;
return $this->data()->set($key, $value);
}
/**
* {@inheritdocs}
*/
public function append($key, $value = null)
{
$this->exportIsDirty = true;
return $this->data()->append($key, $value);
}
/**
* {@inheritdocs}
*/
public function exportRaw()
{
return $this->data()->export();
}
/**
* {@inheritdocs}
*/
public function export()
{
if ($this->exportIsDirty) {
$this->resolvedExport = $this->data()->export();
$this->resolveValues($this->resolvedExport);
$this->exportIsDirty = false;
}
return $this->resolvedExport;
}
/**
* {@inheritdocs}
*/
public function exportData()
{
return new Data($this->export());
}
/**
* {@inheritdocs}
*/
public function importRaw($imported = null, $clobber = true)
{
$this->exportIsDirty = true;
if (null !== $imported) {
$this->data()->import($imported, $clobber);
}
}
/**
* {@inheritdocs}
*/
public function import(ConfigurationInterface $imported, $clobber = true)
{
return $this->importRaw($imported->exportRaw(), $clobber);
}
/**
* {@inheritdocs}
*/
public function resolve($value = null)
{
if (null === $value) {
return null;
}
return $this->placeholderResolver()->resolvePlaceholder($value);
}
/**
* {@inheritdocs}
*/
public function setPlaceholderResolver(PlaceholderResolverInterface $placeholderResolver)
{
$this->placeholderResolver = $placeholderResolver;
return $this;
}
/**
* Resolve values
*
* For objects, do nothing. For strings, resolve placeholder.
* For arrays, call resolveValues() on each item.
*
* @param mixed $input
*/
protected function resolveValues(&$input = null)
{
if (is_array($input)) {
foreach ($input as $idx => $value) {
$this->resolveValues($value);
$input[$idx] = $value;
}
} else {
if (!is_object($input)) {
$input = $this->placeholderResolver()->resolvePlaceholder($input);
}
}
}
/**
* Data
*
* @return Data
*/
protected function data()
{
if (null === $this->data) {
$this->data = new Data;
}
return $this->data;
}
/**
* Placeholder Resolver
*
* @return PlaceholderResolverInterface
*/
protected function placeholderResolver()
{
if (null === $this->placeholderResolver) {
$this->placeholderResolver = new RegexPlaceholderResolver(new ConfigurationDataSource($this), '%', '%');
}
return $this->placeholderResolver;
}
}

View file

@ -0,0 +1,94 @@
<?php
/*
* This file is a part of dflydev/dot-access-configuration.
*
* (c) Dragonfly Development Inc.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Dflydev\DotAccessConfiguration;
abstract class AbstractConfigurationBuilder implements ConfigurationBuilderInterface
{
private $configurationFactory;
private $placeholderResolverFactory;
/**
* Set Configuration Factory
*
* @param ConfigurationFactoryInterface $configurationFactory
*
* @return AbstractConfigurationBuilder
*/
public function setConfigurationFactory(ConfigurationFactoryInterface $configurationFactory)
{
$this->configurationFactory = $configurationFactory;
return $this;
}
/**
* Configuration Factory
*
* @return ConfigurationFactoryInterface
*/
protected function configurationFactory()
{
if (null === $this->configurationFactory) {
$this->configurationFactory = new ConfigurationFactory;
}
return $this->configurationFactory;
}
/**
* {@inheritdocs}
*/
public function build()
{
$configuration = $this->configurationFactory()->create();
if (null !== $this->placeholderResolverFactory) {
$placeholderResolver = $this->placeholderResolverFactory->create($configuration);
$configuration->setPlaceholderResolver($placeholderResolver);
}
$this->internalBuild($configuration);
return $configuration;
}
/**
* Set Placeholder Resolver Factory
*
* @param PlaceholderResolverFactoryInterface $placeholderResolverFactory
*/
public function setPlaceholderResolverFactory(PlaceholderResolverFactoryInterface $placeholderResolverFactory)
{
$this->placeholderResolverFactory = $placeholderResolverFactory;
}
/**
* Called to reconfigure the specified Configuration Builder to be similar to this instance
*
* @param AbstractConfigurationBuilder $configurationBuilder
*/
public function reconfigure(AbstractConfigurationBuilder $configurationBuilder)
{
if (null !== $this->placeholderResolverFactory) {
$configurationBuilder->setPlaceholderResolverFactory($this->placeholderResolverFactory);
}
$configurationBuilder->setConfigurationFactory($this->configurationFactory());
}
/**
* Internal build
*
* @param ConfigurationInterface $configuration
*/
abstract protected function internalBuild(ConfigurationInterface $configuration);
}

View file

@ -0,0 +1,35 @@
<?php
/*
* This file is a part of dflydev/dot-access-configuration.
*
* (c) Dragonfly Development Inc.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Dflydev\DotAccessConfiguration;
use Dflydev\PlaceholderResolver\DataSource\DataSourceInterface;
abstract class AbstractPlaceholderResolverFactory implements PlaceholderResolverFactoryInterface
{
/**
* {@inheritdocs}
*/
public function create(ConfigurationInterface $configuration)
{
return $this->createInternal($configuration, new ConfigurationDataSource($configuration));
}
/**
* Internal create
*
* @param ConfigurationInterface $configuration
* @param DataSourceInterface $dataSource
*
* @return PlaceholderResolverInterface
*/
abstract protected function createInternal(ConfigurationInterface $configuration, DataSourceInterface $dataSource);
}

View file

@ -0,0 +1,25 @@
<?php
/*
* This file is a part of dflydev/dot-access-configuration.
*
* (c) Dragonfly Development Inc.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Dflydev\DotAccessConfiguration;
class Configuration extends AbstractConfiguration
{
/**
* Constructor
*
* @param array|null $config
*/
public function __construct(array $config = null)
{
$this->importRaw($config);
}
}

View file

@ -0,0 +1,22 @@
<?php
/*
* This file is a part of dflydev/dot-access-configuration.
*
* (c) Dragonfly Development Inc.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Dflydev\DotAccessConfiguration;
interface ConfigurationBuilderInterface
{
/**
* Build a Configuration
*
* @return ConfigurationInterface
*/
public function build();
}

View file

@ -0,0 +1,67 @@
<?php
/*
* This file is a part of dflydev/dot-access-configuration.
*
* (c) Dragonfly Development Inc.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Dflydev\DotAccessConfiguration;
use Dflydev\PlaceholderResolver\DataSource\DataSourceInterface;
class ConfigurationDataSource implements DataSourceInterface
{
private $configuration;
/**
* Constructor
*
* @param ConfigurationInterface $configuration
*/
public function __construct(ConfigurationInterface $configuration)
{
$this->setConfiguration($configuration);
}
/**
* {@inheritdoc}
*/
public function exists($key, $system = false)
{
if ($system) {
return false;
}
return null !== $this->configuration->getRaw($key);
}
/**
* {@inheritdoc}
*/
public function get($key, $system = false)
{
if ($system) {
return null;
}
return $this->configuration->getRaw($key);
}
/**
* Set Configuration
*
* @param ConfigurationInterface $configuration
*
* @return ConfigurationDataSource
*/
public function setConfiguration(ConfigurationInterface $configuration)
{
$this->configuration = $configuration;
return $this;
}
}

View file

@ -0,0 +1,23 @@
<?php
/*
* This file is a part of dflydev/dot-access-configuration.
*
* (c) Dragonfly Development Inc.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Dflydev\DotAccessConfiguration;
class ConfigurationFactory implements ConfigurationFactoryInterface
{
/**
* {@inheritdocs}
*/
public function create()
{
return new Configuration;
}
}

View file

@ -0,0 +1,22 @@
<?php
/*
* This file is a part of dflydev/dot-access-configuration.
*
* (c) Dragonfly Development Inc.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Dflydev\DotAccessConfiguration;
interface ConfigurationFactoryInterface
{
/**
* Create a Configuration
*
* @return ConfigurationInterface
*/
public function create();
}

View file

@ -0,0 +1,111 @@
<?php
/*
* This file is a part of dflydev/dot-access-configuration.
*
* (c) Dragonfly Development Inc.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Dflydev\DotAccessConfiguration;
use Dflydev\DotAccessData\Data;
use Dflydev\PlaceholderResolver\PlaceholderResolverInterface;
interface ConfigurationInterface
{
/**
* Get a value (with placeholders unresolved)
*
* @param string $key
*
* @return mixed
*/
public function getRaw($key);
/**
* Get a value (with placeholders resolved)
*
* @param string $key
*
* @return mixed
*/
public function get($key);
/**
* Set a value
*
* @param string $key
* @param mixed $value
*/
public function set($key, $value = null);
/**
* Append a value
*
* Will force key to be an array if it is only a string
*
* @param string $key
* @param mixed $value
*/
public function append($key, $value = null);
/**
* Export configuration data as an associtaive array (with placeholders unresolved)
*
* @return array
*/
public function exportRaw();
/**
* Export configuration data as an associtaive array (with placeholders resolved)
*
* @return array
*/
public function export();
/**
* Underlying Data representation
*
* Will have all placeholders resolved.
*
* @return Data
*/
public function exportData();
/**
* Import another Configuration
*
* @param array $imported
* @param bool $clobber
*/
public function importRaw($imported, $clobber = true);
/**
* Import another Configuration
*
* @param ConfigurationInterface $imported
* @param bool $clobber
*/
public function import(ConfigurationInterface $imported, $clobber = true);
/**
* Resolve placeholders in value from configuration
*
* @param string|null $value
*
* @return string
*/
public function resolve($value = null);
/**
* Set Placeholder Resolver
*
* @param PlaceholderResolver $placeholderResolver
*
* @return ConfigurationInterface
*/
public function setPlaceholderResolver(PlaceholderResolverInterface $placeholderResolver);
}

View file

@ -0,0 +1,26 @@
<?php
/*
* This file is a part of dflydev/dot-access-configuration.
*
* (c) Dragonfly Development Inc.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Dflydev\DotAccessConfiguration;
use Dflydev\PlaceholderResolver\DataSource\DataSourceInterface;
use Dflydev\PlaceholderResolver\RegexPlaceholderResolver;
class PlaceholderResolverFactory extends AbstractPlaceholderResolverFactory
{
/**
* {@inheritdocs}
*/
protected function createInternal(ConfigurationInterface $configuration, DataSourceInterface $dataSource)
{
return new RegexPlaceholderResolver($dataSource, '%', '%');
}
}

View file

@ -0,0 +1,26 @@
<?php
/*
* This file is a part of dflydev/dot-access-configuration.
*
* (c) Dragonfly Development Inc.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Dflydev\DotAccessConfiguration;
use Dflydev\PlaceholderResolver\PlaceholderResolverInterface;
interface PlaceholderResolverFactoryInterface
{
/**
* Configuration
*
* @param ConfigurationInterface $configuration
*
* @return PlaceholderResolverInterface
*/
public function create(ConfigurationInterface $configuration);
}

View file

@ -0,0 +1,54 @@
<?php
/*
* This file is a part of dflydev/dot-access-configuration.
*
* (c) Dragonfly Development Inc.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Dflydev\DotAccessConfiguration;
use Psr\Log\InvalidArgumentException;
use Symfony\Component\Yaml\Yaml;
class YamlConfigurationBuilder extends AbstractConfigurationBuilder
{
/**
* YAML input string
*
* @var string
*/
protected $input;
/**
* Constructor
*
* @param string|null $input
*/
public function __construct($input = null)
{
$this->input = $input;
}
/**
* {@inheritdocs}
*/
public function internalBuild(ConfigurationInterface $configuration)
{
if (null !== $this->input) {
try{
$yml = Yaml::parse($this->input, Yaml::PARSE_EXCEPTION_ON_INVALID_TYPE);
} catch (\Exception $e) {
throw new InvalidArgumentException($e->getMessage(), 0, $e);
}
if (is_string($yml))
{
throw(new \InvalidArgumentException('Yaml could not be parsed, parser detected a string.'));
}
$configuration->importRaw($yml);
}
}
}

View file

@ -0,0 +1,85 @@
<?php
/*
* This file is a part of dflydev/dot-access-configuration.
*
* (c) Dragonfly Development Inc.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Dflydev\DotAccessConfiguration;
use Dflydev\DotAccessData\Util as DotAccessDataUtil;
use Symfony\Component\Yaml\Yaml;
class YamlFileConfigurationBuilder extends AbstractConfigurationBuilder
{
/**
* YAML Configuration Filenames
*
* @var array
*/
private $yamlConfigurationFilenames;
/**
* Constructor
*
* @param array $yamlConfigurationFilenames
*/
public function __construct(array $yamlConfigurationFilenames)
{
$this->yamlConfigurationFilenames = $yamlConfigurationFilenames;
}
/**
* {@inheritdocs}
*/
public function internalBuild(ConfigurationInterface $configuration)
{
$config = array();
$imports = array();
foreach ($this->yamlConfigurationFilenames as $yamlConfigurationFilename) {
if (file_exists($yamlConfigurationFilename)) {
$config = DotAccessDataUtil::mergeAssocArray($config, Yaml::parse(file_get_contents($yamlConfigurationFilename)));
if (isset($config['imports'])) {
foreach ((array) $config['imports'] as $file) {
if (0 === strpos($file, '/')) {
// Absolute path
$imports[] = $file;
} else {
if ($realpath = realpath(dirname($yamlConfigurationFilename).'/'.$file)) {
$imports[] = $realpath;
}
}
}
}
}
}
if ($imports) {
$importsBuilder = new static($imports);
// We want to reconfigure the imports builder to have the
// same basic configuration as this instance.
$this->reconfigure($importsBuilder);
$configuration->import($importsBuilder->build());
$internalImports = $configuration->get('imports');
} else {
$internalImports = null;
}
$configuration->importRaw($config);
if ($internalImports) {
foreach ((array) $internalImports as $import) {
$configuration->append('imports', $import);
}
}
return $configuration;
}
}

View file

@ -0,0 +1,89 @@
<?php
/*
* This file is a part of dflydev/dot-access-configuration.
*
* (c) Dragonfly Development Inc.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Dflydev\DotAccessConfiguration;
class AbstractConfigurationBuilderTest extends \PHPUnit_Framework_TestCase
{
public function testPlaceholderResolver()
{
$placeholderResolver = $this->getMock('Dflydev\PlaceholderResolver\PlaceholderResolverInterface');
$placeholderResolverFactory = $this->getMock('Dflydev\DotAccessConfiguration\PlaceholderResolverFactoryInterface');
$placeholderResolverFactory
->expects($this->once())
->method('create')
->will($this->returnValue($placeholderResolver))
;
$configurationBuilder = $this->getMockForAbstractClass('Dflydev\DotAccessConfiguration\AbstractConfigurationBuilder');
$configurationBuilder
->expects($this->once())
->method('internalBuild')
;
$configurationBuilder->setPlaceholderResolverFactory($placeholderResolverFactory);
$configurationBuilder->build();
}
public function testReconfigure()
{
$configuration000 = $this->getMock('Dflydev\DotAccessConfiguration\ConfigurationInterface');
$configuration000
->expects($this->exactly(2))
->method('get')
->with($this->equalTo('foo'))
->will($this->returnValue('FOO'))
;
$configuration001 = $this->getMock('Dflydev\DotAccessConfiguration\ConfigurationInterface');
$configuration001
->expects($this->exactly(2))
->method('get')
->with($this->equalTo('bar'))
->will($this->returnValue('BAR'))
;
$placeholderResolver = $this->getMock('Dflydev\PlaceholderResolver\PlaceholderResolverInterface');
$placeholderResolverFactory = $this->getMock('Dflydev\DotAccessConfiguration\PlaceholderResolverFactoryInterface');
$placeholderResolverFactory
->expects($this->exactly(2))
->method('create')
->will($this->returnValue($placeholderResolver))
;
$configurationFactory = $this->getMock('Dflydev\DotAccessConfiguration\ConfigurationFactoryInterface');
$configurationFactory
->expects($this->exactly(2))
->method('create')
->will($this->onConsecutiveCalls($configuration000, $configuration001));
;
$configurationBuilder = $this->getMockForAbstractClass('Dflydev\DotAccessConfiguration\AbstractConfigurationBuilder');
$configurationBuilder->setPlaceholderResolverFactory($placeholderResolverFactory);
$configurationBuilder->setConfigurationFactory($configurationFactory);
$reconfiguredConfigurationBuilder = $this->getMockForAbstractClass('Dflydev\DotAccessConfiguration\AbstractConfigurationBuilder');
$configurationBuilder->reconfigure($reconfiguredConfigurationBuilder);
$configurationTest000 = $configurationBuilder->build();
$configurationTest001 = $reconfiguredConfigurationBuilder->build();
$this->assertEquals('FOO', $configuration000->get('foo'));
$this->assertEquals('FOO', $configurationTest000->get('foo'));
$this->assertEquals('BAR', $configuration001->get('bar'));
$this->assertEquals('BAR', $configurationTest001->get('bar'));
}
}

View file

@ -0,0 +1,39 @@
<?php
/*
* This file is a part of dflydev/dot-access-configuration.
*
* (c) Dragonfly Development Inc.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Dflydev\DotAccessConfiguration;
class ConfigurationDataSourceTest extends \PHPUnit_Framework_TestCase
{
public function test()
{
$configuration = $this->getMock('Dflydev\DotAccessConfiguration\Configuration');
$configuration
->expects($this->any())
->method('getRaw')
->will($this->returnValueMap(array(
array('foo', 'bar'),
array('foo', null, true),
array('foo', 'bar', false),
)))
;
$dataSource = new ConfigurationDataSource($configuration);
$this->assertEquals('bar', $dataSource->get('foo'));
$this->assertTrue($dataSource->exists('foo'));
$this->assertEquals('bar', $dataSource->get('foo', false));
$this->assertTrue($dataSource->exists('foo', false));
$this->assertNull($dataSource->get('foo', true));
$this->assertFalse($dataSource->exists('foo', true));
}
}

View file

@ -0,0 +1,21 @@
<?php
/*
* This file is a part of dflydev/dot-access-configuration.
*
* (c) Dragonfly Development Inc.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Dflydev\DotAccessConfiguration;
class ConfigurationFactoryTest extends \PHPUnit_Framework_TestCase
{
public function testCreate()
{
$configurationFactory = new ConfigurationFactory;
$configuration = $configurationFactory->create();
}
}

View file

@ -0,0 +1,175 @@
<?php
/*
* This file is a part of dflydev/dot-access-configuration.
*
* (c) Dragonfly Development Inc.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Dflydev\DotAccessConfiguration;
class ConfigurationTest extends \PHPUnit_Framework_TestCase
{
protected function getTestData()
{
return array(
'a' => array(
'b' => array(
'c' => 'ABC',
),
),
'abc' => '%a.b.c%',
'abcd' => '%a.b.c.d%',
'some' => array(
'object' => new ConfigurationTestObject('some.object'),
'other' => array(
'object' => new ConfigurationTestObject('some.other.object'),
),
),
'object' => new ConfigurationTestObject('object'),
'an_array' => array('hello'),
);
}
protected function runBasicTests($configuration)
{
$this->assertEquals('ABC', $configuration->get('a.b.c'), 'Direct access by dot notation');
$this->assertEquals('ABC', $configuration->get('abc'), 'Resolved access');
$this->assertEquals('%a.b.c.d%', $configuration->get('abcd'), 'Unresolved access');
$this->assertEquals('object', $configuration->get('object')->key);
$this->assertEquals('some.object', $configuration->get('some.object')->key);
$this->assertEquals('some.other.object', $configuration->get('some.other.object')->key);
$this->assertEquals(array('hello'), $configuration->get('an_array'));
$this->assertEquals('This is ABC', $configuration->resolve('This is %a.b.c%'));
$this->assertNull($configuration->resolve());
}
public function testGet()
{
$configuration = new Configuration($this->getTestData());
$this->runBasicTests($configuration);
}
public function testAppend()
{
$configuration = new Configuration($this->getTestData());
$configuration->append('a.b.c', 'abc');
$configuration->append('an_array', 'world');
$this->assertEquals(array('ABC', 'abc'), $configuration->get('a.b.c'));
$this->assertEquals(array('hello', 'world'), $configuration->get('an_array'));
}
public function testExportRaw()
{
$configuration = new Configuration($this->getTestData());
// Start with "known" expected value.
$expected = $this->getTestData();
$this->assertEquals($expected, $configuration->exportRaw());
// Simulate change on an object to ensure that objects
// are being handled correctly.
$expected['object']->key = 'object (modified)';
// Make the same change in the object that the
// configuration is managing.
$configuration->get('object')->key = 'object (modified)';
$this->assertEquals($expected, $configuration->exportRaw());
}
public function testExport()
{
$configuration = new Configuration($this->getTestData());
// Start with "known" expected value.
$expected = $this->getTestData();
// We have one replacement that is expected to happen.
// It should be represented in the export as the
// resolved value!
$expected['abc'] = 'ABC';
$this->assertEquals($expected, $configuration->export());
// Simulate change on an object to ensure that objects
// are being handled correctly.
$expected['object']->key = 'object (modified)';
// Make the same change in the object that the
// configuration is managing.
$configuration->get('object')->key = 'object (modified)';
$this->assertEquals($expected, $configuration->export());
// Test to make sure that set will result in setting
// a new value and also that export will show this new
// value. (tests "export is dirty" functionality)
$configuration->set('abc', 'ABCD');
$expected['abc'] = 'ABCD';
$this->assertEquals($expected, $configuration->export());
}
public function testExportData()
{
$configuration = new Configuration($this->getTestData());
$data = $configuration->exportData();
// The exportData call should return data filled with
// resolved data.
$this->assertEquals('ABC', $data->get('abc'));
}
public function testImportRaw()
{
$configuration = new Configuration();
$configuration->importRaw($this->getTestData());
$this->runBasicTests($configuration);
}
public function testImport()
{
$configuration = new Configuration();
$configuration->import(new Configuration($this->getTestData()));
$this->runBasicTests($configuration);
}
public function testSetPlaceholderResolver()
{
$placeholderResolver = $this->getMock('Dflydev\PlaceholderResolver\PlaceholderResolverInterface');
$placeholderResolver
->expects($this->once())
->method('resolvePlaceholder')
->with($this->equalTo('foo'))
->will($this->returnValue('bar'))
;
$configuration = new Configuration;
$configuration->setPlaceholderResolver($placeholderResolver);
$this->assertEquals('bar', $configuration->resolve('foo'));
}
}
class ConfigurationTestObject
{
public $key;
public function __construct($key)
{
$this->key = $key;
}
}

View file

@ -0,0 +1,22 @@
<?php
/*
* This file is a part of dflydev/dot-access-configuration.
*
* (c) Dragonfly Development Inc.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Dflydev\DotAccessConfiguration;
class PlaceholderResolverFactoryTest extends \PHPUnit_Framework_TestCase
{
public function testCreate()
{
$configuration = $this->getMock('Dflydev\DotAccessConfiguration\Configuration');
$placeholderResolverFactory = new PlaceholderResolverFactory;
$placeholderResolver = $placeholderResolverFactory->create($configuration);
}
}

View file

@ -0,0 +1,34 @@
<?php
/*
* This file is a part of dflydev/dot-access-configuration.
*
* (c) Dragonfly Development Inc.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Dflydev\DotAccessConfiguration;
class YamlConfigurationBuilderTest extends \PHPUnit_Framework_TestCase
{
public function setUp()
{
if (!class_exists('Symfony\Component\Yaml\Yaml')) {
$this->markTestSkipped('The Symfony2 YAML library is not available');
}
}
public function testBuild()
{
$configurationBuilder = new YamlConfigurationBuilder;
$configuration = $configurationBuilder->build();
}
public function testBuildWithData()
{
$configurationBuilder = new YamlConfigurationBuilder('foo: bar');
$configuration = $configurationBuilder->build();
}
}

View file

@ -0,0 +1,38 @@
<?php
/*
* This file is a part of dflydev/dot-access-configuration.
*
* (c) Dragonfly Development Inc.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Dflydev\DotAccessConfiguration;
class YamlFileConfigurationBuilderTest extends \PHPUnit_Framework_TestCase
{
public function setUp()
{
if (!class_exists('Symfony\Component\Yaml\Yaml')) {
$this->markTestSkipped('The Symfony2 YAML library is not available');
}
}
public function testBuilder()
{
$configurationBuilder = new YamlFileConfigurationBuilder(array(__DIR__.'/fixtures/yamlFileConfigurationBuilderTest-testBuilder.yml'));
$configuration = $configurationBuilder->build();
$this->assertEquals('C', $configuration->get('a.b.c'));
$this->assertEquals('C0', $configuration->get('a0.b0.c0'));
$this->assertEquals('C1', $configuration->get('a1.b1.c1'));
$this->assertEquals(array(
'yamlFileConfigurationBuilderTest-testBuilder-import-level0.yml',
'/tmp/testing-this-file-should-not-exist.yml',
'yamlFileConfigurationBuilderTest-testBuilder-import-level1.yml',
), $configuration->get('imports'));
}
}

View file

@ -0,0 +1,6 @@
imports:
- yamlFileConfigurationBuilderTest-testBuilder-import-level1.yml
a0:
b0:
c0: C0

View file

@ -0,0 +1,7 @@
imports:
- yamlFileConfigurationBuilderTest-testBuilder-import-level0.yml
- /tmp/testing-this-file-should-not-exist.yml
a:
b:
c: C

View file

@ -0,0 +1,13 @@
<?php
/*
* This file is a part of dflydev/dot-access-configuration.
*
* (c) Dragonfly Development Inc.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
$loader = require dirname(__DIR__).'/vendor/autoload.php';

View file

@ -0,0 +1,2 @@
composer.lock
vendor

View file

@ -0,0 +1,13 @@
language: php
php:
- 5.3
- 5.4
- 5.5
- 5.6
before_script:
- wget -nc http://getcomposer.org/composer.phar
- php composer.phar install --dev
script: phpunit --coverage-text

19
vendor/dflydev/dot-access-data/LICENSE vendored Normal file
View file

@ -0,0 +1,19 @@
Copyright (c) 2012 Dragonfly Development Inc.
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.

118
vendor/dflydev/dot-access-data/README.md vendored Normal file
View file

@ -0,0 +1,118 @@
Dot Access Data
===============
Given a deep data structure, access data by dot notation.
Requirements
------------
* PHP (5.3+)
Usage
-----
Abstract example:
```php
use Dflydev\DotAccessData\Data;
$data = new Data;
$data->set('a.b.c', 'C');
$data->set('a.b.d', 'D1');
$data->append('a.b.d', 'D2');
$data->set('a.b.e', array('E0', 'E1', 'E2'));
// C
$data->get('a.b.c');
// array('D1', 'D2')
$data->get('a.b.d');
// array('E0', 'E1', 'E2')
$data->get('a.b.e');
// true
$data->has('a.b.c');
// false
$data->has('a.b.d.j');
```
A more concrete example:
```php
use Dflydev\DotAccessData\Data;
$data = new Data(array(
'hosts' => array(
'hewey' => array(
'username' => 'hman',
'password' => 'HPASS',
'roles' => array('web'),
),
'dewey' => array(
'username' => 'dman',
'password' => 'D---S',
'roles' => array('web', 'db'),
'nick' => 'dewey dman'
),
'lewey' => array(
'username' => 'lman',
'password' => 'LP@$$',
'roles' => array('db'),
),
)
));
// hman
$username = $data->get('hosts.hewey.username');
// HPASS
$password = $data->get('hosts.hewey.password');
// array('web')
$roles = $data->get('hosts.hewey.roles');
// dewey dman
$nick = $data->get('hosts.dewey.nick');
// Unknown
$nick = $data->get('hosts.lewey.nick', 'Unknown');
// DataInterface instance
$dewey = $data->getData('hosts.dewey');
// dman
$username = $dewey->get('username');
// D---S
$password = $dewey->get('password');
// array('web', 'db')
$roles = $dewey->get('roles');
// No more lewey
$data->remove('hosts.lewey');
// Add DB to hewey's roles
$data->append('hosts.hewey.roles', 'db');
$data->set('hosts.april', array(
'username' => 'aman',
'password' => '@---S',
'roles' => array('web'),
));
// Check if a key exists (true to this case)
$hasKey = $data->has('hosts.dewey.username');
```
License
-------
This library is licensed under the New BSD License - see the LICENSE file
for details.
Community
---------
If you have questions or want to help out, join us in the
[#dflydev](irc://irc.freenode.net/#dflydev) channel on irc.freenode.net.

View file

@ -0,0 +1,38 @@
{
"name": "dflydev/dot-access-data",
"type": "library",
"description": "Given a deep data structure, access data by dot notation.",
"homepage": "https://github.com/dflydev/dflydev-dot-access-data",
"keywords": ["dot", "access", "data", "notation"],
"license": "MIT",
"authors": [
{
"name": "Dragonfly Development Inc.",
"email": "info@dflydev.com",
"homepage": "http://dflydev.com"
},
{
"name": "Beau Simensen",
"email": "beau@dflydev.com",
"homepage": "http://beausimensen.com"
},
{
"name": "Carlos Frutos",
"email": "carlos@kiwing.it",
"homepage": "https://github.com/cfrutos"
}
],
"require": {
"php": ">=5.3.2"
},
"autoload": {
"psr-0": {
"Dflydev\\DotAccessData": "src"
}
},
"extra": {
"branch-alias": {
"dev-master": "1.0-dev"
}
}
}

View file

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit colors="true" bootstrap="tests/bootstrap.php">
<testsuites>
<testsuite name="Dot Access Data Test Suite">
<directory>./tests/Dflydev/DotAccessData</directory>
</testsuite>
</testsuites>
<filter>
<whitelist>
<directory>./src/Dflydev/DotAccessData/</directory>
</whitelist>
</filter>
</phpunit>

View file

@ -0,0 +1,220 @@
<?php
/*
* This file is a part of dflydev/dot-access-data.
*
* (c) Dragonfly Development Inc.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Dflydev\DotAccessData;
class Data implements DataInterface
{
/**
* Internal representation of data data
*
* @var array
*/
protected $data;
/**
* Constructor
*
* @param array|null $data
*/
public function __construct(array $data = null)
{
$this->data = $data ?: array();
}
/**
* {@inheritdoc}
*/
public function append($key, $value = null)
{
if (0 == strlen($key)) {
throw new \RuntimeException("Key cannot be an empty string");
}
$currentValue =& $this->data;
$keyPath = explode('.', $key);
if (1 == count($keyPath)) {
if (!isset($currentValue[$key])) {
$currentValue[$key] = array();
}
if (!is_array($currentValue[$key])) {
// Promote this key to an array.
// TODO: Is this really what we want to do?
$currentValue[$key] = array($currentValue[$key]);
}
$currentValue[$key][] = $value;
return;
}
$endKey = array_pop($keyPath);
for ( $i = 0; $i < count($keyPath); $i++ ) {
$currentKey =& $keyPath[$i];
if ( ! isset($currentValue[$currentKey]) ) {
$currentValue[$currentKey] = array();
}
$currentValue =& $currentValue[$currentKey];
}
if (!isset($currentValue[$endKey])) {
$currentValue[$endKey] = array();
}
if (!is_array($currentValue[$endKey])) {
$currentValue[$endKey] = array($currentValue[$endKey]);
}
// Promote this key to an array.
// TODO: Is this really what we want to do?
$currentValue[$endKey][] = $value;
}
/**
* {@inheritdoc}
*/
public function set($key, $value = null)
{
if (0 == strlen($key)) {
throw new \RuntimeException("Key cannot be an empty string");
}
$currentValue =& $this->data;
$keyPath = explode('.', $key);
if (1 == count($keyPath)) {
$currentValue[$key] = $value;
return;
}
$endKey = array_pop($keyPath);
for ( $i = 0; $i < count($keyPath); $i++ ) {
$currentKey =& $keyPath[$i];
if (!isset($currentValue[$currentKey])) {
$currentValue[$currentKey] = array();
}
if (!is_array($currentValue[$currentKey])) {
throw new \RuntimeException("Key path at $currentKey of $key cannot be indexed into (is not an array)");
}
$currentValue =& $currentValue[$currentKey];
}
$currentValue[$endKey] = $value;
}
/**
* {@inheritdoc}
*/
public function remove($key)
{
if (0 == strlen($key)) {
throw new \RuntimeException("Key cannot be an empty string");
}
$currentValue =& $this->data;
$keyPath = explode('.', $key);
if (1 == count($keyPath)) {
unset($currentValue[$key]);
return;
}
$endKey = array_pop($keyPath);
for ( $i = 0; $i < count($keyPath); $i++ ) {
$currentKey =& $keyPath[$i];
if (!isset($currentValue[$currentKey])) {
return;
}
$currentValue =& $currentValue[$currentKey];
}
unset($currentValue[$endKey]);
}
/**
* {@inheritdoc}
*/
public function get($key, $default = null)
{
$currentValue = $this->data;
$keyPath = explode('.', $key);
for ( $i = 0; $i < count($keyPath); $i++ ) {
$currentKey = $keyPath[$i];
if (!isset($currentValue[$currentKey]) ) {
return $default;
}
if (!is_array($currentValue)) {
return $default;
}
$currentValue = $currentValue[$currentKey];
}
return $currentValue === null ? $default : $currentValue;
}
/**
* {@inheritdoc}
*/
public function has($key)
{
$currentValue = &$this->data;
$keyPath = explode('.', $key);
for ( $i = 0; $i < count($keyPath); $i++ ) {
$currentKey = $keyPath[$i];
if (
!is_array($currentValue) ||
!array_key_exists($currentKey, $currentValue)
) {
return false;
}
$currentValue = &$currentValue[$currentKey];
}
return true;
}
/**
* {@inheritdoc}
*/
public function getData($key)
{
$value = $this->get($key);
if (is_array($value) && Util::isAssoc($value)) {
return new Data($value);
}
throw new \RuntimeException("Value at '$key' could not be represented as a DataInterface");
}
/**
* {@inheritdoc}
*/
public function import(array $data, $clobber = true)
{
$this->data = Util::mergeAssocArray($this->data, $data, $clobber);
}
/**
* {@inheritdoc}
*/
public function importData(DataInterface $data, $clobber = true)
{
$this->import($data->export(), $clobber);
}
/**
* {@inheritdoc}
*/
public function export()
{
return $this->data;
}
}

View file

@ -0,0 +1,89 @@
<?php
/*
* This file is a part of dflydev/dot-access-data.
*
* (c) Dragonfly Development Inc.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Dflydev\DotAccessData;
interface DataInterface
{
/**
* Append a value to a key (assumes key refers to an array value)
*
* @param string $key
* @param mixed $value
*/
public function append($key, $value = null);
/**
* Set a value for a key
*
* @param string $key
* @param mixed $value
*/
public function set($key, $value = null);
/**
* Remove a key
*
* @param string $key
*/
public function remove($key);
/**
* Get the raw value for a key
*
* @param string $key
* @param mixed $default
*
* @return mixed
*/
public function get($key, $default = null);
/**
* Check if the key exists
*
* @param string $key
*
* @return bool
*/
public function has($key);
/**
* Get a data instance for a key
*
* @param string $key
*
* @return DataInterface
*/
public function getData($key);
/**
* Import data into existing data
*
* @param array $data
* @param bool $clobber
*/
public function import(array $data, $clobber = true);
/**
* Import data from an external data into existing data
*
* @param DataInterface $data
* @param bool $clobber
*/
public function importData(DataInterface $data, $clobber = true);
/**
* Export data as raw data
*
* @return array
*/
public function export();
}

View file

@ -0,0 +1,54 @@
<?php
/*
* This file is a part of dflydev/dot-access-data.
*
* (c) Dragonfly Development Inc.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Dflydev\DotAccessData;
class Util
{
/**
* Test if array is an associative array
*
* Note that this function will return true if an array is empty. Meaning
* empty arrays will be treated as if they are associative arrays.
*
* @param array $arr
*
* @return boolean
*/
public static function isAssoc(array $arr)
{
return (is_array($arr) && (!count($arr) || count(array_filter(array_keys($arr),'is_string')) == count($arr)));
}
/**
* Merge contents from one associtative array to another
*
* @param array $to
* @param array $from
* @param bool $clobber
*/
public static function mergeAssocArray($to, $from, $clobber = true)
{
if ( is_array($from) ) {
foreach ($from as $k => $v) {
if (!isset($to[$k])) {
$to[$k] = $v;
} else {
$to[$k] = self::mergeAssocArray($to[$k], $v, $clobber);
}
}
return $to;
}
return $clobber ? $from : $to;
}
}

View file

@ -0,0 +1,205 @@
<?php
/*
* This file is a part of dflydev/dot-access-data.
*
* (c) Dragonfly Development Inc.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Dflydev\DotAccessData;
class DataTest extends \PHPUnit_Framework_TestCase
{
protected function getSampleData()
{
return array(
'a' => 'A',
'b' => array(
'b' => 'B',
'c' => array('C1', 'C2', 'C3'),
'd' => array(
'd1' => 'D1',
'd2' => 'D2',
'd3' => 'D3',
),
),
'c' => array('c1', 'c2', 'c3'),
'f' => array(
'g' => array(
'h' => 'FGH',
),
),
'h' => array(
'i' => 'I',
),
'i' => array(
'j' => 'J',
),
);
}
protected function runSampleDataTests(DataInterface $data)
{
$this->assertEquals('A', $data->get('a'));
$this->assertEquals('B', $data->get('b.b'));
$this->assertEquals(array('C1', 'C2', 'C3'), $data->get('b.c'));
$this->assertEquals('D3', $data->get('b.d.d3'));
$this->assertEquals(array('c1', 'c2', 'c3'), $data->get('c'));
$this->assertNull($data->get('foo'), 'Foo should not exist');
$this->assertNull($data->get('f.g.h.i'));
$this->assertEquals($data->get('foo', 'default-value-1'), 'default-value-1', 'Return default value');
$this->assertEquals($data->get('f.g.h.i', 'default-value-2'), 'default-value-2');
}
public function testAppend()
{
$data = new Data($this->getSampleData());
$data->append('a', 'B');
$data->append('c', 'c4');
$data->append('b.c', 'C4');
$data->append('b.d.d3', 'D3b');
$data->append('b.d.d4', 'D');
$data->append('e', 'E');
$data->append('f.a', 'b');
$data->append('h.i', 'I2');
$data->append('i.k.l', 'L');
$this->assertEquals(array('A', 'B'), $data->get('a'));
$this->assertEquals(array('c1', 'c2', 'c3', 'c4'), $data->get('c'));
$this->assertEquals(array('C1', 'C2', 'C3', 'C4'), $data->get('b.c'));
$this->assertEquals(array('D3', 'D3b'), $data->get('b.d.d3'));
$this->assertEquals(array('D'), $data->get('b.d.d4'));
$this->assertEquals(array('E'), $data->get('e'));
$this->assertEquals(array('b'), $data->get('f.a'));
$this->assertEquals(array('I', 'I2'), $data->get('h.i'));
$this->assertEquals(array('L'), $data->get('i.k.l'));
$this->setExpectedException('RuntimeException');
$data->append('', 'broken');
}
public function testSet()
{
$data = new Data;
$this->assertNull($data->get('a'));
$this->assertNull($data->get('b.c'));
$this->assertNull($data->get('d.e'));
$data->set('a', 'A');
$data->set('b.c', 'C');
$data->set('d.e', array('f' => 'F', 'g' => 'G',));
$this->assertEquals('A', $data->get('a'));
$this->assertEquals(array('c' => 'C'), $data->get('b'));
$this->assertEquals('C', $data->get('b.c'));
$this->assertEquals('F', $data->get('d.e.f'));
$this->assertEquals(array('e' => array('f' => 'F', 'g' => 'G',)), $data->get('d'));
$this->setExpectedException('RuntimeException');
$data->set('', 'broken');
}
public function testSetClobberStringInPath()
{
$data = new Data;
$data->set('a.b.c', 'Should not be able to write to a.b.c.d.e');
$this->setExpectedException('RuntimeException');
$data->set('a.b.c.d.e', 'broken');
}
public function testRemove()
{
$data = new Data($this->getSampleData());
$data->remove('a');
$data->remove('b.c');
$data->remove('b.d.d3');
$data->remove('d');
$data->remove('d.e.f');
$data->remove('empty.path');
$this->assertNull($data->get('a'));
$this->assertNull($data->get('b.c'));
$this->assertNull($data->get('b.d.d3'));
$this->assertNull(null);
$this->assertEquals('D2', $data->get('b.d.d2'));
$this->setExpectedException('RuntimeException');
$data->remove('', 'broken');
}
public function testGet()
{
$data = new Data($this->getSampleData());
$this->runSampleDataTests($data);
}
public function testHas()
{
$data = new Data($this->getSampleData());
foreach (
array('a', 'i', 'b.d', 'f.g.h', 'h.i', 'b.d.d1') as $existentKey
) {
$this->assertTrue($data->has($existentKey));
}
foreach (
array('p', 'b.b1', 'b.c.C1', 'h.i.I', 'b.d.d1.D1') as $notExistentKey
) {
$this->assertFalse($data->has($notExistentKey));
}
}
public function testGetData()
{
$wrappedData = new Data(array(
'wrapped' => array(
'sampleData' => $this->getSampleData()
),
));
$data = $wrappedData->getData('wrapped.sampleData');
$this->runSampleDataTests($data);
$this->setExpectedException('RuntimeException');
$data = $wrappedData->getData('wrapped.sampleData.a');
}
public function testImport()
{
$data = new Data();
$data->import($this->getSampleData());
$this->runSampleDataTests($data);
}
public function testImportData()
{
$data = new Data();
$data->importData(new Data($this->getSampleData()));
$this->runSampleDataTests($data);
}
public function testExport()
{
$data = new Data($this->getSampleData());
$this->assertEquals($this->getSampleData(), $data->export());
}
}

View file

@ -0,0 +1,121 @@
<?php
/*
* This file is a part of dflydev/dot-access-data.
*
* (c) Dragonfly Development Inc.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Dflydev\DotAccessData;
class UtilTest extends \PHPUnit_Framework_TestCase
{
public function testIsAssoc()
{
$this->assertTrue(Util::isAssoc(array('a' => 'A',)));
$this->assertTrue(Util::isAssoc(array()));
$this->assertFalse(Util::isAssoc(array(1 => 'One',)));
}
/**
* @dataProvider mergeAssocArrayProvider
*/
public function testMergeAssocArray($message, $to, $from, $clobber, $expectedResult)
{
$result = Util::mergeAssocArray($to, $from, $clobber);
$this->assertEquals($expectedResult, $result, $message);
}
public function mergeAssocArrayProvider()
{
return array(
array(
'Clobber should replace to value with from value for strings (shallow)',
// to
array('a' => 'A'),
// from
array('a' => 'B'),
// clobber
true,
// expected result
array('a' => 'B'),
),
array(
'Clobber should replace to value with from value for strings (deep)',
// to
array('a' => array('b' => 'B',),),
// from
array('a' => array('b' => 'C',),),
// clobber
true,
// expected result
array('a' => array('b' => 'C',),),
),
array(
'Clobber should NOTreplace to value with from value for strings (shallow)',
// to
array('a' => 'A'),
// from
array('a' => 'B'),
// clobber
false,
// expected result
array('a' => 'A'),
),
array(
'Clobber should NOT replace to value with from value for strings (deep)',
// to
array('a' => array('b' => 'B',),),
// from
array('a' => array('b' => 'C',),),
// clobber
false,
// expected result
array('a' => array('b' => 'B',),),
),
array(
'Associative arrays should be combined',
// to
array('a' => array('b' => 'B',),),
// from
array('a' => array('c' => 'C',),),
// clobber
null,
// expected result
array('a' => array('b' => 'B', 'c' => 'C',),),
),
array(
'Arrays should be replaced (with clobber enabled)',
// to
array('a' => array('b', 'c',)),
// from
array('a' => array('B', 'C',),),
// clobber
true,
// expected result
array('a' => array('B', 'C',),),
),
array(
'Arrays should be NOT replaced (with clobber disabled)',
// to
array('a' => array('b', 'c',)),
// from
array('a' => array('B', 'C',),),
// clobber
false,
// expected result
array('a' => array('b', 'c',),),
),
);
}
}

View file

@ -0,0 +1,13 @@
<?php
/*
* This file is a part of dflydev/dot-access-data.
*
* (c) Dragonfly Development Inc.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
$loader = require dirname(__DIR__).'/vendor/autoload.php';

View file

@ -0,0 +1,2 @@
composer.lock
vendor

View file

@ -0,0 +1,12 @@
language: php
php:
- 5.3.3
- 5.3
- 5.4
before_script:
- wget -nc http://getcomposer.org/composer.phar
- php composer.phar install --dev
script: phpunit --coverage-text --verbose

View file

@ -0,0 +1,19 @@
Copyright (c) 2012 Dragonfly Development Inc.
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,101 @@
Placeholder Resolver
====================
Given a data source representing key => value pairs, resolve placeholders
like `${foo.bar}` to the value associated with the `foo.bar` key in
the data source.
Placeholder Resolver is intended to be used at a relatively low level.
For example, a configuration library could use Placeholder Resolver
behind the scenes to allow for configuration values to reference
other configuration values.
Example
-------
conn.driver: mysql
conn.db_name: example
conn.hostname: 127.0.0.1
conn.username: root
conn.password: pa$$word
Given the appropriate `DataSourceInterface` implementation to provide
the above data as a set of key => value pairs, the Placeholder Resolver
would resolve the value of `$dsnPattern` to `mysql:dbname=example;host=127.0.0.1`.
$dsnPattern = '${conn.driver}:dbname=${conn.db_name};host=${conn.hostname}';
$dsn = $placeholderResolver->resolveValue($dsnPattern);
// mysql:dbname=example;host=127.0.0.1
Requirements
------------
* PHP 5.3+
Usage
-----
use Dflydev\PlaceholderResolver\RegexPlaceholderResolver;
// YourDataSource implements Dflydev\PlaceholderResolver\DataSource\DataSourceInterface
$dataSource = new YourDataSource;
// Create the placeholder resolver
$placeholderResolver = new RegexPlaceholderResolver($dataSource);
// Start resolving placeholders
$value = $placeholderResolver->resolvePlaceholder('${foo}');
The `RegexPlaceholderResolver` constructor accepts two additional arguments,
a placeholder prefix and a placeholder suffix. The default placeholder
prefix is `${` and the default placeholder suffix is `}`.
To handle placeholders that look like `<foo.bar>` instead of `${foo.bar}`,
one would instantiate the class like this:
$placeholderResolver = new RegexPlaceholderResolver($dataSource, '<', '>');
Placeholders can recursively resolve placeholders. For example, given a
data source with the following:
array(
'foo' => 'FOO',
'bar' => 'BAR',
'FOO.BAR' => 'BAZ!',
);
The placeholder `${${foo}.${bar}}` would internally be resolved to
`${FOO.BAR}` before being further resolved to `BAZ!`.
Resolved placeholders are cached using the `CacheInterface`. The default
`Cache` implementation is used unless it is explicitly set on the
Placeholder Resolver.
// YourCache implements Dflydev\PlaceholderResolver\Cache\CacheInterface
$cache = new YourCache;
$placeholderResolver->setCache($cache);
License
-------
This library is licensed under the New BSD License - see the LICENSE file
for details.
Community
---------
If you have questions or want to help out, join us in the
[#dflydev](irc://irc.freenode.net/#dflydev) channel on irc.freenode.net.
Not Invented Here
-----------------
Much of the ideas behind this library came from Spring's Property
Placeholder Configurer implementation.

View file

@ -0,0 +1,33 @@
{
"name": "dflydev/placeholder-resolver",
"type": "library",
"description": "Given a data source representing key => value pairs, resolve placeholders like ${foo.bar} to the value associated with the 'foo.bar' key in the data source.",
"homepage": "https://github.com/dflydev/dflydev-placeholder-resolver",
"keywords": ["placeholder", "resolver"],
"license": "MIT",
"authors": [
{
"name": "Dragonfly Development Inc.",
"email": "info@dflydev.com",
"homepage": "http://dflydev.com"
},
{
"name": "Beau Simensen",
"email": "beau@dflydev.com",
"homepage": "http://beausimensen.com"
}
],
"require": {
"php": ">=5.3.2"
},
"autoload": {
"psr-0": {
"Dflydev\\PlaceholderResolver": "src"
}
},
"extra": {
"branch-alias": {
"dev-master": "1.0-dev"
}
}
}

View file

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit colors="true" bootstrap="tests/bootstrap.php">
<testsuites>
<testsuite name="Placeholder Resolver Test Suite">
<directory>./tests/Dflydev/PlaceholderResolver</directory>
</testsuite>
</testsuites>
<filter>
<whitelist>
<directory>./src/Dflydev/PlaceholderResolver/</directory>
</whitelist>
</filter>
</phpunit>

View file

@ -0,0 +1,59 @@
<?php
/*
* This file is a part of dflydev/placeholder-resolver.
*
* (c) Dragonfly Development Inc.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Dflydev\PlaceholderResolver;
use Dflydev\PlaceholderResolver\Cache\Cache;
use Dflydev\PlaceholderResolver\Cache\CacheInterface;
abstract class AbstractPlaceholderResolver implements PlaceholderResolverInterface
{
private $cache;
protected $maxReplacementDepth = 10;
/**
* Set maximum depth for recursive replacement
*
* @param int $maxReplacementDepth
*
* @return PlaceholderResolver
*/
public function setMaxReplacementDepth($maxReplacementDepth)
{
$this->maxReplacementDepth = $maxReplacementDepth;
return $this;
}
/**
* Get cache
*
* @return CacheInterface
*/
public function getCache()
{
if (null === $this->cache) {
$this->cache = new Cache;
}
return $this->cache;
}
/**
* Set cache
*
* @param CacheInterface $cache
*/
public function setCache(CacheInterface $cache)
{
$this->cache = $cache;
}
}

View file

@ -0,0 +1,62 @@
<?php
/*
* This file is a part of dflydev/placeholder-resolver.
*
* (c) Dragonfly Development Inc.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Dflydev\PlaceholderResolver\Cache;
class Cache implements CacheInterface
{
private $cache = array();
/**
* {@inheritdoc}
*/
public function exists($placeholder)
{
if (is_array($placeholder)) {
throw new \RuntimeException('Placeholder is an array');
}
return array_key_exists((string) $placeholder, $this->cache);
}
/**
* {@inheritdoc}
*/
public function get($placeholder)
{
if (is_array($placeholder)) {
throw new \RuntimeException('Placeholder is an array');
}
return array_key_exists((string) $placeholder, $this->cache)
? $this->cache[(string) $placeholder]
: null;
}
/**
* {@inheritdoc}
*/
public function set($placeholder, $value = null)
{
if (is_array($placeholder)) {
throw new \RuntimeException('Placeholder is an array');
}
$this->cache[(string) $placeholder] = $value;
}
/**
* {@inheritdoc}
*/
public function flush()
{
$this->cache = array();
}
}

View file

@ -0,0 +1,48 @@
<?php
/*
* This file is a part of dflydev/placeholder-resolver.
*
* (c) Dragonfly Development Inc.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Dflydev\PlaceholderResolver\Cache;
interface CacheInterface
{
/**
* Does specified placeholder exist?
*
* @param string $placeholder
*
* @return bool
*/
public function exists($placeholder);
/**
* Get placeholder's value
*
* @param string $placeholder
*
* @return string|null
*/
public function get($placeholder);
/**
* Set placeholder's value
*
* @param string $placeholder
* @param string|null $value
*
* @return string|null
*/
public function set($placeholder, $value = null);
/**
* Flush cache
*/
public function flush();
}

View file

@ -0,0 +1,61 @@
<?php
/*
* This file is a part of dflydev/placeholder-resolver.
*
* (c) Dragonfly Development Inc.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Dflydev\PlaceholderResolver\DataSource;
/**
* Array Data Source
*
* Simple array based implementation of the Data Source Interface
*
* @author Beau Simensen <beau@dflydev.com>
*/
class ArrayDataSource implements DataSourceInterface
{
/**
* @var array
*/
protected $array;
/**
* Constructor
*
* @param array $array
*/
public function __construct(array $array = array())
{
$this->array = $array;
}
/**
* {@inheritdoc}
*/
public function exists($key, $system = false)
{
if ($system) {
return false;
}
return isset($this->array[$key]);
}
/**
* {@inheritdoc}
*/
public function get($key, $system = false)
{
if ($system) {
return null;
}
return isset($this->array[$key]) ? $this->array[$key] : null;
}
}

View file

@ -0,0 +1,41 @@
<?php
/*
* This file is a part of dflydev/placeholder-resolver.
*
* (c) Dragonfly Development Inc.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Dflydev\PlaceholderResolver\DataSource;
interface DataSourceInterface
{
/**
* Does specified key exist?
*
* If $system is true, check system data. Otherwise,
* use application data. (think system == $_SERVER)
*
* @param string $key
* @param bool|null $system
*
* @return bool
*/
public function exists($key, $system = false);
/**
* Get key's value
*
* If $system is true, check system data. Otherwise,
* use application data. (think system == $_SERVER)
*
* @param string $key
* @param bool|null $system
*
* @return string|null
*/
public function get($key, $system = false);
}

View file

@ -0,0 +1,24 @@
<?php
/*
* This file is a part of dflydev/placeholder-resolver.
*
* (c) Dragonfly Development Inc.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Dflydev\PlaceholderResolver;
interface PlaceholderResolverInterface
{
/**
* Resolve a placeholder
*
* @param string $placeholder
*
* @return string|null
*/
public function resolvePlaceholder($placeholder);
}

View file

@ -0,0 +1,69 @@
<?php
/*
* This file is a part of dflydev/placeholder-resolver.
*
* (c) Dragonfly Development Inc.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Dflydev\PlaceholderResolver;
use Dflydev\PlaceholderResolver\DataSource\DataSourceInterface;
class RegexPlaceholderResolver extends AbstractPlaceholderResolver
{
/**
* @var PlaceholderResolverCallback
*/
private $placeholderResolverCallback;
/**
* @var string
*/
private $pattern;
/**
* Constructor
*
* @param DataSourceInterface $dataSource
* @param string|null $placeholderPrefix
* @param string|null $placeholderSuffix
*/
public function __construct(DataSourceInterface $dataSource, $placeholderPrefix = '${', $placeholderSuffix = '}')
{
$this->placeholderResolverCallback = new RegexPlaceholderResolverCallback($dataSource);
$placeholderPrefix = preg_quote($placeholderPrefix);
$placeholderSuffix = preg_quote($placeholderSuffix);
$this->pattern = "/{$placeholderPrefix}([a-zA-Z0-9\.\(\)_\:]+?){$placeholderSuffix}/";
}
/**
* {@inheritdoc}
*/
public function resolvePlaceholder($placeholder)
{
if ($this->getCache()->exists($placeholder)) {
return $this->getCache()->get($placeholder);
}
$value = $placeholder;
$counter = 0;
while ($counter++ < $this->maxReplacementDepth) {
$newValue = preg_replace_callback(
$this->pattern,
array($this->placeholderResolverCallback, 'callback'),
$value
);
if ($newValue === $value) { break; }
$value = $newValue;
}
$this->getCache()->set($placeholder, $value);
return $value;
}
}

View file

@ -0,0 +1,71 @@
<?php
/*
* This file is a part of dflydev/placeholder-resolver.
*
* (c) Dragonfly Development Inc.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Dflydev\PlaceholderResolver;
use Dflydev\PlaceholderResolver\DataSource\DataSourceInterface;
class RegexPlaceholderResolverCallback
{
/**
* @var DataSourceInterface
*/
private $dataSource;
/**
* Constructor
*
* @param DataSourceInterface $dataSource
*/
public function __construct(DataSourceInterface $dataSource)
{
$this->dataSource = $dataSource;
}
/**
* Callback for preg_replace_callback() generally called in PlaceholderResolver
*
* The expected input will be array($fullMatch, $potentialKey) and the
* expected output will be either a value from the data source, a special
* value from SERVER or CONSTANT, or the contents of $fullMatch (the key
* itself with its wrapped prefix and suffix).
*
* @param array $matches
*
* @return string|null
*/
public function callback($matches)
{
list ($fullMatch, $potentialKey) = $matches;
if (preg_match('/^(SYSTEM|SERVER|CONSTANT):(\w+)$/', $potentialKey, $specialMatches)) {
list ($dummy, $which, $specialKey) = $specialMatches;
switch ($which) {
case 'SERVER':
case 'SYSTEM':
if ($this->dataSource->exists($specialKey, true)) {
return $this->dataSource->get($specialKey, true);
}
break;
case 'CONSTANT':
if (defined($specialKey)) {
return constant($specialKey);
}
break;
}
}
if ($this->dataSource->exists($potentialKey)) {
return $this->dataSource->get($potentialKey);
}
return $fullMatch;
}
}

View file

@ -0,0 +1,125 @@
<?php
/*
* This file is a part of dflydev/placeholder-resolver.
*
* (c) Dragonfly Development Inc.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Dflydev\PlaceholderResolver\Cache;
class CacheTest extends \PHPUnit_Framework_TestCase
{
public function testSetAndGet()
{
$object = new CacheTestToSTring;
$cache = new Cache;
$cache->set(1, "one as integer");
$cache->set("2", "two as string '2'");
$cache->set("three", "three as string");
$cache->set($object, "object");
$this->assertEquals("one as integer", $cache->get(1));
$this->assertEquals("two as string '2'", $cache->get('2'));
$this->assertEquals("three as string", $cache->get('three'));
$this->assertEquals("object", $cache->get($object));
$this->assertNull($cache->get(11));
$this->assertNull($cache->get('12'));
$this->assertNull($cache->get('thirteen'));
}
public function testExists()
{
$object = new CacheTestToSTring;
$cache = new Cache;
$this->assertFalse($cache->exists(1));
$this->assertFalse($cache->exists("2"));
$this->assertFalse($cache->exists("three"));
$this->assertFalse($cache->exists($object));
}
public function testExistsArray()
{
$array = array();
$cache = new Cache;
$this->setExpectedException('RuntimeException');
$cache->exists($array);
}
public function testGetArray()
{
$array = array();
$cache = new Cache;
$this->setExpectedException('RuntimeException');
$cache->get($array);
}
public function testSetArray()
{
$array = array();
$cache = new Cache;
$this->setExpectedException('RuntimeException');
$cache->set($array, 'broken');
}
public function testExistsNoToString()
{
$object = new CacheTestNoToSTring;
$cache = new Cache;
$this->setExpectedException('PHPUnit_Framework_Error');
$cache->exists($object);
}
public function testGetNoToString()
{
$object = new CacheTestNoToSTring;
$cache = new Cache;
$this->setExpectedException('PHPUnit_Framework_Error');
$cache->get($object);
}
public function testSetNoToString()
{
$object = new CacheTestNoToSTring;
$cache = new Cache;
$this->setExpectedException('PHPUnit_Framework_Error');
$cache->set($object, 'broken');
}
}
class CacheTestNoToSTring
{
}
class CacheTestToSTring
{
public function __toString()
{
return 'any string';
}
}

View file

@ -0,0 +1,48 @@
<?php
/*
* This file is a part of dflydev/placeholder-resolver.
*
* (c) Dragonfly Development Inc.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Dflydev\PlaceholderResolver\DataSource;
/**
* ArrayDataSource Test
*
* @author Beau Simensen <beau@dflydev.com>
*/
class ArrayDataSourceTest extends \PHPUnit_Framework_TestCase
{
/**
* Test basic functionality
*/
public function testBasic()
{
$dataSource = new ArrayDataSource(array(
'a' => 'A',
'b' => 'B',
'c' => 'C',
));
$this->assertTrue($dataSource->exists('a'));
$this->assertTrue($dataSource->exists('b'));
$this->assertTrue($dataSource->exists('c'));
$this->assertFalse($dataSource->exists('d'));
$this->assertFalse($dataSource->exists('a', true));
$this->assertFalse($dataSource->exists('d', true));
$this->assertEquals('A', $dataSource->get('a'));
$this->assertEquals('B', $dataSource->get('b'));
$this->assertEquals('C', $dataSource->get('c'));
$this->assertNull($dataSource->get('d'));
$this->assertNull($dataSource->get('a', true));
$this->assertNull($dataSource->get('d', true));
}
}

View file

@ -0,0 +1,57 @@
<?php
/*
* This file is a part of dflydev/placeholder-resolver.
*
* (c) Dragonfly Development Inc.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Dflydev\PlaceholderResolver;
class RegexPlaceholderResolverCallbackTest extends \PHPUnit_Framework_TestCase
{
public function testCallback()
{
$dataSource = $this->getMock('Dflydev\PlaceholderResolver\DataSource\DataSourceInterface');
$dataSource
->expects($this->any())
->method('exists')
->will($this->returnValueMap(array(
array('foo', false, true),
array('bar', false, true),
array('baz', false, true),
array('bat', false, false),
array('foo', true, true),
array('bar', true, false),
)))
;
$dataSource
->expects($this->any())
->method('get')
->will($this->returnValueMap(array(
array('foo', false, 'FOO'),
array('bar', false, 'BAR'),
array('baz', false, 'BAZ'),
array('foo', true, 'SYSTEM FOO'),
)))
;
$placeholderResolverCallback = new RegexPlaceholderResolverCallback($dataSource);
define('TEST_CONSTANT_RESOLVE', 'abc123');
$this->assertEquals('FOO', $placeholderResolverCallback->callback(array('${foo}', 'foo')));
$this->assertEquals('BAR', $placeholderResolverCallback->callback(array('${bar}', 'bar')));
$this->assertEquals('BAZ', $placeholderResolverCallback->callback(array('${baz}', 'baz')));
$this->assertEquals('${bat}', $placeholderResolverCallback->callback(array('${bat}', 'bat')));
$this->assertEquals('SYSTEM FOO', $placeholderResolverCallback->callback(array('${SYSTEM:foo}', 'SYSTEM:foo')));
$this->assertEquals('${SYSTEM:bar}', $placeholderResolverCallback->callback(array('${SYSTEM:bar}', 'SYSTEM:bar')));
$this->assertEquals('SYSTEM FOO', $placeholderResolverCallback->callback(array('${SERVER:foo}', 'SERVER:foo')));
$this->assertEquals('${SERVER:bar}', $placeholderResolverCallback->callback(array('${SERVER:bar}', 'SERVER:bar')));
$this->assertEquals('abc123', $placeholderResolverCallback->callback(array('${CONSTANT:TEST_CONSTANT_RESOLVE}', 'CONSTANT:TEST_CONSTANT_RESOLVE')));
$this->assertEquals('${CONSTANT:MISSING_TEST_CONSTANT_RESOLVE}', $placeholderResolverCallback->callback(array('${CONSTANT:MISSING_TEST_CONSTANT_RESOLVE}', 'CONSTANT:MISSING_TEST_CONSTANT_RESOLVE')));
}
}

View file

@ -0,0 +1,101 @@
<?php
/*
* This file is a part of dflydev/placeholder-resolver.
*
* (c) Dragonfly Development Inc.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Dflydev\PlaceholderResolver;
class PlaceholderResolverTest extends \PHPUnit_Framework_TestCase
{
public function testResolvePlaceholder()
{
$dataSource = $this->getMock('Dflydev\PlaceholderResolver\DataSource\DataSourceInterface');
$dataSource
->expects($this->any())
->method('exists')
->will($this->returnValueMap(array(
array('foo', false, true),
array('bar', false, true),
array('baz', false, true),
array('bat', false, false),
array('composite', false, true),
array('FOO.BAR', false, true),
array('FOO.BAR.BAZ', false, false),
)))
;
$dataSource
->expects($this->any())
->method('get')
->will($this->returnValueMap(array(
array('foo', false, 'FOO'),
array('bar', false, 'BAR'),
array('baz', false, 'BAZ'),
array('composite', false, '${foo}-${bar}'),
array('FOO.BAR', false, 'Foo Dot Bar'),
)))
;
$placeholderResolver = new RegexPlaceholderResolver($dataSource);
$this->assertEquals("FOO", $placeholderResolver->resolvePlaceholder('${foo}'));
$this->assertEquals("BAR", $placeholderResolver->resolvePlaceholder('${bar}'));
$this->assertEquals("BAZ", $placeholderResolver->resolvePlaceholder('${baz}'));
$this->assertEquals("FOO-BAR", $placeholderResolver->resolvePlaceholder('${composite}'));
$this->assertEquals("FOO-BAR-BAZ", $placeholderResolver->resolvePlaceholder('${composite}-${baz}'));
$this->assertEquals("Foo Dot Bar", $placeholderResolver->resolvePlaceholder('${${foo}.${bar}}'));
$this->assertEquals('${FOO.BAR.BAZ}', $placeholderResolver->resolvePlaceholder('${FOO.BAR.BAZ}'));
}
/**
* @dataProvider resolvePlaceholderPrefixAndSuffixProvider
*/
public function testResolvePlaceholderPrefixAndSuffix($prefix, $suffix)
{
$dataSource = $this->getMock('Dflydev\PlaceholderResolver\DataSource\DataSourceInterface');
$dataSource
->expects($this->any())
->method('exists')
->will($this->returnValueMap(array(
array('foo', false, true),
array('bar', false, true),
array('baz', false, true),
array('bat', false, false),
array('composite', false, true),
array('FOO.BAR', false, true),
)))
;
$dataSource
->expects($this->any())
->method('get')
->will($this->returnValueMap(array(
array('foo', false, 'FOO'),
array('bar', false, 'BAR'),
array('baz', false, 'BAZ'),
array('composite', false, $prefix.'foo'.$suffix.'-'.$prefix.'bar'.$suffix),
array('FOO.BAR', false, 'Foo Dot Bar'),
)))
;
$placeholderResolver = new RegexPlaceholderResolver($dataSource, $prefix, $suffix);
$this->assertEquals("FOO", $placeholderResolver->resolvePlaceholder($prefix.'foo'.$suffix));
$this->assertEquals($prefix.'bat'.$suffix, $placeholderResolver->resolvePlaceholder($prefix.'bat'.$suffix));
$this->assertEquals("FOO-BAR", $placeholderResolver->resolvePlaceholder($prefix.'composite'.$suffix));
$this->assertEquals("FOO-BAR-BAZ", $placeholderResolver->resolvePlaceholder($prefix.'composite'.$suffix.'-'.$prefix.'baz'.$suffix));
$this->assertEquals("Foo Dot Bar", $placeholderResolver->resolvePlaceholder($prefix.$prefix.'foo'.$suffix.'.'.$prefix.'bar'.$suffix.$suffix));
}
public function resolvePlaceholderPrefixAndSuffixProvider()
{
return array(
array('%', '%'),
array('<', '>'),
array('(<)', '(>)'),
);
}
}

View file

@ -0,0 +1,13 @@
<?php
/*
* This file is a part of dflydev/placeholder-resolver.
*
* (c) Dragonfly Development Inc.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
$loader = require dirname(__DIR__).'/vendor/autoload.php';