Passed
Push — master ( d0bef4...166358 )
by Vitaly
03:57
created

StructureSorter::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 5
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 3
nc 1
nop 2
1
<?php declare(strict_types=1);
2
/**
3
 * Created by Vitaly Iegorov <[email protected]>.
4
 * on 05.04.17 at 15:18
5
 */
6
7
namespace samsonframework\stringconditiontree;
8
9
/**
10
 * Parametrized strings sorting.
11
 *
12
 * @author Vitaly Egorov <[email protected]>
13
 */
14
class StructureSorter
15
{
16
    /** @var string Parametrized string start marker */
17
    protected $parameterStartMarker;
18
19
    /** @var string Parametrized string end marker */
20
    protected $parameterEndMarker;
21
22
    /**
23
     * StructureSorter constructor.
24
     *
25
     * @param string $parameterStartMarker Parametrized string start marker
26
     * @param string $parameterEndMarker Parametrized string end marker
27
     */
28
    public function __construct(string $parameterStartMarker, string $parameterEndMarker)
29
    {
30
        $this->parameterStartMarker = $parameterStartMarker;
31
        $this->parameterEndMarker = $parameterEndMarker;
32
    }
33
34
    /**
35
     * Sort strings array considering PCG and NPCG string structure.
36
     *
37
     * @param array $input Input array for sorting
38
     *
39
     * @return array Sorted keys array
40
     */
41
    public function sortArrayByKeys(array $input): array
42
    {
43
        // Convert string array keys into structure arrays
44
        $prefixes = array_map([$this, 'getPrefixStructure'], array_keys($input));
45
46
        // Sort parametrized string array according sorting rules
47
        usort($prefixes, [$this, 'compareStringStructure']);
48
49
        // Restore initial strings sub-arrays
50
        $result = [];
51
        foreach ($prefixes as $sortingData) {
52
            $result[$sortingData[0][2]] = $input[$sortingData[0][2]];
53
        }
54
        return $result;
55
    }
56
57
    /**
58
     * Build string character group structure considering parametrized
59
     * and not parametrized character groups and their length(PCG, NPCG).
60
     *
61
     * @param string $prefix Prefix string
62
     *
63
     * @return array String character groups structure
64
     */
65
    protected function getPrefixStructure(string $prefix): array
66
    {
67
        /** @var array $structureMatrix String PCG(0)/NPCG(1) structure matrix for comparison */
68
        $structureMatrix = [];
69
70
        // Flags for showing current string character group
71
        /** @var bool $isPCG Flags showing PCG started */
72
        $isPCG = false;
73
        /** @var bool $isNPCG Flags showing NPCG started */
74
        $isNPCG = true;
75
76
        // Pointer to current CG to count string NPCG length
77
        $currentCG = 0;
78
79
        /**
80
         * TODO: Try to find PCG filter :... pattern and process it also as
81
         * PCG with filters should be prioritized over PSG without filter
82
         * even if filter is .*
83
         */
84
85
        // Iterate string by characters
86
        for ($i = 0, $length = strlen($prefix); $i < $length; $i++) {
87
            if (!$isPCG && $prefix{$i} === $this->parameterStartMarker) {
88
                $isPCG = true;
89
                $isNPCG = false;
90
                $structureMatrix[] = [0, 0, $prefix];
91
                $currentCG = &$structureMatrix[count($structureMatrix) - 1][1];
92
            } elseif ($isPCG && $prefix{$i} === $this->parameterEndMarker) {
93
                $isPCG = false;
94
                $isNPCG = true;
95
            } elseif ($isNPCG) {
96
                $isNPCG = false;
97
                $structureMatrix[] = [1, 0, $prefix];
98
                $currentCG = &$structureMatrix[count($structureMatrix) - 1][1];
99
            }
100
101
            // Store current character group length
102
            $currentCG++;
103
        }
104
105
        return $structureMatrix;
106
    }
107
108
    /**
109
     * Compare string structures.
110
     *
111
     * @param array $initial  Initial string structure
112
     * @param array $compared Compared string structure
113
     *
114
     * @return int Result of array elements comparison
115
     */
116
    protected function compareStringStructure(array $initial, array $compared): int
117
    {
118
        $maxStructureSize = max(count($initial), count($compared));
119
120
        // Make structures same size preserving previous existing structure value
121
        for ($i = 1; $i < $maxStructureSize; $i++) {
122
            if (!array_key_exists($i, $initial)) {
123
                $initial[$i] = $initial[$i - 1];
124
            }
125
            if (!array_key_exists($i, $compared)) {
126
                $compared[$i] = $compared[$i - 1];
127
            }
128
        }
129
130
        // Iterate every structure group
131
        for ($i = 0; $i < $maxStructureSize; $i++) {
132
            // If initial structure has NPCG than it has higher priority
133
            if ($initial[$i][0] > $compared[$i][0]) {
134
                return -1;
135
            }
136
137
            // If compared structure has NPCG than it has higher priority
138
            if ($initial[$i][0] < $compared[$i][0]) {
139
                return 1;
140
            }
141
142
            // Compare NOT starting NPCG length
143
            if ($i > 0 && $initial[$i][0] === 1) {
144
                if ($initial[$i][1] > $compared[$i][1]) {
145
                    return -1;
146
                }
147
148
                if ($initial[$i][1] < $compared[$i][1]) {
149
                    return 1;
150
                }
151
            }
152
153
            // They are equal continue to next structure group comparison
154
        }
155
156
        // If both structures are equal compare lengths of NPCG
157 View Code Duplication
        for ($i = 0; $i < $maxStructureSize; $i++) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
158
            // If current CG is NPCG
159
            if ($initial[$i][0] === 1) {
160
                if ($initial[$i][1] > $compared[$i][1]) {
161
                    return 1;
162
                }
163
164
                if ($initial[$i][1] < $compared[$i][1]) {
165
                    return -1;
166
                }
167
            }
168
169
            // Current NPCG character groups have equal length - continue
170
        }
171
172
        // If both structures are equal and NPCG length are equal - compare lengths of PCG
173 View Code Duplication
        for ($i = 0; $i < $maxStructureSize; $i++) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
174
            // If current CG is PCG
175
            if ($initial[$i][0] === 0) {
176
                if ($initial[$i][1] > $compared[$i][1]) {
177
                    return -1;
178
                }
179
180
                if ($initial[$i][1] < $compared[$i][1]) {
181
                    return 1;
182
                }
183
            }
184
185
            // Current PCG character groups have equal length - continue
186
        }
187
188
        // Structures are absolutely equal
189
        return 0;
190
    }
191
}
192