Passed
Push — master ( 203740...2c4c0a )
by Kacper
04:22
created

Token::setStart()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 9
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 2

Importance

Changes 5
Bugs 1 Features 0
Metric Value
c 5
b 1
f 0
dl 0
loc 9
ccs 7
cts 7
cp 1
rs 9.6666
cc 2
eloc 5
nc 2
nop 1
crap 2
1
<?php
2
/**
3
 * Highlighter
4
 *
5
 * Copyright (C) 2015, Some right reserved.
6
 *
7
 * @author Kacper "Kadet" Donat <[email protected]>
8
 *
9
 * Contact with author:
10
 * Xmpp: [email protected]
11
 * E-mail: [email protected]
12
 *
13
 * From Kadet with love.
14
 */
15
16
namespace Kadet\Highlighter\Parser;
17
18
19
use Kadet\Highlighter\Language\Language;
20
use Kadet\Highlighter\Utils\Helper;
21
use Kadet\Highlighter\Utils\StringHelper;
22
23
class Token
24
{
25
    const NAME  = null;
26
    const START = 0x1;
27
    const END   = 0x2;
28
29
    protected static $_id = 0;
30
31
    public $pos;
32
    public $name;
33
    public $index = 1;
34
35
    /**
36
     * @var Token|null|false
37
     */
38
    protected $_end;
39
40
    /**
41
     * @var Token|null|false
42
     */
43
    protected $_start;
44
45
    /** @var Rule */
46
    protected $_rule;
47
48
    protected $_valid;
49
    protected $_length;
50
51
    public $id;
52
53
    /**
54
     * Token constructor.
55
     *
56
     * @param array $options
57
     */
58 51
    public function __construct(array $options)
59
    {
60 51
        if (isset($options[0])) {
61 39
            $this->name = $options[0];
62 39
        }
63
64 51
        if (isset($options['pos'])) {
65 48
            $this->pos = $options['pos'];
66 50
        }
67
68 51
        if (isset($options['index'])) {
69 6
            $this->index = $options['index'];
70 6
        }
71
72 51
        if (isset($options['start'])) {
73 2
            $this->setStart($options['start']);
74 2
        }
75
76 51
        if (isset($options['rule'])) {
77 19
            $this->setRule($options['rule']);
78 19
        } else {
79 33
            $this->setRule(new Rule());
80
        }
81
82 51
        if (isset($options['end'])) {
83 41
            $this->setEnd($options['end']);
84 41
        }
85
86 51
        $this->id = ++self::$_id;
87 51
    }
88
89 13
    public static function compare(Token $a, Token $b)
90
    {
91 13
        $multiplier = $a->isEnd() ? -1 : 1;
92
93 13
        if (($a->isStart() && $b->isEnd()) || ($a->isEnd() && $b->isStart())) {
94 1
            if($a->getStart() == $b) {
95 1
                return 1;
96 1
            } elseif($a->getEnd() == $b) {
97
                return -1;
98
            } else {
99 1
                return $multiplier;
100
            }
101 12
        } elseif (($rule = Helper::cmp($b->_rule->priority, $a->_rule->priority)) !== 0) {
102 10
            return $multiplier*$rule;
103 5
        } elseif (($rule = Helper::cmp($b->index, $a->index)) !== 0) {
104 1
            return $multiplier*$rule;
105
        } else {
106 4
            return $multiplier*($a->id < $b->id ? -1 : 1);
107
        }
108
    }
109
110 34
    public function isStart()
111
    {
112 34
        return $this->_start === null;
113
    }
114
115 32
    public function isEnd()
116
    {
117 32
        return $this->_end === null;
118
    }
119
120 16
    public function isValid(Language $language, $context = null)
121
    {
122 16
        if ($this->_valid === null) {
123 15
            $this->validate($language, $context);
124 15
        }
125
126 16
        return $this->_valid;
127
    }
128
129 11
    protected function validate(Language $language, $context)
130
    {
131 11
        $this->setValid(
132 11
            $language === $this->_rule->language &&
133 11
            $this->_rule->validateContext($context, $this->isEnd() ? [$this->name => Rule::CONTEXT_IN] : [])
134 11
        );
135 11
    }
136
137 15
    public function setValid($valid = true)
138
    {
139 15
        $this->_valid = $valid;
140
141 15
        if ($this->_end) {
142 12
            $this->_end->_valid = $this->_valid;
143 15
        } elseif ($this->_start) {
144 12
            $this->_start->_valid = $this->_valid;
145 12
        }
146 15
    }
147
148
    /**
149
     * @return mixed
150
     */
151 28
    public function getStart()
152
    {
153 28
        return $this->_start;
154
    }
155
156
    /**
157
     * @param Token|null|false $start
158
     */
159 3
    public function setStart($start = null)
160
    {
161 3
        $this->_end = null;
162 3
        $this->_start = $start;
163
164 3
        if ($start instanceof Token) {
165 2
            $start->_end = $this;
166 2
        }
167 3
    }
168
169
    /**
170
     * @return Token|null
171
     */
172 39
    public function getEnd()
173
    {
174 39
        return $this->_end;
175
    }
176
177
    /**
178
     * @param Token|null|false $end
179
     */
180 41
    public function setEnd($end = null)
181
    {
182 41
        $this->_start = null;
183 41
        $this->_end = $end;
184 41
        $this->_length = null;
185
186 41
        if ($end instanceof Token) {
187 41
            $end->_start = $this;
188 41
        }
189 41
    }
190
191
    /**
192
     * @return Rule
193
     */
194 16
    public function getRule()
195
    {
196 16
        return $this->_rule;
197
    }
198
199
    /**
200
     * @param Rule $rule
201
     */
202 51
    public function setRule(Rule $rule)
203
    {
204 51
        $this->_rule = $rule;
205 51
    }
206
207 2
    public function getLength()
208
    {
209 2
        if ($this->_length === null) {
210 2
            $this->_length = $this->_end === null ? 0 : $this->_end->pos - $this->pos;
211 2
        }
212
213 2
        return $this->_length;
214
    }
215
216
    /**
217
     * @codeCoverageIgnore
218
     */
219
    public function dump($text = null)
220
    {
221
        $pos = StringHelper::positionToLine($text, $this->pos);
222
        $pos = $pos['line'] . ':' . $pos['pos'];
223
224
        if ($this->isStart()) {
225
            $result = "Start ({$this->name}) $pos";
226
            if ($text !== null && $this->_end !== null) {
227
                $result .= "  \x02" . substr($text, $this->pos, $this->_end->pos - $this->pos) . "\x03";
228
            }
229
        } else {
230
            $result = "End ({$this->name}) $pos";
231
        }
232
233
        return $result;
234
    }
235
}