Edit Review Improvements/New filters for edit review/How to implement a filter

From MediaWiki.org
Jump to: navigation, search

Product and design[edit]

RCFilters Group With Label Description.svg

There are first some product and design questions to answer:

  • Purpose and effect of the filter - Consider the user experience and use cases. This will both help you decide what the filter does, and how to describe it.
  • Choose text - You will need a label and description, which will be placed as shown in the image. You will also need a group title if you are creating a new group; you can also optionally specify What's This? text to provide more information about the group.
What's This Popup.svg

Listener[edit]

Register a listener for the ChangesListSpecialPageStructuredFilters hook. That will give you access to $special, a ChangesListSpecialPage instance used below.

Group[edit]

First, choose whether you want to create a ChangesListStringOptionsGroup or a ChangesListBooleanFilterGroup . ChangesListStringOptionsGroup is best if you have many options, they are not naturally expressed as hide-based (e.g. hideanons) filters, and/or they are not full coverage (full coverage means checking all boxes in a group is the same as checking no boxes). ChangesListBooleanFilterGroup is best for existing hide-based filters (like hideanons), or filters that can be expressed simply using that idea.

If you are creating a new group, create an object for that. The 'name' is an internal identifier. However, for ChangesListStringOptionsGroup, it's also used as the URL parameter. Either (see above):

$group = new ChangesListBooleanFilterGroup(
    [
        'name' => 'groupname',
        'title' => 'myextension-rcfilters-groupname-title',
        
        'filters' => [
            // Each element of 'filters' is an array using the format
            // passed to the ChangesListBooleanFilter constructor
        ],
    ]
);

or:

$group = new ChangesListStringOptionsFilterGroup(
    [
        'name' => 'groupname',
        'title' => 'myextension-rcfilters-groupname-title',
        'default' => 'foo,bar',
        
        'filters' => [
            // Each element of 'filters' is an array using the format
            // passed to the ChangesListStringOptionsFilter constructor
        ],
        
        'isFullCoverage' => true, // see explanation above for how to choose this value,
        'queryCallable' => function (
            $specialPageClassName,
            IContextSource $context,
            IDatabase $dbr,
            array &$tables,
            array &$fields,
            array &$conds,
            array &$query_options,
            array &$join_conds,
            array $selectedValues
        ) {
            // selectedValues is an array of the values the user chose.
            // Add necessary tables, fields, and conditions to implement your database condition.
        }
    ]
);

Either way, you then register the group with:

$special->registerFilterGroup( $group );

You can optionally include information for a What's This? popup (whatsThisHeader, whatsThisBody, whatsThisUrl, and whatsThisLinkText). If you need to access an existing group (e.g. defined by core), instead use:

$group = $special->getFilterGroup( 'existinggroup' );

Filters[edit]

Regardless of whether you created a group, you will want to add filters to new or existing groups.

If all the filters belong to a group you're creating, you should put the definitions in the filters parameter of the group constructor; this will automatically order them for you. To add filters to pre-existing groups, follow the below instructions.

There are currently two types of filter, ChangesListBooleanFilter and ChangesListStringOptionsFilter. They each go only in the group with the matching type. The 'name' is used as an identifier, which also appears in the URL. Use:

$filter = new ChangesListBooleanFilter(
    [
		'name' => 'hidesomething',
		'group' => $group,
		'label' => 'myextension-rcfilters-groupname-hidesomething-label',
		'description' => 'myextension-rcfilters-groupname-hidesomething-desc',
		'showHideSuffix' => 'myextension-rcfilters-groupname-showhidesomething',
		'default' => false, // true to hide by default, false not to hide by default
		
		// Adjust priority as needed to order your filters where you wish, or use the
		// 'filters' parameter of the group constructor, which handles this.
		'priority' => -1,
		
		'queryCallable' => function ( $specialClassName, $ctx, $dbr, &$tables, &$fields, &$conds,
		    &$query_options, &$join_conds ) {

			// Add necessary tables, fields, and conditions to implement your database condition.
		},
		'cssClassSuffix' => 'something',
		'isRowApplicableCallable' => function ( $ctx, $rc ) {
            // Return true if the $rc row (part of the result set) is controlled by this filter.
            // E.g. if this filter hides logged inusers, and $rc is an action taken
            // by a logged inuser.
		},
    ]
);

or:

$filter = new ChangesListStringOptionsFilter(
    [
		'name' => 'choice',
		'group' => $group,
		'label' => 'myextension-rcfilters-groupname-choice-label',
		'description' => 'myextension-rcfilters-groupname-choice-desc',
		
		// Adjust priority as needed to order your filters where you wish, or use the
		// 'filters' parameter of the group constructor, which handles this.
		'priority' => -1,
		
		'cssClassSuffix' => 'something',
		'isRowApplicableCallable' => function ( $ctx, $rc ) {
            // Return true if the $rc row (part of the output) is controlled by this filter.
            // E.g. if this filter shows log actions, and $rc is a log action.
		},
    ]
);

You do not have to do anything after constructing the filter.