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