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 info.magnolia.module.site.Site site = siteManager.getCurrentSite();
221 if (site instanceof Site) {
222 return (Site) site;
223 }
224 return null;
225 }
226
227
228
229
230
231
232
233
234 public Site site(Node content) {
235 try {
236 info.magnolia.module.site.Site site = siteManager.getAssignedSite(content);
237 if (site instanceof Site) {
238 return (Site) site;
239 }
240 return null;
241 } catch (IllegalStateException e) {
242 log.error("Unable to access assigned site ({}) until following issue is resolved: {}", content.toString(), e.getMessage());
243 return null;
244 }
245 }
246
247
248
249
250
251 public Theme theme(Site site) {
252 final String theme = site.getTheme().getName();
253 return StringUtils.isBlank(theme) ? new ThemeImpl(new STKImagingSupport()) : (Theme) moduleProvider.get().getTheme(theme);
254 }
255
256 public info.magnolia.module.site.theme.Theme theme(info.magnolia.module.site.Site site) {
257 final String theme = site.getTheme().getName();
258 return StringUtils.isBlank(theme) ? new ConfiguredTheme(null) : moduleProvider.get().getTheme(theme);
259 }
260
261
262
263
264
265
266
267
268 public Site site(ContentMap content) {
269 return site(content.getJCRNode());
270 }
271
272
273
274
275
276
277
278
279
280
281 public Node siteRoot(Node content) {
282 return this.siteRoot(content, SITEROOT_TEMPLATE_CATEGORY);
283 }
284
285
286
287
288
289
290
291
292
293
294 public ContentMap siteRoot(ContentMap content) {
295 return this.siteRoot(content, SITEROOT_TEMPLATE_CATEGORY);
296 }
297
298
299
300
301
302
303
304
305
306
307
308
309 public ContentMap siteRoot(ContentMap content, String siteRootTemplateCategory) {
310 return templatingFunctions.asContentMap(siteRoot(content.getJCRNode(), siteRootTemplateCategory));
311 }
312
313
314
315
316
317
318
319
320
321
322
323
324 public Node siteRoot(Node content, String siteRootTemplateCategory) {
325 if (StringUtils.isEmpty(siteRootTemplateCategory)) {
326 siteRootTemplateCategory = SITEROOT_TEMPLATE_CATEGORY;
327 }
328 try {
329 Node page = this.templatingFunctions.page(content);
330 Node root = TemplateCategoryUtil.findParentWithTemplateCategory(page, siteRootTemplateCategory);
331 return (root == null) ? (Node) page.getAncestor(0) : root;
332 } catch (RepositoryException e) {
333 throw new RuntimeException("Can't access site root.", e);
334 }
335 }
336
337 public List<ContentMap> ancestorsInSite(ContentMap content) throws RepositoryException {
338 return ancestorsInSite(content, null);
339 }
340
341 public List<Node> ancestorsInSite(Node content) throws RepositoryException {
342 return ancestorsInSite(content, null);
343 }
344
345 public List<ContentMap> ancestorsInSite(ContentMap content, String nodeTypeName) throws RepositoryException {
346 return templatingFunctions.asContentMapList(ancestorsInSite(content.getJCRNode(), nodeTypeName));
347 }
348
349 public List<Node> ancestorsInSite(Node content, String nodeTypeName) throws RepositoryException {
350 List<Node> allAncestors = templatingFunctions.ancestors(content, nodeTypeName);
351 Node siteRoot = siteRoot(content);
352
353 List<Node> ancestoresInSite = new ArrayList<Node>();
354 for (Node current : allAncestors) {
355 if (current.getDepth() >= siteRoot.getDepth()) {
356 ancestoresInSite.add(current);
357 }
358 }
359 return ancestoresInSite;
360 }
361
362
363
364
365 @Deprecated
366 public String getAssetLink(Node content, String assetProperty) {
367 return getAssetLink(content, assetProperty, ImagingSupport.VARIATION_ORIGINAL);
368 }
369
370
371
372
373 @Deprecated
374 public String getAssetLink(ContentMap content, String assetProperty) {
375 return getAssetLink(content.getJCRNode(), assetProperty);
376 }
377
378
379
380
381
382 @Deprecated
383 public String getAssetLink(ContentMap content, String assetProperty, AbstractSTKTemplateModel<? extends TemplateDefinition> model) {
384 return getAssetLink(content.getJCRNode(), assetProperty, resolveImageVariationName(model));
385 }
386
387
388
389
390 @Deprecated
391 public String getAssetLink(ContentMap content, String assetProperty, String renditionName) {
392 return getAssetLink(content.getJCRNode(), assetProperty, renditionName);
393 }
394
395
396
397
398 @Deprecated
399 public String getAssetLink(Node content, String assetProperty, String renditionName) {
400
401 String assetIdentifier = PropertyUtil.getString(content, assetProperty);
402 if (StringUtils.isNotBlank(assetIdentifier)) {
403 return damTemplatingFunctions.getAssetLinkForId(assetIdentifier, renditionName);
404 }
405 return null;
406 }
407
408
409
410
411
412
413
414 public String resolveImageVariationName(AbstractSTKTemplateModel<? extends TemplateDefinition> model) {
415 if (model == null) {
416 return ImagingSupport.VARIATION_ORIGINAL;
417 }
418 TemplateDefinition definition = model.getDefinition();
419 String variationName = (String) definition.getParameters().get("imageVariation");
420
421 if (StringUtils.isNotEmpty(variationName)) {
422 return variationName;
423 }
424
425 String cssSelector = cssSelectorBuilder.createCssSelector(model);
426 String imageClass = (String) definition.getParameters().get("imageClass");
427 if (StringUtils.isNotEmpty(imageClass)) {
428 cssSelector = cssSelector + " ." + imageClass.replace(" ", ".");
429 }
430
431 try {
432 return getImagingSupport().resolveVariationName(cssSelector);
433 } catch (NoSuchRenditionException e) {
434 log.warn(e.getMessage());
435 return ImagingSupport.VARIATION_ORIGINAL;
436 }
437 }
438
439
440
441
442
443 @Deprecated
444 public AssetRendition getAssetVariation(Asset asset, String renditionName) {
445 return damTemplatingFunctions.getRendition(asset.getItemKey().asString(), renditionName);
446 }
447
448
449
450
451
452 public Node wrap(Node content) {
453 return (content == null) ? null : templatingFunctions.encode(new I18nNodeWrapper(content));
454 }
455
456
457
458
459 @Deprecated
460 public List<ContentMap> getCategories(Node page) {
461 return categorizationSupport.getCategories(page);
462 }
463
464
465
466
467 @Deprecated
468 public String getCategoryLink(Node page, String categoryName) {
469 return categorizationSupport.getCategoryLink(page, categoryName);
470 }
471
472
473
474
475 public List<Node> getContentListByTemplateCategorySubCategory(Node siteRoot, String category, String subCategory) throws RepositoryException {
476 return getContentListByTemplateCategorySubCategory(siteRoot, category, subCategory, Integer.MAX_VALUE, null, null);
477 }
478
479
480
481
482 public static List<Node> getContentListByTemplateCategorySubCategory(Node siteRoot, String category, String subCategory, int maxResultSize, String andClause, String orderBy)
483 throws RepositoryException {
484 return TemplateCategoryUtil.getContentListByTemplateCategorySubCategory(siteRoot, category, subCategory, maxResultSize, andClause, orderBy);
485 }
486
487
488
489
490 public Node getNearestContentByTemplateCategorySubCategory(Node siteRoot, String category, String subCategory, Node current) throws RepositoryException {
491 return TemplateCategoryUtil.getNearestContentByTemplateCategorySubCategory(siteRoot, category, subCategory, current);
492 }
493
494
495
496
497 public static List<Node> getContentListByTemplateName(Node searchRoot, String templateName) throws RepositoryException {
498 return TemplateCategoryUtil.getContentListByTemplateName(searchRoot, templateName);
499 }
500
501
502
503
504 public static List<Node> getContentListByTemplateName(Node searchRoot, String templateName, int maxResultSize, String andClause, String orderByClause) throws RepositoryException {
505 return TemplateCategoryUtil.getContentListByTemplateName(searchRoot, templateName, maxResultSize, andClause, orderByClause);
506 }
507
508
509
510
511 public static List<Node> getContentListByTemplateNames(Node searchRoot, Set<String> templateIds, int maxResultSize, String andClause, String orderByClause) throws RepositoryException {
512 return TemplateCategoryUtil.getContentListByTemplateNames(searchRoot, templateIds, maxResultSize, andClause, orderByClause);
513 }
514
515
516
517
518
519
520
521
522
523
524
525 public Node getReferencedContent(Node content, String idPropertyName, String referencedWorkspace) throws RepositoryException {
526 if (content.hasProperty(idPropertyName)) {
527 String identifier = PropertyUtil.getString(content, idPropertyName);
528 return wrap(NodeUtil.getNodeByIdentifier(referencedWorkspace, identifier));
529 }
530 return null;
531 }
532
533
534
535
536
537
538
539
540
541
542
543 public Asset getAsset(Node node, String assetProperty, String renditionName) {
544 try {
545 if (node.hasProperty(assetProperty)) {
546 String assetNodeIdentifier = node.getProperty(assetProperty).getString();
547 return damTemplatingFunctions.getAssetRenditionForAssetId(assetNodeIdentifier, renditionName);
548 }
549 } catch (RepositoryException e) {
550 log.warn("Could not find asset for '{}' at '{}'", new Object[]{assetProperty, NodeUtil.getNodePathIfPossible(node), e});
551 return null;
552 }
553
554 return null;
555 }
556
557
558
559
560 public Asset getAsset(Node content, String assetProperty) {
561 try {
562 if (content.hasProperty(assetProperty)) {
563 String assetNodeIdentifier = content.getProperty(assetProperty).getString();
564 return new LegacyAssetWrapper(damTemplatingFunctions.getAssetForId(assetNodeIdentifier));
565 }
566 } catch (RepositoryException e) {
567 log.warn("Could not find asset for '{}' at '{}'", new Object[]{assetProperty, NodeUtil.getNodePathIfPossible(content), e});
568 }
569 return null;
570 }
571
572
573
574
575 public Asset getAsset(ContentMap content, String assetProperty) {
576 return getAsset(content.getJCRNode(), assetProperty);
577 }
578
579
580
581
582 public Asset getAsset(ContentMap content, String nodeDataPrefix, String variationName) {
583 return getAsset(content.getJCRNode(), nodeDataPrefix, variationName);
584 }
585
586
587
588
589
590
591 public List<Asset> getAssetsFromFolder(Node node, String assetProperty) {
592
593 try {
594 if (node.hasProperty(assetProperty)) {
595 String folderIdentifier = node.getProperty(assetProperty).getString();
596 final List<Asset> assets = damTemplatingFunctions.getAssetsFromFolderId(folderIdentifier);
597 for (int i = 0; i < assets.size(); i++) {
598 assets.set(i, new LegacyAssetWrapper(assets.get(i)));
599 }
600 return assets;
601 }
602 } catch (RepositoryException e) {
603 log.warn("Failed to get assets from folder.", e);
604 }
605
606 return new ArrayList<Asset>();
607 }
608
609
610
611
612
613
614
615 @Deprecated
616 public List<Asset> getAssetsByQuery(String statement) {
617 AssetQuery assetQuery = new AssetQuery.Builder().withAdditionalQueryStatement(statement).build();
618 final List<Asset> assets = damTemplatingFunctions.getAssetsForFilter(assetQuery);
619 for (int i = 0; i < assets.size(); i++) {
620 assets.set(i, new LegacyAssetWrapper(assets.get(i)));
621 }
622 return assets;
623 }
624
625
626
627
628
629 public List<Node> cutList(List<Node> itemsList, final int maxResults) {
630 if (itemsList.size() > maxResults) {
631 return itemsList.subList(0, maxResults);
632 }
633 return itemsList;
634 }
635
636
637 public String abbreviateString(String stringToCut, int size) {
638 return abbreviateString(stringToCut, size, " ...");
639 }
640
641 public String abbreviateString(String stringToCut, int size, String closureString) {
642 if (stringToCut.length() > size) {
643 int sizeMinusClosure = size - closureString.length();
644 String cutString = StringUtils.left(stringToCut, sizeMinusClosure);
645
646
647
648 String firstCharAfterCut = stringToCut.substring(sizeMinusClosure, sizeMinusClosure + 1);
649 if (!firstCharAfterCut.equals(" ")) {
650 cutString = StringUtils.substringBeforeLast(cutString, " ");
651 }
652
653 return cutString + closureString;
654
655 }
656 return stringToCut;
657 }
658
659
660
661
662
663 public int count(String name) {
664 String attributeName = STKTemplatingFunctions.class.getName() + name;
665 if (!MgnlContext.hasAttribute(attributeName)) {
666 MgnlContext.setAttribute(attributeName, new MutableInt(0));
667 }
668 MutableInt counter = (MutableInt) MgnlContext.getAttribute(attributeName);
669 counter.increment();
670 return counter.intValue();
671 }
672
673 public String getDivIdAbbreviation(String divID) {
674 return getDivIdAbbreviation(divID, "-");
675 }
676
677 public String getDivIdAbbreviation(String divID, String delimiter) {
678 String result = StringUtils.EMPTY;
679 if (StringUtils.isNotEmpty(divID) && StringUtils.isNotEmpty(delimiter)) {
680 String[] values = divID.split("\\" + delimiter);
681 for (String value : values) {
682 result += value.substring(0, 1);
683 }
684 }
685 return result;
686 }
687
688
689
690
691 public String metaDataProperty(Node content, String property) {
692 return templatingFunctions.metaData(content, property);
693 }
694
695 public String metaDataProperty(ContentMap content, String property) {
696 return templatingFunctions.metaData(content, property);
697 }
698
699
700
701
702
703 public String metaDataTemplate(Node content) {
704 try {
705 return NodeTypes.Renderable.getTemplate(content);
706 } catch (RepositoryException e) {
707 return null;
708 }
709 }
710
711 public String metaDataTemplate(ContentMap content) {
712 return metaDataTemplate(content.getJCRNode());
713 }
714
715
716
717
718 public void setCssSelectorBuilder(CssSelectorBuilder cssSelectorBuilder) {
719 this.cssSelectorBuilder = cssSelectorBuilder;
720 }
721
722
723
724
725 public void setCategorizationSupport(CategorizationSupport categorizationSupport) {
726 this.categorizationSupport = categorizationSupport;
727 }
728
729
730
731
732
733 public String getImageVariationLinkFromBinary(ContentMap binaryContent, AbstractSTKTemplateModel<? extends TemplateDefinition> model) {
734 if (binaryContent == null) {
735 return null;
736 }
737 return getImageVariationLinkFromBinary(binaryContent.getJCRNode(), model);
738 }
739
740
741
742
743 public String getImageVariationLinkFromBinary(Node binaryContent, AbstractSTKTemplateModel<? extends TemplateDefinition> model) {
744 return getImageVariationLinkFromBinary(binaryContent, resolveImageVariationName(model));
745 }
746
747
748
749
750 public String getImageVariationLinkFromBinary(ContentMap binaryContent, String rendition) {
751 if (binaryContent == null) {
752 return null;
753 }
754 return getImageVariationLinkFromBinary(binaryContent.getJCRNode(), rendition);
755 }
756
757
758
759
760 public String getImageVariationLinkFromBinary(Node binaryContent, String rendition) {
761 if (binaryContent == null || rendition == null) {
762 return null;
763 }
764
765 try {
766 String link = getImagingSupport().createLink(binaryContent.getProperty(JcrConstants.JCR_DATA), rendition);
767
768
769
770 return Text.escapePath(link);
771 } catch (Exception e) {
772 throw new DamException("AssetRendition exception", e) {
773 };
774 }
775 }
776
777 protected ImagingSupport getImagingSupport() {
778 return (ImagingSupport) theme(site()).getImaging();
779 }
780
781 }