Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
25 / 25
100.00% covered (success)
100.00%
2 / 2
CRAP
100.00% covered (success)
100.00%
1 / 1
FilterCompare
100.00% covered (success)
100.00%
25 / 25
100.00% covered (success)
100.00%
2 / 2
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
 compareVersions
100.00% covered (success)
100.00%
24 / 24
100.00% covered (success)
100.00%
1 / 1
10
1<?php
2
3namespace MediaWiki\Extension\AbuseFilter;
4
5use MediaWiki\Extension\AbuseFilter\Consequences\ConsequencesRegistry;
6use MediaWiki\Extension\AbuseFilter\Filter\Filter;
7
8/**
9 * This service allows comparing two versions of a filter.
10 * @todo We might want to expand this to cover the use case of ViewDiff
11 * @internal
12 */
13class FilterCompare {
14    public const SERVICE_NAME = 'AbuseFilterFilterCompare';
15
16    /** @var ConsequencesRegistry */
17    private $consequencesRegistry;
18
19    /**
20     * @param ConsequencesRegistry $consequencesRegistry
21     */
22    public function __construct( ConsequencesRegistry $consequencesRegistry ) {
23        $this->consequencesRegistry = $consequencesRegistry;
24    }
25
26    /**
27     * @param Filter $firstFilter
28     * @param Filter $secondFilter
29     * @return array Fields that are different
30     */
31    public function compareVersions( Filter $firstFilter, Filter $secondFilter ): array {
32        // TODO: Avoid DB references here, re-add when saving the filter
33        $methods = [
34            'af_public_comments' => 'getName',
35            'af_pattern' => 'getRules',
36            'af_comments' => 'getComments',
37            'af_deleted' => 'isDeleted',
38            'af_enabled' => 'isEnabled',
39            'af_hidden' => 'getPrivacyLevel',
40            'af_global' => 'isGlobal',
41            'af_group' => 'getGroup',
42        ];
43
44        $differences = [];
45
46        foreach ( $methods as $field => $method ) {
47            if ( $firstFilter->$method() !== $secondFilter->$method() ) {
48                $differences[] = $field;
49            }
50        }
51
52        $firstActions = $firstFilter->getActions();
53        $secondActions = $secondFilter->getActions();
54        foreach ( $this->consequencesRegistry->getAllEnabledActionNames() as $action ) {
55            if ( !isset( $firstActions[$action] ) && !isset( $secondActions[$action] ) ) {
56                // They're both unset
57            } elseif ( isset( $firstActions[$action] ) && isset( $secondActions[$action] ) ) {
58                // They're both set. Double check needed, e.g. per T180194
59                if ( array_diff( $firstActions[$action], $secondActions[$action] ) ||
60                    array_diff( $secondActions[$action], $firstActions[$action] ) ) {
61                    // Different parameters
62                    $differences[] = 'actions';
63                }
64            } else {
65                // One's unset, one's set.
66                $differences[] = 'actions';
67            }
68        }
69
70        return array_unique( $differences );
71    }
72}