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

ConfigProcessor   A

Complexity

Total Complexity 15

Size/Duplication

Total Lines 124
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 2

Importance

Changes 0
Metric Value
wmc 15
lcom 1
cbo 2
dl 0
loc 124
rs 10
c 0
b 0
f 0

9 Methods

Rating   Name   Duplication   Size   Complexity  
A extend() 0 4 1
A add() 0 9 2
A export() 0 10 2
A fetchUnprocessed() 0 6 1
A process() 0 5 1
A preprocess() 0 4 1
A reduceOne() 0 5 1
A evaluate() 0 7 1
B arrayMergeRecursiveDistinct() 0 15 5
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
    public function extend(ConfigLoaderInterface $loader)
21
    {
22
        return $this->add($loader->export(), $loader->getSourceName());
23
    }
24
25
    /**
26
     * Extend the configuration to be processed with
27
     * the provided nested array.
28
     */
29
    public function add($data, $source = '')
30
    {
31
        if (empty($source)) {
32
            $this->unprocessedConfig[] = $data;
33
            return $this;
34
        }
35
        $this->unprocessedConfig[$source] = $data;
36
        return $this;
37
    }
38
39
    /**
40
     * Process all of the configuration that has been collected,
41
     * and return a nested array.
42
     */
43
    public function export()
44
    {
45
        if (!empty($this->unprocessedConfig)) {
46
            $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...
47
                $this->processedConfig,
48
                $this->fetchUnprocessed()
49
            );
50
        }
51
        return $this->processedConfig;
52
    }
53
54
    /**
55
     * Get the configuration to be processed, and clear out the
56
     * 'unprocessed' list.
57
     * @return array
58
     */
59
    protected function fetchUnprocessed()
60
    {
61
        $toBeProcessed = $this->unprocessedConfig;
62
        $this->unprocessedConfig = [];
63
        return $toBeProcessed;
64
    }
65
66
    /**
67
     * Use a map-reduce to evaluate the items to be processed,
68
     * and merge them into the processed array.
69
     */
70
    protected function process($processed, $toBeProcessed)
71
    {
72
        $toBeReduced = array_map([$this, 'preprocess'], $toBeProcessed);
73
        return array_reduce($toBeReduced, [$this, 'reduceOne'], $processed);
74
    }
75
76
    /**
77
     * Process a single configuration file from the 'to be processed'
78
     * list. By default this is a no-op. Override this method to
79
     * provide any desired configuration preprocessing, e.g. dot-notation
80
     * expansion of the configuration keys, etc.
81
     */
82
    protected function preprocess($config)
83
    {
84
        return $config;
85
    }
86
87
    /**
88
     * Evaluate one item in the 'to be evaluated' list, and then
89
     * merge it into the processed configuration (the 'carry').
90
     */
91
    protected function reduceOne($processed, $config)
92
    {
93
        $evaluated = $this->evaluate($processed, $config);
94
        return static::arrayMergeRecursiveDistinct($processed, $evaluated);
95
    }
96
97
    /**
98
     * Evaluate one configuration item.
99
     */
100
    protected function evaluate($processed, $config)
101
    {
102
        return Expander::expandArrayProperties(
103
            $config,
104
            $processed
105
        );
106
    }
107
108
    /**
109
     * Merges arrays recursively while preserving.
110
     *
111
     * @param array $array1
112
     * @param array $array2
113
     *
114
     * @return array
115
     *
116
     * @see http://php.net/manual/en/function.array-merge-recursive.php#92195
117
     * @see https://github.com/grasmash/bolt/blob/robo-rebase/src/Robo/Common/ArrayManipulator.php#L22
118
     */
119
    public static function arrayMergeRecursiveDistinct(
120
        array &$array1,
121
        array &$array2
122
    ) {
123
        $merged = $array1;
124
        foreach ($array2 as $key => &$value) {
125
            if (is_array($value) && isset($merged[$key]) && is_array($merged[$key])) {
126
                $merged[$key] = self::arrayMergeRecursiveDistinct($merged[$key], $value);
127
            }
128
            else {
129
                $merged[$key] = $value;
130
            }
131
        }
132
        return $merged;
133
    }
134
}
135