Skip to content

PHP functions

Templates can call PHP functions:

fenom
{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 templatestrrev, 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:

countis_stringis_array
is_numericis_intis_double
is_objectgettypeconstant
strtotimejson_encodejson_decode
ip2longlong2ipstrip_tags
nl2brexplodeimplode

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.php
php
return [
    '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:

php
// core/App/Helpers/fenom/modifiers.php
return [
    'excerpt' => fn ($text, int $n = 100) => mb_substr(strip_tags((string) $text), 0, $n),
];
fenom
{$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.

© PageBlocks 2019-present