Go to main content

Textpattern CMS support forum

You are not logged in. Register | Login | Help

#1 2018-08-20 08:12:13

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

Problems using if_different in a plugin

I’m attempting to resurrect mka_ical and wanted to add if_first, if_last and if_different functionality. The first two I’ve managed but only by introducing new tags/functions for those as an event list is not an article context, so the existing functions won’t work.

Looking at the code for if_different, it looks as if that code should work in any loop context, but I’m getting mixed success.

mka_ical uses placeholders – {start_date}, {end_date}, {title} etc. – and if I use them in a form with if_different like the following snippet, this works:

<txp:mka_ical url="testfile.ics">
<txp:if_different><h5 class="dt-start">{start_date}</h5></txp:if_different>
<p><span class="dt-end">{start_time}</span> – <span class="p-summary">{title}</span></p>
</txp:mka_ical>

I get just each new date listed and the times on that day listed beneath it without repeating the date.

mka_ical has a format attribute for times but only for everything. I’ve added a simple additional tag to the plugin to make it possible to reformat date output as follows:

function mka_format_date($atts, $thing = '')
{
    extract(lAtts(array(
        'format' => ''
    ), $atts, false));

    if ($format === '') {
        return $thing;
    } else {
        return strftime($format, strtotime($thing));
    }
}

When I use this tag in if_different, for example to show a heading at the beginning of each year (or month), it doesn’t work:

<txp:mka_ical url="testfile.ics">
<txp:if_different><h3><txp:mka_format_date format="%Y">{start_date}</txp:mka_format_date></h3></txp:if_different>
<txp:if_different><h5 class="dt-start">{start_date}</h5></txp:if_different>
<p><span class="dt-end">{start_time}</span> – <span class="p-summary">{title}</span></p>
</txp:mka_ical>

I get a year heading for every new {start_date}.

However, if I first write the result into a variable and then do if_different on the variable, I can trick it into working:

<txp:mka_ical url="testfile.ics">
<txp:variable name="start_year"><txp:mka_format_date format="%Y">{start_date}</txp:mka_format_date></txp:variable>
<txp:if_different><txp:variable name="start_year" wraptag="h3" /></txp:if_different>
<txp:if_different><h5 class="dt-start">{start_date}</h5></txp:if_different>
<p><span class="dt-end">{start_time}</span> – <span class="p-summary">{title}</span></p>
</txp:mka_ical>

What do I need to change in my function to make if_different notice the output of the function, and not the {start_date} item being reformatted?

Or do I need a custom if_different function? And if so, what has to be different?


TXP Builders – finely-crafted code, design and txp

Offline

#2 2018-08-20 15:04:33

etc
Developer
Registered: 2010-11-11
Posts: 5,186
Website GitHub

Re: Problems using if_different in a plugin

Interesting case. The values stored by if_different are indexed by md5 hashes of their unparsed content. So,

<txp:if_different><txp:variable name="start_year" wraptag="h3" /></txp:if_different>

will always use d41d8cd98f00b204e9800998ecf8427e key (i.e. md5('<txp:variable name="start_year" wraptag="h3" />')) to store the last value of <txp:variable name="start_year" wraptag="h3" />. But

<txp:if_different><h3><txp:mka_format_date format="%Y">{start_date}</txp:mka_format_date></h3></txp:if_different>

will use a new key as soon as {start_date} is changed, so a new value of <h3><txp:mka_format_date format="%Y">{start_date}</txp:mka_format_date></h3> will not be compared with a previous one (unless dates are identical).

Dunno what is the best way to fix it. An easy one is to introduce some id (or key or hash) attribute to <txp:if_different />.

Offline

#3 2018-08-20 21:20:07

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

Re: Problems using if_different in a plugin

Thanks for the feedback Oleg. That was my conclusion too, though I wasn’t sure of the reason. For the moment I’m using the txp:variable workaround which works, but it’s not really a good solution. It would be much better if the plugin responded as one would expect it to.

Could I :

a) make a separate mka_if_different tag that adds that extra hash/id attribute. Could you fill me in with what that’s supposed to do?

b) Currently I’ve kept the {placeholder} items so as not to move too far away from the existing plugin. One could create a tag to output the items much like txp:image_info does for images but it breaks backwards compatibility. An own tag would almost certainly then work with if_different, no?

At present, the {placeholders} correspond more-or-less directly to the items in the ical feed/functions in the ical parser library with just {start_date} / {start_time} and the end equivalents being put through a date formatter which uses the tag’s fmtdate and fmttime attributes (which is global for an entire calendar). That was all in the plugin already. I added {start_datetime} and {end_datetime} with fixed formatting for use with the html datetime attribute as that has to have a predefined format even if dates are displayed differently to visitors. They serve a common need/scenario. I guess one could create {start_year}, {start_month}, {start_day} etc. placeholders, so that if_different acts on a preformatted item but it quickly gets long-winded as you try to cover ever more situations, so it’s not particularly elegant. I wonder whether the might be a way to incorporate date formatting directly into the placeholder item (that is hashed by if_different), but I’m not sure how?


TXP Builders – finely-crafted code, design and txp

Offline

#4 2018-08-21 17:10:53

etc
Developer
Registered: 2010-11-11
Posts: 5,186
Website GitHub

Re: Problems using if_different in a plugin

jakob wrote #313545:

Could I :

a) make a separate mka_if_different tag that adds that extra hash/id attribute. Could you fill me in with what that’s supposed to do?

function mka_if_different($atts, $thing)
{
    static $last = array();

    extract(lAtts(array('key' => md5($thing)), $atts));
//    $key = md5($thing);
    $out = parse($thing, 1);

    if (empty($last[$key]) || $out != $last[$key]) {
        return $last[$key] = $out;
    } else {
        return parse($thing, 0);
    }
}

You then can fix a key of the last array that will be used for comparison:

<txp:mka_if_different key="start_date">
<h3><txp:mka_format_date format="%Y">{start_date}</txp:mka_format_date></h3>
</txp:mka_if_different>

b) Currently I’ve kept the {placeholder} items so as not to move too far away from the existing plugin. One could create a tag to output the items much like txp:image_info does for images but it breaks backwards compatibility. An own tag would almost certainly then work with if_different, no?

If this new tag is processed in the normal flow (from outside to inside), then yes. The problem with placeholders is that they are filled before the surrounding tags are parsed.

Offline

#5 2018-08-21 17:24:39

etc
Developer
Registered: 2010-11-11
Posts: 5,186
Website GitHub

Re: Problems using if_different in a plugin

Just for the record, in

<txp:if_different>
<txp:php>echo 2*2;</txp:php>
</txp:if_different>

<txp:if_different>
<txp:php>echo 2*2;</txp:php>
</txp:if_different>

only the first tag will output 4. But

<txp:if_different>
<txp:php>echo 2*2;</txp:php>
</txp:if_different>

<txp:if_different>
<txp:php>echo 2+2;</txp:php>
</txp:if_different>

will both output 4, even if the results are identical.

Offline

#6 2018-08-21 22:31:52

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

Re: Problems using if_different in a plugin

Thanks Oleg. That does it.

I understand from your example, that it’s hashing the method and not the output. I’ll experiment some more but I think I have it working now.


TXP Builders – finely-crafted code, design and txp

Offline

Board footer

Powered by FluxBB