RCFilters: add namespace filters for all contents and all discussions
authorStephane Bisson <sbisson@wikimedia.org>
Thu, 15 Aug 2019 17:24:11 +0000 (13:24 -0400)
committerStephane Bisson <sbisson@wikimedia.org>
Thu, 15 Aug 2019 17:57:02 +0000 (13:57 -0400)
These filters provide a shortcut to see or highlight all entries associated
with a subject or a talk namespace.

They are defined as real filters on the client-side and are superset
of all other namespace filters.

They are expanded to the list of namespaces they represent on the server-side.

Bug: T201520
Change-Id: Id9e04a38c2d7c8165c27af98959aa5715225faa8

includes/changes/ChangesList.php
includes/specialpage/ChangesListSpecialPage.php
languages/i18n/en.json
languages/i18n/qqq.json
resources/Resources.php
resources/src/mediawiki.rcfilters/Controller.js
tests/phpunit/includes/specialpage/ChangesListSpecialPageTest.php

index e2b35a8..7807877 100644 (file)
@@ -232,6 +232,13 @@ class ChangesList extends ContextSource {
                $classes[] = Sanitizer::escapeClass( self::CSS_CLASS_PREFIX . 'ns-' .
                        $rc->mAttribs['rc_namespace'] );
 
+               $nsInfo = MediaWikiServices::getInstance()->getNamespaceInfo();
+               $classes[] = Sanitizer::escapeClass(
+                       self::CSS_CLASS_PREFIX .
+                       'ns-' .
+                       ( $nsInfo->isTalk( $rc->mAttribs['rc_namespace'] ) ? 'talk' : 'subject' )
+               );
+
                if ( $this->filterGroups !== null ) {
                        foreach ( $this->filterGroups as $filterGroup ) {
                                foreach ( $filterGroup->getFilters() as $filter ) {
index bbbd6a8..2fa8fab 100644 (file)
@@ -1503,6 +1503,8 @@ abstract class ChangesListSpecialPage extends SpecialPage {
                if ( $opts[ 'namespace' ] !== '' ) {
                        $namespaces = explode( ';', $opts[ 'namespace' ] );
 
+                       $namespaces = $this->expandSymbolicNamespaceFilters( $namespaces );
+
                        if ( $opts[ 'associated' ] ) {
                                $namespaceInfo = MediaWikiServices::getInstance()->getNamespaceInfo();
                                $associatedNamespaces = array_map(
@@ -1948,4 +1950,21 @@ abstract class ChangesListSpecialPage extends SpecialPage {
        public function getDefaultDays() {
                return floatval( $this->getUser()->getOption( static::$daysPreferenceName ) );
        }
+
+       private function expandSymbolicNamespaceFilters( array $namespaces ) {
+               $nsInfo = MediaWikiServices::getInstance()->getNamespaceInfo();
+               $symbolicFilters = [
+                       'all-contents' => $nsInfo->getSubjectNamespaces(),
+                       'all-discussions' => $nsInfo->getTalkNamespaces(),
+               ];
+               $additionalNamespaces = [];
+               foreach ( $symbolicFilters as $name => $values ) {
+                       if ( in_array( $name, $namespaces ) ) {
+                               $additionalNamespaces = array_merge( $additionalNamespaces, $values );
+                       }
+               }
+               $namespaces = array_diff( $namespaces, array_keys( $symbolicFilters ) );
+               $namespaces = array_merge( $namespaces, $additionalNamespaces );
+               return array_unique( $namespaces );
+       }
 }
index 5e85bf2..32f08dc 100644 (file)
        "rcfilters-filter-showlinkedto-label": "Show changes on pages linking to",
        "rcfilters-filter-showlinkedto-option-label": "<strong>Pages linking to</strong> the selected page",
        "rcfilters-target-page-placeholder": "Enter a page name (or category)",
+       "rcfilters-allcontents-label": "All contents",
+       "rcfilters-alldiscussions-label": "All discussions",
        "rcnotefrom": "Below {{PLURAL:$5|is the change|are the changes}} since <strong>$3, $4</strong> (up to <strong>$1</strong> shown).",
        "rclistfromreset": "Reset date selection",
        "rclistfrom": "Show new changes starting from $2, $3",
index 21b7cc7..acfa996 100644 (file)
        "rcfilters-filter-showlinkedto-label": "Label that indicates that the page is showing changes that link TO the target page. Used on [[Special:Recentchangeslinked]] when structured filters are enabled.",
        "rcfilters-filter-showlinkedto-option-label": "Menu option to show changes TO the target page. Used on [[Special:Recentchangeslinked]] when structured filters are enabled.",
        "rcfilters-target-page-placeholder": "Placeholder text for the title lookup [[Special:Recentchangeslinked]] when structured filters are enabled.",
+       "rcfilters-allcontents-label": "Label of the filter for all content namespaces on [[Special:Recentchanges]] or [[Special:Watchlist]] when structured filters are enabled.",
+       "rcfilters-alldiscussions-label": "Label of the filter for all discussion namespaces on [[Special:Recentchanges]] or [[Special:Watchlist]] when structured filters are enabled.",
        "rcnotefrom": "This message is displayed at [[Special:RecentChanges]] when viewing recentchanges from some specific time.\n\nThe corresponding message is {{msg-mw|Rclistfrom}}.\n\nParameters:\n* $1 - the maximum number of changes that are displayed\n* $2 - (Optional) a date and time\n* $3 - a date\n* $4 - a time\n* $5 - Number of changes are displayed, for use with PLURAL",
        "rclistfromreset": "Used on [[Special:RecentChanges]] to reset a selection of a certain date range.",
        "rclistfrom": "Used on [[Special:RecentChanges]]. Parameters:\n* $1 - (Currently not use) date and time. The date and the time adds to the rclistfrom description.\n* $2 - time. The time adds to the rclistfrom link description (with split of date and time).\n* $3 - date. The date adds to the rclistfrom link description (with split of date and time).\n\nThe corresponding message is {{msg-mw|Rcnotefrom}}.",
index c9a1660..354d4ee 100644 (file)
@@ -1934,6 +1934,8 @@ return [
                        'rcfilters-filter-showlinkedto-label',
                        'rcfilters-filter-showlinkedto-option-label',
                        'rcfilters-target-page-placeholder',
+                       'rcfilters-allcontents-label',
+                       'rcfilters-alldiscussions-label',
                        'blanknamespace',
                        'namespaces',
                        'tags-title',
index 97b73ae..85a4efe 100644 (file)
@@ -58,6 +58,7 @@ OO.initClass( Controller );
  */
 Controller.prototype.initialize = function ( filterStructure, namespaceStructure, tagList, conditionalViews ) {
        var parsedSavedQueries, pieces,
+               nsAllContents, nsAllDiscussions,
                displayConfig = mw.config.get( 'StructuredChangeFiltersDisplayConfig' ),
                defaultSavedQueryExists = mw.config.get( 'wgStructuredChangeFiltersDefaultSavedQueryExists' ),
                controller = this,
@@ -67,20 +68,38 @@ Controller.prototype.initialize = function ( filterStructure, namespaceStructure
 
        // Prepare views
        if ( namespaceStructure ) {
-               items = [];
+               nsAllContents = {
+                       name: 'all-contents',
+                       label: mw.msg( 'rcfilters-allcontents-label' ),
+                       description: '',
+                       identifiers: [ 'subject' ],
+                       cssClass: 'mw-changeslist-ns-subject',
+                       subset: []
+               };
+               nsAllDiscussions = {
+                       name: 'all-discussions',
+                       label: mw.msg( 'rcfilters-alldiscussions-label' ),
+                       description: '',
+                       identifiers: [ 'talk' ],
+                       cssClass: 'mw-changeslist-ns-talk',
+                       subset: []
+               };
+               items = [ nsAllContents, nsAllDiscussions ];
                // eslint-disable-next-line no-jquery/no-each-util
                $.each( namespaceStructure, function ( namespaceID, label ) {
                        // Build and clean up the individual namespace items definition
-                       items.push( {
-                               name: namespaceID,
-                               label: label || mw.msg( 'blanknamespace' ),
-                               description: '',
-                               identifiers: [
-                                       mw.Title.isTalkNamespace( namespaceID ) ?
-                                               'talk' : 'subject'
-                               ],
-                               cssClass: 'mw-changeslist-ns-' + namespaceID
-                       } );
+                       var isTalk = mw.Title.isTalkNamespace( namespaceID ),
+                               nsFilter = {
+                                       name: namespaceID,
+                                       label: label || mw.msg( 'blanknamespace' ),
+                                       description: '',
+                                       identifiers: [
+                                               isTalk ? 'talk' : 'subject'
+                                       ],
+                                       cssClass: 'mw-changeslist-ns-' + namespaceID
+                               };
+                       items.push( nsFilter );
+                       ( isTalk ? nsAllDiscussions : nsAllContents ).subset.push( { filter: namespaceID } );
                } );
 
                views.namespaces = {
index dff18ca..9d58cef 100644 (file)
@@ -1,5 +1,6 @@
 <?php
 
+use MediaWiki\MediaWikiServices;
 use Wikimedia\TestingAccessWrapper;
 
 /**
@@ -209,6 +210,19 @@ class ChangesListSpecialPageTest extends AbstractChangesListSpecialPageTestCase
                );
        }
 
+       public function testRcNsFilterAllContents() {
+               $namespaces = MediaWikiServices::getInstance()->getNamespaceInfo()->getSubjectNamespaces();
+               $this->assertConditions(
+                       [ # expected
+                               'rc_namespace IN (' . $this->db->makeList( $namespaces ) . ')',
+                       ],
+                       [
+                               'namespace' => 'all-contents',
+                       ],
+                       "rc conditions with all-contents"
+               );
+       }
+
        public function testRcHidemyselfFilter() {
                $this->setMwGlobals( 'wgActorTableSchemaMigrationStage', SCHEMA_COMPAT_NEW );
                $this->overrideMwServices();