Passed
Push — master ( ce13c2...e57cc1 )
by Peter
05:04 queued 02:18
created

ay()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 3
c 1
b 0
f 0
nc 1
nop 2
dl 0
loc 6
rs 10
1
<?php
2
3
namespace YamlStandards\Model\YamlIndent;
4
5
use YamlStandards\Model\Component\YamlService;
6
7
class YamlIndentDataFactory
8
{
9
    /**
10
     * @param string[] $fileLines
11
     * @param int $key
12
     * @param int $countOfIndents
13
     * @param string $fileLine current checked line in loop
14
     * @param bool $isCommentLine
15
     * @return string
16
     *
17
     * @SuppressWarnings("CyclomaticComplexity")
18
     * @SuppressWarnings("ExcessiveMethodLength")
19
     */
20
    public function getRightFileLines(array $fileLines, $key, $countOfIndents, $fileLine, $isCommentLine = false)
21
    {
22
        if (YamlService::isLineComment($fileLines[$key])) {
23
            $key++;
24
            return $this->getRightFileLines($fileLines, $key, $countOfIndents, $fileLine, true);
25
        }
26
27
        $line = $fileLines[$key];
28
        $trimmedLine = trim($line);
29
        $countOfRowIndents = YamlService::rowIndentsOf($line);
30
        $explodedLine = explode(':', $line);
31
32
        // empty line
33
        if ($trimmedLine === '') {
34
            $fileRows = array_keys($fileLines);
35
            $lastFileRow = end($fileRows);
36
            /* set comment line indents by next non-empty line, e.g
37
                (empty line)
38
                # comment line
39
                (empty line)
40
                foo: bar
41
            */
42
            if ($isCommentLine && $lastFileRow !== $key) {
43
                $key++;
44
                return $this->getRightFileLines($fileLines, $key, $countOfIndents, $fileLine, true);
45
            }
46
47
            $correctIndents = $this->getCorrectIndents(0);
48
            $trimmedFileLine = trim($fileLine);
49
50
            return $correctIndents . $trimmedFileLine;
51
        }
52
53
        // the highest parent
54
        if ($countOfRowIndents === 0) {
55
            // line is directive
56
            if (YamlService::hasLineThreeDashesOnStartOfLine($trimmedLine)) {
57
                $correctIndents = $this->getCorrectIndents($countOfRowIndents);
58
                $trimmedFileLine = trim($fileLine);
59
60
                return $correctIndents . $trimmedFileLine;
61
            }
62
63
            // parent start as array, e.g. "- foo: bar"
64
            // skip comment line because we want result after this condition
65
            if ($isCommentLine === false && YamlService::isLineStartOfArrayWithKeyAndValue($trimmedLine)) {
66
                return $this->getCorrectLineForArrayWithKeyAndValue($line, $fileLines, $key, $countOfIndents, $fileLine, $isCommentLine);
67
            }
68
69
            $correctIndents = $this->getCorrectIndents($countOfRowIndents);
70
            $trimmedFileLine = trim($fileLine);
71
72
            return $correctIndents . $trimmedFileLine;
73
        }
74
75
        // line start of array, e.g. "- foo: bar" or "- foo" or "- { foo: bar }"
76
        if (YamlService::isLineStartOfArrayWithKeyAndValue($trimmedLine)) {
77
            return $this->getCorrectLineForArrayWithKeyAndValue($line, $fileLines, $key, $countOfIndents, $fileLine, $isCommentLine);
78
        }
79
80
        // children of array, description over name of function
81
        if ($this->belongLineToArray($fileLines, $key)) {
82
            $countOfParents = $this->getCountOfParentsForLine($fileLines, $key);
83
            $correctIndents = $this->getCorrectIndents($countOfParents * $countOfIndents);
84
            $trimmedFileLine = trim($fileLine);
85
86
            return $correctIndents . $trimmedFileLine;
87
        }
88
89
        // line without ':', e.g. array or string
90
        if (array_key_exists(1, $explodedLine) === false) {
91
            // is multidimensional array?
92
            if ($trimmedLine === '-') {
93
                $countOfParents = $this->getCountOfParentsForLine($fileLines, $key);
94
95
                $correctIndents = $this->getCorrectIndents($countOfParents * $countOfIndents);
96
                $trimmedFileLine = trim($fileLine);
97
98
                return $correctIndents . $trimmedFileLine;
99
            }
100
101
            // is array or string?
102
            $countOfParents = $this->getCountOfParentsForLine($fileLines, $key);
103
            $correctIndents = $this->getCorrectIndents($countOfParents * $countOfIndents);
104
            $trimmedFileLine = trim($fileLine);
105
106
            return $correctIndents . $trimmedFileLine;
107
        }
108
109
        $lineValue = $explodedLine[1];
110
        $trimmedLineValue = trim($lineValue);
111
112
        // parent, not comment line
113
        if ($isCommentLine === false && ($trimmedLineValue === '' || YamlService::isValueReuseVariable($trimmedLineValue))) {
114
            $nextLine = $fileLines[$key + 1];
115
            if (YamlService::rowIndentsOf($nextLine) > $countOfRowIndents) {
116
                $countOfParents = $this->getCountOfParentsForLine($fileLines, $key);
117
118
                $correctIndents = $this->getCorrectIndents($countOfParents * $countOfIndents);
119
                $trimmedFileLine = trim($fileLine);
120
121
                return $correctIndents . $trimmedFileLine;
122
            }
123
        }
124
125
        $countOfParents = $this->getCountOfParentsForLine($fileLines, $key);
126
        $correctIndents = $this->getCorrectIndents($countOfParents * $countOfIndents);
127
        $trimmedFileLine = trim($fileLine);
128
129
        return $correctIndents . $trimmedFileLine;
130
    }
131
132
    /**
133
     * @param int $countOfIndents
134
     * @return string
135
     */
136
    private function getCorrectIndents($countOfIndents)
137
    {
138
        return str_repeat(' ', $countOfIndents);
139
    }
140
141
    /**
142
     * Belong line to children of array, e.g.
143
     * - foo: bar
144
     *   baz: qux
145
     *   quux: quuz
146
     *   etc.: etc.
147
     *
148
     * @param string[] $fileLines
149
     * @param int $key
150
     * @return bool
151
     */
152
    private function belongLineToArray(array $fileLines, $key)
153
    {
154
        while ($key >= 0) {
155
            $line = $fileLines[$key];
156
            $key--;
157
            $prevLine = $fileLines[$key];
158
            $trimmedPrevLine = trim($prevLine);
159
160
            if (YamlService::hasLineDashOnStartOfLine($trimmedPrevLine)) {
161
                $prevLine = preg_replace('/-/', ' ', $prevLine, 1); // replace '-' for space
162
            }
163
164
            if (YamlService::rowIndentsOf($prevLine) === YamlService::rowIndentsOf($line)) {
165
                if (YamlService::isLineStartOfArrayWithKeyAndValue($trimmedPrevLine)) {
166
                    return true;
167
                }
168
            } else {
169
                break;
170
            }
171
        }
172
173
        return false;
174
    }
175
176
    /**
177
     * line start of array, e.g. "- foo: bar" or "- foo" or "- { foo: bar }"
178
     *
179
     * @param string $line
180
     * @param string[] $fileLines
181
     * @param int $key
182
     * @param int $countOfIndents
183
     * @param string $fileLine current checked line in loop
184
     * @param bool $isCommentLine
185
     * @return string
186
     */
187
    private function getCorrectLineForArrayWithKeyAndValue($line, array $fileLines, $key, $countOfIndents, $fileLine, $isCommentLine)
188
    {
189
        $lineWithReplacedDashToSpace = preg_replace('/-/', ' ', $line, 1);
190
        $trimmedLineWithoutDash = trim($lineWithReplacedDashToSpace);
191
192
        $countOfParents = $this->getCountOfParentsForLine($fileLines, $key);
193
        $correctIndentsOnStartOfLine = $this->getCorrectIndents($countOfParents * $countOfIndents);
194
195
        $trimmedFileLine = trim($fileLine);
196
        if ($isCommentLine) {
197
            return $correctIndentsOnStartOfLine . $trimmedFileLine;
198
        }
199
200
        // solution "- { foo: bar }"
201
        if (YamlService::isCurlyBracketInStartOfString($trimmedLineWithoutDash)) {
202
            $correctIndentsBetweenDashAndBracket = $this->getCorrectIndents(1);
203
204
            return $correctIndentsOnStartOfLine . '-' . $correctIndentsBetweenDashAndBracket . $trimmedLineWithoutDash;
205
        }
206
207
        // solution "- foo" (single value of an array)
208
        if (YamlService::isKeyInStartOfString($trimmedLineWithoutDash) === false) {
209
            $correctIndentsBetweenDashAndKey = $this->getCorrectIndents(1);
210
211
            return $correctIndentsOnStartOfLine . '-' . $correctIndentsBetweenDashAndKey . $trimmedLineWithoutDash;
212
        }
213
214
        /**
215
         * solution for one or more values in array
216
         * "- foo: bar"
217
         * "  baz: qux"
218
         */
219
        $correctIndentsBetweenDashAndKey = $this->getCorrectIndents($countOfIndents - 1); // 1 space is dash, dash is as indent
220
221
        return $correctIndentsOnStartOfLine . '-' . $correctIndentsBetweenDashAndKey . $trimmedLineWithoutDash;
222
    }
223
224
    /**
225
     * Go back until deepest parent and count them
226
     *
227
     * @param string[] $fileLines
228
     * @param int $key
229
     * @return int
230
     *
231
     * @SuppressWarnings("CyclomaticComplexity")
232
     * @SuppressWarnings("ExcessiveMethodLength")
233
     */
234
    private function getCountOfParentsForLine(array $fileLines, $key)
235
    {
236
        $countOfParents = 0;
237
        $line = $fileLines[$key];
238
        $originalLine = $line;
239
        $countOfRowIndents = YamlService::rowIndentsOf($line);
240
        $trimmedLine = trim($line);
241
        $isArrayLine = YamlService::hasLineDashOnStartOfLine($trimmedLine);
242
243
        while ($key > 0) {
244
            $key--;
245
            $prevLine = $fileLines[$key];
246
            $trimmedPrevLine = trim($prevLine);
247
            $isPrevLineArrayLine = YamlService::hasLineDashOnStartOfLine($trimmedPrevLine);
248
            $countOfPrevRowIndents = YamlService::rowIndentsOf($prevLine);
249
250
            // ignore comment line and empty line
251
            if ($trimmedPrevLine === '' || YamlService::isLineComment($prevLine)) {
252
                continue;
253
            }
254
255
            if (/* is start of array in array, e.g.
256
                   foo:
257
                     - bar:
258
                       - 'any text'
259
                */
260
                ($isArrayLine && $countOfPrevRowIndents < $countOfRowIndents && $isPrevLineArrayLine) ||
261
                /* is start of array, e.g.
262
                   foo:
263
                     - bar: baz
264
                */
265
                ($isArrayLine && $countOfPrevRowIndents <= $countOfRowIndents && $isPrevLineArrayLine === false) ||
266
                /* is classic hierarchy, e.g.
267
                   foo:
268
                     bar: baz
269
                */
270
                ($isArrayLine === false && $countOfPrevRowIndents < $countOfRowIndents)
271
            ) {
272
                $line = $fileLines[$key];
273
                $countOfRowIndents = YamlService::rowIndentsOf($line);
274
                $trimmedLine = trim($line);
275
                $isArrayLine = YamlService::hasLineDashOnStartOfLine($trimmedLine);
276
277
                $countOfParents++;
278
279
                /* nested hierarchy in array fix, eg.
280
                   - foo:
281
                       nested: value
282
                     bar: baz
283
                */
284
                if ($isArrayLine && YamlService::isLineOpeningAnArray($trimmedLine) && YamlService::keyIndentsOf($originalLine) > YamlService::keyIndentsOf($line)) {
285
                    $countOfParents++;
286
                }
287
            }
288
289
            // if line has zero counts of indents then it's highest parent and should be ended
290
            if ($countOfRowIndents === 0) {
291
                // find parent if line belong to array, if it exists then add one parent to count of parents variable
292
                if (YamlService::isLineStartOfArrayWithKeyAndValue($trimmedLine)) {
293
                    while ($key > 0) {
294
                        $key--;
295
                        $prevLine = $fileLines[$key];
296
                        $trimmedPrevLine = trim($prevLine);
297
                        if ($trimmedPrevLine === '' || YamlService::isLineComment($prevLine)) {
298
                            continue;
299
                        }
300
301
                        $countOfRowIndents = YamlService::rowIndentsOf($prevLine);
302
                        $explodedPrevLine = explode(':', $prevLine);
303
                        if ($countOfRowIndents === 0 && array_key_exists(1, $explodedPrevLine) && trim($explodedPrevLine[1]) === '') {
304
                            $countOfParents++;
305
306
                            break;
307
                        }
308
                    }
309
                }
310
311
                break;
312
            }
313
        }
314
315
        return $countOfParents;
316
    }
317
}
318