Skip to content

Template Plugins#

{anchor}#

The anchor template plugin creates a HTML elements. The easiest way to use the template plugin is to pass it an instance of ITitledLinkObject:

1
{anchor object=$object}

generates the same output as

1
<a href="{$object->getLink()}">{$object->getTitle()}</a>

Instead of an object parameter, a link and content parameter can be used:

1
{anchor link=$linkObject content=$content}

where $linkObject implements ILinkableObject and $content is either an object implementing ITitledObject or having a __toString() method or $content is a string or a number.

The last special attribute is append whose contents are appended to the href attribute of the generated anchor element.

All of the other attributes matching ~^[a-z]+([A-z]+)+$~, expect for href which is disallowed, are added as attributes to the anchor element.

If an object attribute is present, the object also implements IPopoverObject and if the return value of IPopoverObject::getPopoverLinkClass() is included in the class attribute of the anchor tag, data-object-id is automatically added. This functionality makes it easy to generate links with popover support. Instead of

1
<a href="{$entry->getLink()}" class="blogEntryLink" data-object-id="{$entry->entryID}">{$entry->subject}</a>

using

1
{anchor object=$entry class='blogEntryLink'}

is sufficient if Entry::getPopoverLinkClass() returns blogEntryLink.

{anchorAttributes}#

anchorAttributes compliments the StringUtil::getAnchorTagAttributes(string, bool): string method. It allows to easily generate the necessary attributes for an anchor tag based off the destination URL.

1
<a href="https://www.example.com" {anchorAttributes url='https://www.example.com' appendHref=false appendClassname=true isUgc=true}>
Attribute Description
url destination URL
appendHref whether the href attribute should be generated; true by default
isUgc whether the rel="ugc" attribute should be generated; false by default
appendClassname whether the class="externalURL" attribute should be generated; true by default

{append}#

If a string should be appended to the value of a variable, append can be used:

1
2
3
4
5
6
7
{assign var=templateVariable value='newValue'}

{$templateVariable} {* prints 'newValue *}

{append var=templateVariable value='2'}

{$templateVariable} {* now prints 'newValue2 *}

If the variables does not exist yet, append creates a new one with the given value. If append is used on an array as the variable, the value is appended to all elements of the array.

{assign}#

New template variables can be declared and new values can be assigned to existing template variables using assign:

1
2
3
{assign var=templateVariable value='newValue'}

{$templateVariable} {* prints 'newValue *}

{capture}#

In some situations, assign is not sufficient to assign values to variables in templates if the value is complex. Instead, capture can be used:

1
2
3
4
5
6
7
{capture var=templateVariable}
    {if $foo}
        <p>{$bar}</p>
    {else}
        <small>{$baz}</small>
    {/if}
{/capture}

{counter}#

counter can be used to generate and optionally print a counter:

1
2
3
4
5
6
7
{counter name=fooCounter print=true} {* prints '1' *}

{counter name=fooCounter print=true} {* prints '2' now *}

{counter name=fooCounter} {* prints nothing, but counter value is '3' now internally *}

{counter name=fooCounter print=true} {* prints '4' *}

Counter supports the following attributes:

Attribute Description
assign optional name of the template variable the current counter value is assigned to
direction counting direction, either up or down; up by default
name name of the counter, relevant if multiple counters are used simultaneously
print if true, the current counter value is printed; false by default
skip positive counting increment; 1 by default
start start counter value; 1 by default

5.4+ csrfToken#

{csrfToken} prints out the session's CSRF token (“Security Token”).

1
2
3
4
5
<form action="{link controller="Foo"}{/link}" method="post">
    {* snip *}

    {csrfToken}
</form>

The {csrfToken} template plugin supports a type parameter. Specifying this parameter might be required in rare situations. Please check the implementation for details.

{cycle}#

cycle can be used to cycle between different values:

1
2
3
4
5
6
7
{cycle name=fooCycle values='bar,baz'} {* prints 'bar' *}

{cycle name=fooCycle} {* prints 'baz' *}

{cycle name=fooCycle advance=false} {* prints 'baz' again *}

{cycle name=fooCycle} {* prints 'bar' *}

The values attribute only has to be present for the first call. If cycle is used in a loop, the presence of the same values in consecutive calls has no effect. Only once the values change, the cycle is reset.

Attribute Description
advance if true, the current cycle value is advanced to the next value; true by default
assign optional name of the template variable the current cycle value is assigned to; if used, print is set to false
delimiter delimiter between the different cycle values; , by default
name name of the cycle, relevant if multiple cycles are used simultaneously
print if true, the current cycle value is printed, false by default
reset if true, the current cycle value is set to the first value, false by default
values string containing the different cycles values, also see delimiter

{dateInterval}#

dateInterval calculates the difference between two unix timestamps and generated a textual date interval.

1
{dateInterval start=$startTimestamp end=$endTimestamp full=true format='sentence'}
Attribute Description
end end of the time interval; current timestamp by default (though either start or end has to be set)
format output format, either default, sentence, or plain; defaults to default, see wcf\util\DateUtil::FORMAT_* constants
full if true, full difference in minutes is shown; if false, only the longest time interval is shown; false by default
start start of the time interval; current timestamp by default (though either start or end has to be set)

{event}#

event provides extension points in templates that template listeners can use.

1
{event name='foo'}

{hascontent}#

In many cases, conditional statements can be used to determine if a certain section of a template is shown:

1
2
3
{if $foo === 'bar'}
    only shown if $foo is bar
{/if}

In some situations, however, such conditional statements are not sufficient. One prominent example is a template event:

1
2
3
4
5
6
7
8
9
{if $foo === 'bar'}
    <ul>
        {if $foo === 'bar'}
            <li>Bar</li>
        {/if}

        {event name='listItems'}
    </li>
{/if}

In this example, if $foo !== 'bar', the list will not be shown, regardless of the additional template code provided by template listeners. In such a situation, hascontent has to be used:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
{hascontent}
    <ul>
        {content}
            {if $foo === 'bar'}
                <li>Bar</li>
            {/if}

            {event name='listItems'}
        {/content}
    </ul>
{/hascontent}

If the part of the template wrapped in the content tags has any (trimmed) content, the part of the template wrapped by hascontent tags is shown (including the part wrapped by the content tags), otherwise nothing is shown. Thus, this construct avoids an empty list compared to the if solution above.

Like foreach, hascontent also supports an else part:

1
2
3
4
5
6
7
8
9
{hascontent}
    <ul>
        {content}
            {* … *}
        {/content}
    </ul>
{hascontentelse}
    no list
{/hascontent}

{htmlCheckboxes}#

htmlCheckboxes generates a list of HTML checkboxes.

1
2
3
{htmlCheckboxes name=foo options=$fooOptions selected=$currentFoo}

{htmlCheckboxes name=bar output=$barLabels values=$barValues selected=$currentBar}
Attribute Description
disabled if true, all checkboxes are disabled
disableEncoding if true, the values are not passed through wcf\util\StringUtil::encodeHTML(); false by default
name name attribute of the input checkbox element
output array used as keys and values for options if present; not present by default
options array selectable options with the key used as value attribute and the value as the checkbox label
selected current selected value(s)
separator separator between the different checkboxes in the generated output; empty string by default
values array with values used in combination with output, where output is only used as keys for options

{htmlOptions}#

htmlOptions generates an select HTML element.

1
2
3
4
5
6
{htmlOptions name='foo' options=$options selected=$selected}

<select name="bar">
    <option value=""{if !$selected} selected{/if}>{lang}foo.bar.default{/lang}</option>
    {htmlOptions options=$options selected=$selected} {* no `name` attribute *}
</select>
Attribute Description
disableEncoding if true, the values are not passed through wcf\util\StringUtil::encodeHTML(); false by default
object optional instance of wcf\data\DatabaseObjectList that provides the selectable options (overwrites options attribute internally)
name name attribute of the select element; if not present, only the contents of the select element are printed
output array used as keys and values for options if present; not present by default
values array with values used in combination with output, where output is only used as keys for options
options array selectable options with the key used as value attribute and the value as the option label; if a value is an array, an optgroup is generated with the array key as the optgroup label
selected current selected value(s)

All additional attributes are added as attributes of the select HTML element.

{icon}#

{icon} renders a “Font Awesome” icon with support for brand icons.

1
2
3
4
{icon name='magnifying-glass'}
{icon size=24 name='github' type='brand'}
{icon size=32 name='user' type='solid'}
{icon size=64 name='bell'}
Attribute Description
size the size of the icon, possible values are 16, 24, 32, 48, 64, 96, 128 and 144; defaults to 16
type requests the least “thick” icon when omitted, the solid variant with 'solid' and a brand icon with 'brand'

{implode}#

implodes transforms an array into a string and prints it.

1
{implode from=$array key=key item=item glue=";"}{$key}: {$value}{/implode}
Attribute Description
from array with the imploded values
glue separator between the different array values; ', ' by default
item template variable name where the current array value is stored during the iteration
key optional template variable name where the current array key is stored during the iteration

{js}#

js generates script tags based on whether ENABLE_DEBUG_MODE and VISITOR_USE_TINY_BUILD are enabled.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
{js application='wbb' file='WBB'} {* generates 'http://example.com/js/WBB.js' *}

{js application='wcf' file='WCF.User' bundle='WCF.Combined'}
    {* generates 'http://example.com/wcf/js/WCF.User.js' if ENABLE_DEBUG_MODE=1 *}
    {* generates 'http://example.com/wcf/js/WCF.Combined.min.js' if ENABLE_DEBUG_MODE=0 *}

{js application='wcf' lib='jquery'}
    {* generates 'http://example.com/wcf/js/3rdParty/jquery.js' *}

{js application='wcf' lib='jquery-ui' file='awesomeWidget'}
    {* generates 'http://example.com/wcf/js/3rdParty/jquery-ui/awesomeWidget.js' *}

{js application='wcf' file='WCF.User' bundle='WCF.Combined' hasTiny=true}
    {* generates 'http://example.com/wcf/js/WCF.User.js' if ENABLE_DEBUG_MODE=1 *}
    {* generates 'http://example.com/wcf/js/WCF.Combined.min.js' (ENABLE_DEBUG_MODE=0 *}
    {* generates 'http://example.com/wcf/js/WCF.Combined.tiny.min.js' if ENABLE_DEBUG_MODE=0 and VISITOR_USE_TINY_BUILD=1 *}

{jslang}#

jslang works like lang with the difference that the resulting string is automatically passed through encodeJS.

1
2
3
4
5
6
7
require(['Language', /* … */], function(Language, /* … */) {
    Language.addObject({
        'app.foo.bar': '{jslang}app.foo.bar{/jslang}',
    });

    // 
});

6.0+ {jsphrase}#

jsphrase generates the necessary JavaScript code to register a phrase in the JavaScript language store. This plugin only supports static phrase names. If a dynamic phrase should be registered, the jslang plugin needs to be used.

1
2
3
4
5
<script data-relocate="true">
{jsphrase name='app.foo.bar'}

// …
</script>

{lang}#

lang replaces a language items with its value.

1
2
3
4
5
6
7
{lang}foo.bar.baz{/lang}

{lang __literal=true}foo.bar.baz{/lang}

{lang foo='baz'}foo.bar.baz{/lang}

{lang}foo.bar.baz.{$action}{/lang}
Attribute Description
__encode if true, the output will be passed through StringUtil::encodeHTML()
__literal if true, template variables will not resolved but printed as they are in the language item; false by default
__optional if true and the language item does not exist, an empty string is printed; false by default

All additional attributes are available when parsing the language item.

link generates internal links using LinkHandler.

1
<a href="{link controller='FooList' application='bar'}param1=2&param2=A{/link}">Foo</a>
Attribute Description
application abbreviation of the application the controller belongs to; wcf by default
controller name of the controller; if not present, the landing page is linked in the frontend and the index page in the ACP
encode if true, the generated link is passed through wcf\util\StringUtil::encodeHTML(); true by default
isEmail sets encode=false and forces links to link to the frontend

Additional attributes are passed to LinkHandler::getLink().

5.4+ objectAction#

objectAction generates action buttons to be used in combination with the WoltLabSuite/Core/Ui/Object/Action API. For detailed information on its usage, we refer to the extensive documentation in the ObjectActionFunctionTemplatePlugin class itself.

{page}#

page generates an internal link to a CMS page.

1
2
3
4
5
6
7
{page}com.woltlab.wcf.CookiePolicy{/page}

{page pageID=1}{/page}

{page language='de'}com.woltlab.wcf.CookiePolicy{/page}

{page languageID=2}com.woltlab.wcf.CookiePolicy{/page}
Attribute Description
pageID unique id of the page (cannot be used together with a page identifier as value)
languageID id of the page language (cannot be used together with language)
language language code of the page language (cannot be used together with languageID)

{pages}#

This template plugin has been deprecated in WoltLab Suite 6.0.

pages generates a pagination.

1
2
3
{pages controller='FooList' link="pageNo=%d" print=true assign=pagesLinks} {* prints pagination *}

{@$pagesLinks} {* prints same pagination again *}
Attribute Description
assign optional name of the template variable the pagination is assigned to
controller controller name of the generated links
link additional link parameter where %d will be replaced with the relevant page number
pages maximum number of of pages; by default, the template variable $pages is used
print if false and assign=true, the pagination is not printed
application, id, object, title additional parameters passed to LinkHandler::getLink() to generate page links

{plural}#

plural allows to easily select the correct plural form of a phrase based on a given value. The pluralization logic follows the Unicode Language Plural Rules for cardinal numbers.

The # placeholder within the resulting phrase is replaced by the value. It is automatically formatted using StringUtil::formatNumeric.

English:

Note the use of 1 if the number (#) is not used within the phrase and the use of one otherwise. They are equivalent for English, but following this rule generalizes better to other languages, helping the translator.

1
2
3
4
{assign var=numberOfWorlds value=2}
<h1>Hello {plural value=$numberOfWorlds 1='World' other='Worlds'}!</h1>
<p>There {plural value=$numberOfWorlds 1='is one world' other='are # worlds'}!</p>
<p>There {plural value=$numberOfWorlds one='is # world' other='are # worlds'}!</p>

German:

1
2
3
4
{assign var=numberOfWorlds value=2}
<h1>Hallo {plural value=$numberOfWorlds 1='Welt' other='Welten'}!</h1>
<p>Es gibt {plural value=$numberOfWorlds 1='eine Welt' other='# Welten'}!</p>
<p>Es gibt {plural value=$numberOfWorlds one='# Welt' other='# Welten'}!</p>

Romanian:

Note the additional use of few which is not required in English or German.

1
2
3
4
{assign var=numberOfWorlds value=2}
<h1>Salut {plural value=$numberOfWorlds 1='lume' other='lumi'}!</h1>
<p>Există {plural value=$numberOfWorlds 1='o lume' few='# lumi' other='# de lumi'}!</p>
<p>Există {plural value=$numberOfWorlds one='# lume' few='# lumi' other='# de lumi'}!</p>

Russian:

Note the difference between 1 (exactly 1) and one (ending in 1, except ending in 11).

1
2
3
{assign var=numberOfWorlds value=2}
<h1>Привет {plural value=$numberOfWorld 1='мир' other='миры'}!</h1>
<p>Есть {plural value=$numberOfWorlds 1='мир' one='# мир' few='# мира' many='# миров' other='# миров'}!</p>

Attribute Description
value The value that is used to select the proper phrase.
other The phrase that is used when no other selector matches.
Any Category Name The phrase that is used when value belongs to the named category. Available categories depend on the language.
Any Integer The phrase that is used when value is that exact integer.

{prepend}#

If a string should be prepended to the value of a variable, prepend can be used:

1
2
3
4
5
6
7
{assign var=templateVariable value='newValue'}

{$templateVariable} {* prints 'newValue *}

{prepend var=templateVariable value='2'}

{$templateVariable} {* now prints '2newValue' *}

If the variables does not exist yet, prepend creates a new one with the given value. If prepend is used on an array as the variable, the value is prepended to all elements of the array.

{time}#

time allows to output times in different (human readable) formats. Acceptables inputs are either a \DateTimeInterface or an integer representing a Unix timestamp.

1
2
3
4
5
{time time=$time}
{time time=$time type='plainTime'}
{time time=$time type='plainDate'}
{time time=$time type='machine'}
{time time=$time type='custom' format='Y-m-d'}
Attribute Description
time The \DateTimeInterface or Unix timestamp to format.
type The output format.
Type Description
An interactive <woltlab-core-date-time> element that renders as dynamically updated relative times.
plainTime Date with time in the user’s locale and timezone as a plain string.
plainDate Date without time in the user’s locale and timezone as a plain string.
machine A machine readable string in ISO-8601 format.
custom A custom format that is passed to \DateTimeInterface::format(). The timezone will be the user’s timezone.

{user}#

user generates links to user profiles. The mandatory object parameter requires an instances of UserProfile. The optional type parameter is responsible for what the generated link contains:

  • type='default' (also applies if no type is given) outputs the formatted username relying on the “User Marking” setting of the relevant user group. Additionally, the user popover card will be shown when hovering over the generated link.
  • type='plain' outputs the username without additional formatting.
  • type='avatar(\d+)' outputs the user’s avatar in the specified size, i.e., avatar48 outputs the avatar with a width and height of 48 pixels.

The last special attribute is append whose contents are appended to the href attribute of the generated anchor element.

All of the other attributes matching ~^[a-z]+([A-z]+)+$~, except for href which may not be added, are added as attributes to the anchor element.

Examples:

1
{user object=$user}

generates

1
<a href="{$user->getLink()}" data-object-id="{$user->userID}" class="userLink">{@$user->getFormattedUsername()}</a>

and

1
{user object=$user type='avatar48' foo='bar'}

generates

1
<a href="{$user->getLink()}" foo="bar">{@$object->getAvatar()->getImageTag(48)}</a>

Last update: 2023-06-09