Passed
Pull Request — master (#62)
by Sergei
02:11
created

ReplaceValue::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 1
dl 0
loc 3
ccs 2
cts 2
cp 1
crap 1
rs 10
c 0
b 0
f 0
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
     * @return self
74
     */
75 1
    public function withKey($key): self
76
    {
77 1
        $new = clone $this;
78 1
        $new->key = $key;
79 1
        return $new;
80
    }
81
82 7
    public function beforeMerge(array $arrays, int $index): array
83
    {
84 7
        $currentArray = $arrays[$index];
85
86 7
        if (!array_key_exists($this->key, $currentArray)) {
87 2
            return $arrays[$index];
88
        }
89
90 6
        foreach (array_slice($arrays, $index + 1) as $array) {
91 4
            if (array_key_exists($this->key, $array)) {
92 2
                $currentArray[$this->key] = null;
93 2
                return $currentArray;
94
            }
95
        }
96
97 4
        foreach (array_slice($arrays, 0, $index) as $array) {
98 4
            if (array_key_exists($this->key, $array)) {
99 3
                $this->value = $currentArray[$this->key];
100 3
                $this->setValueAfterMerge = true;
101 3
                return $currentArray;
102
            }
103
        }
104
105 1
        return $currentArray;
106
    }
107
108 7
    public function afterMerge(array $data): array
109
    {
110 7
        if ($this->setValueAfterMerge) {
111 3
            $data[$this->key] = $this->value;
112 3
            $this->setValueAfterMerge = false;
113
        }
114 7
        return $data;
115
    }
116
}
117