thunderer/Shortcode

Parsing wildcard tag like [banner-*]

Closed this issue · 4 comments

Hi there!

I have a 300+ documents having a set of shortcodes like [banner-top], [banner-bottom] and so on. I do not know the full set of these shortcodes but I know the naming convention [banner-*] where * is fitting [a-z-_] regex. All I need is to register them in DB and replace with another shortcode like [banner type="top"].

Is it possible to define one handler for whole set of these shortcodes without collecting them manually before actual processing with your lib?

Hi @spotman! Thanks for reporting the issue, what you are trying to achieve can be seen as two problems:

  • actually parsing shortcode wildcards, ie. matching shortcodes with certain wildcards with the single handler (register [banner-*], have all [banner-top], [banner-bottom_left] shortcodes passed to that single handler),
  • handling wildcard shortcode just like any other one, just falling back to default handler to dispatch it manually or handle inside.

Actually parsing wildcards is an interesting idea I will put into #16. I will need to find a way to make it work without changing shortcode syntax. As for the default handler, I prepared an example for you below - it works by catching all unhandled shortcodes and replacing them out manually. Note that I used TextSerializer instead of returning raw string because it automatically produces proper self-closed and with-content shortcode, but it is not mandatory. Please let me know what do you think and whether it solves your problem.

$handlers = new HandlerContainer();
$handlers->setDefault(function(ShortcodeInterface $s) {
    if(preg_match('~^banner-([a-zA-Z0-9_]+)$~', $s->getName(), $matches)) {
        $serializer = new TextSerializer();
        $new = new Shortcode('banner', ['type' => $matches[1]], $s->getContent());

        return $serializer->serialize($new);
    }
});
$processor = new Processor(new RegularParser(), $handlers);

assert('[banner type=top /]' === $processor->process('[banner-top]'));
assert('[banner type=top]content[/banner]' === $processor->process('[banner-top]content[/banner-top]'));
assert('[banner type=top_left /]' === $processor->process('[banner-top_left]'));

@thunderer Thank you for quick and detailed answer! I've tested it and this approach is OK for me coz all other shortcodes are fully described. You may close this issue (or keep it as doc, up to you).

I'm happy that it solved your problem, I will probably update README with this example. You gave me an interesting idea to think about, thanks!

I'm glad to help you :)