# User:Patrick/pf

**Other languages:** Template:ParserFunctions

This MediaWiki extension is a collection of parser functions. Parser functions typically have the syntax:

- {{#functionname: argument 1 | argument 2 | argument 3...}}

## Contents

## Functions[edit]

This module defines six functions at present: `expr`, `if`, `ifeq`, `ifexist`, `ifexpr`, and `switch`.

### #expr:[edit]

The `expr` function computes mathematical expressions based on permutations of numbers (or variables/parameters that translate to numbers) and operators. It does *not* work with strings; use `ifeq` below instead. The syntax is:

{{ #expr:expression}}

A list of supported operators follows. For more details about the operator precedence see Help:Calculation, it's roughly **(1)** grouping (parentheses), **(2)** unary (+/- signs and NOT), **(3)** multiplicative (*, /, div, mod), **(4)** additive (+ and -), **(5)** round, **(6)** comparative (=, !=, <, >, etc.), **(7)** logical AND, **(8)** logical OR. Within the same precedence class operators are evaluated left to right. As always some redundant parentheses are better than erroneous terse code.

Operator |
Operation |
Example |
---|---|---|

none | {{#expr: 123456789012345}} = 1.2345678901234E+14 | |

{{#expr: 0.000001}} = 1.0E-6 | ||

( ) | Grouping operators | {{#expr: (30 + 7) * 7 }} = 259 |

+ | Unary sign+ |
{{#expr: +30 * +7}} = 210 |

- | Unary sign (negation)- |
{{#expr: -30 * -7}} = 210 |

not | Unary NOT, logical NOT | {{#expr: not 0 * 7}} = 7 {{#expr: not 30+7}} = 7 |

* | Multiplication | {{#expr: 30 * 7}} = 210 |

/ | Division, same as div |
{{#expr: 30 / 7}} = 4.2857142857143 |

div | Division, same as /,no integer division |
{{#expr: 30 div 7}} = 4.2857142857143 {{#expr: 5 div 2 * 2 + 5 mod 2}} = 6 |

mod | "Modulo", remainder of division after truncating both operands to an integer. Caveat, div and mod are different from all programming languages. |
{{#expr: 30 mod 7}} = 2 {{#expr: -8 mod -3}} = -2{{#expr: -8 mod +3}} = -2{{#expr: 8 mod 2.7}} = 0 {{#expr: 8 mod 3.2}} = 2 {{#expr: 8.9 mod 3}} = 2 |

+ |
Addition | {{#expr: 30 + 7}} = 37 |

- |
Subtraction | {{#expr: 30 - 7}} = 23 |

round | Rounds off the number on the left to the power of 1/10 given on the right | {{#expr: 30 / 7 round 3}} = 4.286 {{#expr: 30 / 7 round 0}} = 4 {{#expr: 3456 round -2}} = 3500 |

= | Equality (numerical incl. logical) | {{#expr: 30 = 7}} = 0 |

<> | Inequality, same as != |
{{#expr: 30 <> 7}} = 1 |

!= | Inequality, same as <>, logical xor |
{{#expr: 1 != 0}} = 1 |

< | Less than | {{#expr: 30 < 7}} = 0 |

> | Greater than | {{#expr: 30 > 7}} = 1 |

<= | Less than or equal to | {{#expr: 30 <= 7}} = 0 |

>= | Greater than or equal to | {{#expr: 30 >= 7}} = 1 |

and | Logical AND | {{#expr: 4<5 and 4 mod 2}} = 0 |

or | Logical OR | {{#expr: 4<5 or 4 mod 2}} = 1 |

The boolean operators consider **0** to be "false" and any other number to be "true", on output "true" is shown as **1**.

Numbers are given in decimal with "." for the decimal point. The `formatnum:`

function can be used to change the decimal point to a comma for the appropriate locales. Scientific notation with `E` plus exponent is not yet supported on input for expressions, but used on output, for details see Help:Calculation.

### #if:[edit]

The `if` function is an if-then-else construct. The syntax is:

{{ #if:<condition>|<then text>|<else text>}}

If the condition is an empty string or consists only of whitespace, then it is considered false, and the *else text* is returned. Otherwise, the *then text* is returned. The *else text* may be omitted, in which case the result will be blank if the condition is false.

An example:

{{Template|parameter=something}} {{Template}} {{Template|parameter=}} | | | | | | | | | {{ #if: {{{parameter|}}} | Parameter is defined. | Parameter is undefined, or empty }}

Note that the `if` function does **not** support "=" signs or mathematical expressions. {{#if: 1 = 2|yes|no}} will return "yes", because the string "1 = 2" is not blank. It is intended as an "if not empty" structure.

### #ifeq:[edit]

`ifeq` compares two strings or numbers, and returns another string depending on the result of that comparison. The syntax is:

{{ #ifeq:<text 1>|<text 2>|<equal text>|<not equal text>}}

If both strings can be interpreted as numbers the comparison is numerical. To force a string comparison add tokens that can't be interpreted as numbers:

`{{ #ifeq: +07 | 007 | 1 | 0 }}`gives 1`{{ #ifeq:"+07"|"007"| 1 | 0 }}`gives 0

- For compatibility with older templates #if: cannot directly distinguish defined and undefined parameter values, it's a shorthand for a comparison with the empty string. With #ifeq: it's directly possible to identify undefined parameters:
`{{ #if: {{{x| }}}`= blank,**|**not blank**|**blank}}`{{ #ifeq: {{{x| }}}`= blank,**| |**blank**|**not blank}}`{{ #ifeq: {{{x| }}}`= undefined.**|**{{{x|u}}}**|**defined**|**undefined}}- An undefined parameter without default counts in the comparison as a string consisting of the tag:
`{{ #ifeq: {{{x}}}`= 0.**|**{{ concat**|**{**|**{**|**{x}**|**}**|**} }}**|**1**|**0}}

### #ifexist:[edit]

`ifexist` returns one of two results based on whether or not a named title exists, e.g.

`{{#ifexist:A0|Bar|RFC 3092}}`

gives Bar, because A0 exists`{{#ifexist:a0|Bar|RFC 3092}}`

gives RFC 3092, because a0 does not exist`{{#ifexist:FOO|Bar|RFC 3092}}`

gives RFC 3092 because FOO does not exist`{{#ifexist:ParserFunctions|Thanks|No}}`

gives No.`{{#ifexist:m:Help:Calculation|Yes|Oops}}`

gives Oops although m:Help:Calculation exists, because of the interwiki prefix.

The first parameter is the title to check for, the second is the positive result, and the third, the negative result. If the parameter passed does not produce a valid title object, then the result is negative.

Template:tim gives the same result, except that the result is positive for an interwiki link. Template:tim exploits this difference.

### #ifexpr:[edit]

`ifexpr` evaluates a mathematical expression and returns one of two strings depending on the result.

{{#ifexpr:<expression>|<then text>|<else text>}}

If the expression evaluates to zero, then the *else text* is returned, otherwise the *then text* is returned. Expression syntax is the same as for `expr`.

- At the moment the
*else text*is also returned for an empty expression: `{{#ifexpr: {{ns:0}}|Toast|'''or else'''}}`

gives**or else**- Omitting both
*then text*and*else text*gives no output except possibly an error message; this can be used to check the correctness of an expression, or to check the wording of the error message (emulated*assertions*, forced errors): `{{#ifexpr: 1/{{#ifeq: {{ns:4}}|Meta|1|0}}}}`

**Division by zero.**`{{#ifexpr: 1/{{#ifeq: {{ns:4}}|Meta|0|1}}}}`

`{{#if:{{#ifexpr: 1=2}}|wrong|correct}}`

correct`{{#if:{{#ifexpr: 1E2}}|wrong|correct}}`

correct`{{#if:{{#ifexpr: 1/0}}|wrong|correct}}`

wrong`{{#if:{{#ifexpr: a=b}}|wrong|correct}}`

wrong

For an application, see also Template:tim.

### #switch:[edit]

`switch`

compares a single value against multiple others, returning a string if a match is found. The syntax is basically:

{{ #switch:<comparison value>|<value=_{1}><result|_{1}><value=_{2}><result|_{2}>...|<value=_{n}><result|_{n}><default result>}}

`switch`

will search through each value passed until a match is found with the comparison value. When found, the result for that value is returned (the text string after the equal sign). If no match is found, but the last item has no equal sign in it, it will be returned as the default result. If your default result *must* have an equal sign, you may use `#default`

:

{{ #switch:<comparison value>|<value>=<result>| #default =<default result>}}

Note that it's also possible to have "fall through" for values (reducing the need to duplicate results). For example:

{{ #switch:<comparison value>|<value|_{1}><value|_{2}><value=_{3}><result|_{3}>...|<value=_{n}><result|_{n}><default result>}}

Note how value_{1} and value_{2} contain no equal sign. If they're matched, they are given the result for value_{3} (that is, whatever is in result_{3}).

- As for #ifeq: the comparison is numerical where possible:
`{{ #switch: +07 | 7 = Yes | 007 = Bond | No }}`gives Yes`{{ #switch:"+07"|"7"= Yes |"007"= Bond | No }}`gives No- The matched value can be empty, therefore the following constructs are equivalent:
`{{ #if: {{ns:0}} | not empty | empty }}`gives empty`{{ #switch:{{ns:0}}|=empty|not empty }}`gives empty

## Caveats[edit]

*Most observed problems turned out to be general issues not limited to parser functions.*

### Substitution[edit]

Applying "subst:" to a ParserFunction works, provided that there is no space between "subst:" and "#". For details see Help:Substitution. Note that unless a technique like optional substitution is used, substituting a template which uses a ParserFunction does not replace that ParserFunction with its result. This is often undesirable.

Like other colon functions the parser functions are affected by 5678 in a predictable way. Summary, undefined parameters can be overwritten by *corresponding* parameters, for details see /5678 and Substitution. Substitution is the only case where this is critical wrt to parameter defaults. It doesn't affect defined parameters.

### Tables[edit]

Currently wiki pipe table syntax doesn't work inside conditionals, there are two main workarounds.

- Hide the pipe from parser functions by putting it in a template, e.g. Template:tim as on w:en:.
- Use html style table syntax instead.
- See also Help:Table, completely empty rows or columns are not displayed. Empty cells could be also transformed into dummy
` `cells on pages not affected by 5569.

Note that "** |**" and "

**" were always tricky within templates, this is no new issue.**

`=`If all else fails, try setting `$wgUseTidy=true;`

in your `LocalSettings.php`

.

### Expressions[edit]

**div**is no integer division and (as is) redundant, use**/**(slash) for real divisions.**mod**uses PHP's % operator, which is different from modulo-operators in all other programming languages, see also Template:tim and 6068.**mod**sometimes returns wrong results for the same input values, see 6356 and /MOD10000.*Update: values less than 1E+12 are apparently not affected.*- Valid #expr: results like 1.0E-7 are not yet supported as
**#expr:**input:- {{#expr:1.0E-7}} yields
*1.0E-7*.

- {{#expr:1.0E-7}} yields
- Under certain conditions
**round 0**results in**-0**instead of**0**. For an expression**x**using**0+(x)**fixes this oddity.

## Installation[edit]

Download both of these files and put them in a new directory called *ParserFunctions* in your extensions directory.

Then put the following at the end of your LocalSettings.php:

require_once( "$IP/extensions/ParserFunctions/ParserFunctions.php" );

You can also browse the code tree here:

### 1.8alpha[edit]

All the ParserFunctions work under 1.8alpha, also in the localised forms.

### 1.7[edit]

All the ParserFunctions work under 1.7, but only in English.

### 1.6[edit]

When including the ParserFunctions in 1.6, some notices may be shown. Removing the following line (line 10) in ParserFunctions.php fixes the problem:

$wgHooks['LanguageGetMagic'][] = 'wfParserFunctionsLanguageGetMagic';

Most ParserFunctions (except #if, which does not work at all) work just as well on MediaWiki 1.6, but the syntax of ParserFunctions is without the '#' character. If you want to use the '#' character, find this section of ParserFunctions.php:

$wgParser->setFunctionHook( 'expr', array( &$wgExtParserFunctions, 'expr' ) ); $wgParser->setFunctionHook( 'if', array( &$wgExtParserFunctions, 'ifHook' ) ); $wgParser->setFunctionHook( 'ifeq', array( &$wgExtParserFunctions, 'ifeq' ) ); $wgParser->setFunctionHook( 'ifexpr', array( &$wgExtParserFunctions, 'ifexpr' ) ); $wgParser->setFunctionHook( 'switch', array( &$wgExtParserFunctions, 'switchHook' ) ); $wgParser->setFunctionHook( 'ifexist', array( &$wgExtParserFunctions, 'ifexist' ) );

Then, replace it with this:

$wgParser->setFunctionHook( '#expr', array( &$wgExtParserFunctions, 'expr' ) ); $wgParser->setFunctionHook( '#if', array( &$wgExtParserFunctions, 'ifHook' ) ); $wgParser->setFunctionHook( '#ifeq', array( &$wgExtParserFunctions, 'ifeq' ) ); $wgParser->setFunctionHook( '#ifexpr', array( &$wgExtParserFunctions, 'ifexpr' ) ); $wgParser->setFunctionHook( '#switch', array( &$wgExtParserFunctions, 'switchHook' ) ); $wgParser->setFunctionHook( '#ifexist', array( &$wgExtParserFunctions, 'ifexist' ) );

**A simple fix for #if in this version** -

Replace:

if ($test !== '') {

on line 47 with:

if ($test) {

That's it. Fix by Andrew Tutt. http://www.duiki.com

## See also[edit]

- Help:Calculation
- Help:Magic words
- StringFunctions
- DynamicFunctions
- m:Category:Templates using ParserFunctions
- en:Category:Templates using ParserFunctions