]> scripts.mit.edu Git - autoinstallsdev/mediawiki.git/blob - includes/changes/ChangesListStringOptionsFilterGroup.php
MediaWiki 1.30.2
[autoinstallsdev/mediawiki.git] / includes / changes / ChangesListStringOptionsFilterGroup.php
1 <?php
2 /**
3  * Represents a filter group (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  * @license GPL 2+
22  * @author Matthew Flaschen
23  */
24
25 use Wikimedia\Rdbms\IDatabase;
26
27 /**
28  * Represents a filter group with multiple string options. They are passed to the server as
29  * a single form parameter separated by a delimiter.  The parameter name is the
30  * group name.  E.g. groupname=opt1;opt2 .
31  *
32  * If all options are selected they are replaced by the term "all".
33  *
34  * There is also a single DB query modification for the whole group.
35  *
36  * @since 1.29
37  */
38
39 class ChangesListStringOptionsFilterGroup extends ChangesListFilterGroup {
40         /**
41          * Type marker, used by JavaScript
42          */
43         const TYPE = 'string_options';
44
45         /**
46          * Delimiter
47          */
48         const SEPARATOR = ';';
49
50         /**
51          * Signifies that all options in the group are selected.
52          */
53         const ALL = 'all';
54
55         /**
56          * Signifies that no options in the group are selected, meaning the group has no effect.
57          *
58          * For full-coverage groups, this is the same as ALL if all filters are allowed.
59          * For others, it is not.
60          */
61         const NONE = '';
62
63         /**
64          * Defaul parameter value
65          *
66          * @var string $defaultValue
67          */
68         protected $defaultValue;
69
70         /**
71          * Callable used to do the actual query modification; see constructor
72          *
73          * @var callable $queryCallable
74          */
75         protected $queryCallable;
76
77         /**
78          * Create a new filter group with the specified configuration
79          *
80          * @param array $groupDefinition Configuration of group
81          * * $groupDefinition['name'] string Group name
82          * * $groupDefinition['title'] string i18n key for title (optional, can be omitted
83          *     only if none of the filters in the group display in the structured UI)
84          * * $groupDefinition['priority'] int Priority integer.  Higher means higher in the
85          *     group list.
86          * * $groupDefinition['filters'] array Numeric array of filter definitions, each of which
87          *     is an associative array to be passed to the filter constructor.  However,
88          *     'priority' is optional for the filters.  Any filter that has priority unset
89          *     will be put to the bottom, in the order given.
90          * * $groupDefinition['default'] string Default for group.
91          * * $groupDefinition['isFullCoverage'] bool Whether the group is full coverage;
92          *     if true, this means that checking every item in the group means no
93          *     changes list entries are filtered out.
94          * * $groupDefinition['queryCallable'] callable Callable accepting parameters:
95          *      * string $specialPageClassName Class name of current special page
96          *      * IContextSource $context Context, for e.g. user
97          *      * IDatabase $dbr Database, for addQuotes, makeList, and similar
98          *      * array &$tables Array of tables; see IDatabase::select $table
99          *      * array &$fields Array of fields; see IDatabase::select $vars
100          *      * array &$conds Array of conditions; see IDatabase::select $conds
101          *      * array &$query_options Array of query options; see IDatabase::select $options
102          *      * array &$join_conds Array of join conditions; see IDatabase::select $join_conds
103          *      * array $selectedValues The allowed and requested values, lower-cased and sorted
104          * * $groupDefinition['whatsThisHeader'] string i18n key for header of "What's
105          *     This" popup (optional).
106          * * $groupDefinition['whatsThisBody'] string i18n key for body of "What's This"
107          *     popup (optional).
108          * * $groupDefinition['whatsThisUrl'] string URL for main link of "What's This"
109          *     popup (optional).
110          * * $groupDefinition['whatsThisLinkText'] string i18n key of text for main link of
111          *     "What's This" popup (optional).
112          */
113         public function __construct( array $groupDefinition ) {
114                 if ( !isset( $groupDefinition['isFullCoverage'] ) ) {
115                         throw new MWException( 'You must specify isFullCoverage' );
116                 }
117
118                 $groupDefinition['type'] = self::TYPE;
119
120                 parent::__construct( $groupDefinition );
121
122                 $this->queryCallable = $groupDefinition['queryCallable'];
123
124                 if ( isset( $groupDefinition['default'] ) ) {
125                         $this->setDefault( $groupDefinition['default'] );
126                 } else {
127                         throw new MWException( 'You must specify a default' );
128                 }
129         }
130
131         /**
132          * @inheritDoc
133          */
134         public function isPerGroupRequestParameter() {
135                 return true;
136         }
137
138         /**
139          * Sets default of filter group.
140          *
141          * @param string $defaultValue
142          */
143         public function setDefault( $defaultValue ) {
144                 $this->defaultValue = $defaultValue;
145         }
146
147         /**
148          * Gets default of filter group
149          *
150          * @return string $defaultValue
151          */
152         public function getDefault() {
153                 return $this->defaultValue;
154         }
155
156         /**
157          * @inheritDoc
158          */
159         protected function createFilter( array $filterDefinition ) {
160                 return new ChangesListStringOptionsFilter( $filterDefinition );
161         }
162
163         /**
164          * Registers a filter in this group
165          *
166          * @param ChangesListStringOptionsFilter $filter ChangesListStringOptionsFilter
167          */
168         public function registerFilter( ChangesListStringOptionsFilter $filter ) {
169                 $this->filters[$filter->getName()] = $filter;
170         }
171
172         /**
173          * Modifies the query to include the filter group.
174          *
175          * The modification is only done if the filter group is in effect.  This means that
176          * one or more valid and allowed filters were selected.
177          *
178          * @param IDatabase $dbr Database, for addQuotes, makeList, and similar
179          * @param ChangesListSpecialPage $specialPage Current special page
180          * @param array &$tables Array of tables; see IDatabase::select $table
181          * @param array &$fields Array of fields; see IDatabase::select $vars
182          * @param array &$conds Array of conditions; see IDatabase::select $conds
183          * @param array &$query_options Array of query options; see IDatabase::select $options
184          * @param array &$join_conds Array of join conditions; see IDatabase::select $join_conds
185          * @param string $value URL parameter value
186          */
187         public function modifyQuery( IDatabase $dbr, ChangesListSpecialPage $specialPage,
188                 &$tables, &$fields, &$conds, &$query_options, &$join_conds, $value
189         ) {
190                 $allowedFilterNames = [];
191                 foreach ( $this->filters as $filter ) {
192                         $allowedFilterNames[] = $filter->getName();
193                 }
194
195                 if ( $value === self::ALL ) {
196                         $selectedValues = $allowedFilterNames;
197                 } else {
198                         $selectedValues = explode( self::SEPARATOR, strtolower( $value ) );
199
200                         // remove values that are not recognized or not currently allowed
201                         $selectedValues = array_intersect(
202                                 $selectedValues,
203                                 $allowedFilterNames
204                         );
205                 }
206
207                 // If there are now no values, because all are disallowed or invalid (also,
208                 // the user may not have selected any), this is a no-op.
209
210                 // If everything is unchecked, the group always has no effect, regardless
211                 // of full-coverage.
212                 if ( count( $selectedValues ) === 0 ) {
213                         return;
214                 }
215
216                 sort( $selectedValues );
217
218                 call_user_func_array(
219                         $this->queryCallable,
220                         [
221                                 get_class( $specialPage ),
222                                 $specialPage->getContext(),
223                                 $dbr,
224                                 &$tables,
225                                 &$fields,
226                                 &$conds,
227                                 &$query_options,
228                                 &$join_conds,
229                                 $selectedValues
230                         ]
231                 );
232         }
233
234         /**
235          * @inheritDoc
236          */
237         public function getJsData() {
238                 $output = parent::getJsData();
239
240                 $output['separator'] = self::SEPARATOR;
241                 $output['default'] = $this->getDefault();
242
243                 return $output;
244         }
245 }