Completed
Push — master ( a498f5...578d3f )
by brian
02:12
created

ComparatorVersionParser::canParse()   B

Complexity

Conditions 6
Paths 3

Size

Total Lines 18
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 11
CRAP Score 6

Importance

Changes 0
Metric Value
dl 0
loc 18
ccs 11
cts 11
cp 1
rs 8.8571
c 0
b 0
f 0
cc 6
eloc 9
nc 3
nop 1
crap 6
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\Matcher;
13
14
use ptlis\SemanticVersion\Comparator\ComparatorFactory;
15
use ptlis\SemanticVersion\Parse\Token;
16
use ptlis\SemanticVersion\Version\VersionBuilder;
17
use ptlis\SemanticVersion\VersionRange\ComparatorVersion;
18
use ptlis\SemanticVersion\VersionRange\VersionRangeInterface;
19
20
/**
21
 * Comparator versions store a comparator & version specifying part of a version range.
22
 */
23
final class ComparatorVersionParser implements RangeParserInterface
24
{
25
    use ChunkByDash;
26
27
    /** @var ComparatorFactory */
28
    private $comparatorFactory;
29
30
    /** @var VersionBuilder */
31
    private $versionBuilder;
32
33
34
    /**
35
     * Constructor.
36
     *
37
     * @param ComparatorFactory $comparatorFactory
38
     * @param VersionBuilder $versionBuilder
39
     */
40 5
    public function __construct(
41
        ComparatorFactory $comparatorFactory,
42
        VersionBuilder $versionBuilder
43
    ) {
44 5
        $this->comparatorFactory = $comparatorFactory;
45 5
        $this->versionBuilder = $versionBuilder;
46 5
    }
47
48
    /**
49
     * Returns true if the tokens can be parsed as a ComparatorVersion.
50
     *
51
     * @param Token[] $tokenList
52
     *
53
     * @return boolean
54
     */
55 5
    public function canParse(array $tokenList)
56
    {
57 5
        $canParse = false;
58
59
        // No illegal tokens present
60 5
        if (!$this->hasIllegalTokens($tokenList)) {
61 5
            $chunkedList = $this->chunk($tokenList);
62
63
            if (
64 5
                (1 === count($chunkedList) && Token::LABEL_STRING !== $chunkedList[0][0]->getType())
65 1
                || (2 === count($chunkedList) && Token::LABEL_STRING === $chunkedList[1][0]->getType())
66 5
            ) {
67 5
                $canParse = true;
68 5
            }
69 5
        }
70
71 5
        return $canParse;
72
    }
73
74
    /**
75
     * Build a ComparatorVersion representing the comparator & version.
76
     *
77
     * @param Token[] $tokenList
78
     *
79
     * @return VersionRangeInterface
80
     */
81 5
    public function parse(array $tokenList)
82
    {
83
        $comparatorList = [
84 5
            '<',
85 5
            '<=',
86 5
            '>',
87 5
            '>=',
88
            '='
89 5
        ];
90
91
        // Prefixed comparator, hydrate & remove
92 5
        if (count($tokenList) > 0 && in_array($tokenList[0]->getValue(), $comparatorList)) {
93 4
            $comparator = $this->comparatorFactory->get($tokenList[0]->getValue());
94 4
            $tokenList = array_slice($tokenList, 1);
95
96
        // Default to equality
97 4
        } else {
98 1
            $comparator = $this->comparatorFactory->get('=');
99
        }
100
101 5
        $chunkList = $this->chunk($tokenList);
102 5
        $versionTokenList = $chunkList[0];
103 5
        $labelTokenList = [];
104 5
        if (count($chunkList) > 1) {
105 1
            $labelTokenList = $chunkList[1];
106 1
        }
107
108 5
        return new ComparatorVersion(
109 5
            $comparator,
0 ignored issues
show
Bug introduced by
It seems like $comparator can be null; however, __construct() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
110 5
            $this->versionBuilder->buildFromTokens($versionTokenList, $labelTokenList)
0 ignored issues
show
Bug introduced by
It seems like $this->versionBuilder->b...nList, $labelTokenList) can be null; however, __construct() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
111 5
        );
112
    }
113
114
    /**
115
     * Returns true if an illegal token is found.
116
     *
117
     * @param Token[] $tokenList
118
     *
119
     * @return boolean
120
     */
121 5
    public function hasIllegalTokens(array $tokenList)
122
    {
123
        $illegalTokenList = [
124 5
            Token::CARET_RANGE,
125 5
            Token::TILDE_RANGE,
126 5
            Token::WILDCARD_DIGITS,
127 5
            Token::LOGICAL_AND,
128
            Token::LOGICAL_OR
129 5
        ];
130
131 5
        $hasIllegalToken = false;
132 5
        foreach ($tokenList as $token) {
133 5
            if (in_array($token->getType(), $illegalTokenList)) {
134
                $hasIllegalToken = true;
135
            }
136 5
        }
137
138 5
        return $hasIllegalToken;
139
    }
140
}
141