Last modified: 2010-05-15 15:52:00 UTC

Wikimedia Bugzilla is closed!

Wikimedia has migrated from Bugzilla to Phabricator. Bug reports should be created and updated in Wikimedia Phabricator instead. Please create an account in Phabricator and add your Bugzilla email address to it.
Wikimedia Bugzilla is read-only. If you try to edit or create any bug report in Bugzilla you will be shown an intentional error message.
In order to access the Phabricator task corresponding to a Bugzilla report, just remove "static-" from its URL.
You could still run searches in Bugzilla or access your list of votes but bug reports will obviously not be up-to-date in Bugzilla.
Bug 10719 - SpecialPage hooks are broken
SpecialPage hooks are broken
Status: RESOLVED FIXED
Product: MediaWiki
Classification: Unclassified
Special pages (Other open bugs)
1.10.x
All All
: Normal blocker with 1 vote (vote)
: ---
Assigned To: Nobody - You can work on this!
http://www.mediawiki.org/wiki/Manual:...
:
Depends on:
Blocks:
  Show dependency treegraph
 
Reported: 2007-07-27 10:50 UTC by Matthew Vickery
Modified: 2010-05-15 15:52 UTC (History)
3 users (show)

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


Attachments

Description Matthew Vickery 2007-07-27 10:50:46 UTC
The hooks SpecialPageExecuteBeforePage and SpecialPageExecuteAfterPage are broken broken for extensions and anything else that subclasses SpecialPage.

There is a note in includes/SpecialPage.php where these hooks are called stating that it is broken for extensions, see below:

# FIXME: these hooks are broken for extensions and anything else that subclasses SpecialPage.

I am attempting to modify the Special:Preferences page via an extension rather than directly within the core code. See my code below which is not working as expected:

$wgHooks['SpecialPageExecuteBeforePage'][] = 'CustomUserPreferencesPage';

function CustomUserPreferencesPage($specialpage, $par, $func) {

  // Check if this hook has been called from the correct page
  if ($specialpage->mName == 'Preferences') {
                
    global $IP ;
                        
    $specialpage->file($IP . "/extensions/CustomUserPreferencesPage/templates/CustomSpecialPreferences.php") ;
                
  }
                
  return true ;
}
Comment 1 Christian Neubauer 2007-07-30 20:25:56 UTC
These hooks are broken for pages that extends SpecialPage (like SpecialPreferences) because those classes override the SpecialPage execute function and never fire the hooks in their new execute function.  You can probably work around this by inserting the hook firing bit back into the PreferencesForm->execute() function in the appropriate place:

function execute() {
  $par = $func = '';
  if ( ! wfRunHooks( 'SpecialPageExecuteBeforePage', array( &$this, &$par, &$func ) ) )
    return;

  // all the rest of SpecialPreferences->execute() goes here.
}
Comment 2 Rob Church 2007-07-30 21:47:29 UTC
The best solution to this, I guess, would be to move the hook execution elsewhere; extending SpecialPage and overriding the constructor and execute() method seems to be the preferred and recommended means of writing special pages now, so as it is, I doubt we're going to rewrite all the custom and core special pages in existence to call these hooks, and we shouldn't have to.
Comment 3 Christian Neubauer 2008-02-11 22:17:47 UTC
Jesus, this is complicated.  Okay, it looks like you can subclass SpecialPage and still get these hooks to fire.  To do this, you have to:

1.  Rename your subclass 'execute' function to something like 'run'.
2.  Specify a function name in your constructor that will be called when your subclass is executed.

If you do this, then SpecialPage->execute() will be called (instead of your subclass execute function) which will in turn call the function you specified which will call the run function of your special page.  Using Brion's AskSql extension as an example, instead of: 

/** Main class that define a new special page*/
class SpecialAsksql extends SpecialPage {

	function SpecialAsksql() {
		SpecialPage::SpecialPage( 'Asksql', 'asksql' );
	}

	function execute( $par ) { ... }
etc


You would do this:

function efRunSpecialAsksql( $par ) {
	SpecialAsksql::run( $par );
}

/** Main class that define a new special page*/
class SpecialAsksql extends SpecialPage {

	function SpecialAsksql() {
		SpecialPage::SpecialPage( 'Asksql', 'asksql', true, 'efRunSpecialAsksql' );
	}

	function run( $par ) { ... }
etc


SpecialPages like SpecialPreferences don't actually subclass SpecialPage at all although they do have an execute function.  Instead, when they are executed, a SpecialPage is created on demand which runs the default function name for SpecialPages (wfSpecial.$name).  This global function then instantiates a new instance of PreferencesForm and calls it's execute function.  Regardless, the hooks fire properly for SpecialPreferences and I assume for all the core SpecialPages.  I'm going to update the documentation on http://www.mediawiki.org/wiki/Manual:Special_pages to explain some of this craziness.  Maybe this bug should be closed once the documentation is clear.
Comment 4 Christian Neubauer 2008-08-25 19:38:53 UTC
This problem appears to be getting worse since some of the core special pages are being modified to subclass SpecialPage (r39873).  This bug could be more or less fixed by moving the SpecialPage hook firing bits from SpecialPage->execute (which is only called if the "special page" doesn't subclass SpecialPage) to SpecialPage->executePath (which is called every time a "special page" is executed.  The meaning of SpecialPageExecuteBeforePage and SpecialPageExecuteAfterPage would change a bit since they would be fired outside of the userCanExecute checks.
Comment 5 Aaron Schulz 2008-10-13 04:32:00 UTC
Does anything even use these?
Comment 6 Aaron Schulz 2008-10-13 04:39:50 UTC
I just removed the crap in r42015 all together.

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


Navigation
Links