GREYSimplification of our current tag library. See MAGNOLIA-2993@jiraGREY
The current tag library has a few shortcomings. It is outdated, too complex to use and to maintain. New concepts have been introduced at higher levels to solve similar problems.
- it has complex inheritance logic, which can now be enabled by
InheritanceContentWrapper; this is for instance used with
STKUtil, templating models, ...
- legacy code for support of nested paragraphs, which is not needed anymore.
- it is only a tag library, so it's not useable outside the context of JSP templates. We're "lucky" that FreeMarker provides support for taglibs; support for other templating engines would require duplicating everything that's in those tags)
- the templating module now provides a set of objects (content, mgnl(MagnoliaTemplatingUtilities), ctx, ...) to templates.
- the templating module now supports model classes, thus giving the ability to move complex logic out of the templates.
We need to provide solutions for this; we will most likely deprecate a bunch of the existing tags in favor of new ones.
- Whatever we introduce should still make some sense with Magnolia 5 (underlying implementations will be changed/swapped, but the templates should ideally be 1:1 compatible)
- Easier support for other templating engines than JSP tags;
- Hide underlying complexity: provide a sensible, simple API, with "good defaults"; can be wrapped for Freemarker, JSP tags or any other kind of templating engine.
- Extensibility: Corner cases that are currently possible to reach, by accident or not, will probably be not supported. On the other hand, it should be easy to extend/replace/add functionality such that such corner cases can provided for on a case-by-case basis.
- Deprecate current tags, at least those we provide a direct replacement for.
- Lastly, we should have a look at the (generated documentation). We currently have 2 different formats that document the taglib; neither is great. We should stick to a single one, and improve it. (for ex: http://dev.magnolia-cms.com/ref/latest/magnolia-taglib-cms/tagreference.html has some html tags in the attributes' description which should not have been encoded)
Our primary target are the button, editBar, editButton, mainBar and newBar tags. A second close might focus on the
includeTemplate usecases, although that might end up in a different location.
We should provide good, sensible, default behaviours. Simple buttons/actions, and the ability to customize/expose new buttons/bars easily, rather than try to cover each and every corner case like our current taglib does.
Rendering, currently done via the use of the magnolia-gui components, could be swapped at a later time to use FreeMarker, but this is independent from the templating language with which these tags/bars/buttons are used. If we want to do rendering of the components via templates, we'll need to expose something similar to the rendering models, to expose methods like "isAuthorized" etc.
Some tags (adminOnly, publicOnly, ...) are redundant with facilities provided by MagnoliaTemplatingUtilities.
Other tags, like ifEmpty, etc, can also be avoided by using EL/jstl (which was not supported in earlier, JSP1.x-based, versions of Magnolia).
Some tags are still useful in the context of JSP (not so much in FreeMarker; for other templating engines, they may or may not be, but are generally simple enough to be reimplemented)
Such tags could/should be kept around, but simplified, too. There's a whole lot of legacy in there that we could get rid of.
Subclasses of BaseContentTag are the most "complex" one because they rely on the complex inheritance patterns provided by getFirstMatchingNode() and resolveNode() - which use different parameters and combinations thereof.
Cms:out and cms:include are also quite complex, and could most likely be simplified. The latter's behaviour is already in part reproduced with
Some other tags should be replaced/reimplemented/split away:
- cms:links (html head tags for js and css)
- set, setNode, user, loadPage, ...
In any case: we could already:
- Split, at least packages. Separate concerns.
- Some renaming might help clarifying too.
- We could do this without a deprecation phase, since the tags classes are not a public API. (i.e. the API is the TLD, which would not change)
- Provide examples for replacements of
IsEmptyand similar tags.
For the 5 tags above (button, editBar, editButton, mainBar and newBar), we can simply see 2 concepts: bars and buttons; or containers and items.
The rendering, or output, of these is mostly irrelevant for this issue; for 4.3, this will most likely still simply delegate to the magnolia-gui components. The important thing being that this becomes a hidden implementation detail, which we will be able to replace/update/improve later without the hassle of having to figure out each and every corner case the current taglib covers.
Buttons have actions, but these do nothing on their own other than generate links to servlets, so this can be considered an implementation detail, hidden in the rendering.
Another point to take into consideration is permissions. Currently, some of the tags or magnolia-gui components do check for permissions, for instance before rendering the editBar, but it doesn't seem to be a consistent behavior.
Common properties of items:
- label, description (help). i18n is implied. This can even exist at "container"-level.
- target: the node which the action is about (i.e for "edit", the paragraph node we're editing; for "new", the node into which we'll add a new child; etc.)
Ideally, the above should be enough. The dialog name for edit-paragraph can be deduced, and allowed paragraphs for new-button could be deduced from configuration, ... There are however sensible, often used, properties we can support too:
- dialog: the name of the dialog to use (page properties, page header, ...)
- allowed paragraphs: in current templates, this list is always passed to the jsp tag (even though with STK its value comes from the configuration). In some cases, it's just convenient if the template itself can enforce which paragraphs are added, even if not exactly the most elegant thing. (and that's our only option outside STK at the moment)
- expose these new components via
TemplateDirectiveModel. These have the same syntax than macros for templaters.
- allow configuration of object pushed in the rendering context? This could also be done for jsp.
- or shared variables http://freemarker.org/docs/pgui_config_sharedvariables.html
- JSP tags - either coded (should be fairly straightforward, just a little repetitive), could be generated.
- Using the JSP 2.0 SimpleTag API - removes concerns about pooling, etc.
- I'd rather keep the jsp-specific implementation separate from the new components, and keep those completely independant: testability, reusability.
Still haven't found a good name for these "new components".
Some of the brainstorm keywords: tag, ui component, admininterface, editor, bars, greenbars, author, authoring, buttons, dialog, edit paragraph, page edit, content edition
[@ui.edit /] ?
Some details about the current implementation:
- adapter (which warns/throws on author instance or develop mode but silently delegate to "old" taglib in public instances)
- documentation / examples for replacements etc!
Just some random bits of things I need to look at:
This and our
info.magnolia.cms.taglibs.CmsFunctionsclass could somewhat be redundant with
STKUtil. Consolidation needed ?
- Consider using
tagfiles; maybe this would help extensibility/customizability for the jsp pendant.
- Think about compatibility/migration. Would be nice if users had the possibility to "swap" to the "new tags" without touching anything? (and/or maybe a compatibility "add-on" ?)
// TODO if ((!adminOnly || ? with jsp tag EditBar, you can do adminOnly="false" and get the button/bar on public instance !?
// TODO - deduce page dialog from target node...?
- no support for comma-delimited strings? currently not supported by FM directives (but could) but still supported by tags
- templating made area-aware; area be a 1st class citizen; perhaps currentArea and currentNode/Paragraph be added to an hypothetical TemplatingState; or currentNode be updated with area when iterating, etc.: target=always current node, no need for "container"
- templating components - how they would still be used