[Tutorial] Convert to Twig Syntax

Discussion forum for Extension Writers regarding Extension Development.
User avatar
MattF
Extensions Development Coordinator
Extensions Development Coordinator
Posts: 6039
Joined: Sat Jan 17, 2009 9:37 am
Location: Los Angeles, CA
Name: Matt Friedman

[Tutorial] Convert to Twig Syntax

Post by MattF »

Why should you convert to (or start using) Twig syntax in your extensions?

1. phpBB's template syntax is converted behind the scenes to use twig anyways, so if your extension is already written using twig syntax, it does not need to be converted, which means less processing/memory overhead from your extension.

2. Twig is the most common PHP template syntax format so every reputable IDE and text editor can recognize twig syntax, providing syntax highlighting, auto completion, inspection and error detection, etc. It simply makes writing your code easier to read and inspect.

3. Twig is phpBB's future. While prosilver does still use the old phpBB syntax this is only because it's too much work to rewrite it. Twig will be used as the template language behind the core style that may be developed for a future release of phpBB.

4. You can do a heck of a lot more with Twig than you could ever do with phpBB syntax.

What follows are basic example conversions from old phpBB to twig syntaxes:

Variables
phpBB syntax

Code: Select all

{FOO_BAR}
Twig syntax

Code: Select all

{{ FOO_BAR }}

Language keys
phpBB syntax

Code: Select all

{L_FOO_BAR}
Twig syntax

Code: Select all

{{ lang('FOO_BAR') }}
phpBB syntax

Code: Select all

{LA_ESCAPED_FOR_JAVASCRIPT}
Twig syntax

Code: Select all

{{ lang('ESCAPED_FOR_JAVASCRIPT')|e("js") }}
or
{{ lang('ESCAPED_FOR_JAVASCRIPT')|addslashes }}

Logic
phpBB syntax

Code: Select all

<!-- IF S_FOO -->
    ... hello ...
<!-- ELSE -->
    ... world...
<!-- ENDIF -->
Twig syntax

Code: Select all

{% if S_FOO %}
    ... hello ...
{% else %}
    ... world ...
{% endif %}
https://twig.sensiolabs.org/doc/2.x/tags/if.html


Looping
phpBB syntax

Code: Select all

<!-- IF .users -->
    <!-- BEGIN users -->
        This is {users.VALUE}
    <!-- BEGINELSE -->
        no values
    <!-- END users -->
<!-- ENDIF -->
Twig syntax

Code: Select all

{% if loops.users %}
    {% for user in loops.users %}
        This is {{ user.VALUE }}
    {% else %}
        no values
    {% endfor %}
{% endif %}
https://twig.sensiolabs.org/doc/2.x/tags/for.html
Note that where we defined user in the for context, you can name that anything you want. Also note that the loops. prefix is only needed in phpBB 3.1.x, and is not needed if you are writing for 3.2.x or later.


Includes
phpBB syntax

Code: Select all

<!-- INCLUDE overall_header.html -->
<!-- INCLUDECSS @foo_bar/style.css -->
<!-- INCLUDEJS @foo_bar/script.js -->
Twig syntax

Code: Select all

{% include 'overall_header.html' %}
{% INCLUDECSS '@foo_bar/style.css' %}
{% INCLUDEJS '@foo_bar/script.js' %}
https://twig.sensiolabs.org/doc/2.x/tags/include.html


Template events
phpBB syntax

Code: Select all

<!-- EVENT foo_template_event_location -->
Twig syntax

Code: Select all

{% EVENT foo_template_event_location %}

Defining template variables
phpBB syntax

Code: Select all

<!-- DEFINE $FOO = 'foo' -->
<!-- IF $FOO neq '' -->
    {$FOO}
<!-- ENDIF -->
Twig syntax

Code: Select all

{% DEFINE FOO = 'foo' %}
{% if definition.FOO != '' %}
    {{ definition.FOO }}
{% endif %}

{# or if your custom var will never be used in phpBB style syntax use: #}

{% set bar = 'bar' %}
{% if bar != '' %}
    {{ bar }}
{% endif %}
https://twig.sensiolabs.org/doc/2.x/tem ... -variables


Comments
phpBB syntax

Code: Select all

<!-- This is a comment -->
Twig syntax

Code: Select all

{# This is a comment #}
Formerly known as VSEMy ExtensionsPlease do not PM me for support.
User avatar
3Di
I've Been Banned!
Posts: 17538
Joined: Mon Apr 04, 2005 11:09 pm
Location: I'm with Ukraine 🇺🇦
Name: Marco

Re: [Tutorial] Convert to Twig Syntax

Post by 3Di »

Nice one, thx. A typo here..
{% INCLUDECSS '@foo_bar/style.cs's %}
should be
{% INCLUDECSS '@foo_bar/style.css' %}

And a note, isn't more understandable?

Code: Select all

{% for foo in loops.foo %}
	{{ foo.VALUE }}
{% endfor %}
I am against this kind of foo/bar/baz (Dated 1938, as the beginning) way of explain things.
I personally feel more confortable with ACME examples, so to speak.

Code: Select all

{% for user in loops.user %}
	{{ user.VALUE }}
{% endfor %}
If I define with $template->assign_block_vars('user', $template_vars); the template group I do have to use the above example, and not

Code: Select all

{% for user in loops.users %}
	{{ user.VALUE }}
{% endfor %}
notice the appended "s".

Sort of discrepance, I can say. Not so clear and leads to misunderstandings.
🆓 Free support for our extensions also provided here: phpBB Studio
🚀 Looking for a specific feature or alternative option? We will rock you!
Please PM me only to request paid works. Thx. Buy me a coffee -> Image
My development's activity º PhpStorm's proud user º Extensions, Scripts, MOD porting, Update/Upgrades
User avatar
david63
Registered User
Posts: 20646
Joined: Thu Dec 19, 2002 8:08 am

Re: [Tutorial] Convert to Twig Syntax

Post by david63 »

@Matt - one part that you have missed is the passing and escaping of variables in templates to js which, I believe, when using Twig is different than when using phpBB syntax.
David
Remember: You only know what you know and - you don't know what you don't know!

I now no longer support any of my extensions but they will start to become available here
User avatar
Galandas
Registered User
Posts: 774
Joined: Thu Jul 23, 2009 4:11 pm
Location: Italy
Name: Rey

Re: [Tutorial] Convert to Twig Syntax

Post by Galandas »

subscribed to topic :)
English is not my native language My CDB Contributions My RC extensions
User avatar
AlfredoRamos
Recognised Extension Developer
Posts: 1307
Joined: Wed Dec 25, 2013 9:06 pm
Location: /dev/null
Name: Alfredo

Re: [Tutorial] Convert to Twig Syntax

Post by AlfredoRamos »

Too bad that language keys cannot be accessed using the Twig syntax in the BBCode HTML replacement.
Some of my phpBB extensions:
:chart_with_upwards_trend: SEO Metadata | Image Markdown | :shield: hCaptcha
:trophy: Check out all my validated extensions :trophy:

:penguin: Arch Linux user | Linux Boards :penguin:
User avatar
javiexin
Code Contributor
Posts: 1157
Joined: Wed Oct 12, 2011 11:46 pm
Location: Madrid, Spain
Name: Javier

Re: [Tutorial] Convert to Twig Syntax

Post by javiexin »

Very useful for a Twig newbie like myself! Thanks a lot!

I miss a couple of things though: And what happens with the language vars that are filled in in the code, like enabled.actions.L_ACTION_EXPLAIN in the above code?

EDIT: One other thing that I stumbled with recently and that surprised me a lot is the following:
https://github.com/phpbb/phpbb/blob/ad0 ... #L151-L157
I think it would be interesting to explain such type of usage, that is new and quite powerful I must say!

Again, many thanks! Just trying to get an even more complete view, and an even better tutorial!
-javiexin
User avatar
MattF
Extensions Development Coordinator
Extensions Development Coordinator
Posts: 6039
Joined: Sat Jan 17, 2009 9:37 am
Location: Los Angeles, CA
Name: Matt Friedman

Re: [Tutorial] Convert to Twig Syntax

Post by MattF »

david63 wrote: Wed May 24, 2017 7:12 am @Matt - one part that you have missed is the passing and escaping of variables in templates to js which, I believe, when using Twig is different than when using phpBB syntax.
Well technically this post is about converting from phpBB syntax to twig. phpBB syntax does not have any sort of JS/HTML escaping in the template syntax as it has always relied on doing it in the PHP code. So it wasn't mentioned on purpose.

That falls under the category of you can do a ton of other stuff with Twig that wasn't possible in phpBB syntax. For all that other stuff, there's the Twig documentation ;)
Formerly known as VSEMy ExtensionsPlease do not PM me for support.
User avatar
MattF
Extensions Development Coordinator
Extensions Development Coordinator
Posts: 6039
Joined: Sat Jan 17, 2009 9:37 am
Location: Los Angeles, CA
Name: Matt Friedman

Re: [Tutorial] Convert to Twig Syntax

Post by MattF »

javiexin wrote: Wed May 24, 2017 8:23 pm Very useful for a Twig newbie like myself! Thanks a lot!

I miss a couple of things though: And what happens with the language vars that are filled in in the code, like enabled.actions.L_ACTION_EXPLAIN in the above code?

EDIT: One other thing that I stumbled with recently and that surprised me a lot is the following:
https://github.com/phpbb/phpbb/blob/ad0 ... #L151-L157
I think it would be interesting to explain such type of usage, that is new and quite powerful I must say!

Again, many thanks! Just trying to get an even more complete view, and an even better tutorial!
-javiexin
<!-- IF .enabled -->
{% if loops.enabled %}

Your nested loop I think would look like

Code: Select all

{% for enabled in loops.enabled %}
	{% for action in enabled.actions %}	
		{{ action.U_ACTION }}
	{% endfor %}
{% endfor %}
The code you link to at the bottom...this is all about arrays. In Twig, if a variable is an array, you can access an array item like {{ array.key }}. In the nested loops above, actions is an array value in in enabled variable, just as enabled is an array vaule in loops:

You can do nicer stuff like name a key and value of an array in the template for a more readbale template:

Code: Select all

<?php	
$template->assign_var('CURRENCIES', array(
	'USD' => 'U.S. Dollar $',
	'AUD' => 'Australian Dollar $',
	'CAD' => 'Canadian Dollar $',
));
And used in a twig template:

Code: Select all

{% for value, label in CURRENCIES %}
	<option value="{{ value }}">{{ label }}</option>
{% endfor %}
Formerly known as VSEMy ExtensionsPlease do not PM me for support.
User avatar
javiexin
Code Contributor
Posts: 1157
Joined: Wed Oct 12, 2011 11:46 pm
Location: Madrid, Spain
Name: Javier

Re: [Tutorial] Convert to Twig Syntax

Post by javiexin »

Thanks again, VSE!
javiexin wrote: Wed May 24, 2017 8:23 pm And what happens with the language vars that are filled in in the code, like enabled.actions.L_ACTION_EXPLAIN in the above code?
Would this be {{ action.L_ACTION_EXPLAIN }} ?
If so, that might be an issue, as when you code the template, you MUST know whether the language key is a direct link to the language file, or it is processed. And you cannot modify it from the (PHP) code either, that is done in some extensions, something like this:

Code: Select all

$template->assign_var('L_CORE_MESSAGE', $user->lang['CORE_MESSAGE'] . '<br/>' . $user->lang['EXT_MESSAGE']);
This would be limiting, and I would prefer to keep the current phpBB template language manipulation...
VSE wrote: Wed May 24, 2017 11:29 pm
javiexin wrote: Wed May 24, 2017 8:23 pm EDIT: One other thing that I stumbled with recently and that surprised me a lot is the following:
https://github.com/phpbb/phpbb/blob/ad0 ... #L151-L157
I think it would be interesting to explain such type of usage, that is new and quite powerful I must say!
The code you link to at the bottom...this is all about arrays.
In that particular code, it is even more extreme: it is using an OBJECT as template var value, and is using its methods in the template to get values to be presented!

-javiexin
User avatar
MattF
Extensions Development Coordinator
Extensions Development Coordinator
Posts: 6039
Joined: Sat Jan 17, 2009 9:37 am
Location: Los Angeles, CA
Name: Matt Friedman

Re: [Tutorial] Convert to Twig Syntax

Post by MattF »

javiexin wrote: Thu May 25, 2017 9:43 am Thanks again, VSE!
javiexin wrote: Wed May 24, 2017 8:23 pm And what happens with the language vars that are filled in in the code, like enabled.actions.L_ACTION_EXPLAIN in the above code?
Would this be {{ action.L_ACTION_EXPLAIN }} ?
If so, that might be an issue, as when you code the template, you MUST know whether the language key is a direct link to the language file, or it is processed. And you cannot modify it from the (PHP) code either, that is done in some extensions, something like this:

Code: Select all

$template->assign_var('L_CORE_MESSAGE', $user->lang['CORE_MESSAGE'] . '<br/>' . $user->lang['EXT_MESSAGE']);
This would be limiting, and I would prefer to keep the current phpBB template language manipulation...
-javiexin
First remember that everything in the old syntax is converted to twig. Twig is our template system.

At any rate enabled.actions.L_ACTION_EXPLAIN is no different than foo.BAR. So your example is just:

Code: Select all

{% for enabled in loops.enabled %}
   {% for actions in enabled.actions %}
      {{ actions.L_ACTION_EXPLAIN }}
   {% endfor %}
{% endfor %}
You are being misguided by the L_ in your examle. Normally any variable like {L_XX} gets sent through the lang method. But in your example it is not a simple lang var. It's just a regular variable, set in PHP code somewhere and assigned to a template var. It could just as well be be named enabled.actions.ACTION_EXPLAIN For example:
https://github.com/phpbb/phpbb/blob/mas ... s.php#L397
Formerly known as VSEMy ExtensionsPlease do not PM me for support.
User avatar
javiexin
Code Contributor
Posts: 1157
Joined: Wed Oct 12, 2011 11:46 pm
Location: Madrid, Spain
Name: Javier

Re: [Tutorial] Convert to Twig Syntax

Post by javiexin »

Yes, so you are confirming what I thought: that the variable is treated as any other, and you must know upfront whether any L_ (label) var is processed or not.

Now, my problem is not so much with L_ vars that are pre-processed and that is a known fact.

My issue is that now, the template MUST know upfront whether something is a language key, or may be filled in in PHP code, while before, that was totally transparent. This will break some extensions, as some might rely on using CORE language strings to modify content and convey additional messages.

One example: https://github.com/Wolfsblvt/advancedpo ... s.php#L629
Also here: https://github.com/Wolfsblvt/advancedpo ... s.php#L655
Note that these are only examples, so no need to solve them specifically, they are just showing what I mean.

This use would be broken using Twig language processing, as the core would use the var as language key {{ lang('NO_VOTES') }} and then the replacement in the extension would fail.

What would be the alternative for extension developers in such cases?

As you said, everything is converted to Twig, so, how is it done now? Because this works currently, so there must be a way. I assume that for vars named L_* it is checking if a regular var exists with that name, otherwise it strips the L_ and evaluates as a language key. Something like this, or somehow equivalent, would be helpful in maintaining BC.

Thanks a lot,
-javiexin
User avatar
MattF
Extensions Development Coordinator
Extensions Development Coordinator
Posts: 6039
Joined: Sat Jan 17, 2009 9:37 am
Location: Los Angeles, CA
Name: Matt Friedman

Re: [Tutorial] Convert to Twig Syntax

Post by MattF »

javiexin wrote: Thu May 25, 2017 6:48 pm My issue is that now, the template MUST know upfront whether something is a language key, or may be filled in in PHP code, while before, that was totally transparent. This will break some extensions, as some might rely on using CORE language strings to modify content and convey additional messages.
First of all nothing will break. It is up to you to convert your templates to twig, and only if you want to. You don't have to. And of course in doing so, it is up to you to convert them correctly. That is, to use the lang() method in the template on vars that are actually L_ vars. At any rate, any time you're using an L_* var, especially from the core, it should always go through {{ lang() }}

There is no magic to any of this or how it already happens. Every single {L_*} variable has always been run through the lang() method. Which is why it is wrong for ext authors and the core to still use {L_*} for anything that has already been translated in PHP, because those just get run through the lang() a second time, in either syntax, but since it's already been translated nothing changes (and nothing breaks).

Of course the core can be forgiven for this since it's full of old code (the original idea was the L_ prefix signaled the variable was tied to a language key). But the examples from from the wolfsblvt ext you linked to are wrong. You really should only prefix a lang key now with L_ in the template if you need it to be automatically fed through lang(). If you translated the variable in PHP, then it's jusrt another variable and doen't need an L_ prefix.

It's simple: Language variables that have not been translated in PHP need to be done within the template. In phpBB syntax that meant L_*... In twig it just means {{ lang() }} method.
javiexin wrote: Thu May 25, 2017 6:48 pm As you said, everything is converted to Twig, so, how is it done now? Because this works currently, so there must be a way. I assume that for vars named L_* it is checking if a regular var exists with that name, otherwise it strips the L_ and evaluates as a language key. Something like this, or somehow equivalent, would be helpful in maintaining BC.
Any key that starts with L_ in phpBB's template syntax is run through lang() and that's it. If the value matches a lang key then the value is shown, otherwise the key is passed straight through (which is why untranslated keys appear as the key itself on screen).

The template system is totally fine. There are no BC issues. There's nothing to worry about here. Calm yourself.

You can write extension in phpBB or Twig syntax, and they will work just fine in 3.1.x, 3.2.x and 3.3.x.

Here's a straight forward example of an extension being Twigified:
https://github.com/phpbb-extensions/pag ... 1b3c8d67a6
Formerly known as VSEMy ExtensionsPlease do not PM me for support.
User avatar
david63
Registered User
Posts: 20646
Joined: Thu Dec 19, 2002 8:08 am

Re: [Tutorial] Convert to Twig Syntax

Post by david63 »

Just as an aside to this discussion are there any plans as to when phpBB template syntax will be dropped?
David
Remember: You only know what you know and - you don't know what you don't know!

I now no longer support any of my extensions but they will start to become available here
User avatar
MattF
Extensions Development Coordinator
Extensions Development Coordinator
Posts: 6039
Joined: Sat Jan 17, 2009 9:37 am
Location: Los Angeles, CA
Name: Matt Friedman

Re: [Tutorial] Convert to Twig Syntax

Post by MattF »

david63 wrote: Fri May 26, 2017 6:29 am Just as an aside to this discussion are there any plans as to when phpBB template syntax will be dropped?
Not in the forseeable future and not until prosilver has been abandoned for a completely new style which will definitely be written in twig.
Formerly known as VSEMy ExtensionsPlease do not PM me for support.
User avatar
javiexin
Code Contributor
Posts: 1157
Joined: Wed Oct 12, 2011 11:46 pm
Location: Madrid, Spain
Name: Javier

Re: [Tutorial] Convert to Twig Syntax

Post by javiexin »

Thanks a lot VSE for your patience.

I have looked at the code implementing this, and I have found that:
  • lang() is NOT a Twig function, it is a phpBB function used in the "special" Twig variant used here, and enabled by the fact that Twig allows for such functions being used in the (Twig) templates
  • Regardless of the type of template syntax (phpBB or Twig), the behavior is exactly the same: the template context is checked first to see if the L_ var was set directly, and if not, then the key is used to call the user/language object, and if not, the key itself is used as the label.
    See https://github.com/phpbb/phpbb/blob/3.2 ... #L159-L184
  • An interesting effect of this, is that now, in the Twig template syntax, you CAN use language keys with parameters! So you could write something like {{ lang('KEY', 3) }} or even nesting vars, if that is allowed {{ lang('KEY', {{ VALUE }}) }} (VSE?)
So, if things stay this way, I am very happy, as I see many positives in the Twig syntax, and the potential issue around lang is a non-issue, and we can continue using the PHP template assignments as usual, without any changes.
VSE wrote: Fri May 26, 2017 6:18 am But the examples from from the wolfsblvt ext you linked to are wrong. You really should only prefix a lang key now with L_ in the template if you need it to be automatically fed through lang(). If you translated the variable in PHP, then it's jusrt another variable and doen't need an L_ prefix.
Sorry, VSE, but I disagree on both of your statements here:
The code in the wolfsblvt extension (that by the way, is mine, and not wolfsblvt's, and it is around two years old) is not wrong, it is meant to be like that: replacing ALREADY EXISTING language keys from the core with new messages. The other way to do it would be, in my opinion, more intrusive and error prone (changing the $lang array on the fly).
And I think that readability of code is VERY important, and using the L_ prefix to signal ANY (language) label is far more important than the insignificant overhead introduce by using the extra lang call (that by the way, it is NOT the same that was already used to process the language). If not, why are we sticking to using the S_ prefix for switches? Same thing here: readability is key, in my opinion, even at the expense of one extra (very simple) function call. I would even go further, and would claim that, with Twig syntax, all labels should be surrounded by lang() calls, regardless of whether they are processed or not, just for readability.
VSE wrote: Fri May 26, 2017 6:18 am
javiexin wrote: Thu May 25, 2017 6:48 pm I assume that for vars named L_* it is checking if a regular var exists with that name, otherwise it strips the L_ and evaluates as a language key. Something like this, or somehow equivalent, would be helpful in maintaining BC.
Any key that starts with L_ in phpBB's template syntax is run through lang() and that's it. If the value matches a lang key then the value is shown, otherwise the key is passed straight through (which is why untranslated keys appear as the key itself on screen).
Yes, but. The lang() function that every L_ var is run through is NOT $user->lang() or $language->lang(), but $template->twig_extension->lang(), (linked above) that does exactly what I described: finds out whether the L_ var exists in the $template->context first, then, if not found there, it calls $user->lang(), that in turn will return the translation, or the key itself if not found.

As I have said many times, thanks a lot, as this type of conversations I think are quite constructive both for the participants and for the readers.
-javiexin

PS: I will start playing around with Twig syntax templates, as I have found several very useful additions to the existing possibilities!

Return to “Extension Writers Discussion”