Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
26 / 26
100.00% covered (success)
100.00%
15 / 15
CRAP
100.00% covered (success)
100.00%
1 / 1
AbstractFilter
100.00% covered (success)
100.00%
26 / 26
100.00% covered (success)
100.00%
15 / 15
18
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
 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 callable|array[] $actions Array with params or callable that will return them
31     * @phan-param array[]|callable():array[] $actions
32     */
33    public function __construct(
34        Specs $specs,
35        Flags $flags,
36        $actions
37    ) {
38        $this->specs = clone $specs;
39        $this->flags = clone $flags;
40        Assert::parameterType( 'callable|array', $actions, '$actions' );
41        if ( is_callable( $actions ) ) {
42            $this->actionsCallback = $actions;
43        } elseif ( is_array( $actions ) ) {
44            $this->setActions( $actions );
45        }
46    }
47
48    /**
49     * @return Specs
50     */
51    public function getSpecs(): Specs {
52        return clone $this->specs;
53    }
54
55    /**
56     * @return Flags
57     */
58    public function getFlags(): Flags {
59        return clone $this->flags;
60    }
61
62    /**
63     * @return string
64     */
65    public function getRules(): string {
66        return $this->specs->getRules();
67    }
68
69    /**
70     * @return string
71     */
72    public function getComments(): string {
73        return $this->specs->getComments();
74    }
75
76    /**
77     * @return string
78     */
79    public function getName(): string {
80        return $this->specs->getName();
81    }
82
83    /**
84     * @note Callers should not rely on the order, because it's nondeterministic.
85     * @return string[]
86     */
87    public function getActionsNames(): array {
88        return $this->specs->getActionsNames();
89    }
90
91    /**
92     * @return string
93     */
94    public function getGroup(): string {
95        return $this->specs->getGroup();
96    }
97
98    /**
99     * @return bool
100     */
101    public function isEnabled(): bool {
102        return $this->flags->getEnabled();
103    }
104
105    /**
106     * @return bool
107     */
108    public function isDeleted(): bool {
109        return $this->flags->getDeleted();
110    }
111
112    /**
113     * @return bool
114     */
115    public function isHidden(): bool {
116        return $this->flags->getHidden();
117    }
118
119    /**
120     * @return bool
121     */
122    public function isGlobal(): bool {
123        return $this->flags->getGlobal();
124    }
125
126    /**
127     * @return array[]
128     */
129    public function getActions(): array {
130        if ( $this->actions === null ) {
131            $this->setActions( call_user_func( $this->actionsCallback ) );
132            // This is to ease testing
133            $this->actionsCallback = null;
134        }
135        return $this->actions;
136    }
137
138    /**
139     * @param array $actions
140     */
141    protected function setActions( array $actions ): void {
142        $this->actions = $actions;
143        $this->specs->setActionsNames( array_keys( $actions ) );
144    }
145
146    /**
147     * Make sure we don't leave any (writeable) reference
148     */
149    public function __clone() {
150        $this->specs = clone $this->specs;
151        $this->flags = clone $this->flags;
152    }
153
154}