Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
100.00% |
43 / 43 |
|
100.00% |
10 / 10 |
CRAP | |
100.00% |
1 / 1 |
RunnerData | |
100.00% |
43 / 43 |
|
100.00% |
10 / 10 |
11 | |
100.00% |
1 / 1 |
__construct | |
100.00% |
4 / 4 |
|
100.00% |
1 / 1 |
1 | |||
record | |
100.00% |
11 / 11 |
|
100.00% |
1 / 1 |
2 | |||
getMatchesMap | |
100.00% |
6 / 6 |
|
100.00% |
1 / 1 |
1 | |||
getAllFilters | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
getMatchedFilters | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
getProfilingData | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
getTotalRuntime | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
getTotalConditions | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
toArray | |
100.00% |
11 / 11 |
|
100.00% |
1 / 1 |
1 | |||
fromArray | |
100.00% |
6 / 6 |
|
100.00% |
1 / 1 |
1 |
1 | <?php |
2 | |
3 | namespace MediaWiki\Extension\AbuseFilter; |
4 | |
5 | use LogicException; |
6 | use MediaWiki\Extension\AbuseFilter\Parser\RuleCheckerStatus; |
7 | |
8 | /** |
9 | * Mutable value class storing and accumulating information about filter matches and runtime |
10 | */ |
11 | class RunnerData { |
12 | |
13 | /** |
14 | * @var array<string,RuleCheckerStatus> |
15 | */ |
16 | private $matchedFilters; |
17 | |
18 | /** |
19 | * @var array[] |
20 | * @phan-var array<string,array{time:float,conds:int,result:bool}> |
21 | */ |
22 | private $profilingData; |
23 | |
24 | /** @var float */ |
25 | private $totalRuntime; |
26 | |
27 | /** @var int */ |
28 | private $totalConditions; |
29 | |
30 | /** |
31 | * @param RuleCheckerStatus[] $matchedFilters |
32 | * @param array[] $profilingData |
33 | * @param float $totalRuntime |
34 | * @param int $totalConditions |
35 | */ |
36 | public function __construct( |
37 | array $matchedFilters = [], |
38 | array $profilingData = [], |
39 | float $totalRuntime = 0.0, |
40 | int $totalConditions = 0 |
41 | ) { |
42 | $this->matchedFilters = $matchedFilters; |
43 | $this->profilingData = $profilingData; |
44 | $this->totalRuntime = $totalRuntime; |
45 | $this->totalConditions = $totalConditions; |
46 | } |
47 | |
48 | /** |
49 | * Record (memorize) data from a filter run |
50 | * |
51 | * @param int $filterID |
52 | * @param bool $global |
53 | * @param RuleCheckerStatus $status |
54 | * @param float $timeTaken |
55 | */ |
56 | public function record( int $filterID, bool $global, RuleCheckerStatus $status, float $timeTaken ): void { |
57 | $key = GlobalNameUtils::buildGlobalName( $filterID, $global ); |
58 | if ( array_key_exists( $key, $this->matchedFilters ) ) { |
59 | throw new LogicException( "Filter '$key' has already been recorded" ); |
60 | } |
61 | $this->matchedFilters[$key] = $status; |
62 | $this->profilingData[$key] = [ |
63 | 'time' => $timeTaken, |
64 | 'conds' => $status->getCondsUsed(), |
65 | 'result' => $status->getResult() |
66 | ]; |
67 | $this->totalRuntime += $timeTaken; |
68 | $this->totalConditions += $status->getCondsUsed(); |
69 | } |
70 | |
71 | /** |
72 | * Get information about filter matches in backwards compatible format |
73 | * @return bool[] |
74 | * @phan-return array<string,bool> |
75 | */ |
76 | public function getMatchesMap(): array { |
77 | return array_map( |
78 | static function ( $status ) { |
79 | return $status->getResult(); |
80 | }, |
81 | $this->matchedFilters |
82 | ); |
83 | } |
84 | |
85 | /** |
86 | * @return string[] |
87 | */ |
88 | public function getAllFilters(): array { |
89 | return array_keys( $this->matchedFilters ); |
90 | } |
91 | |
92 | /** |
93 | * @return string[] |
94 | */ |
95 | public function getMatchedFilters(): array { |
96 | return array_keys( array_filter( $this->getMatchesMap() ) ); |
97 | } |
98 | |
99 | /** |
100 | * @return array[] |
101 | */ |
102 | public function getProfilingData(): array { |
103 | return $this->profilingData; |
104 | } |
105 | |
106 | /** |
107 | * @return float |
108 | */ |
109 | public function getTotalRuntime(): float { |
110 | return $this->totalRuntime; |
111 | } |
112 | |
113 | /** |
114 | * @return int |
115 | */ |
116 | public function getTotalConditions(): int { |
117 | return $this->totalConditions; |
118 | } |
119 | |
120 | /** |
121 | * Serialize data for edit stash |
122 | * @return array |
123 | * @phan-return array{matches:array<string,array>,runtime:float,condCount:int,profiling:array} |
124 | */ |
125 | public function toArray(): array { |
126 | return [ |
127 | 'matches' => array_map( |
128 | static function ( $status ) { |
129 | return $status->toArray(); |
130 | }, |
131 | $this->matchedFilters |
132 | ), |
133 | 'profiling' => $this->profilingData, |
134 | 'condCount' => $this->totalConditions, |
135 | 'runtime' => $this->totalRuntime, |
136 | ]; |
137 | } |
138 | |
139 | /** |
140 | * Deserialize data from edit stash |
141 | * @param array $value |
142 | * @return self |
143 | */ |
144 | public static function fromArray( array $value ): self { |
145 | return new self( |
146 | array_map( [ RuleCheckerStatus::class, 'fromArray' ], $value['matches'] ), |
147 | $value['profiling'], |
148 | $value['runtime'], |
149 | $value['condCount'] |
150 | ); |
151 | } |
152 | |
153 | } |