Forum

Thread tagged as: Question

Conditionally output "Read more" depending on word count

Hello,

Is it possible to conditionally output something based on the word count of the field?

For example, on a "list" page I am outputting a truncated bio of a profile like this:

<perch:content id="biography" words="42" append=" &hellip;"/>

This is fine, but I would like to add a "read more" link only if the word count is over the limit of 42. For instance, like this:

<perch:content id="biography" words="42" append=" <a href="/some-page/<perch:content id="slug" type="slug" />">View Full Profile</a>"/>

Obviously the above does not work because it's outputting as a string, but it demos what I would like to happen.

Is something like this possible?

Jay George

Jay George 2 points

  • 4 years ago
Drew McLellan

Drew McLellan 2638 points
Perch Support

I think you'd to write a template filter to do that.

Thanks, I have it working except I'm not sure how to wrap a link from the HTML template around the "read more" text. Is this possible?

So this is the template filter working, without the link, in filters.php

<?php
class PerchTemplateFilter_read_more extends PerchTemplateFilter 
{
    public function filterBeforeProcessing($value, $valueIsMarkup = false)
    {

        $number_of_words_in_value = str_word_count($value);

        $max_words = 40;

        /* Source: https://css-tricks.com/snippets/php/truncate-string-by-words/ */
        $phrase_array = explode(' ',$value);
        if(count($phrase_array) > $max_words && $max_words > 0);
        $value = implode(' ',array_slice($phrase_array, 0, $max_words));

        if($number_of_words_in_value > 40) {
            $value = $value . "… read more";
        }

        return ($value);
    }
}
PerchSystem::register_template_filter('read-more', 'PerchTemplateFilter_read_more');

And I want it to do something like this (but this obviously doesn't work)…

<?php
class PerchTemplateFilter_read_more extends PerchTemplateFilter 
{
    public function filterBeforeProcessing($value, $valueIsMarkup = false)
    {

        $number_of_words_in_value = str_word_count($value);

        $max_words = 40;

        /* Source: https://css-tricks.com/snippets/php/truncate-string-by-words/ */
        $phrase_array = explode(' ',$value);
        if(count($phrase_array) > $max_words && $max_words > 0);
        $value = implode(' ',array_slice($phrase_array, 0, $max_words));

        if($number_of_words_in_value > 40) {
            $value = $value . "<a href='somepage.php?search=<perch:content id='slug' type='slug' />'>" . "… read more" . "</a>";
        }

        return ($value);
    }
}
PerchSystem::register_template_filter('read-more', 'PerchTemplateFilter_read_more');

Whoops, found the instruction "Accessing the template tag" in the documentation.

I now have it working except the the output does not seem to be returning as markup, despite setting this to "true". So it's now outputting rather literally as sometext here <a href="somelink">…read more</a> rather than actually outputting the anchor markup. I'll keep working on this and post a solution once I crack it.

<?php
class PerchTemplateFilter_read_more extends PerchTemplateFilter 
{
    public function filterBeforeProcessing($value, $valueIsMarkup = true)
    {

        $number_of_words_in_value = str_word_count($value);

        $max_words = 40;

        /* Source: https://css-tricks.com/snippets/php/truncate-string-by-words/ */
        $phrase_array = explode(' ',$value);
        if(count($phrase_array) > $max_words && $max_words > 0);
        $value = implode(' ',array_slice($phrase_array, 0, $max_words));

        if($number_of_words_in_value > 40) {
            $value = $value . ' <a href="somepage.php?search=' .$this->content['slug'] . '">' . '… read more' . '</a>';
        }

        return ($value);
    }
}
PerchSystem::register_template_filter('read-more', 'PerchTemplateFilter_read_more');

You should set mark up to true like this

public $returns_markup = true;

Thanks Dexter, I've set that variable but it doesn't help (see below).

I'm also confused at why this variable exists alongside the $valueIsMarkup variable inside public function filterBeforeProcessing($value, $valueIsMarkup = false)

<?php
class PerchTemplateFilter_read_more extends PerchTemplateFilter 
{
    public function filterBeforeProcessing($value, $valueIsMarkup = false)
    {

        $number_of_words_in_value = str_word_count($value);

        $max_words = 40;

        /* Source: https://css-tricks.com/snippets/php/truncate-string-by-words/ */
        $phrase_array = explode(' ',$value);
        if(count($phrase_array) > $max_words && $max_words > 0);
        $value = implode(' ',array_slice($phrase_array, 0, $max_words));

        if($number_of_words_in_value > 40) {
            $value = $value . ' <a href="/searchpage.php?=' .$this->content['slug'] . '">' . '… read more' . '</a>';
        }

        $returns_markup = true;

        return ($value);
    }
}
PerchSystem::register_template_filter('read-more', 'PerchTemplateFilter_read_more');

Hi Jay you'd do it like so: (This works for me anyway)

class PerchTemplateFilter_xxx extends PerchTemplateFilter {
  public $returns_markup = true;
  public function filterBeforeProcessing($value, $valueisMarkUp = false) {

 }
}

PerchSystem::register_template_filter('xxx', 'PerchTemplateFilter_xxx');

That's awesome. Works for me too. Thanks so much!