Safe way to make changes in Grav Common

Is there a safe way to make a change to code in a core Grav Module, so it won’t be overridden next time I update grav?

A case in point right now is that the page summary hard truncates at the summary size set in the Admin panel with ellipsis. I would rather that it truncated on word boundary. A quick look through the code reveals that the summary is generated in

/system/src/Grav/Common/Page/Page.php

on line 712 which says

$summary = Utils::truncateHtml($content, $size);

It is easy to change this to

$summary = Utils::safeTruncateHtml($content, $size);

which gives the desired result but is this the right thing to do?

I did a grep on safeTruncateHtml and it appears to be defined, but unused in my installation

Maybe a plugin with onPageInitialized, where you can do whatever you want with the page?

@Slartibartfast, According the docs, you could also use the function in Twig using Grav’s Twig filter |safe_truncate_html.

Having said that… Changes created using a plugin will (might) be cached, while changes created in Twig will not be cached.

2 Likes

Thank you both

I will check those out

I will check those out

It has been 7 days… Any progress you would like to share with the community?

Actually got stuck in a whole ‘nother set of config and forgot to add my unsafe little tweak in the core to the to-do list, so thanks for the reminder.

Yes, the twig filter does what it says on the tin, and so solves the specific use case.

For the record

{% if truncate and page.header.excludeSummary %}
  <div class="p-summary e-content">
    {{ page.summary|raw }}
    <p><a href="{{ page.url }}">{{ 'BLOG.ITEM.CONTINUE_READING'|t }}</a></p>
  </div>
{% elseif truncate %}
  <div class="p-summary e-content">
    {{ page.content|safe_truncate_html|raw }}
    <p><a href="{{ page.url }}">{{ 'BLOG.ITEM.CONTINUE_READING'|t }}</a></p>
  </div>
{% else %}
  <div class="e-content">
    {% if page.header.excludeSummary %}
      {{ page.content|slice(page.summary|length)|raw }}
    {% else %}
      {{ page.content|raw }}
    {% endif %}
  </div>        
  {% set show_prev_next = true %}
{% endif %}

where page.header.exclude summary is a variable I added to the defaults.yaml blueprint so that posts could have a teaser summary, different from the body content.

I’m assuming that the broader question of how best to change core code the answer is probably “don’t”, but it does look like plugins are the easiest solution. I’m used to an environment where the norm was inherit and override

I think the answer is more like “you’re probably doing it wrong” and you likely realise now that a better title would have addressed the specific question rather than gone broader. But these are easy beginner fumbles!

You gotta be careful with your words around here :wink: I think that is the norm.

1 Like

As the others suggest, the safest and most resilient way is utilizing a plugin to add rather than change functionality. That doesn’t, however, mean it cannot be done. Grav is a package that follows PSR-4 in autoloading dependencies. That also means you can override classes like you normally would with a library loaded through Composer, fairly straightforwardly through the psr-4 and/or files properties.

For the specific use-case your theme or plugin could more easily supply a different Twig function or filter to do the truncation. Many themes and plugins does this, and there’s a dedicated entry in the cookbook for how: Custom Twig Filter/Function.

1 Like

Thanks. I’ll do some more reading!