Passed
Push — master ( 454cf7...0d52c3 )
by Kacper
02:57
created

Token::__construct()   D

Complexity

Conditions 8
Paths 128

Size

Total Lines 36
Code Lines 20

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 24
CRAP Score 8.0291

Importance

Changes 2
Bugs 0 Features 0
Metric Value
c 2
b 0
f 0
dl 0
loc 36
rs 4.6666
ccs 24
cts 26
cp 0.9231
cc 8
eloc 20
nc 128
nop 1
crap 8.0291
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\Token;
17
18
use Kadet\Highlighter\Language\Language;
19
use Kadet\Highlighter\Parser\Rule;
20
use Kadet\Highlighter\Parser\Validator\Validator;
21
use Kadet\Highlighter\Utils\Helper;
22
use Kadet\Highlighter\Utils\StringHelper;
23
24
class Token
25
{
26
    const NAME  = null;
27
    const START = 0x1;
28
    const END   = 0x2;
29
30
    protected static $_id = 0;
31
32
    public $pos;
33
    public $name;
34
    public $closedBy;
35
    public $index = 1;
36
37
    /**
38
     * @var Token|null|false
39
     */
40
    protected $_end;
41
42
    /**
43
     * @var Token|null|false
44
     */
45
    protected $_start;
46
47
    /** @var Rule */
48
    protected $_rule;
49
50
    protected $_valid;
51
    protected $_length;
52
53
    public $id;
54
55
    /**
56
     * Token constructor.
57
     *
58
     * @param array $options
59
     */
60 52
    public function __construct(array $options)
61
    {
62 52
        if (isset($options[0])) {
63 39
            $this->name = $options[0];
64 39
        }
65
66 52
        if (isset($options['pos'])) {
67 49
            $this->pos = $options['pos'];
68 49
        }
69
70 52
        if (isset($options['index'])) {
71 6
            $this->index = $options['index'];
72 6
        }
73
74 52
        if (isset($options['start'])) {
75 2
            $this->setStart($options['start']);
76 2
        }
77
78 52
        if (isset($options['rule'])) {
79 19
            $this->setRule($options['rule']);
80 19
        } else {
81 34
            $this->setRule(new Rule());
82
        }
83
84 52
        if (isset($options['end'])) {
85 42
            $this->setEnd($options['end']);
86 42
        }
87
88 52
        if (isset($options['closed-by'])) {
89
            $this->closedBy = $options['closed-by'];
90
        } else {
91 52
            $this->closedBy = $this->name;
92
        }
93
94 52
        $this->id = ++self::$_id;
95 52
    }
96
97 13
    public static function compare(Token $a, Token $b)
98
    {
99 13
        $multiplier = $a->isEnd() ? -1 : 1;
100
101 13
        if (($a->isStart() && $b->isEnd()) || ($a->isEnd() && $b->isStart())) {
102 1
            if ($a->getStart() == $b) {
103 1
                return 1;
104 1
            } elseif ($a->getEnd() == $b) {
105
                return -1;
106
            } else {
107 1
                return $multiplier;
108
            }
109 12
        } elseif (($rule = Helper::cmp($b->_rule->priority, $a->_rule->priority)) !== 0) {
110 10
            return $multiplier*$rule;
111 5
        } elseif (($rule = Helper::cmp($b->index, $a->index)) !== 0) {
112 1
            return $multiplier*$rule;
113
        } else {
114 4
            return $multiplier*($a->id < $b->id ? -1 : 1);
115
        }
116
    }
117
118 35
    public function isStart()
119
    {
120 35
        return $this->_start === null;
121
    }
122
123 33
    public function isEnd()
124
    {
125 33
        return $this->_end === null;
126
    }
127
128 16
    public function isValid(Language $language, $context = null)
129
    {
130 16
        if ($this->_valid === null) {
131 15
            $this->validate($language, $context);
132 15
        }
133
134 16
        return $this->_valid;
135
    }
136
137 11
    protected function validate(Language $language, $context)
138
    {
139 11
        $this->setValid(
140 11
            $language === $this->_rule->language &&
141 11
            $this->_rule->validate($context, $this->isEnd() ? [$this->name => Validator::CONTEXT_IN] : [])
142 11
        );
143 11
    }
144
145 15
    public function setValid($valid = true)
146
    {
147 15
        $this->_valid = $valid;
148
149 15
        if ($this->_end) {
150 12
            $this->_end->_valid = $this->_valid;
151 15
        } elseif ($this->_start) {
152 12
            $this->_start->_valid = $this->_valid;
153 12
        }
154 15
    }
155
156
    /**
157
     * @return mixed
158
     */
159 29
    public function getStart()
160
    {
161 29
        return $this->_start;
162
    }
163
164
    /**
165
     * @param Token|null|false $start
166
     */
167 3 View Code Duplication
    public function setStart($start = null)
1 ignored issue
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
168
    {
169 3
        $this->_end   = null;
170 3
        $this->_start = $start;
171
172 3
        if ($start instanceof Token) {
173 2
            $this->_start->_length = null;
174 2
            $start->_end = $this;
175 2
        }
176 3
    }
177
178
    /**
179
     * @return Token|null
180
     */
181 40
    public function getEnd()
182
    {
183 40
        return $this->_end;
184
    }
185
186
    /**
187
     * @param Token|null|false $end
188
     */
189 42 View Code Duplication
    public function setEnd($end = null)
1 ignored issue
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
190
    {
191 42
        $this->_start  = null;
192 42
        $this->_end    = $end;
193 42
        $this->_length = null;
194
195 42
        if ($end instanceof Token) {
196 42
            $end->_start = $this;
197 42
        }
198 42
    }
199
200
    /**
201
     * @return Rule
202
     */
203 16
    public function getRule()
204
    {
205 16
        return $this->_rule;
206
    }
207
208
    /**
209
     * @param Rule $rule
210
     */
211 52
    public function setRule(Rule $rule)
212
    {
213 52
        $this->_rule = $rule;
214 52
    }
215
216 2
    public function getLength()
217
    {
218 2
        if ($this->_length === null) {
219 2
            $this->_length = $this->_end === null ? 0 : $this->_end->pos - $this->pos;
220 2
        }
221
222 2
        return $this->_length;
223
    }
224
225
    /**
226
     * @codeCoverageIgnore
227
     */
228
    public function dump($text = null)
229
    {
230
        $pos = StringHelper::positionToLine($text, $this->pos);
231
        $pos = $pos['line'] . ':' . $pos['pos'];
232
233
        if ($this->isStart()) {
234
            $result = "Start ({$this->name}) $pos";
235
            if ($text !== null && $this->_end !== null) {
236
                $result .= "  \x02" . substr($text, $this->pos, $this->_end->pos - $this->pos) . "\x03";
237
            }
238
        } else {
239
            $result = "End ({$this->name}) $pos";
240
        }
241
242
        return $result;
243
    }
244
245 11
    public function __get($name)
246
    {
247 11
        return $this->getRule()->$name;
248
    }
249
}
250