001/* 002 * Copyright 2016 Anyware Services 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package org.ametys.web.transformation.xslt; 018 019import java.io.IOException; 020import java.util.ArrayList; 021import java.util.Arrays; 022import java.util.Collection; 023import java.util.Collections; 024import java.util.HashMap; 025import java.util.Iterator; 026import java.util.List; 027import java.util.Map; 028import java.util.Optional; 029import java.util.Set; 030 031import org.apache.avalon.framework.service.ServiceException; 032import org.apache.avalon.framework.service.ServiceManager; 033import org.apache.cocoon.components.ContextHelper; 034import org.apache.cocoon.environment.Request; 035import org.apache.cocoon.environment.Response; 036import org.apache.cocoon.xml.dom.DOMBuilder; 037import org.apache.commons.lang3.StringUtils; 038import org.apache.excalibur.source.Source; 039import org.w3c.dom.Element; 040import org.w3c.dom.Node; 041import org.w3c.dom.NodeList; 042import org.xml.sax.SAXException; 043 044import org.ametys.cms.CmsConstants; 045import org.ametys.cms.repository.Content; 046import org.ametys.cms.repository.ContentQueryHelper; 047import org.ametys.cms.repository.LanguageExpression; 048import org.ametys.core.right.RightManager.RightResult; 049import org.ametys.core.user.population.PopulationContextHelper; 050import org.ametys.core.util.I18nUtils; 051import org.ametys.core.util.dom.AmetysNodeList; 052import org.ametys.core.util.dom.EmptyElement; 053import org.ametys.core.util.dom.MapElement; 054import org.ametys.core.util.dom.MapElement.MapNode; 055import org.ametys.core.util.dom.SourceElement; 056import org.ametys.core.util.dom.StringElement; 057import org.ametys.plugins.explorer.resources.Resource; 058import org.ametys.plugins.explorer.resources.ResourceCollection; 059import org.ametys.plugins.explorer.resources.dom.ResourceCollectionElement; 060import org.ametys.plugins.explorer.resources.dom.ResourceElement; 061import org.ametys.plugins.repository.AmetysObject; 062import org.ametys.plugins.repository.AmetysObjectIterable; 063import org.ametys.plugins.repository.AmetysObjectResolver; 064import org.ametys.plugins.repository.UnknownAmetysObjectException; 065import org.ametys.plugins.repository.data.holder.ModelAwareDataHolder; 066import org.ametys.plugins.repository.data.holder.group.Repeater; 067import org.ametys.plugins.repository.data.holder.group.RepeaterEntry; 068import org.ametys.plugins.repository.data.type.ModelItemTypeConstants; 069import org.ametys.plugins.repository.model.RepeaterDefinition; 070import org.ametys.plugins.repository.model.RepositoryDataContext; 071import org.ametys.plugins.repository.query.expression.AndExpression; 072import org.ametys.plugins.repository.query.expression.Expression; 073import org.ametys.plugins.repository.query.expression.ExpressionContext; 074import org.ametys.plugins.repository.query.expression.Expression.Operator; 075import org.ametys.plugins.repository.query.expression.MetadataExpression; 076import org.ametys.plugins.repository.query.expression.NotExpression; 077import org.ametys.plugins.repository.query.expression.StringExpression; 078import org.ametys.runtime.model.ElementDefinition; 079import org.ametys.runtime.model.ModelHelper; 080import org.ametys.runtime.model.ModelItem; 081import org.ametys.runtime.model.type.DataContext; 082import org.ametys.runtime.model.type.ElementType; 083import org.ametys.runtime.model.type.ModelItemType; 084import org.ametys.web.URIPrefixHandler; 085import org.ametys.web.WebConstants; 086import org.ametys.web.cache.PageHelper; 087import org.ametys.web.parameters.view.ViewParametersManager; 088import org.ametys.web.parameters.view.ViewParametersManager.ViewParameterHolder; 089import org.ametys.web.parameters.view.ViewParametersModel; 090import org.ametys.web.renderingcontext.RenderingContext; 091import org.ametys.web.renderingcontext.RenderingContextHandler; 092import org.ametys.web.repository.content.WebContent; 093import org.ametys.web.repository.dom.PageElement; 094import org.ametys.web.repository.page.Page; 095import org.ametys.web.repository.page.Page.PageType; 096import org.ametys.web.repository.page.PageDAO; 097import org.ametys.web.repository.page.SitemapElement; 098import org.ametys.web.repository.page.Zone; 099import org.ametys.web.repository.page.ZoneItem; 100import org.ametys.web.repository.page.ZoneItem.ZoneType; 101import org.ametys.web.repository.site.Site; 102import org.ametys.web.repository.site.SiteManager; 103import org.ametys.web.repository.sitemap.Sitemap; 104import org.ametys.web.service.Service; 105import org.ametys.web.service.ServiceExtensionPoint; 106import org.ametys.web.skin.SkinsManager; 107import org.ametys.web.tags.TagExpression; 108import org.ametys.web.url.UrlPreview; 109import org.ametys.web.url.UrlPreviewComponent; 110 111/** 112 * Helper component to be used from XSL stylesheets. 113 */ 114public class AmetysXSLTHelper extends org.ametys.cms.transformation.xslt.AmetysXSLTHelper 115{ 116 static final int _PAGINATION_CURRENT = -1; 117 static final int _PAGINATION_SEPARATOR = -2; 118 static final int _PAGINATION_SPACE = -3; 119 120 private static final String __NAME_ATTRIBUTE = "name"; 121 private static final String __TYPE_ATTRIBUTE = "type"; 122 private static final String __REPEATER_ENTRY_TYPE = ModelItemTypeConstants.REPEATER_TYPE_ID + "_entry"; 123 124 private static SiteManager _siteManager; 125 private static RenderingContextHandler _renderingContextHandler; 126 private static URIPrefixHandler _prefixHandler; 127 private static ServiceExtensionPoint _serviceEP; 128 private static PopulationContextHelper _populationContextHelper; 129 private static UrlPreviewComponent _urlPreview; 130 private static ViewParametersManager _viewParametersManager; 131 private static PageDAO _pageDAO; 132 private static SkinsManager _skinsManager; 133 private static PageHelper _pageHelper; 134 135 @Override 136 public void service(ServiceManager manager) throws ServiceException 137 { 138 _siteManager = (SiteManager) manager.lookup(SiteManager.ROLE); 139 _pageDAO = (PageDAO) manager.lookup(PageDAO.ROLE); 140 _renderingContextHandler = (RenderingContextHandler) manager.lookup(RenderingContextHandler.ROLE); 141 _ametysObjectResolver = (AmetysObjectResolver) manager.lookup(AmetysObjectResolver.ROLE); 142 _i18nUtils = (I18nUtils) manager.lookup(I18nUtils.ROLE); 143 _prefixHandler = (URIPrefixHandler) manager.lookup(URIPrefixHandler.ROLE); 144 _serviceEP = (ServiceExtensionPoint) manager.lookup(ServiceExtensionPoint.ROLE); 145 _populationContextHelper = (PopulationContextHelper) manager.lookup(PopulationContextHelper.ROLE); 146 _urlPreview = (UrlPreviewComponent) manager.lookup(UrlPreviewComponent.ROLE); 147 _viewParametersManager = (ViewParametersManager) manager.lookup(ViewParametersManager.ROLE); 148 _skinsManager = (SkinsManager) manager.lookup(SkinsManager.ROLE); 149 _pageHelper = (PageHelper) manager.lookup(PageHelper.ROLE); 150 } 151 152 /** 153 * Returns the current URI prefix, depending on the rendering context. 154 * @return the current URI prefix. 155 */ 156 public static String uriPrefix() 157 { 158 return _prefixHandler.getUriPrefix(); 159 } 160 161 /** 162 * Returns the URI prefix corresponding to the current site, depending on the rendering context. 163 * @return the URI prefix corresponding to the current site. 164 */ 165 public static String siteUriPrefix() 166 { 167 Request request = ContextHelper.getRequest(_context); 168 String siteName = (String) request.getAttribute("site"); 169 return _prefixHandler.getUriPrefix(siteName); 170 } 171 172 /** 173 * Returns the absolute URI prefix, depending on the rendering context. 174 * @return the absolute URI prefix. 175 */ 176 public static String absoluteUriPrefix() 177 { 178 return _prefixHandler.getAbsoluteUriPrefix(); 179 } 180 181 /** 182 * Returns the absolute URI prefix corresponding to the current site, depending on the rendering context. 183 * @return the absolute URI prefix corresponding to the current site. 184 */ 185 public static String absoluteSiteUriPrefix() 186 { 187 Request request = ContextHelper.getRequest(_context); 188 String siteName = (String) request.getAttribute("site"); 189 return _prefixHandler.getAbsoluteUriPrefix(siteName); 190 } 191 192 /** 193 * Returns the absolute URI prefix corresponding to the given site, depending on the rendering context. 194 * @param siteName The site name. Can be null to get the current site. 195 * @return the absolute URI prefix corresponding to the current site. 196 */ 197 public static String absoluteSiteUriPrefix(String siteName) 198 { 199 if (StringUtils.isEmpty(siteName)) 200 { 201 return absoluteSiteUriPrefix(); 202 } 203 return _prefixHandler.getAbsoluteUriPrefix(siteName); 204 } 205 206 /** 207 * Returns the current skin name. 208 * @return the current skin name. 209 */ 210 public static String skin() 211 { 212 return _skinsManager.getSkinNameFromRequest(); 213 } 214 215 /** 216 * Returns the current template name. 217 * @return the current template name. 218 */ 219 public static String template() 220 { 221 Request request = ContextHelper.getRequest(_context); 222 return (String) request.getAttribute("template"); 223 } 224 225 /** 226 * Returns the current sitemap name. 227 * @return the current sitemap name. 228 */ 229 public static String lang() 230 { 231 Request request = ContextHelper.getRequest(_context); 232 String lang = (String) request.getAttribute("sitemapLanguage"); 233 234 return StringUtils.isNotBlank(lang) 235 ? lang 236 : org.ametys.cms.transformation.xslt.AmetysXSLTHelper.lang(); 237 } 238 239 /** 240 * Returns the current sitemap name. 241 * @param pageId The page identifier to get sitemap on 242 * @return the current sitemap name. 243 */ 244 public static String lang(String pageId) 245 { 246 try 247 { 248 Page page = _getPage(pageId); 249 return page.getSitemapName(); 250 } 251 catch (UnknownAmetysObjectException e) 252 { 253 _logger.error("Can not get sitemap lang on page '" + pageId + "'", e); 254 return ""; 255 } 256 } 257 258 /** 259 * Computes the URI for the given resource in the current site's skin.<br> 260 * If the URI is requested by the front-office, it will be absolutized. 261 * @param path the resource path. 262 * @return the URI for the given resource. 263 */ 264 public static String skinURL(String path) 265 { 266 Request request = ContextHelper.getRequest(_context); 267 String siteName = (String) request.getAttribute("site"); 268 Site site = _siteManager.getSite(siteName); 269 String skin = (String) request.getAttribute("skin"); 270 271 String resourcePath = "/skins/" + skin + "/resources/" + path; 272 273 return _getResourceURL(request, site, resourcePath); 274 } 275 276 /** 277 * Computes the URI for the given image with a given heigth and width in the current site's skin.<br> 278 * If the URI is requested by the front-office, it will be absolutized. 279 * @param path the resource path 280 * @param height the height for the resource to get 281 * @param width the width for the resource to get 282 * @return the URI of the given resource 283 */ 284 public static String skinImageURL(String path, int height, int width) 285 { 286 String skinPath = skinURL(path); 287 return StringUtils.substringBeforeLast(skinPath, ".") + "_" + height + "x" + width + "." + StringUtils.substringAfterLast(skinPath, "."); 288 } 289 290 /** 291 * Computes the base 64 representation of the image at the specified path. <br> 292 * @param skin the skin to search in 293 * @param path the path of the image 294 * @return the base 64-encoded image 295 * @throws IOException if an error occurs while trying to get the file 296 */ 297 public static String skinImageBase64(String skin, String path) throws IOException 298 { 299 Source source = null; 300 try 301 { 302 source = _sourceResolver.resolveURI("skin:" + skin + "://resources/" + path); 303 return _getResourceBase64(source); 304 } 305 finally 306 { 307 if (source != null) 308 { 309 _sourceResolver.release(source); 310 } 311 } 312 } 313 314 /** 315 * Computes the base 64 representation of the image at the specified path. <br> 316 * @param path the path of the image 317 * @return the base 64-encoded image 318 * @throws IOException if an error occurs while trying to get the file 319 */ 320 public static String skinImageBase64 (String path) throws IOException 321 { 322 Source source = null; 323 try 324 { 325 source = _sourceResolver.resolveURI("skin://resources/" + path); 326 return _getResourceBase64(source); 327 } 328 finally 329 { 330 if (source != null) 331 { 332 _sourceResolver.release(source); 333 } 334 } 335 } 336 337 /** 338 * Computes the URI for the given image with a given heigth and width in the current site's skin.<br> 339 * If the URI is requested by the front-office, it will be absolutized. 340 * @param path the resource path 341 * @param maxHeight the maximum height for the resource to get 342 * @param maxWidth the maximum width for the resource to get 343 * @return the URI of the given resource 344 */ 345 public static String skinBoundedImageURL(String path, int maxHeight, int maxWidth) 346 { 347 String skinPath = skinURL(path); 348 return StringUtils.substringBeforeLast(skinPath, ".") + "_max" + maxHeight + "x" + maxWidth + "." + StringUtils.substringAfterLast(skinPath, "."); 349 } 350 351 /** 352 * Computes the URI for the given resource in the current template.<br> 353 * If the URI is requested by the front-office, it will be absolutized. 354 * @param path the resource path. 355 * @return the URI for the given resource. 356 */ 357 public static String templateURL(String path) 358 { 359 Request request = ContextHelper.getRequest(_context); 360 String siteName = (String) request.getAttribute("site"); 361 Site site = _siteManager.getSite(siteName); 362 String skin = (String) request.getAttribute("skin"); 363 String template = (String) request.getAttribute("template"); 364 365 String resourcePath = "/skins/" + skin + "/templates/" + template + "/resources/" + path; 366 367 return _getResourceURL(request, site, resourcePath); 368 } 369 370 /** 371 * Computes the URI for the given resource in the given plugin.<br> 372 * If the URI is requested by the front-office, it will be absolutized. 373 * @param plugin the plugin name. 374 * @param path the resource path. 375 * @return the URI for the given resource. 376 */ 377 public static String pluginResourceURL(String plugin, String path) 378 { 379 Request request = ContextHelper.getRequest(_context); 380 String siteName = (String) request.getAttribute("site"); 381 Site site = _siteManager.getSite(siteName); 382 383 String resourcePath = "/plugins/" + plugin + "/resources/" + path; 384 385 return _getResourceURL(request, site, resourcePath); 386 } 387 388 private static String _getResourceURL(Request request, Site site, String resourcePath) 389 { 390 String prefix; 391 switch (_renderingContextHandler.getRenderingContext()) 392 { 393 case FRONT: 394 String[] aliases = site.getUrlAliases(); 395 int position = Math.abs(resourcePath.hashCode()) % aliases.length; 396 397 boolean absolute = request.getAttribute("forceAbsoluteUrl") != null ? (Boolean) request.getAttribute("forceAbsoluteUrl") : false; 398 prefix = position == 0 && !absolute ? siteUriPrefix() : aliases[position]; 399 return prefix + resourcePath; 400 401 default: 402 prefix = StringUtils.trimToEmpty((String) request.getAttribute(CmsConstants.PATH_PREFIX_ATTRIBUTE)); 403 return request.getContextPath() + prefix + resourcePath; 404 } 405 } 406 407 /** 408 * Returns the current {@link RenderingContext}. 409 * @return the current {@link RenderingContext}. 410 */ 411 public static String renderingContext() 412 { 413 return _renderingContextHandler.getRenderingContext().toString(); 414 } 415 416 /** 417 * Return the name of the zone beeing handled 418 * @param defaultValue If no page is handled currently, this value is returned (can be null, empty...) 419 * @return the name or the default value (so can be null or empty) 420 */ 421 public static String zone(String defaultValue) 422 { 423 Request request = ContextHelper.getRequest(_context); 424 425 return StringUtils.defaultIfEmpty((String) request.getAttribute(Zone.class.getName()), defaultValue); 426 } 427 428 /** 429 * Return the value of a site parameter as a String. 430 * @param parameter the parameter ID. 431 * @return the parameter value as a String. 432 */ 433 public static String siteParameter(String parameter) 434 { 435 Request request = ContextHelper.getRequest(_context); 436 437 String siteName = (String) request.getAttribute("site"); 438 if (StringUtils.isBlank(siteName)) 439 { 440 // In BO xsl 441 siteName = (String) request.getAttribute("siteName"); 442 } 443 444 return siteParameter(siteName, parameter); 445 } 446 447 /** 448 * Return the value of a site parameter as a String. 449 * @param siteName the site name 450 * @param parameter the parameter ID. 451 * @return the parameter value as a String. 452 */ 453 public static String siteParameter(String siteName, String parameter) 454 { 455 try 456 { 457 Site site = _siteManager.getSite(siteName); 458 Object value = site.getValue(parameter); 459 if (value != null) 460 { 461 return value.toString(); 462 } 463 else 464 { 465 return null; 466 } 467 } 468 catch (Exception e) 469 { 470 String message = "Error retrieving the value of the site parameter " + parameter; 471 _logger.error(message, e); 472 throw new RuntimeException(message, e); 473 } 474 } 475 476 /** 477 * Returns the sitemap' names handled by the current site 478 * @return The available languages 479 */ 480 public static NodeList siteLanguages() 481 { 482 Request request = ContextHelper.getRequest(_context); 483 484 String siteName = (String) request.getAttribute("site"); 485 if (StringUtils.isBlank(siteName)) 486 { 487 // In BO xsl 488 siteName = (String) request.getAttribute("siteName"); 489 } 490 491 return siteLanguages(siteName); 492 } 493 494 /** 495 * Returns the sitemap' names handled by a site 496 * @param siteName The site name 497 * @return The available languages 498 */ 499 public static NodeList siteLanguages(String siteName) 500 { 501 List<StringElement> languages = new ArrayList<>(); 502 503 try 504 { 505 Site site = _siteManager.getSite(siteName); 506 AmetysObjectIterable<Sitemap> sitemaps = site.getSitemaps(); 507 for (Sitemap sitemap : sitemaps) 508 { 509 languages.add(new StringElement("lang", sitemap.getName())); 510 } 511 } 512 catch (Exception e) 513 { 514 String message = "Error retrieving the available languages for the site " + siteName; 515 _logger.error(message, e); 516 throw new RuntimeException(message, e); 517 } 518 519 return new AmetysNodeList(languages); 520 } 521 522 /** 523 * Get the service parameters as a {@link Node}. 524 * @return the service parameters as a {@link Node}. 525 */ 526 public static Node serviceParameters() 527 { 528 ZoneItem zoneItem = _getZoneItemFromRequest(); 529 return _serviceParameters(zoneItem); 530 } 531 532 static Node _serviceParameters(ZoneItem zoneItem) 533 { 534 Map<String, MapNode> values = new HashMap<>(); 535 536 ModelAwareDataHolder dataHolder = zoneItem.getServiceParameters(); 537 String serviceId = zoneItem.getServiceId(); 538 Service service = _serviceEP.getExtension(serviceId); 539 540 for (String parameterName : dataHolder.getDataNames()) 541 { 542 ModelItem modelItem = service.getModelItem(parameterName); 543 values.putAll(_getParameterValue(parameterName, modelItem, dataHolder, null)); 544 } 545 546 return new MapElement("serviceParameters", values); 547 } 548 549 /** 550 * Returns the value of the given parameter for the current service, or the empty string if the parameter does not exist. 551 * @param parameterPath the parameter path. 552 * @return the value of the given parameter for the current service. 553 */ 554 public static Node serviceParameter(String parameterPath) 555 { 556 return serviceParameter(parameterPath, ""); 557 } 558 559 /** 560 * Returns the value of the given parameter for the current service, or the provided default value if the parameter does not exist. 561 * @param parameterPath the parameter path. 562 * @param defaultValue the default value. Note that default value is ignored if the parameter is a composite parameter. 563 * @return the value of the given parameter for the current service. 564 */ 565 public static Node serviceParameter(String parameterPath, Object defaultValue) 566 { 567 ZoneItem zoneItem = _getZoneItemFromRequest(); 568 return _serviceParameter(zoneItem, parameterPath, defaultValue); 569 } 570 571 static Node _serviceParameter(ZoneItem zoneItem, String parameterPath, Object defaultValue) 572 { 573 ModelAwareDataHolder dataHolder = zoneItem.getServiceParameters(); 574 575 String serviceId = zoneItem.getServiceId(); 576 String definitionPath = ModelHelper.getDefinitionPathFromDataPath(parameterPath); 577 578 Service service = _serviceEP.getExtension(serviceId); 579 ModelItem paramDef; 580 if (service.hasModelItem(definitionPath)) 581 { 582 paramDef = service.getModelItem(definitionPath); 583 } 584 else 585 { 586 // The parameter is unknown 587 if (defaultValue == null 588 || defaultValue instanceof String && StringUtils.isEmpty((String) defaultValue)) 589 { 590 return null; 591 } 592 else 593 { 594 return new StringElement(parameterPath, Collections.EMPTY_MAP, defaultValue.toString()); 595 } 596 } 597 598 Map<String, MapNode> value = _getParameterValue(parameterPath, paramDef, dataHolder, defaultValue); 599 600 if (!value.containsKey(parameterPath)) 601 { 602 return null; 603 } 604 else if (paramDef instanceof RepeaterDefinition 605 || paramDef instanceof ElementDefinition && ((ElementDefinition) paramDef).isMultiple()) 606 { 607 MapNode node = value.get(parameterPath); 608 @SuppressWarnings("unchecked") 609 Map<String, ? extends Object> values = (Map<String, ? extends Object>) node.getValue(); 610 return new MapElement(parameterPath, node.getAttributes(), values); 611 } 612 else 613 { 614 return new StringElement(parameterPath, value.get(parameterPath).getAttributes(), (String) value.get(parameterPath).getValue()); 615 } 616 } 617 618 private static String _convertTagName(String name) 619 { 620 char c = name.charAt(0); 621 if (c >= '0' && c <= '9') 622 { 623 String hex = Integer.toHexString(c); 624 return "_x" + StringUtils.leftPad(hex, 4, '0') + "_" + name.substring(1); 625 } 626 else 627 { 628 return name; 629 } 630 } 631 632 @SuppressWarnings("unchecked") 633 private static Map<String, MapNode> _getParameterValue(String parameterPath, ModelItem modelItem, ModelAwareDataHolder dataHolder, Object defaultValue) 634 { 635 String[] pathSegments = StringUtils.split(parameterPath, ModelItem.ITEM_PATH_SEPARATOR); 636 String parameterName = pathSegments[pathSegments.length - 1]; 637 Map<String, MapNode> paramValues = new HashMap<>(); 638 639 if (modelItem instanceof RepeaterDefinition) 640 { 641 if (!dataHolder.hasValue(parameterPath)) 642 { 643 return paramValues; 644 } 645 646 Map<String, String> attributes = new HashMap<>(); 647 attributes.put(__NAME_ATTRIBUTE, parameterName); 648 attributes.put(__TYPE_ATTRIBUTE, ModelItemTypeConstants.REPEATER_TYPE_ID); 649 650 Map<String, Object> children = new HashMap<>(); 651 652 Repeater repeater = dataHolder.getRepeater(parameterPath); 653 for (RepeaterEntry entry : repeater.getEntries()) 654 { 655 Map<String, Object> entryValue = new HashMap<>(); 656 657 for (ModelItem childModelItem : ((RepeaterDefinition) modelItem).getChildren()) 658 { 659 // Default value is ignored if parameter is a repeater 660 Map<String, MapNode> childParamValues = _getParameterValue(childModelItem.getName(), childModelItem, entry, null); 661 entryValue.putAll(childParamValues); 662 } 663 664 Map<String, String> entryAttributes = new HashMap<>(); 665 entryAttributes.put(__NAME_ATTRIBUTE, String.valueOf(entry.getPosition())); 666 entryAttributes.put(__TYPE_ATTRIBUTE, __REPEATER_ENTRY_TYPE); 667 668 MapNode entryNode = new MapNode(entryValue, entryAttributes); 669 children.put(_convertTagName(String.valueOf(entry.getPosition())), entryNode); 670 } 671 672 MapNode node = new MapNode(children, attributes); 673 paramValues.put(parameterPath, node); 674 } 675 else 676 { 677 if (!_hasParameterValueOrDefaultValue(parameterPath, dataHolder, defaultValue)) 678 { 679 return paramValues; 680 } 681 682 Map<String, String> attributes = new HashMap<>(); 683 attributes.put(__NAME_ATTRIBUTE, parameterName); 684 ElementDefinition elementDefinition = (ElementDefinition) modelItem; 685 ElementType elementType = elementDefinition.getType(); 686 attributes.put(__TYPE_ATTRIBUTE, elementType.getId()); 687 688 if (elementDefinition.isMultiple()) 689 { 690 Map<String, List<String>> values = new HashMap<>(); 691 List<String> value = new ArrayList<>(); 692 Object[] valueArray = (Object[]) dataHolder.getValueOrDefault(parameterPath, defaultValue); 693 for (Object arrayItem : valueArray) 694 { 695 value.add(elementType.toString(arrayItem)); 696 } 697 values.put("value", value); 698 699 MapNode node = new MapNode(values, attributes); 700 paramValues.put(parameterPath, node); 701 } 702 else 703 { 704 705 String value = elementType.toString(dataHolder.getValueOrDefault(parameterPath, defaultValue)); 706 MapNode node = new MapNode(value, attributes); 707 paramValues.put(parameterPath, node); 708 } 709 } 710 711 return paramValues; 712 } 713 714 private static boolean _hasParameterValueOrDefaultValue(String parameterPath, ModelAwareDataHolder dataHolder, Object defaultValue) 715 { 716 if (dataHolder.hasValue(parameterPath)) 717 { 718 return true; 719 } 720 else 721 { 722 if (defaultValue != null) 723 { 724 return defaultValue instanceof String ? StringUtils.isNotEmpty((String) defaultValue) : true; 725 } 726 else 727 { 728 return false; 729 } 730 } 731 } 732 733 /** 734 * Returns the current site 735 * @return the current site 736 */ 737 public static String site() 738 { 739 Request request = ContextHelper.getRequest(_context); 740 return (String) request.getAttribute("site"); 741 } 742 743 /** 744 * Returns the current site 745 * @param pageId The identifier ot the page 746 * @return the current site 747 */ 748 public static String site(String pageId) 749 { 750 try 751 { 752 Page page = _getPage(pageId); 753 return page.getSiteName(); 754 } 755 catch (UnknownAmetysObjectException e) 756 { 757 _logger.error("Can not get site on page '" + pageId + "'", e); 758 return ""; 759 } 760 } 761 762 /** 763 * Return the current sitemap as a {@link Node}. 764 * Invisible pages will not be displayed 765 * @return the current sitemap. 766 * @deprecated Use the version with depth argument 767 */ 768 @Deprecated 769 public static Node sitemap() 770 { 771 throw new UnsupportedOperationException("DEPRECATED Use the ametys:sitemap(DEPTH) where DEPTH can be 1 to get root pages, 2 or more to get their children at n levels ; 0 to get only sitemap infos ; -1 to get infinite sitemap (to avoid)"); 772 } 773 774 /** 775 * Return the current sitemap as a {@link Node}. 776 * Invisible pages will not be displayed 777 * @param depth The depth to get. 1 for root pages, -1 for infinite. 778 * @return the current sitemap. 779 */ 780 public static Node sitemap(long depth) 781 { 782 return sitemap(depth, false); 783 } 784 785 /** 786 * Return the current sitemap as a {@link Node}. 787 * @param includeInvisiblePages Should return child invisible pages 788 * @return the current sitemap. 789 * @deprecated Use the version with depth argument 790 */ 791 @Deprecated 792 public static Node sitemap(boolean includeInvisiblePages) 793 { 794 throw new UnsupportedOperationException("DEPRECATED Use the ametys:sitemap(DEPTH, includeInvisiblePages) where DEPTH can be 1 to get root pages, 2 or more to get their children at n levels ; 0 to get only sitemap infos ; -1 to get infinite sitemap (to avoid)"); 795 } 796 797 /** 798 * Return the current sitemap as a {@link Node}. 799 * @param depth The depth to get. 1 for root pages, -1 for infinite. 800 * @param includeInvisiblePages Should return child invisible pages 801 * @return the current sitemap. 802 */ 803 public static Node sitemap(long depth, boolean includeInvisiblePages) 804 { 805 Request request = ContextHelper.getRequest(_context); 806 Sitemap sitemap = (Sitemap) request.getAttribute(Sitemap.class.getName()); 807 808 if (sitemap == null) 809 { 810 // Try to get sitemap from content 811 Content content = (Content) request.getAttribute(Content.class.getName()); 812 if (content instanceof WebContent) 813 { 814 sitemap = ((WebContent) content).getSite().getSitemap(content.getLanguage()); 815 } 816 } 817 818 if (sitemap == null) 819 { 820 return new EmptyElement("sitemap"); 821 } 822 823 Page page = (Page) request.getAttribute(WebConstants.REQUEST_ATTR_PAGE); 824 825 return new org.ametys.web.repository.dom.SitemapElement(sitemap, page != null ? page.getPathInSitemap() : null, _rightManager, _renderingContextHandler, _currentUserProvider.getUser(), depth, includeInvisiblePages, _tagProviderExtPt); 826 } 827 828 /** 829 * Return the subsitemap of the given page as a {@link Node}. 830 * Invisible child pages will not be returned; 831 * @param pageId The root page 832 * @return The page as node. 833 * @deprecated Use the version with depth argument 834 */ 835 @Deprecated 836 public static Node sitemap(String pageId) 837 { 838 throw new UnsupportedOperationException("DEPRECATED Use the ametys:sitemap(pageId, DEPTH) where DEPTH can be 1 (or more) to get page and children at n levels ; 0 to get only this page infos ; -1 to get infinite sitemap (to avoid)"); 839 } 840 841 /** 842 * Return the subsitemap of the given page as a {@link Node}. 843 * Invisible child pages will not be returned; 844 * @param pageId The root page 845 * @param depth The depth to get. 0 for the root page only, 1 for its child pages, -1 for infinite child pages. 846 * @return The page as node. 847 */ 848 public static Node sitemap(String pageId, long depth) 849 { 850 return sitemap(pageId, depth, false); 851 } 852 853 /** 854 * Return the subsitemap of the given page as a {@link Node}. 855 * @param pageId The root page 856 * @param includeInvisiblePages Should return child invisible pages 857 * @return The page as node. 858 */ 859 public static Node sitemap(String pageId, boolean includeInvisiblePages) 860 { 861 return sitemap(pageId, -1, includeInvisiblePages); 862 } 863 864 /** 865 * Return the subsitemap of the given page as a {@link Node}. 866 * @param pageId The root page 867 * @param depth The depth to get. 0 for the root page only, 1 for its child pages, -1 for infinite child pages. 868 * @param includeInvisiblePages Should return child invisible pages 869 * @return The page as node. 870 */ 871 public static Node sitemap(String pageId, long depth, boolean includeInvisiblePages) 872 { 873 Page rootPage = null; 874 try 875 { 876 rootPage = _ametysObjectResolver.resolveById(pageId); 877 } 878 catch (UnknownAmetysObjectException e) 879 { 880 return new EmptyElement("page"); 881 } 882 883 Page page = _getPageFromRequest(); 884 return new PageElement(rootPage, _rightManager, _renderingContextHandler, page != null ? page.getPathInSitemap() : null, _currentUserProvider.getUser(), depth, includeInvisiblePages, _tagProviderExtPt); 885 } 886 887 /** 888 * Computes the breadcrumb of the current page. 889 * @return a NodeList containing all ancestor pages, rooted at the sitemap. 890 */ 891 public static NodeList breadcrumb() 892 { 893 Page page = _getPageFromRequest(); 894 return _breadcrumb(page); 895 } 896 897 /** 898 * Computes the breadcrumb of a given page. 899 * @param pageId The page id 900 * @return a NodeList containing all ancestor pages, rooted at the sitemap. 901 */ 902 public static NodeList breadcrumb(String pageId) 903 { 904 Page page = _ametysObjectResolver.resolveById(pageId); 905 return _breadcrumb(page); 906 } 907 908 private static NodeList _breadcrumb(Page page) 909 { 910 List<Element> result = new ArrayList<>(); 911 912 AmetysObject parent = page.getParent(); 913 while (parent instanceof Page) 914 { 915 Element node = new StringElement("page", (Map<String, String>) null, parent.getId()); 916 result.add(node); 917 parent = parent.getParent(); 918 } 919 920 Collections.reverse(result); 921 return new AmetysNodeList(result); 922 } 923 924 /** 925 * Returns a DOM {@link Element} representing files and folder of the resources explorer, 926 * under the {@link ResourceCollection} corresponding to the given id. 927 * @param collectionId the id of the root {@link ResourceCollection}. 928 * @return an Element containing files and folders. 929 */ 930 public static Node resourcesById(String collectionId) 931 { 932 ResourceCollection collection = _ametysObjectResolver.resolveById(collectionId); 933 return new ResourceCollectionElement(collection); 934 } 935 936 /** 937 * Returns a DOM {@link Element} representing files and folder of the resources explorer, 938 * under the {@link ResourceCollection} corresponding to the given path. <br> 939 * This path is intended to be relative to the current site's resource explorer. 940 * @param path the path of the root {@link ResourceCollection}, relative to the current site's resource explorer. 941 * @return an Element containing files and folders or null if the specified resource does not exist. 942 */ 943 public static Node resourcesByPath(String path) 944 { 945 Request request = ContextHelper.getRequest(_context); 946 String siteName = (String) request.getAttribute("site"); 947 Site site = _siteManager.getSite(siteName); 948 949 try 950 { 951 ResourceCollection collection = site.getRootResources().getChild(path); 952 return new ResourceCollectionElement(collection); 953 } 954 catch (UnknownAmetysObjectException ex) 955 { 956 return null; 957 } 958 } 959 960 /** 961 * Returns a DOM {@link Element} representing a single file of the resources explorer. <br> 962 * This path is intended to be relative to the current site's resource explorer. 963 * @param path the path of the {@link Resource}, relative to the current site's resource explorer. 964 * @return an Element containing a file or null if the specified resource does not exist. 965 */ 966 public static Node resourceByPath(String path) 967 { 968 Request request = ContextHelper.getRequest(_context); 969 String siteName = (String) request.getAttribute("site"); 970 Site site = _siteManager.getSite(siteName); 971 972 try 973 { 974 Resource resource = site.getRootResources().getChild(path); 975 return new ResourceElement(resource, null); 976 } 977 catch (UnknownAmetysObjectException ex) 978 { 979 return null; 980 } 981 } 982 983 /** 984 * Returns a DOM {@link Element} representing files and folder of a skin directory. <br> 985 * This path is intended to be relative to the current skin's 'resources' directory. 986 * @param path the path of the root {@link ResourceCollection}, relative to the current skin's 'resources' directory. Can be a file path to test its existance. 987 * @return an Element containing files and folders. node name is 'collection' or 'resource' with an attribute 'name'. Return null if the path does not exits. 988 * @throws IOException if an error occurred while listing files. 989 */ 990 public static Node skinResources(String path) throws IOException 991 { 992 Source source = _sourceResolver.resolveURI("skin://resources/" + path); 993 if (source.exists()) 994 { 995 return new SourceElement(source); 996 } 997 else 998 { 999 return null; 1000 } 1001 } 1002 1003 //************************* 1004 // Page methods 1005 //************************* 1006 1007 /** 1008 * Get the site name of a page. 1009 * @param pageId The page id. 1010 * @return The name or empty if the page does not exist. 1011 */ 1012 public static String pageSiteName(String pageId) 1013 { 1014 try 1015 { 1016 Page page = _getPage(pageId); 1017 return page.getSiteName(); 1018 } 1019 catch (UnknownAmetysObjectException e) 1020 { 1021 _logger.error("Can not get site name on page with id '" + pageId + "'", e); 1022 return ""; 1023 } 1024 } 1025 1026 /** 1027 * Get the title of a page. 1028 * @param sitename the site name. 1029 * @param lang the sitemap name. 1030 * @param path the page path. 1031 * @return The name or empty if the meta or the page does not exist. 1032 */ 1033 public static String pageTitle(String sitename, String lang, String path) 1034 { 1035 try 1036 { 1037 Page page = _getPage(sitename, lang, path); 1038 return page.getTitle(); 1039 } 1040 catch (UnknownAmetysObjectException e) 1041 { 1042 _logger.warn("Unknown page at path '" + sitename + "/" + lang + "/" + path + "'", e); 1043 return ""; 1044 } 1045 } 1046 1047 /** 1048 * Determines if page exists 1049 * @param sitename the site name. 1050 * @param lang the sitemap name. 1051 * @param path the page path. 1052 * @return <code>false</code> the page does not exist. 1053 */ 1054 public static boolean pageExists(String sitename, String lang, String path) 1055 { 1056 try 1057 { 1058 _getPage(sitename, lang, path); 1059 return true; 1060 } 1061 catch (UnknownAmetysObjectException e) 1062 { 1063 _logger.debug("Page at path '" + sitename + "/" + lang + "/" + path + "' does not exists", e); 1064 return false; 1065 } 1066 } 1067 1068 /** 1069 * Get the title of a page. 1070 * @param pageId The page id. 1071 * @return The name or empty if the meta or the page does not exist. 1072 */ 1073 public static String pageTitle(String pageId) 1074 { 1075 try 1076 { 1077 Page page = _getPage(pageId); 1078 return page.getTitle(); 1079 } 1080 catch (UnknownAmetysObjectException e) 1081 { 1082 _logger.error("Can not get title on page with id '" + pageId + "'", e); 1083 return ""; 1084 } 1085 } 1086 1087 /** 1088 * Get the long title of a page 1089 * @param sitename the site name 1090 * @param lang the page's language 1091 * @param path the page's path 1092 * @return The name or empty if the meta or the page does not exist 1093 */ 1094 public static String pageLongTitle(String sitename, String lang, String path) 1095 { 1096 try 1097 { 1098 Page page = _getPage(sitename, lang, path); 1099 return page.getLongTitle(); 1100 } 1101 catch (UnknownAmetysObjectException e) 1102 { 1103 _logger.error("Can not get long title on page '" + sitename + "/" + lang + "/" + path + "'", e); 1104 return ""; 1105 } 1106 } 1107 /** 1108 * Get the long title of a page 1109 * @param pageId The page id 1110 * @return The name or empty if the meta or the page does not exist 1111 */ 1112 public static String pageLongTitle(String pageId) 1113 { 1114 try 1115 { 1116 Page page = _getPage(pageId); 1117 return page.getLongTitle(); 1118 } 1119 catch (UnknownAmetysObjectException e) 1120 { 1121 _logger.error("Can not get long title on page with id '" + pageId + "'", e); 1122 return ""; 1123 } 1124 } 1125 1126 /** 1127 * Get the type of a page. 1128 * @param pageId The page id. 1129 * @return The type or empty if the page does not exist. 1130 */ 1131 public static String pageType(String pageId) 1132 { 1133 try 1134 { 1135 Page page = _getPage(pageId); 1136 return page.getType().name(); 1137 } 1138 catch (UnknownAmetysObjectException e) 1139 { 1140 _logger.error("Can not get type of page with id '" + pageId + "'", e); 1141 return ""; 1142 } 1143 } 1144 1145 /** 1146 * Get the linked url of a page. 1147 * @param pageId The page id. 1148 * @return The linked url or empty if the page does not exist or if it is not a LINK page 1149 */ 1150 public static String pageUrl(String pageId) 1151 { 1152 try 1153 { 1154 Page page = _getPage(pageId); 1155 return page.getType() == PageType.LINK ? page.getURL() : ""; 1156 } 1157 catch (UnknownAmetysObjectException e) 1158 { 1159 _logger.error("Can not get type of page with id '" + pageId + "'", e); 1160 return ""; 1161 } 1162 } 1163 1164 /** 1165 * Get the linked URL type of a page. 1166 * @param pageId The page id. 1167 * @return The linked URL type or empty if the page does not exist or if it is not a LINK page 1168 */ 1169 public static String pageUrlType(String pageId) 1170 { 1171 try 1172 { 1173 Page page = _getPage(pageId); 1174 return page.getType() == PageType.LINK ? page.getURLType().name() : ""; 1175 } 1176 catch (UnknownAmetysObjectException e) 1177 { 1178 _logger.error("Can not get type of page with id '" + pageId + "'", e); 1179 return ""; 1180 } 1181 } 1182 1183 /** 1184 * Get the data of a page at the given path 1185 * @param sitename the site name 1186 * @param lang the page's language 1187 * @param path the page's path 1188 * @param dataPath The data path (use '/' as separator for composites and repeaters) 1189 * @return The value or empty if the data or the page does not exist 1190 */ 1191 public static String pageMetadata(String sitename, String lang, String path, String dataPath) 1192 { 1193 try 1194 { 1195 Page page = _getPage(sitename, lang, path); 1196 return _getPageData(page, dataPath); 1197 } 1198 catch (UnknownAmetysObjectException e) 1199 { 1200 _logger.error("Can not get data at path '" + dataPath + "' on page '" + sitename + "/" + lang + "/" + path + "'", e); 1201 return StringUtils.EMPTY; 1202 } 1203 } 1204 1205 /** 1206 * Get the data of a page at the given path 1207 * @param pageId The page id 1208 * @param dataPath The data path (use '/' as separator for composites and repeaters) 1209 * @return The value or empty if the data or the page does not exist 1210 */ 1211 public static String pageMetadata(String pageId, String dataPath) 1212 { 1213 try 1214 { 1215 Page page = _getPage(pageId); 1216 return _getPageData(page, dataPath); 1217 } 1218 catch (UnknownAmetysObjectException e) 1219 { 1220 _logger.error("Can not get data at path '" + dataPath + "' on page with id '" + pageId + "'", e); 1221 return StringUtils.EMPTY; 1222 } 1223 } 1224 1225 @SuppressWarnings("unchecked") 1226 private static String _getPageData(Page page, String dataPath) 1227 { 1228 try 1229 { 1230 Object value = page.getValue(dataPath); 1231 if (value != null) 1232 { 1233 ModelItemType type = page.getType(dataPath); 1234 if (type instanceof ElementType) 1235 { 1236 return ((ElementType) type).toString(value); 1237 } 1238 } 1239 1240 _logger.error("Can not get data at path '" + dataPath + "' on page with id '" + page.getId() + "'"); 1241 return StringUtils.EMPTY; 1242 } 1243 catch (Exception e) 1244 { 1245 _logger.error("Can not get data at path '" + dataPath + "' on page with id '" + page.getId() + "'", e); 1246 return StringUtils.EMPTY; 1247 } 1248 } 1249 1250 /** 1251 * Returns true if the given page is visible into navigation elements 1252 * @param pageId the page id. 1253 * @return true if the page is visible 1254 */ 1255 public static boolean pageIsVisible (String pageId) 1256 { 1257 try 1258 { 1259 Page page = _getPage(pageId); 1260 return page.isVisible(); 1261 } 1262 catch (UnknownAmetysObjectException e) 1263 { 1264 _logger.error("Can not get visibility status on page with id '" + pageId + "'", e); 1265 return false; 1266 } 1267 } 1268 1269 /** 1270 * Returns true if the given page is visible into navigation elements 1271 * @param sitename the site name 1272 * @param lang the page's language 1273 * @param path the page's path 1274 * @return true if the page is visible 1275 */ 1276 public static boolean pageIsVisible (String sitename, String lang, String path) 1277 { 1278 try 1279 { 1280 Page page = _getPage(sitename, lang, path); 1281 return page.isVisible(); 1282 } 1283 catch (UnknownAmetysObjectException e) 1284 { 1285 _logger.error("Can not get visibility status on page with id '" + sitename + "/" + lang + "/" + path + "'", e); 1286 return false; 1287 } 1288 } 1289 1290 /** 1291 * Returns true if the given page has restricted access. 1292 * @param pageId the page id. 1293 * @return true if the page exists and has restricted access. 1294 */ 1295 public static boolean pageHasRestrictedAccess(String pageId) 1296 { 1297 try 1298 { 1299 Page page = _getPage(pageId); 1300 return !_rightManager.hasAnonymousReadAccess(page); 1301 } 1302 catch (UnknownAmetysObjectException e) 1303 { 1304 _logger.error("Can not get page access info on page with id '" + pageId + "'", e); 1305 return false; 1306 } 1307 } 1308 1309 /** 1310 * Returns true if the current user has read access on the specified page 1311 * @param pageId Page Id 1312 * @return true if the current user has read access on the specified page 1313 */ 1314 public static boolean hasReadAccessOnPage(String pageId) 1315 { 1316 Page page = _getPage(pageId); 1317 return _rightManager.currentUserHasReadAccess(page); 1318 } 1319 1320 /** 1321 * Returns true if the current user has the specified right on the current page 1322 * @param rightId Right Id 1323 * @return true if the current user has the specified right on the current page 1324 */ 1325 public static boolean hasRightOnPage(String rightId) 1326 { 1327 Page page = _getPageFromRequest(); 1328 return _hasRightOnPage(rightId, page); 1329 } 1330 1331 /** 1332 * Returns true if the current user has the specified right on the specified page 1333 * @param rightId Right Id 1334 * @param pageId Page Id 1335 * @return true if the current user has the specified right on the specified page 1336 */ 1337 public static boolean hasRightOnPage(String rightId, String pageId) 1338 { 1339 Page page = _getPage(pageId); 1340 return _hasRightOnPage(rightId, page); 1341 } 1342 1343 /** 1344 * Returns true if the current user has the specified right on the specified page 1345 * @param rightId Right Id 1346 * @param page Page 1347 * @return true if the current user has the specified right on the specified page 1348 */ 1349 private static boolean _hasRightOnPage(String rightId, Page page) 1350 { 1351 RightResult rightResult = _rightManager.currentUserHasRight(rightId, page); 1352 return rightResult == RightResult.RIGHT_ALLOW; 1353 } 1354 1355 /** 1356 * Returns true if the given page has restricted access. 1357 * @param sitename the site name 1358 * @param lang the page's language 1359 * @param path the page's path 1360 * @return true if the page exists and has restricted access. 1361 */ 1362 public static boolean pageHasRestrictedAccess(String sitename, String lang, String path) 1363 { 1364 try 1365 { 1366 Page page = _getPage(sitename, lang, path); 1367 return !_rightManager.hasAnonymousReadAccess(page); 1368 } 1369 catch (UnknownAmetysObjectException e) 1370 { 1371 _logger.error("Can not get page access info on page with id '" + sitename + "/" + lang + "/" + path + "'", e); 1372 return false; 1373 } 1374 } 1375 1376 private static Page _getPage(String id) 1377 { 1378 return _ametysObjectResolver.resolveById(id); 1379 } 1380 1381 private static Page _getPage(String sitename, String lang, String path) 1382 { 1383 Site site = _siteManager.getSite(sitename); 1384 Sitemap sitemap = site.getSitemap(lang); 1385 return sitemap.getChild(path); 1386 } 1387 1388 private static Page _getPageFromRequest() 1389 { 1390 Request request = ContextHelper.getRequest(_context); 1391 return (Page) request.getAttribute(WebConstants.REQUEST_ATTR_PAGE); 1392 } 1393 1394 /** 1395 * Returns the path of the current page, relative to the sitemap's root. 1396 * @return the path of the current Page, or empty if there's no current page. 1397 */ 1398 public static String pagePath() 1399 { 1400 Page page = _getPageFromRequest(); 1401 return page == null ? "" : page.getPathInSitemap(); 1402 } 1403 1404 /** 1405 * Returns the path in sitemap of a page 1406 * @param pageId The id of page 1407 * @return the path of the Page, or empty if not exists 1408 */ 1409 public static String pagePath(String pageId) 1410 { 1411 try 1412 { 1413 Page page = _getPage(pageId); 1414 return page.getPathInSitemap(); 1415 } 1416 catch (UnknownAmetysObjectException e) 1417 { 1418 _logger.error("Can not get title on page with id '" + pageId + "'", e); 1419 return ""; 1420 } 1421 } 1422 1423 /** 1424 * Returns the id of the current page. 1425 * @return the id of the current Page, or empty if there's no current page. 1426 */ 1427 public static String pageId() 1428 { 1429 Page page = _getPageFromRequest(); 1430 return page == null ? "" : page.getId(); 1431 } 1432 1433 private static Zone _getZone(Page page, String zoneName) 1434 { 1435 if (StringUtils.isNotBlank(zoneName) && page.hasZone(zoneName)) 1436 { 1437 return page.getZone(zoneName); 1438 } 1439 1440 return null; 1441 } 1442 1443 private static Zone _getZoneFromRequest(Page page) 1444 { 1445 Request request = ContextHelper.getRequest(_context); 1446 String currentZoneName = (String) request.getAttribute(WebConstants.REQUEST_ATTR_ZONE_NAME); 1447 if (StringUtils.isNotBlank(currentZoneName) && page.hasZone(currentZoneName)) 1448 { 1449 return page.getZone(currentZoneName); 1450 } 1451 1452 return null; 1453 } 1454 1455 /** 1456 * Returns the id of the current zone item id. 1457 * @return the id of the current zone item id, or empty if there's no current zone item. 1458 */ 1459 public static String zoneItemId() 1460 { 1461 ZoneItem zoneItem = _getZoneItemFromRequest(); 1462 return zoneItem == null ? "" : StringUtils.defaultString(zoneItem.getId()); 1463 } 1464 1465 private static ZoneItem _getZoneItem(String id) 1466 { 1467 return _ametysObjectResolver.resolveById(id); 1468 } 1469 1470 private static ZoneItem _getZoneItemFromRequest() 1471 { 1472 Request request = ContextHelper.getRequest(_context); 1473 return (ZoneItem) request.getAttribute(WebConstants.REQUEST_ATTR_ZONEITEM); 1474 } 1475 1476 private static Content _getContentFromRequest() 1477 { 1478 Request request = ContextHelper.getRequest(_context); 1479 return (Content) request.getAttribute(Content.class.getName()); 1480 } 1481 1482 /** 1483 * Get the position of the current zone item in its zone 1484 * @return the position of the current zone item or -1 if there's no current zone item. 1485 */ 1486 public static int zoneItemPosition() 1487 { 1488 ZoneItem zoneItem = _getZoneItemFromRequest(); 1489 if (zoneItem != null) 1490 { 1491 Zone zone = zoneItem.getZone(); 1492 int index = 1; 1493 1494 AmetysObjectIterable< ? extends ZoneItem> zoneItems = zone.getZoneItems(); 1495 for (ZoneItem childZoneItem : zoneItems) 1496 { 1497 if (childZoneItem.equals(zoneItem)) 1498 { 1499 return index; 1500 } 1501 index++; 1502 } 1503 } 1504 1505 return -1; 1506 } 1507 1508 /** 1509 * Determines if the current zone item or (if there is no current zone item) the current page is cacheable 1510 * This method is only valid for a page. 1511 * @return true if the current zone item or page is cacheable. 1512 */ 1513 public static boolean isCacheable() 1514 { 1515 Request request = ContextHelper.getRequest(_context); 1516 if (request.getAttribute("IsZoneItemCacheable") != null) 1517 { 1518 return (Boolean) request.getAttribute("IsZoneItemCacheable"); 1519 } 1520 1521 // The method was called from the skin, out of a zone item 1522 Response response = ContextHelper.getResponse(_context); 1523 if (response.containsHeader("X-Ametys-Cacheable")) 1524 { 1525 return true; 1526 } 1527 return false; 1528 } 1529 1530 /** 1531 * Determines if we are in an edition mode 1532 * @return true if we are in edition mode 1533 */ 1534 public static boolean isEditionMode() 1535 { 1536 RenderingContext renderingContext = _renderingContextHandler.getRenderingContext(); 1537 Request request = ContextHelper.getRequest(_context); 1538 if (renderingContext == RenderingContext.FRONT && request.getParameter("_edition") != null && "true".equals(request.getParameter("_edition"))) 1539 { 1540 return true; 1541 } 1542 return false; 1543 } 1544 1545 /** 1546 * Determines if a captcha is required on forms of the current page 1547 * @return true if a captcha is required 1548 */ 1549 public static boolean isCaptchaRequired() 1550 { 1551 Page page = _getPageFromRequest(); 1552 return page == null || _pageHelper.isCaptchaRequired(page); 1553 } 1554 1555 /** 1556 * Determines if a captcha is required on forms of the given ametys object 1557 * @param ametysObjectId the ametys object id. Can be a sitemap element or a zone item. 1558 * @return true if a captcha is required 1559 */ 1560 public static boolean isCaptchaRequired(String ametysObjectId) 1561 { 1562 if (StringUtils.isBlank(ametysObjectId)) 1563 { 1564 // The given id is null, so return true for security 1565 return true; 1566 } 1567 1568 AmetysObject ametysObject = _ametysObjectResolver.resolveById(ametysObjectId); 1569 if (ametysObject instanceof SitemapElement sitemapElement) 1570 { 1571 return _pageHelper.isCaptchaRequired(sitemapElement); 1572 } 1573 else if (ametysObject instanceof ZoneItem zoneItem) 1574 { 1575 return _pageHelper.isCaptchaRequired(zoneItem.getZone().getSitemapElement()); 1576 } 1577 1578 // The ametys object is not a sitemap element or a zone item, so return true for security 1579 return true; 1580 } 1581 1582 /** 1583 * Returns the id of pages referencing the content and for which the Front-office user can access 1584 * @param contentId The content's id 1585 * @return The pages' id 1586 */ 1587 public static NodeList accessibleReferencedPages (String contentId) 1588 { 1589 RenderingContext renderingContext = _renderingContextHandler.getRenderingContext(); 1590 boolean inBackOffice = renderingContext == RenderingContext.BACK || renderingContext == RenderingContext.PREVIEW; 1591 1592 List<StringElement> pages = new ArrayList<>(); 1593 1594 Content content = _ametysObjectResolver.resolveById(contentId); 1595 if (content instanceof WebContent) 1596 { 1597 Collection<ZoneItem> zoneItems = ((WebContent) content).getReferencingZoneItems(); 1598 1599 for (ZoneItem zoneItem : zoneItems) 1600 { 1601 String metadataSetName = zoneItem.getViewName(); 1602 SitemapElement sitemapElement = zoneItem.getZone().getSitemapElement(); 1603 1604 if (sitemapElement instanceof Page page 1605 && (inBackOffice || _rightManager.hasReadAccess(_currentUserProvider.getUser(), page))) 1606 { 1607 Map<String, String> attrs = new HashMap<>(); 1608 attrs.put("id", page.getId()); 1609 attrs.put("metadataSetName", metadataSetName); 1610 pages.add(new StringElement("page", attrs)); 1611 } 1612 } 1613 } 1614 1615 return new AmetysNodeList(pages); 1616 } 1617 1618 /** 1619 * Returns the id of pages referencing the content 1620 * @param contentId The content's id 1621 * @return The pages' id 1622 */ 1623 public static NodeList referencedPages (String contentId) 1624 { 1625 List<StringElement> pages = new ArrayList<>(); 1626 1627 Content content = _ametysObjectResolver.resolveById(contentId); 1628 if (content instanceof WebContent) 1629 { 1630 Collection<ZoneItem> zoneItems = ((WebContent) content).getReferencingZoneItems(); 1631 1632 for (ZoneItem zoneItem : zoneItems) 1633 { 1634 String metadataSetName = zoneItem.getViewName(); 1635 SitemapElement sitemapElement = zoneItem.getZone().getSitemapElement(); 1636 1637 if (sitemapElement instanceof Page page) 1638 { 1639 Map<String, String> attrs = new HashMap<>(); 1640 attrs.put("id", page.getId()); 1641 attrs.put("metadataSetName", metadataSetName); 1642 pages.add(new StringElement("page", attrs)); 1643 } 1644 } 1645 } 1646 1647 return new AmetysNodeList(pages); 1648 } 1649 1650 /** 1651 * Returns the ids of the contents 1652 * @param tag The tag id 1653 * @return Array of contents ids 1654 */ 1655 public static NodeList findContentsIdsByTag(String tag) 1656 { 1657 Request request = ContextHelper.getRequest(_context); 1658 String siteName = (String) request.getAttribute("site"); 1659 1660 String lang = (String) request.getAttribute("sitemapLanguage"); 1661 if (lang == null) 1662 { 1663 // Try to get current language from content 1664 Content content = (Content) request.getAttribute(Content.class.getName()); 1665 if (content != null) 1666 { 1667 lang = content.getLanguage(); 1668 } 1669 } 1670 return findContentsIdsByTag(siteName, lang, tag); 1671 } 1672 1673 /** 1674 * Returns the ids of the contents 1675 * @param sitename site name. '+' for any site, '*'/null for any site, including contents without site, '^' for only contents without site 1676 * @param lang lang of the contents 1677 * @param tag The tag id 1678 * @return Array of contents ids 1679 */ 1680 public static NodeList findContentsIdsByTag(String sitename, String lang, String tag) 1681 { 1682 List<Expression> expressions = new ArrayList<>(); 1683 TagExpression tagExpression = new TagExpression(Operator.EQ, tag); 1684 expressions.add(tagExpression); 1685 1686 if (lang != null && !lang.equals("*")) 1687 { 1688 LanguageExpression le = new LanguageExpression(Operator.EQ, lang); 1689 expressions.add(le); 1690 } 1691 1692 if (sitename != null) 1693 { 1694 ExpressionContext siteExpressionContext = ExpressionContext.newInstance().withInternal(true); 1695 if (sitename.equals("+")) 1696 { 1697 MetadataExpression me = new MetadataExpression("site", siteExpressionContext); 1698 expressions.add(me); 1699 } 1700 else if (sitename.equals("*")) 1701 { 1702 // no filter 1703 } 1704 else if (sitename.equals("^")) 1705 { 1706 MetadataExpression me = new MetadataExpression("site", siteExpressionContext); 1707 expressions.add(new NotExpression(me)); 1708 } 1709 else 1710 { 1711 StringExpression se = new StringExpression("site", Operator.EQ, sitename, siteExpressionContext); 1712 expressions.add(se); 1713 } 1714 } 1715 1716 Expression[] expressionsArray = expressions.toArray(new Expression[expressions.size()]); 1717 1718 String xpath = ContentQueryHelper.getContentXPathQuery(new AndExpression(expressionsArray)); 1719 AmetysObjectIterable<Content> contents = _ametysObjectResolver.query(xpath); 1720 Iterator<Content> it = contents.iterator(); 1721 1722 List<StringElement> list = new ArrayList<>(); 1723 while (it.hasNext()) 1724 { 1725 list.add(new StringElement("content", "id", it.next().getId())); 1726 } 1727 return new AmetysNodeList(list); 1728 } 1729 1730 /** 1731 * Returns the ids of the pages tagged with the specified tag 1732 * @param sitename The site id 1733 * @param lang The language code 1734 * @param tag The tag id 1735 * @return Array of pages ids 1736 */ 1737 public static NodeList findPagesIdsByTag(String sitename, String lang, String tag) 1738 { 1739 return findPagesIdsByTag(sitename, lang, tag, false); 1740 } 1741 1742 /** 1743 * Returns the ids of the pages tagged with the specified tag 1744 * @param sitename The site id 1745 * @param lang The language code 1746 * @param tag The tag id 1747 * @param checkReadAccess true to return only pages with read access for current user 1748 * @return Array of pages ids 1749 */ 1750 public static NodeList findPagesIdsByTag(String sitename, String lang, String tag, boolean checkReadAccess) 1751 { 1752 List<StringElement> list = new ArrayList<>(); 1753 for (String pageId : _pageDAO.findPagedIdsByTag(sitename, lang, tag)) 1754 { 1755 if (!checkReadAccess || _hasReadAccess(pageId)) 1756 { 1757 list.add(new StringElement("page", "id", pageId)); 1758 } 1759 } 1760 1761 return new AmetysNodeList(list); 1762 } 1763 1764 private static boolean _hasReadAccess(String pageId) 1765 { 1766 try 1767 { 1768 Page page = _ametysObjectResolver.resolveById(pageId); 1769 return _rightManager.currentUserHasReadAccess(page); 1770 } 1771 catch (UnknownAmetysObjectException e) 1772 { 1773 return false; 1774 } 1775 } 1776 1777 /** 1778 * Returns the ids of the pages tagged with the specified tag 1779 * @param tag The tag id 1780 * @return Array of pages ids 1781 */ 1782 public static NodeList findPagesIdsByTag(String tag) 1783 { 1784 return findPagesIdsByTag(tag, false); 1785 } 1786 1787 /** 1788 * Returns the ids of the pages tagged with the specified tag 1789 * @param tag The tag id 1790 * @param checkReadAccess true to return only pages with read access for current user 1791 * @return Array of pages ids 1792 */ 1793 public static NodeList findPagesIdsByTag(String tag, boolean checkReadAccess) 1794 { 1795 Request request = ContextHelper.getRequest(_context); 1796 String siteName = (String) request.getAttribute("site"); 1797 1798 String lang = (String) request.getAttribute("sitemapLanguage"); 1799 if (lang == null) 1800 { 1801 // Try to get current language from content 1802 Content content = (Content) request.getAttribute(Content.class.getName()); 1803 if (content != null) 1804 { 1805 lang = content.getLanguage(); 1806 } 1807 } 1808 1809 return findPagesIdsByTag(siteName, lang, tag, checkReadAccess); 1810 } 1811 1812 1813 /** 1814 * Return the given user by its email over all authorized population on current site 1815 * @param email the concerned user's email 1816 * @return The informations about the given user 1817 * @throws SAXException If an error occurred while saxing the user 1818 */ 1819 public static Node userByMail(String email) throws SAXException 1820 { 1821 String siteName = site(); 1822 1823 Set<String> userPopulationsOnSite = _populationContextHelper.getUserPopulationsOnContexts(Arrays.asList("/sites/" + siteName, "/sites-fo/" + siteName), false, false); 1824 1825 for (String populationId : userPopulationsOnSite) 1826 { 1827 Node user = userByMail(email, populationId); 1828 if (user != null) 1829 { 1830 return user; 1831 } 1832 } 1833 1834 return null; 1835 } 1836 1837 /** 1838 * Get the preview of a url (title, description, image, favico) 1839 * @param url the web link 1840 * @return the url preview 1841 * @throws SAXException If an error occurred while saxing 1842 */ 1843 public static Node urlPreview(String url) throws SAXException 1844 { 1845 try 1846 { 1847 String lang = StringUtils.defaultIfEmpty(lang(), "en"); 1848 UrlPreview urlPreview = _urlPreview.getUrlPreview(url, lang); 1849 DOMBuilder domBuilder = new DOMBuilder(); 1850 1851 urlPreview.toSAX(domBuilder, "preview"); 1852 1853 return domBuilder.getDocument(); 1854 } 1855 catch (IOException e) 1856 { 1857 _logger.error("Unable to get preview URL at " + url, e); 1858 return null; 1859 } 1860 } 1861 1862 /** 1863 * Generates a XML structure to help to creates a complex pagination. 1864 * <br> 1865 * <br>Example: pagination(39, 19, 2, 5, 2) will return 1866 * 1867 * <pre> 1868 * <gotofirstpage enabled="true">1</gotofirstpage> 1869 * <gotopreviouspage enabled="true">18</gotopreviouspage> 1870 * <page>1</page> 1871 * <page>2</page> 1872 * <separator/> 1873 * <page>17</page> 1874 * <page>18</page> 1875 * <current>19</current> 1876 * <page>20</page> 1877 * <page>21</page> 1878 * <separator/> 1879 * <page>38</page> 1880 * <page>39</page> 1881 * <gotonextpage enabled="true">20</gotonextpage> 1882 * <gotolastpage enabled="true">39</gotonextpage> 1883 * </pre> 1884 * 1885 * Example: pagination(5, 2, 2, 5, 2) will return 1886 * 1887 * <pre> 1888 * <gotofirstpage enabled="true">1</gotofirstpage> 1889 * <gotopreviouspage enabled="true">1</gotopreviouspage> 1890 * <page>1</page> 1891 * <current>2</page> 1892 * <page>3</page> 1893 * <page>4</page> 1894 * <page>5</page> 1895 * <space/> 1896 * <space/> 1897 * <space/> 1898 * <space/> 1899 * <gotonextpage enabled="true">3</gotonextpage> 1900 * <gotolastpage enabled="true">5</gotonextpage> 1901 * </pre> 1902 * 1903 * @param nbPages The total number of pages 1904 * @param currentPage The currently displayed page (1 based) 1905 * @param nbFirstPages The max number of pages to display before the 1st separator 1906 * @param nbCentralPages The max number of pages to display around the current page 1907 * @param nbLastPages The max number of pages to display after the 2nd separator 1908 * @return The xml described 1909 */ 1910 public static AmetysNodeList pagination(int nbPages, int currentPage, int nbFirstPages, int nbCentralPages, int nbLastPages) 1911 { 1912 List<Node> elements = new ArrayList<>(); 1913 1914 1915 elements.add(new StringElement("gotofirstpage", "enabled", Boolean.toString(currentPage > 1), "1")); 1916 elements.add(new StringElement("gotopreviouspage", "enabled", Boolean.toString(currentPage > 1), currentPage > 1 ? currentPage - 1 + "" : "")); 1917 1918 int[] pagination = _pagination(nbPages, currentPage, nbFirstPages, nbCentralPages, nbLastPages); 1919 for (int page : pagination) 1920 { 1921 if (page == _PAGINATION_SEPARATOR) 1922 { 1923 elements.add(new StringElement("separator", "")); 1924 } 1925 else if (page == _PAGINATION_SPACE) 1926 { 1927 elements.add(new StringElement("space", "")); 1928 } 1929 else if (page == _PAGINATION_CURRENT) 1930 { 1931 elements.add(new StringElement("current", Integer.toString(currentPage))); 1932 } 1933 else 1934 { 1935 elements.add(new StringElement("page", Integer.toString(page))); 1936 } 1937 } 1938 1939 elements.add(new StringElement("gotonextpage", "enabled", Boolean.toString(currentPage < nbPages), currentPage < nbPages ? currentPage + 1 + "" : "")); 1940 elements.add(new StringElement("gotolastpage", "enabled", Boolean.toString(currentPage < nbPages), nbPages + "")); 1941 1942 return new AmetysNodeList(elements); 1943 } 1944 1945 static int[] _pagination(int nbPages, int currentPage, int nbFirstPages, int nbCentralPages, int nbLastPages) 1946 { 1947 int displayedPages = nbFirstPages + 1 + nbCentralPages + 1 + nbLastPages; // The +1 are the room for separators 1948 1949 int[] values = new int[displayedPages]; 1950 1951 int centerOfCentralPages = (int) Math.ceil(nbCentralPages / 2.0); 1952 int centralCursor = nbFirstPages + 1 + centerOfCentralPages; 1953 boolean firstSeparator = nbPages > displayedPages && currentPage > centralCursor; 1954 boolean secondSeparator = nbPages > displayedPages && currentPage <= nbPages - centralCursor; 1955 1956 int cursor = 1; 1957 1958 // Before first separator 1959 cursor = _paginationFirstPages(nbPages, nbFirstPages, currentPage, values, cursor); 1960 1961 // First separator 1962 cursor = _paginationFirstSeparator(nbPages, firstSeparator, currentPage, values, cursor); 1963 1964 int offset = _paginationComputeOffsetAfterFirstSeparator(nbPages, currentPage, nbCentralPages, nbLastPages, centerOfCentralPages, firstSeparator, secondSeparator, cursor); 1965 1966 // Middle part 1967 cursor = _paginationMiddle(nbPages, currentPage, nbFirstPages, nbCentralPages, values, cursor, offset); 1968 1969 // Second separator 1970 cursor = _paginationSecondSeparator(nbPages, secondSeparator, currentPage, nbLastPages, values, cursor, offset); 1971 1972 // After second separator 1973 cursor = _paginationLastPages(nbPages, currentPage, displayedPages, values, cursor, offset); 1974 1975 return values; 1976 } 1977 1978 private static int _paginationMiddle(int nbPages, int currentPage, int nbFirstPages, int nbCentralPages, int[] values, int cursorP, int offset) 1979 { 1980 int cursor = cursorP; 1981 for (; cursor <= nbFirstPages + 1 + nbCentralPages; cursor++) 1982 { 1983 if (cursor + offset > nbPages) 1984 { 1985 values[cursor - 1] = _PAGINATION_SPACE; 1986 } 1987 else if (cursor + offset == currentPage) 1988 { 1989 values[cursor - 1] = _PAGINATION_CURRENT; 1990 } 1991 else 1992 { 1993 values[cursor - 1] = offset + cursor; 1994 } 1995 } 1996 return cursor; 1997 } 1998 1999 private static int _paginationComputeOffsetAfterFirstSeparator(int nbPages, int currentPage, int nbCentralPages, int nbLastPages, int centerOfCentralPages, boolean firstSeparator, boolean secondSeparator, int cursor) 2000 { 2001 if (!firstSeparator) 2002 { 2003 return 0; 2004 } 2005 else if (!secondSeparator) 2006 { 2007 return nbPages - nbLastPages - nbCentralPages - cursor; 2008 } 2009 else 2010 { 2011 return currentPage + 1 - centerOfCentralPages - cursor; 2012 } 2013 } 2014 2015 private static int _paginationLastPages(int nbPages, int currentPage, int displayedPages, int[] values, int cursorP, int offset) 2016 { 2017 int cursor = cursorP; 2018 for (; cursor <= displayedPages; cursor++) 2019 { 2020 if (cursor > nbPages) 2021 { 2022 values[cursor - 1] = _PAGINATION_SPACE; 2023 } 2024 else if (cursor + offset == currentPage) 2025 { 2026 values[cursor - 1] = _PAGINATION_CURRENT; 2027 } 2028 else 2029 { 2030 values[cursor - 1] = nbPages - (displayedPages - cursor); 2031 } 2032 } 2033 return cursor; 2034 } 2035 2036 private static int _paginationSecondSeparator(int nbPages, boolean secondSeparator, int currentPage, int nbLastPages, int[] values, int cursor, int offset) 2037 { 2038 if (cursor + offset > nbPages) 2039 { 2040 values[cursor - 1] = _PAGINATION_SPACE; 2041 } 2042 else if (currentPage == cursor + offset) 2043 { 2044 values[cursor - 1] = _PAGINATION_CURRENT; 2045 } 2046 else if (secondSeparator) 2047 { 2048 values[cursor - 1] = _PAGINATION_SEPARATOR; 2049 } 2050 else 2051 { 2052 values[cursor - 1] = nbPages - nbLastPages; 2053 } 2054 return cursor + 1; 2055 } 2056 2057 private static int _paginationFirstSeparator(int nbPages, boolean firstSeparator, int currentPage, int[] values, int cursor) 2058 { 2059 if (cursor > nbPages) 2060 { 2061 values[cursor - 1] = _PAGINATION_SPACE; 2062 } 2063 else if (currentPage == cursor) 2064 { 2065 values[cursor - 1] = _PAGINATION_CURRENT; 2066 } 2067 else if (firstSeparator) 2068 { 2069 values[cursor - 1] = _PAGINATION_SEPARATOR; 2070 } 2071 else 2072 { 2073 values[cursor - 1] = cursor; 2074 } 2075 return cursor + 1; 2076 } 2077 2078 private static int _paginationFirstPages(int nbPages, int nbFirstPages, int currentPage, int[] values, int cursorP) 2079 { 2080 int cursor = cursorP; 2081 for (; cursor <= nbFirstPages; cursor++) 2082 { 2083 if (cursor > nbPages) 2084 { 2085 values[cursor - 1] = _PAGINATION_SPACE; 2086 } 2087 else if (cursor == currentPage) 2088 { 2089 values[cursor - 1] = _PAGINATION_CURRENT; 2090 } 2091 else 2092 { 2093 values[cursor - 1] = cursor; 2094 } 2095 } 2096 return cursor; 2097 } 2098 2099 /** 2100 * Get the parameters' values of the current template 2101 * @return the values of template's parameters 2102 */ 2103 public static Node templateParameters() 2104 { 2105 Map<String, MapNode> parameters = new HashMap<>(); 2106 2107 Page page = _getPageFromRequest(); 2108 if (page != null) 2109 { 2110 Optional<ViewParametersModel> viewParametersModelOptional = _viewParametersManager.getTemplateViewParametersModel(page.getSite().getSkinId(), page.getTemplate()); 2111 if (viewParametersModelOptional.isPresent()) 2112 { 2113 ViewParametersModel viewParametersModel = viewParametersModelOptional.get(); 2114 2115 Collection< ? extends ModelItem> modelItems = viewParametersModel.getModelItems(); 2116 for (ModelItem modelItem : modelItems) 2117 { 2118 Optional<ViewParameterHolder> templateParameterHolderOptional = _viewParametersManager.getTemplateViewParameterHolderWithInheritance(page, modelItem); 2119 if (templateParameterHolderOptional.isPresent()) 2120 { 2121 ViewParameterHolder templateParameterHolder = templateParameterHolderOptional.get(); 2122 Map<String, MapNode> values = _getParameterValue(templateParameterHolder.getPath(), modelItem, templateParameterHolder.getDataHolder(), null); 2123 if (values != null) 2124 { 2125 parameters.putAll(values); 2126 } 2127 } 2128 } 2129 } 2130 } 2131 2132 return new MapElement("templateParameters", parameters); 2133 } 2134 2135 /** 2136 * Returns the value of the given parameter for the current page template, or the empty node if the parameter does not exist. 2137 * @param parameterPath the parameter path. 2138 * @return the value of the given parameter for the current page template. 2139 */ 2140 public static NodeList templateParameter(String parameterPath) 2141 { 2142 return templateParameter(null, parameterPath); 2143 } 2144 2145 /** 2146 * Returns the value of the given parameter for the given page template, or the empty node if the parameter does not exist. 2147 * @param pageId the page id 2148 * @param parameterPath the parameter path. 2149 * @return the value of the given parameter for the given page template. 2150 */ 2151 public static NodeList templateParameter(String pageId, String parameterPath) 2152 { 2153 Page page = StringUtils.isNotBlank(pageId) ? _getPage(pageId) : _getPageFromRequest(); 2154 if (page != null) 2155 { 2156 Optional<ViewParameterHolder> templateParameterHolderOptional = _viewParametersManager.getTemplateViewParameterHolderWithInheritance(page, parameterPath); 2157 if (templateParameterHolderOptional.isPresent()) 2158 { 2159 ViewParameterHolder templateParameterHolder = templateParameterHolderOptional.get(); 2160 List<Node> values = _getNodeValues(templateParameterHolder.getDataHolder(), templateParameterHolder.getPath(), null); 2161 if (values != null) 2162 { 2163 return new AmetysNodeList(values); 2164 } 2165 } 2166 } 2167 2168 return null; 2169 } 2170 2171 /** 2172 * Get the parameters of the current zone 2173 * @return the zone's parameters 2174 */ 2175 public static Node zoneParameters() 2176 { 2177 return zoneParameters(null); 2178 } 2179 2180 /** 2181 * Get the parameters of a given zone 2182 * @param zoneName The zone's name. Can be null or empty to get the current zone. 2183 * @return the zone's parameters 2184 */ 2185 public static Node zoneParameters(String zoneName) 2186 { 2187 Map<String, MapNode> parameters = new HashMap<>(); 2188 2189 Page page = _getPageFromRequest(); 2190 if (page != null) 2191 { 2192 Zone zone = _getZoneForParameter(page, zoneName); 2193 if (zone != null) 2194 { 2195 Optional<ViewParametersModel> viewParametersModelOptional = _viewParametersManager.getZoneViewParametersModel(page.getSite().getSkinId(), page.getTemplate(), zone.getName()); 2196 if (viewParametersModelOptional.isPresent()) 2197 { 2198 ViewParametersModel viewParametersModel = viewParametersModelOptional.get(); 2199 2200 Collection< ? extends ModelItem> modelItems = viewParametersModel.getModelItems(); 2201 for (ModelItem modelItem : modelItems) 2202 { 2203 Optional<ViewParameterHolder> zoneParameterHolderOptional = _viewParametersManager.getZoneViewParameterHolderWithInheritance(page, zone, modelItem); 2204 if (zoneParameterHolderOptional.isPresent()) 2205 { 2206 ViewParameterHolder zoneParameterHolder = zoneParameterHolderOptional.get(); 2207 Map<String, MapNode> values = _getParameterValue(zoneParameterHolder.getPath(), modelItem, zoneParameterHolder.getDataHolder(), null); 2208 if (values != null) 2209 { 2210 parameters.putAll(values); 2211 } 2212 } 2213 } 2214 } 2215 } 2216 } 2217 2218 return new MapElement("zoneParameters", parameters); 2219 } 2220 2221 /** 2222 * Returns the value of the given parameter for the current page and current zone, or the empty node if the parameter does not exist. 2223 * @param parameterPath the parameter path. 2224 * @return the value of the given parameter for the current page and current zone. 2225 */ 2226 public static NodeList zoneParameter(String parameterPath) 2227 { 2228 return zoneParameter(null, null, parameterPath); 2229 } 2230 2231 /** 2232 * Returns the value of the given parameter for the current page and given zone, or the empty node if the parameter does not exist. 2233 * @param zoneName the zone name 2234 * @param parameterPath the parameter path. 2235 * @return the value of the given parameter for the current page and given zone. 2236 */ 2237 public static NodeList zoneParameter(String zoneName, String parameterPath) 2238 { 2239 return zoneParameter(null, zoneName, parameterPath); 2240 } 2241 2242 /** 2243 * Returns the value of the given parameter for the given page and given zone name, or the empty node if the parameter does not exist. 2244 * @param pageId the page id 2245 * @param zoneName the zone name 2246 * @param parameterPath the parameter path. 2247 * @return the value of the given parameter for the given page and given zone name. 2248 */ 2249 public static NodeList zoneParameter(String pageId, String zoneName, String parameterPath) 2250 { 2251 Page page = StringUtils.isNotBlank(pageId) ? _getPage(pageId) : _getPageFromRequest(); 2252 if (page != null) 2253 { 2254 Zone zone = _getZoneForParameter(page, zoneName); 2255 if (zone != null) 2256 { 2257 Optional<ViewParameterHolder> zoneParameterHolderOptional = _viewParametersManager.getZoneViewParameterHolderWithInheritance(page, zone, parameterPath); 2258 if (zoneParameterHolderOptional.isPresent()) 2259 { 2260 ViewParameterHolder zoneParameterHolder = zoneParameterHolderOptional.get(); 2261 List<Node> values = _getNodeValues(zoneParameterHolder.getDataHolder(), zoneParameterHolder.getPath(), null); 2262 if (values != null) 2263 { 2264 return new AmetysNodeList(values); 2265 } 2266 } 2267 } 2268 } 2269 2270 return null; 2271 } 2272 2273 /** 2274 * Get the parameters of the current zone item 2275 * @return the zone items's parameters 2276 */ 2277 public static Node zoneItemParameters() 2278 { 2279 return zoneItemParameters(null); 2280 } 2281 2282 /** 2283 * Get the parameters of a given zone item 2284 * @param zoneItemId The id of zone item. Can be null or empty to get the current zone item 2285 * @return the zone items's parameters 2286 */ 2287 public static Node zoneItemParameters(String zoneItemId) 2288 { 2289 Map<String, MapNode> parameters = new HashMap<>(); 2290 2291 ZoneItem zoneItem = StringUtils.isNotBlank(zoneItemId) ? _getZoneItem(zoneItemId) : _getZoneItemFromRequest(); 2292 if (zoneItem != null) 2293 { 2294 Optional<ViewParametersModel> viewParametersModelOptional = _viewParametersManager.getZoneItemViewParametersModel(zoneItem); 2295 if (viewParametersModelOptional.isPresent()) 2296 { 2297 Collection< ? extends ModelItem> modelItems = viewParametersModelOptional.get().getModelItems(); 2298 for (ModelItem modelItem : modelItems) 2299 { 2300 Map<String, MapNode> values = _getParameterValue(modelItem.getPath(), modelItem, zoneItem.getZoneItemParametersHolder(), null); 2301 if (values != null) 2302 { 2303 parameters.putAll(values); 2304 } 2305 } 2306 } 2307 } 2308 2309 return new MapElement("zoneItemParameters", parameters); 2310 } 2311 2312 /** 2313 * Returns the value of the given parameter for the current zone item, or the empty node if the parameter does not exist. 2314 * @param parameterPath the parameter path. 2315 * @return the value of the given parameter for the current zone item. 2316 */ 2317 public static NodeList zoneItemParameter(String parameterPath) 2318 { 2319 return zoneItemParameter(null, parameterPath); 2320 } 2321 2322 /** 2323 * Returns the value of the given parameter for the given zone item, or the empty node if the parameter does not exist. 2324 * @param zoneItemId the zone item id 2325 * @param parameterPath the parameter path. 2326 * @return the value of the given parameter for the given zone item. 2327 */ 2328 public static NodeList zoneItemParameter(String zoneItemId, String parameterPath) 2329 { 2330 ZoneItem zoneItem = StringUtils.isNotBlank(zoneItemId) ? _getZoneItem(zoneItemId) : _getZoneItemFromRequest(); 2331 if (zoneItem != null) 2332 { 2333 ModelAwareDataHolder dataHolder = zoneItem.getZoneItemParametersHolder(); 2334 List<Node> values = _getNodeValues(dataHolder, parameterPath, null); 2335 if (values != null) 2336 { 2337 return new AmetysNodeList(values); 2338 } 2339 } 2340 2341 return null; 2342 } 2343 2344 /** 2345 * Get the parameters of the current service 2346 * @return the service's parameters 2347 */ 2348 public static Node serviceViewParameters() 2349 { 2350 Map<String, MapNode> parameters = new HashMap<>(); 2351 2352 ZoneItem zoneItem = _getZoneItemFromRequest(); 2353 if (zoneItem != null) 2354 { 2355 if (zoneItem.getType() == ZoneType.SERVICE) 2356 { 2357 Optional<ViewParametersModel> serviceViewParametersModel = _viewParametersManager.getServiceViewParametersModel(zoneItem); 2358 if (serviceViewParametersModel.isPresent()) 2359 { 2360 String viewName = zoneItem.getServiceParameters().getValue(ViewParametersManager.SERVICE_VIEW_DEFAULT_MODEL_ITEM_NAME); 2361 2362 Collection< ? extends ModelItem> modelItems = serviceViewParametersModel.get().getModelItems(); 2363 for (ModelItem modelItem : modelItems) 2364 { 2365 Map<String, MapNode> values = _getParameterValue(modelItem.getPath(), modelItem, zoneItem.getServiceViewParametersHolder(viewName), null); 2366 if (values != null) 2367 { 2368 parameters.putAll(values); 2369 } 2370 } 2371 } 2372 } 2373 } 2374 2375 return new MapElement("serviceViewParameters", parameters); 2376 } 2377 2378 /** 2379 * Returns the value of the given parameter for the current service, or the empty node if the parameter does not exist. 2380 * @param parameterPath the parameter path. 2381 * @return the value of the given parameter for the current service. 2382 */ 2383 public static NodeList serviceViewParameter(String parameterPath) 2384 { 2385 ZoneItem zoneItem = _getZoneItemFromRequest(); 2386 if (zoneItem != null) 2387 { 2388 if (zoneItem.getType() == ZoneType.SERVICE) 2389 { 2390 Optional<ModelAwareDataHolder> serviceViewParametersHolder = _viewParametersManager.getServiceViewParametersHolder(zoneItem); 2391 if (serviceViewParametersHolder.isPresent()) 2392 { 2393 List<Node> values = _getNodeValues(serviceViewParametersHolder.get(), parameterPath, null); 2394 if (values != null) 2395 { 2396 return new AmetysNodeList(values); 2397 } 2398 } 2399 } 2400 } 2401 2402 return null; 2403 } 2404 2405 /** 2406 * Get the parameters of the current content 2407 * @return the content's parameters 2408 */ 2409 public static Node contentViewParameters() 2410 { 2411 Map<String, MapNode> parameters = new HashMap<>(); 2412 2413 ZoneItem zoneItem = _getZoneItemFromRequest(); 2414 if (zoneItem != null) 2415 { 2416 if (zoneItem.getType() == ZoneType.CONTENT) 2417 { 2418 Content content = _getContentFromRequest(); 2419 Content zoneItemContent = zoneItem.getContent(); 2420 2421 // Test if the content in the zone item is the same in the request. For example, can have different content if a content call the method AmetysXSLTHelper#getContentView 2422 if (content != null && content.getId().equals(zoneItemContent.getId())) 2423 { 2424 Optional<ViewParametersModel> contentViewParametersModel = _viewParametersManager.getContentViewParametersModel(zoneItem); 2425 if (contentViewParametersModel.isPresent()) 2426 { 2427 String viewName = zoneItem.getViewName(); 2428 Collection< ? extends ModelItem> modelItems = contentViewParametersModel.get().getModelItems(); 2429 for (ModelItem modelItem : modelItems) 2430 { 2431 Map<String, MapNode> values = _getParameterValue(modelItem.getPath(), modelItem, zoneItem.getContentViewParametersHolder(viewName), null); 2432 if (values != null) 2433 { 2434 parameters.putAll(values); 2435 } 2436 } 2437 } 2438 } 2439 } 2440 } 2441 2442 return new MapElement("contentViewParameters", parameters); 2443 } 2444 2445 /** 2446 * Returns the value of the given parameter for the current content, or the empty node if the parameter does not exist. 2447 * @param parameterPath the parameter path. 2448 * @return the value of the given parameter for the current content. 2449 */ 2450 public static NodeList contentViewParameter(String parameterPath) 2451 { 2452 ZoneItem zoneItem = _getZoneItemFromRequest(); 2453 if (zoneItem != null) 2454 { 2455 if (zoneItem.getType() == ZoneType.CONTENT) 2456 { 2457 Content content = _getContentFromRequest(); 2458 Content zoneItemContent = zoneItem.getContent(); 2459 2460 // Test if the content in the zone item is the same in the request. For example, can have different content if a content call the method AmetysXSLTHelper#getContentView 2461 if (content != null && content.getId().equals(zoneItemContent.getId())) 2462 { 2463 Optional<ModelAwareDataHolder> contentViewParametersHolder = _viewParametersManager.getContentViewParametersHolder(zoneItem); 2464 if (contentViewParametersHolder.isPresent()) 2465 { 2466 DataContext context = RepositoryDataContext.newInstance() 2467 .withObject(content); 2468 2469 List<Node> values = _getNodeValues(contentViewParametersHolder.get(), parameterPath, null, context); 2470 if (values != null) 2471 { 2472 return new AmetysNodeList(values); 2473 } 2474 } 2475 } 2476 } 2477 } 2478 2479 return null; 2480 } 2481 2482 private static Zone _getZoneForParameter(Page page, String zoneName) 2483 { 2484 Zone zone = _getZone(page, zoneName); 2485 if (zone == null) 2486 { 2487 zone = _getZoneFromRequest(page); 2488 if (zone == null) 2489 { 2490 ZoneItem zoneItem = _getZoneItemFromRequest(); 2491 if (zoneItem != null) 2492 { 2493 zone = zoneItem.getZone(); 2494 } 2495 } 2496 } 2497 2498 return zone; 2499 } 2500}