Skip to content

Commit 3824b8a

Browse files
committed
Add new MERGE import mode; change clobber to no longer be boolean
1 parent 7c13ae1 commit 3824b8a

4 files changed

Lines changed: 72 additions & 35 deletions

File tree

src/Data.php

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -200,17 +200,17 @@ public function getData(string $key): DataInterface
200200
/**
201201
* {@inheritdoc}
202202
*/
203-
public function import(array $data, bool $clobber = true): void
203+
public function import(array $data, int $mode = self::REPLACE): void
204204
{
205-
$this->data = Util::mergeAssocArray($this->data, $data, $clobber);
205+
$this->data = Util::mergeAssocArray($this->data, $data, $mode);
206206
}
207207

208208
/**
209209
* {@inheritdoc}
210210
*/
211-
public function importData(DataInterface $data, bool $clobber = true): void
211+
public function importData(DataInterface $data, int $mode = self::REPLACE): void
212212
{
213-
$this->import($data->export(), $clobber);
213+
$this->import($data->export(), $mode);
214214
}
215215

216216
/**

src/DataInterface.php

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@
1616

1717
interface DataInterface
1818
{
19+
public const PRESERVE = 0;
20+
public const REPLACE = 1;
21+
public const MERGE = 2;
22+
1923
/**
2024
* Append a value to a key (assumes key refers to an array value)
2125
*
@@ -85,18 +89,18 @@ public function getData(string $key): DataInterface;
8589
/**
8690
* Import data into existing data
8791
*
88-
* @param array<string, mixed> $data
89-
* @param bool $clobber
92+
* @param array<string, mixed> $data
93+
* @param self::PRESERVE|self::REPLACE|self::MERGE $mode
9094
*/
91-
public function import(array $data, bool $clobber = true): void;
95+
public function import(array $data, int $mode = self::REPLACE): void;
9296

9397
/**
9498
* Import data from an external data into existing data
9599
*
96-
* @param DataInterface $data
97-
* @param bool $clobber
100+
* @param DataInterface $data
101+
* @param self::PRESERVE|self::REPLACE|self::MERGE $mode
98102
*/
99-
public function importData(DataInterface $data, bool $clobber = true): void;
103+
public function importData(DataInterface $data, int $mode = self::REPLACE): void;
100104

101105
/**
102106
* Export data as raw data

src/Util.php

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,26 +35,42 @@ public static function isAssoc(array $arr): bool
3535
*
3636
* @param mixed $to
3737
* @param mixed $from
38-
* @param bool $clobber
38+
* @param DataInterface::PRESERVE|DataInterface::REPLACE|DataInterface::MERGE $mode
3939
*
4040
* @return mixed
4141
*
4242
* @psalm-pure
4343
*/
44-
public static function mergeAssocArray($to, $from, $clobber = true)
44+
public static function mergeAssocArray($to, $from, int $mode = DataInterface::REPLACE)
4545
{
46+
if ($mode === DataInterface::MERGE && self::isList($to) && self::isList($from)) {
47+
return array_merge($to, $from);
48+
}
49+
4650
if (is_array($from)) {
4751
foreach ($from as $k => $v) {
4852
if (!isset($to[$k])) {
4953
$to[$k] = $v;
5054
} else {
51-
$to[$k] = self::mergeAssocArray($to[$k], $v, $clobber);
55+
$to[$k] = self::mergeAssocArray($to[$k], $v, $mode);
5256
}
5357
}
5458

5559
return $to;
5660
}
5761

58-
return $clobber ? $from : $to;
62+
return $mode === DataInterface::PRESERVE ? $to : $from;
63+
}
64+
65+
/**
66+
* @param mixed $value
67+
*
68+
* @return bool
69+
*
70+
* @psalm-pure
71+
*/
72+
private static function isList($value): bool
73+
{
74+
return is_array($value) && array_values($value) === $value;
5975
}
6076
}

tests/UtilTest.php

Lines changed: 38 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -25,59 +25,64 @@ public function testIsAssoc()
2525
/**
2626
* @dataProvider mergeAssocArrayProvider
2727
*/
28-
public function testMergeAssocArray($message, $to, $from, $clobber, $expectedResult)
28+
public function testMergeAssocArray($message, $to, $from, $mode, $expectedResult)
2929
{
30-
$result = Util::mergeAssocArray($to, $from, $clobber);
30+
if ($mode === null) {
31+
$result = Util::mergeAssocArray($to, $from);
32+
} else {
33+
$result = Util::mergeAssocArray($to, $from, $mode);
34+
}
35+
3136
$this->assertEquals($expectedResult, $result, $message);
3237
}
3338

3439
public function mergeAssocArrayProvider()
3540
{
3641
return [
3742
[
38-
'Clobber should replace to value with from value for strings (shallow)',
43+
'Overwrite should replace to value with from value for strings (shallow)',
3944
// to
4045
['a' => 'A'],
4146
// from
4247
['a' => 'B'],
43-
// clobber
44-
true,
48+
// mode
49+
DataInterface::REPLACE,
4550
// expected result
4651
['a' => 'B'],
4752
],
4853

4954
[
50-
'Clobber should replace to value with from value for strings (deep)',
55+
'Overwrite should replace to value with from value for strings (deep)',
5156
// to
5257
['a' => ['b' => 'B']],
5358
// from
5459
['a' => ['b' => 'C']],
55-
// clobber
56-
true,
60+
// mode
61+
DataInterface::REPLACE,
5762
// expected result
5863
['a' => ['b' => 'C']]
5964
],
6065

6166
[
62-
'Clobber should NOTreplace to value with from value for strings (shallow)',
67+
'Existing values are not replaced in preserve mode (shallow)',
6368
// to
6469
['a' => 'A'],
6570
// from
6671
['a' => 'B'],
67-
// clobber
68-
false,
72+
// mode
73+
DataInterface::PRESERVE,
6974
// expected result
7075
['a' => 'A'],
7176
],
7277

7378
[
74-
'Clobber should NOT replace to value with from value for strings (deep)',
79+
'Existing values are not replaced in preserve mode (deep)',
7580
// to
7681
['a' => ['b' => 'B']],
7782
// from
7883
['a' => ['b' => 'C']],
79-
// clobber
80-
false,
84+
// mode
85+
DataInterface::PRESERVE,
8186
// expected result
8287
['a' => ['b' => 'B']],
8388
],
@@ -88,35 +93,47 @@ public function mergeAssocArrayProvider()
8893
['a' => ['b' => 'B']],
8994
// from
9095
['a' => ['c' => 'C']],
91-
// clobber
96+
// mode
9297
null,
9398
// expected result
9499
['a' => ['b' => 'B', 'c' => 'C']],
95100
],
96101

97102
[
98-
'Arrays should be replaced (with clobber enabled)',
103+
'Arrays should be replaced',
99104
// to
100105
['a' => ['b', 'c']],
101106
// from
102107
['a' => ['B', 'C']],
103-
// clobber
104-
true,
108+
// mode
109+
DataInterface::REPLACE,
105110
// expected result
106111
['a' => ['B', 'C']],
107112
],
108113

109114
[
110-
'Arrays should be NOT replaced (with clobber disabled)',
115+
'Arrays should be preserved',
111116
// to
112117
['a' => ['b', 'c']],
113118
// from
114119
['a' => ['B', 'C']],
115-
// clobber
116-
false,
120+
// mode
121+
DataInterface::PRESERVE,
117122
// expected result
118123
['a' => ['b', 'c']],
119124
],
125+
126+
[
127+
'Arrays should be merged/appended (when using MERGE)',
128+
// to
129+
['a' => 1, 'b' => 1, 'n' => [1]],
130+
// from
131+
['a' => 2, 'c' => 2, 'n' => [2]],
132+
// mode
133+
DataInterface::MERGE,
134+
// expected result
135+
['a' => 2, 'b' => 1, 'c' => 2, 'n' => [1, 2]]
136+
],
120137
];
121138
}
122139
}

0 commit comments

Comments
 (0)