From 04f0b682a5343a8340b8f56e990a2fcf16363379 Mon Sep 17 00:00:00 2001 From: Stephane Bisson Date: Thu, 15 Aug 2019 13:24:11 -0400 Subject: [PATCH] RCFilters: add namespace filters for all contents and all discussions 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 | 7 ++++ .../specialpage/ChangesListSpecialPage.php | 19 +++++++++ languages/i18n/en.json | 2 + languages/i18n/qqq.json | 2 + resources/Resources.php | 2 + .../src/mediawiki.rcfilters/Controller.js | 41 ++++++++++++++----- .../ChangesListSpecialPageTest.php | 14 +++++++ 7 files changed, 76 insertions(+), 11 deletions(-) diff --git a/includes/changes/ChangesList.php b/includes/changes/ChangesList.php index e2b35a8632..78078770b2 100644 --- a/includes/changes/ChangesList.php +++ b/includes/changes/ChangesList.php @@ -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 ) { diff --git a/includes/specialpage/ChangesListSpecialPage.php b/includes/specialpage/ChangesListSpecialPage.php index bbbd6a8585..2fa8fab647 100644 --- a/includes/specialpage/ChangesListSpecialPage.php +++ b/includes/specialpage/ChangesListSpecialPage.php @@ -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 ); + } } diff --git a/languages/i18n/en.json b/languages/i18n/en.json index 5e85bf29a9..32f08dc5a3 100644 --- a/languages/i18n/en.json +++ b/languages/i18n/en.json @@ -1584,6 +1584,8 @@ "rcfilters-filter-showlinkedto-label": "Show changes on pages linking to", "rcfilters-filter-showlinkedto-option-label": "Pages linking to 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 $3, $4 (up to $1 shown).", "rclistfromreset": "Reset date selection", "rclistfrom": "Show new changes starting from $2, $3", diff --git a/languages/i18n/qqq.json b/languages/i18n/qqq.json index 21b7cc7b30..acfa996a87 100644 --- a/languages/i18n/qqq.json +++ b/languages/i18n/qqq.json @@ -1793,6 +1793,8 @@ "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}}.", diff --git a/resources/Resources.php b/resources/Resources.php index c9a1660ed3..354d4eecf9 100644 --- a/resources/Resources.php +++ b/resources/Resources.php @@ -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', diff --git a/resources/src/mediawiki.rcfilters/Controller.js b/resources/src/mediawiki.rcfilters/Controller.js index 97b73ae2bd..85a4efe5f7 100644 --- a/resources/src/mediawiki.rcfilters/Controller.js +++ b/resources/src/mediawiki.rcfilters/Controller.js @@ -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 = { diff --git a/tests/phpunit/includes/specialpage/ChangesListSpecialPageTest.php b/tests/phpunit/includes/specialpage/ChangesListSpecialPageTest.php index dff18ca286..9d58cef71e 100644 --- a/tests/phpunit/includes/specialpage/ChangesListSpecialPageTest.php +++ b/tests/phpunit/includes/specialpage/ChangesListSpecialPageTest.php @@ -1,5 +1,6 @@ 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(); -- 2.20.1