Completed
Push — master ( 24d488...605ec5 )
by Vitaly
05:14
created

Structure   A

Complexity

Total Complexity 14

Size/Duplication

Total Lines 125
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 2

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
wmc 14
lcom 1
cbo 2
dl 0
loc 125
ccs 32
cts 32
cp 1
rs 10
c 0
b 0
f 0

5 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 16 4
A compare() 0 21 3
A getShortestStructure() 0 5 2
B getCommonPrefix() 0 26 3
A isStringNotMatchingAnyCG() 0 4 2
1
<?php declare(strict_types=1);
2
/**
3
 * Created by Vitaly Iegorov <[email protected]>.
4
 * on 06.04.17 at 07:30
5
 */
6
namespace samsonframework\stringconditiontree\string;
7
8
/**
9
 * This class describes string character group structure(CGS).
10
 *
11
 * @author Vitaly Egorov <[email protected]>
12
 */
13
class Structure extends IterableStructure
14
{
15
    /** array Supported character group types */
16
    const CG_TYPES = [
17
        VariableFixedCG::class,
18
        VariableCG::class,
19
        FixedCG::class,
20
    ];
21
22
    /** @var string Input string */
23
    public $string;
24
25
    /**
26
     * Create string character group structure from string string.
27
     *
28
     * @param string $input Input string for string character group structure
29
     */
30 19
    public function __construct(string $input)
31
    {
32 19
        $this->string = $input;
33
34
        // Iterate until string is cleared
35 19
        while (strlen($input)) {
36 19
            foreach (self::CG_TYPES as $characterGroupType) {
37
                // Try to create character group
38 19
                if (!($group = $characterGroupType::fromString($input)) instanceof NullCG) {
39 19
                    $this->groups[] = $group;
40
                    // Reset CG type iterator to preserve order
41 19
                    break;
42
                }
43
            }
44
        }
45 19
    }
46
47
    /**
48
     * Compare structure character groups.
49
     *
50
     * @param Structure $structure Compared string structure group
51
     *
52
     * @return int Comparison result
53
     */
54 17
    public function compare(Structure $structure): int
55
    {
56 17
        $initialStructureSize = count($this->groups);
57 17
        $comparedStructureSize = count($structure->groups);
58 17
        $maxSize = max($initialStructureSize, $comparedStructureSize);
59
60
        // Iterate maximum sized structure
61 17
        for ($index = 0; $index < $maxSize; $index++) {
62
            // Get compared/initial group or last compared character group is size mismatches
63 17
            $comparedGroup = $structure->groups[$index] ?? $structure->groups[$comparedStructureSize - 1];
64 17
            $initialGroup = $this->groups[$index] ?? $this->groups[$initialStructureSize - 1];
65
66
            // Define if character group with higher priority
67 17
            if (($return = $initialGroup->compare($comparedGroup)) !== 0) {
68 15
                return $return;
69
            }
70
        }
71
72
        // Structures are equal
73 3
        return 0;
74
    }
75
76
    /**
77
     * Get longest common prefix between strings.
78
     *
79
     * @param Structure $compared Compared character group structure
80
     *
81
     * @return string Strings Longest common prefix or empty string
82
     *
83
     */
84 2
    public function getCommonPrefix(Structure $compared)
85
    {
86 2
        $longestPrefix = '';
87
88
        /** @var AbstractCG $group Iterate longest structure character groups */
89 2
        foreach ($this->getShortestStructure($compared) as $index => $group) {
90 2
            $initialGroup = $this->groups[$index];
91 2
            $comparedGroup = $compared->groups[$index];
92
93
            // Get longest matching prefix between character groups.
94 2
            $prefix = $initialGroup->getCommonPrefix($comparedGroup);
95
96
            // Concatenate common prefix
97 2
            $longestPrefix .= $prefix;
98
99
            /**
100
             * If returned prefix is not equal to initial/compared character groups then it means
101
             * that it is shorter and we need to stop searching.
102
             */
103 2
            if ($this->isStringNotMatchingAnyCG($prefix, $initialGroup, $comparedGroup)) {
104 2
                break;
105
            }
106
        }
107
108 2
        return $longestPrefix;
109
    }
110
111
    /**
112
     * Define shortest structure.
113
     *
114
     * @param Structure $compared Structure to compare
115
     *
116
     * @return Structure Shortest structure
117
     */
118 2
    private function getShortestStructure(Structure $compared): Structure
119
    {
120
121 2
        return $this->count() < $compared->count() ? $this : $compared;
122
    }
123
124
    /**
125
     * Define if string does not match any of the passed character groups.
126
     *
127
     * @param string     $string String for comparison
128
     * @param AbstractCG $initialGroup Initial character group
129
     * @param AbstractCG $comparedGroup Compared character group
130
     *
131
     * @return bool True if string not matching any of character groups
132
     */
133 2
    private function isStringNotMatchingAnyCG(string $string, AbstractCG $initialGroup, AbstractCG $comparedGroup): bool
134
    {
135 2
        return $string !== $initialGroup->getString() || $string !== $comparedGroup->getString();
136
    }
137
}
138