On 9/9/07, Tim Starling tstarling@wikimedia.org wrote:
I think $wgUser is the last global we should get rid of, if we get rid of it at all.
I think it's closer to the first, really . . .
The problem is that the existence of a single global user is implied in many places.
Not really. Or rather, any given context might imply one single user, but that user need not be the same as in every other context up and down the stack and in all past and future iterations within that request.
You don't gain any flexibility by having the "global $wgUser" in the caller instead of the callee.
Sure you do, because other callers can use other Users.
And in 99% of code there is no application for multiple user objects.
What's a method where there could be no possible benefit from allowing it to deal with users other than the one generating the web request (if applicable)?
You could gain some flexibility by bundling variables like $wgUser, $wgRequest and the configuration variables into a single context object, and then using that context object as a factory for subsidiary objects. So you would have:
$popt = $mw->newParserOptions();
or in the userCan case:
$title = $mw->newTitle($titleText); $title->getUserPermissionsErrors( 'view' );
It still assumes a single fixed user object as part of an execution context, but it allows subclassing of core objects and comprehensive namespace separation to be implemented transparently to the caller. It also allows straightforward context generation and cloning, which gives you some amount of flexibility if you need to go outside the usual use case.
Well, at the very least a "bundle" object would be needed if we were to kill all the globals. You aren't going to pass the request object, user object, article object, etc. up the stack separately. Adding factory methods to it as you propose is an interesting idea, but it doesn't seem useful as such: it seems to be identical in function except for the nonstandard syntax, basically. Subclassing should work somewhat for extensions, but there are sharp limits to that when you have multiple extensions working together. If two extensions each replace context objects at various points in the code with their own derived objects that they need to function, it's potluck which context object will be handy when it next comes back to the extension.