Go to main content

Textpattern CMS support forum

You are not logged in. Register | Login | Help

#1 2022-04-26 14:44:12

jakob
Admin
From: Germany
Registered: 2005-01-20
Posts: 4,578
Website

Sorting article groups using if_different, breakby and breakform?

I want to show a series of past events grouped by course title and date. After some experimentation using the breakby and breakform attributes, I’ve got it very nearly working. The events are output grouped by course title, but the order of the course titles is descending.

This is what I have so far:

<txp:article_custom section="events" time="past" category="workshop" 
                    limit="99" sort="UPPER(Title) desc, Posted desc"
                    breakform="events_past_breakform" breakby="<txp:title />">
    <li class="event__item">
        <txp:posted format="%e %B %Y" /> – <txp:expires format="%e %B %Y" /> : <txp:custom_field name="event_location" /> <txp:custom_field name="event_note" escape="textile,p" />
    </li>
</txp:article_custom>

The events_past_breakform breakform:

<txp:if_different>
<div class="event  event--past" id="<txp:php>global $thisarticle; echo stripSpace($thisarticle['title']);</txp:php>">
    <txp:title escape="textile,p" wraptag="h4" class="event__title" />
    <ul class="event__list">
        <+>
    </ul>
</div>
</txp:if_different>

What this does is loop over all past articles ordered first by Title so that if_different only lists the course title once, and then by descending Posted date for the dates that match that course. The breakform is the wrapper around the individual item and contains the if_different tag. The breakby attribute triggers the wrapper only when a new title (from the if_different) occurs.

That works very nicely all in one query and produces this output, which is desired … except for the order of the blocks.

<div class="event  event--past" id="thrilling-event-title">
    <h4 class="event__title">Thrilling Event Title</h4>
    <ul class="event__list">
        <li class="event__item">
            15 February 2019 – 17 February 2019 : Amazing Academy 
        </li>
        <li class="event__item">
            16 November 2018 – 18 November 2018 : Teacher Training Centre 
        </li>
        <li class="event__item">
            7 September 2018 – 9 September 2018 : Amazing Academy 
        </li>
        <li class="event__item">
            9 June 2017 – 11 June 2017 : Weavers Workshop Centre 
        </li>
    </ul>
</div>

<div class="event  event--past" id="exceptional-workshop-name">
    <h4 class="event__title">Exceptional Workshop Name</h4>
    <ul class="event__list">
        <li class="event__item">
            8 June 2020 – 10 June 2020 : Amazing Academy <span>(with guest tutor Joe Bloggs)</span>
        </li>
    </ul>
</div>

…

My problem is that the course blocks are ordered in descending alphabetical order (e.g. “Thrilling” before “Exceptional”) but ideally the most recent course should be at the top of the list (e.g. the one with the date from 2020). How might I tackle this?

(Loose idea: use this approach to build an array of course article ids with sub-arrays for the individual events. Determine a list of course titles in date order and also save as an array – I can do this by looping over the articles and building a list of titles and corresponding ids as variables, skipping any titles already encountered. Then use some php to reorder the first array by the second. Flatten the resulting to array to a list of article id numbers. Plug that into an article_custom tag to produce the final desired output. That’s at least three queries).


TXP Builders – finely-crafted code, design and txp

Offline

#2 2022-04-26 14:51:34

jakob
Admin
From: Germany
Registered: 2005-01-20
Posts: 4,578
Website

Re: Sorting article groups using if_different, breakby and breakform?

One other aside: I had thought we could do <txp:title escape="url_title" /> but it seems I was mistaken (or could not find the right setting). I was probably confusing it in my mind with smd_wrap, which has this option. Is this something we could add?

In the above code, I realized it with:

<txp:php>global $thisarticle; echo stripSpace($thisarticle['title']);</txp:php>

… but it is a bit untidy. I can’t use txp:article_url_title here as each course instance has the date appended to the article_url_title (because txp complains about identical article urls) and that throws out the if_different block.


TXP Builders – finely-crafted code, design and txp

Offline

#3 2022-04-27 09:53:42

jakob
Admin
From: Germany
Registered: 2005-01-20
Posts: 4,578
Website

Re: Sorting article groups using if_different, breakby and breakform?

jakob wrote #333159:

Aside: I had thought we could do <txp:title escape="url_title" /> but it seems I was mistaken …

I’ve submitted escape="url_title" as a suggestion/issue to the GitHub repo, along with corresponding code (tested locally).


TXP Builders – finely-crafted code, design and txp

Offline

#4 2022-05-02 16:35:28

jakob
Admin
From: Germany
Registered: 2005-01-20
Posts: 4,578
Website

Re: Sorting article groups using if_different, breakby and breakform?

jakob wrote #333158:

Loose idea: use this approach to build an array of course article ids with sub-arrays for the individual events. Determine a list of course titles in date order and also save as an array – I can do this by looping over the articles and building a list of titles and corresponding ids as variables, skipping any titles already encountered. Then use some php to reorder the first array by the second. Flatten the resulting to array to a list of article id numbers. Plug that into an article_custom tag to produce the final desired output. That’s at least three queries.

Building on this, I achieved it as follows, but it feels very roundabout and does require three article_custom statements. I’d love to hear if it can be improved on.

Step 1: Loop over all past events by descending date and build a list of event titles = add to variable when encountered for the first time, skip if already seen.

<txp:variable name="event_titles_dateorder"></txp:variable>
<txp:article_custom section="events" time="past" category="workshop" limit="99" sort="Posted desc">
<txp:if_variable name="event_titles_dateorder" value='<txp:title escape="url_title" />' match="any" not>
    <txp:variable name="event_titles_dateorder"><txp:variable name="event_titles_dateorder" /><txp:title escape="url_title" />|</txp:variable>
</txp:if_variable>
</txp:article_custom>

Result 1: variable with |-separated list of dumbed-down (article-url-title style) event titles in the order most-recent to most-past.

event-title|another-event|…

———

Step 2: Loop over past events sorted by title and descending posted date to make a json-style list of events with the articles that belong to them:

<txp:variable name="event_title_ids">{
<txp:article_custom section="events" time="past" category="workshop" limit="99" sort="UPPER(Title) desc, Posted desc" breakform="events_past_json_breakform" breakby="<txp:title />" break=","><txp:article_id />,</txp:article_custom>
}</txp:variable>

and the breakform:

<txp:if_different>
    <txp:title escape="url_title" wraptag='"' />: "<+>"
</txp:if_different>

Result 2: a Textpattern variable with a json string in the format:

{ "another-event": "12,45,48,56," , "event-title": "85,37,23,68," ,  … }

———

Step 3: Make arrays of the two variables in php. Loop over the ordered array, for each event title, find a match in the json-decoded array and append its respective article ids to a variable to successively build up the list of article ids in the new order.

<txp:php>
    global $variable;

    $ordered_events = explode("|", trim($variable['event_titles_dateorder'],"|"));
    $event_ids = json_decode($variable['event_title_ids']);

    $result = "";
    foreach($ordered_events as $event) {
        foreach($event_ids as $key => $val) {
            if ($key == $event) {
                $result = $result . $val;
            }
        }
    }
    $variable['event_past_ids_ordered'] = trim($result,",");
</txp:php>

Result 3: A variable with a list of article ids in the desired order: grouped by event title but with the most recent events at the top of the list.

85,37,23,68,12,45,48,56, …

———

Step 4: Output the desired HTML output using the order of the article ids supplied.

<txp:article_custom id='<txp:variable name="event_past_ids_ordered" />' time="past" limit="99"  breakform="events_past_breakform" breakby="<txp:title />">
            <li class="event__item">
                <txp::event_dates /> : <txp:custom_field name="event_location" /> <txp:custom_field name="event_note" escape="textile,p" />
            </li>
</txp:article_custom>

with breakform as follows:

<txp:if_different>
<div class="event  event--past" id="<txp:title escape="url_title" />-past">
    <txp:title wraptag="h4" class="event__title" />
    <ul class="event__list">
        <+>
    </ul>
</div>
</txp:if_different>

Final result: HTML output of course dates grouped by course title in the order most-recent event to most-past event.


TXP Builders – finely-crafted code, design and txp

Offline

Board footer

Powered by FluxBB