Completed
Branch 0.8-dev (a3ec9f)
by Kacper
02:57
created

Token::compare()   B

Complexity

Conditions 11
Paths 14

Size

Total Lines 20
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 12
CRAP Score 11.055

Importance

Changes 2
Bugs 0 Features 0
Metric Value
c 2
b 0
f 0
dl 0
loc 20
ccs 12
cts 13
cp 0.9231
rs 7.1162
cc 11
eloc 15
nc 14
nop 2
crap 11.055

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/**
3
 * Highlighter
4
 *
5
 * Copyright (C) 2016, 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\Result;
20
use Kadet\Highlighter\Parser\Rule;
21
use Kadet\Highlighter\Parser\TokenIterator;
22
use Kadet\Highlighter\Parser\Validator\Validator;
23
use Kadet\Highlighter\Utils\ArrayHelper;
24
use Kadet\Highlighter\Utils\Helper;
25
26
class Token
27
{
28
    const NAME  = null;
29
    const START = 0x1;
30
    const END   = 0x2;
31
32
    protected static $_id = 0;
33
34
    public $pos;
35
    public $name;
36
    public $closedBy;
37
    public $index = 1;
38
    public $id;
39
    public $rule;
40
41
    # region >>> cache
42
    /**
43
     * @var static|null|false
44
     */
45
    protected $_end;
46
47
    /**
48
     * @var static|null|false
49
     */
50
    protected $_start;
51
52
    protected $_valid;
53
    protected $_length;
54
    # endregion
55
56
    /**
57
     * Token constructor.
58
     *
59
     * @param array $options
60
     */
61 52
    public function __construct(array $options)
62
    {
63 52
        if (isset($options[0])) {
64 39
            $this->name     = $options[0];
65 39
            $this->closedBy = $this->name;
66 39
        }
67
68 52
        if (isset($options['pos'])) {
69 49
            $this->pos = $options['pos'];
70 49
        }
71
72 52
        if (isset($options['index'])) {
73 6
            $this->index = $options['index'];
74 6
        }
75
76 52
        if (isset($options['start'])) {
77 2
            $this->setStart($options['start']);
78 2
        }
79
80 52
        $this->rule = isset($options['rule']) ? $options['rule'] : new Rule();
81
82 52
        if (isset($options['end'])) {
83 42
            $this->setEnd($options['end']);
84 42
        }
85
86 52
        if (isset($options['closed-by'])) {
87
            $this->closedBy = $options['closed-by'];
88
        }
89
90 52
        $this->id = ++self::$_id;
91 52
    }
92
93 35
    public function isStart()
94
    {
95 35
        return $this->_start === null;
96
    }
97
98 33
    public function isEnd()
99
    {
100 33
        return $this->_end === null;
101
    }
102
103 16
    public function isValid(Language $language, $context = null)
104
    {
105 16
        if ($this->_valid === null) {
106 15
            $this->validate($language, $context);
107 15
        }
108
109 16
        return $this->_valid;
110
    }
111
112 11
    protected function validate(Language $language, $context)
113
    {
114 11
        $this->setValid(
115 11
            $language === $this->rule->language &&
116 11
            $this->rule->validator->validate($context, $this->isEnd() ? [$this->name => Validator::CONTEXT_IN] : [])
117 11
        );
118 11
    }
119
120 15
    public function setValid($valid = true)
121
    {
122 15
        $this->_valid = $valid;
123
124 15
        if ($this->_end) {
125 12
            $this->_end->_valid = $this->_valid;
126 15
        } elseif ($this->_start) {
127 12
            $this->_start->_valid = $this->_valid;
128 12
        }
129 15
    }
130
131
    /**
132
     * @return Token|null|false
133
     */
134 29
    public function getStart()
135
    {
136 29
        return $this->_start;
137
    }
138
139
    /**
140
     * @param Token|null|false $start
141
     */
142 13 View Code Duplication
    public function setStart($start = null)
143
    {
144 13
        $this->_end   = null;
145 13
        $this->_start = $start;
146
147 13
        if ($start instanceof Token) {
148 12
            $this->_start->_length = null;
149 12
            $start->_end = $this;
150 12
        }
151 13
    }
152
153
    /**
154
     * @return Token|null|false
155
     */
156 40
    public function getEnd()
157
    {
158 40
        return $this->_end;
159
    }
160
161
    /**
162
     * @param Token|null|false $end
163
     */
164 42 View Code Duplication
    public function setEnd($end = null)
165
    {
166 42
        $this->_start  = null;
167 42
        $this->_end    = $end;
168 42
        $this->_length = null;
169
170 42
        if ($end instanceof Token) {
171 42
            $end->_start = $this;
172 42
        }
173 42
    }
174
175 2
    public function getLength()
176
    {
177 2
        if ($this->_length === null) {
178 2
            $this->_length = !$this->_end ? 0 : $this->_end->pos - $this->pos;
179 2
        }
180
181 2
        return $this->_length;
182
    }
183
184 11
    public function __get($name)
185
    {
186 11
        return $this->rule->$name;
187
    }
188
189
    /**
190
     * @param array         $context
191
     * @param Language      $language
192
     * @param Result        $result
193
     * @param TokenIterator $tokens
194
     *
195
     * todo: Documentation
196
     *
197
     * @return bool Return true to continue processing, false to return already processed tokens.
198
     */
199 11
    public function process(array &$context, Language $language, Result $result, TokenIterator $tokens) {
200 11
        if(!$this->isValid($language, $context)) {
201 3
            return true;
202
        }
203
204 11
        return $this->isStart() ?
205 11
            $this->processStart($context, $language, $result, $tokens) :
206 11
            $this->processEnd($context, $language, $result, $tokens);
207
    }
208
209 10
    protected function processStart(array &$context, Language $language, Result $result, TokenIterator $tokens) {
1 ignored issue
show
Unused Code introduced by
The parameter $language is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
210 10
        $result->append($this);
211 10
        $context[$tokens->key()] = $this->name;
212
213 10
        return true;
214
    }
215
216 9
    protected function processEnd(array &$context, Language $language, Result $result, TokenIterator $tokens) {
1 ignored issue
show
Unused Code introduced by
The parameter $language is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
217 9
        if($this->_start) {
218 8
            unset($context[spl_object_hash($this->_start)]);
219 8
        } else {
220 1
            $start = ArrayHelper::find(array_reverse($context), function ($k, $v) {
221 1
                return $v === $this->closedBy;
222 1
            });
223
224 1
            if ($start !== false) {
225 1
                $this->setStart($tokens[$start]);
226
227 1
                unset($context[$start]);
228 1
            }
229
        }
230
231 9
        if (!$this->_start instanceof MetaToken) {
232 9
            $result->append($this);
233 9
        }
234
235 9
        return true;
236
    }
237
238 13
    public static function compare(Token $a, Token $b)
239
    {
240 13
        $multiplier = $a->isEnd() ? -1 : 1;
241
242 13
        if (($a->isStart() && $b->isEnd()) || ($a->isEnd() && $b->isStart())) {
243 1
            if ($a->getStart() == $b) {
244 1
                return 1;
245 1
            } elseif ($a->getEnd() == $b) {
246
                return -1;
247
            } else {
248 1
                return $multiplier;
249
            }
250 12
        } elseif (($rule = Helper::cmp($b->rule->priority, $a->rule->priority)) !== 0) {
251 10
            return $multiplier*$rule;
252 5
        } elseif (($rule = Helper::cmp($b->index, $a->index)) !== 0) {
253 1
            return $multiplier*$rule;
254
        } else {
255 4
            return $multiplier*($a->id < $b->id ? -1 : 1);
256
        }
257
    }
258
}
259