The Article class was a problem we've been trying to fix. Article basically was 3 things rolled all into one: 1) A page generation class that when run would fill up OutputPage 2) A context that references a Title, of course using the global $wg context for the rest at the time 3) A glorified Title, containing helpers for doing article related things
Taking the place of 1) we have things like SpecialPage, Action, and some things that are still left inside Article. (I'm hoping to eliminate Action and Article with the pageoutput branch though.) Taking the place of 2) we have a RequestContext system. Instead of hoarding information to itself the classes that fill up OutputPage make use of a context. Taking the place of 3) we have WikiPage.
However, I'm starting to see a new pattern in the quest to eliminate Article that's making a brand new mistake. function __constructor( Page $page, IContextSource $context = null ) { ... }
People seam to be changing constructors for (1) type things that fill up OutputPage that once took an Article into one that takes a WikiPage and a RequestContext, in situations where a Context should be enough information.
WikiPage is basically a glorified title. It takes a single title, and provides access to a number of helpers for that title, such as fetching content, and other information. Anyone with a title can get a WikiPage perfectly usable for their purposes by calling WikiPage::factory( $title ); WikiPage has ABSOLUTELY no user state to it. There is no setXYZ on WikiPage that would make one WikiPage unique from another WikiPage obtained from the same title and warrant keeping WikiPage around. The only /state/ WikiPage has is a few member variables to cache information about the title it's fetched from the database, such as the contents of the revision so that it doesn't keep re-fetching them. The ONLY reason I see to pass a WikiPage when you already have a Title is so that the WikiPage instance you have doesn't lose the cached stuff like revision that it already fetched from the database.
----
I'd like to propose a different pattern.
Because WikiPage is basically a glorified Title we move our pattern for getting ahold of a WikiPage to where we get our title. In other words, we add RequestContext::getWikiPage which will run WikiPage::factory( $this->getTitle() ); to get the WikiPage relevant to a Title. If setTitle is used on that RequestContext we unset the WikiPage we have on RequestContext since the title has changed. ((Unless someone thinks that it would be a better idea for WikiPage::factory or whatever we call it to only create a singleton instance per-title. ie: `WikiPage::factory( Title::newFromText( 'Asdf' ) === WikiPage::factory( Title::newFromText( 'Asdf' );`))
Our page generation classes like Action, etc... accept a Context. If they need a WikiPage to access the Title helpers they use getWikiPage on the context they are working in.
In the case where we need to tell a output page generating class to use a different title than the one we have in our context, we make use of a proper DerivativeContext instead of handing it a WikiPage for a different title than the context and utterly confusing it. For example, if we had Special:History/Foo as our title and wanted to run HistoryPage with a context of "Foo" as a title: $pageContext = new DerivativeContext( $context ); $pageContext->setTitle( Title::newFromText( 'Foo' ) ); $... = new HistoryPage( $pageContext );