Skip to content

Commit 17aa0d2

Browse files
authored
Merge 22735a7 into e496601
2 parents e496601 + 22735a7 commit 17aa0d2

File tree

3 files changed

+78
-0
lines changed

3 files changed

+78
-0
lines changed

src/ArrayHelper.php

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
use InvalidArgumentException;
66
use Yiisoft\Arrays\Modifier\ModifierInterface;
77
use Yiisoft\Strings\StringHelper;
8+
use Yiisoft\Arrays\Modifier\ReverseBlockMerge;
89

910
/**
1011
* Yii array helper provides static methods allowing you to deal with arrays more efficiently.
@@ -105,6 +106,12 @@ public static function toArray($object, array $properties = [], bool $recursive
105106
*/
106107
public static function merge(...$args): array
107108
{
109+
$lastArray = end($args);
110+
if (isset($lastArray[ReverseBlockMerge::class]) && $lastArray[ReverseBlockMerge::class] instanceof ReverseBlockMerge) {
111+
reset($lastArray);
112+
return self::applyModifiers(self::performReverseBlockMerge(...$args));
113+
}
114+
108115
return self::applyModifiers(self::performMerge(...$args));
109116
}
110117

@@ -130,6 +137,28 @@ private static function performMerge(...$args): array
130137
return $res;
131138
}
132139

140+
private static function performReverseBlockMerge(...$args): array
141+
{
142+
$res = array_pop($args) ?: [];
143+
while (!empty($args)) {
144+
foreach (array_pop($args) as $k => $v) {
145+
if (is_int($k)) {
146+
if (array_key_exists($k, $res) && $res[$k] !== $v) {
147+
$res[] = $v;
148+
} else {
149+
$res[$k] = $v;
150+
}
151+
} elseif (is_array($v) && isset($res[$k]) && is_array($res[$k])) {
152+
$res[$k] = self::performReverseBlockMerge($v, $res[$k]);
153+
} elseif (!isset($res[$k])) {
154+
$res[$k] = $v;
155+
}
156+
}
157+
}
158+
159+
return $res;
160+
}
161+
133162
public static function applyModifiers(array $data): array
134163
{
135164
$modifiers = [];

src/Modifier/ReverseBlockMerge.php

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<?php
2+
3+
namespace Yiisoft\Arrays\Modifier;
4+
5+
/**
6+
* Reverse arrays order
7+
*/
8+
class ReverseBlockMerge implements ModifierInterface
9+
{
10+
public function apply(array $data, string $key): array
11+
{
12+
return $data;
13+
}
14+
}

tests/ArrayHelperTest.php

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
use Yiisoft\Arrays\ArrayableInterface;
1010
use Yiisoft\Arrays\ArrayHelper;
1111
use Yiisoft\Arrays\Modifier\RemoveKeys;
12+
use Yiisoft\Arrays\Modifier\ReverseBlockMerge;
1213
use Yiisoft\Arrays\Modifier\ReverseValues;
1314
use Yiisoft\Arrays\Modifier\ReplaceValue;
1415
use Yiisoft\Arrays\Modifier\UnsetValue;
@@ -372,6 +373,40 @@ public function testMergeWithReverseValues(): void
372373
$this->assertSame($expected, $result);
373374
}
374375

376+
public function testMergeWithReverseBlock(): void
377+
{
378+
$a = [
379+
'name' => 'Yii',
380+
'options' => [
381+
'option1' => 'valueA',
382+
'option3' => 'valueAA',
383+
],
384+
'version' => '1.0',
385+
ReverseBlockMerge::class => new ReverseBlockMerge(),
386+
];
387+
$b = [
388+
'version' => '1.1',
389+
'options' => [
390+
'option1' => 'valueB',
391+
'option2' => 'valueBB',
392+
],
393+
ReverseBlockMerge::class => new ReverseBlockMerge(),
394+
];
395+
396+
$result = ArrayHelper::merge($a, $b);
397+
$expected = [
398+
'version' => '1.1',
399+
'options' => [
400+
'option1' => 'valueB',
401+
'option2' => 'valueBB',
402+
'option3' => 'valueAA',
403+
],
404+
'name' => 'Yii',
405+
];
406+
407+
$this->assertSame($expected, $result);
408+
}
409+
375410
public function testMergeWithNullValues(): void
376411
{
377412
$a = [

0 commit comments

Comments
 (0)