Plugin bundles: how to implement them

Maybe this can be managed somehow through the code, by really registering the “submodules” like routes:

kirby()->modules()->register('field', 'path/to/field/folder');
kirby()->modules()->register('blueprint', 'path/to/blueprint/file');
kirby()->modules()->register('snippet', 'path/to/snippet/file');

This way, the developer has to add/register the submodules actively, not just by including the right folders. Those modules can be so complex (and as far as I think they will be complex, in contrast to neat little plugins with one or two files), that there should be a recommended, but no forcing structure.

This way, we also have a great way to separate between different complexities of plugins.

6 Likes

Great idea! My favorite solution so far. This would also solve the issue of a separate directory. Old plugins will continue to work as before and new ones can register their stuff on their own so they can live in the plugins directory as well.

4 Likes

Didn’t think of this one in the first row, but yes, with this structure we could even keep everything in the plugins folder. Perfect! Let’s do that :wink:

2 Likes

I also like modules as name :smiley:

Another thing which came to my mind if we’d use this kind of registering submodules: we could define custom names for it:

// Use default field name
kirby()->modules()->register('field', '/path/to/field/folder');
// Give people the chance to change field name
kirby()->modules()->register('field', '/path/to/field/folder', c::get('myplugin.fields.myfieldname', 'myfieldname'));

The idea is to bundle a module, but maybe the developer who uses the bundle already has a field using this name. With this syntax (second line) the user could also define an own name for the field.

As I am not as experienced with the Kirby core as the other guys here – I guess this would mean rewriting a lot? Don’t really know how our “submodules” (plugins/snippets/blueprints) are loaded at the moment. Maybe @bastianallgeier can give us his opinion on this topic? This would be a huge step, so it should be well planned.

Edit: Oh, and of course my syntax is just a quick’n’dirty mockup, there should be an even simpler approach :wink:

Just tried to start working on an implementation (Not hoping yet that this would also result in a working PR tho)…

And it is quite tricky. Not registering, but actually calling the right stuff at the right time. For example: Calling a snippet has been a pretty simple forward thing so far:

snippet($path)

Kirby looks if it can load anything from site/snippets that matches $path.php. If we now register multiple destinations, where do we look first? What if the same files exist in different snippet source locations?

I’d say that the main directories (site/snippets) and so on are always checked first so that users can override the plugin. If the file does not exist, Kirby would check all registered snippet files from plugins.

2 Likes

That sounds logical. So this works already :wink:

1 Like

Awesome!

So that registers all files in the given directory?

Exactly, you basically register another folder where Kirby will look for the snippet file if it cannot find any in site/snippets/. Work in progress: https://github.com/getkirby/kirby/compare/develop...distantnative:feature/bundling

3 Likes

The implementation is really great and simple. So this feature doesn’t even add much complexity to the core.

Panel-side is much harder, having static methods like blueprint:all() which seem to manifest before a plugin can register any additional blueprints folder :confused:

Hm, that sounds a bit complicated to fix. :confused:

It’s mainly hard to find: Panel seems to call blueprint::all() twice on pretty much every page load. If I do a var_dump inside of it, first call return null for kirby()->modules()->blueprints() while the second one actually includes the registered directory. So I’m trying to hunt down when/where that first call to blueprint::all() is made.

So far I got working:

  • Templates
  • Snippets
  • Tags
  • Panel Fields

Making troubles:

  • Blueprints

What else should be “bundle-able”? I was thinking about assets, but has anyone an idea for a smooth, logical… Kirby-like way?

1 Like

Assets can already be exported using routes. But maybe we could create a shortcut for that.

Other components:

  • Controllers
  • Models
  • autocss/autojs (these are assets, so this depends on how we export assets)
  • Widgets
  • Languages (they would not override the languages dir but be loaded before loading the one in site to allow users to override single language variables)

I think this should be everything.

1 Like

Alright, there are PRs as WIP for everything except assets (which you are right, are a little special) – and blueprints, which keep bugging me. If some of you feel confident enough to test it (with stuff that really is just for testing), I’d appreciate any feedback, comments etc.

Finally got hold of blueprints and it seems to be working. So only assets/autocss/autojs, but lets see if/what Bastian says about it. Also a lot of testing I guess.

1 Like

So for autocss and autojs I think we could also just register folders where Kirby look for a file with the template name.

And for other assets maybe something like

kirby()->modules()->asset(__DIR__ . DS . 'assets' . DS . 'css' . 'plugin.css', 'assets/myPlugin/plugin.css')

Which would create the necessary route, so that e.g. in site/snippets/header.php this could be added:

<?= css('assets/myPlugin/plugin.css') ?>

Or maybe not for individual files but

kirby()->modules()->asset(__DIR__ . DS . 'assets' . DS . 'css', 'assets/myPlugin/css')

Thoughts?

Looks good. I would prefer the “whole directory” (also with subdirectories!) approach however to be consistent with the other methods.

Concerning autocss/autojs: Yes, sounds great. But it would need to register a route again internally so that the files can actually be accessed.