Last modified: 2014-04-09 17:01:44 UTC

Wikimedia Bugzilla is closed!

Wikimedia migrated from Bugzilla to Phabricator. Bug reports are handled in Wikimedia Phabricator.
This static website is read-only and for historical purposes. It is not possible to log in and except for displaying bug reports and their history, links might be broken. See T65706, the corresponding Phabricator task for complete and up-to-date bug report information.
Bug 63706 - OutputPage#getWikiPage dies unexpectedly on special pages
OutputPage#getWikiPage dies unexpectedly on special pages
Status: RESOLVED WONTFIX
Product: MediaWiki
Classification: Unclassified
General/Unknown (Other open bugs)
unspecified
All All
: Unprioritized normal (vote)
: ---
Assigned To: Nobody - You can work on this!
:
Depends on:
Blocks:
  Show dependency treegraph
 
Reported: 2014-04-08 21:54 UTC by Mark Holmquist
Modified: 2014-04-09 17:01 UTC (History)
3 users (show)

See Also:
Web browser: ---
Mobile Platform: ---
Assignee Huggle Beta Tester: ---


Attachments

Description Mark Holmquist 2014-04-08 21:54:58 UTC
I had the audacity to write the following code in a BeforePageDisplay hook handler:

$out->getWikiPage()->getTitle()->inNamespace( NS_FILE );

This works like a charm on article pages or file pages, but crashed on a special page (Special:JavaScriptTest) with the following:

Exception from line 118 of /.../mediawiki/core/includes/WikiPage.php: Invalid or virtual namespace -1 given.

I'm using try/catch to prevent this now, but this seems like a mighty silly thing to always fail on. Either give OutputPage a way to tell what namespace it's in (or give it a way to figure out the title of the page it's loading) so we can prevent the error, or return a faux WikiPage object that represents the SpecialPage - I won't mind either way, this just seems like a really weird place to throw an error.
Comment 1 Bawolff (Brian Wolff) 2014-04-08 21:56:33 UTC
I'd say you should do:
$out->getTitle()->inNamespace( NS_FILE );

instead :P
Comment 2 Mark Holmquist 2014-04-08 22:33:49 UTC
OK, that was a dumb mistake, oversight on my part, but if I were trying to access something that was not the title...
Comment 3 Bawolff (Brian Wolff) 2014-04-09 00:12:00 UTC
Hmm, here are the methods in WikiPage (from https://doc.wikimedia.org/mediawiki-core/master/php/html/classWikiPage.html#a38da35460ff1e0fc633fec5c55f3c930 ):

Public Member Functions
 	__construct (Title $title)
 	Constructor and clear the article.
 	checkFlags ($flags)
 	Check flags and add EDIT_NEW or EDIT_UPDATE to them as needed.
 	checkTouched ()
 	Loads page_touched and returns a value indicating if it should be used.
 	clear ()
 	Clear the object.
 	clearPreparedEdit ()
 	Clear the mPreparedEdit cache field, as may be needed by mutable content types.
 	commitRollback ($fromP, $summary, $bot, &$resultDetails, User $guser)
 	Backend implementation of doRollback(), please refer there for parameter and return value documentation.
 	doCascadeProtectionUpdates (ParserOutput $parserOutput)
 	Updates cascading protections.
 	doDeleteArticle ($reason, $suppress=false, $id=0, $commit=true, &$error= '', User $user=null)
 	Same as doDeleteArticleReal(), but returns a simple boolean.
 	doDeleteArticleReal ($reason, $suppress=false, $id=0, $commit=true, &$error= '', User $user=null)
 	Back-end article deletion Deletes the article with database consistency, writes logs, purges caches.
 	doDeleteUpdates ($id, Content $content=null)
 	Do some database updates after deletion.
 	doEdit ($text, $summary, $flags=0, $baseRevId=false, $user=null)
 	Change an existing article or create a new article.
 	doEditContent (Content $content, $summary, $flags=0, $baseRevId=false, User $user=null, $serialisation_format=null)
 	Change an existing article or create a new article.
 	doEditUpdates (Revision $revision, User $user, array $options=array())
 	Do standard deferred updates after page edit.
 	doPurge ()
 	Perform the actions of a page purging.
 	doQuickEdit ($text, User $user, $comment= '', $minor=0)
 	Edit an article without doing all that other stuff The article must already exist; link tables etc are not updated, caches are not flushed.
 	doQuickEditContent (Content $content, User $user, $comment= '', $minor=false, $serialisation_format=null)
 	Edit an article without doing all that other stuff The article must already exist; link tables etc are not updated, caches are not flushed.
 	doRollback ($fromP, $summary, $token, $bot, &$resultDetails, User $user)
 	Roll back the most recent consecutive set of edits to a page from the same user; fails if there are no eligible edits to roll back to, e.g.
 	doUpdateRestrictions (array $limit, array $expiry, &$cascade, $reason, User $user)
 	Update the article's restriction field, and leave a log entry.
 	doViewUpdates (User $user, $oldid=0)
 	Do standard deferred updates after page view (existing or missing page)
 	estimateRevisionCount ()
 	Get the approximate revision count of this page.
 	exists ()
 	followRedirect ()
 	Get the Title object or URL this page redirects to.
 	getActionOverrides ()
 	Returns overrides for action handlers.
 	getAutoDeleteReason (&$hasHistory)
 	Auto-generates a deletion reason.
 	getCategories ()
 	#@-
 	getComment ($audience=Revision::FOR_PUBLIC, User $user=null)
 	getContent ($audience=Revision::FOR_PUBLIC, User $user=null)
 	Get the content of the current revision.
 	getContentHandler ()
 	Returns the ContentHandler instance to be used to deal with the content of this WikiPage.
 	getContentModel ()
 	Returns the page's content model id (see the CONTENT_MODEL_XXX constants).
 	getContributors ()
 	Get a list of users who have edited this article, not including the user who made the most recent revision, which you can get from $article->getUser() if you want it.
 	getCount ()
 	getCreator ($audience=Revision::FOR_PUBLIC, User $user=null)
 	Get the User object of the user who created the page.
 	getDeletionUpdates (Content $content=null)
 	Returns a list of updates to be performed when this page is deleted.
 	getHiddenCategories ()
 	Returns a list of hidden categories this page is a member of.
 	getId ()
 	getLastNAuthors ($num, $revLatest=0)
 	Get the last N authors.
 	getLatest ()
 	Get the page_latest field.
 	getLinksTimestamp ()
 	Get the page_links_updated field.
 	getMinorEdit ()
 	Returns true if last revision was marked as "minor edit".
 	getOldestRevision ()
 	Get the Revision object of the oldest revision.
 	getParserOutput (ParserOptions $parserOptions, $oldid=null)
 	Get a ParserOutput for the given ParserOptions and revision ID.
 	getRawText ()
 	Get the text of the current revision.
 	getRedirectTarget ()
 	If this page is a redirect, get its target.
 	getRedirectURL ($rt)
 	Get the Title object or URL to use for a redirect.
 	getRevision ()
 	Get the latest revision.
 	getText ($audience=Revision::FOR_PUBLIC, User $user=null)
 	Get the text of the current revision.
 	getTimestamp ()
 	getTitle ()
 	Get the title object of the article.
 	getTouched ()
 	Get the page_touched field.
 	getUndoContent (Revision $undo, Revision $undoafter=null)
 	Get the content that needs to be saved in order to undo all revisions between $undo and $undoafter.
 	getUndoText (Revision $undo, Revision $undoafter=null)
 	Get the text that needs to be saved in order to undo all revisions between $undo and $undoafter.
 	getUsedTemplates ()
 	Return a list of templates used by this article.
 	getUser ($audience=Revision::FOR_PUBLIC, User $user=null)
 	getUserText ($audience=Revision::FOR_PUBLIC, User $user=null)
 	hasViewableContent ()
 	Check if this page is something we're going to be showing some sort of sensible content for.
 	insertOn ($dbw)
 	Insert a new empty page record for this article.
 	insertProtectNullRevision ($revCommentMsg, array $limit, array $expiry, $cascade, $reason)
 	Insert a new null revision for this page.
 	insertRedirect ()
 	Insert an entry for this page into the redirect table.
 	insertRedirectEntry ($rt)
 	Insert or update the redirect table entry for this page to indicate it redirects to $rt .
 	isBigDeletion ()
 	Check whether the number of revisions of this page surpasses $wgDeleteRevisionsLimit.
 	isCountable ($editInfo=false)
 	Determine whether a page would be suitable for being counted as an article in the site_stats table based on the title & its content.
 	isParserCacheUsed (ParserOptions $parserOptions, $oldid)
 	Should the parser cache be used?
 	isRedirect ()
 	Tests if the article content represents a redirect.
 	loadFromRow ($data, $from)
 	Load the object from a database row.
 	loadPageData ($from= 'fromdb')
 	Set the general counter, title etc data loaded from some source.
 	makeParserOptions ($context)
 	Get parser options suitable for rendering the primary article wikitext.
 	pageDataFromId ($dbr, $id, $options=array())
 	Fetch a page record matching the requested ID.
 	pageDataFromTitle ($dbr, $title, $options=array())
 	Fetch a page record matching the Title object's namespace and title using a sanitized title string.
 	prepareContentForEdit (Content $content, $revid=null, User $user=null, $serialization_format=null)
 	Prepare content which is about to be saved.
 	prepareTextForEdit ($text, $revid=null, User $user=null)
 	Prepare text which is about to be saved.
 	preSaveTransform ($text, User $user=null, ParserOptions $popts=null)
 	This function is called right before saving the wikitext, so we can do things like signatures and links-in-context.
 	protectDescription (array $limit, array $expiry)
 	Builds the description to serve as comment for the edit.
 	protectDescriptionLog (array $limit, array $expiry)
 	Builds the description to serve as comment for the log entry.
 	replaceSection ($section, $text, $sectionTitle= '', $edittime=null)
 	replaceSectionContent ($section, Content $sectionContent, $sectionTitle= '', $edittime=null)
 	setCachedLastEditTime ($timestamp)
 	Set the cached timestamp for the last time the page changed.
 	setTimestamp ($ts)
 	Set the page timestamp (use only to avoid DB queries)
 	supportsSections ()
 	Returns true if this page's content model supports sections.
 	updateCategoryCounts (array $added, array $deleted)
 	Update all the appropriate counts in the category table, given that we've added the categories $added and deleted the categories $deleted.
 	updateIfNewerOn ($dbw, $revision)
 	If the given revision is newer than the currently set page_latest, update the page record.
 	updateRedirectOn ($dbw, $redirectTitle, $lastRevIsRedirect=null)
 	Add row to the redirect table if this is a redirect, remove otherwise.
 	updateRestrictions ($limit=array(), $reason= '', &$cascade=0, $expiry=array(), User $user=null)
 	Update the article's restriction field, and leave a log entry.
 	updateRevisionOn ($dbw, $revision, $lastRevision=null, $lastRevIsRedirect=null)
 	Update the page record to point to a newly saved revision. 

The only ones that could possibly make sense for a Special Page are:

doViewUpdates (User $user, $oldid=0)
getTitle ()
hasViewableContent ()

So I don't think having WikiPage for a Special page really makes sense.

/me proposes WONTFIX
Comment 4 Mark Holmquist 2014-04-09 16:53:14 UTC
Hm, I guess that makes sense. I'd still prefer it returned null or something instead of killing the entire request, but I'm happy enough with the solution in comment 1 to stop caring now. :)
Comment 5 Umherirrender 2014-04-09 17:01:44 UTC
This fact is already documented in function doc of getWikiPage in IContextSource:

* Get the WikiPage object.
* May throw an exception if there's no Title object set or the Title object
* belongs to a special namespace that doesn't have WikiPage, so use first
* canUseWikiPage() to check whether this method can be called safely.

Note You need to log in before you can comment on or make changes to this bug.


Navigation
Links