- Input Filter
- Output Filter
- Output Modifiers
- Conditional Output Modifiers
- String Output Modifiers
- Caching
- Using an output modifier with tag properties
- Creating a Custom Output Modifier
- Chaining (Multiple Output Filters)
- Examples of Custom Output Filters
- Creating a Custom Output Modifier
- Examples
- alternateClass
- parseLinks
- parseTags
- parseTags
- shorten
- substring
- numberformat
Input Filter
The input filter currently processes tag calls in preparation for the output filter. It is typically only used internally by MODX.
Output Filter
In Revolution, the output filter applies one or more series of output modifiers that behave similarly to PHx calls in MODX Evolution – except they are built into the core. The syntax looks like this:
[[element:modifier=`value`]]
They can also be chained (done left to right):
[[element:modifier:anothermodifier=`value`:andanothermodifier:yetanother=`value2`]]
You can also use them to modify the output of snippets. Note that the modifier comes after the snippet name and before the question mark, like this:
[[mySnippet:modifier=`value`? &mySnippetParam=`something`]]
If you have a longer :then=:else=
statement and you want to make it more readable by putting it on multiple lines, it should be done like this:
[[+placeholder:is=`0`:then=`
// code
`:else=`
// code
`]]
Output Modifiers
The following table lists some of the existing modifiers and provides examples of their use. Although the examples below are placeholder tags, output modifiers can be used with any MODX tag. Make sure the placeholder you use actually receives data.
Conditional Output Modifiers
Modifier | Description | Example |
---|---|---|
if, input | if – specifies an additional condition. input – adds the data to the tag | [[*id:is=`1`:and:if=`[[*id]]`:ne=`2`:then=`Yes`:else=`No`]] – if the resource id = 1 and is not 2, output “Yes” or “No” |
or | Can be used to output output modifiers along with the “OR” relation. | [[+numbooks:is=`5`:or:is=`6`:then=`There are 5 or 6 books!`:else=`Not sure how many books`]] |
and | Can be used to output output modifiers along with the relation «AND». | [[*id:is=`1`:and:if=`[[*id]]`:ne=`2`:then=`Yes`:else=`No`]] – if the resource id = 1 and is not equal to 2, output “Yes” or “No” |
isequalto, isequal, equalto, equals, is, eq | Compares with the passed value and continues if it is the same. Used with “then” and “else” | [[+numbooks:isequalto=`5`:then=`There are 5 or 6 books!`:else=`Not sure how many books`]] |
notequalto, notequals, isnt, isnot, neq, ne | Compares with the passed value and moves if it doesn’t match. Used with “then” and “else” | [[+numbooks:notequalto=`5`:then=`Not sure how many books`:else=`There are 5 books!`]] |
greaterthanorequalto, equalorgreaterthen, ge, eg, isgte, gte | Compares with the passed value and continues if it is greater than or equal to the value. Used with “then” and “else”. | [[+numbooks:gte=`5`:then=`There are 5 books or more than 5 books`:else=`There are less than 5 books`]] |
isgreaterthan, greaterthan, isgt, gt | Compares with the passed value and continues if it is greater than the value. Used with “then” and “else”. | [[+numbooks:gt=`5`:then=`There are more than 5 books`:else=`There are less than 5 books`]] |
equaltoorlessthan, lessthanorequalto, el, le, islte, lte | Compares with the passed value and continues if it is less than or equal to the value. Used with “then” and “else”. | [[+numbooks:lte=`5`:then=`There are 5 or less than 5 books`:else=`There are more than 5 books`]] |
islowerthan, islessthan, lowerthan, lessthan, islt, lt | Compares with the passed value and continues if it is less than the value. Used with “then” and “else”. | [[+numbooks:lt=`5`:then=`There are less than 5 books`:else=`There are more than 5 books`]] |
contains | Checks if the value contains the passed string. | [[+author:contains=`Samuel Clemens`:then=`Mark Twain`]] |
containsnot | Check if the value does not contain the passed string. | [[+author:containsnot=`Samuel Clemens`:then=`Somebody Else`]] |
in, IN, inarray, inArray | Check if value is in array (comma separated) | [[+id:in=`5,15,22`:then=`Yes in array`]] |
hide | Checks earlier conditions and hides the element if the conditions were met. | [[+numbooks:lt=`1`:hide]] |
show | Checks earlier conditions and shows the element if the conditions were met. done. | [[+numbooks:gt=`0`:show]] |
then | Conditional usage. | [[+numbooks:gt=`0`:then=`Now available!`]] |
else | Conditional usage with then. | [[+numbooks:gt=`0`:then=`Now available!`:else=`Sorry, currently sold out.`]] |
select | Print replacement if value is in value list before equal sign. Otherwise, the result is empty. | [[+numbooks:select=`0=Value 0&1=Value 1&2=Value 2`]] |
memberof, ismember, mo | Checks if the user is a member of the specified group(s). | [[+modx.user.id:memberof=`Administrator`]] |
String Output Modifiers
Modifier | Description | Example |
---|---|---|
cat | Appends the parameter value (if not empty) to the input value | [[+numbooks:cat=`books`]] |
after, append | Appends the parameter value to the input value (if both are not empty). Added in 2.6.0. | [[+totalnumber:after=`total`]] |
before, prepend | Adds the parameter value to the input value (if both are not empty). Added in 2.6.0. | [[+booknum:before=`book #`]] |
lcase, lowercase, strtolower | Converts strings to lowercase. Similar to PHP strtolower | [[+title:lcase]] |
ucase, uppercase, strtoupper | Converts strings to uppercase. Similar to PHP strtoupper | [[+headline:ucase]] |
ucwords | Converts the first letter of a word to uppercase. Similar to PHP ucwords | [[+title:ucwords]] |
ucfirst | Converts the first letter of a string to uppercase. Similar to PHP ucfirst | [[+name:ucfirst]] |
htmlent, htmlentities | Replace any character that has an HTML entity with that entity. Similar to PHP htmlentities. Uses the current value of the system setting modx_charset with flag ENT_QUOTES |
[[+email:htmlent]] |
esc,escape | Safely escapes character values using regular expressions and str_replace. | Also removes [, ] and [[+email:escape]] |
strip | Replace all line breaks, tabs, and multiple spaces with a single space | [[+textdocument:strip]] |
stripString | Removes the specified value string | [[+name:stripString=`Mr.`]] |
stripmodxtags | Removes MODX tags from the input. (Added in v2.7) | [[+code:stripmodxtags]] |
replace | Replaces one value with another | [[+pagetitle:replace=`Mr.==Mrs.`]] |
striptags, stripTags,notags,strip_tags | Removes HTML tags from the input. Optionally takes a value to specify which tags to allow. Similar to PHP strip_tags | [[+code:strip\_tags=` `]] |
len,length, strlen | Calculates the length of the skipped string. Similar to PHP strlen | [[+longstring:strlen]] |
reverse, strrev | Reverses the input, character by character. Similar to PHP strrev | [[+mirrortext:reverse]] |
wordwrap | Inserts a newline after a specified number of characters. Similar to PHP wordwrap. Takes optional value to set wordwrap position. | [[+bodytext:wordwrap=`80`]] |
wordwrapcut | Inserts a newline after the given number of characters, regardless of word boundaries. Similar to PHP’s wordwrap, with word wrap enabled. Takes optional value to set word wrap position. | [[+bodytext:wordwrapcut=`80`]] |
limit | Limits a string to a certain number of characters. Default is 100. | [[+description:limit=`50`]] |
ellipsis | Adds an ellipsis and truncates the string if it is longer than a certain number of characters. Only spaces are used as breakpoints. Default is 100. | [[+description:ellipsis=`50`]] |
tag | Displays the raw element without :tag. Useful for documentation. | [[+showThis:tag]] |
tvLabel | Displays a label with TV, useful when using select or checkboxes etc where you use `Label==1 | |
math | Returns the result of an advanced calculation (Deprecated) Removed in Revolution 2.2.6. | [[+blackjack:add=`21`]] |
add,increment,incr | Returns the input incremented by the parameter (default: +1) | [[+downloads:incr]] |
subtract,decrement,decr | Returns input minus the parameter (default: -1) | [[+countdown:decr]] [[+moneys:subtract=`100`]] |
multiply,mpy | Returns input multiplied by the parameter (default: *2) | [[+trifecta:mpy=`3`] |
divide,div | Returns input divided by options (default: /2) Does not accept 0. | [[+rating:div=`4`]] |
modulus,mod | Returns the modulus of the input parameter (default: %2, returns 0 or 1) | [[+number:mod]] or [[+number:mod=`3`]] |
ifempty,default,empty, isempty | Returns the input value if it is empty | [[+name:default=`anonymous`]] |
notempty, !empty, ifnotempty, isnotempty | Returns the input value if it is not empty | [[+name:notempty=`Hello `[[+name]]`!`]] |
nl2br | Converts a newline character (\n) to HTML | |
element. | Use this if you are accepting input that you think should have newlines and it doesn’t. Similar to PHP nl2br. | [[+textfile:nl2br]] |
date | Formats a Unix timestamp into a different format. Similar to PHP strftime. The value is the format. See Date Formats. | [[+birthyear:date=`%Y`]] |
strtotime | Converts a date string to a Unix timestamp. Useful in combination with a date output filter. Similar to PHP’s strtotime. Takes in a date. Check out Date formats. | [[+thetime:strtotime]] |
fuzzydate | Returns a nice date format with yesterday and today filtering. Takes on a date. | [[+createdon:fuzzydate]] |
ago | Returns a nice date format in seconds, minutes, weeks or months ago. Takes you on a date (strtotime). | [[+createdon:date=`%d-%m-%Y`:ago]] |
md5 | Creates an MD5 hash of the input string. Similar to PHP md5. | [[+password:md5]] |
cdata | Wrap text with CDATA tags | [[+content:cdata]] |
userinfo | Returns the requested user data. The element must be a modUser identifier. The value field is the column to grab, such as: fullname, email. See examples below. | [[+modx.user.id:userinfo=`username`]] |
isloggedin | Returns true if the user is authenticated in this context. | [[+modx.user.id:isloggedin]] |
isnotloggedin | Returns true if the user is not authenticated in this context. | [[+modx.user.id:isnotloggedin]] |
toPlaceholder | Puts the entered value into the passed placeholder. It doesn’t interfere with the output of the TV value, so add [[*someTV:toPlaceholder=`placeholder`:notempty=``]] if you don’t want to output the value of the TV itself. |
[[*someTV:toPlaceholder=`placeholder`]] |
cssToHead | Place a <link> element in where the input value is inside the href attribute. |
|
Uses | modX.regClientCSS. | [[+cssTV:cssToHead]] |
htmlToHead | Insert a block of HTML code into the head of the page, before </head> . |
|
Uses | modX.regClientStartupHTMLBlock | [[+htmlTV:htmlToHead]] |
htmlToBottom | Paste the HTML code at the end of the page before </body> . Use modX.regClientHTMLBlock. |
[[+htmlTV:htmlToBottom]] |
jsToHead | Paste the JS code (or link) into the page head before </head> . Use modX.regClientStartupScript. |
[[+jsTV:jsToHead]] |
jsToBottom | Paste the JS code (or link) at the end of the page before </body> . Use modX.regClientScript. |
[[+jsTV:jsToBottom]] |
urlencode | Converts input to a URL-friendly string, similar to what an HTML form does. Similar to PHP urlencode | [[+mystring:urlencode]] |
urldecode | Converts input from a URL-friendly string, similar to PHP urldecode | [[+myparam:urldecode]] |
filterPathSegment | Added in 2.7. Converts input to a URL-friendly string using the same mechanism that turns a page title into an alias, including transliteration if enabled. Useful for custom URLs. | [[+pagetitle:filterPathSegment]] |
Caching
As a general rule, any content in a placeholder that you think might change dynamically should be cached. For example:
[[+placeholder:default=`Default value!`]]
This means that it might sometimes be empty and sometimes not. Why would you want that to be cached? That would defeat the purpose of an output modifier.
It’s sometimes okay to use output modifiers in a cached placeholder, but only if you’re calling a snippet that also sets them to cacheable. Otherwise, you’re doing something counterintuitive – trying to statically cache something that was never static.
The general rule is: If you set a placeholder on an uncached snippet, the placeholder will also need to be cached if you expect the placeholder’s content to be different.
Using an output modifier with tag properties
If you have properties for a tag, you can specify these after the modifier:
[[!getResources:default=`Извините, ничего не соответствует вашему запросу.`?
&tplFirst=`blogTpl`
&parents=`2,3,4,8`
&tvFilters=`blog_tags==%[[!tag:htmlent]]%`
&includeTVs=`1`
]]
Creating a Custom Output Modifier
Also, Snippets can be used as custom modifiers. Simply put, Snippets are a name instead of a modifier. An example snippet makeExciting that adds a variable number of exclamation points:
[[*pagetitle:makeExciting=`4`]]
This call to the document variable with the output modifier will pass these properties to the snippet:
Parameter | Value | Example output |
---|---|---|
input | The value of the element. | The value of [[*pagetitle]] |
options | Any value passed modifier. | ‘4’ |
token | Parent element type. | * (pagetitle token) |
name | Parent element name. | pagetitle |
tag | Full parent tag. | [[*pagetitle:makeExciting=`4`]] |
Here is an example implementation for our makeExciting snippet:
$defaultExcitementLevel = 1;
$result = $input;
if (isset($options)) {
$numberOfExclamations = $options;
} else {
$numberOfExclamations = $defaultExcitementLevel;
}
for ( $i = $numberOfExclamations; $i > 0; $i-- ) {
$result = $result . '!';
}
return $result;
The return value of the call will be whatever the snippet returns. For our example, the result will be the value of the pagetitle document variable with four exclamation marks.
The original input value will be returned if the snippet returns an empty string.
Chaining (Multiple Output Filters)
A good example of chaining would be formatting a date string into a different format, like this:
[[+mydate:strtotime:date=`%Y-%m-%d`]]
Direct access to the modx_user_attributes
table in the database using output modifiers instead of a Snippet can be achieved simply by using the userinfo modifier. Select the appropriate column from the table and specify it as the output modifier property, like this:
User Internal Key: [[!+modx.user.id:userinfo=`internalKey`]]
User name: [[!+modx.user.id:userinfo=`username`]]
Full Name: [[!+modx.user.id:userinfo=`fullname`]]
Role: [[!+modx.user.id:userinfo=`role`]]
E-mail: [[!+modx.user.id:userinfo=`email`]]
Phone: [[!+modx.user.id:userinfo=`phone`]]
Mobile Phone: [[!+modx.user.id:userinfo=`mobilephone`]]
Fax: [[!+modx.user.id:userinfo=`fax`]]
Date of birth: [[!+modx.user.id:userinfo=`dob`:date=`%Y-%m-%d`]]
Gender: [[!+modx.user.id:userinfo=`gender`]]
Country: [[+modx.user.id:userinfo=`country`]]
State: [[+modx.user.id:userinfo=`state`]]
Zip Code: [[+modx.user.id:userinfo=`zip`]]
Photo: [[+modx.user.id:userinfo=`photo`]]
Comment: [[+modx.user.id:userinfo=`comment`]]
Password: [[+modx.user.id:userinfo=`password`]]
Cache Password: [[+modx.user.id:userinfo=`cachepwd`]]
Last Login: [[+modx.user.id:userinfo=`lastlogin`:date=`%Y-%m-%d`]]
The Login:[[+modx.user.id:userinfo=`thislogin`:date=`%Y-%m-%d`]]
Number of Logins: [[+modx.user.id:userinfo=`logincount`]]
[[!+modx.user.id]]
defaults to the currently logged in user id. Of course, you can replace this with [[*madeby]]
or other resource or placeholder field that returns a numeric id representing the user.
Note that the userid and username are already available by default in MODX, so you don’t need to use the userinfo modifier:
[[!+modx.user.id]] - Outputs the userid
[[!+modx.user.username]] - Outputs the username
You’ll probably want to call these without caching (see the note about caching above) to prevent unexpected results.
Examples of Custom Output Filters
Custom output filters are MODX snippets designed to format the output of a placeholder in the presentation layer (in a template or in a block). If a raw placeholder, such as [[*pagetitle]]
.
returns a string of text, you can change it with a custom output filter, such as: [[*pagetitle:myOutputFilter]]
.
simply by creating a snippet named myOutputFilter
In the example above, the pagetitle value will be changed by the snippet named myOutputFilter
Creating a Custom Output Modifier
When writing your own Output Modifier, your snippet can take the following inputs:
$input; // the value to be formatted/filtered
$options; // optional values passed in backticks
A custom output filter is simply a Snippet that is intended to modify content. Simply put, a Snippet instead of a modifier.
The syntax is that the Snippet name comes after the colon. An example snippet named ‘makeDownloadLink’: [[+file:makeDownloadLink=`notitle`]]
.
This will pass these properties to the snippet:
Parameter | Value | Example result |
---|---|---|
input | The value of the element. | The value of [[+file]] |
options | Any value passed to the modifier. | ‘notitle’ |
token | The type of the parent element. | + (token on file ) |
name | Name parent element | file |
tag | The full parent tag. | [[+file:makeDownloadLink=`notitle`]] |
The most important (and perhaps most obvious) of these parameters is the $input parameter. Your snippet could do something as simple as this: return strtolower($input);
.
Examples
Since the examples below are not included in the core, you’ll need to add them yourself. Luckily, MODX makes it ridiculously easy. You can simply use snippets as output filters, so the process of adding a custom output filter is simply adding a new snippet! To use an output filter, you reference the snippet name.
For documentation authors: please add examples in alphabetical order.
alternateClass
alternateClass simply checks if the passed integer (like a count placeholder) can be divided by two. If it can, it returns the class you specified as the output filter property.
<?php
/*
* Based on phx:alternateClass by Smashingred
* Updated for Revolution by Mark Hamstra.
*/
if ($input % 2) {
return $options;
} else {
return ''; // You can set another class here
}
?>
Use it like this: [[+component.idx:alternateClass=`alt`]]
.
parseLinks
The parseLinks output filter finds links and replaces them with the html <a>
attribute </a>
<?php
/*
* Based on phx:parseLinks
*/
$t = $input;
$t = ereg_replace("[a-zA-Z]+://([.]?[a-zA-Z0-9_/-])*", "<a href=\"\\0\">\\0</a>", $t);
$t = ereg_replace("(^| |\n)(www([.]?[a-zA-Z0-9_/-])*)", "\\1<a href=\"http://\\2\">\\2</a>", $t);
return $t;
parseTags
This parseTags takes input as a comma separated list and makes all individual tags a link to resource 9 with the query parameter tag=tagname appended to the link.
<?php
/*
* Based on phx:parseLinks
*/
$t = $input;
$t = ereg_replace("[a-zA-Z]+://([.]?[a-zA-Z0-9_/-])*", "<a href=\"\\0\">\\0</a>", $t);
$t = ereg_replace("(^| |\n)(www([.]?[a-zA-Z0-9_/-])*)", "\\1<a href=\"http://\\2\">\\2</a>", $t);
return $t;
parseTags
This parseTags takes input as a comma separated list and makes all individual tags a link to resource 9 with the tag=tagname query parameter appended to the link.
<?php
/*
* parseTags output filter
* by Mark Hamstra (http://www.markhamstra.nl)
* free to use / modify / distribute to your will
*/
if ($input == '') { return ''; } // Output filters are also processed when the input is empty, so check for that.
$tags = explode(', ',$input); // Based on a delimiter of comma-space.
foreach ($tags as $key => $value) { // Process them individually
$output[] = '<a href="'.$modx->makeurl(9, '', array('tag' => $value)).'">'.$value.'</a>';
}
return implode(', ',$output); // Delimit again with a comma-space
shorten
Это сокращает ввод, например :ellipsis, но не усекает слова. По умолчанию длина макс. 50 символов. Основано на коде от gOmp.
<?php
$output = '';
$options = !empty($options)?$options:50;
if (!empty($input) && !empty($options)) {
if (strlen($input) > $options) {
$output = substr($input, 0, strrpos(substr($input, 0, $options), ' ')).' …';
}
else{
$output = $input;
}
}
return $output;
?>
substring
Get a substring of the input.
<?php
$options=explode(',',$options);
return count($options)>1 ? substr($input,$options[0],$options[1]) : substr($input,$options[0]);
?>
Example:
<span>[[*introtext:substring=`0,1`]]</span>[[*introtext:substring=`1`]]
numberformat
<?php
$number = floatval($input);
$optionsXpld = @explode('&', $options);
$optionsArray = array();
foreach ($optionsXpld as $xpld) {
$params = @explode('=', $xpld);
array_walk($params, function(&$v) { return $v = trim($v);});
if (isset($params[1])) {
$optionsArray[$params[0]] = $params[1];
} else {
$optionsArray[$params[0]] = '';
}
}
$decimals = isset($optionsArray['decimals']) ? $optionsArray['decimals'] : null;
$dec_point = isset($optionsArray['dec_point']) ? $optionsArray['dec_point'] : null;
$thousands_sep = isset($optionsArray['thousands_sep']) ? $optionsArray['thousands_sep'] : null;
$output = number_format($number, $decimals, $dec_point, $thousands_sep);
return $output;
Example:
[[+price:numberformat=`&decimals=2&dec_point=,&thousands_sep=.`]]