* Introduced a "cache mode" concept to simplify the header generation code, and to avoid odd results when conflicting cache header requests are received from submodules, or at least to formalise the handling of such cases.
* Made the cache mode private by default, so that code written in ignorance of caching tends to be safe. If different query modules are used in a single request, private caching is preferred over public caching.
* Removed the "must-revalidate" option from all CC headers, this is really specific to page views with a hacked squid in front, I don't think it's applicable here.
* Made the watchlist module private. This is really the definition of private data. There's nothing in the HTTP spec that says the URL for a CC:public request is private and can't be leaked. CC:private provides protection against unknown proxy behaviour.
* In ApiQueryAllmessages: avoid calling $wgLang->getCode() to check if it's necessary to make a new $wgLang when lang= is specified, since this is the only thing that unstubs $wgUser.
* Removed "FIXME: should this check $user instead of $wgUser?" Answer is no.
$this->dieUsage( 'Incorrect watchlist token provided -- please set a correct token in Special:Preferences', 'bad_wltoken' );
}
} else {
- // User not determined by URL, so don't cache
- $this->getMain()->setVaryCookie();
if ( !$wgUser->isLoggedIn() ) {
$this->dieUsage( 'You must be logged-in to have a watchlist', 'notloggedin' );
}
}
public function execute() {
+ // Cache may vary on $wgUser because ParserOptions gets data from it
+ $this->getMain()->setCacheMode( 'anon-public-user-private' );
+
// Get parameters
$params = $this->extractRequestParams();
public function execute() {
global $wgUser;
- $this->getMain()->setCachePrivate();
$oldName = $wgUser->getName();
$wgUser->logout();
private $mResult, $mAction, $mShowVersions, $mEnableWrite, $mRequest;
private $mInternalMode, $mSquidMaxage, $mModule, $mVaryCookie;
- private $mCacheControl = array( 'must-revalidate' => true );
+ private $mCacheMode = 'private';
+ private $mCacheControl = array();
/**
* Constructs an instance of ApiMain that utilizes the module and format specified by $request.
's-maxage' => $maxage
) );
}
+
+ /**
+ * Set the type of caching headers which will be sent.
+ *
+ * @param $mode One of:
+ * - 'public': Cache this object in public caches, if the maxage or smaxage
+ * parameter is set, or if setCacheMaxAge() was called. If a maximum age is
+ * not provided by any of these means, the object will be private.
+ * - 'private': Cache this object only in private client-side caches.
+ * - 'anon-public-user-private': Make this object cacheable for logged-out
+ * users, but private for logged-in users. IMPORTANT: If this is set, it must be
+ * set consistently for a given URL, it cannot be set differently depending on
+ * things like the contents of the database, or whether the user is logged in.
+ *
+ * If the wiki does not allow anonymous users to read it, the mode set here
+ * will be ignored, and private caching headers will always be sent. In other words,
+ * the "public" mode is equivalent to saying that the data sent is as public as a page
+ * view.
+ *
+ * For user-dependent data, the private mode should generally be used. The
+ * anon-public-user-private mode should only be used where there is a particularly
+ * good performance reason for caching the anonymous response, but where the
+ * response to logged-in users may differ, or may contain private data.
+ *
+ * If this function is never called, then the default will be the private mode.
+ */
+ public function setCacheMode( $mode ) {
+ if ( !in_array( $mode, array( 'private', 'public', 'anon-public-user-private' ) ) ) {
+ wfDebug( __METHOD__.": unrecognised cache mode \"$mode\"\n" );
+ // Ignore for forwards-compatibility
+ return;
+ }
+
+ if ( !in_array( 'read', User::getGroupPermissions( array( '*' ) ), true ) ) {
+ // Private wiki, only private headers
+ if ( $mode !== 'private' ) {
+ wfDebug( __METHOD__.": ignoring request for $mode cache mode, private wiki\n" );
+ return;
+ }
+ }
+
+ wfDebug( __METHOD__.": setting cache mode $mode\n" );
+ $this->mCacheMode = $mode;
+ }
/**
- * Make sure Cache-Control: private is set. Use this when the output of a request
- * is for the current recipient only and should not be cached in any shared cache.
+ * @deprecated Private caching is now the default, so there is usually no
+ * need to call this function. If there is a need, you can use
+ * $this->setCacheMode('private')
*/
public function setCachePrivate() {
- $this->setCacheControl( array( 'private' => true ) );
+ $this->setCacheMode( 'private' );
}
/**
* Set directives (key/value pairs) for the Cache-Control header.
* Boolean values will be formatted as such, by including or omitting
* without an equals sign.
+ *
+ * Cache control values set here will only be used if the cache mode is not
+ * private, see setCacheMode().
*/
public function setCacheControl( $directives ) {
$this->mCacheControl = $directives + $this->mCacheControl;
* WARNING: This function must be called CONSISTENTLY for a given URL. This means that a
* given URL must either always or never call this function; if it sometimes does and
* sometimes doesn't, stuff will break.
+ *
+ * @deprecated Use setCacheMode( 'anon-public-user-private' )
*/
public function setVaryCookie() {
- $this->mVaryCookie = true;
- }
-
- /**
- * Actually output the Vary: Cookie header and its friends, if flagged with setVaryCookie().
- * Outputs the appropriate X-Vary-Options header and Cache-Control: private if needed.
- */
- private function outputVaryCookieHeader() {
- global $wgUseXVO, $wgOut;
- if ( $this->mVaryCookie ) {
- header( 'Vary: Cookie' );
- if ( $wgUseXVO ) {
- header( $wgOut->getXVO() );
- if ( $wgOut->haveCacheVaryCookies() ) {
- $this->setCacheControl( array( 'private' => true ) );
- }
- }
- }
+ $this->setCacheMode( 'anon-public-user-private' );
}
/**
$errCode = $this->substituteResultWithError( $e );
// Error results should not be cached
- $this->setCacheMaxAge( 0 );
- $this->setCachePrivate();
+ $this->setCacheMode( 'private' );
$headerStr = 'MediaWiki-API-Error: ' . $errCode;
if ( $e->getCode() === 0 ) {
$this->mPrinter->safeProfileOut();
$this->printResult( true );
}
-
- // If this wiki is private, don't cache anything ever
- if ( ! in_array( 'read', User::getGroupPermissions( array( '*' ) ), true ) ) {
- $this->setCachePrivate();
+
+ // Send cache headers after any code which might generate an error, to
+ // avoid sending public cache headers for errors.
+ $this->sendCacheHeaders();
+
+ if ( $this->mPrinter->getIsHtml() && !$this->mPrinter->isDisabled() ) {
+ echo wfReportTime();
+ }
+
+ ob_end_flush();
+ }
+
+ protected function sendCacheHeaders() {
+ if ( $this->mCacheMode == 'private' ) {
+ header( 'Cache-Control: private' );
+ return;
+ }
+
+ if ( $this->mCacheMode == 'anon-public-user-private' ) {
+ global $wgUseXVO, $wgOut;
+ header( 'Vary: Accept-Encoding, Cookie' );
+ if ( $wgUseXVO ) {
+ header( $wgOut->getXVO() );
+ if ( $wgOut->haveCacheVaryCookies() ) {
+ // Logged in, mark this request private
+ header( 'Cache-Control: private' );
+ return;
+ }
+ // Logged out, send normal public headers below
+ } elseif ( session_id() != '' ) {
+ // Logged in or otherwise has session (e.g. anonymous users who have edited)
+ // Mark request private
+ header( 'Cache-Control: private' );
+ return;
+ } // else no XVO and anonymous, send public headers below
+ } else /* if public */ {
+ // Give a debugging message if the user object is unstubbed on a public request
+ global $wgUser;
+ if ( !( $wgUser instanceof StubUser ) ) {
+ wfDebug( __METHOD__." \$wgUser is unstubbed on a public request!\n" );
+ }
}
// If nobody called setCacheMaxAge(), use the (s)maxage parameters
$this->mCacheControl['max-age'] = $this->getParameter( 'maxage' );
}
- // Set the cache expiration at the last moment, as any errors may change the expiration.
- // if $this->mSquidMaxage == 0, the expiry time is set to the first second of unix epoch
- $exp = min( $this->mCacheControl['s-maxage'], $this->mCacheControl['max-age'] );
- $expires = ( $exp == 0 ? 1 : time() + $exp );
- header( 'Expires: ' . wfTimestamp( TS_RFC2822, $expires ) );
+ if ( !$this->mCacheControl['s-maxage'] && !$this->mCacheControl['max-age'] ) {
+ // Public cache not requested
+ // Sending a Vary header in this case is harmless, and protects us
+ // against conditional calls of setCacheMaxAge().
+ header( 'Cache-Control: private' );
+ return;
+ }
+
+ $this->mCacheControl['public'] = true;
+
+ // Send an Expires header
+ $maxAge = min( $this->mCacheControl['s-maxage'], $this->mCacheControl['max-age'] );
+ $expiryUnixTime = ( $maxAge == 0 ? 1 : time() + $maxAge );
+ header( 'Expires: ' . wfTimestamp( TS_RFC2822, $expiryUnixTime ) );
// Construct the Cache-Control header
$ccHeader = '';
}
header( "Cache-Control: $ccHeader" );
- $this->outputVaryCookieHeader();
-
- if ( $this->mPrinter->getIsHtml() && !$this->mPrinter->isDisabled() ) {
- echo wfReportTime();
- }
-
- ob_end_flush();
}
/**
// Open search results may be stored for a very long
// time
$this->getMain()->setCacheMaxAge( $wgSearchSuggestCacheExpiry );
- $this->getMain()->setCacheControl( array( 'must-revalidate' => false ) );
+ $this->getMain()->setCacheMode( 'public' );
$srchres = PrefixSearch::titleSearch( $search, $limit,
$namespaces );
}
public function execute() {
+ // The data is hot but user-dependent, like page views, so we set vary cookies
+ $this->getMain()->setCacheMode( 'anon-public-user-private' );
+
// Get parameters
$params = $this->extractRequestParams();
$text = $params['text'];
if ( $params['pst'] || $params['onlypst'] ) {
$text = $wgParser->preSaveTransform( $text, $titleObj, $wgUser, $popts );
- $this->getMain()->setVaryCookie();
}
if ( $params['onlypst'] ) {
// Build a result and bail out
if ( !is_null( $params['summary'] ) ) {
$result_array['parsedsummary'] = array();
- $this->getMain()->setVaryCookie();
$result->setContent( $result_array['parsedsummary'], $wgUser->getSkin()->formatComment( $params['summary'], $titleObj ) );
}
if ( isset( $prop['headitems'] ) || isset( $prop['headhtml'] ) ) {
$out = new OutputPage;
$out->addParserOutputNoText( $p_result );
- $this->getMain()->setVaryCookie();
$userSkin = $wgUser->getSkin();
}
public function getVersion() {
return __CLASS__ . ': $Id$';
}
-}
\ No newline at end of file
+}
* Patrols the article or provides the reason the patrol failed.
*/
public function execute() {
- $this->getMain()->setCachePrivate();
$params = $this->extractRequestParams();
if ( !isset( $params['rcid'] ) ) {
public function getVersion() {
return __CLASS__ . ': $Id$';
}
-}
\ No newline at end of file
+}
*/
public function execute() {
global $wgUser;
- $this->getMain()->setCachePrivate();
$params = $this->extractRequestParams();
if ( !$wgUser->isAllowed( 'purge' ) ) {
$this->dieUsageMsg( array( 'cantpurge' ) );
$this->instantiateModules( $modules, 'list', $this->mQueryListModules );
$this->instantiateModules( $modules, 'meta', $this->mQueryMetaModules );
+ $cacheMode = 'public';
+
// If given, execute generator to substitute user supplied data with generated data.
if ( isset( $this->params['generator'] ) ) {
- $this->executeGeneratorModule( $this->params['generator'], $modules );
+ $generator = $this->newGenerator( $this->params['generator'] );
+ $params = $generator->extractRequestParams();
+ $cacheMode = $this->mergeCacheMode( $cacheMode,
+ $generator->getCacheMode( $params ) );
+ $this->executeGeneratorModule( $generator, $modules );
} else {
// Append custom fields and populate page/revision information
$this->addCustomFldsToPageSet( $modules, $this->mPageSet );
// Execute all requested modules.
foreach ( $modules as $module ) {
+ $params = $module->extractRequestParams();
+ $cacheMode = $this->mergeCacheMode(
+ $cacheMode, $module->getCacheMode( $params ) );
$module->profileIn();
$module->execute();
wfRunHooks( 'APIQueryAfterExecute', array( &$module ) );
$module->profileOut();
}
+
+ // Set the cache mode
+ $this->getMain()->setCacheMode( $cacheMode );
+ }
+
+ /**
+ * Update a cache mode string, applying the cache mode of a new module to it.
+ * The cache mode may increase in the level of privacy, but public modules
+ * added to private data do not decrease the level of privacy.
+ */
+ protected function mergeCacheMode( $cacheMode, $modCacheMode ) {
+ if ( $modCacheMode === 'anon-public-user-private' ) {
+ if ( $cacheMode !== 'private' ) {
+ $cacheMode = 'anon-public-user-private';
+ }
+ } elseif ( $modCacheMode === 'public' ) {
+ // do nothing, if it's public already it will stay public
+ } else { // private
+ $cacheMode = 'private';
+ }
+ return $cacheMode;
}
/**
}
/**
- * For generator mode, execute generator, and use its output as new
- * ApiPageSet
- * @param $generatorName string Module name
- * @param $modules array of module objects
+ * Create a generator object of the given type and return it
*/
- protected function executeGeneratorModule( $generatorName, $modules ) {
+ public function newGenerator( $generatorName ) {
// Find class that implements requested generator
if ( isset( $this->mQueryListModules[$generatorName] ) ) {
$className = $this->mQueryListModules[$generatorName];
} else {
ApiBase::dieDebug( __METHOD__, "Unknown generator=$generatorName" );
}
-
- // Generator results
- $resultPageSet = new ApiPageSet( $this, $this->redirects, $this->convertTitles );
-
- // Create and execute the generator
$generator = new $className ( $this, $generatorName );
if ( !$generator instanceof ApiQueryGeneratorBase ) {
$this->dieUsage( "Module $generatorName cannot be used as a generator", 'badgenerator' );
}
-
$generator->setGeneratorMode();
+ return $generator;
+ }
+
+ /**
+ * For generator mode, execute generator, and use its output as new
+ * ApiPageSet
+ * @param $generatorName string Module name
+ * @param $modules array of module objects
+ */
+ protected function executeGeneratorModule( $generator, $modules ) {
+ // Generator results
+ $resultPageSet = new ApiPageSet( $this, $this->redirects, $this->convertTitles );
// Add any additional fields modules may need
$generator->requestExtraData( $this->mPageSet );
$this->run();
}
+ public function getCacheMode( $params ) {
+ return 'public';
+ }
+
public function executeGenerator( $resultPageSet ) {
$this->run( $resultPageSet );
}
public function getVersion() {
return __CLASS__ . ': $Id$';
}
-}
\ No newline at end of file
+}
$this->run();
}
+ public function getCacheMode( $params ) {
+ return 'public';
+ }
+
public function executeGenerator( $resultPageSet ) {
$this->run( $resultPageSet );
}
public function getVersion() {
return __CLASS__ . ': $Id$';
}
-}
\ No newline at end of file
+}
$result->setIndexedTagName_internal( array( 'query', $this->getModuleName() ), 'u' );
}
+ public function getCacheMode( $params ) {
+ return 'public';
+ }
+
public function getAllowedParams() {
return array(
'from' => null,
public function getVersion() {
return __CLASS__ . ': $Id$';
}
-}
\ No newline at end of file
+}
$this->run();
}
+ public function getCacheMode( $params ) {
+ return 'public';
+ }
+
public function executeGenerator( $resultPageSet ) {
if ( $resultPageSet->isResolvingRedirects() ) {
$this->dieUsage( 'Use "gaifilterredir=nonredirects" option instead of "redirects" when using allimages as a generator', 'params' );
global $wgLang;
$oldLang = null;
- if ( !is_null( $params['lang'] ) && $params['lang'] != $wgLang->getCode() ) {
+ if ( !is_null( $params['lang'] ) ) {
$oldLang = $wgLang; // Keep $wgLang for restore later
$wgLang = Language::factory( $params['lang'] );
- } else if ( is_null( $params['lang'] ) ) {
- // Language not determined by URL but by user preferences, so don't cache
- $this->getMain()->setVaryCookie();
}
$prop = array_flip( (array)$params['prop'] );
}
}
+ public function getCacheMode( $params ) {
+ if ( is_null( $params['lang'] ) ) {
+ // Language not specified, will be fetched from preferences
+ return 'anon-public-user-private';
+ } elseif ( $params['enableparser'] ) {
+ // User-specific parser options will be used
+ return 'anon-public-user-private';
+ } else {
+ // OK to cache
+ return 'public';
+ }
+ }
+
public function getAllowedParams() {
return array(
'messages' => array(
$this->run();
}
+ public function getCacheMode( $params ) {
+ return 'public';
+ }
+
public function executeGenerator( $resultPageSet ) {
if ( $resultPageSet->isResolvingRedirects() ) {
$this->dieUsage( 'Use "gapfilterredir=nonredirects" option instead of "redirects" when using allpages as a generator', 'params' );
$this->run();
}
+ public function getCacheMode( $params ) {
+ return 'public';
+ }
+
public function executeGenerator( $resultPageSet ) {
$this->run( $resultPageSet );
}
$this->resetQueryParams();
}
+ /**
+ * Get the cache mode for the data generated by this module. Override this
+ * in the module subclass.
+ *
+ * Public caching will only be allowed if *all* the modules that supply
+ * data for a given request return a cache mode of public.
+ */
+ public function getCacheMode( $params ) {
+ return 'private';
+ }
+
/**
* Blank the internal arrays with query parameters
*/
) );
}
- // Make sure private data (deleted blocks) isn't cached
- $this->getMain()->setVaryCookie();
if ( !$wgUser->isAllowed( 'hideuser' ) ) {
$this->addWhereFld( 'ipb_deleted', 0 );
}
public function getVersion() {
return __CLASS__ . ': $Id$';
}
-}
\ No newline at end of file
+}
$this->run();
}
+ public function getCacheMode( $params ) {
+ return 'public';
+ }
+
public function executeGenerator( $resultPageSet ) {
$this->run( $resultPageSet );
}
}
}
+ public function getCacheMode( $params ) {
+ return 'public';
+ }
+
public function getAllowedParams() {
return array(
'continue' => null,
public function getVersion() {
return __CLASS__ . ': $Id$';
}
-}
\ No newline at end of file
+}
$this->run();
}
+ public function getCacheMode( $params ) {
+ return 'public';
+ }
+
public function executeGenerator( $resultPageSet ) {
$this->run( $resultPageSet );
}
public function execute() {
global $wgUser;
- $this->getMain()->setVaryCookie();
// Before doing anything at all, let's check permissions
if ( !$wgUser->isAllowed( 'deletedhistory' ) ) {
$this->dieUsage( 'You don\'t have permission to view deleted revision information', 'permissiondenied' );
if ( $fld_parsedcomment ) {
global $wgUser;
- $this->getMain()->setVaryCookie();
$rev['parsedcomment'] = $wgUser->getSkin()->formatComment( $row->ar_comment, $title );
}
if ( $fld_minor && $row->ar_minor_edit == 1 ) {
public function getVersion() {
return __CLASS__ . ': $Id$';
}
-}
\ No newline at end of file
+}
$this->run();
}
+ public function getCacheMode( $params ) {
+ return 'public';
+ }
+
public function executeGenerator( $resultPageSet ) {
$this->run( $resultPageSet );
}
$this->run();
}
+ public function getCacheMode( $params ) {
+ return 'public';
+ }
+
public function executeGenerator( $resultPageSet ) {
$this->run( $resultPageSet );
}
public function getVersion() {
return __CLASS__ . ': $Id$';
}
-}
\ No newline at end of file
+}
}
}
+ public function getCacheMode( $params ) {
+ return 'public';
+ }
+
public function getAllowedParams() {
return array(
'limit' => array(
public function getVersion() {
return __CLASS__ . ': $Id$';
}
-}
\ No newline at end of file
+}
public function execute() {
global $wgUser;
- $this->getMain()->setVaryCookie();
// Before doing anything at all, let's check permissions
if ( !$wgUser->isAllowed( 'deletedhistory' ) ) {
$this->dieUsage( 'You don\'t have permission to view deleted file information', 'permissiondenied' );
}
}
+ public function getCacheMode( $params ) {
+ return 'public';
+ }
+
public function getAllowedParams() {
return array(
'prefix' => null,
}
}
+ public function getCacheMode( $params ) {
+ return 'public';
+ }
+
public function getAllowedParams() {
return array(
'url' => null,
public function getVersion() {
return __CLASS__ . ': $Id$';
}
-}
\ No newline at end of file
+}
return $retval;
}
+ public function getCacheMode( $params ) {
+ return 'public';
+ }
+
private function getContinueStr( $img ) {
return $img->getOriginalTitle()->getText() .
'|' . $img->getTimestamp();
}
}
+ public function getCacheMode( $params ) {
+ return 'public';
+ }
+
public function getAllowedParams() {
return array(
'limit' => array(
public function getVersion() {
return __CLASS__ . ': $Id$';
}
-}
\ No newline at end of file
+}
}
if ( $this->fld_watched ) {
- $this->getMain()->setVaryCookie();
$this->getWatchedInfo();
}
}
if ( !is_null( $this->params['token'] ) ) {
- // Don't cache tokens
- $this->getMain()->setCachePrivate();
-
$tokenFunctions = $this->getTokenFunctions();
$pageInfo['starttimestamp'] = wfTimestamp( TS_ISO_8601, time() );
foreach ( $this->params['token'] as $t ) {
}
}
+ public function getCacheMode( $params ) {
+ $publicProps = array(
+ 'protection',
+ 'talkid',
+ 'subjectid',
+ 'url',
+ 'preload',
+ 'displaytitle',
+ );
+ if ( !is_null( $params['prop'] ) ) {
+ foreach ( $params['prop'] as $prop ) {
+ if ( !in_array( $prop, $publicProps ) ) {
+ return 'private';
+ }
+ }
+ }
+ if ( !is_null( $params['token'] ) ) {
+ return 'private';
+ }
+ return 'public';
+ }
+
public function getAllowedParams() {
return array(
'prop' => array(
ApiBase::PARAM_TYPE => array(
'protection',
'talkid',
- 'watched',
+ 'watched', # private
'subjectid',
'url',
- 'readable',
+ 'readable', # private
'preload',
'displaytitle',
+ // If you add more properties here, please consider whether they
+ // need to be added to getCacheMode()
) ),
'token' => array(
ApiBase::PARAM_DFLT => null,
}
}
+ public function getCacheMode( $params ) {
+ return 'public';
+ }
+
public function getAllowedParams() {
return array(
'limit' => array(
public function getVersion() {
return __CLASS__ . ': $Id$';
}
-}
\ No newline at end of file
+}
$this->run();
}
+ public function getCacheMode( $params ) {
+ return 'public';
+ }
+
public function executeGenerator( $resultPageSet ) {
$this->run( $resultPageSet );
}
public function getVersion() {
return __CLASS__ . ': $Id$';
}
-}
\ No newline at end of file
+}
if ( $this->fld_parsedcomment ) {
global $wgUser;
- $this->getMain()->setVaryCookie();
$vals['parsedcomment'] = $wgUser->getSkin()->formatComment( $row->log_comment, $title );
}
}
return $vals;
}
+ public function getCacheMode( $params ) {
+ if ( !is_null( $params['prop'] ) && in_array( 'parsedcomment', $params['prop'] ) ) {
+ // formatComment() calls wfMsg() among other things
+ return 'anon-public-user-private';
+ } else {
+ return 'public';
+ }
+ }
+
public function getAllowedParams() {
global $wgLogTypes, $wgLogActions;
return array(
if ( isset( $prop['parsedcomment'] ) ) {
global $wgUser;
- $this->getMain()->setVaryCookie();
$vals['parsedcomment'] = $wgUser->getSkin()->formatComment( $row->pt_reason, $title );
}
}
}
+ public function getCacheMode( $params ) {
+ if ( !is_null( $params['prop'] ) && in_array( 'parsedcomment', $params['prop'] ) ) {
+ // formatComment() calls wfMsg() among other things
+ return 'anon-public-user-private';
+ } else {
+ return 'public';
+ }
+ }
+
public function getAllowedParams() {
global $wgRestrictionLevels;
return array(
public function getVersion() {
return __CLASS__ . ': $Id$';
}
-}
\ No newline at end of file
+}
return $vals;
}
+ public function getCacheMode( $params ) {
+ return 'public';
+ }
+
public function getAllowedParams() {
return array(
'namespace' => array(
public function getVersion() {
return __CLASS__ . ': $Id: ApiQueryRandom.php overlordq$';
}
-}
\ No newline at end of file
+}
// Check permissions
global $wgUser;
if ( isset( $show['patrolled'] ) || isset( $show['!patrolled'] ) ) {
- $this->getMain()->setVaryCookie();
if ( !$wgUser->useRCPatrol() && !$wgUser->useNPPatrol() ) {
$this->dieUsage( 'You need the patrol right to request the patrolled flag', 'permissiondenied' );
}
if ( $this->fld_parsedcomment && isset( $row->rc_comment ) ) {
global $wgUser;
- $this->getMain()->setVaryCookie();
$vals['parsedcomment'] = $wgUser->getSkin()->formatComment( $row->rc_comment, $title );
}
}
if ( !is_null( $this->token ) ) {
- // Don't cache tokens
- $this->getMain()->setCachePrivate();
-
$tokenFunctions = $this->getTokenFunctions();
foreach ( $this->token as $t ) {
$val = call_user_func( $tokenFunctions[$t], $row->rc_cur_id,
}
}
+ public function getCacheMode( $params ) {
+ if ( isset( $params['show'] ) ) {
+ foreach ( $params['show'] as $show ) {
+ if ( $show === 'patrolled' || $show === '!patrolled' ) {
+ return 'private';
+ }
+ }
+ }
+ if ( isset( $params['token'] ) ) {
+ return 'private';
+ }
+ if ( !is_null( $params['prop'] ) && in_array( 'parsedcomment', $params['prop'] ) ) {
+ // formatComment() calls wfMsg() among other things
+ return 'anon-public-user-private';
+ }
+ return 'public';
+ }
+
public function getAllowedParams() {
return array(
'start' => array(
if ( $this->fld_parsedcomment ) {
global $wgUser;
- $this->getMain()->setVaryCookie();
$vals['parsedcomment'] = $wgUser->getSkin()->formatComment( $comment, $title );
}
}
}
if ( !is_null( $this->token ) ) {
- // Don't cache tokens
- $this->getMain()->setCachePrivate();
-
$tokenFunctions = $this->getTokenFunctions();
foreach ( $this->token as $t ) {
$val = call_user_func( $tokenFunctions[$t], $title->getArticleID(), $title, $revision );
return $vals;
}
+ public function getCacheMode( $params ) {
+ if ( isset( $params['token'] ) ) {
+ return 'private';
+ }
+ if ( !is_null( $params['prop'] ) && in_array( 'parsedcomment', $params['prop'] ) ) {
+ // formatComment() calls wfMsg() among other things
+ return 'anon-public-user-private';
+ }
+ return 'public';
+ }
+
public function getAllowedParams() {
return array(
'prop' => array(
}
}
+ public function getCacheMode( $params ) {
+ return 'public';
+ }
+
public function getAllowedParams() {
return array(
'search' => null,
return $this->getResult()->addValue( 'query', $property, $data );
}
+ public function getCacheMode( $params ) {
+ return 'public';
+ }
+
public function getAllowedParams() {
return array(
'prop' => array(
return true;
}
+ public function getCacheMode( $params ) {
+ return 'public';
+ }
+
public function getAllowedParams() {
return array(
'continue' => array(
);
}
- // Make sure private data (deleted revisions) isn't cached
- $this->getMain()->setVaryCookie();
if ( !$wgUser->isAllowed( 'hideuser' ) ) {
$this->addWhere( $this->getDB()->bitAnd( 'rev_deleted', Revision::DELETED_USER ) . ' = 0' );
}
$this->fld_patrolled )
{
global $wgUser;
- // Don't cache private data
- $this->getMain()->setVaryCookie();
if ( !$wgUser->useRCPatrol() && !$wgUser->useNPPatrol() ) {
$this->dieUsage( 'You need the patrol right to request the patrolled flag', 'permissiondenied' );
}
if ( $this->fld_parsedcomment ) {
global $wgUser;
- $this->getMain()->setVaryCookie();
$vals['parsedcomment'] = $wgUser->getSkin()->formatComment( $row->rev_comment, $title );
}
}
wfTimestamp( TS_ISO_8601, $row->rev_timestamp );
}
+ public function getCacheMode( $params ) {
+ // This module provides access to deleted revisions and patrol flags if
+ // the requester is logged in
+ return 'anon-public-user-private';
+ }
+
public function getAllowedParams() {
return array(
'limit' => array(
}
public function execute() {
- $this->getMain()->setCachePrivate();
$params = $this->extractRequestParams();
$result = $this->getResult();
$r = array();
}
if ( !is_null( $params['token'] ) ) {
- // Don't cache tokens
- $this->getMain()->setCachePrivate();
-
$tokenFunctions = $this->getTokenFunctions();
foreach ( $params['token'] as $t ) {
$val = call_user_func( $tokenFunctions[$t], $user );
return array_merge( $groups, Autopromote::getAutopromoteGroups( $user ) );
}
+ public function getCacheMode( $params ) {
+ if ( isset( $params['token'] ) ) {
+ return 'private';
+ } else {
+ return 'public';
+ }
+ }
+
public function getAllowedParams() {
return array(
'prop' => array(
$this->fld_notificationtimestamp = isset( $prop['notificationtimestamp'] );
if ( $this->fld_patrol ) {
- $this->getMain()->setVaryCookie();
if ( !$user->useRCPatrol() && !$user->useNPPatrol() ) {
$this->dieUsage( 'patrol property is not available', 'patrol' );
}
$this->dieUsageMsg( array( 'show' ) );
}
- // Check permissions. FIXME: should this check $user instead of $wgUser?
+ // Check permissions.
if ( isset( $show['patrolled'] ) || isset( $show['!patrolled'] ) ) {
- $this->getMain()->setVaryCookie();
if ( !$wgUser->useRCPatrol() && !$wgUser->useNPPatrol() ) {
$this->dieUsage( 'You need the patrol right to request the patrolled flag', 'permissiondenied' );
}
if ( $this->fld_parsedcomment && isset( $row->rc_comment ) ) {
global $wgUser;
- $this->getMain()->setVaryCookie();
$vals['parsedcomment'] = $wgUser->getSkin()->formatComment( $row->rc_comment, $title );
}
public function execute() {
global $wgUser;
- $this->getMain()->setCachePrivate();
if ( !$wgUser->isLoggedIn() ) {
$this->dieUsage( 'You must be logged-in to have a watchlist', 'notloggedin' );
}