Completed
Pull Request — master (#27)
by Petr
05:25
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 = strlen($line) - strlen(ltrim($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
            $countOfNextRowIndents = strlen($nextLine) - strlen(ltrim($nextLine));
116
            if ($countOfNextRowIndents > $countOfRowIndents) {
117
                $countOfParents = $this->getCountOfParentsForLine($fileLines, $key);
118
119
                $correctIndents = $this->getCorrectIndents($countOfParents * $countOfIndents);
120
                $trimmedFileLine = trim($fileLine);
121
122
                return $correctIndents . $trimmedFileLine;
123
            }
124
        }
125
126
        $countOfParents = $this->getCountOfParentsForLine($fileLines, $key);
127
        $correctIndents = $this->getCorrectIndents($countOfParents * $countOfIndents);
128
        $trimmedFileLine = trim($fileLine);
129
130
        return $correctIndents . $trimmedFileLine;
131
    }
132
133
    /**
134
     * @param int $countOfIndents
135
     * @return string
136
     */
137
    private function getCorrectIndents($countOfIndents)
138
    {
139
        return str_repeat(' ', $countOfIndents);
140
    }
141
142
    /**
143
     * Belong line to children of array, e.g.
144
     * - foo: bar
145
     *   baz: qux
146
     *   quux: quuz
147
     *   etc.: etc.
148
     *
149
     * @param string[] $fileLines
150
     * @param int $key
151
     * @return bool
152
     */
153
    private function belongLineToArray(array $fileLines, $key)
154
    {
155
        while ($key >= 0) {
156
            $line = $fileLines[$key];
157
            $countOfRowIndents = strlen($line) - strlen(ltrim($line));
158
159
            $key--;
160
            $prevLine = $fileLines[$key];
161
            $trimmedPrevLine = trim($prevLine);
162
163
            if (YamlService::hasLineDashOnStartOfLine($trimmedPrevLine)) {
164
                $prevLine = preg_replace('/-/', ' ', $prevLine, 1); // replace '-' for space
165
            }
166
167
            $countOfPrevRowIndents = strlen($prevLine) - strlen(ltrim($prevLine));
168
169
            if ($countOfPrevRowIndents === $countOfRowIndents) {
170
                if (YamlService::isLineStartOfArrayWithKeyAndValue($trimmedPrevLine)) {
171
                    return true;
172
                }
173
            } else {
174
                break;
175
            }
176
        }
177
178
        return false;
179
    }
180
181
    /**
182
     * line start of array, e.g. "- foo: bar" or "- foo" or "- { foo: bar }"
183
     *
184
     * @param string $line
185
     * @param string[] $fileLines
186
     * @param int $key
187
     * @param int $countOfIndents
188
     * @param string $fileLine current checked line in loop
189
     * @param bool $isCommentLine
190
     * @return string
191
     */
192
    private function getCorrectLineForArrayWithKeyAndValue($line, array $fileLines, $key, $countOfIndents, $fileLine, $isCommentLine)
193
    {
194
        $lineWithReplacedDashToSpace = preg_replace('/-/', ' ', $line, 1);
195
        $trimmedLineWithoutDash = trim($lineWithReplacedDashToSpace);
196
197
        $countOfParents = $this->getCountOfParentsForLine($fileLines, $key);
198
        $correctIndentsOnStartOfLine = $this->getCorrectIndents($countOfParents * $countOfIndents);
199
200
        $trimmedFileLine = trim($fileLine);
201
        if ($isCommentLine) {
202
            return $correctIndentsOnStartOfLine . $trimmedFileLine;
203
        }
204
205
        // solution "- { foo: bar }"
206
        if (YamlService::isCurlyBracketInStartOfString($trimmedLineWithoutDash)) {
207
            $correctIndentsBetweenDashAndBracket = $this->getCorrectIndents(1);
208
209
            return $correctIndentsOnStartOfLine . '-' . $correctIndentsBetweenDashAndBracket . $trimmedLineWithoutDash;
210
        }
211
212
        // solution "- foo" (single value of an array)
213
        if (!YamlService::isKeyInStartOfString($trimmedLineWithoutDash)) {
214
            $correctIndentsBetweenDashAndKey = $this->getCorrectIndents(1);
215
216
            return $correctIndentsOnStartOfLine . '-' . $correctIndentsBetweenDashAndKey . $trimmedLineWithoutDash;
217
        }
218
219
        /**
220
         * solution for one or more values in array
221
         * "- foo: bar"
222
         * "  baz: qux"
223
         */
224
        $correctIndentsBetweenDashAndKey = $this->getCorrectIndents($countOfIndents - 1); // 1 space is dash, dash is as indent
225
226
        return $correctIndentsOnStartOfLine . '-' . $correctIndentsBetweenDashAndKey . $trimmedLineWithoutDash;
227
    }
228
229
    /**
230
     * Go back until deepest parent and count them
231
     *
232
     * @param string[] $fileLines
233
     * @param int $key
234
     * @return int
235
     *
236
     * @SuppressWarnings("CyclomaticComplexity")
237
     */
238
    private function getCountOfParentsForLine(array $fileLines, $key)
239
    {
240
        $countOfParents = 0;
241
        $line = $fileLines[$key];
242
        $countOfRowIndents = strlen($line) - strlen(ltrim($line));
243
        $trimmedLine = trim($line);
244
        $isArrayLine = YamlService::hasLineDashOnStartOfLine($trimmedLine);
245
246
        while ($key > 0) {
247
            $key--;
248
            $prevLine = $fileLines[$key];
249
            $trimmedPrevLine = trim($prevLine);
250
            $isPrevLineArrayLine = YamlService::hasLineDashOnStartOfLine($trimmedPrevLine);
251
            $countOfPrevRowIndents = strlen($prevLine) - strlen(ltrim($prevLine));
252
253
            // ignore comment line and empty line
254
            if ($trimmedPrevLine === '' || YamlService::isLineComment($prevLine)) {
255
                continue;
256
            }
257
258
            if (/* is start of array in array, e.g.
259
                   foo:
260
                     - bar:
261
                       - 'any text'
262
                */
263
                ($isArrayLine && $countOfPrevRowIndents < $countOfRowIndents && $isPrevLineArrayLine) ||
264
                /* is start of array, e.g.
265
                   foo:
266
                     - bar: baz
267
                */
268
                ($isArrayLine && $countOfPrevRowIndents <= $countOfRowIndents && $isPrevLineArrayLine === false) ||
269
                /* is classic hierarchy, e.g.
270
                   foo:
271
                     bar: baz
272
                */
273
                ($isArrayLine === false && $countOfPrevRowIndents < $countOfRowIndents)
274
            ) {
275
                $line = $fileLines[$key];
276
                $countOfRowIndents = strlen($line) - strlen(ltrim($line));
277
                $trimmedLine = trim($line);
278
                $isArrayLine = YamlService::hasLineDashOnStartOfLine($trimmedLine);
279
280
                $countOfParents++;
281
            }
282
283
            // if line has zero counts of indents then it's highest parent and should be ended
284
            if ($countOfRowIndents === 0) {
285
                // find parent if line belong to array, if it exists then add one parent to count of parents variable
286
                if (YamlService::isLineStartOfArrayWithKeyAndValue($trimmedLine)) {
287
                    while ($key > 0) {
288
                        $key--;
289
                        $prevLine = $fileLines[$key];
290
                        $trimmedPrevLine = trim($prevLine);
291
                        if ($trimmedPrevLine === '' || YamlService::isLineComment($prevLine)) {
292
                            continue;
293
                        }
294
295
                        $countOfRowIndents = strlen($prevLine) - strlen(ltrim($prevLine));
296
                        $explodedPrevLine = explode(':', $prevLine);
297
                        if ($countOfRowIndents === 0 && array_key_exists(1, $explodedPrevLine) && trim($explodedPrevLine[1]) === '') {
298
                            $countOfParents++;
299
300
                            break;
301
                        }
302
                    }
303
                }
304
305
                break;
306
            }
307
        }
308
309
        return $countOfParents;
310
    }
311
}
312