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