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

createRightSortedYamlLines()   C

Complexity

Conditions 15
Paths 135

Size

Total Lines 32
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 20
CRAP Score 15

Importance

Changes 2
Bugs 0 Features 0
Metric Value
eloc 19
c 2
b 0
f 0
dl 0
loc 32
ccs 20
cts 20
cp 1
rs 5.625
cc 15
nc 135
nop 1
crap 15

How to fix   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\YamlAlphabetical;
6
7
use YamlStandards\Model\Component\Parser\YamlParser;
8
use YamlStandards\Model\Component\Parser\YamlParserLineData;
9
use YamlStandards\Model\Component\YamlService;
10
11
class YamlAlphabeticalDataFactory
12
{
13
    public const REGEX_KEY_COMMON_LINE_WITH_NUMBER_AT_END = '/' . YamlParserLineData::KEY_COMMON_LINE . '\d+$/';
14
    public const REGEX_KEY_COMMENT_OR_EMPTY_LINE_WITH_NUMBER_AT_END = '/' . YamlParserLineData::KEY_COMMENT_OR_EMPTY_LINE . '\d+$/';
15
    public const REGEX_KEY_DASH_WITH_NUMBER_AT_END = '/' . YamlParserLineData::KEY_DASH . '\d+$/';
16
    public const REGEX_KEY_EMPTY_ARRAY_WITH_NUMBER_AT_END = '/' . YamlParserLineData::KEY_EMPTY_ARRAY . '\d+$/';
17
    public const REGEX_KEY_ARRAY_WITHOUT_KEY_WITH_NUMBER_AT_END = '/^' . YamlParserLineData::KEY_ARRAY_WITHOUT_KEY . '\d+/';
18
    public const REGEX_KEY_CURLY_BRACKETS_WITH_NUMBER_AT_END = '/' . YamlParserLineData::KEY_CURLY_BRACKETS . '\d+$/';
19
20
    public const REGEX_VALUE_EMPTY_LINE = '/' . YamlParserLineData::EMPTY_LINE_DEFAULT_VALUE . '$/';
21
22
    /**
23
     * @var int
24
     */
25
    private static $index;
26
27
    /**
28
     * @param string $pathToYamlFile
29
     * @param int $depth
30
     * @return string[]
31
     */
32 6
    public static function getCorrectYamlLines(string $pathToYamlFile, int $depth): array
33
    {
34 6
        self::$index = 0; // start from 0 in every file
35
36 6
        $yamlArrayData = YamlParser::getYamlParsedDataFromFile($pathToYamlFile);
37 6
        $yamlArrayDataSorted = self::sortArray($yamlArrayData, $depth);
38
39 6
        return self::createRightSortedYamlLines($yamlArrayDataSorted);
0 ignored issues
show
Bug Best Practice introduced by
The expression return self::createRight...s($yamlArrayDataSorted) returns an array which contains values of type array|string[] which are incompatible with the documented value type string.
Loading history...
40
    }
41
42
    /**
43
     * @param string[] $yamlArrayData
44
     * @param int $depth
45
     * @return string[]
46
     */
47 6
    private static function sortArray(array $yamlArrayData, int $depth): array
48
    {
49 6
        if ($depth > 0) {
50 6
            $yamlArrayData = self::sortArrayKeyWithUnderscoresAsFirst($yamlArrayData);
51
52 6
            if ($depth > 1) {
53 6
                foreach ($yamlArrayData as $key => $value) {
54 6
                    if (is_array($value)) {
55 6
                        $yamlArrayData[$key] = self::recursiveKsort($value, $depth);
56
                    }
57
                }
58
            }
59
        }
60
61 6
        return $yamlArrayData;
62
    }
63
64
    /**
65
     * @param string[] $yamlArrayData
66
     * @param int $depth
67
     * @param int $currentDepth
68
     * @return string[]
69
     */
70 6
    private static function recursiveKsort(array $yamlArrayData, int $depth, int $currentDepth = 1): array
71
    {
72 6
        $yamlArrayData = self::sortArrayKeyWithUnderscoresAsFirst($yamlArrayData);
73 6
        foreach ($yamlArrayData as $key => $value) {
74 6
            if (is_array($value)) {
75 6
                if ($currentDepth <= $depth) {
76 6
                    $yamlArrayData[$key] = self::recursiveKsort($value, $depth, $currentDepth + 1);
77
                }
78
            }
79
        }
80
81 6
        return $yamlArrayData;
82
    }
83
84
    /**
85
     * @param string[] $yamlArrayData
86
     * @return string[]|string[][]
87
     */
88 6
    private static function sortArrayKeyWithUnderscoresAsFirst(array $yamlArrayData): array
89
    {
90 6
        $arrayWithUnderscoreKeys = array_filter($yamlArrayData, [YamlService::class, 'hasArrayKeyUnderscoreAsFirstCharacter'], ARRAY_FILTER_USE_KEY);
91 6
        $arrayWithOtherKeys = array_filter($yamlArrayData, [YamlService::class, 'hasNotArrayKeyUnderscoreAsFirstCharacter'], ARRAY_FILTER_USE_KEY);
92
93 6
        uksort($arrayWithUnderscoreKeys, ['self', 'sortArrayAlphabetical']);
94 6
        uksort($arrayWithOtherKeys, ['self', 'sortArrayAlphabetical']);
95
96 6
        return array_merge($arrayWithUnderscoreKeys, $arrayWithOtherKeys);
97
    }
98
99
    /**
100
     * @param string $key1
101
     * @param string $key2
102
     * @return int
103
     */
104 6
    private static function sortArrayAlphabetical(string $key1, string $key2): int
105
    {
106
        // remove added text for empty line and comment line
107 6
        $key1WithoutNumberAtEnd = preg_replace(self::REGEX_KEY_COMMENT_OR_EMPTY_LINE_WITH_NUMBER_AT_END, '', $key1);
108 6
        $key2WithoutNumberAtEnd = preg_replace(self::REGEX_KEY_COMMENT_OR_EMPTY_LINE_WITH_NUMBER_AT_END, '', $key2);
109
110
        // add key number to end for fix situation when keys are same
111 6
        preg_match('/\d+$/', $key1WithoutNumberAtEnd, $key1NumberAtEnd);
112 6
        preg_match('/\d+$/', $key2WithoutNumberAtEnd, $key2NumberAtEnd);
113 6
        $key1NumberAtEnd = count($key1NumberAtEnd) === 0 ? 0 : reset($key1NumberAtEnd);
114 6
        $key2NumberAtEnd = count($key2NumberAtEnd) === 0 ? 0 : reset($key2NumberAtEnd);
115
116 6
        $key1WithoutNumberAtEnd = preg_match(self::REGEX_KEY_COMMON_LINE_WITH_NUMBER_AT_END, $key1WithoutNumberAtEnd) === 0 ? $key1WithoutNumberAtEnd : preg_replace(self::REGEX_KEY_COMMON_LINE_WITH_NUMBER_AT_END, '', $key1WithoutNumberAtEnd);
117 6
        $key1WithoutNumberAtEnd = preg_match(self::REGEX_KEY_ARRAY_WITHOUT_KEY_WITH_NUMBER_AT_END, $key1WithoutNumberAtEnd) === 0 ? $key1WithoutNumberAtEnd : preg_replace(self::REGEX_KEY_ARRAY_WITHOUT_KEY_WITH_NUMBER_AT_END, '', $key1WithoutNumberAtEnd);
118
119 6
        $key2WithoutNumberAtEnd = preg_match(self::REGEX_KEY_COMMON_LINE_WITH_NUMBER_AT_END, $key2WithoutNumberAtEnd) === 0 ? $key2WithoutNumberAtEnd : preg_replace(self::REGEX_KEY_COMMON_LINE_WITH_NUMBER_AT_END, '', $key2WithoutNumberAtEnd);
120 6
        $key2WithoutNumberAtEnd = preg_match(self::REGEX_KEY_ARRAY_WITHOUT_KEY_WITH_NUMBER_AT_END, $key2WithoutNumberAtEnd) === 0 ? $key2WithoutNumberAtEnd : preg_replace(self::REGEX_KEY_ARRAY_WITHOUT_KEY_WITH_NUMBER_AT_END, '', $key2WithoutNumberAtEnd);
121
122
        /*
123
         * add exclamation mark (!) to penultimate position in string for fix order for "dot" key scenario, e.g:
124
         * foo.bar:
125
         * foo.bar.baz:
126
         * ":" is in alphabetical higher as ".", https://s2799303.files.wordpress.com/2013/08/ascii-codes-table1.jpg
127
         */
128 6
        $key1WithoutNumberAtEnd = substr_replace($key1WithoutNumberAtEnd, '!', -1, 0);
129 6
        $key2WithoutNumberAtEnd = substr_replace($key2WithoutNumberAtEnd, '!', -1, 0);
130
131 6
        $key1WithoutNumberAtEnd .= $key1NumberAtEnd;
132 6
        $key2WithoutNumberAtEnd .= $key2NumberAtEnd;
133
134 6
        if ($key1WithoutNumberAtEnd === $key2WithoutNumberAtEnd) {
135 5
            return strnatcmp(trim($key2), trim($key1));
136
        }
137
138 6
        return strnatcmp(trim($key1WithoutNumberAtEnd), trim($key2WithoutNumberAtEnd));
139
    }
140
141
    /**
142
     * @param string[]|string[][] $sortedYamlData
143
     * @return string[]
144
     */
145 6
    private static function createRightSortedYamlLines(array $sortedYamlData): array
146
    {
147 6
        $rightSortedYamlLines = [];
148
149 6
        foreach ($sortedYamlData as $yamlKey => $yamlValue) {
150 6
            if (is_array($yamlValue) === false && ($yamlValue === YamlParserLineData::EMPTY_LINE_DEFAULT_VALUE || YamlService::isLineComment($yamlValue))) {
0 ignored issues
show
Bug introduced by
$yamlValue of type array is incompatible with the type string expected by parameter $yamlLine of YamlStandards\Model\Comp...ervice::isLineComment(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

150
            if (is_array($yamlValue) === false && ($yamlValue === YamlParserLineData::EMPTY_LINE_DEFAULT_VALUE || YamlService::isLineComment(/** @scrutinizer ignore-type */ $yamlValue))) {
Loading history...
151 6
                $rightSortedYamlLines[] = preg_match(self::REGEX_VALUE_EMPTY_LINE, $yamlValue) === 0 ? $yamlValue : preg_replace(self::REGEX_VALUE_EMPTY_LINE, '', $yamlValue);
0 ignored issues
show
Bug introduced by
$yamlValue of type array is incompatible with the type string expected by parameter $subject of preg_match(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

151
                $rightSortedYamlLines[] = preg_match(self::REGEX_VALUE_EMPTY_LINE, /** @scrutinizer ignore-type */ $yamlValue) === 0 ? $yamlValue : preg_replace(self::REGEX_VALUE_EMPTY_LINE, '', $yamlValue);
Loading history...
152
153 6
                continue;
154
            }
155
156 6
            $yamlKey = is_int($yamlKey) ? (string)$yamlKey : $yamlKey;
157 6
            if (preg_match(self::REGEX_KEY_COMMENT_OR_EMPTY_LINE_WITH_NUMBER_AT_END, $yamlKey) === 0 &&
158 6
                preg_match(self::REGEX_KEY_EMPTY_ARRAY_WITH_NUMBER_AT_END, $yamlKey) === 0
159
            ) {
160 6
                $key = preg_match(self::REGEX_KEY_COMMON_LINE_WITH_NUMBER_AT_END, $yamlKey) === 0 ? $yamlKey : preg_replace(self::REGEX_KEY_COMMON_LINE_WITH_NUMBER_AT_END, '', $yamlKey);
161 6
                $key = preg_match(self::REGEX_KEY_DASH_WITH_NUMBER_AT_END, $key) === 0 ? $key : preg_replace(self::REGEX_KEY_DASH_WITH_NUMBER_AT_END, '-', $key);
162 6
                $key = preg_match(self::REGEX_KEY_CURLY_BRACKETS_WITH_NUMBER_AT_END, $key) === 0 ? $key : preg_replace(self::REGEX_KEY_CURLY_BRACKETS_WITH_NUMBER_AT_END, '', $key);
163 6
                $key = preg_match(self::REGEX_KEY_ARRAY_WITHOUT_KEY_WITH_NUMBER_AT_END, $key) === 0 ? $key : preg_replace(self::REGEX_KEY_ARRAY_WITHOUT_KEY_WITH_NUMBER_AT_END, '', $key);
164 6
                $value = is_array($yamlValue) ? '' : $yamlValue;
165 6
                $rightSortedYamlLines[] = $key . $value;
166
167 6
                self::$index++;
168
            }
169
170 6
            if (is_array($yamlValue)) {
171 6
                $result = self::createRightSortedYamlLines($yamlValue);
172 6
                $rightSortedYamlLines = array_merge($rightSortedYamlLines, $result);
173
            }
174
        }
175
176 6
        return $rightSortedYamlLines;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $rightSortedYamlLines returns an array which contains values of type array|string[] which are incompatible with the documented value type string.
Loading history...
177
    }
178
}
179