Process twig variable in a form frontmatter


#1

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?


#2

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


#3

I did but same unprocessed result…


#4

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?


#5

Nope! Same unprocessed result

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


#6

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


#7

yes! Cache is disabled in the system config file


#8

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


#9

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 }}"
          ...

#10

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…


#11

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.


#12

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