Passed
Push — master ( f01d00...2f7647 )
by Nicolaas
03:27
created

LoadReplacementData   A

Complexity

Total Complexity 29

Size/Duplication

Total Lines 174
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
wmc 29
eloc 80
c 0
b 0
f 0
dl 0
loc 174
rs 10

10 Methods

Rating   Name   Duplication   Size   Complexity  
A setTo() 0 5 1
B __construct() 0 21 7
A getLanguages() 0 3 1
A getFlatFindArray() 0 3 1
A getReplacementArrays() 0 11 3
A getPaths() 0 13 3
B mergeConfig() 0 41 8
A getTos() 0 3 1
A getData() 0 18 3
A getFlatReplacedArray() 0 3 1
1
<?php
2
3
namespace Sunnysideup\UpgradeToSilverstripe4\ReplacementData;
4
5
use SilverStripe\Upgrader\Util\ConfigFile;
6
7
/**
8
 * loads yml data if strings to replace in
9
 * code.
10
 *
11
 * The replacements should be in the same folder as this class.
12
 *
13
 * Alternatively, you can specify another folderContainingLocationData in the
14
 * construct method.
15
 *
16
 * It will also search the root folders for any packages / projects being upgraded.
17
 */
18
19
20
use Sunnysideup\UpgradeToSilverstripe4\ModuleUpgrader;
21
22
class LoadReplacementData
23
{
24
    /**
25
     * Standard file name
26
     */
27
    protected $ymlFileName = '.upgrade.replacements.yml';
28
29
    /**
30
     * Module Object
31
     * @var ModuleUpgrader
32
     */
33
    protected $mu = null;
34
35
    protected $params = '';
36
37
    protected $folderContainingLocationData = '';
38
39
    protected $to = 'SS4';
40
41
    protected $fullArray = [];
42
43
    protected $tos = [];
44
45
    protected $languages = [];
46
47
    protected $flatFindArray = [];
48
49
    protected $flatReplacedArray = [];
50
51
    protected $paths = [];
52
53
    public function __construct($mu, $folderContainingLocationData = '', $params = [])
54
    {
55
        $this->folderContainingLocationData = $folderContainingLocationData ?: __DIR__;
56
        $this->params = $params;
57
        $this->mu = $mu;
58
        $this->fullArray = $this->getData();
59
        $count = 0;
60
        foreach ($this->fullArray as $to => $toArray) {
61
            $this->tos[$to] = $to;
62
            foreach ($toArray as $path => $pathArray) {
63
                foreach ($pathArray as $language => $languageArray) {
64
                    $this->languages[$language] = $language;
65
                    foreach ($languageArray as $findKey => $findKeyArray) {
66
                        if (! isset($findKeyArray['R'])) {
67
                            user_error('replacement key not set: ' . print_r($findKeyArray, 1));
68
                        }
69
                        $replaceKey = $findKeyArray['R'];
70
                        $key = strtolower($to . '_' . $language . '_' . $path . '_' . $count);
71
                        $this->flatFindArray[$key] = $findKey;
72
                        $this->flatReplacedArray[$key] = $replaceKey;
73
                        $count++;
74
                    }
75
                }
76
            }
77
        }
78
    }
79
80
    public function setTo($s)
81
    {
82
        $this->to = $s;
83
84
        return $this;
85
    }
86
87
    public function getReplacementArrays()
88
    {
89
        if (! $this->to) {
90
            return $this->fullArray;
91
        }
92
        if (isset($this->fullArray[$this->to])) {
93
            return $this->fullArray[$this->to];
94
        }
95
        user_error('no data is available for upgrading to: ' . $this->to);
96
97
        return [];
98
    }
99
100
    public function getTos()
101
    {
102
        return $this->tos;
103
    }
104
105
    public function getLanguages()
106
    {
107
        return $this->languages;
108
    }
109
110
    public function getFlatFindArray()
111
    {
112
        return $this->flatFindArray;
113
    }
114
115
    public function getFlatReplacedArray()
116
    {
117
        return $this->flatReplacedArray;
118
    }
119
120
    protected function getPaths()
121
    {
122
        $array = [];
123
        foreach ($this->mu->getExistingModuleDirLocations() as $moduleDir) {
124
            $array[$moduleDir] = $moduleDir;
125
        }
126
        $globalFixes = $this->mu->checkIfPathExistsAndCleanItUp($this->folderContainingLocationData);
127
        if ($globalFixes) {
128
            $array[$globalFixes] = $globalFixes;
129
        }
130
        $this->paths = $array;
131
132
        return $this->paths;
133
    }
134
135
    protected function getData()
136
    {
137
        $this->getPaths();
138
        // Merge with any other upgrade spec in the top level
139
        $config = [];
140
        foreach ($this->paths as $path) {
141
            $nextFile = $path . DIRECTORY_SEPARATOR . $this->ymlFileName;
142
            if (file_exists($nextFile)) {
143
                $nextConfig = ConfigFile::loadConfig($nextFile);
144
                // Merge
145
                $config = $this->mergeConfig($config, $nextConfig);
146
            } else {
147
                $this->mu->colourPrint('could not find: ' . $nextFile);
148
            }
149
        }
150
        ksort($config);
151
152
        return $config;
153
    }
154
155
    protected static function mergeConfig(array $left, array $right)
156
    {
157
        //see ConfigFile for original
158
        $merged = $left;
159
        foreach ($right as $key => $value) {
160
            // if non-associative, just merge in unique items
161
            if (is_numeric($key)) {
162
                if (! in_array($value, $merged, true)) {
163
                    $merged[] = $value;
164
                }
165
                continue;
166
            }
167
168
            // If not merged into left hand side, then simply assign
169
            if (! isset($merged[$key])) {
170
                $merged[$key] = $value;
171
                continue;
172
            }
173
174
            // Make sure both sides are the same type
175
            if (is_array($merged[$key]) !== is_array($value)) {
176
                user_error(
177
                    "Config option ${key} cannot merge non-array with array value."
178
                );
179
            }
180
181
            // If array type, then merge
182
            if (is_array($value)) {
183
                $merged[$key] = self::mergeConfig($merged[$key], $value);
184
                continue;
185
            }
186
187
            // If non array types, don't merge, but instead assert both values are set
188
            if ($merged[$key] !== $value) {
189
                user_error(
190
                    "Config option ${key} is defined with different values in multiple files."
191
                );
192
            }
193
        }
194
195
        return $merged;
196
    }
197
}
198