MediaWiki  1.30.0
ChangesListFilter.php
Go to the documentation of this file.
1 <?php
30 abstract class ChangesListFilter {
36  protected $name;
37 
46  protected $cssClassSuffix;
47 
54 
60  protected $group;
61 
67  protected $label;
68 
74  protected $description;
75 
82  protected $conflictingGroups = [];
83 
90  protected $conflictingFilters = [];
91 
97  protected $subsetFilters = [];
98 
104  protected $priority;
105 
106  const RESERVED_NAME_CHAR = '_';
107 
137  public function __construct( array $filterDefinition ) {
138  if ( isset( $filterDefinition['group'] ) ) {
139  $this->group = $filterDefinition['group'];
140  } else {
141  throw new MWException( 'You must use \'group\' to specify the ' .
142  'ChangesListFilterGroup this filter belongs to' );
143  }
144 
145  if ( strpos( $filterDefinition['name'], self::RESERVED_NAME_CHAR ) !== false ) {
146  throw new MWException( 'Filter names may not contain \'' .
147  self::RESERVED_NAME_CHAR .
148  '\'. Use the naming convention: \'lowercase\''
149  );
150  }
151 
152  if ( $this->group->getFilter( $filterDefinition['name'] ) ) {
153  throw new MWException( 'Two filters in a group cannot have the ' .
154  "same name: '{$filterDefinition['name']}'" );
155  }
156 
157  $this->name = $filterDefinition['name'];
158 
159  if ( isset( $filterDefinition['cssClassSuffix'] ) ) {
160  $this->cssClassSuffix = $filterDefinition['cssClassSuffix'];
161  $this->isRowApplicableCallable = $filterDefinition['isRowApplicableCallable'];
162  }
163 
164  if ( isset( $filterDefinition['label'] ) ) {
165  $this->label = $filterDefinition['label'];
166  $this->description = $filterDefinition['description'];
167  }
168 
169  $this->priority = $filterDefinition['priority'];
170 
171  $this->group->registerFilter( $this );
172  }
173 
189  public function conflictsWith( $other, $globalKey, $forwardKey, $backwardKey ) {
190  if ( $globalKey === null || $forwardKey === null || $backwardKey === null ) {
191  throw new MWException( 'All messages must be specified' );
192  }
193 
195  $other,
196  $globalKey,
197  $forwardKey
198  );
199 
200  $other->setUnidirectionalConflict(
201  $this,
202  $globalKey,
203  $backwardKey
204  );
205  }
206 
219  public function setUnidirectionalConflict( $other, $globalDescription, $contextDescription ) {
220  if ( $other instanceof ChangesListFilterGroup ) {
221  $this->conflictingGroups[] = [
222  'group' => $other->getName(),
223  'groupObject' => $other,
224  'globalDescription' => $globalDescription,
225  'contextDescription' => $contextDescription,
226  ];
227  } elseif ( $other instanceof ChangesListFilter ) {
228  $this->conflictingFilters[] = [
229  'group' => $other->getGroup()->getName(),
230  'filter' => $other->getName(),
231  'filterObject' => $other,
232  'globalDescription' => $globalDescription,
233  'contextDescription' => $contextDescription,
234  ];
235  } else {
236  throw new MWException( 'You can only pass in a ChangesListFilterGroup or a ChangesListFilter' );
237  }
238  }
239 
249  public function setAsSupersetOf( ChangesListFilter $other ) {
250  if ( $other->getGroup() !== $this->getGroup() ) {
251  throw new MWException( 'Supersets can only be defined for filters in the same group' );
252  }
253 
254  $this->subsetFilters[] = [
255  // It's always the same group, but this makes the representation
256  // more consistent with conflicts.
257  'group' => $other->getGroup()->getName(),
258  'filter' => $other->getName(),
259  ];
260  }
261 
265  public function getName() {
266  return $this->name;
267  }
268 
272  public function getGroup() {
273  return $this->group;
274  }
275 
279  public function getLabel() {
280  return $this->label;
281  }
282 
286  public function getDescription() {
287  return $this->description;
288  }
289 
295  abstract public function displaysOnUnstructuredUi();
296 
303  public function displaysOnStructuredUi() {
304  return $this->label !== null;
305  }
306 
315  return $this->displaysOnStructuredUi();
316  }
317 
321  public function getPriority() {
322  return $this->priority;
323  }
324 
330  protected function getCssClass() {
331  if ( $this->cssClassSuffix !== null ) {
333  } else {
334  return null;
335  }
336  }
337 
345  public function applyCssClassIfNeeded( IContextSource $ctx, RecentChange $rc, array &$classes ) {
346  if ( $this->isRowApplicableCallable === null ) {
347  return;
348  }
349 
350  if ( call_user_func( $this->isRowApplicableCallable, $ctx, $rc ) ) {
351  $classes[] = $this->getCssClass();
352  }
353  }
354 
362  public function getJsData() {
363  $output = [
364  'name' => $this->getName(),
365  'label' => $this->getLabel(),
366  'description' => $this->getDescription(),
367  'cssClass' => $this->getCssClass(),
368  'priority' => $this->priority,
369  'subset' => $this->subsetFilters,
370  'conflicts' => [],
371  ];
372 
373  $output['messageKeys'] = [
374  $this->getLabel(),
375  $this->getDescription(),
376  ];
377 
378  $conflicts = array_merge(
379  $this->conflictingGroups,
380  $this->conflictingFilters
381  );
382 
383  foreach ( $conflicts as $conflictInfo ) {
384  unset( $conflictInfo['filterObject'] );
385  unset( $conflictInfo['groupObject'] );
386  $output['conflicts'][] = $conflictInfo;
387  array_push(
388  $output['messageKeys'],
389  $conflictInfo['globalDescription'],
390  $conflictInfo['contextDescription']
391  );
392  }
393 
394  return $output;
395  }
396 
403  abstract public function isSelected( FormOptions $opts );
404 
410  public function getConflictingGroups() {
411  return array_map(
412  function ( $conflictDesc ) {
413  return $conflictDesc[ 'groupObject' ];
414  },
416  );
417  }
418 
424  public function getConflictingFilters() {
425  return array_map(
426  function ( $conflictDesc ) {
427  return $conflictDesc[ 'filterObject' ];
428  },
430  );
431  }
432 
441  if ( $group->anySelected( $opts ) && $this->isSelected( $opts ) ) {
443  foreach ( $this->getSiblings() as $siblingFilter ) {
444  if ( $siblingFilter->isSelected( $opts ) && !$siblingFilter->hasConflictWithGroup( $group ) ) {
445  return false;
446  }
447  }
448  return true;
449  }
450  return false;
451  }
452 
454  return in_array( $group, $this->getConflictingGroups() );
455  }
456 
464  public function activelyInConflictWithFilter( ChangeslistFilter $filter, FormOptions $opts ) {
465  if ( $this->isSelected( $opts ) && $filter->isSelected( $opts ) ) {
467  foreach ( $this->getSiblings() as $siblingFilter ) {
468  if (
469  $siblingFilter->isSelected( $opts ) &&
470  !$siblingFilter->hasConflictWithFilter( $filter )
471  ) {
472  return false;
473  }
474  }
475  return true;
476  }
477  return false;
478  }
479 
480  private function hasConflictWithFilter( ChangeslistFilter $filter ) {
481  return in_array( $filter, $this->getConflictingFilters() );
482  }
483 
489  protected function getSiblings() {
490  return array_filter(
491  $this->getGroup()->getFilters(),
492  function ( $filter ) {
493  return $filter !== $this;
494  }
495  );
496  }
497 }
ChangesListFilter\activelyInConflictWithGroup
activelyInConflictWithGroup(ChangesListFilterGroup $group, FormOptions $opts)
Check if the conflict with a group is currently "active".
Definition: ChangesListFilter.php:440
ChangesListFilter\isSelected
isSelected(FormOptions $opts)
Checks whether this filter is selected in the provided options.
ChangesListFilter\hasConflictWithFilter
hasConflictWithFilter(ChangeslistFilter $filter)
Definition: ChangesListFilter.php:480
ChangesListFilter\$subsetFilters
$subsetFilters
Array of associative arrays with subset information.
Definition: ChangesListFilter.php:97
RecentChange
Utility class for creating new RC entries.
Definition: RecentChange.php:67
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:249
ChangesListFilter\$priority
$priority
Priority integer.
Definition: ChangesListFilter.php:104
ChangesListFilter\displaysOnStructuredUi
displaysOnStructuredUi()
Checks whether the filter should display on the structured UI This refers to the exact filter.
Definition: ChangesListFilter.php:303
ChangesListFilter\activelyInConflictWithFilter
activelyInConflictWithFilter(ChangeslistFilter $filter, FormOptions $opts)
Check if the conflict with a filter is currently "active".
Definition: ChangesListFilter.php:464
ChangesListFilter\getName
getName()
Definition: ChangesListFilter.php:265
ChangesListFilter\$isRowApplicableCallable
$isRowApplicableCallable
Callable that returns true if and only if a row is attributed to this filter.
Definition: ChangesListFilter.php:53
ChangesListFilterGroup
Represents a filter group (used on ChangesListSpecialPage and descendants)
Definition: ChangesListFilterGroup.php:35
$output
static configuration should be added through ResourceLoaderGetConfigVars instead can be used to get the real title after the basic globals have been set but before ordinary actions take place $output
Definition: hooks.txt:2198
php
injection txt This is an overview of how MediaWiki makes use of dependency injection The design described here grew from the discussion of RFC T384 The term dependency this means that anything an object needs to operate should be injected from the the object itself should only know narrow no concrete implementation of the logic it relies on The requirement to inject everything typically results in an architecture that based on two main types of and essentially stateless service objects that use other service objects to operate on the value objects As of the beginning MediaWiki is only starting to use the DI approach Much of the code still relies on global state or direct resulting in a highly cyclical dependency which acts as the top level factory for services in MediaWiki which can be used to gain access to default instances of various services MediaWikiServices however also allows new services to be defined and default services to be redefined Services are defined or redefined by providing a callback the instantiator that will return a new instance of the service When it will create an instance of MediaWikiServices and populate it with the services defined in the files listed by thereby bootstrapping the DI framework Per $wgServiceWiringFiles lists includes ServiceWiring php
Definition: injection.txt:35
ChangesListFilter\$cssClassSuffix
$cssClassSuffix
CSS class suffix used for attribution, e.g.
Definition: ChangesListFilter.php:46
ChangesListFilter\conflictsWith
conflictsWith( $other, $globalKey, $forwardKey, $backwardKey)
Marks that the given ChangesListFilterGroup or ChangesListFilter conflicts with this object.
Definition: ChangesListFilter.php:189
ChangesListFilter\getGroup
getGroup()
Definition: ChangesListFilter.php:272
MWException
MediaWiki exception.
Definition: MWException.php:26
ChangesListFilter\hasConflictWithGroup
hasConflictWithGroup(ChangesListFilterGroup $group)
Definition: ChangesListFilter.php:453
ChangesListFilter\$label
$label
i18n key of label for structured UI
Definition: ChangesListFilter.php:67
ChangesListFilter\$group
$group
Group.
Definition: ChangesListFilter.php:60
ChangesListFilter\getSiblings
getSiblings()
Get filters in the same group.
Definition: ChangesListFilter.php:489
ChangesListFilter\getConflictingGroups
getConflictingGroups()
Get groups conflicting with this filter.
Definition: ChangesListFilter.php:410
ChangesListFilter\getJsData
getJsData()
Gets the JS data required by the front-end of the structured UI.
Definition: ChangesListFilter.php:362
ChangesListFilter\applyCssClassIfNeeded
applyCssClassIfNeeded(IContextSource $ctx, RecentChange $rc, array &$classes)
Add CSS class if needed.
Definition: ChangesListFilter.php:345
ChangesListFilter\getDescription
getDescription()
Definition: ChangesListFilter.php:286
ChangesList\CSS_CLASS_PREFIX
const CSS_CLASS_PREFIX
Definition: ChangesList.php:29
ChangesListFilter\isFeatureAvailableOnStructuredUi
isFeatureAvailableOnStructuredUi()
Checks whether an equivalent feature for this filter is available on the structured UI.
Definition: ChangesListFilter.php:314
ChangesListFilter\getCssClass
getCssClass()
Gets the CSS class.
Definition: ChangesListFilter.php:330
ChangesListFilter\RESERVED_NAME_CHAR
const RESERVED_NAME_CHAR
Definition: ChangesListFilter.php:106
IContextSource
Interface for objects which can provide a MediaWiki context on request.
Definition: IContextSource.php:55
ChangesListFilter\getLabel
getLabel()
Definition: ChangesListFilter.php:279
ChangesListFilter\$conflictingGroups
$conflictingGroups
Array of associative arrays with conflict information.
Definition: ChangesListFilter.php:82
as
This document is intended to provide useful advice for parties seeking to redistribute MediaWiki to end users It s targeted particularly at maintainers for Linux since it s been observed that distribution packages of MediaWiki often break We ve consistently had to recommend that users seeking support use official tarballs instead of their distribution s and this often solves whatever problem the user is having It would be nice if this could such as
Definition: distributors.txt:9
ChangesListFilter\setUnidirectionalConflict
setUnidirectionalConflict( $other, $globalDescription, $contextDescription)
Marks that the given ChangesListFilterGroup or ChangesListFilter conflicts with this object.
Definition: ChangesListFilter.php:219
ChangesListFilter
Represents a filter (used on ChangesListSpecialPage and descendants)
Definition: ChangesListFilter.php:30
ChangesListFilter\$description
$description
i18n key of description for structured UI
Definition: ChangesListFilter.php:74
ChangesListFilter\$conflictingFilters
$conflictingFilters
Array of associative arrays with conflict information.
Definition: ChangesListFilter.php:90
name
design txt This is a brief overview of the new design More thorough and up to date information is available on the documentation wiki at name
Definition: design.txt:12
ChangesListFilter\getPriority
getPriority()
Definition: ChangesListFilter.php:321
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:137
ChangesListFilter\$name
$name
Filter name.
Definition: ChangesListFilter.php:36
group
no text was provided for refs named< code > blankwithnoreference</code ></span ></li ></ol ></div > ! end ! test with< references/> in group ! wikitext Wikipedia rocks< ref > Proceeds of vol XXI</ref > Wikipedia rocks< ref group=note > Proceeds of vol XXI</ref >< references/>< references group=note/> ! html< p > Wikipedia rocks< sup id="cite_ref-1" class="reference">< a href="#cite_note-1"> &Wikipedia rocks< sup id="cite_ref-2" class="reference">< a href="#cite_note-2"> &</p >< div class="mw-references-wrap">< ol class="references">< li id="cite_note-1">< span class="mw-cite-backlink">< a href="#cite_ref-1"> ↑</a ></span >< span class="reference-text"> Proceeds of vol XXI</span ></li ></ol ></div >< div class="mw-references-wrap">< ol class="references">< li id="cite_note-2">< span class="mw-cite-backlink">< a href="#cite_ref-2"> ↑</a ></span >< span class="reference-text"> Proceeds of vol XXI</span ></li ></ol ></div > ! end ! test with< references/> in group
Definition: citeParserTests.txt:306
ChangesListFilter\getConflictingFilters
getConflictingFilters()
Get filters conflicting with this filter.
Definition: ChangesListFilter.php:424
array
the array() calling protocol came about after MediaWiki 1.4rc1.