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