Manual talk:Hooks

From MediaWiki.org
Jump to: navigation, search

This page and it's sub-pages were originally created from information contained at meta:MediaWiki Hooks and their Parameters. --HappyDog 23:48, 17 January 2006 (UTC)

It has subsequently used information from hooks.txt (part of the docs bundled with MediaWiki, and previously called hooks.doc).

Article page outdated[edit]

  • The page contains references to UserLogin, which is no longer a valid hook - at least, it's not in the list of hooks. As I'm struggling to get my UserLoadFromSession hook to work, I'm not the right person to update it!

And 11:42, 10 February 2009 (UTC)

Correct up to 1.6.3[edit]

I have done a thorough search through all versions of MediaWiki from v1.4.0 (where hooks were first introduced) up to 1.6.3 and included all hooks that I found (there were many that had so far been missed) and updated the version numbers for existing hooks, most of which were wrong.

There is still a lot to do here, in particular:

  • I have no idea what a lot of the new hooks are for, or what arguments they take, as they are not documented anywhere. This information needs filling in, and (where necessary) new sub-pages created.
  • I have made some guesses about the function of some of the hooks when placing them in the top table. Feel free to rearrange these. We may also want to split up some of the larger groups.
  • The version numbers on the sub-pages need updating to reflect the correct version numbers on this page. DONE --HappyDog 15:43, 15 April 2006 (UTC)

These lists are now fully complete up to MediaWiki 1.6.3 and all listed version numbers are now correct. Note that unreleased/beta/development versions of the software have been ignored - the version numbers here reflect when the hook was introduced into the public stable version of the software.

--HappyDog 05:42, 15 April 2006 (UTC)

I ran "grep -R wfRunHooks *" on the source for 1.6.7 and then manually crossed off everything already referenced in the text of this page, and I saw no new ones. I assume this is complete. I did not see any wfRunHooks calls that passed a non-constant event (i.e., dynamically called). Is this sufficient to call it good for 1.6.7? - Grubber 02:40, 6 December 2006 (UTC)
I've done the same process for 1.6.8, 1.7.0, 1.7.1, 1.8.0, 1.8.1, and 1.8.2. I have inserted the roughly 5 missing ones and marked the text complete up to 1.8.2. - Grubber 03:54, 6 December 2006 (UTC)
Thank you! --HappyDog 13:19, 6 December 2006 (UTC)

Writing an event handler[edit]

If you want the object to be passed by reference, preceed it with a "&". Otherwise, the event handler will work with a copy of your object.

Format Syntax Resulting function call.
Object only $wgHooks['EventName'][] = &$object; $object->onEventName($param1, $param2);
Object with method $wgHooks['EventName'][] = array(&$object, 'someMethod'); $object->someMethod($param1, $param2);
Object with method and data $wgHooks['EventName'][] = array(&$object, 'someMethod', $someData); $object->someMethod($someData, $param1, $param2);
Object only
(weird syntax, but OK)
$wgHooks['EventName'][] = array(&$object); $object->onEventName($param1, $param2);

More Robust ldapLogin Function[edit]

mailto:jon@myrealmail.net

This function is a bit more robust that the example given in the main document.

Simply set some LDAP server variables like this:

$ldap['server']  ="ldaps://myldap.company.com:636";
 $ldap['base']    = "o=company";
 $ldap['admindn'] = "cn=read,o=company";
 $ldap['adminpw'] = "readPassword";

Then call ldapLogin:

 $loginOK = ldapLogin ($ldap['server'], $ldap['base'], $username, $password, $ldap['admindn'], $ldap['adminpw']);


function ldapLogin ( $server, $base, $username, $password, $admindn="", $adminpw="" )
{
        # Create a filter that will find objects in most LDAP servers and AD
        $filter = "(|(uid=" . $username . ")(cn=" . $username . ")(samAcountname=" . $username. "))";

        # Connect to the LDAP server
        $ds=ldap_connect($server);
        ldap_set_option($ds, LDAP_OPT_PROTOCOL_VERSION, 3); # Force Version 3 Protocol

        if (! $ds) 
        {
                print ("Unable to connect to LDAP server $server");
                return (FALSE);
        }

        # If we can't bind as anonymous to search LDAP, us the $admindn/$adminpw credentials
        if ( $admindn != "" )
        {
                $bind=ldap_bind($ds, $admindn, $adminpw);
                if ( ! $bind )
                {
                        print ("Unable to bind as admin user $admindn to search");
                        ldap_close ($ds);
                        return (FALSE);
                }
        }
        else # Bind anonymously
        {
                $bind=ldap_bind($ds);
                if ( ! $bind )
                {
                        print ("Unable to bind as anonymous user to search $server");
                        ldap_close ($ds);
                        return (FALSE);
                }
        }

        # Search for the $userid using the filter and the search base
        $sr=ldap_search($ds, $base, $filter);
        if ( ! $sr )
        {
                print ("Unable to perform search: $server, base=$base, filter=$filter");
                ldap_close ($ds);
                return (FALSE);
        }

        # Return the entries we found
        $info = ldap_get_entries($ds, $sr);

        # If we get 0 entries, no userid match
        if ( $info["count"] == 0 )
        {
                print ("Can't find object $username!");
                ldap_close ($ds);
                return (FALSE);
        }

        # If we get more than one entry, our search is too loose?
        if ( $info["count"] > 1 )
        {
                print ("Found more than one $username, set the search base differently?");
                ldap_close ($ds);
                return (FALSE);
        }

        # We have one entry, get the DN
        $dn = $info[0][dn];

        # Close this connection
        ldap_close ($ds);

        # Open a new connection
        $ds=ldap_connect($server);
        ldap_set_option($ds, LDAP_OPT_PROTOCOL_VERSION, 3); # Force Version 3 Protocol
        if (! $ds) 
        {
                print ("Unable to connect to LDAP server $server");
                return (FALSE);
        }

        # Bind as the user's DN with password
        $bind=ldap_bind($ds, $dn, $password);
        if ( $bind )
        {
                ldap_close ($ds);
                return (TRUE);
        }

        ldap_close ($ds);
        return (FALSE);
}

static function calls?[edit]

Are static calls like myclass::myfunction possible?

Only if the method has no reference to $this or self unless there's a sanity check like this:
$className = __CLASS__;
if (!is_object($this)) $this = new $className;
self will not work at all from a static context.

-- Egingell 08:18, 16 August 2007 (UTC)

After some testing, it looks like you can't statically call a class method using $wgHooks (not without a rewrite, anyway. -- Egingell 09:04, 16 August 2007 (UTC)

Categorization[edit]

I think the hooks should be categorized by function and then the tables on Manual:MediaWiki hooks dynamically generated (with DPL or something) from the catgories. -Eep² 10:11, 31 July 2007 (UTC)

I think this is a good idea. Something like the Extension Matrix could work as well. Step 1 would be to properly categorize each hook page or better yet, add a good Template:MediaWikiHook entry to each page. --Cneubauer 19:06, 28 August 2007 (UTC)
That would be the best approach, I think, so the tables can be removed from this page altogether. Name and version are already passed to the template, so it would be easy to add these categories automatically, but function would need to be added to each of the hooks manually. I recommend passing it as a new template parameter so that the categorisation is more flexible, and missing cats are easier to spot. --HappyDog 21:53, 28 August 2007 (UTC)

Function Hooks[edit]

Event hooks are nice, but wouldn't it be cool if there was a function hook for every function (I would post this to the bug (suggestion) tracker, but I'm 92% sure that it won't be implemented as it requires going through every single file and pasting the code to every single function and method):

function wfBuiltinFunction( $args ) {
    if ( ! wfRunHooks( __FUNCTION__ . '::Replace', array( &$args ) ) ) return; // If the user function returns true, it's the same as "Before".
    wfRunHooks( __FUNCTION__ . '::Before', array( &$args ) );
    // Go about its business
    wfRunHooks( __FUNCTION__ . '::After', array( &$args ) );
}

class wfBuiltinClass {
    function wfMethod ( $args ) {
        if ( ! wfRunHooks( __CLASS__ . '::' . __FUNCTION__ . '::Replace', array( &$this, &$args ) ) ) return; // If the user function returns true, it's the same as "Before".
        wfRunHooks( __CLASS__ . '::' . __FUNCTION__ . '::Before', array( &$this, &$args ) );
        // Go about its business
        wfRunHooks( __CLASS__ . '::' . __FUNCTION__ . '::After', array( &$this, &$args ) );
    }
}

$wgHooks['[(class name)::](function name)::After|Replace|Before'][] = 'myFunction';

Removing Hooks Groups By Version[edit]

I would like to propose removing the third table of hooks grouped by version. The second table can be sorted by version so we could reduce the cost of maintaining the page by getting rid of the last table. See also this discussion. --Cneubauer 19:03, 28 August 2007 (UTC)

Also note, you can find out a hook's version by checking the annotated SVN page (for example, http://svn.wikimedia.org/viewvc/mediawiki/trunk/phase3/includes/OutputPage.php?view=annotate) and comparing that to the release notes, Important Release Notes. --Cneubauer 23:15, 28 August 2007 (UTC)
Okay, I removed the table. It was out of date anyway. You can still see the old table here: http://www.mediawiki.org/w/index.php?title=Manual:Hooks&oldid=126022. --Cneubauer 12:18, 30 August 2007 (UTC)

Hooks and Templates[edit]

I'm trying to create a hook that process custom wiki markup before parser function extensions have executed. I started with ParserAfterStrip which did the job nicely until I tried to include a template with the custom markup. I've tried various hooks getting only one of three results:

  • The custom markup is parsed in the page but not any included pages.
  • The custom markup is parsed in the page and in the included but pages, but not until after the parser functions have executed.
  • The custom markup is not parsed at all.

I'm running v1.11.0. Anyone have any ideas? —Sledged (talk) 18:23, 1 October 2007 (UTC)

Use ParserBeforeStrip. Jean-Lou Dupont 15:59, 25 October 2007 (UTC)
I'm fairly certain that was the second hook with which I attempted this, and I think I got result #1. I'll try it again when I get a chance just to make sure. Does it work when you try it? What version of MediaWiki are you running? —Sledged (talk) 20:15, 25 October 2007 (UTC)
What about using ParserBeforeStrip and ParserAfterStrip? I'm fairly certain that you can point them to the same function. --Egingell (talk) 18:44, 27 October 2007 (UTC)

Preview Hook?[edit]

I'm not very familiar with MediaWiki's core code. I was surprised to find there is no hook such as "onArticlePreview," and would like to suggest that one be added for future versions of MediaWiki. I want to modify the wiki markup used to generate the preview before it is displayed as a preview. I am assuming the preview is generated from

$_POST['wpTextbox1']

but I still can't find a proper hook for a good entry point. Any ideas? -Wikitonic 21:14, 3 March 2008 (UTC)

UPDATE - I found a crazy work-around for my above problem (it would take too long to explain what I was trying to do and how I got around it), but nevertheless my suggestion still stands that MediaWiki could benefit from a hook such as "beforeArticlePreview" and/or "beforeArticleShowChanges." -Wikitonic 16:31, 7 March 2008 (UTC)
There are a couple hooks you could probably use. Try EditPage::showEditForm:initial and check if $editpage->formtype == 'preview'. If that doesn't work, the MediaWiki developers are pretty good about adding hooks on request. Try submitting a bug report here: https://bugzilla.wikimedia.org/ --Cneubauer 20:45, 8 May 2008 (UTC)
So it appears that a hook has been added in 1.13 called EditPageBeforePreviewText, but I only noticed this because I installed FCKeditor and the hook appeared in the information at Special:Version. It hasn't yet been documented on the manual page here, though... Perhaps someone with a little more knowledge on it might wish to update it? In any case, thanks to the MediaWiki team for adding this hook! --Wikitonic 16:48, 20 June 2008 (UTC)
Looks like I was wrong in the above comment. The hook EditPageBeforePreviewText has NOT been added to the official core MediaWiki code -- rather, it is a part of the FCKeditor extension code. The FCKeditorEditPage class extends the MediaWiki EditPage class and overloads the getPreviewText() method, adding the aforementioned hook in the process. Oh well. I would really like to see this hook added to the core MediaWiki code in the next release. though. --Wikitonic 17:17, 8 July 2008 (UTC)

Thumbnail creation hook[edit]

I have issues on our webserver relating to permissions on uploaded / created files. Basically, I need to "manually" chmod the files after upload to give world-read permissions so they can be seen by the web server.

Whilst I could head into the source code, I would rather write an extension to do this, to make upgrading easier in the future.

Using the "UploadComplete" hook I have done this for files when they are initially uploaded (similarly for deleting and restoring files). However, when images are resized, the new images are created with the wrong permissions, and there don't seem to be any hooks available to know when a thumbnail has been created - have I missed something? --Djomp 14:09, 26 June 2008 (UTC)

Enotif hook[edit]

I have been trying to find a way to modify email notifications with an extension, but I have not been able to find a hook suitable to accomplish this. I want the extension to replace the user id with the real name when its available, is there a hook I am overlooking?--Coban 13:29, 4 August 2008 (UTC)

Reordered and added some "Page Rendering" hooks[edit]

While developing an extension and trying to determine which hooks I needed to use, I was frustrated that the list of "Page Rendering" hooks looked like it was in a plausible run order, but further research showed they were not. So I wrote a short extension to hook everything then output the hook names to the debug output, as they were called. The last 6 hook in the list were not called on any of my test pages, but all the others are now in order of their first use. Some hooks, or course, are called multiple times out of the supplied order. Lil Devil 20:10, 27 May 2010 (UTC)

Are there any hooks about Inter-language wikis?[edit]

Are there any hooks related to Inter-language wiki links, and the posting them on the side of the page? Bud0011 16:50, 21 September 2010 (UTC).

UserLogin Hook?[edit]

I can't seem to find the UserLogin hook (to preform custom logins against a 3rd party application) documented anywhere, despite the fact that both the LDap example and one of the extensions I have installed are using it. Is there any documentation for this hook?

ldapServer?[edit]

This passes $ldapServer as the first parameter to to ldapLogin, right?

$wgHooks['UserLogin'][] = array('ldapLogin', $ldapServer);

So what is $ldapServer?

I'd like to know as well. Bud0011 06:16, 9 April 2011 (UTC).

One list only[edit]

In the past there were three lists, this has been reduced to two, but I think it'd be better to have only one, to make updating easier. The number of hooks keeps growing anyway. We can keep the alphabetical list, and add a column "function" and add for each hook the function, then one can sort the table by that column, so you have the same table as "hooks grouped by function" (which can then be removed). It would require some manual work however.. SPQRobin 11:32, 2 October 2011 (UTC)

Absolutely. Just a few minutes ago I again had to add missing hooks to one of the lists. We should remove the alphabetical list and keep the table as a sortable table also allows to sort the hooks by version or by name. --88.130.119.161 14:44, 5 December 2013 (UTC)

Extending or Overwriting SpecialSearch class[edit]

When I am trying to extend or overwrite the SpecialSearch class, I receive an error that says the class doesn't exists or is undefined. I have tried numerous hooks, however I feel I am not using the correct hook. Any advice or suggestions?

Thanks Jwestyp (talk) 18:01, 10 December 2012 (UTC)

ParserResourceNotFound Hook[edit]

I propose a hook for replacing the output of a token that could not be parse(currently the name of said token in red text). While I am not familiar with the mediawiki internals, I hope the code will be enough to convey the point.

/**
Catch when the parser cannot find the requested item in the DB and alter its output
*/
ParserResourceNotFound( $requestedResource, $&proposedOutput)
{
$r = $requestedResource;
$p = $proposedOutput;
switch ($r.namespace) {
    case "File":
        // do transWiki magicImages
        if(p == NULL) p = parseToken("{{NoImage}}");
        break;
    case "Template":
        //Export required template from wikipedia
        //Import required template
        $p=parseToken($r);
        if(p == NULL){ $p = parseToken("{{NotFound}}")}
        break;
}
$proposedOutput =$p;
}

Passing in parameters and data: read-only vs. modifiable[edit]

Some info gleaned from the Mediawiki mailing list:

Prepending the function argument with an ampersand character causes it to be passed it in by reference. That means you are directly manipulating the original variable inside your function, rather than a copy.

For example, if we wanted to pass in three arguments into a function and edit $b, the event handler would look like this:

   # declare the function to be called at HookName
   $wgHooks['HookName'][] = 'wfEditVariableB';
   # function to set new value of $b. $a and $c remain unchanged.
   function wfEditVariableB( $a, &$b, $c ){
     $b = 'new value';
     return true;
   }

—The preceding unsigned comment was added by Girlwithglasses (talkcontribs) 18:14, 18 March 2014 (UTC)

Note too that the call to wfRunHooks must also have passed the second parameter ($b) as a reference, or else PHP will raise a warning and your hook function will not be called at all.
On the other hand, PHP does not care if the call to wfRunHooks passed $a or $c as a reference. But beware: in PHP 5.3 these variables would still be references inside your hook function, despite not being declared as such in your function declaration! This does not seem to be the case in PHP 5.5 (I don't have PHP 5.4 handy to check). Anomie (talk) 13:26, 19 March 2014 (UTC)

Hook for getting Template parameters[edit]

I'm new to all this. I can't find anything through searching. Is there anyway to use hooks (either one available, or new) that can read the parameters passed to a template, within the template?

Basically, if you call {{templ|par1=value1|par2=val2|par3=val3}} and have a call to a hypothetical extension in the template itself, is there a way for the extension to gather value1, value2, value3 (and possibly the names of the parameters as well)?

This would allow an extension (or a combination of extensions) to add automated array functions to template parameters and would help me greatly. I know there are array extensions and variable extensions, but they don't have the extra layer of abstraction I'm looking for.

Missing hooks.[edit]

I ran a comparison against https://phabricator.wikimedia.org/source/mediawiki/browse/master/docs/hooks.txt and the documented hooks here on MediaWiki.org, and got the following list. These hooks are currently not documented here:

Mainframe98 talk 19:06, 17 March 2017 (UTC)

I'll start adding these :-) thanks for creating a list! SamanthaNguyen (talk) 19:50, 17 March 2017 (UTC)

I misprogrammed my comparison program, and the actual list of missing hooks is much larger (70):
Compared with https://phabricator.wikimedia.org/source/mediawiki/browse/master/docs/hooks.txt. Mainframe98 talk 18:07, 1 April 2017 (UTC)
Just curious, as the way you wrote this a while ago sounds like you wrote your own program. Did you do that, or did you fire findHooks.php instead? (just want to make sure you're aware of it; if you wrote your own, maybe you could upstream those changes in making the maintenance script more accurate?) SamanthaNguyen (talk) 03:03, 13 August 2017 (UTC)
I wasn't even aware there was a maintenance script for it. Since I use Windows, I instead wrote my own. It's... less than usable, since it depends on a framework I wrote that is beyond broken. That, and I wrote it in C#, rather than PHP. It is my intention to rebuild that program one day, but until then I can take a look at the maintenance script. Mainframe98 talk 06:13, 13 August 2017 (UTC)

Sandbox header[edit]

The Homestar Runner Wiki sandbox has a header that is not included in the source. I want to do this for another wiki. The source code is at the Wikipedia page User:It's dot com/ProjectStaticTopText, but I don't know what to do with it. Where should I put this code? 96.48.149.66 19:03, 25 June 2017 (UTC)

Hello? I'm still not sure what to do. 96.48.149.66 01:55, 26 June 2017 (UTC)
...Hello? 96.48.149.66 00:43, 10 July 2017 (UTC)
If you can't install PHP code on the server (which is your case unless you're a referata.com staff), you should ask referata.com support to install this, but there have very low possibilities for this to happen since this looks like a very specific use case which usually doesn't bother wiki farms. --Ciencia Al Poder (talk) 17:45, 10 July 2017 (UTC)