Process twig variable in a form frontmatter

Hi!

I am not able to process twig variable in a form frontmatter.

My form.md:

process:
  twig: true
frontmatter:
  process_twig: true

But for a fieldset

legend: "{{ page.title }}"

Display raw “{{ page.title }}”

Any thought?

Hmm… not sure @Amatiq but did you also try single quotes around your Twig? That is what I’ve used in the past.

I did but same unprocessed result…

As a test, does this work?

legend: '{{ site.title }}'

Not sure if it is related, but when I was using this feature I discovered the processing occurred before page processing so I could not access page-related items: Processing Twig in Page Frontmatter?

Nope! Same unprocessed result

I already read your previous post and I thought it should still work…

Are your caches off? https://learn.getgrav.org/admin-panel/dashboard/configuration-system

yes! Cache is disabled in the system config file

Sorry to say I am stumped! Maybe someone else here might have an idea of why that is not working?

I thought I had figured it out… But no, I didn’t…

I can get it to work for other frontmatter like:

menu: "{{ page.title|upper }}"

But not in form fields like:

form:
    name: contact
    fields:
        - name: name
          label: "{{ page.title }}"
          ...

Had some deeper look into the matter…

TL;DR: ‘form’ and ‘forms’ fields are ignored by default during Twig processing of frontmatter.

Looking at the Page section in the Configuration docs, I noticed the following setting:

pages:
  ...
  frontmatter:
    process_twig: false
    ignore_fields: ['form','forms']

With the description:

ignore_fields : Fields that might contain Twig variables and should not be processed. Example: ['form','forms']

This, by the way, is the default setting in /system/config/system.yaml.
Now we know why Twig in form fields is not being processed.

When resetting the variable in /user/config/system.yaml to:

pages:
   ignore_fields: []

An error is thrown:

‘Unsupported operand types’.

Digging in the log file, I was lead to Page::processFrontmatter():

    protected function processFrontmatter()
    {
        // Quick check for twig output tags in frontmatter if enabled
        $process_fields = (array)$this->header();
        if (Utils::contains(json_encode(array_values($process_fields)), '{{')) {
            $ignored_fields = [];
            foreach ((array)Grav::instance()['config']->get('system.pages.frontmatter.ignore_fields') as $field) {
                if (isset($process_fields[$field])) {
                    $ignored_fields[$field] = $process_fields[$field];
                    unset($process_fields[$field]);
                }
            }
            $text_header = Grav::instance()['twig']->processString(json_encode($process_fields), ['page' => $this]);
            $this->header((object)(json_decode($text_header, true) + $ignored_fields));
        }
    }
  • Since we have set system.pages.frontmatter.ignore_fields to an empty array, no fields are being ignored.
  • Looking at $text_header it looks like the Twig in a form field has now been processed.
  • But… An error is thown by json_decode().

Needs some further digging, but not now… More on this later…

Some further research…

As said above, when the fields ‘form’ and ‘forms’ are not ignored, an error is thrown by json_decode() after Twig has parsed the frontmatter of form.md.

I was using the form as defined in Example: Contact Form and that form has the following actions defined:

...
process:
    - captcha:
        recaptcha_secret: ENTER_YOUR_CAPTCHA_SECRET_KEY
    - email:
        subject: "[Site Contact Form] {{ form.value.name|e }}"
        body: "{% include 'forms/data.html.twig' %}"        <- Leads to error
    - save:
        fileprefix: contact-
        dateformat: Ymd-His-u
        extension: txt
        body: "{% include 'forms/data.txt.twig' %}"         <- Leads to error
    - message: Thank you for getting in touch!
    - display: thankyou

When Twig is allowed to parse fields ‘form’ and ‘forms’ is also parses the include statements. Apparently the content of these files ruin the string generated by json_encode(). The string $text_header (see previous post) has become invalid json and cannot be converted back into an valid PHP array.

So I guess, there is a good reason why the fields ‘form’ and ‘forms’ are excluded from parsing Twig.

You might be tempted to exlude only the fields ‘body’, but that doesn’t work. Only top-level frontmatter fields are excluded.

Thank you very much for all the dig you did!

I also tried without forms excluded but no luck…

You are right there must be good reasons why Twig in Form frontmatter is disabled.

I will jump into plugin creation, so far I will be able to write my special Form with PHP.

I can understand Grav is not intended to provide a default form plugin able to answer all use cases. That is where Plugins become precious!

Have a nice day, thanks again