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