Go to main content

Textpattern CMS support forum

You are not logged in. Register | Login | Help

#1 2014-11-16 18:42:37

ruud
Developer Emeritus
From: a galaxy far far away
Registered: 2006-06-04
Posts: 5,068
Website

Making plugins first-class citizens

Wouldn’t it be nice if instead of writing code like this:

<txp:zem_contact to="me@example.com">
  <txp:zem_contact_email />
  <txp:zem_contact_textarea />
  <txp:zem_contact_submit />
</txp_zem_contact>

… we could simply write this:

<zem:contact to="me@example.com">
  <zem:contact_email />
  <zem:contact_textarea />
  <zem:contact_submit />
</zem:contact>

As it turns out, that only requires a minor modification to the parser: patch for txp4.6-dev
The patch assumes that every plugin developer uses a 3 character plugin prefix, which they should if they follow the guidelines. The patch doesn’t force people to use the new notation; it just offers it as an alternative.

edit:
3 letter prefix patch (updated with fixes for splat and EvalElse)
3 char prefix patch
2-3 char prefix patch

Offline

#2 2014-11-16 21:35:56

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

Re: Making plugins first-class citizens

That would be nice, indeed, but could clash with importing namespaced xml documents. And I think you need to do a minor change in splat() function too, unless I’ve overlooked it in your patch (sorry then).

Offline

#3 2014-11-16 22:00:40

gomedia
Plugin Author
Registered: 2008-06-01
Posts: 1,373

Re: Making plugins first-class citizens

ruud wrote #285799:

Wouldn’t it be nice if instead of writing code like this … we could simply write this …

Yes it would! Any modifications to plugin code required?

And in the interest of forum post interlinking: here’s one that dreamt of a bright new future, including namespaces and tag registering.

Offline

#4 2014-11-17 04:42:40

wet
Developer Emeritus
From: Schoerfling, Austria
Registered: 2005-06-06
Posts: 3,323
Website Mastodon

Re: Making plugins first-class citizens

This looks nice. What would happen if a plugin author chose a prefix with a different length?

Offline

#5 2014-11-17 13:51:55

ruud
Developer Emeritus
From: a galaxy far far away
Registered: 2006-06-04
Posts: 5,068
Website

Re: Making plugins first-class citizens

etc wrote #285804:

That would be nice, indeed, but could clash with importing namespaced xml documents.

It’s not really different from TXP tags, so those would then potentially clash with XML documents as well, I think.

And I think you need to do a minor change in splat() function too, unless I’ve overlooked it in your patch (sorry then).

splat() gets the string of attributes as input, not the tagname itself.

gomedia wrote #285807:

Yes it would! Any modifications to plugin code required?

None at all.

wet wrote #285809:

This looks nice. What would happen if a plugin author chose a prefix with a different length?

With the patch I provided, <long:tag> and <i:m to=“short”> would not be recognized as tags. Those would have to be written as <txp:long_tag> and <txp:i_m to=“short”>
However, it’s easy to rewrite the patch to support variable length prefixes. I chose a fixed width of 3 chars, because that’s what our plugin guidelines specify. Actually, the guidelines specify 3 letters, which is even more specific.

Looking at the currently registered plugin prefixes:
  • 290 three letter prefixes
  • 4 two letter prefixes (it, ja, jk, vg)
  • 4 three character prefixes (an7, e26, ob1,r11)

One could argue that allowing 2-char prefixes gives an unfair advantage, because shorter tends to be more popular.
I’ll update the first post with new patches for strict 3 letter, 3 character, 2-3 character prefixes. The latter can be changed to longer prefixes by changing 2 characters in the patch.

Offline

#6 2014-11-17 13:52:12

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

Re: Making plugins first-class citizens

Very cool. And backwards compatible too, as it’s just an extension for permitting simpler syntax (so no plugin changes required). Reinforcing the three-character prefix in order to take advantage of this feature is a reasonable restriction/convention and actually makes the case for proper prefixing stronger, because plugin authors will surely want their user base to do less typing to work with their public-side plugins :-)

Haven’t tested it yet, but it does look as though etc is right: splat() may need changing to parse and display attributes from first-class plugins in the tag trace. The trick is to do this efficiently, since it’s called a lot.

Regarding the XML import, it shouldn’t be a problem as tags need registering prior to execution to avoid throwing the warning and (ultimately, one day) failing outright. So unless the XML document is handled by a plugin that auto-registers namespaced tags within Textpattern, we should be covered. Ummm, I think…

I’m all for this. And I’d love to see some stuff in the parser like Gocom mentioned in the post to which gomedia linked. I was trying to find that post the other day and failed, thanks!


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

#7 2014-11-17 14:24:27

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

Re: Making plugins first-class citizens

ruud wrote #285833:

It’s not really different from TXP tags, so those would then potentially clash with XML documents as well, I think.

Sure, but every new prefix results in the clash probability increase. Suppose that you need to export some articles as Excel sheet, which includes plenty of <mso:tags />, then using any mso_plugin would be problematic.

splat() gets the string of attributes as input, not the tagname itself.

I mean this:

if (strpos($m[3], '<txp:') !== FALSE)
{
    trace_add("[attribute '".$m[1]."']");
    $val = parse($val);
    trace_add("[/attribute]");
}

It’s not only trace_add(), but parse().

Edit: EvalElse() probably needs to be modified too.

Last edited by etc (2014-11-17 14:43:30)

Offline

#8 2014-11-17 14:36:08

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

Re: Making plugins first-class citizens

Bloke wrote #285834:

The trick is to do this efficiently, since it’s called a lot.

I’ve made some modifications in parse() (running in the wild here) to cache the results of preg_split. The modified parser itself is much faster, but the overall performance is just a little better, because most of runtime is taken by db calls / udfs. It’s still worth implementing, at the risk of sha1 collision (but then it will be the first known one :).

Offline

#9 2014-11-17 15:59:31

ruud
Developer Emeritus
From: a galaxy far far away
Registered: 2006-06-04
Posts: 5,068
Website

Re: Making plugins first-class citizens

New patch (see opening post) with fixes for splat and EvalElse.

Offline

#10 2014-11-17 16:24:06

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

Re: Making plugins first-class citizens

Superb, thanks. Hadn’t considered EvalElse() but from reading the patch, it seems to allow lovely constructs like:

<smd:if ...>
   Yay :-)
<smd:else />
   Nay :-(
</smd:if>

effectively retrofitting every plugin with a personal else tag. If that’s true (is it?), it’ll make multiple nested conditional pages easier to follow, because you can marry else tags up with a plugin’s opening / closing tags by prefix. Brilliant. Of course there’s every chance I’ve misinterpreted the patch out of context with the source itself.

Will test this when I get a chance.


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

#11 2014-11-17 18:15:00

ruud
Developer Emeritus
From: a galaxy far far away
Registered: 2006-06-04
Posts: 5,068
Website

Re: Making plugins first-class citizens

Bloke wrote #285840:

Superb, thanks. Hadn’t considered EvalElse() but from reading the patch, it seems to allow lovely constructs like: […] effectively retrofitting every plugin with a personal else tag.

Hmm… to do that you’d have to replace

$els = strpos($thing, '<txp:else');

with something monstrous like (not tested):

for ($pos = 3, $len = strlen($thing); $pos < $len and false !== $pos = strpos($thing, ':else', $pos+1);)
{
  if ($thing[$pos - 4] != '<') continue;
  for ($i = $pos - 3; $i < $pos; $i++) if (ord($thing[$i]) < 97 or ord($thing[$i]) > 122) continue 2;
  $len = true;
}
$pos = $len ? $pos : $false;

but if we’re not desperately trying to avoid preg_match, you could replace:

$els = strpos($thing, '<txp:else');

if ($els === false) {
    // no <txp:else /> tag
    if ($condition) { 
        return $thing;
    }

    return '';
} elseif ($els === strpos($thing, '<') or $els + 4 === strpos($thing, ':') or !preg_match('/<[a-z]{3}:/', substr($thing, 0, $els))) {
    // no TXP tag before the <txp:else /> tag
    if ($condition) {
        return substr($thing, 0, $els);
    }

    return substr($thing, strpos($thing, '>', $els) + 1);
}

with (also not tested):

if (false === $els = strpos($thing, ':else', 4) or !preg_match('/<[a-z]{3}:(\w+)/', $thing, $matches)) {
    // no <txp:else /> tag
    if ($condition) {
        return $thing;
    } else {
        return '';
    }
} elseif ($matches[1] === 'else') {
    // <txp:else /> is the first tag in $thing
    if ($condition) {
         return substr($thing, 0, $els - 4);
    } else {
         return substr($thing, strpos($thing, '>', $els) + 1);
    }
}

Keep in mind, that this part of the code is just speed optimisation. If someone passes <txp:title /> :else that ideally would trigger the “no <txp:else />” condition, but failing to do so doesn’t break EvalElse. It just makes it a bit slower. Realistically, that is not a situation that will occur a lot. If $thing contains :else, then it’s very likely that it’s part of a TXP tag.

Offline

#12 2014-11-17 19:46:56

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

Re: Making plugins first-class citizens

No worries if it doesn’t do that. I just read the code wrong in haste. Speed of parsing is my main concern rather than the bonus of a mega else tag so the original patch with the EvalElse fixes is just fine at the mo. Thanks for your hard work.


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

Board footer

Powered by FluxBB