Passed
Push — master ( 9a9b0b...b778d8 )
by Peter
08:40
created

YamlParser::getYamlParsedDataFromFile()   C

Complexity

Conditions 13
Paths 9

Size

Total Lines 57
Code Lines 32

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 33
CRAP Score 13

Importance

Changes 0
Metric Value
eloc 32
c 0
b 0
f 0
dl 0
loc 57
ccs 33
cts 33
cp 1
rs 6.6166
cc 13
nc 9
nop 1
crap 13

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
declare(strict_types=1);
4
5
namespace YamlStandards\Model\Component\Parser;
6
7
use YamlStandards\Model\Component\YamlService;
8
9
class YamlParser
10
{
11
    /**
12
     * Go back until deepest parent and count them
13
     *
14
     * @param string[] $yamlLines
15
     * @param int $key
16
     * @return int
17
     */
18 12
    public static function getCountOfParentsForLine(array $yamlLines, int $key): int
19
    {
20 12
        $countOfParents = 0;
21 12
        $line = $yamlLines[$key];
22 12
        $originalLine = $line;
23 12
        $countOfRowIndents = YamlService::rowIndentsOf($line);
24 12
        $trimmedLine = trim($line);
25 12
        $isArrayLine = YamlService::hasLineDashOnStartOfLine($trimmedLine);
26
27 12
        while ($key > 0) {
28 12
            $currentLine = $yamlLines[$key];
29 12
            $countOfCurrentRowIndents = YamlService::rowIndentsOf($currentLine);
30 12
            $key--;
31 12
            $prevLine = $yamlLines[$key];
32 12
            $trimmedPrevLine = trim($prevLine);
33 12
            $isPrevLineArrayLine = YamlService::hasLineDashOnStartOfLine($trimmedPrevLine);
34 12
            $countOfPrevRowIndents = YamlService::rowIndentsOf($prevLine);
35
36
            // ignore comment line and empty line
37 12
            if (YamlService::isLineBlank($prevLine) || YamlService::isLineComment($prevLine)) {
38 6
                continue;
39
            }
40
41 12
            if (self::isPrevLineNextParent($isArrayLine, $countOfPrevRowIndents, $countOfRowIndents, $isPrevLineArrayLine)) {
42 12
                $line = $yamlLines[$key];
43 12
                $countOfRowIndents = YamlService::rowIndentsOf($line);
44 12
                $trimmedLine = trim($line);
45 12
                $isArrayLine = YamlService::hasLineDashOnStartOfLine($trimmedLine);
46
47
                /*
48
                 * array has array values at beginning and is not first element in array, e.g.
49
                 *  -  pathsToCheck:
50
                 *      - path/to/file
51
                 */
52 12
                if ($isArrayLine &&
53 12
                    $countOfParents > 0 &&
54 12
                    YamlService::isLineOpeningAnArray($trimmedLine)
55
                ) {
56 4
                    $countOfParents--;
57
                }
58
59 12
                $countOfParents++;
60
61
                /**
62
                 * nested hierarchy in array fix, eg.
63
                 * - foo:
64
                 *     nested: value
65
                 *   bar: baz
66
                 */
67 12
                if ($isArrayLine && YamlService::isLineOpeningAnArray($trimmedLine) && YamlService::keyIndentsOf($originalLine) > YamlService::keyIndentsOf($line)) {
68 4
                    $countOfParents++;
69
                }
70
            }
71
72
            // if line has zero counts of indents then it's highest parent and should be ended
73 12
            if ($countOfRowIndents === 0) {
74
                /**
75
                 * find parent if line belong to array, if it exists then add one parent to count of parents variable, e.g.
76
                 * foo:
77
                 * - bar
78
                 */
79 12
                if (YamlService::isLineStartOfArrayWithKeyAndValue($trimmedLine)) {
80 4
                    while ($key >= 0) {
81 4
                        $prevLine = $yamlLines[$key];
82 4
                        $countOfPrevRowIndents = YamlService::rowIndentsOf($prevLine);
83 4
                        if (YamlService::isLineBlank($prevLine) || YamlService::isLineComment($prevLine)) {
84 3
                            $key--;
85 3
                            continue;
86
                        }
87
88
                        /**
89
                         * 'qux' is highest parent, so skip this, e.g.
90
                         * - foo:
91
                         *      bar: baz
92
                         * - qux:
93
                         *      - quux: quuz
94
                         */
95 4
                        if ($countOfPrevRowIndents > $countOfCurrentRowIndents) {
96 4
                            break;
97
                        }
98
99 4
                        if ($countOfPrevRowIndents === 0 &&
100 4
                            $countOfPrevRowIndents === $countOfCurrentRowIndents &&
101 4
                            YamlService::hasLineColon($prevLine) &&
102 4
                            YamlService::hasLineValue($prevLine) === false
103
                        ) {
104 3
                            $countOfParents++;
105
106 3
                            break;
107
                        }
108
109 4
                        $currentLine = $yamlLines[$key];
110 4
                        $countOfCurrentRowIndents = YamlService::rowIndentsOf($currentLine);
111 4
                        $key--;
112
                    }
113
                }
114
115 12
                break;
116
            }
117
        }
118
119 12
        return $countOfParents;
120
    }
121
122
    /**
123
     * @param string $pathToYamlFile
124
     * @return string[]
125
     */
126 6
    public static function getYamlParsedDataFromFile(string $pathToYamlFile): array
127
    {
128 6
        $fileContent = file_get_contents($pathToYamlFile);
129 6
        $fileContent = str_replace("\r", '', $fileContent); // remove carriage returns
130 6
        $yamlLines = explode("\n", $fileContent);
131 6
        $yamlLines = YamlService::mergeMultipleValueLinesTogether($yamlLines);
132 6
        $parentsData = [];
133
134 6
        foreach ($yamlLines as $key => $yamlLine) {
135 6
            $yamlParserLineData = new YamlParserLineData($yamlLines, $key);
136 6
            $yamlLine = YamlParserService::addBlankLineIndentsByHisParent($yamlLines, $key);
137 6
            $currentLineWithoutDash = str_replace('-', ' ', $yamlLine);
138 6
            $countOfCurrentRowIndents = YamlService::rowIndentsOf($currentLineWithoutDash);
139 6
            while ($key > 0) {
140
                /**
141
                 * don't associate blank line to previous parent too, e.g.:
142
                 *   -   foo: bar
143
                 * (blank line)⬅
144
                 *   -   baz: qux
145
                 */
146 6
                $nextLine = YamlService::getNextNonCommentAndNonBlankLine($yamlLines, $key);
147 6
                if ((YamlService::isLineBlank($yamlLines[$key]) || YamlService::isLineComment($yamlLines[$key])) &&
148 6
                    $nextLine !== null && YamlService::isLineStartOfArrayWithKeyAndValue(trim($nextLine)) &&
149 6
                    YamlService::rowIndentsOf($nextLine) === 0) {
150 2
                    break;
151
                }
152
153 6
                $key--;
154 6
                $prevLine = $yamlLines[$key];
155 6
                $prevLineWithoutDash = str_replace('-', ' ', $prevLine);
156 6
                $countOfPrevRowIndents = YamlService::rowIndentsOf($prevLineWithoutDash);
157
158
                // ignore comment line and empty line
159 6
                if (YamlService::isLineBlank($prevLine) || YamlService::isLineComment($prevLine)) {
160 6
                    continue;
161
                }
162
163 6
                if ($countOfPrevRowIndents <= $countOfCurrentRowIndents) {
164 6
                    if ($countOfPrevRowIndents < $countOfCurrentRowIndents) {
165 6
                        $yamlParserLineData->addLineKey($yamlLines, $key);
166
                    }
167 6
                    $yamlParserLineData->addArrayKeyWithValueToSeparatedArray($yamlLines, $key);
168
169 6
                    $countOfCurrentRowIndents = $countOfPrevRowIndents; // it's parent, so we want to only higher from him
170
                }
171
172 6
                if ($countOfCurrentRowIndents === 0) {
173 6
                    break;
174
                }
175
            }
176
177 6
            $parentsData[] = $yamlParserLineData->getPathToLineGradually();
178
        }
179
180 6
        $allParentsData = array_merge_recursive(...$parentsData); // add all data to one big array
181
182 6
        return $allParentsData;
183
    }
184
185
    /**
186
     * @param bool $isArrayLine
187
     * @param int $countOfPrevRowIndents
188
     * @param int $countOfRowIndents
189
     * @param bool $isPrevLineArrayLine
190
     * @return bool
191
     */
192 13
    private static function isPrevLineNextParent(bool $isArrayLine, int $countOfPrevRowIndents, int $countOfRowIndents, bool $isPrevLineArrayLine): bool
193
    {
194 13
        return self::isClassicHierarchy($isArrayLine, $countOfPrevRowIndents, $countOfRowIndents) ||
195 13
            self::isStartOfArray($isArrayLine, $countOfPrevRowIndents, $countOfRowIndents, $isPrevLineArrayLine) ||
196 13
            self::isStartOfArrayInArray($isArrayLine, $countOfPrevRowIndents, $countOfRowIndents, $isPrevLineArrayLine);
197
    }
198
199
    /**
200
     * @param bool $isArrayLine
201
     * @param int $countOfPrevRowIndents
202
     * @param int $countOfRowIndents
203
     * @return bool
204
     *
205
     * @example
206
     * foo:
207
     *     bar: baz
208
     */
209 14
    private static function isClassicHierarchy(bool $isArrayLine, int $countOfPrevRowIndents, int $countOfRowIndents): bool
210
    {
211 14
        return $isArrayLine === false && $countOfPrevRowIndents < $countOfRowIndents;
212
    }
213
214
    /**
215
     * @param bool $isArrayLine
216
     * @param int $countOfPrevRowIndents
217
     * @param int $countOfRowIndents
218
     * @param bool $isPrevLineArrayLine
219
     * @return bool
220
     *
221
     * @example
222
     * foo:
223
     *     - bar: baz
224
     */
225 14
    private static function isStartOfArray(bool $isArrayLine, int $countOfPrevRowIndents, int $countOfRowIndents, bool $isPrevLineArrayLine): bool
226
    {
227 14
        return $isArrayLine && $countOfPrevRowIndents <= $countOfRowIndents && $isPrevLineArrayLine === false;
228
    }
229
230
    /**
231
     * @param bool $isArrayLine
232
     * @param int $countOfPrevRowIndents
233
     * @param int $countOfRowIndents
234
     * @param bool $isPrevLineArrayLine
235
     * @return bool
236
     *
237
     * @example
238
     * foo:
239
     *     - bar:
240
     *         - 'any text'
241
     */
242 14
    private static function isStartOfArrayInArray(bool $isArrayLine, int $countOfPrevRowIndents, int $countOfRowIndents, bool $isPrevLineArrayLine): bool
243
    {
244 14
        return $isArrayLine && $countOfPrevRowIndents < $countOfRowIndents && $isPrevLineArrayLine;
245
    }
246
}
247