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