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