1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34 package info.magnolia.module.templatingkit.functions;
35
36 import info.magnolia.cms.util.ContentUtil;
37 import info.magnolia.context.MgnlContext;
38 import info.magnolia.jcr.RuntimeRepositoryException;
39 import info.magnolia.jcr.util.ContentMap;
40 import info.magnolia.jcr.util.NodeUtil;
41 import info.magnolia.jcr.util.PropertyUtil;
42 import info.magnolia.jcr.wrapper.I18nNodeWrapper;
43 import info.magnolia.module.templatingkit.STKModule;
44 import info.magnolia.module.templatingkit.categorization.CategorizationSupport;
45 import info.magnolia.module.templatingkit.dam.Asset;
46 import info.magnolia.module.templatingkit.dam.AssetNotFoundException;
47 import info.magnolia.module.templatingkit.dam.DAMException;
48 import info.magnolia.module.templatingkit.dam.DAMSupport;
49 import info.magnolia.module.templatingkit.dam.NoSuchVariationException;
50 import info.magnolia.module.templatingkit.sites.Site;
51 import info.magnolia.module.templatingkit.sites.SiteManager;
52 import info.magnolia.module.templatingkit.style.CssSelectorBuilder;
53 import info.magnolia.module.templatingkit.style.Theme;
54 import info.magnolia.module.templatingkit.style.ThemeImpl;
55 import info.magnolia.module.templatingkit.templates.AbstractSTKTemplateModel;
56 import info.magnolia.module.templatingkit.templates.category.TemplateCategory;
57 import info.magnolia.module.templatingkit.templates.category.TemplateCategoryUtil;
58 import info.magnolia.rendering.template.TemplateDefinition;
59 import info.magnolia.repository.RepositoryConstants;
60 import info.magnolia.templating.functions.TemplatingFunctions;
61
62 import java.util.ArrayList;
63 import java.util.List;
64 import java.util.Set;
65
66 import javax.inject.Inject;
67 import javax.inject.Provider;
68 import javax.inject.Singleton;
69 import javax.jcr.Node;
70 import javax.jcr.Property;
71 import javax.jcr.RepositoryException;
72
73 import org.apache.commons.lang.StringUtils;
74 import org.apache.commons.lang.mutable.MutableInt;
75 import org.slf4j.Logger;
76 import org.slf4j.LoggerFactory;
77
78
79
80
81
82
83
84 @Singleton
85 public class STKTemplatingFunctions{
86
87 private static Logger log = LoggerFactory.getLogger(STKTemplatingFunctions.class);
88
89 public static final String SITEROOT_TEMPLATE_CATEGORY = TemplateCategory.HOME;
90
91 protected static final String TITLE_PROP_NAME = "title";
92 protected static final String SITE_TITLE_PROP_NAME = "siteTitle";
93 protected static final String METADATA_NODE_NAME = "MetaData";
94 protected static final String TEMPLATE_PROP_NAME = "mgnl:template";
95
96
97 private CssSelectorBuilder cssSelectorBuilder;
98 private CategorizationSupport categorizationSupport;
99 private SiteManager siteManager;
100 private TemplatingFunctions templatingFunctions;
101 private Provider<STKModule> moduleProvider;
102
103 @Inject
104 public STKTemplatingFunctions(TemplatingFunctions templatingFunctions, CssSelectorBuilder cssSelectorBuilder, CategorizationSupport categorizationSupport, SiteManager siteManager, Provider<STKModule> moduleProvider) {
105 this.templatingFunctions = templatingFunctions;
106 this.cssSelectorBuilder = cssSelectorBuilder;
107 this.categorizationSupport = categorizationSupport;
108 this.siteManager = siteManager;
109 this.moduleProvider = moduleProvider;
110 }
111
112
113
114
115
116
117
118
119
120
121 public String searchPageLink(Node content) {
122 String searchResultPageUUID = PropertyUtil.getString(siteRoot(content), "searchUUID");
123 return (StringUtils.isEmpty(searchResultPageUUID)) ? null : templatingFunctions.link(RepositoryConstants.WEBSITE, searchResultPageUUID);
124 }
125 public String searchPageLink(ContentMap content) {
126 return searchPageLink(content.getJCRNode());
127 }
128
129
130
131
132 public String homeName(Node content) {
133 return NodeUtil.getName(siteRoot(content));
134 }
135 public String homeName(ContentMap content) {
136 return homeName(content.getJCRNode());
137 }
138
139
140
141
142
143 public String homeTitle(Node content) {
144 return PropertyUtil.getString(siteRoot(content), TITLE_PROP_NAME );
145 }
146 public String homeTitle(ContentMap content) {
147 return homeTitle(content.getJCRNode());
148 }
149
150
151
152
153
154 public String siteTitle(Node content) {
155 return PropertyUtil.getString(siteRoot(content), SITE_TITLE_PROP_NAME );
156 }
157 public String siteTitle(ContentMap content) {
158 return siteTitle(content.getJCRNode());
159 }
160
161
162
163
164 public String homeLink(Node content) {
165 return templatingFunctions.link(siteRoot(content));
166 }
167
168 public String homeLink(ContentMap content) {
169 return homeLink(content.getJCRNode());
170 }
171
172 public Site site() {
173 return siteManager.getCurrentSite();
174 }
175
176
177
178
179
180
181
182 public Site site(Node content){
183 try {
184 return (content == null) ? null : siteManager.getAssignedSite(content);
185 } catch (IllegalStateException e) {
186 log.error("Unable to access assigned site ({}) until following issue is resolved: {}", content.toString(), e.getMessage());
187 return null;
188 }
189 }
190
191
192
193 public Theme theme(Site site) {
194 final String theme = site.getTheme().getName();
195 return StringUtils.isBlank(theme) ? new ThemeImpl() : moduleProvider.get().getTheme(theme);
196
197 }
198
199
200
201
202
203
204 public Site site(ContentMap content){
205 return site(content.getJCRNode());
206 }
207
208
209
210
211
212
213
214
215
216 public Node siteRoot(Node content) {
217 return this.siteRoot(content, SITEROOT_TEMPLATE_CATEGORY);
218 }
219
220
221
222
223
224
225
226
227
228 public ContentMap siteRoot(ContentMap content) {
229 return this.siteRoot(content, SITEROOT_TEMPLATE_CATEGORY);
230 }
231
232
233
234
235
236
237
238
239
240
241
242 public ContentMap siteRoot(ContentMap content, String siteRootTemplateCategory) {
243 return templatingFunctions.asContentMap(siteRoot(content.getJCRNode(), siteRootTemplateCategory));
244 }
245
246
247
248
249
250
251
252
253
254
255
256
257 public Node siteRoot(Node content, String siteRootTemplateCategory) {
258 if(StringUtils.isEmpty(siteRootTemplateCategory)){
259 siteRootTemplateCategory = SITEROOT_TEMPLATE_CATEGORY;
260 }
261 try {
262 Node page = this.templatingFunctions.page(content);
263 Node root = TemplateCategoryUtil.findParentWithTemplateCategory(page, siteRootTemplateCategory);
264 return (root == null) ? (Node)page.getAncestor(0) : root;
265 }
266 catch (RepositoryException e) {
267 throw new RuntimeException("Can't access site root.", e);
268 }
269 }
270
271 public List<ContentMap> ancestorsInSite(ContentMap content) throws RepositoryException {
272 return ancestorsInSite(content, null);
273 }
274
275 public List<Node> ancestorsInSite(Node content) throws RepositoryException {
276 return ancestorsInSite(content, null);
277 }
278
279 public List<ContentMap> ancestorsInSite(ContentMap content, String nodeTypeName) throws RepositoryException {
280 return templatingFunctions.asContentMapList(ancestorsInSite(content.getJCRNode(), nodeTypeName));
281 }
282
283 public List<Node> ancestorsInSite(Node content, String nodeTypeName) throws RepositoryException {
284 List<Node> allAncestors = templatingFunctions.ancestors(content, nodeTypeName);
285 Node siteRoot = siteRoot(content);
286
287 List<Node> ancestoresInSite = new ArrayList<Node>();
288 for(Node current: allAncestors){
289 if(current.getDepth() >= siteRoot.getDepth()){
290 ancestoresInSite.add(current);
291 }
292 }
293 return ancestoresInSite;
294 }
295
296
297
298
299
300 public String getAssetLink(Node content, String nodeDataPrefix){
301 return getAssetLink( content, nodeDataPrefix, DAMSupport.VARIATION_ORIGINAL);
302 }
303
304
305
306
307 public String getAssetLink(ContentMap content, String nodeDataPrefix){
308 return getAssetLink(content.getJCRNode(), nodeDataPrefix);
309 }
310
311 public String getAssetLink(ContentMap content, String nodeDataPrefix, AbstractSTKTemplateModel<? extends TemplateDefinition> model){
312 return getAssetLink(content.getJCRNode(), nodeDataPrefix, resolveImageVariationName(model));
313 }
314
315 public String getAssetLink(ContentMap content, String nodeDataPrefix, String variationName){
316 return getAssetLink(content.getJCRNode(), nodeDataPrefix,variationName);
317 }
318
319 public String getAssetLink(Node content, String nodeDataPrefix, String variationName){
320 final Asset asset = getAsset(content, nodeDataPrefix, variationName);
321 if(asset != null){
322 try {
323 return asset.getLink();
324 }
325 catch (DAMException e) {
326 log.warn("Failed to get asset link with exception: " + e.getMessage(), e);
327 return null;
328 }
329 }
330 return null;
331 }
332
333
334 public String resolveImageVariationName(AbstractSTKTemplateModel<? extends TemplateDefinition> model) {
335 final String cssSelector = cssSelectorBuilder.createCssSelector(model);
336 try {
337 return theme(site(model.getNode())).getImaging().resolveVariationName(cssSelector);
338 }
339 catch (NoSuchVariationException e) {
340 log.warn(e.getMessage());
341 return DAMSupport.VARIATION_ORIGINAL;
342 }
343 }
344
345 public Asset getAssetVariation(Asset original, String variationName){
346 if(!variationName.equals(DAMSupport.VARIATION_ORIGINAL)){
347 try {
348 return original.getVariation(variationName);
349 }
350 catch (NoSuchVariationException e) {
351 log.warn("Can't find the variation " + variationName + " for asset [" + original + "]. Will use the original instead.");
352 }
353 catch(DAMException e){
354 log.warn("Failed to get asset variation " + variationName + " with exception: " + e.getMessage(), e);
355 return null;
356 }
357 }
358 return original;
359 }
360
361
362
363
364
365 public Node wrap(Node content){
366 return (content == null) ? null : templatingFunctions.encode(new I18nNodeWrapper(content));
367 }
368
369
370
371
372 public List<ContentMap> getCategories(Node page) {
373 return categorizationSupport.getCategories(page);
374 }
375
376
377
378
379 public String getCategoryLink(Node page, String categoryName) {
380 return categorizationSupport.getCategoryLink(page, categoryName);
381 }
382
383
384
385
386 public List<Node> getContentListByTemplateCategorySubCategory(Node siteRoot, String category, String subCategory) throws RepositoryException {
387 return getContentListByTemplateCategorySubCategory(siteRoot, category, subCategory, Integer.MAX_VALUE, null, null);
388 }
389
390
391
392
393 public static List<Node> getContentListByTemplateCategorySubCategory(Node siteRoot, String category, String subCategory, int maxResultSize, String andClause, String orderBy) throws RepositoryException {
394 return TemplateCategoryUtil.getContentListByTemplateCategorySubCategory(siteRoot, category, subCategory, maxResultSize, andClause, orderBy);
395 }
396
397
398
399
400 public Node getNearestContentByTemplateCategorySubCategory(Node siteRoot, String category, String subCategory, Node current) throws RepositoryException {
401 return TemplateCategoryUtil.getNearestContentByTemplateCategorySubCategory(siteRoot, category, subCategory,current);
402 }
403
404
405
406
407 public static List<Node> getContentListByTemplateName(Node searchRoot, String templateName) throws RepositoryException {
408 return TemplateCategoryUtil.getContentListByTemplateName(searchRoot, templateName);
409 }
410
411
412
413
414 public static List<Node> getContentListByTemplateName(Node searchRoot, String templateName, int maxResultSize, String andClause, String orderByClause) throws RepositoryException {
415 return TemplateCategoryUtil.getContentListByTemplateName(searchRoot, templateName, maxResultSize, andClause, orderByClause);
416 }
417
418
419
420
421 public static List<Node> getContentListByTemplateNames(Node searchRoot, Set<String> templateIds, int maxResultSize, String andClause, String orderByClause) throws RepositoryException{
422 return TemplateCategoryUtil.getContentListByTemplateNames(searchRoot, templateIds, maxResultSize, andClause, orderByClause);
423 }
424
425
426
427
428
429
430
431
432 public Node getReferencedContent(Node content, String idPropertyName, String referencedWorkspace){
433 try {
434 if(content.hasProperty(idPropertyName)){
435 String identifier = PropertyUtil.getString(content, idPropertyName);
436 return wrap(NodeUtil.getNodeByIdentifier(referencedWorkspace, identifier));
437 }
438 } catch (RepositoryException e) {
439 log.error("can't read value '" + idPropertyName + "' of the Node '" + content.toString() + "'.", e);
440 throw new RuntimeRepositoryException(e);
441 }
442 return null;
443 }
444
445
446
447
448 public Asset getAsset(Node content, String nodeDataPrefix, String variationName){
449 try{
450 final Asset asset = moduleProvider.get().getDamSupport().getAsset(ContentUtil.asContent(content), nodeDataPrefix);
451 return getAssetVariation(asset, variationName);
452 }
453 catch(AssetNotFoundException e){
454 return null;
455 }
456 catch(DAMException e){
457 log.warn("Failed to get asset with exception: " + e.getMessage(), e);
458 return null;
459 }
460 }
461
462 public Asset getAsset(Node content, String nodeDataPrefix){
463 return getAsset(content, nodeDataPrefix, DAMSupport.VARIATION_ORIGINAL);
464 }
465
466 public Asset getAsset(ContentMap content, String nodeDataPrefix){
467 return getAsset(content.getJCRNode(), nodeDataPrefix);
468 }
469
470
471
472
473
474 public List<Node> cutList(List<Node> itemsList, final int maxResults){
475 if(itemsList.size() > maxResults) {
476 return itemsList.subList(0, maxResults);
477 }
478 return itemsList;
479 }
480
481
482 public String abbreviateString(String stringToCut, int size) {
483 return abbreviateString(stringToCut, size, " ...");
484 }
485
486 public String abbreviateString(String stringToCut, int size, String closureString) {
487 if(stringToCut.length() > size) {
488 int sizeMinusClosue= size - closureString.length();
489 String cuttedString = StringUtils.left(stringToCut, sizeMinusClosue);
490
491
492 String firstCharAfterCut = stringToCut.substring(sizeMinusClosue, sizeMinusClosue+1);
493 if(!firstCharAfterCut.equals(" ")){
494 cuttedString = StringUtils.substringBeforeLast(cuttedString, " ");
495 }
496
497 return cuttedString + closureString;
498
499 }
500 return stringToCut;
501 }
502
503
504
505
506 public int count(String name){
507 String attributeName = STKTemplatingFunctions.class.getName() + name;
508 if(!MgnlContext.hasAttribute(attributeName)){
509 MgnlContext.setAttribute(attributeName, new MutableInt(0));
510 }
511 MutableInt counter = (MutableInt) MgnlContext.getAttribute(attributeName);
512 counter.increment();
513 return counter.intValue();
514 }
515
516 public String getDivIdAbbreviation(String divID){
517 return getDivIdAbbreviation(divID, "-");
518 }
519
520 public String getDivIdAbbreviation(String divID, String delimiter){
521 String result = StringUtils.EMPTY;
522 if(StringUtils.isNotEmpty(divID) && StringUtils.isNotEmpty(delimiter)){
523 String[] values = divID.split("\\"+delimiter);
524 for(String value : values ){
525 result += value.substring(0, 1);
526 }
527 }
528 return result;
529 }
530
531
532
533
534 public String metaDataProperty(Node content, String property){
535 try {
536 if(content.hasNode(METADATA_NODE_NAME)){
537 Node node = content.getNode(METADATA_NODE_NAME);
538 Property metaDataProp = PropertyUtil.getProperty(node, property);
539 if(metaDataProp != null){
540 return metaDataProp.getString();
541 }
542 }
543 } catch (RepositoryException e) {
544 throw new RuntimeException(e);
545 }
546 return null;
547 }
548
549 public String metaDataProperty(ContentMap content, String property){
550 return metaDataProperty(content.getJCRNode(), property);
551 }
552
553
554
555
556 public String metaDataTemplate(Node content){
557 return metaDataProperty(content,TEMPLATE_PROP_NAME);
558 }
559
560 public String metaDataTemplate(ContentMap content){
561 return metaDataProperty(content,TEMPLATE_PROP_NAME);
562 }
563
564
565
566
567 public void setCssSelectorBuilder(CssSelectorBuilder cssSelectorBuilder){
568 this.cssSelectorBuilder = cssSelectorBuilder;
569 }
570
571
572
573
574 public void setCategorizationSupport(CategorizationSupport categorizationSupport){
575 this.categorizationSupport = categorizationSupport;
576 }
577
578 }