Go to main content

Textpattern CMS support forum

You are not logged in. Register | Login | Help

#1 2025-04-29 09:08:54

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

Making a public tag in a plugin use the global attributes?

EDIT: decided to split this out into a new topic from the old making plugins 4.7 compatible thread.

etc wrote #306991:

An important new feature of the upcoming txp 4.7 are global attributes. Roughly speaking, any plugin can register one or more attributes that will be valid for any (core or plugin) tag and applied to its output. …

… Some of the commonly used attributes (wraptag, class, etc) have been registered by core, so plugins don’t have to implement them anymore. But if you wish, you can override the core behavior and treat them yourself. For this, it is important to call lAtts() function somewhere inside your plugin:

  • bad way: $wraptag = $atts['wraptag'];
  • good way: extract(lAtts(array('wraptag' => ''), $atts));

This will inform the core that the plugin has its own wraptag attribute, so the global one will not be applied. Fortunately, most plugins adhere to this rule, but if yours starts to wrap its output twice, you know what to do now.

To resume, a public-side plugin:

  • does not need to implement wraptag, class, html_id, atts, label, labeltag and escape attributes if it treats them in the usual way;
  • otherwise, ensure that they are passed through lAtts() filter;
  • if you register a global attribute, don’t give it a txp- prefixed name, they are reserved for core;
  • additionally, parse(EvalElse($thing, $condition)) is deprecated, replace it with parse($thing, $condition).

As part of my attempt to revive another old plugin – this time rss_unlimited_categories (a WIP at the moment) – to smooth the upgrade path to 4.9, I’d like to pass the handling of wraptag, class, break, breakclass, html-id etc. to the global method, but it’s not working quite as envisaged.

The function in question is rss_uc_article_list.

As it currently stands, wraptag and class are applied but not break and breakclass. I’m guessing this has got to do with how the function flattens the $articles array using a join? If I use doWrap(…) it complains about missing variables, if I add those attributes to the list of attributes in $atts, it then works as one would expect, but now the plugin function is doing the work, not the global method. How should I return the $articles array so that the global attributes can do their magic on their own?
I’d like to then apply that principle to other functions in the plugin that currently already use doWrap().

An aside: rss_uc was written a long time ago and replicates quite a bit of the (then) core. Out of curiosity, is there a way to construct an own query and then pass it through parseArticles(…) so that Textpattern does the work of handling pagination, article output, exclusions etc. and rss_uc_article_list only does the constructing of a suitable query?


TXP Builders – finely-crafted code, design and txp

Offline

#2 2025-04-29 10:45:21

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

Re: Making a public tag in a plugin use the global attributes?

Currently, the output of every tag is transformed into string (there are plans to change it in txp5). Hence, if the tag itself does not call doWrap() function before flattening an array, the global break can only be applied if this string is split somehow, typically by the global breakby attribute.

Probably, the easiest way in your case is to register wraptag in the plugin and return doWrap($articles, $wraptag)? Rather oddly, doWrap() does not import the global wraptag atm.

Offline

#3 2025-04-29 10:50:43

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

Re: Making a public tag in a plugin use the global attributes?

Thanks. That means my current modification (not yet online) of adding the attributes to the list at the top of the plugin and adding doLabel and doWrap in the return statement is currently the way to go here?


TXP Builders – finely-crafted code, design and txp

Offline

#4 2025-04-29 11:06:12

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

Re: Making a public tag in a plugin use the global attributes?

I think you only need to add wraptag attribute and return doWrap($articles, $wraptag). The global attributes should be able to handle the rest.

Offline

#5 2025-04-29 11:53:02

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

Re: Making a public tag in a plugin use the global attributes?

Nice, you’re right (of course!). So the $wraptag is really just a placeholder/trigger so that one can use the doWrap function to iterate over the output, allowing the other global attributes to be included along the way?


TXP Builders – finely-crafted code, design and txp

Offline

#6 2025-04-29 12:22:13

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

Re: Making a public tag in a plugin use the global attributes?

jakob wrote #339627:

So the $wraptag is really just a placeholder/trigger for the doWrap function?

Yes and no. It acts as a trigger when processed as global attribute, applied to the output of a tag. But tags output is a string, so you’d need to split it first by the global breakby to be able to apply break etc.

When a tag calls doWrap() itself, $wraptag is.. well, wraptag :-) That’s a little odd that you need to define it in the plugin, it should be possible to return just doWrap($articles), which then would import global attributes. It actually already does it for all of them except wraptag, dunno why. Leave it with me.

Offline

#7 2025-04-29 12:44:06

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

Re: Making a public tag in a plugin use the global attributes?

etc wrote #339628:

That’s a little odd that you need to define it in the plugin, it should be possible to return just doWrap($articles).

Sorry, I’ll clarify that better. Without 'wraptag' => '' in the attribute list, I get a missing $wraptag error with doWrap($articles, $wraptag). If I just do doWrap($articles), the error disappears. In both cases, however, break, breakclass and label, labeltag work but class and html_id do not.

With doWrap($articles, $wraptag) and 'wraptag' => '' in the attribute list, I get correct output.


TXP Builders – finely-crafted code, design and txp

Offline

#8 2025-04-29 15:06:35

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

Re: Making a public tag in a plugin use the global attributes?

Thank you, that’s perfectly clear. I meant that the current state of things is a bit inconvenient since it forces plugin authors to define $wraptag and call doWrap($articles, $wraptag) if they want to benefit from some other global attributes. In a future version (maybe even 4.9) a mere doWrap($articles) will suffice. And in txp5 tags will be able to return an array (without calling doWrap()) and leave the rest with the globals.

Offline

#9 2025-04-29 15:24:47

Bloke
Developer
From: Leeds, UK
Registered: 2006-01-29
Posts: 11,755
Website GitHub

Re: Making a public tag in a plugin use the global attributes?

etc wrote #339634:

In a future version (maybe even 4.9) a mere doWrap($articles) will suffice.

I like the ‘maybe even 4.9’ bit, if it’s doable.


The smd plugin menagerie — for when you need one more gribble of power from Textpattern. Bleeding-edge code available on GitHub.

Txp Builders – finely-crafted code, design and Txp

Offline

#10 2025-04-29 21:32:27

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

Re: Making a public tag in a plugin use the global attributes?

This one looks easy. I have also abused <txp:authors /> as guinea pig, please test.

Offline

#11 2025-04-29 21:56:31

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

Re: Making a public tag in a plugin use the global attributes?

Thanks, that looks good. I’ll give it a go.

In rss_uc, one of the functions (rss_uc_filedunder) has a preset value like break => ', ' between items in a category list. I noticed, I needed to include that attribute and $break in the doWrap function for the default to be used. Just adding the preset break => ', ' attribute was ignored.

Another ‘anomaly’ is that a couple of the rss_uc functions such as rss_uc_list and rss_uc_cloud optionally add a wrapper tag. Previously the label was coded as being within the outer wrapper:

return doTag(
    doLabel($label, $labeltag) .
    doWrap($cats, $wraptag),
    $listwraptag
);

giving you

<section>
    <h4>My label</h4>
    <ul class="my-list">
        <li>…</li>
        …
    </ul>
</section>

but when I switch to using the global method:

return doTag(
    doWrap($cats, $wraptag),
    $listwraptag
);

the label is placed above what the function returns as a whole, not above the doWrap:

<h4>My label</h4>
<section>
    <ul class="my-list">
        <li>…</li>
        …
    </ul>
</section>

The solution seems to be to include the label and labeltag attributes and explicitly include doLabel(…).


TXP Builders – finely-crafted code, design and txp

Offline

#12 2025-04-30 08:45:47

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

Re: Making a public tag in a plugin use the global attributes?

jakob wrote #339639:

In rss_uc, one of the functions (rss_uc_filedunder) has a preset value like break => ', ' between items in a category list. I noticed, I needed to include that attribute and $break in the doWrap function for the default to be used. Just adding the preset break => ', ' attribute was ignored.

This is expected, since global attributes are unset when they are set locally. Otherwise some unpredictable effects (double wrapping etc) might happen.

Another ‘anomaly’ …

is expected too. The typical output of global attributes is

<labeltag>Label</labeltag>
<wraptag class="..." id="...">
    <!-- tags output -->
</wraptag>

Offline

Board footer

Powered by FluxBB