Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
32.56% |
14 / 43 |
|
30.00% |
3 / 10 |
CRAP | |
0.00% |
0 / 1 |
ChangesListBooleanFilter | |
32.56% |
14 / 43 |
|
30.00% |
3 / 10 |
142.70 | |
0.00% |
0 / 1 |
__construct | |
80.00% |
8 / 10 |
|
0.00% |
0 / 1 |
4.13 | |||
getDefault | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
12 | |||
setDefault | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
getShowHide | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
displaysOnUnstructuredUi | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
isFeatureAvailableOnStructuredUi | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
2 | |||
modifyQuery | |
0.00% |
0 / 12 |
|
0.00% |
0 / 1 |
6 | |||
getJsData | |
100.00% |
3 / 3 |
|
100.00% |
1 / 1 |
1 | |||
isSelected | |
0.00% |
0 / 7 |
|
0.00% |
0 / 1 |
6 | |||
isActive | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
12 |
1 | <?php |
2 | /** |
3 | * Represents a hide-based boolean filter (used on ChangesListSpecialPage and descendants) |
4 | * |
5 | * This program is free software; you can redistribute it and/or modify |
6 | * it under the terms of the GNU General Public License as published by |
7 | * the Free Software Foundation; either version 2 of the License, or |
8 | * (at your option) any later version. |
9 | * |
10 | * This program is distributed in the hope that it will be useful, |
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
13 | * GNU General Public License for more details. |
14 | * |
15 | * You should have received a copy of the GNU General Public License along |
16 | * with this program; if not, write to the Free Software Foundation, Inc., |
17 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
18 | * http://www.gnu.org/copyleft/gpl.html |
19 | * |
20 | * @file |
21 | * @author Matthew Flaschen |
22 | */ |
23 | |
24 | use MediaWiki\Html\FormOptions; |
25 | use MediaWiki\SpecialPage\ChangesListSpecialPage; |
26 | use Wikimedia\Rdbms\IReadableDatabase; |
27 | |
28 | /** |
29 | * Represents a hide-based boolean filter (used on ChangesListSpecialPage and descendants) |
30 | * |
31 | * @since 1.29 |
32 | */ |
33 | class ChangesListBooleanFilter extends ChangesListFilter { |
34 | /** |
35 | * Main unstructured UI i18n key |
36 | * |
37 | * @var string |
38 | */ |
39 | protected $showHide; |
40 | |
41 | /** |
42 | * Whether there is a feature designed to replace this filter available on the |
43 | * structured UI |
44 | * |
45 | * @var bool |
46 | */ |
47 | protected $isReplacedInStructuredUi; |
48 | |
49 | /** |
50 | * Default |
51 | * |
52 | * @var bool |
53 | */ |
54 | protected $defaultValue; |
55 | |
56 | /** |
57 | * Callable used to do the actual query modification; see constructor |
58 | * |
59 | * @var callable |
60 | */ |
61 | protected $queryCallable; |
62 | |
63 | /** |
64 | * Value that defined when this filter is considered active |
65 | * |
66 | * @var bool |
67 | */ |
68 | protected $activeValue; |
69 | |
70 | /** |
71 | * Create a new filter with the specified configuration. |
72 | * |
73 | * It infers which UI (it can be either or both) to display the filter on based on |
74 | * which messages are provided. |
75 | * |
76 | * If 'label' is provided, it will be displayed on the structured UI. If |
77 | * 'showHide' is provided, it will be displayed on the unstructured UI. Thus, |
78 | * 'label', 'description', and 'showHide' are optional depending on which UI |
79 | * it's for. |
80 | * |
81 | * @param array $filterDefinition ChangesListFilter definition |
82 | * * $filterDefinition['name'] string Name. Used as URL parameter. |
83 | * * $filterDefinition['group'] ChangesListFilterGroup Group. Filter group this |
84 | * belongs to. |
85 | * * $filterDefinition['label'] string i18n key of label for structured UI. |
86 | * * $filterDefinition['description'] string i18n key of description for structured |
87 | * UI. |
88 | * * $filterDefinition['showHide'] string Main i18n key used for unstructured UI. |
89 | * * $filterDefinition['isReplacedInStructuredUi'] bool Whether there is an |
90 | * equivalent feature available in the structured UI; this is optional, defaulting |
91 | * to true. It does not need to be set if the exact same filter is simply visible |
92 | * on both. |
93 | * * $filterDefinition['default'] bool Default |
94 | * * $filterDefinition['activeValue'] bool This filter is considered active when |
95 | * its value is equal to its activeValue. Default is true. |
96 | * * $filterDefinition['priority'] int Priority integer. Higher value means higher |
97 | * up in the group's filter list. |
98 | * * $filterDefinition['queryCallable'] callable Callable accepting parameters, used |
99 | * to implement filter's DB query modification. Required, except for legacy |
100 | * filters that still use the query hooks directly. Callback parameters: |
101 | * * string $specialPageClassName Class name of current special page |
102 | * * IContextSource $context Context, for e.g. user |
103 | * * IDatabase $dbr Database, for addQuotes, makeList, and similar |
104 | * * array &$tables Array of tables; see IDatabase::select $table |
105 | * * array &$fields Array of fields; see IDatabase::select $vars |
106 | * * array &$conds Array of conditions; see IDatabase::select $conds |
107 | * * array &$query_options Array of query options; see IDatabase::select $options |
108 | * * array &$join_conds Array of join conditions; see IDatabase::select $join_conds |
109 | */ |
110 | public function __construct( $filterDefinition ) { |
111 | parent::__construct( $filterDefinition ); |
112 | |
113 | if ( isset( $filterDefinition['showHide'] ) ) { |
114 | $this->showHide = $filterDefinition['showHide']; |
115 | } |
116 | |
117 | $this->isReplacedInStructuredUi = $filterDefinition['isReplacedInStructuredUi'] ?? false; |
118 | |
119 | if ( isset( $filterDefinition['default'] ) ) { |
120 | $this->setDefault( $filterDefinition['default'] ); |
121 | } else { |
122 | throw new InvalidArgumentException( 'You must set a default' ); |
123 | } |
124 | |
125 | if ( isset( $filterDefinition['queryCallable'] ) ) { |
126 | $this->queryCallable = $filterDefinition['queryCallable']; |
127 | } |
128 | |
129 | $this->activeValue = $filterDefinition['activeValue'] ?? true; |
130 | } |
131 | |
132 | /** |
133 | * Get the default value |
134 | * |
135 | * @param bool $structuredUI Are we currently showing the structured UI |
136 | * @return bool|null Default value |
137 | */ |
138 | public function getDefault( $structuredUI = false ) { |
139 | return $this->isReplacedInStructuredUi && $structuredUI ? |
140 | !$this->activeValue : |
141 | $this->defaultValue; |
142 | } |
143 | |
144 | /** |
145 | * Sets default. It must be a boolean. |
146 | * |
147 | * It will be coerced to boolean. |
148 | * |
149 | * @param bool $defaultValue |
150 | */ |
151 | public function setDefault( $defaultValue ) { |
152 | $this->defaultValue = (bool)$defaultValue; |
153 | } |
154 | |
155 | /** |
156 | * @return string Main i18n key for unstructured UI |
157 | */ |
158 | public function getShowHide() { |
159 | return $this->showHide; |
160 | } |
161 | |
162 | /** |
163 | * @inheritDoc |
164 | */ |
165 | public function displaysOnUnstructuredUi() { |
166 | return (bool)$this->showHide; |
167 | } |
168 | |
169 | /** |
170 | * @inheritDoc |
171 | */ |
172 | public function isFeatureAvailableOnStructuredUi() { |
173 | return $this->isReplacedInStructuredUi || |
174 | parent::isFeatureAvailableOnStructuredUi(); |
175 | } |
176 | |
177 | /** |
178 | * Modifies the query to include the filter. This is only called if the filter is |
179 | * in effect (taking into account the default). |
180 | * |
181 | * @param IReadableDatabase $dbr Database, for addQuotes, makeList, and similar |
182 | * @param ChangesListSpecialPage $specialPage Current special page |
183 | * @param array &$tables Array of tables; see IDatabase::select $table |
184 | * @param array &$fields Array of fields; see IDatabase::select $vars |
185 | * @param array &$conds Array of conditions; see IDatabase::select $conds |
186 | * @param array &$query_options Array of query options; see IDatabase::select $options |
187 | * @param array &$join_conds Array of join conditions; see IDatabase::select $join_conds |
188 | */ |
189 | public function modifyQuery( IReadableDatabase $dbr, ChangesListSpecialPage $specialPage, |
190 | &$tables, &$fields, &$conds, &$query_options, &$join_conds |
191 | ) { |
192 | if ( $this->queryCallable === null ) { |
193 | return; |
194 | } |
195 | |
196 | ( $this->queryCallable )( |
197 | get_class( $specialPage ), |
198 | $specialPage->getContext(), |
199 | $dbr, |
200 | $tables, |
201 | $fields, |
202 | $conds, |
203 | $query_options, |
204 | $join_conds |
205 | ); |
206 | } |
207 | |
208 | /** |
209 | * @inheritDoc |
210 | */ |
211 | public function getJsData() { |
212 | $output = parent::getJsData(); |
213 | |
214 | $output['default'] = $this->defaultValue; |
215 | |
216 | return $output; |
217 | } |
218 | |
219 | /** |
220 | * @inheritDoc |
221 | */ |
222 | public function isSelected( FormOptions $opts ) { |
223 | return !$opts[ $this->getName() ] && |
224 | array_filter( |
225 | $this->getSiblings(), |
226 | static function ( ChangesListBooleanFilter $sibling ) use ( $opts ) { |
227 | return $opts[ $sibling->getName() ]; |
228 | } |
229 | ); |
230 | } |
231 | |
232 | /** |
233 | * @param FormOptions $opts Query parameters merged with defaults |
234 | * @param bool $isStructuredUI Whether the structured UI is currently enabled |
235 | * @return bool Whether this filter should be considered active |
236 | */ |
237 | public function isActive( FormOptions $opts, $isStructuredUI ) { |
238 | if ( $this->isReplacedInStructuredUi && $isStructuredUI ) { |
239 | return false; |
240 | } |
241 | |
242 | return $opts[ $this->getName() ] === $this->activeValue; |
243 | } |
244 | } |