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