Twig
Functions
ems_html
Will return a instance of EmsHtml which is an extension of Twig\Markup. You can easyly replace text, remove html tags, printUrls.
Example
This example is usefull for generating pdf's.
- This wil replace 'example' by 'EXAMPLE' and 'searchX' by 'replaceX'
- Remove all a tags if the attribute text contains 'mywebsite.com' and will keep the content
- Print urls will transform the a tags based on the format (default: ':content (:href)')
{% set description = ems_html(page.description) %}
{% do description
.replace({ 'example': 'EXAMPLE', 'searchX': 'replaceX' })
.removeTag('a', ".*?mywebsite.com.*?", true)
.printUrls(':content (<i><u>:href</u></i>)')
%}
{{ description|emsch_routing_config(emschRoutingConfig) }}ems_nested_search
Search all choices of a nested field, and this function will runtime cache the result.
Arguments
- alias: name of the elasticsearch alias
- contentTypeNames: string or array of contentType names
- nestedFieldName: namem of the nestedField
- search: key/value array, key is nested property name, value is search value
Example
The following example will build 3 variables by using the ems_nested_search, the choices will only build once and cached.
{% set example1 = ems_nested_search('my_alias', 'structure', 'documents', {'id': 'd2214354-a946-4e60-8e1a-921a643df3ad'}) %}
{% set example2 = ems_nested_search('my_alias', 'structure', 'documents', {'id': '9d501b0f-13c1-42e1-a4ae-242650dc6dbd'}) %}
{% set example3 = ems_nested_search('my_alias', 'structure', 'documents', {'id': '0186c0ac-4d8f-4755-a8f0-afa9fb86d599'}) %}ems_image_info
Retrieve information (size, resolution, mime type and extension) about an image, based on its hash. If the hash can not be recognized as an image or does not exist, null is returned.
Arguments
- hash: hash(sha1) of the image
Where '4ef5796bb14ce4b711737dc44aa20bff82193cf5' is the hash of a jpg
{{ ems_image_info('4ef5796bb14ce4b711737dc44aa20bff82193cf5') }}
// will return
{
'width': 128,
'height': 245,
'mimeType': 'image/jpg',
'extension': jpg,
'heightResolution': 96,
'widthResolution': 96
}ems_uuid
Generate a version 4 (random) UUID. More info.
{{ ems_uuid() }}ems_store_read
Retrieve, or initialize, an associative array (a.k.a. store data) for a given key from the first Store Data Services where the key is available. See the Stora Data documentation for more details.
{% set data = ems_store_read('forum') %}
<form method="post" action="{{ path('emsch_update_store') }}">
<textarea name="data" cols="10">{{ data.get('[data]') }}</textarea>
<input name="submit" type="submit" value="Submit">
</form>ems_store_save
Update a store data in all store data services. This function must be called in a non-safe request (i.e. POST or PUT). See the Stora Data documentation for more details.
emsch_update_store:
config:
path: '/post-data'
controller: 'emsch.controller.router::redirect'
method: [POST]
template_static: template/redirects/post-data.json.twig{%- block request %}
{% apply spaceless %}
{% set data = ems_store_read('forum') %}
{% do data.set('[data]', app.request.get('data')) %}
{% do ems_store_save(data) %}
{{ {
url: path('home'),
}|json_encode|raw }}
{% endapply %}
{% endblock request -%}ems_store_delete
Delete a store data in all store data services. This function must be called in a non-safe request (i.e. POST or PUT). See the Stora Data documentation for more details.
emsch_delete_store:
config:
path: '/delete-post-data'
controller: 'emsch.controller.router::redirect'
method: [POST]
template_static: template/redirects/delete-post-data.json.twig{%- block request %}
{% apply spaceless %}
{% do ems_store_delete('forum') %}
{{ {
url: path('home'),
}|json_encode|raw }}
{% endapply %}
{% endblock request -%}ems_flash
Add a flash to the symfony request flash bag.
{% do ems_flash('error', 'error.default'|trans) %}You can use the following template for displaying the flashes (bootstrap5).
{%- set alertTypes = {
'success': 'alert-success',
'error': 'alert-danger',
'warning': 'alert-warning',
'info': 'alert-info'
} -%}
{%- for type, class in alertTypes -%}
{%- for message in app.session.flashBag.get(type) -%}
<div class="alert {{ class }} alert-dismissible fade show" role="alert">
{{ message }}
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
</div>
{%- endfor -%}
{%- endfor -%}ems_file_reader_data
Use the FileReader to get CSV or MS Excel fil content.
<pre>{{ ems_file_reader_data('57bcba09d6f5e06852b83b2b2ba545529f862a87', {'all_sheets': true})|json_encode(constant('JSON_PRETTY_PRINT')) }}</pre>Options:
delimiter(string): For CSV fileencoding(string): file's charsetall_sheets(boolean): Extract only the active sheet (false, default) or all sheets (true)
ems_file_reader_cells
Returns a cells iterator
<pre>{% set cellsIterator = ems_file_reader_cells('57bcba09d6f5e06852b83b2b2ba545529f862a87', {'exclude_rows': [0]}) }}</pre>Options:
mime_type(string): File mimetypedelimiter(string): CSV delimiterencoding(string): file's charsetexclude_rows(int[]): skip those rowslimit(int): limit to the first rows
ems_check_ip
Checks if an IPv4 or IPv6 address is contained in the list of given IPs or subnets. In order to avoid HTTP cache issues, this function must be called in a non-safe request (i.e. POST or PUT).
{% set clientIp = app.request.headers.get('X-FORWARDED-FOR')|default('192.168.0.5') %}
{% set ranges = [
'192.168.0.0/24',
'10.0.0.0/8',
'203.0.113.5',
'172.16.0.0/255.240.0.0',
'2001:db8::/32',
'fd00::/8',
'2a02:26f0:10::5',
] %}
{% if ems_check_ip(clientIp, ranges) %}
{# display sensitive contents here #}
{% endif %}Twig filters
ems_anti_spam
For obfuscation of pii on your website when the user agent is a robot.
Implementation details are based on http://www.wbwip.com/wbw/emailencoder.html using ems_html_encode. The following data can be obfuscated (even inside a wysiwyg field):
- emailadress
no_reply@example.com
{{- 'no_reply@example.com'|ems_anti_spam -}}- phone number in
<a href="tel:____">
{{- '<a href="tel:02/123.50.00">repeated here, the number will not be encoded</a>'|ems_anti_spam -}}- custom selection of pii using a span with class "pii"
{{- '<span class="pii">02/123.50.00</span>'|ems_anti_spam -}}See unit test for more examples.
Note: Phone numbers are only obfuscated if they are found inside "tel:" notation. When a phone is used outside an anchor, the custom selection of pii method should be used.
Note: When using custom selection of pii, make sure that no HTML tags are present inside the pii span.
Note: the custom selection pii span is only present in the backend. The obfuscation method removes the span tag from the code that is sent to the browser.
ems_html_encode
You can transform any text to its equivalent in html character encoding.
{{- 'text and téxt'|ems_html_encode -}}See unit test for more examples.
ems_markdown
Filter converting a Markdown text into an HTML text following the GitHub standards.
{{ source.body|ems_markdown }}ems_stringify
Filter converting any scalar value, array or object into a string.
{{ someObject|ems_stringify }}
{{ someArray|ems_stringify }}ems_asset_average_color
Filter returning the average color, in CSS rgb format, of a passed hash.
I.e.
{{ 'ed266b89065e74483248da7ff71cb80e3cca40a5'|ems_asset_average_color}}Will return #666666. It might be useful in order to define a background color:
{{ ems_asset_path({
filename: 'avatar.jpg',
sha1: avatarHash,
mimetype: 'image/jpeg',
}, {
_config_type: 'image',
_resize: 'fill',
_background: avatarHash|ems_asset_average_color,
_width: 400,
_height: 600,
_quality: 80,
_get_file_path: localPath,
}) }}style="background-color: {{ avatarHash|ems_asset_average_color }}"ems_replace_regex
Apply php preg_replace function on a text string. All possible exceptions are catched and logged as warning.
Example replace all ems links by a span tag.
{% set text %}
<h1>Example</h1>
<p><a href="ems://object:page:dabc33113a53866fe1a1443b42a4c16d1f4bc138">Homepage</a></p>
<p><a href="ems://object:page:7cc6310cc57818bb571e706ede0a4c10623b430c">News</a></p>
<p>the end</p>
{% endset %}
{{ text|ems_replace_regex('/<a.*?href="ems:\\/\\/\\S+".*?>(.*?)<\\/a>', '<span>$1</span>')|raw }}ems_html_decode
Convert HTML entities to their corresponding characters
The following example will generate a è :
{{ '`'|ems_html_decode|json_encode|raw }}Other parameters:
- flags: refers to html_entity_decode's flags paramter, default value
ENT_QUOTES | ENT_SUBSTITUTE | ENT_HTML5 - encoding: defining the encoding used when converting characters, default value
"UTF-8""
ems_hash
Generate a hash value from the message. See the PHP hash function.
{{ 'foobar'|ems_hash }}
{{ 'foobar'|ems_hash('sha1') }} {# outputs 8843d7f92416211de9ebb963ff4ce28125932878 #}Other parameters:
- algo: refers to the hash's algo parameter, default value
nullwhich means that theems_common.hash_algowill be used - binary: refers to the hash's binary parameter, default value
false. When set totrue, outputs raw binary data
ems_format_bytes
Useful to generate a human readable file size from an interger.
{{ 21666|ems_format_bytes }} {# displays: 21.16 KB #}A second 'precision' parameter can be defined:
{{ 21666|ems_format_bytes(1) }} {# displays: 21.2 KB #}ems_ascii_folding
Convert UTF-8 characters in string by their equivalent in the "old" ascii table:
{{ 'Chemin d''accès: î$]&²'|ems_ascii_folding }} {# displays: Chemin d acces: i$]&² #}It's useful if you want to sort an array regardless accented characters:
{% set sortedArray = notSortedArray|sort((a, b) => a|ems_ascii_folding <=> b|ems_ascii_folding) %}ems_template_exists
Test if a template exists or not. This function works with all kind of templates:
{% if not ems_template_exists("@EMSCH/template/page/#{name}.html.twig") %}
{% do emsch_http_error(404, 'Page not found') %}
{% endif %}ems_analyze
Analyze an input string using the elasticsearch Analyze API:
<p>{{ ems_analyze('― — – ‒ ‹ › ′ ‵ ‘ ’ ‚ ‛ ″ ‴ ‶ ‷ “ ” „ ‟ « » ü Ü ß ẞ ä ö Ä Ö', {
'filter': ['asciifolding'],
'tokenizer': 'keyword'
}) }}</p>
{# ― - - - ' ' ' ' ' ' ' ' " ‴ " ‷ " " " ‟ " " u U ss SS a o A O #}Arguments:
- text: the text to analyze (string)
- parameters: the Analyze API parameters (check the elasticsearch Analyze API documentation) (array)
- index: an optional index name (string)
ems_json_decode
Call the PHP \json_decode method with those default values: public function jsonDecode(string $json, bool $assoc = true, int $depth = 512, int $options = 0)
{% set config = 'conems_array_key
Use the value of the parameter identified by the given name as array index
{% set paths = rawData.paths|default([])|filter(p => p.locale == locale)|ems_array_key('uid') %}ems_ouuid
Extract a OUUID from an ElasticMS link
{% set categories = emsch_search('category', {
"size": 1000,
"query": { "terms": { "_id": query.aggregations.categories.buckets|map(p => p.key|ems_ouuid) }},
"sort": [
{("title_#{locale}.alpha_order"): {"order": "asc"}}
],
"_source": ["#{app.request.locale}.title"]
}).hits.hits|default([])|ems_array_key('_id')|map(p => attribute(p._source, app.request.locale).title) %}ems_md5
Calculate the md5 hash of a string
{{ app.user.email|lower|md5 }}ems_luma
Calculate the luminance of a color(string)
{% set luminance = '#FF56DD'|ems_luma %}ems_contrast_ratio
Calculate the contrast ratio between 2 colors (string)
{% if '#FF56DD'|ems_contrast_ratio('black') > '#FF56DD'|ems_contrast_ratio('white') %}#000000{% else %}#ffffff{% endif %}ems_color
Convert a color (string) into a EMS\Helpers\Standard\Color
{% set color = '#FF56DD'|ems_color %}ems_slug
Convert a string into an url friendly string
{{ 'How do you do ?'|ems_slug }}
{# how-do-you-do #}Arguments:
- locale: default value
en - separator: default value
- - lower: default value
true
{{ 'Wie fährst du deinen großen LKW ?'|ems_slug('de', '/', false) }}
{# Wie/faehrst/du/deinen/grossen/LKW #}ems_file_from_archive
Returns a path to a temporary asset extracted from an archive (a zip file). Useful to get local path to an asset (e.g. in case of PDF generation)
{% set path = ems_file_from_archive('253b903b1fb3ac30975ae9844a0352a65cdcfa3d', 'img/logos/full-logo.svg') %}This function also accept extra options:
extract: Specify that the function can not try to re-extract the archive if the searched path is missing. If disabled the function won't throw an error butnull. Default value:true.asTempFile: Returns a EMS\Helpers\File\TempFile object when activated, a path to the temporary file instead. A TempFile is useful to get file's contents with the member functiongetContents(). Default valuefalse
Example:
{% set tempFile = ems_file_from_archive(hash, "#{path}/index.php", {
extract: false,
asTempFile: true,
}) %}ems_files_in_archive
Returns the list of files present in an archive (EMS archive or Zip file)
{% set files = ems_files_in_archive(hash) %}This method returns an array like this:
{
"0693f7c7e26507b5d464a99f6a03b9309560abf3.json": {
"filename": "0693f7c7e26507b5d464accf6a03b9309560abf3.json",
"hash": "0693f7c7e26507b5d464accf6a03b9309560abf3",
"type": "application/json",
"size": 3561
},
"crm-export.xlsx": {
"filename": "crm-export.xlsx",
"hash": "dd2650a9d4537c5127b9907e83f1e508523d3c18",
"type": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
"size": 167352
},
"2025-09 Facture Service 1113975398.PDF": {
"filename": "2025-09 Facture Service 1113975398.PDF",
"hash": "2ddf565c90bb89b0d860a538828f1dd7bb8b37a5",
"type": "application/pdf",
"size": 32640
}
}ems_link
Return the EMSLink object
{% set emsLink = 'page:064efcc7751ee8b0915416a717e2db46d15c77eb'|ems_link %}ems_valid_mail
Returns true if the input is a valid email
{%- if _source.email|ems_valid_mail -%}{% endif %}ems_uuid filter
Generate a version 5 UUID from a value. More info.
{{ 'my_unique_id_value'|ems_uuid }}ems_date
Generate a \DateTimeImmutable object from a value.
{% set date = '31/12/1998 0:00:00'|ems_date('j/m/Y H:i:s') %}
{{ date.format('d-m-Y') }}
{{ date.timezone }}ems_int
Use php \intval function on input
{% set size = app.request.query.get('size', 0)|ems_int %}ems_clear_http_caches
Calls the configured reverse proxy services to invalidate part or all of their caches.
It accepts one optional argument:
URL or Tags(optional):- If it contains an empty array (default value), a full cache purge will be sent.
- If it is a string starting with
/, a cache clear by URL will be sent. - Otherwise, a cache clear by tags will be sent.
Example of a cache clear route
The URL is triggered by a clear-cache webhook event, at the endpoint //localhost/_clear_cache.
Depending on the event data:
- If it contains a
tagsattribute (string or array of strings), a tag-based cache clear will be sent. - If it contains a
urlattribute (string), a URL-based cache clear will be sent. - Otherwise, a full cache purge will be sent.
The emsch_clear_cache route:
emsch_clear_cache:
config:
path: '/_clear_cache'
method: [POST]
host: 'localhost'
template_static: template/admin/clear-cache.html.twigThe template/admin/clear-cache.html.twig twig:
{%- set event = emsch_webhook_event() -%}
{%- if event.name == 'clear-cache' -%}
{%- do ems_clear_http_caches(event.data.tags|default(event.data.url|default([]))) -%}
{%- set success = true -%}
{%- endif -%}
{{- { success: success|default(false) }|json_encode|raw -}}