Passed
Pull Request — master (#62)
by Alexander
07:46
created

ReplaceValue   A

Complexity

Total Complexity 10

Size/Duplication

Total Lines 67
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 10
eloc 24
dl 0
loc 67
ccs 26
cts 26
cp 1
rs 10
c 1
b 0
f 0

4 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 3 1
A afterMerge() 0 7 2
A withKey() 0 5 1
A beforeMerge() 0 24 6
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Arrays\Collection\Modifier;
6
7
use Yiisoft\Arrays\Collection\Modifier\ModifierInterface\AfterMergeModifierInterface;
8
use Yiisoft\Arrays\Collection\Modifier\ModifierInterface\BeforeMergeModifierInterface;
9
10
use function array_slice;
11
12
/**
13
 * The modifier allows to mark an array element from the collection it is applied to,
14
 * as the element to be processed in a special way on merge.
15
 *
16
 * - In case there are elements with the same keys in previous arrays, they will be replaced
17
 *   with a value from the current array.
18
 *
19
 * - If there are elements with the same keys in next arrays, they will replace current array value.
20
 *
21
 * If there is no element with the given key in the array, modifier won't change anything.
22
 *
23
 * Note that this modifier is applied on merge.
24
 *
25
 * Usage example:
26
 *
27
 * ```php
28
 * $a = [
29
 *     'name' => 'Yii',
30
 *     'version' => '1.1',
31
 *     'features' => ['mvc'],
32
 * ];
33
 * $b = new ArrayCollection(
34
 *     [
35
 *         'version' => '3.0',
36
 *         'features' => ['gii'],
37
 *     ],
38
 *     new ReplaceValue('features')
39
 * );
40
 *
41
 * // [
42
 * //     'name' => 'Yii',
43
 * //     'version' => '3.0',
44
 * //     'features' => ['gii'],
45
 * // ],
46
 * $result = ArrayHelper::merge($a, $b));
47
 * ```
48
 */
49
final class ReplaceValue extends Modifier implements BeforeMergeModifierInterface, AfterMergeModifierInterface
50
{
51
    /**
52
     * @var int|string
53
     */
54
    private $key;
55
56
    /**
57
     * @var mixed
58
     */
59
    private $value;
60
61
    private bool $setValueAfterMerge = false;
62
63
    /**
64
     * @param int|string $key
65
     */
66 7
    public function __construct($key)
67
    {
68 7
        $this->key = $key;
69 7
    }
70
71
    /**
72
     * @param int|string $key
73
     *
74
     * @return self
75
     */
76 1
    public function withKey($key): self
77
    {
78 1
        $new = clone $this;
79 1
        $new->key = $key;
80 1
        return $new;
81
    }
82
83 7
    public function beforeMerge(array $arrays, int $index): array
84
    {
85 7
        $currentArray = $arrays[$index];
86
87 7
        if (!array_key_exists($this->key, $currentArray)) {
88 2
            return $arrays[$index];
89
        }
90
91 6
        foreach (array_slice($arrays, $index + 1) as $array) {
92 4
            if (array_key_exists($this->key, $array)) {
93 2
                $currentArray[$this->key] = null;
94 2
                return $currentArray;
95
            }
96
        }
97
98 4
        foreach (array_slice($arrays, 0, $index) as $array) {
99 4
            if (array_key_exists($this->key, $array)) {
100 3
                $this->value = $currentArray[$this->key];
101 3
                $this->setValueAfterMerge = true;
102 3
                return $currentArray;
103
            }
104
        }
105
106 1
        return $currentArray;
107
    }
108
109 7
    public function afterMerge(array $data): array
110
    {
111 7
        if ($this->setValueAfterMerge) {
112 3
            $data[$this->key] = $this->value;
113 3
            $this->setValueAfterMerge = false;
114
        }
115 7
        return $data;
116
    }
117
}
118