Completed
Push — master ( 578d3f...fb2c6d )
by brian
02:16
created

VersionParser::clusterTokens()   B

Complexity

Conditions 4
Paths 6

Size

Total Lines 32
Code Lines 18

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 19
CRAP Score 4

Importance

Changes 0
Metric Value
dl 0
loc 32
ccs 19
cts 19
cp 1
rs 8.5806
c 0
b 0
f 0
cc 4
eloc 18
nc 6
nop 1
crap 4

1 Method

Rating   Name   Duplication   Size   Complexity  
A VersionParser::tokensMatchPattern() 0 14 3
1
<?php
2
3
/**
4
 * @copyright   (c) 2014-2017 brian ridley
5
 * @author      brian ridley <[email protected]>
6
 * @license     http://opensource.org/licenses/MIT MIT
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace ptlis\SemanticVersion\Parse;
13
14
use ptlis\SemanticVersion\Parse\Token;
15
use ptlis\SemanticVersion\Version\Label\LabelBuilder;
16
use ptlis\SemanticVersion\Version\Version;
17
use ptlis\SemanticVersion\Version\VersionInterface;
18
19
/**
20
 * Matcher that can be used to parse version numbers.
21
 */
22
final class VersionParser
23
{
24
    /** @var LabelBuilder */
25
    private $labelBuilder;
26
27
    /** Array of token patterns that can be used to construct a valid semantic version number */
28
    const VALID_PATTERNS = [
29
        [Token::DIGITS],
30
        [Token::DIGITS, Token::DOT_SEPARATOR], // Allow trailing dot
31
        [Token::DIGITS, Token::DOT_SEPARATOR, Token::DIGITS],
32
        [Token::DIGITS, Token::DOT_SEPARATOR, Token::DIGITS, Token::DOT_SEPARATOR], // Allow trailing dot
33
        [Token::DIGITS, Token::DOT_SEPARATOR, Token::DIGITS, Token::DOT_SEPARATOR, Token::DIGITS],
34
        [Token::DIGITS, Token::DOT_SEPARATOR, Token::DIGITS, Token::DOT_SEPARATOR, Token::DIGITS,
35
            Token::DASH_SEPARATOR, Token::LABEL_STRING],
36
        [Token::DIGITS, Token::DOT_SEPARATOR, Token::DIGITS, Token::DOT_SEPARATOR, Token::DIGITS,
37
            Token::DASH_SEPARATOR, Token::LABEL_STRING, Token::DOT_SEPARATOR, Token::DIGITS]
38
    ];
39
40
41
    /**
42
     * @param LabelBuilder $labelBuilder
43
     */
44 8
    public function __construct(
45
        LabelBuilder $labelBuilder
46
    ) {
47 8
        $this->labelBuilder = $labelBuilder;
48 8
    }
49
50
    /**
51
     * {@inheritdoc}
52
     */
53 8
    public function canParse(array $tokenList)
54
    {
55 8
        $isVersion = false;
56 8
        foreach (self::VALID_PATTERNS as $pattern) {
57 8
            $isVersion = $isVersion || $this->tokensMatchPattern($tokenList, $pattern);
58
        }
59
60 8
        return $isVersion;
61
    }
62
63
64
    /**
65
     * Parses the token list into an appropriate value type.
66
     *
67
     * @throws \RuntimeException If the version cannot be parsed.
68
     *
69
     * @param Token[] $tokenList
70
     *
71
     * @return VersionInterface
72
     */
73 8
    public function parse(array $tokenList)
74
    {
75 8
        if (!$this->canParse($tokenList)) {
76 1
            throw new \RuntimeException('Invalid version');
77
        }
78
79 7
        $major = $tokenList[0]->getValue();
80 7
        $minor = 0;
81 7
        $patch = 0;
82 7
        $label = null;
83
84 7
        if (count($tokenList) >= 3) {
85 5
            $minor = $tokenList[2]->getValue();
86
        }
87
88 7
        if (count($tokenList) >= 5) {
89 3
            $patch = $tokenList[4]->getValue();
90
        }
91
92
        // Build label from tokens following hyphen seperator
93 7
        if (count($tokenList) >= 7) {
94 2
            $label = $this->labelBuilder->buildFromTokens(array_slice($tokenList, 6));
95
        }
96
97 7
        return new Version($major, $minor, $patch, $label);
98
    }
99
100
    /**
101
     * Returns true if the tokens match the specified pattern.
102
     *
103
     * @param Token[] $tokenList
104
     * @param string[] $pattern
105
     *
106
     * @return bool
107
     */
108 8
    private function tokensMatchPattern(
109
        array $tokenList,
110
        array $pattern
111
    ) {
112 8
        $matches = count($tokenList) === count($pattern);
113
114 8
        foreach ($tokenList as $index => $token) {
115 8
            if ($matches) {
116 8
                $matches = $pattern[$index] === $token->getType();
117
            }
118
        }
119
120 8
        return $matches;
121
    }
122
}