Completed
Push — master ( e9cc16...40005e )
by Vitaly
02:15
created

StructureCollection::getCommonPrefixesCollection()   F

Complexity

Conditions 16
Paths 304

Size

Total Lines 86
Code Lines 41

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 39
CRAP Score 16.0296

Importance

Changes 0
Metric Value
dl 0
loc 86
ccs 39
cts 41
cp 0.9512
rs 3.7109
c 0
b 0
f 0
cc 16
eloc 41
nc 304
nop 0
crap 16.0296

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 declare(strict_types=1);
2
/**
3
 * Created by Vitaly Iegorov <[email protected]>.
4
 * on 08.04.17 at 09:08
5
 */
6
namespace samsonframework\stringconditiontree\string;
7
8
use samsonframework\stringconditiontree\AbstractIterable;
9
10
/**
11
 * Class StructureCollection
12
 *
13
 * @author Vitaly Egorov <[email protected]>
14
 */
15
class StructureCollection extends AbstractIterable
16
{
17
    /** string Internal collection name */
18
    protected const COLLECTION_NAME = 'structures';
19
20
    /** @var Structure[] */
21
    protected $structures = [];
22
23
    /**
24
     * Create structures collection from array of strings.
25
     *
26
     * @param array $strings Strings array
27
     *
28
     * @return StructureCollection StructureCollection instance
29
     *
30
     * @throws \InvalidArgumentException If collection variable is missing
31
     */
32 3
    public static function fromStringsArray(array $strings): StructureCollection
33
    {
34
        // Create internalCollection
35 3
        $structureCollection = new StructureCollection();
36 3
        foreach ($strings as $string) {
37 3
            $structureCollection->structures[$string] = new Structure($string);
38
        }
39
40 3
        return $structureCollection;
41
    }
42
43
    /**
44
     * Get collection of StructureCollection instances grouped by longest common prefixes.
45
     *
46
     * @return StructureCollection[] Longest common prefixes array of StructureCollection instances
47
     */
48 2
    public function getCommonPrefixesCollection(): array
49
    {
50 2
        $this->sort();
51
52
        /** @var StructureCollection[] $commonPrefixes */
53 2
        $commonPrefixes = [];
54
55
        /** @var Structure[] $usedStructures */
56 2
        $usedStructures = [];
57
58
        // Iterate sorted character group internalCollection
59 2
        foreach ($this->structures as $initialStructure) {
60 2
            $oneCommonPrefixFound = false;
61
            // Iterate all character group internalCollection again
62 2
            foreach ($this->structures as $comparedStructure) {
63
                // Ignore same internalCollection
64 2
                if ($initialStructure !== $comparedStructure) {
65 2
                    $foundPrefix = $initialStructure->getCommonPrefix($comparedStructure);
66
67
                    // If we have found common prefix between two structures
68 2
                    if ($foundPrefix !== '') {
69
                        /**
70
                         * Try to find if this prefix can be merged into already found common prefix
71
                         * as our structures collection is already sorted.
72
                         */
73 2
                        $foundPrefixStructure = new Structure($foundPrefix);
74 2
                        foreach ($commonPrefixes as $existingPrefix => $structures) {
75 2
                            $internalPrefix = (new Structure($existingPrefix))->getCommonPrefix($foundPrefixStructure);
76 2
                            if ($internalPrefix !== '') {
77 2
                                $foundPrefix = $internalPrefix;
78 2
                                break;
79
                            }
80
                        }
81
82
                        // Create new structure collection with common prefix
83 2
                        if (!array_key_exists($foundPrefix, $commonPrefixes)) {
84 2
                            $commonPrefixes[$foundPrefix] = new StructureCollection();
85
                        }
86
87 2
                        $foundInOtherCollection = in_array($comparedStructure, $usedStructures);
88
89 2
                        $newPrefix = substr($comparedStructure->getString(), strlen($foundPrefix));
90 2
                        if (!$foundInOtherCollection && strlen($newPrefix)) {
91 2
                            $usedStructures[] = $comparedStructure;
92
                            // Add structure to structure collection
93 2
                            $commonPrefixes[$foundPrefix]->addUniqueStructure(new Structure($newPrefix));
94
                        }
95
96 2
                        $oneCommonPrefixFound = true;
97
                    }
98
                }
99
            }
100
101 2
            if (!$oneCommonPrefixFound) {
102 1
                $foundPrefix = $initialStructure->getString();
103
104
                // Create new structure collection with common prefix
105 1
                if (!array_key_exists($foundPrefix, $commonPrefixes)) {
106 1
                    $commonPrefixes[$foundPrefix] = new StructureCollection();
107
                }
108
109 1
                $foundInOtherCollection = in_array($initialStructure, $usedStructures);
110
111 1
                $newPrefix = substr($initialStructure->getString(), strlen($foundPrefix));
112 1
                if (!$foundInOtherCollection && strlen($newPrefix)) {
113
                    $usedStructures[] = $initialStructure;
114
                    // Add structure to structure collection
115
                    $commonPrefixes[$foundPrefix]->addUniqueStructure(new Structure($newPrefix));
116
                }
117
            }
118
        }
119
120
        // Sort common prefixes
121 2
        $commonPrefixesCollection = new StructureCollection();
122 2
        foreach ($commonPrefixes as $prefix => $structures) {
123 2
            $commonPrefixesCollection->add(new Structure($prefix));
124
        }
125 2
        $commonPrefixesCollection->sort();
126
127 2
        $final = [];
128 2
        foreach ($commonPrefixesCollection as $prefix => $structureCollection) {
129 2
            $final[$prefix] = $commonPrefixes[$prefix];
130
        }
131
132 2
        return $final;
133
    }
134
135
    /**
136
     * Sort structures.
137
     *
138
     * @param bool $ascending Ascending sorting order
139
     *
140
     * @return array|Structure|Structure[]
141
     */
142
    protected function sort(bool $ascending = true)
143
    {
144
        // Sort internalCollection
145 2
        uasort($this->structures, function (Structure $initial, Structure $compared) {
146 2
            return $initial->compare($compared);
147 2
        });
148
149
        // Sort descending if needed
150 2
        $this->structures = $ascending ? array_reverse($this->structures) : $this->structures;
151 2
    }
152
153
    /**
154
     * Add only unique structure to collection.
155
     *
156
     * @param Structure $structure Added structure
157
     */
158 2
    public function addUniqueStructure(Structure $structure): void
159
    {
160 2
        if (!$this->has($structure)) {
161 2
            $this->add($structure);
162
        }
163 2
    }
164
165
    /**
166
     * @param Structure $structure
167
     *
168
     * @return bool
169
     */
170 2
    public function has(Structure $structure): bool
171
    {
172 2
        foreach ($this->structures as $comparedStructure) {
173 2
            if ($this->isSameStructure($structure, $comparedStructure)) {
174
                return true;
175
            }
176
        }
177
178 2
        return false;
179
    }
180
181
    /**
182
     * Compare two structures.
183
     *
184
     * @param Structure $initial Initial structure
185
     * @param Structure $compared Compared structure
186
     *
187
     * @return bool True is structures are equal
188
     */
189 2
    protected function isSameStructure(Structure $initial, Structure $compared): bool
190
    {
191 2
        return $initial->getString() === $compared->getString();
192
    }
193
194
    /**
195
     * Add structure to structure collection.
196
     *
197
     * @param Structure $structure Added structure
198
     */
199 2
    public function add(Structure $structure): void
200
    {
201 2
        $this->structures[$structure->getString()] = $structure;
202 2
    }
203
}
204