Requests for comment/Context object

From mediawiki.org
Request for comment (RFC)
Context object
Component General
Creation date
Author(s) IAlex
Document status implemented

We are currently using more and more member variables to store local versions of global objects such as Title object in OutputPage, Skin, ... There are some problems with this method:

  • We need to do this to this for each object we want to store in every class that need it
  • When something changes, it needs to be passed to all objects
  • ...

The proposal here is to replace all these members with only one "context" object that would contain the following members:

  • $request to replace $wgRequest
  • $title to replace $wgTitle
  • $out to replace $wgOut
  • $user to replace $wgUser
  • $lang to replace $wgLang
  • $skin to replace $wgUser->getSkin() since there was concerns that this method should not be in the User class

As you can see, I propose to not add an $article member to this object.

Mockup of the class[edit]

<?php

/**
 * A class that hold request-dependant object
 */
class RequestContext {
	private $request; /// WebRequest object
	private $title;   /// Title object
	private $out;     /// OutputPage object
	private $user;    /// User object
	private $lang;    /// Language object
	private $skin;    /// Skin object

	/**
	 * Constructor
	 *
	 * @param $request WebRequest object
	 * @param $title Title object
	 * @param $user User object, optional
	 */
	public function __construct( $request, $title = null, $user = null ) {
		$this->request = $request;
		$this->title = $title;
		$this->user = $user;
	}

	// Accessors

	/**
	 * Get the WebRequest object
	 *
	 * @return WebRequest object
	 */
	public function getRequest() {
		return $this->request;
	}

	/**
	 * Get the Title object
	 *
	 * @return Title object
	 */
	public function getTitle() {
		if ( $this->out === null ) {
			// Get a Title object
		}
		return $this->title;
	}

	/**
	 * Get the OutputPage object
	 *
	 * @return OutputPage object
	 */
	public function getOut() {
		if ( $this->out === null ) {
			$this->out = new OutputPage;
			$this->out->setContext( $this );
		}
		return $this->out;
	}

	/**
	 * Get the User object
	 *
	 * @return User object
	 */
	public function getUser() {
		if ( $this->user === null ) {
			$this->user = User::newFromSession( $this->request );
		}
		return $this->user;
	}

	/**
	 * Get the Language object
	 *
	 * @return Language object
	 */
	public function getLang() {
		if ( $this->lang === null ) {
			// Insert code from StubUserLang::_newObject()
			// Maybe run a hook
		}
		return $this->lang;
	}

	/**
	 * Get the Skin object
	 *
	 * @return Skin object
	 */
	public function getSkin() {
		if ( $this->lang === null ) {
			// Insert code from User::getSkin()
			// Maybe run a hook
		}
		return $this->skin;
	}

	// Other useful functions

	/**
	 * Get a Message object with context set
	 * Parameters are the same as wfMessage()
	 *
	 * @return Message object
	 */
	public function msg() {
		$args = function_get_args();
		return call_user_func_array( 'wfMessage', $args )->inLanguage( $this->getLang() )->outputPage( $this->getOut() );
	}

	// Static functions

	/**
	 * Get the RequestContext object associated with the main request
	 *
	 * @return RequestContext object
	 */
	public static function getMain() {
		static $instance = null;
		if ( $instance === null ) {
			global $wgRequest;

			$instance = new self( $wgRequest );
		}
		return $instance;
	}
}

Backward compatibility[edit]

Backward compatibility would not be hard to maintain by using StubObject; e.g.

<?php

class StubUserLang extends StubObject {

// [...]

	function _newObject() {
		return RequestContext::getMain()->getLang();
	}
}

Classes that should have a context object[edit]

Classes that should not have a context object[edit]

  • Article
  • Title
  • User
  • ...

See also[edit]