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