X-Git-Url: https://git.heureux-cyclage.org/?a=blobdiff_plain;f=includes%2FMediaWiki.php;h=7846ca428c7f9375615303161b3b79c5451e6aba;hb=f8e44b8b113f9f9d1d09412f082f36000cfde379;hp=3b5a1b107c9213060f89b70220ca54b12346ff13;hpb=13e788862bc4349d732286970d57cd8375a7d774;p=lhc%2Fweb%2Fwiklou.git diff --git a/includes/MediaWiki.php b/includes/MediaWiki.php index 3b5a1b107c..7846ca428c 100644 --- a/includes/MediaWiki.php +++ b/includes/MediaWiki.php @@ -379,23 +379,26 @@ class MediaWiki { * Initialize the main Article object for "standard" actions (view, etc) * Create an Article object for the page, following redirects if needed. * - * @return mixed An Article, or a string to redirect to another URL + * @return Article|string An Article, or a string to redirect to another URL */ private function initializeArticle() { - $title = $this->context->getTitle(); if ( $this->context->canUseWikiPage() ) { // Try to use request context wiki page, as there // is already data from db saved in per process // cache there from this->getAction() call. $page = $this->context->getWikiPage(); - $article = Article::newFromWikiPage( $page, $this->context ); } else { // This case should not happen, but just in case. - $article = Article::newFromTitle( $title, $this->context ); - $this->context->setWikiPage( $article->getPage() ); + // @TODO: remove this or use an exception + $page = WikiPage::factory( $title ); + $this->context->setWikiPage( $page ); + wfWarn( "RequestContext::canUseWikiPage() returned false" ); } + // Make GUI wrapper for the WikiPage + $article = Article::newFromWikiPage( $page, $this->context ); + // Skip some unnecessary code if the content model doesn't support redirects if ( !ContentHandler::getForTitle( $title )->supportsRedirects() ) { return $article; @@ -406,7 +409,7 @@ class MediaWiki { // Namespace might change when using redirects // Check for redirects ... $action = $request->getVal( 'action', 'view' ); - $file = ( $title->getNamespace() == NS_FILE ) ? $article->getFile() : null; + $file = ( $page instanceof WikiFilePage ) ? $page->getFile() : null; if ( ( $action == 'view' || $action == 'render' ) // ... for actions that show content && !$request->getVal( 'oldid' ) // ... and are not old revisions && !$request->getVal( 'diff' ) // ... and not when showing diff @@ -419,12 +422,13 @@ class MediaWiki { Hooks::run( 'InitializeArticleMaybeRedirect', array( &$title, &$request, &$ignoreRedirect, &$target, &$article ) ); + $page = $article->getPage(); // reflect any hook changes // Follow redirects only for... redirects. // If $target is set, then a hook wanted to redirect. - if ( !$ignoreRedirect && ( $target || $article->isRedirect() ) ) { + if ( !$ignoreRedirect && ( $target || $page->isRedirect() ) ) { // Is the target already set by an extension? - $target = $target ? $target : $article->followRedirect(); + $target = $target ? $target : $page->followRedirect(); if ( is_string( $target ) ) { if ( !$this->config->get( 'DisableHardRedirects' ) ) { // we'll need to redirect @@ -433,16 +437,19 @@ class MediaWiki { } if ( is_object( $target ) ) { // Rewrite environment to redirected article - $rarticle = Article::newFromTitle( $target, $this->context ); - $rarticle->loadPageData(); - if ( $rarticle->exists() || ( is_object( $file ) && !$file->isLocal() ) ) { + $rpage = WikiPage::factory( $target ); + $rpage->loadPageData(); + if ( $rpage->exists() || ( is_object( $file ) && !$file->isLocal() ) ) { + $rarticle = Article::newFromWikiPage( $rpage, $this->context ); $rarticle->setRedirectedFrom( $title ); + $article = $rarticle; $this->context->setTitle( $target ); $this->context->setWikiPage( $article->getPage() ); } } } else { + // Article may have been changed by hook $this->context->setTitle( $article->getTitle() ); $this->context->setWikiPage( $article->getPage() ); } @@ -458,7 +465,6 @@ class MediaWiki { * @param Title $requestTitle The original title, before any redirects were applied */ private function performAction( Page $page, Title $requestTitle ) { - $request = $this->context->getRequest(); $output = $this->context->getOutput(); $title = $this->context->getTitle(); @@ -471,10 +477,16 @@ class MediaWiki { } $act = $this->getAction(); - $action = Action::factory( $act, $page, $this->context ); if ( $action instanceof Action ) { + // Narrow DB query expectations for this HTTP request + $trxLimits = $this->config->get( 'TrxProfilerLimits' ); + $trxProfiler = Profiler::instance()->getTransactionProfiler(); + if ( $request->wasPosted() && !$action->doesWrites() ) { + $trxProfiler->setExpectations( $trxLimits['POST-nonwrite'], __METHOD__ ); + } + # Let CDN cache things if we can purge them. if ( $this->config->get( 'UseSquid' ) && in_array( @@ -494,7 +506,6 @@ class MediaWiki { $output->setStatusCode( 404 ); $output->showErrorPage( 'nosuchaction', 'nosuchactiontext' ); } - } /** @@ -540,21 +551,12 @@ class MediaWiki { $config = $context->getConfig(); $factory = wfGetLBFactory(); - // Check if any transaction was too big - $limit = $config->get( 'MaxUserDBWriteDuration' ); - $factory->forEachLB( function ( LoadBalancer $lb ) use ( $limit ) { - $lb->forEachOpenConnection( function ( IDatabase $db ) use ( $limit ) { - $time = $db->pendingWriteQueryDuration(); - if ( $limit > 0 && $time > $limit ) { - throw new DBTransactionError( - $db, - wfMessage( 'transaction-duration-limit-exceeded', $time, $limit )->text() - ); - } - } ); - } ); // Commit all changes - $factory->commitMasterChanges( __METHOD__ ); + $factory->commitMasterChanges( + __METHOD__, + // Abort if any transaction was too big + array( 'maxWriteDuration' => $config->get( 'MaxUserDBWriteDuration' ) ) + ); // Record ChronologyProtector positions $factory->shutdown(); wfDebug( __METHOD__ . ': all transactions committed' ); @@ -562,15 +564,19 @@ class MediaWiki { DeferredUpdates::doUpdates( 'enqueue', DeferredUpdates::PRESEND ); wfDebug( __METHOD__ . ': pre-send deferred updates completed' ); - // Set a cookie to tell all CDN edge nodes to "stick" the user to the - // DC that handles this POST request (e.g. the "master" data center) + // Set a cookie to tell all CDN edge nodes to "stick" the user to the DC that handles this + // POST request (e.g. the "master" data center). Also have the user briefly bypass CDN so + // ChronologyProtector works for cacheable URLs. $request = $context->getRequest(); if ( $request->wasPosted() && $factory->hasOrMadeRecentMasterChanges() ) { $expires = time() + $config->get( 'DataCenterUpdateStickTTL' ); - $request->response()->setCookie( 'UseDC', 'master', $expires, array( 'prefix' => '' ) ); + $options = array( 'prefix' => '' ); + $request->response()->setCookie( 'UseDC', 'master', $expires, $options ); + $request->response()->setCookie( 'UseCDNCache', 'false', $expires, $options ); } - // Avoid letting a few seconds of slave lag cause a month of stale data + // Avoid letting a few seconds of slave lag cause a month of stale data. This logic is + // also intimately related to the value of $wgCdnReboundPurgeDelay. if ( $factory->laggedSlaveUsed() ) { $maxAge = $config->get( 'CdnMaxageLagged' ); $context->getOutput()->lowerCdnMaxage( $maxAge ); @@ -623,7 +629,7 @@ class MediaWiki { } private function main() { - global $wgTitle, $wgTrxProfilerLimits; + global $wgTitle; $request = $this->context->getRequest(); @@ -647,13 +653,14 @@ class MediaWiki { $action = $this->getAction(); $wgTitle = $title; + // Set DB query expectations for this HTTP request + $trxLimits = $this->config->get( 'TrxProfilerLimits' ); $trxProfiler = Profiler::instance()->getTransactionProfiler(); $trxProfiler->setLogger( LoggerFactory::getInstance( 'DBPerformance' ) ); - if ( $request->wasPosted() ) { - $trxProfiler->setExpectations( $wgTrxProfilerLimits['POST'], __METHOD__ ); + $trxProfiler->setExpectations( $trxLimits['POST'], __METHOD__ ); } else { - $trxProfiler->setExpectations( $wgTrxProfilerLimits['GET'], __METHOD__ ); + $trxProfiler->setExpectations( $trxLimits['GET'], __METHOD__ ); } // If the user has forceHTTPS set to true, or if the user