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