Template queries
Introduction
Goal
Understand what template queries are, what they are used for, and where they are stored in the repository.
Background
CMS users can create new documents and subfolders within existing content folders. They do this by browsing to a folder, opening its context menu, choosing one of the available "Add ..." options, and choosing one of the document or folder types available for that option. The new document or folder is then created by copying the appropriate template to the selected parent folder and substituting any of the template's default property values if needed.
Template queries are used to define the available "Add ..." options, the available document or folder types, and the substitution patterns to use when copying the template.
This page describes the node types and properties used to configure template queries, and how they relate to each other. They are illustrated with some basic examples.
For a detailed hands-on example of defining and using custom template queries, see Control Which Document Types Can Be Used in Which Folder.
Since Bloomreach Experience Manager 12.3, a template query generator is packaged with the Essentials development tools, providing an easy way to create template queries for custom document types.
Folder Types and Template Queries
Concepts
Content folders, which are nodes of type hippostd:folder, have a multi-valued String property called hippostd:foldertype. Each value of this property refers to a template query, and is rendered as an "Add ..." option in the folder's content menu in the CMS UI.
Template queries are stored as nodes of type hippostd:templatequery at the following repository location:
/hippo:configuration/hippo:queries/hippo:templates
The hippostd:templatequery type inherits from the built-in JCR node type nt:query and as such has two properties that represent the query:
[nt:query] > nt:base - jcr:statement (string) - jcr:language (string)
where the first property contains the query statement and the second the query language in which the statement is written (xpath, sql, JCR-SQL2, or JCR-JQOM).
The query should select the template nodes of the document or folder types that the user should be able to choose for the corresponding "Add ..." option.
For documents, templates are stored as "prototype" document within the document type definitions. For example:
/hippo:namespaces/myhippoproject/newsdocument/hipposysedit:prototypes/hipposysedit:prototype
For folders, templates are stored within the template query node structure. For example:
/hippo:configuration/hippo:queries/hippo:templates/new-translated-folder/hippostd:templates/hippostd:folder
Example
Taking a Bloomreach Experience Manager project created using the Maven archetype using the default settings, consider the following example:
The default content root folder /content/documents/myhippoproject has two "folder types" defined:
/content/documents/myhippoproject: jcr:primaryType: hippostd:folder hippostd:foldertype: [new-translated-folder, new-document]
Each of the values of the hippostd:foldertype property refers to a template query stored as a child node of /hippo:configuration/hippo:queries/hippo:templates.
Localized labels for template queries are defined in resource bundles under /hippo:configuration/hippo:translations/hippo:templates:
/hippo:configuration/hippo:translations/hippo:templates: jcr:primaryType: hipposys:resourcebundles /en: jcr:primaryType: hipposys:resourcebundle new-document: new document new-translated-folder: new translated folder
In the CMS UI, when the user opens the context menu for the myhippoproject folder, a localized menu option is displayed for each template query referred to in the folder's hippostd:foldertypes property:
Now take a look at the relevant structure and properties of the new-translated-folder template query node:
/hippo:configuration/hippo:queries/hippo:templates/new-translated-folder: jcr:primaryType: hippostd:templatequery /hippostd:templates: jcr:primaryType: hippostd:templates /hippostd:folder: jcr:primaryType: hippostd:folder hippostd:foldertype: [new-translated-folder, new-document] jcr:language: xpath jcr:statement: /jcr:root/hippo:configuration/hippo:queries/hippo:templates/new-translated-folder/hippostd:templates/node()
Note that the folder template is defined within the template query node structure, and contains the hippostd:foldertype values for the new folder that will be created using this template.
Also note that the query statement selects any template nodes defined within this template query node structure.
In the CMS UI, when the user selects the Add new translated folder option, a dialog appears in which the user can enter a name for the new folder. Because this template query has only one result, there is no option in the dialog to select the folder type.
Now take a look at the properties of the new-document template query node:
/hippo:configuration/hippo:queries/hippo:templates/new-document: jcr:primaryType: hippostd:templatequery jcr:language: xpath jcr:statement: //element(*,hipposysedit:namespacefolder)/element(*,mix:referenceable)/element(*,hipposysedit:templatetype)/hipposysedit:prototypes/element(hipposysedit:prototype,hippo:document)
Note that the query statement selects all hipposysedit:prototype nodes of type hippo:document within the document type definitions in the namespace folder (/hippo:namespaces). Because all document types descend from hippo:document, a folder defining this template query in its folder types allows users to create documents of any type inside that folder.
In the CMS UI, when the user selects the Add new document option, a dialog appears in which the user can enter a name for the new document. Because this template query has multiple results, the user must also select a document type from a dropdown list.
Value Substitution
Concept
As explained above, when a user creates a new document or folder, the appropriate template is copied to the selected parent folder. Typically, the default values for some document or folder properties depend on the context in which it is created. For example, the current date, the current user, or values entered by the user in the create document/folder dialog.
For this purpose, template query nodes have a multi-valued property hippostd:modify which contains relative paths to properties of the template nodes with the values to be substituted when copying the template to the new document or folder during creation. The special _name pseudo property allows modifying the name of the node.
The values of the hippostd:modify property alternate between the path to the property to be substituted and the value to substitute it with. The paths are relative to the root of the template selected by the query and can contain the special wildcard path element matcher _node that matches any node. The following table specifies the special substitution values available:
$name | The URL name specified in the create document/folder dialog. |
$holder | The id of the current user. |
$now | Current date-time specified in the format yyyy-MM-dd'T'HH:mm:ss.SSSZ |
$inherited | The value of the property is copied from the parent node. |
$uuid | A newly created UUID. |
Optional math functions may be used along with the $now option, time units supported include:
- Y for year
- M for month
- D for day
- H for hour
- MIN for minute
- SEC for second
- MIL for millisecond
Some example usages are:
- $now/H: Round to the start of the current hour
- $now/D: Round to the start of the current day
- $now+2Y: Exactly two years in the future from now
- $now-1D: Exactly 1 day prior to now
- $now+6M+3D/D: 6 months and 3 days in the future from now, rounded down to nearest day
Properties specified in hippostd:modify must exist on the template node for the substitution to take place. If a property specified in hippostd:modify doesn't exist on the template node, it is not created but rather ignored.
Example
The template query new-translated-folder has the following hippostd:modify values:
/hippo:configuration/hippo:queries/hippo:templates/new-translated-folder: jcr:primaryType: hippostd:templatequery hippostd:modify: [./_name, $name, ./hippotranslation:id, $uuid, ./hippotranslation:locale, $inherited]
These values are interpreted as follows:
- The new node's name will be the URL name specified in the create document/folder dialog.
- The new node's hippotranslation:id property will have its value substituted by a newly generated UUID.
- The new node's hippotranslation:locale property will have its value subsituted with the value of the same property of the new item's parent node.
The template query new-document has many more interesting hippostd:modify value pairs, including:
- ./hippostdpubwf:createdBy
$holder
Substitutes the hippostdpubwf:createdBy property's default value with the username of the user who created the document. - ./hippostdpubwf:creationDate
$now
Substitutes the hippostdpubwf:creationDate property's default value with the current date.