0

Using Grav v1.3.8 (running on PHP 5.6.30), I'm currently getting a Server error ("Illegal offset type in isset or empty") when trying to render a Twig template that is using a macro.

What's interesting is that this only happens when I use the macro by itself. As soon as I append a filter, like trim, everything works as expected.

The (shortened) macro file, helpers.twig:

{% macro ascii(str) %}
{% spaceless %}
    {{ str|replace({
        'Á': 'A',
        'À': 'A',
        'Â': 'A',
        'Ã': 'A',
        ....
        'ƒ': 'f'
      })
    }}
{% endspaceless %}
{% endmacro ascii %}

The template (MCVE):

{% import 'macros/helpers.twig' as helpers %}

{% set img = helpers.ascii('günter-berger.jpg') %}
{% if page.media[img] is defined %}
    <img src="{{ page.media[img].url }}">
{% endif %}

This will produce the error. I narrowed it down to the if line. Apparently, the macro is working fine, but the condition will throw an error if fed the output of it, unfiltered. Adding any filter, like trim or lower, will get it to work again.

In other words, these work:

  • {% if page.media['günter-berger.jpg'] is defined %}
  • {% if page.media[helpers.ascii('günter-berger.jpg')|trim] is defined %}

But this will throw an error:

  • {% if page.media[helpers.ascii('günter-berger.jpg')] is defined %}

However, trying the same thing on twigfiddle, all three seem to work there.
Maybe an issue with Grav? Can someone point out any possible causes?

domsson
  • 4,553
  • 2
  • 22
  • 40
  • It seems the macro is [not](https://twigfiddle.com/ua5gjw) the problem here though – DarkBee Nov 28 '17 at 13:25
  • @DarkBee you're right. Thanks to your hint, I was able to further narrow down the issue. Question has been updated accordingly. – domsson Nov 28 '17 at 14:16

1 Answers1

3

I forgot this, but a macro does not return a string but instead returns an instance of a Twig_Markup

{% set test = macro.ascii('Ghünter.jpg') %}
{{ dump(test) }}

Output : object(Twig_Markup)#10679 (2) { ["content":protected]=> string(11) "Ghunter.jpg" ["charset":protected]=> string(5) "UTF-8" }

Because the return type is an object you get this notification as you can't use objects as index. By using a filter on this instance, the magic method __toString method will be called, causing it to return a string, thus making it useable as index for an array

The only was to bypass this, would be writing a filter instead of a macro

DarkBee
  • 16,592
  • 6
  • 46
  • 58
  • Ha, I suspected something like this! Just a minute ago, I tried casting the result of the macro to string by using the `string` filter and that worked, too. However, this feels a bit brittle - removing the filter in the future will again lead to this error. Is there a better (more stable or elegant) way of going about this? Maybe a way to force a macro to actually return a string? – domsson Nov 28 '17 at 14:34
  • 1
    You can't force a macro to return a string. But you should be able to do sthing like this in grav: ` – DarkBee Nov 28 '17 at 14:41
  • Thank you! Now I understand what caused the issue and how to work around the problem. – domsson Nov 28 '17 at 14:46
  • 1
    An alternate way of getting the macro to return a string is to use the spaceless filter. So for example this: `macro.ascii('Ghünter.jpg')|spaceless` should return a string. – Sten Van den Bergh Aug 06 '19 at 14:43