PHP functions
Templates can call PHP functions:
{count($items)} items
{json_encode(['foo' => 'bar'])}
{strip_tags($html)}
{profile('fullname')}The whitelist is off in PageBlocks
Take this literally: any existing PHP function is reachable from a template — strrev, file_get_contents, exec, unlink. The engine does have a whitelist, but it is enabled by the disable_native_funcs option, and View::init() does not set it. Until it is set, the check is effectively function_exists() and lets everything through.
The practical consequence: a template is equivalent to PHP code. Anyone who can edit a chunk in the manager can run anything on the server. Grant element-editing permissions accordingly — as filesystem access, not as markup access.
The whitelist, once enabled
disable_native_funcs turns on the list check. That is a sensible setting for sites where chunks are edited by content people rather than developers.
The engine's base list is 18 functions:
count | is_string | is_array |
is_numeric | is_int | is_double |
is_object | gettype | constant |
strtotime | json_encode | json_decode |
ip2long | long2ip | strip_tags |
nl2br | explode | implode |
On top of it the component adds its own helpers: asset, langs, language, languages, lang_url, multilingual, resources, pbresources, pbResources, users.
Your own go in the site file:
core/App/Helpers/fenom/php_functions.phpreturn [
'file_exists',
'profile',
'person_name',
];The check is case-sensitive
contactDefaults and contactdefaults are two different names as far as this list is concerned. List a function you write in camelCase under both spellings.
While disable_native_funcs is off, this file changes nothing — everything is allowed anyway. Its point is to describe up front the set the site is meant to run on, so that enabling the check does not break anything.
A modifier instead of a function
A PHP function in a template is neither the only nor usually the best option. A modifier in modifiers.php works both as a filter and as a function, does not depend on the whitelist, and does not drag global names into the template:
// core/App/Helpers/fenom/modifiers.php
return [
'excerpt' => fn ($text, int $n = 100) => mb_substr(strip_tags((string) $text), 0, $n),
];{$page.introtext|excerpt:200}
{excerpt($page.introtext, 200)}{$.php} and {$.call}
These accessors call an arbitrary callable. Upstream, they reached call_user_func_array() with no checks at all — the option to forbid PHP calls existed, but the code never asked for it. In this fork both disable_php_calls and the native function whitelist are honoured; see the introduction.