Smarty HTML generation plugins


1Introduction

When creating Smarty templates, you can use control structures ({if} conditions, {foreach} loops, etc.), custom tags ({cycle}, {mailto}, {math}, etc.), and modifiers (default, date_format, escape, replace, etc.) provided by Smarty.

To make development easier, you can create your own custom tags and modifiers. Here's an example of each.


2Create a custom modifier

We're going to create a modifier that translates a string into another language.
(see Smarty documentation on writing modifiers)

For example, by writing this in a Smarty template:

{* direct translation of a string *}
{"Article title"|translate:'fr'}

{* translation of variable contents *}
{$product1.type|translate:'fr'}
{$product2.type|translate:'fr'}

You might get the following result:

Titre de l'article

Ordinateur
Écran

To develop this modifier, we'll use the data source that connects to the Deepl API, which we saw in the previous tutorial. The modifier code presupposes the presence of this data source in the configuration file, under the name transl.
Here's the modifier code, to be saved in the lib/smarty-plugins/modifier.translate.php file:

<?php

/**
 * Smarty modifier for translating texts.
 * @param   string    $text    String to translate.
 * @param   string    $lang    Language into which to translate the text.
 * @return  string    The translated text.
 */
function smarty_modifier_translate(string $text, string $lang) : string {
    // data source retrieval
    global $temma;
    $datasource = $temma->getLoader()->dataSources['trad'] ?? null;
    if (!$datasource)
        return ($text);

    // call the Deepl API to translate the string
    try {
        $result = $datasource->translate($text, $lang);
    } catch (\Exception $e) {
        $result = null;
    }

    return ($result ?: $text);
}
  • Line 9: Definition of the smarty_modifier_translate() function.
  • Line 11: Definition of the $temma global variable, which contains the framework's main object.
  • Line 12: Use the global variable to retrieve the dependency injection component (with the getLoader() method), then retrieve the array of data sources, and from there retrieve the data source connected to the Deepl API.
  • Lines 13 and 14: If the data source is not defined, the original (untranslated) text is returned.
  • Lines 17 to 21: Call the data source to translate the text.
  • Line 23: Return translated text. If empty, the original text is returned.

3Create a custom tag

Let's imagine you wanted to create a Smarty tag to facilitate the creation of titles.
(see Smarty documentation on writing custom tags).

For example, by writing this in your template:

{title text="First title" level="1"}
{title text="First sub-title" level="2"}
<p>Blah blah</p>

{title text="Second sub-title" level="2"}
<p>Blah blah</p>

{title text="Second title" level="1"}
{title text="First sub-title" level="2"}
<p>Blah blah</p>

{title text="Second sub-title" level="2"}
<p>Blah blah</p>

You would get the following HTML code:

<h1 id="1-first-title">1 First title</h1>
<h2 id="1-1-first-sub-title">1.1 First sub-title</h2>
<p>Blah blah</p>

<h2 id="1-2-second-sub-title">1.2 Second sub-title</h2>
<p>Blah blah</p>

<h1 id="2-Second-titre">2 Second title</h1>
<h2 id="2-1-first-sub-title">2.1 First sub-title</h2>
<p>Blah blah</p>

<h2 id="2-2-second-sub-title">2.2 Second sub-title</h2>
<p>Blah blah</p>

Here's the code for such a custom tag, to be saved in the lib/smarty-plugins/function.title.php file:

<?php

/**
 * Smarty tag used to insert HTML titles.
 * @param   array             $params   Associative array containing the parameters supplied to the tag.
 * @param   \Smarty\Template  $template Object representing the processed template.
 * @return  string   The generated HTML code.
 */
function smarty_tag_title($params, $template) {
    // initialize the static variable $levelsCount,
    // which contains the depth of each title level
    static $levelsCount = [0];

    // parameters retrieval
    $text = trim($params['text'] ?? null);
    $level = intval($params['level'] ?? 1) ?: 1;

    // check
    if (!$text)
        return ('');

    // management of the static variable
    $levelsCount = array_slice($levelsCount, 0, $level);
    $levelsCount[$level - 1] ??= 0;
    $levelsCount[$level - 1]++;

    // result preparation
    $title = implode('.', $levelsCount) . ' ' . $text;
    $id = \Temma\Utils\Text::urlize($title);

    return sprintf('<h%d id="%s">%s</h%d>', $level, $id, $title, $level);
}
  • Line 9: Declaration of the smarty_tag_title() function. It takes two parameters, an associative array containing the parameters defined in the template, and an object representing the template in which the tag was used (we won't use this object).
  • Line 12: Definition of a static variable which is initialized to an array containing an integer equal to zero. The fact that this is a static variable means that it will retain its value between each call to the function. This variable contains the depth of each title level, i.e. the number of titles known for each current title level.
  • Lines 15 and 16: Retrieve the parameters supplied to the tag in the template. Absent or incorrect values are handled.
  • Lines 19 and 20: Handling of empty text.
  • Line 23: The $levelsCount array is reduced if necessary, when the title level passed as a parameter is lower than the previous one.
  • Lines 24 and 25: In the $levelsCount array, the entry corresponding to the title level passed in parameter is incremented (after being initialized to zero if necessary).
  • Lines 28 and 29: Definition of the title to be inserted in the HTML code, and of the associated identifier. To generate the identifier, apply the urlize() function to the title.
  • Line 31: Returns the HTML string formed by the <Hn> tag, with the identifier as attribute and the title as content.