Completed
Pull Request — master (#17)
by Greg
01:54
created

ConfigProcessor::addFromSource()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 8
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 5
nc 2
nop 2
1
<?php
2
3
namespace Consolidation\Config\Loader;
4
5
use Grasmash\Expander\Expander;
6
use Consolidation\Config\Util\ArrayUtil;
7
8
/**
9
 * The config processor combines multiple configuration
10
 * files together, and processes them as necessary.
11
 */
12
class ConfigProcessor
13
{
14
    protected $processedConfig = [];
15
    protected $unprocessedConfig = [];
16
    protected $expander;
17
18
    public function __construct($expander = null)
19
    {
20
        $this->expander = $expander ?: new Expander();
21
    }
22
23
    /**
24
     * Extend the configuration to be processed with the
25
     * configuration provided by the specified loader.
26
     *
27
     * @param ConfigLoaderInterface $loader
28
     */
29
    public function extend(ConfigLoaderInterface $loader)
30
    {
31
        return $this->addFromSource($loader->export(), $loader->getSourceName());
32
    }
33
34
    /**
35
     * Extend the configuration to be processed with
36
     * the provided nested array.
37
     *
38
     * @param array $data
39
     */
40
    public function add($data)
41
    {
42
        $this->unprocessedConfig[] = $data;
43
        return $this;
44
    }
45
46
    /**
47
     * Extend the configuration to be processed with
48
     * the provided nested array. Also record the name
49
     * of the data source, if applicable.
50
     *
51
     * @param array $data
52
     * @param string $source
53
     */
54
    protected function addFromSource($data, $source = '')
55
    {
56
        if (empty($source)) {
57
            return $this->add($data);
58
        }
59
        $this->unprocessedConfig[$source] = $data;
60
        return $this;
61
    }
62
63
    /**
64
     * Process all of the configuration that has been collected,
65
     * and return a nested array.
66
     *
67
     * @return array
68
     */
69
    public function export($referenceArray = [])
70
    {
71
        if (!empty($this->unprocessedConfig)) {
72
            $this->processedConfig = $this->process(
73
                $this->processedConfig,
74
                $this->fetchUnprocessed(),
75
                $referenceArray
76
            );
77
        }
78
        return $this->processedConfig;
79
    }
80
81
    /**
82
     * To aid in debugging: return the source of each configuration item.
83
     * n.b. Must call this function *before* export and save the result
84
     * if persistence is desired.
85
     */
86
    public function sources()
87
    {
88
        $sources = [];
89
        foreach ($this->unprocessedConfig as $sourceName => $config) {
90
            if (!empty($sourceName)) {
91
                $configSources = ArrayUtil::fillRecursive($config, $sourceName);
92
                $sources = ArrayUtil::mergeRecursiveDistinct($sources, $configSources);
93
            }
94
        }
95
        return $sources;
96
    }
97
98
    /**
99
     * Get the configuration to be processed, and clear out the
100
     * 'unprocessed' list.
101
     *
102
     * @return array
103
     */
104
    protected function fetchUnprocessed()
105
    {
106
        $toBeProcessed = $this->unprocessedConfig;
107
        $this->unprocessedConfig = [];
108
        return $toBeProcessed;
109
    }
110
111
    /**
112
     * Use a map-reduce to evaluate the items to be processed,
113
     * and merge them into the processed array.
114
     *
115
     * @param array $processed
116
     * @param array $toBeProcessed
117
     * @return array
118
     */
119
    protected function process(array $processed, array $toBeProcessed, $referenceArray = [])
120
    {
121
        $toBeReduced = array_map([$this, 'preprocess'], $toBeProcessed);
122
        $reduced = array_reduce($toBeReduced, [$this, 'reduceOne'], $processed);
123
        return $this->evaluate($reduced, $referenceArray);
124
    }
125
126
    /**
127
     * Process a single configuration file from the 'to be processed'
128
     * list. By default this is a no-op. Override this method to
129
     * provide any desired configuration preprocessing, e.g. dot-notation
130
     * expansion of the configuration keys, etc.
131
     *
132
     * @param array $config
133
     * @return array
134
     */
135
    protected function preprocess(array $config)
136
    {
137
        return $config;
138
    }
139
140
    /**
141
     * Evaluate one item in the 'to be evaluated' list, and then
142
     * merge it into the processed configuration (the 'carry').
143
     *
144
     * @param array $processed
145
     * @param array $config
146
     * @return array
147
     */
148
    protected function reduceOne(array $processed, array $config)
149
    {
150
        return ArrayUtil::mergeRecursiveDistinct($processed, $config);
151
    }
152
153
    /**
154
     * Evaluate one configuration item.
155
     *
156
     * @param array $processed
0 ignored issues
show
Bug introduced by
There is no parameter named $processed. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
157
     * @param array $config
158
     * @return array
159
     */
160
    protected function evaluate(array $config, $referenceArray = [])
161
    {
162
        return $this->expander->expandArrayProperties(
163
            $config,
164
            $referenceArray
165
        );
166
    }
167
}
168