UserTags/Extending

''This is the developer documentation for extending UserTags with new modules. This information is not relevant to users.''

Introduction
You should read the user documentation first, make sure you understand the difference between a group and a tag. UserTags modules are straightforward to create, modules are objects that implement the following interface: All functions are optional, although you do need to use  in order for   and   to be called. Modules that have just  are fine, or just.

Modules are installed by adding them to the  field of the configuration block. The  configuration block actually has more fields than are mentioned in the user documentation since they aren't relevant there:

start(config, username, logger, lang)
The start function is essentially the core function for a module, it receives the user configuration and decides what the module is going to do. It starts any internal AJAX if needed and returns an information block.

The primary return value is an object literal with the following fields (all fields are optional): The function may return an array of groups or a promise directly instead of the above literal, these will be interpreted as  and   respectively, and are functionally equivalent. If you return null/false/undefined/etc then the core will consider that "generic success" and will ignore the module until the filtering pass (i.e. only the  function will be called later, no other effect occurs).

Resolving the Promise
When the promise you provide is resolved (if you provided one) then you should resolve it with the same values as per the return values for  and. When the promise is rejected, the value you reject it with does not matter.

Tags Reference
These are the fields in the tags object map:

generate(json...)
If  returned an AJAX descriptor then the core will perform the requested AJAX then call this function with the resulting JSON. If you provided an array of AJAX then the core will give you one JSON object for each AJAX descriptor in the order they were specified in the array as separate parameters.

'''Do not try to modify the JSON parameters. The data is frozen and will cause your module to crash in Strict Mode (in non-strict mode, it will fail silently).'''

The return value should be an object literal with the following fields (all fields are optional): Like, you can return an array which will be interpreted as. You can also return undefined/null/etc which is the same as returning an empty object literal (i.e. no effect, the core will just move to the filtering pass).

generateFailed
This function is called if any of the AJAX you wanted have failed. You should only implement this function if you need to cancel your own internal AJAX, or if you can actually recover from the fault. It has no parameters but returns the same results as.

filter(groups)
This function is called during the filtering pass when UserTags is removing groups before it starts generating the tags. This function returns an array of groups to be removed. The  parameter the function receives is an object hash of all the groups that were generated by every module, this hash is not reduced at any point so the order that the filter functions were called does not matter (if another module already removed group X, group X will still be in the hash).

'''Do not try to modify the groups parameter. It's frozen.'''

Logging Object
The logging object you receive in the  parameter has the following interface: Please avoid filling the console with noise. You should only log warning and errors by default, use a debug configuration option to disable other messages by default.

Using AJAX
UserTags provides an internal AJAX engine. You should take advantage of this as much as physically possible as the core engine will merge requests from multiple modules into a single request which is much faster than if you issue your own AJAX separately. This engine only works with  requests though, if you require a different   request then you will have to do that manually.

Accessing the AJAX engine is done via the  field in the return value from your   function. The requests you place in there will be added to the internal pool and the results will be returned to your  function when the AJAX is done. The format of the AJAX descriptors is identical to the  field of the object literal taken by jQuery's  function. The important thing to note is that you can only request one type of request at a time. If you want to request multiple data blocks, like  as well as blockinfo in the above example then you must use separate AJAX descriptors to do so, attempting to combine multiple requests into a single descriptor will cause an exception. Also make sure that the fields you use are relevant to the request you are making, if you use irrelevant fields then you can break other modules or cause the entire script to abort due a parameter collision.

There are also several special message types that the engine processes specially because they are relatively common and can be merged easily. These special types must be invoked manually using a special request format.

action=query&amp;list=users
To access user information, use: This is equivalent to the generic request for  (  is an array of   values), except that the properties list will be merged with the properties lists from other modules as well, thereby minimising the number of AJAX requests that need to be performed. It is equivalent to:

action=query&amp;list=usercontribs
This is equivalent to:

action=query&amp;meta=allmessages
You can retrieve a limited set of messages from the server using this special format. This format is only for retrieving gender specific messages from the servers translation cache, like [ ]. This is equivalent to:

Example
Here's a simple Hello World module that adds a tag saying "Hello" to everyone: We define a new group "hello", we assign a tag containing the relevant text to it and we unconditionally return the 'hello' group for every user. Simple enough. You'll notice that we don't use any configuration but I still set the configuration data to true, this is because the core will not load the module unless the module is enabled (i.e. configured). Setting the configuration to true satisfies that requirement.

An equally simple example of removing the 'sysop' group from every user would be:

If you've read the Using AJAX section then you'll already have a reasonable idea how AJAX works, but what if you want to do your own custom AJAX? Things get somewhat more complicated. Let's try adding a custom tag to users who have over 100 edits in the main article namespace. We'll do this using Special:Editcount and the Parsing API:

Hopefully you get the idea. You can also look at the built-in modules for more examples.