X-Git-Url: https://scripts.mit.edu/gitweb/autoinstallsdev/mediawiki.git/blobdiff_plain/19e297c21b10b1b8a3acad5e73fc71dcb35db44a..6932310fd58ebef145fa01eb76edf7150284d8ea:/includes/api/ApiPurge.php diff --git a/includes/api/ApiPurge.php b/includes/api/ApiPurge.php index 2f4648be..35f93e07 100644 --- a/includes/api/ApiPurge.php +++ b/includes/api/ApiPurge.php @@ -24,94 +24,159 @@ * * @file */ - -if ( !defined( 'MEDIAWIKI' ) ) { - require_once( 'ApiBase.php' ); -} +use MediaWiki\Logger\LoggerFactory; +use MediaWiki\MediaWikiServices; /** * API interface for page purging * @ingroup API */ class ApiPurge extends ApiBase { - - public function __construct( $main, $action ) { - parent::__construct( $main, $action ); - } + private $mPageSet; /** * Purges the cache of a page */ public function execute() { - global $wgUser; $params = $this->extractRequestParams(); - if ( !$wgUser->isAllowed( 'purge' ) && !$this->getMain()->isInternalMode() && - !$this->getMain()->getRequest()->wasPosted() ) { - $this->dieUsageMsg( array( 'mustbeposted', $this->getModuleName() ) ); - } - $result = array(); - foreach ( $params['titles'] as $t ) { - $r = array(); - $title = Title::newFromText( $t ); - if ( !$title instanceof Title ) { - $r['title'] = $t; - $r['invalid'] = ''; - $result[] = $r; - continue; - } + + $continuationManager = new ApiContinuationManager( $this, [], [] ); + $this->setContinuationManager( $continuationManager ); + + $forceLinkUpdate = $params['forcelinkupdate']; + $forceRecursiveLinkUpdate = $params['forcerecursivelinkupdate']; + $pageSet = $this->getPageSet(); + $pageSet->execute(); + + $result = $pageSet->getInvalidTitlesAndRevisions(); + $user = $this->getUser(); + + foreach ( $pageSet->getGoodTitles() as $title ) { + $r = []; ApiQueryBase::addTitleInfo( $r, $title ); - if ( !$title->exists() ) { - $r['missing'] = ''; - $result[] = $r; - continue; + $page = WikiPage::factory( $title ); + if ( !$user->pingLimiter( 'purge' ) ) { + // Directly purge and skip the UI part of purge() + $page->doPurge(); + $r['purged'] = true; + } else { + $this->addWarning( 'apierror-ratelimited' ); + } + + if ( $forceLinkUpdate || $forceRecursiveLinkUpdate ) { + if ( !$user->pingLimiter( 'linkpurge' ) ) { + $popts = $page->makeParserOptions( 'canonical' ); + + # Parse content; note that HTML generation is only needed if we want to cache the result. + $content = $page->getContent( Revision::RAW ); + if ( $content ) { + $enableParserCache = $this->getConfig()->get( 'EnableParserCache' ); + $p_result = $content->getParserOutput( + $title, + $page->getLatest(), + $popts, + $enableParserCache + ); + + # Logging to better see expensive usage patterns + if ( $forceRecursiveLinkUpdate ) { + LoggerFactory::getInstance( 'RecursiveLinkPurge' )->info( + "Recursive link purge enqueued for {title}", + [ + 'user' => $this->getUser()->getName(), + 'title' => $title->getPrefixedText() + ] + ); + } + + # Update the links tables + $updates = $content->getSecondaryDataUpdates( + $title, null, $forceRecursiveLinkUpdate, $p_result ); + foreach ( $updates as $update ) { + DeferredUpdates::addUpdate( $update, DeferredUpdates::PRESEND ); + } + + $r['linkupdate'] = true; + + if ( $enableParserCache ) { + $pcache = MediaWikiServices::getInstance()->getParserCache(); + $pcache->save( $p_result, $page, $popts ); + } + } + } else { + $this->addWarning( 'apierror-ratelimited' ); + $forceLinkUpdate = false; + } } - $article = MediaWiki::articleFromTitle( $title ); - $article->doPurge(); // Directly purge and skip the UI part of purge(). - $r['purged'] = ''; + $result[] = $r; } - $this->getResult()->setIndexedTagName( $result, 'page' ); - $this->getResult()->addValue( null, $this->getModuleName(), $result ); - } + $apiResult = $this->getResult(); + ApiResult::setIndexedTagName( $result, 'page' ); + $apiResult->addValue( null, $this->getModuleName(), $result ); - public function isWriteMode() { - return true; + $values = $pageSet->getNormalizedTitlesAsResult( $apiResult ); + if ( $values ) { + $apiResult->addValue( null, 'normalized', $values ); + } + $values = $pageSet->getConvertedTitlesAsResult( $apiResult ); + if ( $values ) { + $apiResult->addValue( null, 'converted', $values ); + } + $values = $pageSet->getRedirectTitlesAsResult( $apiResult ); + if ( $values ) { + $apiResult->addValue( null, 'redirects', $values ); + } + + $this->setContinuationManager( null ); + $continuationManager->setContinuationIntoResult( $apiResult ); } - public function getAllowedParams() { - return array( - 'titles' => array( - ApiBase::PARAM_ISMULTI => true, - ApiBase::PARAM_REQUIRED => true - ) - ); + /** + * Get a cached instance of an ApiPageSet object + * @return ApiPageSet + */ + private function getPageSet() { + if ( !isset( $this->mPageSet ) ) { + $this->mPageSet = new ApiPageSet( $this ); + } + + return $this->mPageSet; } - public function getParamDescription() { - return array( - 'titles' => 'A list of titles', - ); + public function isWriteMode() { + return true; } - public function getDescription() { - return array( 'Purge the cache for the given titles.', - 'This module requires a POST request if the user is not logged in.' - ); + public function mustBePosted() { + return true; } - public function getPossibleErrors() { - return array_merge( parent::getPossibleErrors(), array( - array( 'cantpurge' ), - ) ); + public function getAllowedParams( $flags = 0 ) { + $result = [ + 'forcelinkupdate' => false, + 'forcerecursivelinkupdate' => false, + 'continue' => [ + ApiBase::PARAM_HELP_MSG => 'api-help-param-continue', + ], + ]; + if ( $flags ) { + $result += $this->getPageSet()->getFinalParams( $flags ); + } + + return $result; } - protected function getExamples() { - return array( - 'api.php?action=purge&titles=Main_Page|API' - ); + protected function getExamplesMessages() { + return [ + 'action=purge&titles=Main_Page|API' + => 'apihelp-purge-example-simple', + 'action=purge&generator=allpages&gapnamespace=0&gaplimit=10' + => 'apihelp-purge-example-generator', + ]; } - public function getVersion() { - return __CLASS__ . ': $Id$'; + public function getHelpUrls() { + return 'https://www.mediawiki.org/wiki/Special:MyLanguage/API:Purge'; } }