Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
29 / 29
100.00% covered (success)
100.00%
18 / 18
CRAP
100.00% covered (success)
100.00%
1 / 1
AbstractFilter
100.00% covered (success)
100.00%
29 / 29
100.00% covered (success)
100.00%
18 / 18
21
100.00% covered (success)
100.00%
1 / 1
 __construct
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
1 / 1
3
 getSpecs
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getFlags
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getRules
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getComments
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getName
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getActionsNames
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getGroup
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 isEnabled
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 isDeleted
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 isHidden
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 isProtected
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 isSuppressed
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getPrivacyLevel
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 isGlobal
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getActions
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
2
 setActions
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 __clone
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
1<?php
2
3namespace MediaWiki\Extension\AbuseFilter\Filter;
4
5use Wikimedia\Assert\Assert;
6
7/**
8 * Immutable value object that represents a single filter. This object can be used to represent
9 * filters that do not necessarily exist in the database. You'll usually want to use subclasses.
10 */
11class AbstractFilter {
12    /** @var Specs */
13    protected $specs;
14    /** @var Flags */
15    protected $flags;
16    /**
17     * @var array[]|null Actions and parameters, can be lazy-loaded with $actionsCallback
18     */
19    protected $actions;
20    /**
21     * @var callable|null
22     * @todo Evaluate whether this can be avoided, e.g. by using a JOIN. This property also makes
23     *   the class not serializable.
24     */
25    protected $actionsCallback;
26
27    /**
28     * @param Specs $specs
29     * @param Flags $flags
30     * @param array[]|callable():array[] $actions Array with params or callable that will return them
31     */
32    public function __construct(
33        Specs $specs,
34        Flags $flags,
35        $actions
36    ) {
37        $this->specs = clone $specs;
38        $this->flags = clone $flags;
39        Assert::parameterType( [ 'callable', 'array' ], $actions, '$actions' );
40        if ( is_callable( $actions ) ) {
41            $this->actionsCallback = $actions;
42        } elseif ( is_array( $actions ) ) {
43            $this->setActions( $actions );
44        }
45    }
46
47    public function getSpecs(): Specs {
48        return clone $this->specs;
49    }
50
51    public function getFlags(): Flags {
52        return clone $this->flags;
53    }
54
55    public function getRules(): string {
56        return $this->specs->getRules();
57    }
58
59    public function getComments(): string {
60        return $this->specs->getComments();
61    }
62
63    public function getName(): string {
64        return $this->specs->getName();
65    }
66
67    /**
68     * @note Callers should not rely on the order, because it's nondeterministic.
69     * @return string[]
70     */
71    public function getActionsNames(): array {
72        return $this->specs->getActionsNames();
73    }
74
75    public function getGroup(): string {
76        return $this->specs->getGroup();
77    }
78
79    public function isEnabled(): bool {
80        return $this->flags->getEnabled();
81    }
82
83    public function isDeleted(): bool {
84        return $this->flags->getDeleted();
85    }
86
87    public function isHidden(): bool {
88        return $this->flags->getHidden();
89    }
90
91    public function isProtected(): bool {
92        return $this->flags->getProtected();
93    }
94
95    public function isSuppressed(): bool {
96        return $this->flags->getSuppressed();
97    }
98
99    public function getPrivacyLevel(): int {
100        return $this->flags->getPrivacyLevel();
101    }
102
103    public function isGlobal(): bool {
104        return $this->flags->getGlobal();
105    }
106
107    /**
108     * @return array[]
109     */
110    public function getActions(): array {
111        if ( $this->actions === null ) {
112            $this->setActions( ( $this->actionsCallback )() );
113            // This is to ease testing
114            $this->actionsCallback = null;
115        }
116        return $this->actions;
117    }
118
119    protected function setActions( array $actions ): void {
120        $this->actions = $actions;
121        $this->specs->setActionsNames( array_keys( $actions ) );
122    }
123
124    /**
125     * Make sure we don't leave any (writeable) reference
126     */
127    public function __clone() {
128        $this->specs = clone $this->specs;
129        $this->flags = clone $this->flags;
130    }
131
132}