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