MediaWiki  1.34.0
ChangesListFilter.php
Go to the documentation of this file.
1 <?php
29 abstract class ChangesListFilter {
35  protected $name;
36 
45  protected $cssClassSuffix;
46 
53 
59  protected $group;
60 
66  protected $label;
67 
73  protected $description;
74 
81  protected $conflictingGroups = [];
82 
89  protected $conflictingFilters = [];
90 
96  protected $subsetFilters = [];
97 
103  protected $priority;
104 
110 
111  const RESERVED_NAME_CHAR = '_';
112 
142  public function __construct( array $filterDefinition ) {
143  if ( isset( $filterDefinition['group'] ) ) {
144  $this->group = $filterDefinition['group'];
145  } else {
146  throw new MWException( 'You must use \'group\' to specify the ' .
147  'ChangesListFilterGroup this filter belongs to' );
148  }
149 
150  if ( strpos( $filterDefinition['name'], self::RESERVED_NAME_CHAR ) !== false ) {
151  throw new MWException( 'Filter names may not contain \'' .
152  self::RESERVED_NAME_CHAR .
153  '\'. Use the naming convention: \'lowercase\''
154  );
155  }
156 
157  if ( $this->group->getFilter( $filterDefinition['name'] ) ) {
158  throw new MWException( 'Two filters in a group cannot have the ' .
159  "same name: '{$filterDefinition['name']}'" );
160  }
161 
162  $this->name = $filterDefinition['name'];
163 
164  if ( isset( $filterDefinition['cssClassSuffix'] ) ) {
165  $this->cssClassSuffix = $filterDefinition['cssClassSuffix'];
166  $this->isRowApplicableCallable = $filterDefinition['isRowApplicableCallable'];
167  }
168 
169  if ( isset( $filterDefinition['label'] ) ) {
170  $this->label = $filterDefinition['label'];
171  $this->description = $filterDefinition['description'];
172  }
173 
174  $this->priority = $filterDefinition['priority'];
175 
176  $this->group->registerFilter( $this );
177  }
178 
193  public function conflictsWith( $other, $globalKey, $forwardKey, $backwardKey ) {
194  if ( $globalKey === null || $forwardKey === null || $backwardKey === null ) {
195  throw new MWException( 'All messages must be specified' );
196  }
197 
199  $other,
200  $globalKey,
201  $forwardKey
202  );
203 
204  $other->setUnidirectionalConflict(
205  $this,
206  $globalKey,
207  $backwardKey
208  );
209  }
210 
222  public function setUnidirectionalConflict( $other, $globalDescription, $contextDescription ) {
223  if ( $other instanceof ChangesListFilterGroup ) {
224  $this->conflictingGroups[] = [
225  'group' => $other->getName(),
226  'groupObject' => $other,
227  'globalDescription' => $globalDescription,
228  'contextDescription' => $contextDescription,
229  ];
230  } elseif ( $other instanceof ChangesListFilter ) {
231  $this->conflictingFilters[] = [
232  'group' => $other->getGroup()->getName(),
233  'filter' => $other->getName(),
234  'filterObject' => $other,
235  'globalDescription' => $globalDescription,
236  'contextDescription' => $contextDescription,
237  ];
238  } else {
239  throw new MWException( 'You can only pass in a ChangesListFilterGroup or a ChangesListFilter' );
240  }
241  }
242 
252  public function setAsSupersetOf( ChangesListFilter $other ) {
253  if ( $other->getGroup() !== $this->getGroup() ) {
254  throw new MWException( 'Supersets can only be defined for filters in the same group' );
255  }
256 
257  $this->subsetFilters[] = [
258  // It's always the same group, but this makes the representation
259  // more consistent with conflicts.
260  'group' => $other->getGroup()->getName(),
261  'filter' => $other->getName(),
262  ];
263  }
264 
268  public function getName() {
269  return $this->name;
270  }
271 
275  public function getGroup() {
276  return $this->group;
277  }
278 
282  public function getLabel() {
283  return $this->label;
284  }
285 
289  public function getDescription() {
290  return $this->description;
291  }
292 
298  abstract public function displaysOnUnstructuredUi();
299 
306  public function displaysOnStructuredUi() {
307  return $this->label !== null;
308  }
309 
318  return $this->displaysOnStructuredUi();
319  }
320 
324  public function getPriority() {
325  return $this->priority;
326  }
327 
333  protected function getCssClass() {
334  if ( $this->cssClassSuffix !== null ) {
336  } else {
337  return null;
338  }
339  }
340 
348  public function applyCssClassIfNeeded( IContextSource $ctx, RecentChange $rc, array &$classes ) {
349  if ( $this->isRowApplicableCallable === null ) {
350  return;
351  }
352 
353  if ( call_user_func( $this->isRowApplicableCallable, $ctx, $rc ) ) {
354  $classes[] = $this->getCssClass();
355  }
356  }
357 
365  public function getJsData() {
366  $output = [
367  'name' => $this->getName(),
368  'label' => $this->getLabel(),
369  'description' => $this->getDescription(),
370  'cssClass' => $this->getCssClass(),
371  'priority' => $this->priority,
372  'subset' => $this->subsetFilters,
373  'conflicts' => [],
374  'defaultHighlightColor' => $this->defaultHighlightColor
375  ];
376 
377  $output['messageKeys'] = [
378  $this->getLabel(),
379  $this->getDescription(),
380  ];
381 
382  $conflicts = array_merge(
383  $this->conflictingGroups,
384  $this->conflictingFilters
385  );
386 
387  foreach ( $conflicts as $conflictInfo ) {
388  unset( $conflictInfo['filterObject'] );
389  unset( $conflictInfo['groupObject'] );
390  $output['conflicts'][] = $conflictInfo;
391  array_push(
392  $output['messageKeys'],
393  $conflictInfo['globalDescription'],
394  $conflictInfo['contextDescription']
395  );
396  }
397 
398  return $output;
399  }
400 
407  abstract public function isSelected( FormOptions $opts );
408 
414  public function getConflictingGroups() {
415  return array_map(
416  function ( $conflictDesc ) {
417  return $conflictDesc[ 'groupObject' ];
418  },
420  );
421  }
422 
428  public function getConflictingFilters() {
429  return array_map(
430  function ( $conflictDesc ) {
431  return $conflictDesc[ 'filterObject' ];
432  },
434  );
435  }
436 
445  if ( $group->anySelected( $opts ) && $this->isSelected( $opts ) ) {
447  foreach ( $this->getSiblings() as $siblingFilter ) {
448  if ( $siblingFilter->isSelected( $opts ) && !$siblingFilter->hasConflictWithGroup( $group ) ) {
449  return false;
450  }
451  }
452  return true;
453  }
454  return false;
455  }
456 
458  return in_array( $group, $this->getConflictingGroups() );
459  }
460 
469  if ( $this->isSelected( $opts ) && $filter->isSelected( $opts ) ) {
471  foreach ( $this->getSiblings() as $siblingFilter ) {
472  if (
473  $siblingFilter->isSelected( $opts ) &&
474  !$siblingFilter->hasConflictWithFilter( $filter )
475  ) {
476  return false;
477  }
478  }
479  return true;
480  }
481  return false;
482  }
483 
485  return in_array( $filter, $this->getConflictingFilters() );
486  }
487 
493  protected function getSiblings() {
494  return array_filter(
495  $this->getGroup()->getFilters(),
496  function ( $filter ) {
497  return $filter !== $this;
498  }
499  );
500  }
501 
506  $this->defaultHighlightColor = $defaultHighlightColor;
507  }
508 }
$filter
$filter
Definition: profileinfo.php:344
ChangesListFilter\activelyInConflictWithGroup
activelyInConflictWithGroup(ChangesListFilterGroup $group, FormOptions $opts)
Check if the conflict with a group is currently "active".
Definition: ChangesListFilter.php:444
ChangesListFilter\isSelected
isSelected(FormOptions $opts)
Checks whether this filter is selected in the provided options.
ChangesListFilter\$subsetFilters
$subsetFilters
Array of associative arrays with subset information.
Definition: ChangesListFilter.php:96
RecentChange
Utility class for creating new RC entries.
Definition: RecentChange.php:70
ChangesListFilter\displaysOnUnstructuredUi
displaysOnUnstructuredUi()
Checks whether the filter should display on the unstructured UI.
ChangesListFilter\setAsSupersetOf
setAsSupersetOf(ChangesListFilter $other)
Marks that the current instance is (also) a superset of the filter passed in.
Definition: ChangesListFilter.php:252
ChangesListFilter\$priority
$priority
Priority integer.
Definition: ChangesListFilter.php:103
ChangesListFilter\displaysOnStructuredUi
displaysOnStructuredUi()
Checks whether the filter should display on the structured UI This refers to the exact filter.
Definition: ChangesListFilter.php:306
ChangesListFilter\getName
getName()
Definition: ChangesListFilter.php:268
ChangesListFilter\$isRowApplicableCallable
$isRowApplicableCallable
Callable that returns true if and only if a row is attributed to this filter.
Definition: ChangesListFilter.php:52
ChangesListFilterGroup
Represents a filter group (used on ChangesListSpecialPage and descendants)
Definition: ChangesListFilterGroup.php:37
ChangesListFilter\$cssClassSuffix
$cssClassSuffix
CSS class suffix used for attribution, e.g.
Definition: ChangesListFilter.php:45
ChangesListFilter\conflictsWith
conflictsWith( $other, $globalKey, $forwardKey, $backwardKey)
Marks that the given ChangesListFilterGroup or ChangesListFilter conflicts with this object.
Definition: ChangesListFilter.php:193
ChangesListFilter\hasConflictWithFilter
hasConflictWithFilter(ChangesListFilter $filter)
Definition: ChangesListFilter.php:484
ChangesListFilter\getGroup
getGroup()
Definition: ChangesListFilter.php:275
MWException
MediaWiki exception.
Definition: MWException.php:26
ChangesListFilter\hasConflictWithGroup
hasConflictWithGroup(ChangesListFilterGroup $group)
Definition: ChangesListFilter.php:457
ChangesListFilter\$label
$label
i18n key of label for structured UI
Definition: ChangesListFilter.php:66
ChangesListFilter\$group
$group
Group.
Definition: ChangesListFilter.php:59
ChangesListFilter\getSiblings
getSiblings()
Get filters in the same group.
Definition: ChangesListFilter.php:493
ChangesListFilter\getConflictingGroups
getConflictingGroups()
Get groups conflicting with this filter.
Definition: ChangesListFilter.php:414
ChangesListFilter\getJsData
getJsData()
Gets the JS data required by the front-end of the structured UI.
Definition: ChangesListFilter.php:365
ChangesListFilter\applyCssClassIfNeeded
applyCssClassIfNeeded(IContextSource $ctx, RecentChange $rc, array &$classes)
Add CSS class if needed.
Definition: ChangesListFilter.php:348
ChangesListFilter\getDescription
getDescription()
Definition: ChangesListFilter.php:289
ChangesList\CSS_CLASS_PREFIX
const CSS_CLASS_PREFIX
Definition: ChangesList.php:30
ChangesListFilter\isFeatureAvailableOnStructuredUi
isFeatureAvailableOnStructuredUi()
Checks whether an equivalent feature for this filter is available on the structured UI.
Definition: ChangesListFilter.php:317
$output
$output
Definition: SyntaxHighlight.php:335
ChangesListFilter\getCssClass
getCssClass()
Gets the CSS class.
Definition: ChangesListFilter.php:333
ChangesListFilter\$defaultHighlightColor
$defaultHighlightColor
Definition: ChangesListFilter.php:109
ChangesListFilter\RESERVED_NAME_CHAR
const RESERVED_NAME_CHAR
Definition: ChangesListFilter.php:111
ChangesListFilter\setDefaultHighlightColor
setDefaultHighlightColor( $defaultHighlightColor)
Definition: ChangesListFilter.php:505
IContextSource
Interface for objects which can provide a MediaWiki context on request.
Definition: IContextSource.php:53
ChangesListFilter\getLabel
getLabel()
Definition: ChangesListFilter.php:282
ChangesListFilter\$conflictingGroups
$conflictingGroups
Array of associative arrays with conflict information.
Definition: ChangesListFilter.php:81
ChangesListFilter\activelyInConflictWithFilter
activelyInConflictWithFilter(ChangesListFilter $filter, FormOptions $opts)
Check if the conflict with a filter is currently "active".
Definition: ChangesListFilter.php:468
ChangesListFilter\setUnidirectionalConflict
setUnidirectionalConflict( $other, $globalDescription, $contextDescription)
Marks that the given ChangesListFilterGroup or ChangesListFilter conflicts with this object.
Definition: ChangesListFilter.php:222
ChangesListFilter
Represents a filter (used on ChangesListSpecialPage and descendants)
Definition: ChangesListFilter.php:29
ChangesListFilter\$description
$description
i18n key of description for structured UI
Definition: ChangesListFilter.php:73
ChangesListFilter\$conflictingFilters
$conflictingFilters
Array of associative arrays with conflict information.
Definition: ChangesListFilter.php:89
ChangesListFilter\getPriority
getPriority()
Definition: ChangesListFilter.php:324
FormOptions
Helper class to keep track of options when mixing links and form elements.
Definition: FormOptions.php:35
ChangesListFilter\__construct
__construct(array $filterDefinition)
Creates a new filter with the specified configuration, and registers it to the specified group.
Definition: ChangesListFilter.php:142
ChangesListFilter\$name
$name
Filter name.
Definition: ChangesListFilter.php:35
ChangesListFilter\getConflictingFilters
getConflictingFilters()
Get filters conflicting with this filter.
Definition: ChangesListFilter.php:428