Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
100.00% |
341 / 341 |
|
100.00% |
27 / 27 |
CRAP | |
100.00% |
1 / 1 |
AFPTreeParser | |
100.00% |
341 / 341 |
|
100.00% |
27 / 27 |
112 | |
100.00% |
1 / 1 |
__construct | |
100.00% |
4 / 4 |
|
100.00% |
1 / 1 |
1 | |||
setFilter | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
resetState | |
100.00% |
3 / 3 |
|
100.00% |
1 / 1 |
1 | |||
move | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
getNextToken | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
getState | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
setState | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
1 | |||
parse | |
100.00% |
3 / 3 |
|
100.00% |
1 / 1 |
1 | |||
buildSyntaxTree | |
100.00% |
4 / 4 |
|
100.00% |
1 / 1 |
1 | |||
doLevelEntry | |
100.00% |
7 / 7 |
|
100.00% |
1 / 1 |
2 | |||
doLevelSemicolon | |
100.00% |
16 / 16 |
|
100.00% |
1 / 1 |
7 | |||
doLevelSet | |
100.00% |
34 / 34 |
|
100.00% |
1 / 1 |
13 | |||
doLevelConditions | |
100.00% |
56 / 56 |
|
100.00% |
1 / 1 |
13 | |||
doLevelBoolOps | |
100.00% |
13 / 13 |
|
100.00% |
1 / 1 |
3 | |||
doLevelCompares | |
100.00% |
18 / 18 |
|
100.00% |
1 / 1 |
4 | |||
doLevelSumRels | |
100.00% |
13 / 13 |
|
100.00% |
1 / 1 |
3 | |||
doLevelMulRels | |
100.00% |
13 / 13 |
|
100.00% |
1 / 1 |
3 | |||
doLevelPow | |
100.00% |
7 / 7 |
|
100.00% |
1 / 1 |
3 | |||
doLevelBoolInvert | |
100.00% |
6 / 6 |
|
100.00% |
1 / 1 |
3 | |||
doLevelKeywordOperators | |
100.00% |
13 / 13 |
|
100.00% |
1 / 1 |
3 | |||
doLevelUnarys | |
100.00% |
7 / 7 |
|
100.00% |
1 / 1 |
4 | |||
doLevelArrayElements | |
100.00% |
10 / 10 |
|
100.00% |
1 / 1 |
5 | |||
doLevelParenthesis | |
100.00% |
21 / 21 |
|
100.00% |
1 / 1 |
7 | |||
doLevelFunction | |
100.00% |
37 / 37 |
|
100.00% |
1 / 1 |
10 | |||
doLevelAtom | |
100.00% |
46 / 46 |
|
100.00% |
1 / 1 |
16 | |||
checkLogDeprecatedVar | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
2 | |||
functionIsVariadic | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
2 |
1 | <?php |
2 | |
3 | /** |
4 | * A version of the abuse filter parser that separates parsing the filter and |
5 | * evaluating it into different passes, allowing the parse tree to be cached. |
6 | * |
7 | * @file |
8 | * @phan-file-suppress PhanPossiblyInfiniteRecursionSameParams Recursion controlled by class props |
9 | */ |
10 | |
11 | namespace MediaWiki\Extension\AbuseFilter\Parser; |
12 | |
13 | use IBufferingStatsdDataFactory; |
14 | use InvalidArgumentException; |
15 | use MediaWiki\Extension\AbuseFilter\KeywordsManager; |
16 | use MediaWiki\Extension\AbuseFilter\Parser\Exception\UserVisibleException; |
17 | use Psr\Log\LoggerInterface; |
18 | |
19 | /** |
20 | * A parser that transforms the text of the filter into a parse tree. |
21 | */ |
22 | class AFPTreeParser { |
23 | /** |
24 | * @var array[] Contains the AFPTokens for the code being parsed |
25 | * @phan-var array<int,array{0:AFPToken,1:int}> |
26 | */ |
27 | private $mTokens; |
28 | /** |
29 | * @var AFPToken The current token |
30 | */ |
31 | private $mCur; |
32 | /** @var int The position of the current token */ |
33 | private $mPos; |
34 | |
35 | /** |
36 | * @var string|null The ID of the filter being parsed, if available. Can also be "global-$ID" |
37 | */ |
38 | private $mFilter; |
39 | |
40 | public const CACHE_VERSION = 2; |
41 | |
42 | /** |
43 | * @var LoggerInterface Used for debugging |
44 | */ |
45 | private $logger; |
46 | |
47 | /** |
48 | * @var IBufferingStatsdDataFactory |
49 | */ |
50 | private $statsd; |
51 | |
52 | /** @var KeywordsManager */ |
53 | private $keywordsManager; |
54 | |
55 | /** |
56 | * @param LoggerInterface $logger Used for debugging |
57 | * @param IBufferingStatsdDataFactory $statsd |
58 | * @param KeywordsManager $keywordsManager |
59 | */ |
60 | public function __construct( |
61 | LoggerInterface $logger, |
62 | IBufferingStatsdDataFactory $statsd, |
63 | KeywordsManager $keywordsManager |
64 | ) { |
65 | $this->logger = $logger; |
66 | $this->statsd = $statsd; |
67 | $this->keywordsManager = $keywordsManager; |
68 | $this->resetState(); |
69 | } |
70 | |
71 | /** |
72 | * @param string $filter |
73 | */ |
74 | public function setFilter( $filter ) { |
75 | $this->mFilter = $filter; |
76 | } |
77 | |
78 | /** |
79 | * Resets the state |
80 | */ |
81 | private function resetState() { |
82 | $this->mTokens = []; |
83 | $this->mPos = 0; |
84 | $this->mFilter = null; |
85 | } |
86 | |
87 | /** |
88 | * Advances the parser to the next token in the filter code. |
89 | */ |
90 | private function move() { |
91 | [ $this->mCur, $this->mPos ] = $this->mTokens[$this->mPos]; |
92 | } |
93 | |
94 | /** |
95 | * Get the next token. This is similar to move() but doesn't change class members, |
96 | * allowing to look ahead without rolling back the state. |
97 | * |
98 | * @return AFPToken |
99 | */ |
100 | private function getNextToken() { |
101 | return $this->mTokens[$this->mPos][0]; |
102 | } |
103 | |
104 | /** |
105 | * getState() function allows parser state to be rollbacked to several tokens |
106 | * back. |
107 | * |
108 | * @return AFPParserState |
109 | */ |
110 | private function getState() { |
111 | return new AFPParserState( $this->mCur, $this->mPos ); |
112 | } |
113 | |
114 | /** |
115 | * setState() function allows parser state to be rollbacked to several tokens |
116 | * back. |
117 | * |
118 | * @param AFPParserState $state |
119 | */ |
120 | private function setState( AFPParserState $state ) { |
121 | $this->mCur = $state->token; |