Use a function php/twig [with PLUGIN] in a page-collection

Hello. After a lot of research, I ask for your help.

I have a collection() in a template page (category.html.twig). No problem.
With a for each loop, i can get all pages with differents templates (‘article, breve’).

{% for p in default_collection %}
  {% if p.template == 'breve' %}
   {% include 'partials/category/cat-content-breve.html.twig' %}
  {% elseif p.template == 'article' %}
    {% include 'partials/category/cat-content-article.html.twig' %}
  {% endif %}
{% endfor %}

For each item in this loop, i use a button ‘read-more’ with a link to the (article or breve)
I know, i can make a include to call this button for each template.

<a href="{{ p.url }}" class="btn-read-more" title="{{ p.title }}">
  {% include('@images/icones/fa_plus.svg') %}
</a>

But is it possible to make a php function to create this button ?
I tried to create a plugin for this. No problem.

After i create a twig function : {{ button_RM() }} in the differents templates ( ex: article.html.twig).

The problem : I can get the page.url (the url of page category);
But how to take the page.url of each item ? (‘article’ or ‘breve’) ?
I don’t understand why my function return the “parent page” url and not the “child page” url.
Do I need, a new loop for this ?
My function {{ button_RM() }} is called in a for each loop.
Why doesn’t she “just” return the url of the page (‘article’ or ‘breve’) where she is called ?

public function onPagesInitialized() {
  $button_read_more = new \Twig_SimpleFunction('button_RM', function () {
     
  $page = $this->grav['page'];
  $page_title = $page->title();
  $page_url = $page->url();

  $btn_rm = '<a href="' . $page_url . '">';
  $btn_rm .= 'Read more';
  $btn_rm .= '</a>';

  return $btn_rm;
});

  $this->grav['twig']->twig->addFunction($button_read_more);
  // And use it in Twig with {{ button_RM() }}
}

@BKaernel,

  • $this->grav['page']; contains the current page, which is the page that is looping the collection.
  • You will need to pass page (p) inside the loop into the Twig function
    • Update the function definition:
      $button_read_more = new TwigFunction('button_RM', function (Page $page) { ... } );
      
    • Note: Twig_SimpleFunction has been deprecated.
    • In Twig pass the current page inside the loop (p) into the function using {{ button_RM(p) | raw }}.
      You need the |raw filter to prevent the <a> element returned from the function from being escaped.

Hint: Use $btn_rm = "<a href=\"$page_url\">Read more</a>"; for creating the anchor element…

1 Like

Thank you for your answer ! It’s very clear - I will try…

I was looking at the hook onCollectionProcessed (that you already told me about) but your solution seems more easy for me.

My intention with this is to create multiples functions to add class (for example) in template or modular.