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