*/
protected $description;
- /**
- * Callable used to check whether this filter is allowed to take effect
- *
- * @var callable $isAllowedCallable
- */
- protected $isAllowedCallable;
-
/**
* List of conflicting groups
*
* $filterDefinition['label'] string i18n key of label for structured UI.
* $filterDefinition['description'] string i18n key of description for structured
* UI.
- * $filterDefinition['isAllowedCallable'] callable Callable taking two parameters,
- * the class name of the special page and an IContextSource, and returning true
- * if and only if the current user is permitted to use this filter on the current
- * wiki. If it returns false, it will both hide the UI (in all UIs) and prevent
- * the DB query modification from taking effect. (optional, defaults to allowed)
* $filterDefinition['priority'] int Priority integer. Higher value means higher
* up in the group's filter list.
*/
$this->description = $filterDefinition['description'];
}
- if ( isset( $filterDefinition['isAllowedCallable'] ) ) {
- $this->isAllowedCallable = $filterDefinition['isAllowedCallable'];
- }
-
$this->priority = $filterDefinition['priority'];
$this->group->registerFilter( $this );
if ( $other instanceof ChangesListFilterGroup ) {
$this->conflictingGroups[] = [
'group' => $other->getName(),
+ 'groupObject' => $other,
'globalDescription' => $globalDescription,
'contextDescription' => $contextDescription,
];
$this->conflictingFilters[] = [
'group' => $other->getGroup()->getName(),
'filter' => $other->getName(),
+ 'filterObject' => $other,
'globalDescription' => $globalDescription,
'contextDescription' => $contextDescription,
];
/**
* Checks whether the filter should display on the unstructured UI
*
- * @param ChangesListSpecialPage $specialPage Current special page
* @return bool Whether to display
*/
- abstract public function displaysOnUnstructuredUi( ChangesListSpecialPage $specialPage );
+ abstract public function displaysOnUnstructuredUi();
/**
* Checks whether the filter should display on the structured UI
* This refers to the exact filter. See also isFeatureAvailableOnStructuredUi.
*
- * @param ChangesListSpecialPage $specialPage Current special page
* @return bool Whether to display
*/
- public function displaysOnStructuredUi( ChangesListSpecialPage $specialPage ) {
- return $this->label !== null && $this->isAllowed( $specialPage );
+ public function displaysOnStructuredUi() {
+ return $this->label !== null;
}
/**
*
* This can either be the exact filter, or a new filter that replaces it.
*/
- public function isFeatureAvailableOnStructuredUi( ChangesListSpecialPage $specialPage ) {
- return $this->displaysOnStructuredUi( $specialPage );
+ public function isFeatureAvailableOnStructuredUi() {
+ return $this->displaysOnStructuredUi();
}
/**
return $this->priority;
}
- /**
- * Checks whether the filter is allowed for the current context
- *
- * @param ChangesListSpecialPage $specialPage Current special page
- * @return bool Whether it is allowed
- */
- public function isAllowed( ChangesListSpecialPage $specialPage ) {
- if ( $this->isAllowedCallable === null ) {
- return true;
- } else {
- return call_user_func(
- $this->isAllowedCallable,
- get_class( $specialPage ),
- $specialPage->getContext()
- );
- }
- }
-
/**
* Gets the CSS class
*
);
foreach ( $conflicts as $conflictInfo ) {
+ unset( $conflictInfo['filterObject'] );
+ unset( $conflictInfo['groupObject'] );
$output['conflicts'][] = $conflictInfo;
array_push(
$output['messageKeys'],
return $output;
}
+
+ /**
+ * Checks whether this filter is selected in the provided options
+ *
+ * @param FormOptions $opts
+ * @return bool
+ */
+ abstract public function isSelected( FormOptions $opts );
+
+ /**
+ * Get groups conflicting with this filter
+ *
+ * @return ChangesListFilterGroup[]
+ */
+ public function getConflictingGroups() {
+ return array_map(
+ function ( $conflictDesc ) {
+ return $conflictDesc[ 'groupObject' ];
+ },
+ $this->conflictingGroups
+ );
+ }
+
+ /**
+ * Get filters conflicting with this filter
+ *
+ * @return ChangesListFilter[]
+ */
+ public function getConflictingFilters() {
+ return array_map(
+ function ( $conflictDesc ) {
+ return $conflictDesc[ 'filterObject' ];
+ },
+ $this->conflictingFilters
+ );
+ }
+
+ /**
+ * Check if the conflict with a group is currently "active"
+ *
+ * @param ChangesListFilterGroup $group
+ * @param FormOptions $opts
+ * @return bool
+ */
+ public function activelyInConflictWithGroup( ChangesListFilterGroup $group, FormOptions $opts ) {
+ if ( $group->anySelected( $opts ) && $this->isSelected( $opts ) ) {
+ /** @var ChangesListFilter $siblingFilter */
+ foreach ( $this->getSiblings() as $siblingFilter ) {
+ if ( $siblingFilter->isSelected( $opts ) && !$siblingFilter->hasConflictWithGroup( $group ) ) {
+ return false;
+ }
+ }
+ return true;
+ }
+ return false;
+ }
+
+ private function hasConflictWithGroup( ChangesListFilterGroup $group ) {
+ return in_array( $group, $this->getConflictingGroups() );
+ }
+
+ /**
+ * Check if the conflict with a filter is currently "active"
+ *
+ * @param ChangesListFilter $filter
+ * @param FormOptions $opts
+ * @return bool
+ */
+ public function activelyInConflictWithFilter( ChangeslistFilter $filter, FormOptions $opts ) {
+ if ( $this->isSelected( $opts ) && $filter->isSelected( $opts ) ) {
+ /** @var ChangesListFilter $siblingFilter */
+ foreach ( $this->getSiblings() as $siblingFilter ) {
+ if (
+ $siblingFilter->isSelected( $opts ) &&
+ !$siblingFilter->hasConflictWithFilter( $filter )
+ ) {
+ return false;
+ }
+ }
+ return true;
+ }
+ return false;
+ }
+
+ private function hasConflictWithFilter( ChangeslistFilter $filter ) {
+ return in_array( $filter, $this->getConflictingFilters() );
+ }
+
+ /**
+ * Get filters in the same group
+ *
+ * @return ChangesListFilter[]
+ */
+ protected function getSiblings() {
+ return array_filter(
+ $this->getGroup()->getFilters(),
+ function ( $filter ) {
+ return $filter !== $this;
+ }
+ );
+ }
}