Completed
Pull Request — master (#552)
by Greg
03:13
created

ConfigProcessor::arrayMergeRecursiveDistinct()   B

Complexity

Conditions 5
Paths 3

Size

Total Lines 14
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 14
rs 8.8571
c 0
b 0
f 0
cc 5
eloc 10
nc 3
nop 2
1
<?php
2
3
namespace Robo\Config;
4
5
use Grasmash\YamlExpander\Expander;
6
7
/**
8
 * The config processor combines multiple configuration
9
 * files together, and processes them as necessary.
10
 */
11
class ConfigProcessor
12
{
13
    protected $processedConfig = [];
14
    protected $unprocessedConfig = [];
15
16
    /**
17
     * Extend the configuration to be processed with the
18
     * configuration provided by the specified loader.
19
     *
20
     * @param ConfigLoaderInterface $loader
21
     */
22
    public function extend(ConfigLoaderInterface $loader)
23
    {
24
        return $this->add($loader->export(), $loader->getSourceName());
25
    }
26
27
    /**
28
     * Extend the configuration to be processed with
29
     * the provided nested array.
30
     *
31
     * @param array $data
32
     * @param string $source
33
     */
34
    public function add($data, $source = '')
35
    {
36
        if (empty($source)) {
37
            $this->unprocessedConfig[] = $data;
38
            return $this;
39
        }
40
        $this->unprocessedConfig[$source] = $data;
41
        return $this;
42
    }
43
44
    /**
45
     * Process all of the configuration that has been collected,
46
     * and return a nested array.
47
     *
48
     * @return array
49
     */
50
    public function export()
51
    {
52
        if (!empty($this->unprocessedConfig)) {
53
            $this->processedConfig = $this->process(
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->process($this->pr...is->fetchUnprocessed()) of type * is incompatible with the declared type array of property $processedConfig.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
54
                $this->processedConfig,
55
                $this->fetchUnprocessed()
56
            );
57
        }
58
        return $this->processedConfig;
59
    }
60
61
    /**
62
     * Get the configuration to be processed, and clear out the
63
     * 'unprocessed' list.
64
     *
65
     * @return array
66
     */
67
    protected function fetchUnprocessed()
68
    {
69
        $toBeProcessed = $this->unprocessedConfig;
70
        $this->unprocessedConfig = [];
71
        return $toBeProcessed;
72
    }
73
74
    /**
75
     * Use a map-reduce to evaluate the items to be processed,
76
     * and merge them into the processed array.
77
     *
78
     * @param array $processed
79
     * @param array $toBeProcessed
80
     */
81
    protected function process($processed, $toBeProcessed)
82
    {
83
        $toBeReduced = array_map([$this, 'preprocess'], $toBeProcessed);
84
        return array_reduce($toBeReduced, [$this, 'reduceOne'], $processed);
85
    }
86
87
    /**
88
     * Process a single configuration file from the 'to be processed'
89
     * list. By default this is a no-op. Override this method to
90
     * provide any desired configuration preprocessing, e.g. dot-notation
91
     * expansion of the configuration keys, etc.
92
     *
93
     * @param array $config
94
     */
95
    protected function preprocess($config)
96
    {
97
        return $config;
98
    }
99
100
    /**
101
     * Evaluate one item in the 'to be evaluated' list, and then
102
     * merge it into the processed configuration (the 'carry').
103
     *
104
     * @param array $processed
105
     * @param array $config
106
     */
107
    protected function reduceOne($processed, $config)
108
    {
109
        $evaluated = $this->evaluate($processed, $config);
110
        return static::arrayMergeRecursiveDistinct($processed, $evaluated);
111
    }
112
113
    /**
114
     * Evaluate one configuration item.
115
     *
116
     * @param array $processed
117
     * @param array $config
118
     */
119
    protected function evaluate($processed, $config)
120
    {
121
        return Expander::expandArrayProperties(
122
            $config,
123
            $processed
124
        );
125
    }
126
127
    /**
128
     * Merges arrays recursively while preserving.
129
     *
130
     * @param array $array1
131
     * @param array $array2
132
     *
133
     * @return array
134
     *
135
     * @see http://php.net/manual/en/function.array-merge-recursive.php#92195
136
     * @see https://github.com/grasmash/bolt/blob/robo-rebase/src/Robo/Common/ArrayManipulator.php#L22
137
     */
138
    public static function arrayMergeRecursiveDistinct(
139
        array &$array1,
140
        array &$array2
141
    ) {
142
        $merged = $array1;
143
        foreach ($array2 as $key => &$value) {
144
            if (is_array($value) && isset($merged[$key]) && is_array($merged[$key])) {
145
                $merged[$key] = self::arrayMergeRecursiveDistinct($merged[$key], $value);
146
            } else {
147
                $merged[$key] = $value;
148
            }
149
        }
150
        return $merged;
151
    }
152
}
153