X-Git-Url: https://git.heureux-cyclage.org/?a=blobdiff_plain;f=includes%2Fspecialpage%2FChangesListSpecialPage.php;h=51949839646ae7b2526602193b613757510dfab7;hb=5120937028f768749d058aa91dde82a96de0af1c;hp=3f452505086939ca1cb1a759723e467ca4bcbe61;hpb=90845301542482bd4e502221e6485a7375193529;p=lhc%2Fweb%2Fwiklou.git diff --git a/includes/specialpage/ChangesListSpecialPage.php b/includes/specialpage/ChangesListSpecialPage.php index 3f45250508..5194983964 100644 --- a/includes/specialpage/ChangesListSpecialPage.php +++ b/includes/specialpage/ChangesListSpecialPage.php @@ -21,6 +21,7 @@ * @ingroup SpecialPage */ use MediaWiki\Logger\LoggerFactory; +use Wikimedia\Rdbms\DBQueryTimeoutError; use Wikimedia\Rdbms\ResultWrapper; use Wikimedia\Rdbms\FakeResultWrapper; use Wikimedia\Rdbms\IDatabase; @@ -542,45 +543,57 @@ abstract class ChangesListSpecialPage extends SpecialPage { $this->considerActionsForDefaultSavedQuery(); - $rows = $this->getRows(); $opts = $this->getOptions(); - if ( $rows === false ) { - $rows = new FakeResultWrapper( [] ); - } + try { + $rows = $this->getRows(); + if ( $rows === false ) { + $rows = new FakeResultWrapper( [] ); + } - // Used by Structured UI app to get results without MW chrome - if ( $this->getRequest()->getVal( 'action' ) === 'render' ) { - $this->getOutput()->setArticleBodyOnly( true ); - } + // Used by Structured UI app to get results without MW chrome + if ( $this->getRequest()->getVal( 'action' ) === 'render' ) { + $this->getOutput()->setArticleBodyOnly( true ); + } - // Used by "live update" and "view newest" to check - // if there's new changes with minimal data transfer - if ( $this->getRequest()->getBool( 'peek' ) ) { + // Used by "live update" and "view newest" to check + // if there's new changes with minimal data transfer + if ( $this->getRequest()->getBool( 'peek' ) ) { $code = $rows->numRows() > 0 ? 200 : 204; - $this->getOutput()->setStatusCode( $code ); - return; - } + $this->getOutput()->setStatusCode( $code ); + return; + } - $batch = new LinkBatch; - foreach ( $rows as $row ) { - $batch->add( NS_USER, $row->rc_user_text ); - $batch->add( NS_USER_TALK, $row->rc_user_text ); - $batch->add( $row->rc_namespace, $row->rc_title ); - if ( $row->rc_source === RecentChange::SRC_LOG ) { - $formatter = LogFormatter::newFromRow( $row ); - foreach ( $formatter->getPreloadTitles() as $title ) { - $batch->addObj( $title ); + $batch = new LinkBatch; + foreach ( $rows as $row ) { + $batch->add( NS_USER, $row->rc_user_text ); + $batch->add( NS_USER_TALK, $row->rc_user_text ); + $batch->add( $row->rc_namespace, $row->rc_title ); + if ( $row->rc_source === RecentChange::SRC_LOG ) { + $formatter = LogFormatter::newFromRow( $row ); + foreach ( $formatter->getPreloadTitles() as $title ) { + $batch->addObj( $title ); + } } } - } - $batch->execute(); + $batch->execute(); - $this->setHeaders(); - $this->outputHeader(); - $this->addModules(); - $this->webOutput( $rows, $opts ); + $this->setHeaders(); + $this->outputHeader(); + $this->addModules(); + $this->webOutput( $rows, $opts ); - $rows->free(); + $rows->free(); + } catch ( DBQueryTimeoutError $timeoutException ) { + MWExceptionHandler::logException( $timeoutException ); + + $this->setHeaders(); + $this->outputHeader(); + $this->addModules(); + + $this->getOutput()->setStatusCode( 500 ); + $this->webOutputHeader( 0, $opts ); + $this->outputTimeout(); + } if ( $this->getConfig()->get( 'EnableWANCacheReaper' ) ) { // Clean up any bad page entries for titles showing up in RC @@ -791,6 +804,17 @@ abstract class ChangesListSpecialPage extends SpecialPage { ); } + /** + * Add the "timeout" message to the output + */ + protected function outputTimeout() { + $this->getOutput()->addHTML( + '
' . + $this->msg( 'recentchanges-timeout' )->parse() . + '
' + ); + } + /** * Get the database result for this special page instance. Used by ApiFeedRecentChanges. * @@ -970,6 +994,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 @@ -1010,19 +1051,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 ); @@ -1153,9 +1184,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; } @@ -1185,7 +1216,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 ) ); } @@ -1256,6 +1290,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() @@ -1291,22 +1353,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() ) { - if ( $filterGroup->isActive( $isStructuredUI ) ) { - $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 @@ -1362,8 +1412,10 @@ abstract class ChangesListSpecialPage extends SpecialPage { protected function doMainQuery( $tables, $fields, $conds, $query_options, $join_conds, FormOptions $opts ) { - $tables[] = 'recentchanges'; - $fields = array_merge( RecentChange::selectFields(), $fields ); + $rcQuery = RecentChange::getQueryInfo(); + $tables = array_merge( $tables, $rcQuery['tables'] ); + $fields = array_merge( $rcQuery['fields'], $fields ); + $join_conds = array_merge( $join_conds, $rcQuery['joins'] ); ChangeTags::modifyDisplayQuery( $tables, @@ -1411,16 +1463,26 @@ abstract class ChangesListSpecialPage extends SpecialPage { } /** - * Send output to the OutputPage object, only called if not used feeds + * Send header output to the OutputPage object, only called if not using feeds * - * @param ResultWrapper $rows Database rows + * @param int $rowCount Number of database rows * @param FormOptions $opts */ - public function webOutput( $rows, $opts ) { + private function webOutputHeader( $rowCount, $opts ) { if ( !$this->including() ) { $this->outputFeedLinks(); - $this->doHeader( $opts, $rows->numRows() ); + $this->doHeader( $opts, $rowCount ); } + } + + /** + * Send output to the OutputPage object, only called if not used feeds + * + * @param ResultWrapper $rows Database rows + * @param FormOptions $opts + */ + public function webOutput( $rows, $opts ) { + $this->webOutputHeader( $rows->numRows(), $opts ); $this->outputChangesList( $rows, $opts ); }