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.ModelAwareRepeater; 070import org.ametys.plugins.repository.data.holder.group.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.cache.PageHelper; 088import org.ametys.web.parameters.view.ViewParametersManager; 089import org.ametys.web.parameters.view.ViewParametersManager.ViewParameterHolder; 090import org.ametys.web.parameters.view.ViewParametersModel; 091import org.ametys.web.renderingcontext.RenderingContext; 092import org.ametys.web.renderingcontext.RenderingContextHandler; 093import org.ametys.web.repository.content.WebContent; 094import org.ametys.web.repository.dom.PageElement; 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.SitemapElement; 099import org.ametys.web.repository.page.Zone; 100import org.ametys.web.repository.page.ZoneItem; 101import org.ametys.web.repository.page.ZoneItem.ZoneType; 102import org.ametys.web.repository.site.Site; 103import org.ametys.web.repository.site.SiteManager; 104import org.ametys.web.repository.sitemap.Sitemap; 105import org.ametys.web.service.Service; 106import org.ametys.web.service.ServiceExtensionPoint; 107import org.ametys.web.skin.SkinsManager; 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 private static SkinsManager _skinsManager; 134 private static PageHelper _pageHelper; 135 136 @Override 137 public void service(ServiceManager manager) throws ServiceException 138 { 139 _siteManager = (SiteManager) manager.lookup(SiteManager.ROLE); 140 _pageDAO = (PageDAO) manager.lookup(PageDAO.ROLE); 141 _renderingContextHandler = (RenderingContextHandler) manager.lookup(RenderingContextHandler.ROLE); 142 _ametysObjectResolver = (AmetysObjectResolver) manager.lookup(AmetysObjectResolver.ROLE); 143 _i18nUtils = (I18nUtils) manager.lookup(I18nUtils.ROLE); 144 _prefixHandler = (URIPrefixHandler) manager.lookup(URIPrefixHandler.ROLE); 145 _serviceEP = (ServiceExtensionPoint) manager.lookup(ServiceExtensionPoint.ROLE); 146 _populationContextHelper = (PopulationContextHelper) manager.lookup(PopulationContextHelper.ROLE); 147 _urlPreview = (UrlPreviewComponent) manager.lookup(UrlPreviewComponent.ROLE); 148 _viewParametersManager = (ViewParametersManager) manager.lookup(ViewParametersManager.ROLE); 149 _skinsManager = (SkinsManager) manager.lookup(SkinsManager.ROLE); 150 _pageHelper = (PageHelper) manager.lookup(PageHelper.ROLE); 151 } 152 153 /** 154 * Returns the current URI prefix, depending on the rendering context. 155 * @return the current URI prefix. 156 */ 157 public static String uriPrefix() 158 { 159 return _prefixHandler.getUriPrefix(); 160 } 161 162 /** 163 * Returns the URI prefix corresponding to the current site, depending on the rendering context. 164 * @return the URI prefix corresponding to the current site. 165 */ 166 public static String siteUriPrefix() 167 { 168 Request request = ContextHelper.getRequest(_context); 169 String siteName = (String) request.getAttribute("site"); 170 return _prefixHandler.getUriPrefix(siteName); 171 } 172 173 /** 174 * Returns the absolute URI prefix, depending on the rendering context. 175 * @return the absolute URI prefix. 176 */ 177 public static String absoluteUriPrefix() 178 { 179 return _prefixHandler.getAbsoluteUriPrefix(); 180 } 181 182 /** 183 * Returns the absolute URI prefix corresponding to the current site, depending on the rendering context. 184 * @return the absolute URI prefix corresponding to the current site. 185 */ 186 public static String absoluteSiteUriPrefix() 187 { 188 Request request = ContextHelper.getRequest(_context); 189 String siteName = (String) request.getAttribute("site"); 190 return _prefixHandler.getAbsoluteUriPrefix(siteName); 191 } 192 193 /** 194 * Returns the absolute URI prefix corresponding to the given site, depending on the rendering context. 195 * @param siteName The site name. Can be null to get the current site. 196 * @return the absolute URI prefix corresponding to the current site. 197 */ 198 public static String absoluteSiteUriPrefix(String siteName) 199 { 200 if (StringUtils.isEmpty(siteName)) 201 { 202 return absoluteSiteUriPrefix(); 203 } 204 return _prefixHandler.getAbsoluteUriPrefix(siteName); 205 } 206 207 /** 208 * Returns the current skin name. 209 * @return the current skin name. 210 */ 211 public static String skin() 212 { 213 return _skinsManager.getSkinNameFromRequest(); 214 } 215 216 /** 217 * Returns the current template name. 218 * @return the current template name. 219 */ 220 public static String template() 221 { 222 Request request = ContextHelper.getRequest(_context); 223 return (String) request.getAttribute("template"); 224 } 225 226 /** 227 * Returns the current sitemap name. 228 * @return the current sitemap name. 229 */ 230 public static String lang() 231 { 232 Request request = ContextHelper.getRequest(_context); 233 return (String) request.getAttribute("sitemapLanguage"); 234 } 235 236 /** 237 * Returns the current sitemap name. 238 * @param pageId The page identifier to get sitemap on 239 * @return the current sitemap name. 240 */ 241 public static String lang(String pageId) 242 { 243 try 244 { 245 Page page = _getPage(pageId); 246 return page.getSitemapName(); 247 } 248 catch (UnknownAmetysObjectException e) 249 { 250 _logger.error("Can not get sitemap lang on page '" + pageId + "'", e); 251 return ""; 252 } 253 } 254 255 /** 256 * Computes the URI for the given resource in the current site's skin.<br> 257 * If the URI is requested by the front-office, it will be absolutized. 258 * @param path the resource path. 259 * @return the URI for the given resource. 260 */ 261 public static String skinURL(String path) 262 { 263 Request request = ContextHelper.getRequest(_context); 264 String siteName = (String) request.getAttribute("site"); 265 Site site = _siteManager.getSite(siteName); 266 String skin = (String) request.getAttribute("skin"); 267 268 String resourcePath = "/skins/" + skin + "/resources/" + path; 269 270 return _getResourceURL(request, site, resourcePath); 271 } 272 273 /** 274 * Computes the URI for the given image with a given heigth and width in the current site's skin.<br> 275 * If the URI is requested by the front-office, it will be absolutized. 276 * @param path the resource path 277 * @param height the height for the resource to get 278 * @param width the width for the resource to get 279 * @return the URI of the given resource 280 */ 281 public static String skinImageURL(String path, int height, int width) 282 { 283 String skinPath = skinURL(path); 284 return StringUtils.substringBeforeLast(skinPath, ".") + "_" + height + "x" + width + "." + StringUtils.substringAfterLast(skinPath, "."); 285 } 286 287 /** 288 * Computes the base 64 representation of the image at the specified path. <br> 289 * @param path the path of the image 290 * @return the base 64-encoded image 291 * @throws IOException if an error occurs while trying to get the file 292 */ 293 public static String skinImageBase64 (String path) throws IOException 294 { 295 Source source = null; 296 try 297 { 298 source = _sourceResolver.resolveURI("skin://resources/" + path); 299 return _getResourceBase64(source); 300 } 301 finally 302 { 303 if (source != null) 304 { 305 _sourceResolver.release(source); 306 } 307 } 308 } 309 310 /** 311 * Computes the URI for the given image with a given heigth and width in the current site's skin.<br> 312 * If the URI is requested by the front-office, it will be absolutized. 313 * @param path the resource path 314 * @param maxHeight the maximum height for the resource to get 315 * @param maxWidth the maximum width for the resource to get 316 * @return the URI of the given resource 317 */ 318 public static String skinBoundedImageURL(String path, int maxHeight, int maxWidth) 319 { 320 String skinPath = skinURL(path); 321 return StringUtils.substringBeforeLast(skinPath, ".") + "_max" + maxHeight + "x" + maxWidth + "." + StringUtils.substringAfterLast(skinPath, "."); 322 } 323 324 /** 325 * Computes the URI for the given resource in the current template.<br> 326 * If the URI is requested by the front-office, it will be absolutized. 327 * @param path the resource path. 328 * @return the URI for the given resource. 329 */ 330 public static String templateURL(String path) 331 { 332 Request request = ContextHelper.getRequest(_context); 333 String siteName = (String) request.getAttribute("site"); 334 Site site = _siteManager.getSite(siteName); 335 String skin = (String) request.getAttribute("skin"); 336 String template = (String) request.getAttribute("template"); 337 338 String resourcePath = "/skins/" + skin + "/templates/" + template + "/resources/" + path; 339 340 return _getResourceURL(request, site, resourcePath); 341 } 342 343 /** 344 * Computes the URI for the given resource in the given plugin.<br> 345 * If the URI is requested by the front-office, it will be absolutized. 346 * @param plugin the plugin name. 347 * @param path the resource path. 348 * @return the URI for the given resource. 349 */ 350 public static String pluginResourceURL(String plugin, String path) 351 { 352 Request request = ContextHelper.getRequest(_context); 353 String siteName = (String) request.getAttribute("site"); 354 Site site = _siteManager.getSite(siteName); 355 356 String resourcePath = "/plugins/" + plugin + "/resources/" + path; 357 358 return _getResourceURL(request, site, resourcePath); 359 } 360 361 /** 362 * Computes the base 64 representation of the image at the specified path in the given plugin. 363 * @param plugin the plugin's name. 364 * @param path the resource path. 365 * @return the base 64 encoding for the given resource. 366 * @throws IOException if an error occurs when trying to get the file 367 * @throws MalformedURLException if the url is invalid 368 */ 369 public static String pluginImageBase64(String plugin, String path) throws MalformedURLException, IOException 370 { 371 Source source = null; 372 try 373 { 374 source = _sourceResolver.resolveURI("plugin:" + plugin + "://resources/" + path); 375 return _getResourceBase64(source); 376 } 377 finally 378 { 379 if (source != null) 380 { 381 _sourceResolver.release(source); 382 } 383 } 384 } 385 386 387 private static String _getResourceURL(Request request, Site site, String resourcePath) 388 { 389 String prefix; 390 switch (_renderingContextHandler.getRenderingContext()) 391 { 392 case FRONT: 393 String[] aliases = site.getUrlAliases(); 394 int position = Math.abs(resourcePath.hashCode()) % aliases.length; 395 396 boolean absolute = request.getAttribute("forceAbsoluteUrl") != null ? (Boolean) request.getAttribute("forceAbsoluteUrl") : false; 397 prefix = position == 0 && !absolute ? siteUriPrefix() : aliases[position]; 398 return prefix + resourcePath; 399 400 default: 401 prefix = StringUtils.trimToEmpty((String) request.getAttribute(CmsConstants.PATH_PREFIX_ATTRIBUTE)); 402 return request.getContextPath() + prefix + resourcePath; 403 } 404 } 405 406 /** 407 * Get the base 64 encoding for the given source 408 * @param source the source 409 * @return the base 64 encoding of the source 410 */ 411 private static String _getResourceBase64(Source source) 412 { 413 if (source.exists()) 414 { 415 416 try (InputStream dataIs = source.getInputStream()) 417 { 418 return ImageResolverHelper.resolveImageAsBase64(dataIs, source.getMimeType(), 0, 0, 0, 0); 419 } 420 catch (Exception e) 421 { 422 throw new IllegalStateException(e); 423 } 424 } 425 426 return ""; 427 } 428 429 /** 430 * Returns the current {@link RenderingContext}. 431 * @return the current {@link RenderingContext}. 432 */ 433 public static String renderingContext() 434 { 435 return _renderingContextHandler.getRenderingContext().toString(); 436 } 437 438 /** 439 * Return the name of the zone beeing handled 440 * @param defaultValue If no page is handled currently, this value is returned (can be null, empty...) 441 * @return the name or the default value (so can be null or empty) 442 */ 443 public static String zone(String defaultValue) 444 { 445 Request request = ContextHelper.getRequest(_context); 446 447 return StringUtils.defaultIfEmpty((String) request.getAttribute(Zone.class.getName()), defaultValue); 448 } 449 450 /** 451 * Return the value of a site parameter as a String. 452 * @param parameter the parameter ID. 453 * @return the parameter value as a String. 454 */ 455 public static String siteParameter(String parameter) 456 { 457 Request request = ContextHelper.getRequest(_context); 458 459 String siteName = (String) request.getAttribute("site"); 460 if (StringUtils.isBlank(siteName)) 461 { 462 // In BO xsl 463 siteName = (String) request.getAttribute("siteName"); 464 } 465 466 return siteParameter(siteName, parameter); 467 } 468 469 /** 470 * Return the value of a site parameter as a String. 471 * @param siteName the site name 472 * @param parameter the parameter ID. 473 * @return the parameter value as a String. 474 */ 475 public static String siteParameter(String siteName, String parameter) 476 { 477 try 478 { 479 Site site = _siteManager.getSite(siteName); 480 Object value = site.getValue(parameter); 481 if (value != null) 482 { 483 return value.toString(); 484 } 485 else 486 { 487 return null; 488 } 489 } 490 catch (Exception e) 491 { 492 String message = "Error retrieving the value of the site parameter " + parameter; 493 _logger.error(message, e); 494 throw new RuntimeException(message, e); 495 } 496 } 497 498 /** 499 * Get the service parameters as a {@link Node}. 500 * @return the service parameters as a {@link Node}. 501 */ 502 public static Node serviceParameters() 503 { 504 ZoneItem zoneItem = _getZoneItemFromRequest(); 505 return _serviceParameters(zoneItem); 506 } 507 508 static Node _serviceParameters(ZoneItem zoneItem) 509 { 510 Map<String, MapNode> values = new HashMap<>(); 511 512 ModelAwareDataHolder dataHolder = zoneItem.getServiceParameters(); 513 String serviceId = zoneItem.getServiceId(); 514 Service service = _serviceEP.getExtension(serviceId); 515 516 for (String parameterName : dataHolder.getDataNames()) 517 { 518 ModelItem modelItem = service.getModelItem(parameterName); 519 values.putAll(_getParameterValue(parameterName, modelItem, dataHolder, null)); 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 org.ametys.web.repository.dom.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 * Determines if a captcha is required on forms of the current page 1482 * @return true if a captcha is required 1483 */ 1484 public static boolean isCaptchaRequired() 1485 { 1486 Page page = _getPageFromRequest(); 1487 return page == null || _pageHelper.isCaptchaRequired(page); 1488 } 1489 1490 /** 1491 * Determines if a captcha is required on forms of the given ametys object 1492 * @param ametysObjectId the ametys object id. Can be a sitemap element or a zone item. 1493 * @return true if a captcha is required 1494 */ 1495 public static boolean isCaptchaRequired(String ametysObjectId) 1496 { 1497 if (StringUtils.isBlank(ametysObjectId)) 1498 { 1499 // The given id is null, so return true for security 1500 return true; 1501 } 1502 1503 AmetysObject ametysObject = _ametysObjectResolver.resolveById(ametysObjectId); 1504 if (ametysObject instanceof SitemapElement sitemapElement) 1505 { 1506 return _pageHelper.isCaptchaRequired(sitemapElement); 1507 } 1508 else if (ametysObject instanceof ZoneItem zoneItem) 1509 { 1510 return _pageHelper.isCaptchaRequired(zoneItem.getZone().getSitemapElement()); 1511 } 1512 1513 // The ametys object is not a sitemap element or a zone item, so return true for security 1514 return true; 1515 } 1516 1517 /** 1518 * Returns the id of pages referencing the content and for which the Front-office user can access 1519 * @param contentId The content's id 1520 * @return The pages' id 1521 */ 1522 public static NodeList accessibleReferencedPages (String contentId) 1523 { 1524 RenderingContext renderingContext = _renderingContextHandler.getRenderingContext(); 1525 boolean inBackOffice = renderingContext == RenderingContext.BACK || renderingContext == RenderingContext.PREVIEW; 1526 1527 List<StringElement> pages = new ArrayList<>(); 1528 1529 Content content = _ametysObjectResolver.resolveById(contentId); 1530 if (content instanceof WebContent) 1531 { 1532 Collection<ZoneItem> zoneItems = ((WebContent) content).getReferencingZoneItems(); 1533 1534 for (ZoneItem zoneItem : zoneItems) 1535 { 1536 String metadataSetName = zoneItem.getViewName(); 1537 SitemapElement sitemapElement = zoneItem.getZone().getSitemapElement(); 1538 1539 if (sitemapElement instanceof Page page 1540 && (inBackOffice || _rightManager.hasReadAccess(_currentUserProvider.getUser(), page))) 1541 { 1542 Map<String, String> attrs = new HashMap<>(); 1543 attrs.put("id", page.getId()); 1544 attrs.put("metadataSetName", metadataSetName); 1545 pages.add(new StringElement("page", attrs)); 1546 } 1547 } 1548 } 1549 1550 return new AmetysNodeList(pages); 1551 } 1552 1553 /** 1554 * Returns the id of pages referencing the content 1555 * @param contentId The content's id 1556 * @return The pages' id 1557 */ 1558 public static NodeList referencedPages (String contentId) 1559 { 1560 List<StringElement> pages = new ArrayList<>(); 1561 1562 Content content = _ametysObjectResolver.resolveById(contentId); 1563 if (content instanceof WebContent) 1564 { 1565 Collection<ZoneItem> zoneItems = ((WebContent) content).getReferencingZoneItems(); 1566 1567 for (ZoneItem zoneItem : zoneItems) 1568 { 1569 String metadataSetName = zoneItem.getViewName(); 1570 SitemapElement sitemapElement = zoneItem.getZone().getSitemapElement(); 1571 1572 if (sitemapElement instanceof Page page) 1573 { 1574 Map<String, String> attrs = new HashMap<>(); 1575 attrs.put("id", page.getId()); 1576 attrs.put("metadataSetName", metadataSetName); 1577 pages.add(new StringElement("page", attrs)); 1578 } 1579 } 1580 } 1581 1582 return new AmetysNodeList(pages); 1583 } 1584 1585 /** 1586 * Returns the ids of the contents 1587 * @param tag The tag id 1588 * @return Array of contents ids 1589 */ 1590 public static NodeList findContentsIdsByTag(String tag) 1591 { 1592 Request request = ContextHelper.getRequest(_context); 1593 String siteName = (String) request.getAttribute("site"); 1594 1595 String lang = (String) request.getAttribute("sitemapLanguage"); 1596 if (lang == null) 1597 { 1598 // Try to get current language from content 1599 Content content = (Content) request.getAttribute(Content.class.getName()); 1600 if (content != null) 1601 { 1602 lang = content.getLanguage(); 1603 } 1604 } 1605 return findContentsIdsByTag(siteName, lang, tag); 1606 } 1607 1608 /** 1609 * Returns the ids of the contents 1610 * @param sitename site name. '+' for any site, '*'/null for any site, including contents without site, '^' for only contents without site 1611 * @param lang lang of the contents 1612 * @param tag The tag id 1613 * @return Array of contents ids 1614 */ 1615 public static NodeList findContentsIdsByTag(String sitename, String lang, String tag) 1616 { 1617 List<Expression> expressions = new ArrayList<>(); 1618 TagExpression tagExpression = new TagExpression(Operator.EQ, tag); 1619 expressions.add(tagExpression); 1620 1621 if (lang != null && !lang.equals("*")) 1622 { 1623 LanguageExpression le = new LanguageExpression(Operator.EQ, lang); 1624 expressions.add(le); 1625 } 1626 1627 if (sitename != null) 1628 { 1629 if (sitename.equals("+")) 1630 { 1631 MetadataExpression me = new MetadataExpression("site"); 1632 expressions.add(me); 1633 } 1634 else if (sitename.equals("*")) 1635 { 1636 // no filter 1637 } 1638 else if (sitename.equals("^")) 1639 { 1640 MetadataExpression me = new MetadataExpression("site"); 1641 expressions.add(new NotExpression(me)); 1642 } 1643 else 1644 { 1645 StringExpression se = new StringExpression("site", Operator.EQ, sitename); 1646 expressions.add(se); 1647 } 1648 } 1649 1650 Expression[] expressionsArray = expressions.toArray(new Expression[expressions.size()]); 1651 1652 String xpath = ContentQueryHelper.getContentXPathQuery(new AndExpression(expressionsArray)); 1653 AmetysObjectIterable<Content> contents = _ametysObjectResolver.query(xpath); 1654 Iterator<Content> it = contents.iterator(); 1655 1656 List<StringElement> list = new ArrayList<>(); 1657 while (it.hasNext()) 1658 { 1659 list.add(new StringElement("content", "id", it.next().getId())); 1660 } 1661 return new AmetysNodeList(list); 1662 } 1663 1664 /** 1665 * Returns the ids of the pages tagged with the specified tag 1666 * @param sitename The site id 1667 * @param lang The language code 1668 * @param tag The tag id 1669 * @return Array of pages ids 1670 */ 1671 public static NodeList findPagesIdsByTag(String sitename, String lang, String tag) 1672 { 1673 return findPagesIdsByTag(sitename, lang, tag, false); 1674 } 1675 1676 /** 1677 * Returns the ids of the pages tagged with the specified tag 1678 * @param sitename The site id 1679 * @param lang The language code 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 sitename, String lang, String tag, boolean checkReadAccess) 1685 { 1686 List<StringElement> list = new ArrayList<>(); 1687 for (String pageId : _pageDAO.findPagedIdsByTag(sitename, lang, tag)) 1688 { 1689 if (!checkReadAccess || _hasReadAccess(pageId)) 1690 { 1691 list.add(new StringElement("page", "id", pageId)); 1692 } 1693 } 1694 1695 return new AmetysNodeList(list); 1696 } 1697 1698 private static boolean _hasReadAccess(String pageId) 1699 { 1700 try 1701 { 1702 Page page = _ametysObjectResolver.resolveById(pageId); 1703 return _rightManager.currentUserHasReadAccess(page); 1704 } 1705 catch (UnknownAmetysObjectException e) 1706 { 1707 return false; 1708 } 1709 } 1710 1711 /** 1712 * Returns the ids of the pages tagged with the specified tag 1713 * @param tag The tag id 1714 * @return Array of pages ids 1715 */ 1716 public static NodeList findPagesIdsByTag(String tag) 1717 { 1718 return findPagesIdsByTag(tag, false); 1719 } 1720 1721 /** 1722 * Returns the ids of the pages tagged with the specified tag 1723 * @param tag The tag id 1724 * @param checkReadAccess true to return only pages with read access for current user 1725 * @return Array of pages ids 1726 */ 1727 public static NodeList findPagesIdsByTag(String tag, boolean checkReadAccess) 1728 { 1729 Request request = ContextHelper.getRequest(_context); 1730 String siteName = (String) request.getAttribute("site"); 1731 1732 String lang = (String) request.getAttribute("sitemapLanguage"); 1733 if (lang == null) 1734 { 1735 // Try to get current language from content 1736 Content content = (Content) request.getAttribute(Content.class.getName()); 1737 if (content != null) 1738 { 1739 lang = content.getLanguage(); 1740 } 1741 } 1742 1743 return findPagesIdsByTag(siteName, lang, tag, checkReadAccess); 1744 } 1745 1746 1747 /** 1748 * Return the given user by its email over all authorized population on current site 1749 * @param email the concerned user's email 1750 * @return The informations about the given user 1751 * @throws SAXException If an error occurred while saxing the user 1752 */ 1753 public static Node userByMail(String email) throws SAXException 1754 { 1755 String siteName = site(); 1756 1757 Set<String> userPopulationsOnSite = _populationContextHelper.getUserPopulationsOnContexts(Arrays.asList("/sites/" + siteName, "/sites-fo/" + siteName), false, false); 1758 1759 for (String populationId : userPopulationsOnSite) 1760 { 1761 Node user = userByMail(email, populationId); 1762 if (user != null) 1763 { 1764 return user; 1765 } 1766 } 1767 1768 return null; 1769 } 1770 1771 /** 1772 * Get the preview of a url (title, description, image, favico) 1773 * @param url the web link 1774 * @return the url preview 1775 * @throws SAXException If an error occurred while saxing 1776 */ 1777 public static Node urlPreview(String url) throws SAXException 1778 { 1779 try 1780 { 1781 String lang = StringUtils.defaultIfEmpty(lang(), "en"); 1782 UrlPreview urlPreview = _urlPreview.getUrlPreview(url, lang); 1783 DOMBuilder domBuilder = new DOMBuilder(); 1784 1785 urlPreview.toSAX(domBuilder, "preview"); 1786 1787 return domBuilder.getDocument(); 1788 } 1789 catch (IOException e) 1790 { 1791 _logger.error("Unable to get preview URL at " + url, e); 1792 return null; 1793 } 1794 } 1795 1796 /** 1797 * Generates a XML structure to help to creates a complex pagination. 1798 * <br> 1799 * <br>Example: pagination(39, 19, 2, 5, 2) will return 1800 * 1801 * <pre> 1802 * <gotofirstpage enabled="true">1</gotofirstpage> 1803 * <gotopreviouspage enabled="true">18</gotopreviouspage> 1804 * <page>1</page> 1805 * <page>2</page> 1806 * <separator/> 1807 * <page>17</page> 1808 * <page>18</page> 1809 * <current>19</current> 1810 * <page>20</page> 1811 * <page>21</page> 1812 * <separator/> 1813 * <page>38</page> 1814 * <page>39</page> 1815 * <gotonextpage enabled="true">20</gotonextpage> 1816 * <gotolastpage enabled="true">39</gotonextpage> 1817 * </pre> 1818 * 1819 * Example: pagination(5, 2, 2, 5, 2) will return 1820 * 1821 * <pre> 1822 * <gotofirstpage enabled="true">1</gotofirstpage> 1823 * <gotopreviouspage enabled="true">1</gotopreviouspage> 1824 * <page>1</page> 1825 * <current>2</page> 1826 * <page>3</page> 1827 * <page>4</page> 1828 * <page>5</page> 1829 * <space/> 1830 * <space/> 1831 * <space/> 1832 * <space/> 1833 * <gotonextpage enabled="true">3</gotonextpage> 1834 * <gotolastpage enabled="true">5</gotonextpage> 1835 * </pre> 1836 * 1837 * @param nbPages The total number of pages 1838 * @param currentPage The currently displayed page (1 based) 1839 * @param nbFirstPages The max number of pages to display before the 1st separator 1840 * @param nbCentralPages The max number of pages to display around the current page 1841 * @param nbLastPages The max number of pages to display after the 2nd separator 1842 * @return The xml described 1843 */ 1844 public static AmetysNodeList pagination(int nbPages, int currentPage, int nbFirstPages, int nbCentralPages, int nbLastPages) 1845 { 1846 List<Node> elements = new ArrayList<>(); 1847 1848 1849 elements.add(new StringElement("gotofirstpage", "enabled", Boolean.toString(currentPage > 1), "1")); 1850 elements.add(new StringElement("gotopreviouspage", "enabled", Boolean.toString(currentPage > 1), currentPage > 1 ? currentPage - 1 + "" : "")); 1851 1852 int[] pagination = _pagination(nbPages, currentPage, nbFirstPages, nbCentralPages, nbLastPages); 1853 for (int page : pagination) 1854 { 1855 if (page == _PAGINATION_SEPARATOR) 1856 { 1857 elements.add(new StringElement("separator", "")); 1858 } 1859 else if (page == _PAGINATION_SPACE) 1860 { 1861 elements.add(new StringElement("space", "")); 1862 } 1863 else if (page == _PAGINATION_CURRENT) 1864 { 1865 elements.add(new StringElement("current", Integer.toString(currentPage))); 1866 } 1867 else 1868 { 1869 elements.add(new StringElement("page", Integer.toString(page))); 1870 } 1871 } 1872 1873 elements.add(new StringElement("gotonextpage", "enabled", Boolean.toString(currentPage < nbPages), currentPage < nbPages ? currentPage + 1 + "" : "")); 1874 elements.add(new StringElement("gotolastpage", "enabled", Boolean.toString(currentPage < nbPages), nbPages + "")); 1875 1876 return new AmetysNodeList(elements); 1877 } 1878 1879 static int[] _pagination(int nbPages, int currentPage, int nbFirstPages, int nbCentralPages, int nbLastPages) 1880 { 1881 int displayedPages = nbFirstPages + 1 + nbCentralPages + 1 + nbLastPages; // The +1 are the room for separators 1882 1883 int[] values = new int[displayedPages]; 1884 1885 int centerOfCentralPages = (int) Math.ceil(nbCentralPages / 2.0); 1886 int centralCursor = nbFirstPages + 1 + centerOfCentralPages; 1887 boolean firstSeparator = nbPages > displayedPages && currentPage > centralCursor; 1888 boolean secondSeparator = nbPages > displayedPages && currentPage <= nbPages - centralCursor; 1889 1890 int cursor = 1; 1891 1892 // Before first separator 1893 cursor = _paginationFirstPages(nbPages, nbFirstPages, currentPage, values, cursor); 1894 1895 // First separator 1896 cursor = _paginationFirstSeparator(nbPages, firstSeparator, currentPage, values, cursor); 1897 1898 int offset = _paginationComputeOffsetAfterFirstSeparator(nbPages, currentPage, nbCentralPages, nbLastPages, centerOfCentralPages, firstSeparator, secondSeparator, cursor); 1899 1900 // Middle part 1901 cursor = _paginationMiddle(nbPages, currentPage, nbFirstPages, nbCentralPages, values, cursor, offset); 1902 1903 // Second separator 1904 cursor = _paginationSecondSeparator(nbPages, secondSeparator, currentPage, nbLastPages, values, cursor, offset); 1905 1906 // After second separator 1907 cursor = _paginationLastPages(nbPages, currentPage, displayedPages, values, cursor, offset); 1908 1909 return values; 1910 } 1911 1912 private static int _paginationMiddle(int nbPages, int currentPage, int nbFirstPages, int nbCentralPages, int[] values, int cursorP, int offset) 1913 { 1914 int cursor = cursorP; 1915 for (; cursor <= nbFirstPages + 1 + nbCentralPages; cursor++) 1916 { 1917 if (cursor + offset > nbPages) 1918 { 1919 values[cursor - 1] = _PAGINATION_SPACE; 1920 } 1921 else if (cursor + offset == currentPage) 1922 { 1923 values[cursor - 1] = _PAGINATION_CURRENT; 1924 } 1925 else 1926 { 1927 values[cursor - 1] = offset + cursor; 1928 } 1929 } 1930 return cursor; 1931 } 1932 1933 private static int _paginationComputeOffsetAfterFirstSeparator(int nbPages, int currentPage, int nbCentralPages, int nbLastPages, int centerOfCentralPages, boolean firstSeparator, boolean secondSeparator, int cursor) 1934 { 1935 if (!firstSeparator) 1936 { 1937 return 0; 1938 } 1939 else if (!secondSeparator) 1940 { 1941 return nbPages - nbLastPages - nbCentralPages - cursor; 1942 } 1943 else 1944 { 1945 return currentPage + 1 - centerOfCentralPages - cursor; 1946 } 1947 } 1948 1949 private static int _paginationLastPages(int nbPages, int currentPage, int displayedPages, int[] values, int cursorP, int offset) 1950 { 1951 int cursor = cursorP; 1952 for (; cursor <= displayedPages; cursor++) 1953 { 1954 if (cursor > nbPages) 1955 { 1956 values[cursor - 1] = _PAGINATION_SPACE; 1957 } 1958 else if (cursor + offset == currentPage) 1959 { 1960 values[cursor - 1] = _PAGINATION_CURRENT; 1961 } 1962 else 1963 { 1964 values[cursor - 1] = nbPages - (displayedPages - cursor); 1965 } 1966 } 1967 return cursor; 1968 } 1969 1970 private static int _paginationSecondSeparator(int nbPages, boolean secondSeparator, int currentPage, int nbLastPages, int[] values, int cursor, int offset) 1971 { 1972 if (cursor + offset > nbPages) 1973 { 1974 values[cursor - 1] = _PAGINATION_SPACE; 1975 } 1976 else if (currentPage == cursor + offset) 1977 { 1978 values[cursor - 1] = _PAGINATION_CURRENT; 1979 } 1980 else if (secondSeparator) 1981 { 1982 values[cursor - 1] = _PAGINATION_SEPARATOR; 1983 } 1984 else 1985 { 1986 values[cursor - 1] = nbPages - nbLastPages; 1987 } 1988 return cursor + 1; 1989 } 1990 1991 private static int _paginationFirstSeparator(int nbPages, boolean firstSeparator, int currentPage, int[] values, int cursor) 1992 { 1993 if (cursor > nbPages) 1994 { 1995 values[cursor - 1] = _PAGINATION_SPACE; 1996 } 1997 else if (currentPage == cursor) 1998 { 1999 values[cursor - 1] = _PAGINATION_CURRENT; 2000 } 2001 else if (firstSeparator) 2002 { 2003 values[cursor - 1] = _PAGINATION_SEPARATOR; 2004 } 2005 else 2006 { 2007 values[cursor - 1] = cursor; 2008 } 2009 return cursor + 1; 2010 } 2011 2012 private static int _paginationFirstPages(int nbPages, int nbFirstPages, int currentPage, int[] values, int cursorP) 2013 { 2014 int cursor = cursorP; 2015 for (; cursor <= nbFirstPages; cursor++) 2016 { 2017 if (cursor > nbPages) 2018 { 2019 values[cursor - 1] = _PAGINATION_SPACE; 2020 } 2021 else if (cursor == currentPage) 2022 { 2023 values[cursor - 1] = _PAGINATION_CURRENT; 2024 } 2025 else 2026 { 2027 values[cursor - 1] = cursor; 2028 } 2029 } 2030 return cursor; 2031 } 2032 2033 /** 2034 * Get the parameters' values of the current template 2035 * @return the values of template's parameters 2036 */ 2037 public static NodeList templateParameters() 2038 { 2039 List<Node> parameters = new ArrayList<>(); 2040 2041 Page page = _getPageFromRequest(); 2042 if (page != null) 2043 { 2044 Optional<ViewParametersModel> viewParametersModelOptional = _viewParametersManager.getTemplateViewParametersModel(page.getSite().getSkinId(), page.getTemplate()); 2045 if (viewParametersModelOptional.isPresent()) 2046 { 2047 ViewParametersModel viewParametersModel = viewParametersModelOptional.get(); 2048 2049 Collection< ? extends ModelItem> modelItems = viewParametersModel.getModelItems(); 2050 for (ModelItem modelItem : modelItems) 2051 { 2052 Optional<ViewParameterHolder> templateParameterHolderOptional = _viewParametersManager.getTemplateViewParameterHolderWithInheritance(page, modelItem); 2053 if (templateParameterHolderOptional.isPresent()) 2054 { 2055 ViewParameterHolder templateParameterHolder = templateParameterHolderOptional.get(); 2056 List<Node> values = _getNodeValues(templateParameterHolder.getDataHolder(), templateParameterHolder.getPath(), null); 2057 if (values != null) 2058 { 2059 parameters.addAll(values); 2060 } 2061 } 2062 } 2063 } 2064 } 2065 2066 return new AmetysNodeList(parameters); 2067 } 2068 2069 /** 2070 * Returns the value of the given parameter for the current page template, or the empty node if the parameter does not exist. 2071 * @param parameterPath the parameter path. 2072 * @return the value of the given parameter for the current page template. 2073 */ 2074 public static NodeList templateParameter(String parameterPath) 2075 { 2076 return templateParameter(null, parameterPath); 2077 } 2078 2079 /** 2080 * Returns the value of the given parameter for the given page template, or the empty node if the parameter does not exist. 2081 * @param pageId the page id 2082 * @param parameterPath the parameter path. 2083 * @return the value of the given parameter for the given page template. 2084 */ 2085 public static NodeList templateParameter(String pageId, String parameterPath) 2086 { 2087 Page page = StringUtils.isNotBlank(pageId) ? _getPage(pageId) : _getPageFromRequest(); 2088 if (page != null) 2089 { 2090 Optional<ViewParameterHolder> templateParameterHolderOptional = _viewParametersManager.getTemplateViewParameterHolderWithInheritance(page, parameterPath); 2091 if (templateParameterHolderOptional.isPresent()) 2092 { 2093 ViewParameterHolder templateParameterHolder = templateParameterHolderOptional.get(); 2094 List<Node> values = _getNodeValues(templateParameterHolder.getDataHolder(), templateParameterHolder.getPath(), null); 2095 if (values != null) 2096 { 2097 return new AmetysNodeList(values); 2098 } 2099 } 2100 } 2101 2102 return null; 2103 } 2104 2105 /** 2106 * Get the parameters of the current zone 2107 * @return the zone's parameters 2108 */ 2109 public static NodeList zoneParameters() 2110 { 2111 return zoneParameters(null); 2112 } 2113 2114 /** 2115 * Get the parameters of a given zone 2116 * @param zoneName The zone's name. Can be null or empty to get the current zone. 2117 * @return the zone's parameters 2118 */ 2119 public static NodeList zoneParameters(String zoneName) 2120 { 2121 List<Node> parameters = new ArrayList<>(); 2122 2123 Page page = _getPageFromRequest(); 2124 if (page != null) 2125 { 2126 Zone zone = _getZoneForParameter(page, zoneName); 2127 if (zone != null) 2128 { 2129 Optional<ViewParametersModel> viewParametersModelOptional = _viewParametersManager.getZoneViewParametersModel(page.getSite().getSkinId(), page.getTemplate(), zone.getName()); 2130 if (viewParametersModelOptional.isPresent()) 2131 { 2132 ViewParametersModel viewParametersModel = viewParametersModelOptional.get(); 2133 2134 Collection< ? extends ModelItem> modelItems = viewParametersModel.getModelItems(); 2135 for (ModelItem modelItem : modelItems) 2136 { 2137 Optional<ViewParameterHolder> zoneParameterHolderOptional = _viewParametersManager.getZoneViewParameterHolderWithInheritance(page, zone, modelItem); 2138 if (zoneParameterHolderOptional.isPresent()) 2139 { 2140 ViewParameterHolder zoneParameterHolder = zoneParameterHolderOptional.get(); 2141 List<Node> values = _getNodeValues(zoneParameterHolder.getDataHolder(), zoneParameterHolder.getPath(), null); 2142 if (values != null) 2143 { 2144 parameters.addAll(values); 2145 } 2146 } 2147 } 2148 } 2149 } 2150 } 2151 2152 return new AmetysNodeList(parameters); 2153 } 2154 2155 /** 2156 * Returns the value of the given parameter for the current page and current zone, or the empty node if the parameter does not exist. 2157 * @param parameterPath the parameter path. 2158 * @return the value of the given parameter for the current page and current zone. 2159 */ 2160 public static NodeList zoneParameter(String parameterPath) 2161 { 2162 return zoneParameter(null, null, parameterPath); 2163 } 2164 2165 /** 2166 * Returns the value of the given parameter for the current page and given zone, or the empty node if the parameter does not exist. 2167 * @param zoneName the zone name 2168 * @param parameterPath the parameter path. 2169 * @return the value of the given parameter for the current page and given zone. 2170 */ 2171 public static NodeList zoneParameter(String zoneName, String parameterPath) 2172 { 2173 return zoneParameter(null, zoneName, parameterPath); 2174 } 2175 2176 /** 2177 * 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. 2178 * @param pageId the page id 2179 * @param zoneName the zone name 2180 * @param parameterPath the parameter path. 2181 * @return the value of the given parameter for the given page and given zone name. 2182 */ 2183 public static NodeList zoneParameter(String pageId, String zoneName, String parameterPath) 2184 { 2185 Page page = StringUtils.isNotBlank(pageId) ? _getPage(pageId) : _getPageFromRequest(); 2186 if (page != null) 2187 { 2188 Zone zone = _getZoneForParameter(page, zoneName); 2189 if (zone != null) 2190 { 2191 Optional<ViewParameterHolder> zoneParameterHolderOptional = _viewParametersManager.getZoneViewParameterHolderWithInheritance(page, zone, parameterPath); 2192 if (zoneParameterHolderOptional.isPresent()) 2193 { 2194 ViewParameterHolder zoneParameterHolder = zoneParameterHolderOptional.get(); 2195 List<Node> values = _getNodeValues(zoneParameterHolder.getDataHolder(), zoneParameterHolder.getPath(), null); 2196 if (values != null) 2197 { 2198 return new AmetysNodeList(values); 2199 } 2200 } 2201 } 2202 } 2203 2204 return null; 2205 } 2206 2207 /** 2208 * Get the parameters of the current zone item 2209 * @return the zone items's parameters 2210 */ 2211 public static NodeList zoneItemParameters() 2212 { 2213 return zoneItemParameters(null); 2214 } 2215 2216 /** 2217 * Get the parameters of a given zone item 2218 * @param zoneItemId The id of zone item. Can be null or empty to get the current zone item 2219 * @return the zone items's parameters 2220 */ 2221 public static NodeList zoneItemParameters(String zoneItemId) 2222 { 2223 List<Node> parameters = new ArrayList<>(); 2224 2225 ZoneItem zoneItem = StringUtils.isNotBlank(zoneItemId) ? _getZoneItem(zoneItemId) : _getZoneItemFromRequest(); 2226 if (zoneItem != null) 2227 { 2228 Optional<ViewParametersModel> viewParametersModelOptional = _viewParametersManager.getZoneItemViewParametersModel(zoneItem); 2229 if (viewParametersModelOptional.isPresent()) 2230 { 2231 Collection< ? extends ModelItem> modelItems = viewParametersModelOptional.get().getModelItems(); 2232 for (ModelItem modelItem : modelItems) 2233 { 2234 List<Node> values = _getNodeValues(zoneItem.getZoneItemParametersHolder(), modelItem.getPath(), null); 2235 if (values != null) 2236 { 2237 parameters.addAll(values); 2238 } 2239 } 2240 } 2241 } 2242 2243 return new AmetysNodeList(parameters); 2244 } 2245 2246 /** 2247 * Returns the value of the given parameter for the current zone item, or the empty node if the parameter does not exist. 2248 * @param parameterPath the parameter path. 2249 * @return the value of the given parameter for the current zone item. 2250 */ 2251 public static NodeList zoneItemParameter(String parameterPath) 2252 { 2253 return zoneItemParameter(null, parameterPath); 2254 } 2255 2256 /** 2257 * Returns the value of the given parameter for the given zone item, or the empty node if the parameter does not exist. 2258 * @param zoneItemId the zone item id 2259 * @param parameterPath the parameter path. 2260 * @return the value of the given parameter for the given zone item. 2261 */ 2262 public static NodeList zoneItemParameter(String zoneItemId, String parameterPath) 2263 { 2264 ZoneItem zoneItem = StringUtils.isNotBlank(zoneItemId) ? _getZoneItem(zoneItemId) : _getZoneItemFromRequest(); 2265 if (zoneItem != null) 2266 { 2267 ModelAwareDataHolder dataHolder = zoneItem.getZoneItemParametersHolder(); 2268 List<Node> values = _getNodeValues(dataHolder, parameterPath, null); 2269 if (values != null) 2270 { 2271 return new AmetysNodeList(values); 2272 } 2273 } 2274 2275 return null; 2276 } 2277 2278 /** 2279 * Get the parameters of the current service 2280 * @return the service's parameters 2281 */ 2282 public static NodeList serviceViewParameters() 2283 { 2284 List<Node> parameters = new ArrayList<>(); 2285 2286 ZoneItem zoneItem = _getZoneItemFromRequest(); 2287 if (zoneItem != null) 2288 { 2289 if (zoneItem.getType() == ZoneType.SERVICE) 2290 { 2291 Optional<ViewParametersModel> serviceViewParametersModel = _viewParametersManager.getServiceViewParametersModel(zoneItem); 2292 if (serviceViewParametersModel.isPresent()) 2293 { 2294 String viewName = zoneItem.getServiceParameters().getValue(ViewParametersManager.SERVICE_VIEW_DEFAULT_MODEL_ITEM_NAME); 2295 2296 Collection< ? extends ModelItem> modelItems = serviceViewParametersModel.get().getModelItems(); 2297 for (ModelItem modelItem : modelItems) 2298 { 2299 List<Node> values = _getNodeValues(zoneItem.getServiceViewParametersHolder(viewName), modelItem.getPath(), null); 2300 if (values != null) 2301 { 2302 parameters.addAll(values); 2303 } 2304 } 2305 } 2306 } 2307 } 2308 2309 return new AmetysNodeList(parameters); 2310 } 2311 2312 /** 2313 * Returns the value of the given parameter for the current service, or the empty node if the parameter does not exist. 2314 * @param parameterPath the parameter path. 2315 * @return the value of the given parameter for the current service. 2316 */ 2317 public static NodeList serviceViewParameter(String parameterPath) 2318 { 2319 ZoneItem zoneItem = _getZoneItemFromRequest(); 2320 if (zoneItem != null) 2321 { 2322 if (zoneItem.getType() == ZoneType.SERVICE) 2323 { 2324 Optional<ModelAwareDataHolder> serviceViewParametersHolder = _viewParametersManager.getServiceViewParametersHolder(zoneItem); 2325 if (serviceViewParametersHolder.isPresent()) 2326 { 2327 List<Node> values = _getNodeValues(serviceViewParametersHolder.get(), parameterPath, null); 2328 if (values != null) 2329 { 2330 return new AmetysNodeList(values); 2331 } 2332 } 2333 } 2334 } 2335 2336 return null; 2337 } 2338 2339 /** 2340 * Get the parameters of the current content 2341 * @return the content's parameters 2342 */ 2343 public static NodeList contentViewParameters() 2344 { 2345 List<Node> parameters = new ArrayList<>(); 2346 2347 ZoneItem zoneItem = _getZoneItemFromRequest(); 2348 if (zoneItem != null) 2349 { 2350 if (zoneItem.getType() == ZoneType.CONTENT) 2351 { 2352 Content content = _getContentFromRequest(); 2353 Content zoneItemContent = zoneItem.getContent(); 2354 2355 // 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 2356 if (content != null && content.getId().equals(zoneItemContent.getId())) 2357 { 2358 Optional<ViewParametersModel> contentViewParametersModel = _viewParametersManager.getContentViewParametersModel(zoneItem); 2359 if (contentViewParametersModel.isPresent()) 2360 { 2361 String viewName = zoneItem.getViewName(); 2362 Collection< ? extends ModelItem> modelItems = contentViewParametersModel.get().getModelItems(); 2363 for (ModelItem modelItem : modelItems) 2364 { 2365 List<Node> values = _getNodeValues(zoneItem.getContentViewParametersHolder(viewName), modelItem.getPath(), null, DataContext.newInstance().withObjectId(content.getId())); 2366 if (values != null) 2367 { 2368 parameters.addAll(values); 2369 } 2370 } 2371 } 2372 } 2373 } 2374 } 2375 2376 return new AmetysNodeList(parameters); 2377 } 2378 2379 /** 2380 * Returns the value of the given parameter for the current content, or the empty node if the parameter does not exist. 2381 * @param parameterPath the parameter path. 2382 * @return the value of the given parameter for the current content. 2383 */ 2384 public static NodeList contentViewParameter(String parameterPath) 2385 { 2386 ZoneItem zoneItem = _getZoneItemFromRequest(); 2387 if (zoneItem != null) 2388 { 2389 if (zoneItem.getType() == ZoneType.CONTENT) 2390 { 2391 Content content = _getContentFromRequest(); 2392 Content zoneItemContent = zoneItem.getContent(); 2393 2394 // 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 2395 if (content != null && content.getId().equals(zoneItemContent.getId())) 2396 { 2397 Optional<ModelAwareDataHolder> contentViewParametersHolder = _viewParametersManager.getContentViewParametersHolder(zoneItem); 2398 if (contentViewParametersHolder.isPresent()) 2399 { 2400 List<Node> values = _getNodeValues(contentViewParametersHolder.get(), parameterPath, null, DataContext.newInstance().withObjectId(content.getId())); 2401 if (values != null) 2402 { 2403 return new AmetysNodeList(values); 2404 } 2405 } 2406 } 2407 } 2408 } 2409 2410 return null; 2411 } 2412 2413 private static Zone _getZoneForParameter(Page page, String zoneName) 2414 { 2415 Zone zone = _getZone(page, zoneName); 2416 if (zone == null) 2417 { 2418 zone = _getZoneFromRequest(page); 2419 if (zone == null) 2420 { 2421 ZoneItem zoneItem = _getZoneItemFromRequest(); 2422 if (zoneItem != null) 2423 { 2424 zone = zoneItem.getZone(); 2425 } 2426 } 2427 } 2428 2429 return zone; 2430 } 2431}