Completed
Push — master ( 8d7014...4fa85a )
by brian
05:27
created

VersionParser   A

Complexity

Total Complexity 11

Size/Duplication

Total Lines 105
Duplicated Lines 0 %

Coupling/Cohesion

Dependencies 3

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
wmc 11
cbo 3
dl 0
loc 105
ccs 35
cts 35
cp 1
rs 10
c 0
b 0
f 0

3 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
B parseRange() 0 39 6
B clusterTokens() 0 32 4
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\Matcher\RangeParserInterface;
15
use ptlis\SemanticVersion\VersionRange\VersionRangeInterface;
16
17
/**
18
 * Parser accepting array of tokens and returning an array of comparators & versions.
19
 *
20
 * @todo Correctly validate versions
21
 */
22
final class VersionParser
23
{
24
    /**
25
     * @var RangeParserInterface[]
26
     */
27
    private $rangeParserList;
28
29
30
    /**
31
     * Constructor.
32
     *
33
     * @param RangeParserInterface[] $rangeParserList
34
     */
35 30
    public function __construct(array $rangeParserList)
36
    {
37 30
        $this->rangeParserList = $rangeParserList;
38 30
    }
39
40
    /**
41
     * Parse a version range.
42
     *
43
     * @param Token[] $tokenList
44
     *
45
     * @return VersionRangeInterface
46
     */
47 30
    public function parseRange(array $tokenList)
48
    {
49 30
        $clusteredTokenList = $this->clusterTokens($tokenList);
50
51
        $operatorList = [
52 30
            Token::LOGICAL_AND,
53
            Token::LOGICAL_OR
54
        ];
55
56 30
        $realResultList = [];
57 30
        foreach ($clusteredTokenList as $clusteredTokens) {
1 ignored issue
show
Coding Style introduced by
Blank line found at start of control structure
Loading history...
58
59 30
            $parsed = null;
60 30
            foreach ($this->rangeParserList as $rangeParser) {
61 30
                if ($rangeParser->canParse($clusteredTokens)) {
62 30
                    $parsed = $rangeParser->parse($clusteredTokens);
63 30
                    break;
64
                }
65
            }
66
67 30
            if (is_null($parsed)) {
1 ignored issue
show
Coding Style introduced by
Blank line found at start of control structure
Loading history...
68
69 5
                if (in_array($clusteredTokens[0]->getType(), $operatorList)) {
70 5
                    $realResultList[] = $clusteredTokens[0];
71
72
1 ignored issue
show
Coding Style introduced by
Blank line found at end of control structure
Loading history...
73
                } else {
74 5
                    throw new \RuntimeException('Unable to parse version string');
75
                }
76
            } else {
77 30
                $realResultList[] = $parsed;
78
            }
79
1 ignored issue
show
Coding Style introduced by
Blank line found at end of control structure
Loading history...
80
        }
81
82 30
        $buildRange = new LogicalOperatorProcessor();
83
84 30
        return $buildRange->run($realResultList);
85
    }
86
87
    /**
88
     * Clusters the tokens, breaking them up upon finding a logical AND / OR.
89
     *
90
     * @param Token[] $tokenList
91
     *
92
     * @return Token[][] $tokenList
93
     */
94 30
    private function clusterTokens(array $tokenList)
95
    {
96
        $comparatorTokenList = [
97 30
            Token::LOGICAL_AND,
98
            Token::LOGICAL_OR
99
        ];
100
101 30
        $tokenClusterList = [];
102
103
        // Stores tokens not yet parcelled out
104 30
        $tokenAccumulator = [];
105 30
        $tokenListCount = count($tokenList);
106 30
        for ($i = 0; $i < $tokenListCount; $i++) {
107 30
            $currentToken = $tokenList[$i];
108
109 30
            if (in_array($currentToken->getType(), $comparatorTokenList)) {
110 5
                $tokenClusterList[] = $tokenAccumulator;
111 5
                $tokenClusterList[] = [$currentToken];
112 5
                $tokenAccumulator = [];
113
1 ignored issue
show
Coding Style introduced by
Blank line found at end of control structure
Loading history...
114
            } else {
115 30
                $tokenAccumulator[] = $currentToken;
116
            }
117
        }
118
119
        // Add any remaining tokens
120 30
        if (count($tokenAccumulator)) {
121 30
            $tokenClusterList[] = $tokenAccumulator;
122
        }
123
124 30
        return $tokenClusterList;
125
    }
126
}
127