summaryrefslogtreecommitdiff
path: root/includes/context/RequestContext.php
diff options
context:
space:
mode:
Diffstat (limited to 'includes/context/RequestContext.php')
-rw-r--r--includes/context/RequestContext.php88
1 files changed, 64 insertions, 24 deletions
diff --git a/includes/context/RequestContext.php b/includes/context/RequestContext.php
index ede10fe9..4e790c04 100644
--- a/includes/context/RequestContext.php
+++ b/includes/context/RequestContext.php
@@ -1,7 +1,5 @@
<?php
/**
- * Request-dependant objects containers.
- *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
@@ -64,6 +62,11 @@ class RequestContext implements IContextSource {
private $skin;
/**
+ * @var StatsdDataFactory
+ */
+ private $stats;
+
+ /**
* @var Config
*/
private $config;
@@ -121,6 +124,22 @@ class RequestContext implements IContextSource {
}
/**
+ * Get the Stats object
+ *
+ * @return BufferingStatsdDataFactory
+ */
+ public function getStats() {
+ if ( $this->stats === null ) {
+ $config = $this->getConfig();
+ $prefix = $config->has( 'StatsdMetricPrefix' )
+ ? rtrim( $config->get( 'StatsdMetricPrefix' ), '.' )
+ : 'MediaWiki';
+ $this->stats = new BufferingStatsdDataFactory( $prefix );
+ }
+ return $this->stats;
+ }
+
+ /**
* Set the Title object
*
* @param Title $title
@@ -140,12 +159,23 @@ class RequestContext implements IContextSource {
if ( $this->title === null ) {
global $wgTitle; # fallback to $wg till we can improve this
$this->title = $wgTitle;
+ wfDebugLog( 'GlobalTitleFail', __METHOD__ . ' called by ' . wfGetAllCallers( 5 ) . ' with no title set.' );
}
return $this->title;
}
/**
+ * Check, if a Title object is set
+ *
+ * @since 1.25
+ * @return bool
+ */
+ public function hasTitle() {
+ return $this->title !== null;
+ }
+
+ /**
* Check whether a WikiPage object can be get with getWikiPage().
* Callers should expect that an exception is thrown from getWikiPage()
* if this method returns false.
@@ -171,9 +201,8 @@ class RequestContext implements IContextSource {
* @param WikiPage $p
*/
public function setWikiPage( WikiPage $p ) {
- $contextTitle = $this->getTitle();
$pageTitle = $p->getTitle();
- if ( !$contextTitle || !$pageTitle->equals( $contextTitle ) ) {
+ if ( !$this->hasTitle() || !$pageTitle->equals( $this->getTitle() ) ) {
$this->setTitle( $pageTitle );
}
// Defer this to the end since setTitle sets it to null.
@@ -287,8 +316,8 @@ class RequestContext implements IContextSource {
/**
* Get the Language object.
* Initialization of user or request objects can depend on this.
- *
* @return Language
+ * @throws Exception
* @since 1.19
*/
public function getLanguage() {
@@ -308,10 +337,13 @@ class RequestContext implements IContextSource {
$request = $this->getRequest();
$user = $this->getUser();
- $code = $request->getVal( 'uselang', $user->getOption( 'language' ) );
+ $code = $request->getVal( 'uselang', 'user' );
+ if ( $code === 'user' ) {
+ $code = $user->getOption( 'language' );
+ }
$code = self::sanitizeLangCode( $code );
- wfRunHooks( 'UserGetLanguageObject', array( $user, &$code, $this ) );
+ Hooks::run( 'UserGetLanguageObject', array( $user, &$code, $this ) );
if ( $code === $this->getConfig()->get( 'LanguageCode' ) ) {
$this->lang = $wgContLang;
@@ -348,10 +380,9 @@ class RequestContext implements IContextSource {
*/
public function getSkin() {
if ( $this->skin === null ) {
- wfProfileIn( __METHOD__ . '-createskin' );
$skin = null;
- wfRunHooks( 'RequestContextCreateSkin', array( $this, &$skin ) );
+ Hooks::run( 'RequestContextCreateSkin', array( $this, &$skin ) );
$factory = SkinFactory::getDefaultInstance();
// If the hook worked try to set a skin from it
@@ -386,7 +417,6 @@ class RequestContext implements IContextSource {
// After all that set a context on whatever skin got created
$this->skin->setContext( $this );
- wfProfileOut( __METHOD__ . '-createskin' );
}
return $this->skin;
@@ -463,10 +493,14 @@ class RequestContext implements IContextSource {
}
/**
- * Import the resolved user IP, HTTP headers, user ID, and session ID.
+ * Import an client IP address, HTTP headers, user ID, and session ID
+ *
* This sets the current session and sets $wgUser and $wgRequest.
* Once the return value falls out of scope, the old context is restored.
- * This function can only be called within CLI mode scripts.
+ * This method should only be called in contexts (CLI or HTTP job runners)
+ * where there is no session ID or end user receiving the response. This
+ * is partly enforced, and is done so to avoid leaking cookies if certain
+ * error conditions arise.
*
* This will setup the session from the given ID. This is useful when
* background scripts inherit context when acting on behalf of a user.
@@ -479,11 +513,12 @@ class RequestContext implements IContextSource {
* @since 1.21
*/
public static function importScopedSession( array $params ) {
- if ( PHP_SAPI !== 'cli' ) {
- // Don't send random private cookies or turn $wgRequest into FauxRequest
- throw new MWException( "Sessions can only be imported in cli mode." );
- } elseif ( !strlen( $params['sessionId'] ) ) {
- throw new MWException( "No session ID was specified." );
+ if ( session_id() != '' && strlen( $params['sessionId'] ) ) {
+ // Sanity check to avoid sending random cookies for the wrong users.
+ // This method should only called by CLI scripts or by HTTP job runners.
+ throw new MWException( "Sessions can only be imported when none is active." );
+ } elseif ( !IP::isValid( $params['ip'] ) ) {
+ throw new MWException( "Invalid client IP address '{$params['ip']}'." );
}
if ( $params['userId'] ) { // logged-in user
@@ -492,13 +527,11 @@ class RequestContext implements IContextSource {
if ( !$user->getId() ) {
throw new MWException( "No user with ID '{$params['userId']}'." );
}
- } elseif ( !IP::isValid( $params['ip'] ) ) {
- throw new MWException( "Could not load user '{$params['ip']}'." );
} else { // anon user
$user = User::newFromName( $params['ip'], false );
}
- $importSessionFunction = function ( User $user, array $params ) {
+ $importSessionFunc = function ( User $user, array $params ) {
global $wgRequest, $wgUser;
$context = RequestContext::getMain();
@@ -531,12 +564,19 @@ class RequestContext implements IContextSource {
// Stash the old session and load in the new one
$oUser = self::getMain()->getUser();
$oParams = self::getMain()->exportSession();
- $importSessionFunction( $user, $params );
+ $oRequest = self::getMain()->getRequest();
+ $importSessionFunc( $user, $params );
// Set callback to save and close the new session and reload the old one
- return new ScopedCallback( function () use ( $importSessionFunction, $oUser, $oParams ) {
- $importSessionFunction( $oUser, $oParams );
- } );
+ return new ScopedCallback(
+ function () use ( $importSessionFunc, $oUser, $oParams, $oRequest ) {
+ global $wgRequest;
+ $importSessionFunc( $oUser, $oParams );
+ // Restore the exact previous Request object (instead of leaving FauxRequest)
+ RequestContext::getMain()->setRequest( $oRequest );
+ $wgRequest = RequestContext::getMain()->getRequest(); // b/c
+ }
+ );
}
/**