Skip to content
This repository has been archived by the owner on Jan 29, 2020. It is now read-only.

Commit

Permalink
Merge branch 'master' into hotfix/json-renderer-merge-unnamed-children
Browse files Browse the repository at this point in the history
  • Loading branch information
Show file tree
Hide file tree
Showing 4 changed files with 154 additions and 43 deletions.
34 changes: 22 additions & 12 deletions src/Config.php
Expand Up @@ -22,7 +22,9 @@

use Countable,
Iterator,
ArrayAccess;
ArrayAccess,
Zend\Stdlib\ArrayUtils
;

/**
* @category Zend
Expand Down Expand Up @@ -335,26 +337,34 @@ public function offsetUnset($offset)
/**
* Merge another Config with this one.
*
* The items in $merge will override the same named items in the current
* config.
* For duplicate keys, the following will be performed:
* - Nested Configs will be recursively merged.
* - Items in $merge with INTEGER keys will be appended.
* - Items in $merge with STRING keys will overwrite current values.
*
* @param self $merge
* @return self
* @param Config $replace
* @return Config
*/
public function merge(self $merge)
{
foreach ($merge as $key => $item) {
foreach ($merge as $key => $value) {
if (array_key_exists($key, $this->data)) {
if ($item instanceof self && $this->data[$key] instanceof self) {
$this->data[$key] = $this->data[$key]->merge(new self($item->toArray(), $this->allowModifications));
if (is_int($key)) {
$this->data[] = $value;
} elseif ($value instanceof self && $this->data[$key] instanceof self) {
$this->data[$key]->merge($value);
} else {
$this->data[$key] = $item;
if ($value instanceof self) {
$this->data[$key] = new self($value->toArray(), $this->allowModifications);
} else {
$this->data[$key] = $value;
}
}
} else {
if ($item instanceof self) {
$this->data[$key] = new self($item->toArray(), $this->allowModifications);
if ($value instanceof self) {
$this->data[$key] = new self($value->toArray(), $this->allowModifications);
} else {
$this->data[$key] = $item;
$this->data[$key] = $value;
}
}
}
Expand Down
4 changes: 3 additions & 1 deletion src/Factory.php
Expand Up @@ -20,6 +20,8 @@

namespace Zend\Config;

use Zend\Stdlib\ArrayUtils;

/**
* Declared abstract to prevent instantiation
*
Expand Down Expand Up @@ -95,7 +97,7 @@ public static function fromFiles(array $files, $returnConfigObject = false)
$config = array();

foreach ($files as $file) {
$config = array_replace_recursive($config, self::fromFile($file));
$config = ArrayUtils::merge($config, self::fromFile($file));
}

return ($returnConfigObject) ? new Config($config) : $config;
Expand Down
4 changes: 2 additions & 2 deletions src/Writer/AbstractWriter.php
Expand Up @@ -23,7 +23,7 @@
use Zend\Config\Writer,
Zend\Config\Exception,
Zend\Config\Config,
Zend\Stdlib\IteratorToArray,
Zend\Stdlib\ArrayUtils,
Traversable;

/**
Expand Down Expand Up @@ -77,7 +77,7 @@ function($error, $message = '', $file = '', $line = 0) use ($filename) {
public function toString($config)
{
if ($config instanceof Traversable) {
$config = IteratorToArray::convert($config);
$config = ArrayUtils::iteratorToArray($config);
} elseif (!is_array($config)) {
throw new Exception\InvalidArgumentException(__METHOD__ . ' expects an array or Traversable config');
}
Expand Down
155 changes: 127 additions & 28 deletions test/ConfigTest.php
Expand Up @@ -77,6 +77,52 @@ public function setUp()
)
);

$this->toCombineA = array(
'foo' => 1,
'bar' => 2,
'text' => 'foo',
'numerical' => array(
'first',
'second',
array(
'third'
)
),
'misaligned' => array(
2 => 'foo',
3 => 'bar'
),
'mixed' => array(
'foo' => 'bar'
),
'replaceAssoc' => array(
'foo' => 'bar'
),
'replaceNumerical' => array(
'foo'
)
);

$this->toCombineB = array(
'foo' => 3,
'text' => 'bar',
'numerical' => array(
'fourth',
'fifth',
array(
'sixth'
)
),
'misaligned' => array(
3 => 'baz'
),
'mixed' => array(
false
),
'replaceAssoc' => null,
'replaceNumerical' => true
);

$this->leadingdot = array('.test' => 'dot-test');
$this->invalidkey = array(' ' => 'test', ''=>'test2');

Expand Down Expand Up @@ -287,36 +333,55 @@ public function testUnset()

public function testMerge()
{
$stdArray = array(
'test_feature' => false,
'some_files' => array(
'foo'=>'dir/foo.xml',
'bar'=>'dir/bar.xml',
),
2 => 123,
);
$stdConfig = new Config($stdArray, true);

$devArray = array(
'test_feature'=>true,
'some_files' => array(
'bar' => 'myDir/bar.xml',
'baz' => 'myDir/baz.xml',
),
2 => 456,
);
$devConfig = new Config($devArray);

$stdConfig->merge($devConfig);

$this->assertTrue($stdConfig->test_feature);
$this->assertEquals('myDir/bar.xml', $stdConfig->some_files->bar);
$this->assertEquals('myDir/baz.xml', $stdConfig->some_files->baz);
$this->assertEquals('dir/foo.xml', $stdConfig->some_files->foo);
$this->assertEquals(456, $stdConfig->{2});
$configA = new Config($this->toCombineA);
$configB = new Config($this->toCombineB);
$configA->merge($configB);

// config->
$this->assertEquals(3, $configA->foo);
$this->assertEquals(2, $configA->bar);
$this->assertEquals('bar', $configA->text);

// config->numerical-> ...
$this->assertInstanceOf('\Zend\Config\Config',$configA->numerical);
$this->assertEquals('first',$configA->numerical->{0});
$this->assertEquals('second',$configA->numerical->{1});

// config->numerical->{2}-> ...
$this->assertInstanceOf('\Zend\Config\Config',$configA->numerical->{2});
$this->assertEquals('third',$configA->numerical->{2}->{0});
$this->assertEquals(null,$configA->numerical->{2}->{1});

// config->numerical-> ...
$this->assertEquals('fourth',$configA->numerical->{3});
$this->assertEquals('fifth',$configA->numerical->{4});

// config->numerical->{5}
$this->assertInstanceOf('\Zend\Config\Config',$configA->numerical->{5});
$this->assertEquals('sixth',$configA->numerical->{5}->{0});
$this->assertEquals(null,$configA->numerical->{5}->{1});

// config->misaligned
$this->assertInstanceOf('\Zend\Config\Config',$configA->misaligned);
$this->assertEquals('foo',$configA->misaligned->{2});
$this->assertEquals('bar',$configA->misaligned->{3});
$this->assertEquals('baz',$configA->misaligned->{4});
$this->assertEquals(null,$configA->misaligned->{0});

// config->mixed
$this->assertInstanceOf('\Zend\Config\Config',$configA->mixed);
$this->assertEquals('bar',$configA->mixed->foo);
$this->assertSame(false,$configA->mixed->{0});
$this->assertSame(null,$configA->mixed->{1});

// config->replaceAssoc
$this->assertSame(null,$configA->replaceAssoc);

// config->replaceNumerical
$this->assertSame(true,$configA->replaceNumerical);

}

public function testArrayAccess()
{
$config = new Config($this->all, true);
Expand Down Expand Up @@ -525,5 +590,39 @@ public function testZF6995_toArrayDoesNotDisturbInternalIterator()
$config->toArray();
$this->assertEquals(1, $config->current());
}

/**
* @depends testMerge
* @link http://framework.zend.com/issues/browse/ZF2-186
*/
public function testZF2_186_mergeReplacingUnnamedConfigSettings(){
$arrayA = array(
'flag' => true,
'text' => 'foo',
'list' => array( 'a', 'b', 'c' ),
'aSpecific' => 12
);

$arrayB = array(
'flag' => false,
'text' => 'bar',
'list' => array( 'd', 'e' ),
'bSpecific' => 100
);

$mergeResult = array(
'flag' => false,
'text' => 'bar',
'list' => array( 'a', 'b', 'c', 'd', 'e' ),
'aSpecific' => 12,
'bSpecific' => 100
);

$configA = new Config($arrayA);
$configB = new Config($arrayB);

$configA->merge($configB); // merge B onto A
$this->assertEquals($mergeResult, $configA->toArray());
}
}

0 comments on commit 0ee93d0

Please sign in to comment.