Passed
Push — master ( 6dedb2...9b1dd9 )
by Vitaly
06:42
created

Structure::getCommonPrefix()   B

Complexity

Conditions 5
Paths 6

Size

Total Lines 29
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 11
CRAP Score 5

Importance

Changes 0
Metric Value
dl 0
loc 29
ccs 11
cts 11
cp 1
rs 8.439
c 0
b 0
f 0
nc 6
cc 5
eloc 11
nop 1
crap 5
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 $input;
24
25
    /**
26
     * Create string character group structure from input 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->input = $input;
33
34
        // Iterate until input 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
        // Define shortest structure
89 2
        $shortestStructure = $this->count() < $compared->count() ? $this : $compared;
90
91
        /** @var AbstractCG $group Iterate longest structure character groups */
92 2
        foreach ($shortestStructure as $index => $group) {
93 2
            $initialGroup = $this->groups[$index];
94 2
            $comparedGroup = $compared->groups[$index];
95
96
            // Get longest matching prefix between character groups.
97 2
            $prefix = $initialGroup->getCommonPrefix($comparedGroup);
98
99
            // Concatenate common prefix
100 2
            $longestPrefix .= $prefix;
101
102
            /**
103
             * If returned prefix is not equal to initial/compared character groups then it means
104
             * that it is shorter and we need to stop searching.
105
             */
106 2
            if ($prefix !== $initialGroup->getString() || $prefix !== $comparedGroup->getString()) {
107 2
                break;
108
            }
109
        }
110
111 2
        return $longestPrefix;
112
    }
113
}
114