X-Git-Url: https://git.heureux-cyclage.org/?p=lhc%2Fweb%2Fwiklou.git;a=blobdiff_plain;f=includes%2Fspecialpage%2FChangesListSpecialPage.php;h=67f68ea10aa26fc5a61c435a228b9702826d60a6;hp=6fd33a7cedf7ac3128efc5a9ff6cbdbc946c2661;hb=d94c0484302f80cf30ef107b2fdb6b84293e1937;hpb=b747307a2002c0c86fd6bbd1e0d96f5a717df8f2 diff --git a/includes/specialpage/ChangesListSpecialPage.php b/includes/specialpage/ChangesListSpecialPage.php index 6fd33a7ced..67f68ea10a 100644 --- a/includes/specialpage/ChangesListSpecialPage.php +++ b/includes/specialpage/ChangesListSpecialPage.php @@ -540,6 +540,8 @@ abstract class ChangesListSpecialPage extends SpecialPage { public function execute( $subpage ) { $this->rcSubpage = $subpage; + $this->considerActionsForDefaultSavedQuery(); + $rows = $this->getRows(); $opts = $this->getOptions(); if ( $rows === false ) { @@ -591,6 +593,77 @@ abstract class ChangesListSpecialPage extends SpecialPage { $this->includeRcFiltersApp(); } + /** + * Check whether or not the page should load defaults, and if so, whether + * a default saved query is relevant to be redirected to. If it is relevant, + * redirect properly with all necessary query parameters. + */ + protected function considerActionsForDefaultSavedQuery() { + if ( !$this->isStructuredFilterUiEnabled() ) { + return; + } + + $knownParams = call_user_func_array( + [ $this->getRequest(), 'getValues' ], + array_keys( $this->getOptions()->getAllValues() ) + ); + + // HACK: Temporarily until we can properly define "sticky" filters and parameters, + // we need to exclude several parameters we know should not be counted towards preventing + // the loading of defaults. + $excludedParams = [ 'limit' => '', 'days' => '', 'enhanced' => '', 'from' => '' ]; + $knownParams = array_diff_key( $knownParams, $excludedParams ); + + if ( + // If there are NO known parameters in the URL request + // (that are not excluded) then we need to check into loading + // the default saved query + count( $knownParams ) === 0 + ) { + // Get the saved queries data and parse it + $savedQueries = FormatJson::decode( + $this->getUser()->getOption( static::$savedQueriesPreferenceName ), + true + ); + + if ( $savedQueries && isset( $savedQueries[ 'default' ] ) ) { + // Only load queries that are 'version' 2, since those + // have parameter representation + if ( isset( $savedQueries[ 'version' ] ) && $savedQueries[ 'version' ] === '2' ) { + $savedQueryDefaultID = $savedQueries[ 'default' ]; + $defaultQuery = $savedQueries[ 'queries' ][ $savedQueryDefaultID ][ 'data' ]; + + // Build the entire parameter list + $query = array_merge( + $defaultQuery[ 'params' ], + $defaultQuery[ 'highlights' ], + [ + 'urlversion' => '2', + ] + ); + // Add to the query any parameters that we may have ignored before + // but are still valid and requested in the URL + $query = array_merge( $this->getRequest()->getValues(), $query ); + unset( $query[ 'title' ] ); + $this->getOutput()->redirect( $this->getPageTitle()->getCanonicalURL( $query ) ); + } else { + // There's a default, but the version is not 2, and the server can't + // actually recognize the query itself. This happens if it is before + // the conversion, so we need to tell the UI to reload saved query as + // it does the conversion to version 2 + $this->getOutput()->addJsConfigVars( + 'wgStructuredChangeFiltersDefaultSavedQueryExists', + true + ); + + // Add the class that tells the frontend it is still loading + // another query + $this->getOutput()->addBodyClasses( 'mw-rcfilters-ui-loading' ); + } + } + } + } + /** * Include the modules and configuration for the RCFilters app. * Conditional on the user having the feature enabled. @@ -619,7 +692,7 @@ abstract class ChangesListSpecialPage extends SpecialPage { $out->addJsConfigVars( 'wgRCFiltersChangeTags', - $this->buildChangeTagList() + $this->getChangeTagList() ); $out->addJsConfigVars( 'StructuredChangeFiltersDisplayConfig', @@ -632,25 +705,15 @@ abstract class ChangesListSpecialPage extends SpecialPage { ] ); + $out->addJsConfigVars( + 'wgStructuredChangeFiltersSavedQueriesPreferenceName', + static::$savedQueriesPreferenceName + ); + $out->addJsConfigVars( 'StructuredChangeFiltersLiveUpdatePollingRate', $this->getConfig()->get( 'StructuredChangeFiltersLiveUpdatePollingRate' ) ); - - if ( static::$savedQueriesPreferenceName ) { - $savedQueries = FormatJson::decode( - $this->getUser()->getOption( static::$savedQueriesPreferenceName ) - ); - if ( $savedQueries && isset( $savedQueries->default ) ) { - // If there is a default saved query, show a loading spinner, - // since the frontend is going to reload the results - $out->addBodyClasses( 'mw-rcfilters-ui-loading' ); - } - $out->addJsConfigVars( - 'wgStructuredChangeFiltersSavedQueriesPreferenceName', - static::$savedQueriesPreferenceName - ); - } } else { $out->addBodyClasses( 'mw-rcfilters-disabled' ); } @@ -661,49 +724,60 @@ abstract class ChangesListSpecialPage extends SpecialPage { * * @return Array Tag data */ - protected function buildChangeTagList() { - $explicitlyDefinedTags = array_fill_keys( ChangeTags::listExplicitlyDefinedTags(), 0 ); - $softwareActivatedTags = array_fill_keys( ChangeTags::listSoftwareActivatedTags(), 0 ); - - // Hit counts disabled for perf reasons, see T169997 - /* - $tagStats = ChangeTags::tagUsageStatistics(); - $tagHitCounts = array_merge( $explicitlyDefinedTags, $softwareActivatedTags, $tagStats ); - - // Sort by hits - arsort( $tagHitCounts ); - */ - $tagHitCounts = array_merge( $explicitlyDefinedTags, $softwareActivatedTags ); - - // Build the list and data - $result = []; - foreach ( $tagHitCounts as $tagName => $hits ) { - if ( - // Only get active tags - isset( $explicitlyDefinedTags[ $tagName ] ) || - isset( $softwareActivatedTags[ $tagName ] ) - ) { - // Parse description - $desc = ChangeTags::tagLongDescriptionMessage( $tagName, $this->getContext() ); - - $result[] = [ - 'name' => $tagName, - 'label' => Sanitizer::stripAllTags( - ChangeTags::tagDescription( $tagName, $this->getContext() ) - ), - 'description' => $desc ? Sanitizer::stripAllTags( $desc->parse() ) : '', - 'cssClass' => Sanitizer::escapeClass( 'mw-tag-' . $tagName ), - 'hits' => $hits, - ]; - } - } + protected function getChangeTagList() { + $cache = ObjectCache::getMainWANInstance(); + $context = $this->getContext(); + return $cache->getWithSetCallback( + $cache->makeKey( 'changeslistspecialpage-changetags', $context->getLanguage()->getCode() ), + $cache::TTL_MINUTE * 10, + function () use ( $context ) { + $explicitlyDefinedTags = array_fill_keys( ChangeTags::listExplicitlyDefinedTags(), 0 ); + $softwareActivatedTags = array_fill_keys( ChangeTags::listSoftwareActivatedTags(), 0 ); + + // Hit counts disabled for perf reasons, see T169997 + /* + $tagStats = ChangeTags::tagUsageStatistics(); + $tagHitCounts = array_merge( $explicitlyDefinedTags, $softwareActivatedTags, $tagStats ); + + // Sort by hits + arsort( $tagHitCounts ); + */ + $tagHitCounts = array_merge( $explicitlyDefinedTags, $softwareActivatedTags ); + + // Build the list and data + $result = []; + foreach ( $tagHitCounts as $tagName => $hits ) { + if ( + // Only get active tags + isset( $explicitlyDefinedTags[ $tagName ] ) || + isset( $softwareActivatedTags[ $tagName ] ) + ) { + // Parse description + $desc = ChangeTags::tagLongDescriptionMessage( $tagName, $context ); + + $result[] = [ + 'name' => $tagName, + 'label' => Sanitizer::stripAllTags( + ChangeTags::tagDescription( $tagName, $context ) + ), + 'description' => $desc ? Sanitizer::stripAllTags( $desc->parse() ) : '', + 'cssClass' => Sanitizer::escapeClass( 'mw-tag-' . $tagName ), + 'hits' => $hits, + ]; + } + } - // Instead of sorting by hit count (disabled, see above), sort by display name - usort( $result, function ( $a, $b ) { - return strcasecmp( $a['label'], $b['label'] ); - } ); + // Instead of sorting by hit count (disabled, see above), sort by display name + usort( $result, function ( $a, $b ) { + return strcasecmp( $a['label'], $b['label'] ); + } ); - return $result; + return $result; + }, + [ + 'lockTSE' => 30 + ] + ); } /** @@ -896,6 +970,23 @@ abstract class ChangesListSpecialPage extends SpecialPage { return $unstructuredGroupDefinition; } + /** + * @return array The legacy show/hide toggle filters + */ + protected function getLegacyShowHideFilters() { + $filters = []; + foreach ( $this->filterGroups as $group ) { + if ( $group instanceof ChangesListBooleanFilterGroup ) { + foreach ( $group->getFilters() as $key => $filter ) { + if ( $filter->displaysOnUnstructuredUi( $this ) ) { + $filters[ $key ] = $filter; + } + } + } + } + return $filters; + } + /** * Register all the filters, including legacy hook-driven ones. * Then create a FormOptions object with options as specified by the user @@ -936,19 +1027,9 @@ abstract class ChangesListSpecialPage extends SpecialPage { // If urlversion=2 is set, ignore the filter defaults and set them all to false/empty $useDefaults = $this->getRequest()->getInt( 'urlversion' ) !== 2; - // Add all filters /** @var ChangesListFilterGroup $filterGroup */ foreach ( $this->filterGroups as $filterGroup ) { - // URL parameters can be per-group, like 'userExpLevel', - // or per-filter, like 'hideminor'. - if ( $filterGroup->isPerGroupRequestParameter() ) { - $opts->add( $filterGroup->getName(), $useDefaults ? $filterGroup->getDefault() : '' ); - } else { - /** @var ChangesListBooleanFilter $filter */ - foreach ( $filterGroup->getFilters() as $filter ) { - $opts->add( $filter->getName(), $useDefaults ? $filter->getDefault( $structuredUI ) : false ); - } - } + $filterGroup->addOptions( $opts, $useDefaults, $structuredUI ); } $opts->add( 'namespace', '', FormOptions::STRING ); @@ -1079,9 +1160,9 @@ abstract class ChangesListSpecialPage extends SpecialPage { // or per-filter, like 'hideminor'. foreach ( $this->filterGroups as $filterGroup ) { - if ( $filterGroup->isPerGroupRequestParameter() ) { + if ( $filterGroup instanceof ChangesListStringOptionsFilterGroup ) { $stringParameterNameSet[$filterGroup->getName()] = true; - } elseif ( $filterGroup->getType() === ChangesListBooleanFilterGroup::TYPE ) { + } elseif ( $filterGroup instanceof ChangesListBooleanFilterGroup ) { foreach ( $filterGroup->getFilters() as $filter ) { $hideParameterNameSet[$filter->getName()] = true; } @@ -1111,7 +1192,10 @@ abstract class ChangesListSpecialPage extends SpecialPage { * @param FormOptions $opts */ public function validateOptions( FormOptions $opts ) { - if ( $this->fixContradictoryOptions( $opts ) ) { + $isContradictory = $this->fixContradictoryOptions( $opts ); + $isReplaced = $this->replaceOldOptions( $opts ); + + if ( $isContradictory || $isReplaced ) { $query = wfArrayToCgi( $this->convertParamsForLink( $opts->getChangedValues() ) ); $this->getOutput()->redirect( $this->getPageTitle()->getCanonicalURL( $query ) ); } @@ -1182,6 +1266,34 @@ abstract class ChangesListSpecialPage extends SpecialPage { return false; } + /** + * Replace old options 'hideanons' or 'hideliu' with structured UI equivalent + * + * @param FormOptions $opts + * @return bool True if the change was made + */ + public function replaceOldOptions( FormOptions $opts ) { + if ( !$this->isStructuredFilterUiEnabled() ) { + return false; + } + + // At this point 'hideanons' and 'hideliu' cannot be both true, + // because fixBackwardsCompatibilityOptions resets (at least) 'hideanons' in such case + if ( $opts[ 'hideanons' ] ) { + $opts->reset( 'hideanons' ); + $opts[ 'userExpLevel' ] = 'registered'; + return true; + } + + if ( $opts[ 'hideliu' ] ) { + $opts->reset( 'hideliu' ); + $opts[ 'userExpLevel' ] = 'unregistered'; + return true; + } + + return false; + } + /** * Convert parameters values from true/false to 1/0 * so they are not omitted by wfArrayToCgi() @@ -1217,20 +1329,10 @@ abstract class ChangesListSpecialPage extends SpecialPage { $dbr = $this->getDB(); $isStructuredUI = $this->isStructuredFilterUiEnabled(); + /** @var ChangesListFilterGroup $filterGroup */ foreach ( $this->filterGroups as $filterGroup ) { - // URL parameters can be per-group, like 'userExpLevel', - // or per-filter, like 'hideminor'. - if ( $filterGroup->isPerGroupRequestParameter() ) { - $filterGroup->modifyQuery( $dbr, $this, $tables, $fields, $conds, - $query_options, $join_conds, $opts[$filterGroup->getName()] ); - } else { - foreach ( $filterGroup->getFilters() as $filter ) { - if ( $filter->isActive( $opts, $isStructuredUI ) ) { - $filter->modifyQuery( $dbr, $this, $tables, $fields, $conds, - $query_options, $join_conds ); - } - } - } + $filterGroup->modifyQuery( $dbr, $this, $tables, $fields, $conds, + $query_options, $join_conds, $opts, $isStructuredUI ); } // Namespace filtering @@ -1456,8 +1558,10 @@ abstract class ChangesListSpecialPage extends SpecialPage { $context->msg( 'recentchanges-legend-heading' )->parse(); # Collapsible + $collapsedState = $this->getRequest()->getCookie( 'changeslist-state' ); + $collapsedClass = $collapsedState === 'collapsed' ? ' mw-collapsed' : ''; $legend = - '
' . + '
' . $legendHeading . '
' . $legend . '
' . '
';