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 890 List<Element> result = new ArrayList<>(); 891 892 AmetysObject parent = page.getParent(); 893 while (parent instanceof Page) 894 { 895 Element node = new StringElement("page", (Map<String, String>) null, parent.getId()); 896 result.add(node); 897 parent = parent.getParent(); 898 } 899 900 Collections.reverse(result); 901 return new AmetysNodeList(result); 902 } 903 904 /** 905 * Returns a DOM {@link Element} representing files and folder of the resources explorer, 906 * under the {@link ResourceCollection} corresponding to the given id. 907 * @param collectionId the id of the root {@link ResourceCollection}. 908 * @return an Element containing files and folders. 909 */ 910 public static Node resourcesById(String collectionId) 911 { 912 ResourceCollection collection = _ametysObjectResolver.resolveById(collectionId); 913 return new ResourceCollectionElement(collection); 914 } 915 916 /** 917 * Returns a DOM {@link Element} representing files and folder of the resources explorer, 918 * under the {@link ResourceCollection} corresponding to the given path. <br> 919 * This path is intended to be relative to the current site's resource explorer. 920 * @param path the path of the root {@link ResourceCollection}, relative to the current site's resource explorer. 921 * @return an Element containing files and folders or null if the specified resource does not exist. 922 */ 923 public static Node resourcesByPath(String path) 924 { 925 Request request = ContextHelper.getRequest(_context); 926 String siteName = (String) request.getAttribute("site"); 927 Site site = _siteManager.getSite(siteName); 928 929 try 930 { 931 ResourceCollection collection = site.getRootResources().getChild(path); 932 return new ResourceCollectionElement(collection); 933 } 934 catch (UnknownAmetysObjectException ex) 935 { 936 return null; 937 } 938 } 939 940 /** 941 * Returns a DOM {@link Element} representing a single file of the resources explorer. <br> 942 * This path is intended to be relative to the current site's resource explorer. 943 * @param path the path of the {@link Resource}, relative to the current site's resource explorer. 944 * @return an Element containing a file or null if the specified resource does not exist. 945 */ 946 public static Node resourceByPath(String path) 947 { 948 Request request = ContextHelper.getRequest(_context); 949 String siteName = (String) request.getAttribute("site"); 950 Site site = _siteManager.getSite(siteName); 951 952 try 953 { 954 Resource resource = site.getRootResources().getChild(path); 955 return new ResourceElement(resource, null); 956 } 957 catch (UnknownAmetysObjectException ex) 958 { 959 return null; 960 } 961 } 962 963 /** 964 * Returns a DOM {@link Element} representing files and folder of a skin directory. <br> 965 * This path is intended to be relative to the current skin's 'resources' directory. 966 * @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. 967 * @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. 968 * @throws IOException if an error occurred while listing files. 969 */ 970 public static Node skinResources(String path) throws IOException 971 { 972 Source source = _sourceResolver.resolveURI("skin://resources/" + path); 973 if (source.exists()) 974 { 975 return new SourceElement(source); 976 } 977 else 978 { 979 return null; 980 } 981 } 982 983 //************************* 984 // Page methods 985 //************************* 986 987 /** 988 * Get the site name of a page. 989 * @param pageId The page id. 990 * @return The name or empty if the page does not exist. 991 */ 992 public static String pageSiteName(String pageId) 993 { 994 try 995 { 996 Page page = _getPage(pageId); 997 return page.getSiteName(); 998 } 999 catch (UnknownAmetysObjectException e) 1000 { 1001 _logger.error("Can not get site name on page with id '" + pageId + "'", e); 1002 return ""; 1003 } 1004 } 1005 1006 /** 1007 * Get the title of a page. 1008 * @param sitename the site name. 1009 * @param lang the sitemap name. 1010 * @param path the page path. 1011 * @return The name or empty if the meta or the page does not exist. 1012 */ 1013 public static String pageTitle(String sitename, String lang, String path) 1014 { 1015 try 1016 { 1017 Page page = _getPage(sitename, lang, path); 1018 return page.getTitle(); 1019 } 1020 catch (UnknownAmetysObjectException e) 1021 { 1022 _logger.warn("Unknown page at path '" + sitename + "/" + lang + "/" + path + "'", e); 1023 return ""; 1024 } 1025 } 1026 1027 /** 1028 * Determines if page exists 1029 * @param sitename the site name. 1030 * @param lang the sitemap name. 1031 * @param path the page path. 1032 * @return <code>false</code> the page does not exist. 1033 */ 1034 public static boolean pageExists(String sitename, String lang, String path) 1035 { 1036 try 1037 { 1038 _getPage(sitename, lang, path); 1039 return true; 1040 } 1041 catch (UnknownAmetysObjectException e) 1042 { 1043 _logger.debug("Page at path '" + sitename + "/" + lang + "/" + path + "' does not exists", e); 1044 return false; 1045 } 1046 } 1047 1048 /** 1049 * Get the title of a page. 1050 * @param pageId The page id. 1051 * @return The name or empty if the meta or the page does not exist. 1052 */ 1053 public static String pageTitle(String pageId) 1054 { 1055 try 1056 { 1057 Page page = _getPage(pageId); 1058 return page.getTitle(); 1059 } 1060 catch (UnknownAmetysObjectException e) 1061 { 1062 _logger.error("Can not get title on page with id '" + pageId + "'", e); 1063 return ""; 1064 } 1065 } 1066 1067 /** 1068 * Get the long title of a page 1069 * @param sitename the site name 1070 * @param lang the page's language 1071 * @param path the page's path 1072 * @return The name or empty if the meta or the page does not exist 1073 */ 1074 public static String pageLongTitle(String sitename, String lang, String path) 1075 { 1076 try 1077 { 1078 Page page = _getPage(sitename, lang, path); 1079 return page.getLongTitle(); 1080 } 1081 catch (UnknownAmetysObjectException e) 1082 { 1083 _logger.error("Can not get long title on page '" + sitename + "/" + lang + "/" + path + "'", e); 1084 return ""; 1085 } 1086 } 1087 /** 1088 * Get the long title of a page 1089 * @param pageId The page id 1090 * @return The name or empty if the meta or the page does not exist 1091 */ 1092 public static String pageLongTitle(String pageId) 1093 { 1094 try 1095 { 1096 Page page = _getPage(pageId); 1097 return page.getLongTitle(); 1098 } 1099 catch (UnknownAmetysObjectException e) 1100 { 1101 _logger.error("Can not get long title on page with id '" + pageId + "'", e); 1102 return ""; 1103 } 1104 } 1105 1106 /** 1107 * Get the type of a page. 1108 * @param pageId The page id. 1109 * @return The type or empty if the page does not exist. 1110 */ 1111 public static String pageType(String pageId) 1112 { 1113 try 1114 { 1115 Page page = _getPage(pageId); 1116 return page.getType().name(); 1117 } 1118 catch (UnknownAmetysObjectException e) 1119 { 1120 _logger.error("Can not get type of page with id '" + pageId + "'", e); 1121 return ""; 1122 } 1123 } 1124 1125 /** 1126 * Get the linked url of a page. 1127 * @param pageId The page id. 1128 * @return The linked url or empty if the page does not exist or if it is not a LINK page 1129 */ 1130 public static String pageUrl(String pageId) 1131 { 1132 try 1133 { 1134 Page page = _getPage(pageId); 1135 return page.getType() == PageType.LINK ? page.getURL() : ""; 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 type of a page. 1146 * @param pageId The page id. 1147 * @return The linked URL type or empty if the page does not exist or if it is not a LINK page 1148 */ 1149 public static String pageUrlType(String pageId) 1150 { 1151 try 1152 { 1153 Page page = _getPage(pageId); 1154 return page.getType() == PageType.LINK ? page.getURLType().name() : ""; 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 data of a page at the given path 1165 * @param sitename the site name 1166 * @param lang the page's language 1167 * @param path the page's path 1168 * @param dataPath The data path (use '/' as separator for composites and repeaters) 1169 * @return The value or empty if the data or the page does not exist 1170 */ 1171 public static String pageMetadata(String sitename, String lang, String path, String dataPath) 1172 { 1173 try 1174 { 1175 Page page = _getPage(sitename, lang, path); 1176 return _getPageData(page, dataPath); 1177 } 1178 catch (UnknownAmetysObjectException e) 1179 { 1180 _logger.error("Can not get data at path '" + dataPath + "' on page '" + sitename + "/" + lang + "/" + path + "'", e); 1181 return StringUtils.EMPTY; 1182 } 1183 } 1184 1185 /** 1186 * Get the data of a page at the given path 1187 * @param pageId The page id 1188 * @param dataPath The data path (use '/' as separator for composites and repeaters) 1189 * @return The value or empty if the data or the page does not exist 1190 */ 1191 public static String pageMetadata(String pageId, String dataPath) 1192 { 1193 try 1194 { 1195 Page page = _getPage(pageId); 1196 return _getPageData(page, dataPath); 1197 } 1198 catch (UnknownAmetysObjectException e) 1199 { 1200 _logger.error("Can not get data at path '" + dataPath + "' on page with id '" + pageId + "'", e); 1201 return StringUtils.EMPTY; 1202 } 1203 } 1204 1205 @SuppressWarnings("unchecked") 1206 private static String _getPageData(Page page, String dataPath) 1207 { 1208 try 1209 { 1210 Object value = page.getValue(dataPath); 1211 if (value != null) 1212 { 1213 ModelItemType type = page.getType(dataPath); 1214 if (type instanceof ElementType) 1215 { 1216 return ((ElementType) type).toString(value); 1217 } 1218 } 1219 1220 _logger.error("Can not get data at path '" + dataPath + "' on page with id '" + page.getId() + "'"); 1221 return StringUtils.EMPTY; 1222 } 1223 catch (Exception e) 1224 { 1225 _logger.error("Can not get data at path '" + dataPath + "' on page with id '" + page.getId() + "'", e); 1226 return StringUtils.EMPTY; 1227 } 1228 } 1229 1230 /** 1231 * Returns true if the given page is visible into navigation elements 1232 * @param pageId the page id. 1233 * @return true if the page is visible 1234 */ 1235 public static boolean pageIsVisible (String pageId) 1236 { 1237 try 1238 { 1239 Page page = _getPage(pageId); 1240 return page.isVisible(); 1241 } 1242 catch (UnknownAmetysObjectException e) 1243 { 1244 _logger.error("Can not get visibility status on page with id '" + pageId + "'", e); 1245 return false; 1246 } 1247 } 1248 1249 /** 1250 * Returns true if the given page is visible into navigation elements 1251 * @param sitename the site name 1252 * @param lang the page's language 1253 * @param path the page's path 1254 * @return true if the page is visible 1255 */ 1256 public static boolean pageIsVisible (String sitename, String lang, String path) 1257 { 1258 try 1259 { 1260 Page page = _getPage(sitename, lang, path); 1261 return page.isVisible(); 1262 } 1263 catch (UnknownAmetysObjectException e) 1264 { 1265 _logger.error("Can not get visibility status on page with id '" + sitename + "/" + lang + "/" + path + "'", e); 1266 return false; 1267 } 1268 } 1269 1270 /** 1271 * Returns true if the given page has restricted access. 1272 * @param pageId the page id. 1273 * @return true if the page exists and has restricted access. 1274 */ 1275 public static boolean pageHasRestrictedAccess(String pageId) 1276 { 1277 try 1278 { 1279 Page page = _getPage(pageId); 1280 return !_rightManager.hasAnonymousReadAccess(page); 1281 } 1282 catch (UnknownAmetysObjectException e) 1283 { 1284 _logger.error("Can not get page access info on page with id '" + pageId + "'", e); 1285 return false; 1286 } 1287 } 1288 1289 /** 1290 * Returns true if the current user has read access on the specified page 1291 * @param pageId Page Id 1292 * @return true if the current user has read access on the specified page 1293 */ 1294 public static boolean hasReadAccessOnPage(String pageId) 1295 { 1296 Page page = _getPage(pageId); 1297 return _rightManager.currentUserHasReadAccess(page); 1298 } 1299 1300 /** 1301 * Returns true if the current user has the specified right on the current page 1302 * @param rightId Right Id 1303 * @return true if the current user has the specified right on the current page 1304 */ 1305 public static boolean hasRightOnPage(String rightId) 1306 { 1307 Page page = _getPageFromRequest(); 1308 return _hasRightOnPage(rightId, page); 1309 } 1310 1311 /** 1312 * Returns true if the current user has the specified right on the specified page 1313 * @param rightId Right Id 1314 * @param pageId Page Id 1315 * @return true if the current user has the specified right on the specified page 1316 */ 1317 public static boolean hasRightOnPage(String rightId, String pageId) 1318 { 1319 Page page = _getPage(pageId); 1320 return _hasRightOnPage(rightId, page); 1321 } 1322 1323 /** 1324 * Returns true if the current user has the specified right on the specified page 1325 * @param rightId Right Id 1326 * @param page Page 1327 * @return true if the current user has the specified right on the specified page 1328 */ 1329 private static boolean _hasRightOnPage(String rightId, Page page) 1330 { 1331 RightResult rightResult = _rightManager.currentUserHasRight(rightId, page); 1332 return rightResult == RightResult.RIGHT_ALLOW; 1333 } 1334 1335 /** 1336 * Returns true if the given page has restricted access. 1337 * @param sitename the site name 1338 * @param lang the page's language 1339 * @param path the page's path 1340 * @return true if the page exists and has restricted access. 1341 */ 1342 public static boolean pageHasRestrictedAccess(String sitename, String lang, String path) 1343 { 1344 try 1345 { 1346 Page page = _getPage(sitename, lang, path); 1347 return !_rightManager.hasAnonymousReadAccess(page); 1348 } 1349 catch (UnknownAmetysObjectException e) 1350 { 1351 _logger.error("Can not get page access info on page with id '" + sitename + "/" + lang + "/" + path + "'", e); 1352 return false; 1353 } 1354 } 1355 1356 private static Page _getPage(String id) 1357 { 1358 return _ametysObjectResolver.resolveById(id); 1359 } 1360 1361 private static Page _getPage(String sitename, String lang, String path) 1362 { 1363 Site site = _siteManager.getSite(sitename); 1364 Sitemap sitemap = site.getSitemap(lang); 1365 return sitemap.getChild(path); 1366 } 1367 1368 private static Page _getPageFromRequest() 1369 { 1370 Request request = ContextHelper.getRequest(_context); 1371 return (Page) request.getAttribute(WebConstants.REQUEST_ATTR_PAGE); 1372 } 1373 1374 /** 1375 * Returns the path of the current page, relative to the sitemap's root. 1376 * @return the path of the current Page, or empty if there's no current page. 1377 */ 1378 public static String pagePath() 1379 { 1380 Page page = _getPageFromRequest(); 1381 return page == null ? "" : page.getPathInSitemap(); 1382 } 1383 1384 /** 1385 * Returns the path in sitemap of a page 1386 * @param pageId The id of page 1387 * @return the path of the Page, or empty if not exists 1388 */ 1389 public static String pagePath(String pageId) 1390 { 1391 try 1392 { 1393 Page page = _getPage(pageId); 1394 return page.getPathInSitemap(); 1395 } 1396 catch (UnknownAmetysObjectException e) 1397 { 1398 _logger.error("Can not get title on page with id '" + pageId + "'", e); 1399 return ""; 1400 } 1401 } 1402 1403 /** 1404 * Returns the id of the current page. 1405 * @return the id of the current Page, or empty if there's no current page. 1406 */ 1407 public static String pageId() 1408 { 1409 Page page = _getPageFromRequest(); 1410 return page == null ? "" : page.getId(); 1411 } 1412 1413 private static Zone _getZone(Page page, String zoneName) 1414 { 1415 if (StringUtils.isNotBlank(zoneName) && page.hasZone(zoneName)) 1416 { 1417 return page.getZone(zoneName); 1418 } 1419 1420 return null; 1421 } 1422 1423 private static Zone _getZoneFromRequest(Page page) 1424 { 1425 Request request = ContextHelper.getRequest(_context); 1426 String currentZoneName = (String) request.getAttribute(WebConstants.REQUEST_ATTR_ZONE_NAME); 1427 if (StringUtils.isNotBlank(currentZoneName) && page.hasZone(currentZoneName)) 1428 { 1429 return page.getZone(currentZoneName); 1430 } 1431 1432 return null; 1433 } 1434 1435 /** 1436 * Returns the id of the current zone item id. 1437 * @return the id of the current zone item id, or empty if there's no current zone item. 1438 */ 1439 public static String zoneItemId() 1440 { 1441 ZoneItem zoneItem = _getZoneItemFromRequest(); 1442 return zoneItem == null ? "" : StringUtils.defaultString(zoneItem.getId()); 1443 } 1444 1445 private static ZoneItem _getZoneItem(String id) 1446 { 1447 return _ametysObjectResolver.resolveById(id); 1448 } 1449 1450 private static ZoneItem _getZoneItemFromRequest() 1451 { 1452 Request request = ContextHelper.getRequest(_context); 1453 return (ZoneItem) request.getAttribute(WebConstants.REQUEST_ATTR_ZONEITEM); 1454 } 1455 1456 private static Content _getContentFromRequest() 1457 { 1458 Request request = ContextHelper.getRequest(_context); 1459 return (Content) request.getAttribute(Content.class.getName()); 1460 } 1461 1462 /** 1463 * Get the position of the current zone item in its zone 1464 * @return the position of the current zone item or -1 if there's no current zone item. 1465 */ 1466 public static int zoneItemPosition() 1467 { 1468 ZoneItem zoneItem = _getZoneItemFromRequest(); 1469 if (zoneItem != null) 1470 { 1471 Zone zone = zoneItem.getZone(); 1472 int index = 1; 1473 1474 AmetysObjectIterable< ? extends ZoneItem> zoneItems = zone.getZoneItems(); 1475 for (ZoneItem childZoneItem : zoneItems) 1476 { 1477 if (childZoneItem.equals(zoneItem)) 1478 { 1479 return index; 1480 } 1481 index++; 1482 } 1483 } 1484 1485 return -1; 1486 } 1487 1488 /** 1489 * Determines if the current zone item or (if there is no current zone item) the current page is cacheable 1490 * This method is only valid for a page. 1491 * @return true if the current zone item or page is cacheable. 1492 */ 1493 public static boolean isCacheable() 1494 { 1495 Request request = ContextHelper.getRequest(_context); 1496 if (request.getAttribute("IsZoneItemCacheable") != null) 1497 { 1498 return (Boolean) request.getAttribute("IsZoneItemCacheable"); 1499 } 1500 1501 // The method was called from the skin, out of a zone item 1502 Response response = ContextHelper.getResponse(_context); 1503 if (response.containsHeader("X-Ametys-Cacheable")) 1504 { 1505 return true; 1506 } 1507 return false; 1508 } 1509 1510 /** 1511 * Determines if we are in an edition mode 1512 * @return true if we are in edition mode 1513 */ 1514 public static boolean isEditionMode() 1515 { 1516 RenderingContext renderingContext = _renderingContextHandler.getRenderingContext(); 1517 Request request = ContextHelper.getRequest(_context); 1518 if (renderingContext == RenderingContext.FRONT && request.getParameter("_edition") != null && "true".equals(request.getParameter("_edition"))) 1519 { 1520 return true; 1521 } 1522 return false; 1523 } 1524 1525 /** 1526 * Determines if a captcha is required on forms of the current page 1527 * @return true if a captcha is required 1528 */ 1529 public static boolean isCaptchaRequired() 1530 { 1531 Page page = _getPageFromRequest(); 1532 return page == null || _pageHelper.isCaptchaRequired(page); 1533 } 1534 1535 /** 1536 * Determines if a captcha is required on forms of the given ametys object 1537 * @param ametysObjectId the ametys object id. Can be a sitemap element or a zone item. 1538 * @return true if a captcha is required 1539 */ 1540 public static boolean isCaptchaRequired(String ametysObjectId) 1541 { 1542 if (StringUtils.isBlank(ametysObjectId)) 1543 { 1544 // The given id is null, so return true for security 1545 return true; 1546 } 1547 1548 AmetysObject ametysObject = _ametysObjectResolver.resolveById(ametysObjectId); 1549 if (ametysObject instanceof SitemapElement sitemapElement) 1550 { 1551 return _pageHelper.isCaptchaRequired(sitemapElement); 1552 } 1553 else if (ametysObject instanceof ZoneItem zoneItem) 1554 { 1555 return _pageHelper.isCaptchaRequired(zoneItem.getZone().getSitemapElement()); 1556 } 1557 1558 // The ametys object is not a sitemap element or a zone item, so return true for security 1559 return true; 1560 } 1561 1562 /** 1563 * Returns the id of pages referencing the content and for which the Front-office user can access 1564 * @param contentId The content's id 1565 * @return The pages' id 1566 */ 1567 public static NodeList accessibleReferencedPages (String contentId) 1568 { 1569 RenderingContext renderingContext = _renderingContextHandler.getRenderingContext(); 1570 boolean inBackOffice = renderingContext == RenderingContext.BACK || renderingContext == RenderingContext.PREVIEW; 1571 1572 List<StringElement> pages = new ArrayList<>(); 1573 1574 Content content = _ametysObjectResolver.resolveById(contentId); 1575 if (content instanceof WebContent) 1576 { 1577 Collection<ZoneItem> zoneItems = ((WebContent) content).getReferencingZoneItems(); 1578 1579 for (ZoneItem zoneItem : zoneItems) 1580 { 1581 String metadataSetName = zoneItem.getViewName(); 1582 SitemapElement sitemapElement = zoneItem.getZone().getSitemapElement(); 1583 1584 if (sitemapElement instanceof Page page 1585 && (inBackOffice || _rightManager.hasReadAccess(_currentUserProvider.getUser(), page))) 1586 { 1587 Map<String, String> attrs = new HashMap<>(); 1588 attrs.put("id", page.getId()); 1589 attrs.put("metadataSetName", metadataSetName); 1590 pages.add(new StringElement("page", attrs)); 1591 } 1592 } 1593 } 1594 1595 return new AmetysNodeList(pages); 1596 } 1597 1598 /** 1599 * Returns the id of pages referencing the content 1600 * @param contentId The content's id 1601 * @return The pages' id 1602 */ 1603 public static NodeList referencedPages (String contentId) 1604 { 1605 List<StringElement> pages = new ArrayList<>(); 1606 1607 Content content = _ametysObjectResolver.resolveById(contentId); 1608 if (content instanceof WebContent) 1609 { 1610 Collection<ZoneItem> zoneItems = ((WebContent) content).getReferencingZoneItems(); 1611 1612 for (ZoneItem zoneItem : zoneItems) 1613 { 1614 String metadataSetName = zoneItem.getViewName(); 1615 SitemapElement sitemapElement = zoneItem.getZone().getSitemapElement(); 1616 1617 if (sitemapElement instanceof Page page) 1618 { 1619 Map<String, String> attrs = new HashMap<>(); 1620 attrs.put("id", page.getId()); 1621 attrs.put("metadataSetName", metadataSetName); 1622 pages.add(new StringElement("page", attrs)); 1623 } 1624 } 1625 } 1626 1627 return new AmetysNodeList(pages); 1628 } 1629 1630 /** 1631 * Returns the ids of the contents 1632 * @param tag The tag id 1633 * @return Array of contents ids 1634 */ 1635 public static NodeList findContentsIdsByTag(String tag) 1636 { 1637 Request request = ContextHelper.getRequest(_context); 1638 String siteName = (String) request.getAttribute("site"); 1639 1640 String lang = (String) request.getAttribute("sitemapLanguage"); 1641 if (lang == null) 1642 { 1643 // Try to get current language from content 1644 Content content = (Content) request.getAttribute(Content.class.getName()); 1645 if (content != null) 1646 { 1647 lang = content.getLanguage(); 1648 } 1649 } 1650 return findContentsIdsByTag(siteName, lang, tag); 1651 } 1652 1653 /** 1654 * Returns the ids of the contents 1655 * @param sitename site name. '+' for any site, '*'/null for any site, including contents without site, '^' for only contents without site 1656 * @param lang lang of the contents 1657 * @param tag The tag id 1658 * @return Array of contents ids 1659 */ 1660 public static NodeList findContentsIdsByTag(String sitename, String lang, String tag) 1661 { 1662 List<Expression> expressions = new ArrayList<>(); 1663 TagExpression tagExpression = new TagExpression(Operator.EQ, tag); 1664 expressions.add(tagExpression); 1665 1666 if (lang != null && !lang.equals("*")) 1667 { 1668 LanguageExpression le = new LanguageExpression(Operator.EQ, lang); 1669 expressions.add(le); 1670 } 1671 1672 if (sitename != null) 1673 { 1674 if (sitename.equals("+")) 1675 { 1676 MetadataExpression me = new MetadataExpression("site"); 1677 expressions.add(me); 1678 } 1679 else if (sitename.equals("*")) 1680 { 1681 // no filter 1682 } 1683 else if (sitename.equals("^")) 1684 { 1685 MetadataExpression me = new MetadataExpression("site"); 1686 expressions.add(new NotExpression(me)); 1687 } 1688 else 1689 { 1690 StringExpression se = new StringExpression("site", Operator.EQ, sitename); 1691 expressions.add(se); 1692 } 1693 } 1694 1695 Expression[] expressionsArray = expressions.toArray(new Expression[expressions.size()]); 1696 1697 String xpath = ContentQueryHelper.getContentXPathQuery(new AndExpression(expressionsArray)); 1698 AmetysObjectIterable<Content> contents = _ametysObjectResolver.query(xpath); 1699 Iterator<Content> it = contents.iterator(); 1700 1701 List<StringElement> list = new ArrayList<>(); 1702 while (it.hasNext()) 1703 { 1704 list.add(new StringElement("content", "id", it.next().getId())); 1705 } 1706 return new AmetysNodeList(list); 1707 } 1708 1709 /** 1710 * Returns the ids of the pages tagged with the specified tag 1711 * @param sitename The site id 1712 * @param lang The language code 1713 * @param tag The tag id 1714 * @return Array of pages ids 1715 */ 1716 public static NodeList findPagesIdsByTag(String sitename, String lang, String tag) 1717 { 1718 return findPagesIdsByTag(sitename, lang, tag, false); 1719 } 1720 1721 /** 1722 * Returns the ids of the pages tagged with the specified tag 1723 * @param sitename The site id 1724 * @param lang The language code 1725 * @param tag The tag id 1726 * @param checkReadAccess true to return only pages with read access for current user 1727 * @return Array of pages ids 1728 */ 1729 public static NodeList findPagesIdsByTag(String sitename, String lang, String tag, boolean checkReadAccess) 1730 { 1731 List<StringElement> list = new ArrayList<>(); 1732 for (String pageId : _pageDAO.findPagedIdsByTag(sitename, lang, tag)) 1733 { 1734 if (!checkReadAccess || _hasReadAccess(pageId)) 1735 { 1736 list.add(new StringElement("page", "id", pageId)); 1737 } 1738 } 1739 1740 return new AmetysNodeList(list); 1741 } 1742 1743 private static boolean _hasReadAccess(String pageId) 1744 { 1745 try 1746 { 1747 Page page = _ametysObjectResolver.resolveById(pageId); 1748 return _rightManager.currentUserHasReadAccess(page); 1749 } 1750 catch (UnknownAmetysObjectException e) 1751 { 1752 return false; 1753 } 1754 } 1755 1756 /** 1757 * Returns the ids of the pages tagged with the specified tag 1758 * @param tag The tag id 1759 * @return Array of pages ids 1760 */ 1761 public static NodeList findPagesIdsByTag(String tag) 1762 { 1763 return findPagesIdsByTag(tag, false); 1764 } 1765 1766 /** 1767 * Returns the ids of the pages tagged with the specified tag 1768 * @param tag The tag id 1769 * @param checkReadAccess true to return only pages with read access for current user 1770 * @return Array of pages ids 1771 */ 1772 public static NodeList findPagesIdsByTag(String tag, boolean checkReadAccess) 1773 { 1774 Request request = ContextHelper.getRequest(_context); 1775 String siteName = (String) request.getAttribute("site"); 1776 1777 String lang = (String) request.getAttribute("sitemapLanguage"); 1778 if (lang == null) 1779 { 1780 // Try to get current language from content 1781 Content content = (Content) request.getAttribute(Content.class.getName()); 1782 if (content != null) 1783 { 1784 lang = content.getLanguage(); 1785 } 1786 } 1787 1788 return findPagesIdsByTag(siteName, lang, tag, checkReadAccess); 1789 } 1790 1791 1792 /** 1793 * Return the given user by its email over all authorized population on current site 1794 * @param email the concerned user's email 1795 * @return The informations about the given user 1796 * @throws SAXException If an error occurred while saxing the user 1797 */ 1798 public static Node userByMail(String email) throws SAXException 1799 { 1800 String siteName = site(); 1801 1802 Set<String> userPopulationsOnSite = _populationContextHelper.getUserPopulationsOnContexts(Arrays.asList("/sites/" + siteName, "/sites-fo/" + siteName), false, false); 1803 1804 for (String populationId : userPopulationsOnSite) 1805 { 1806 Node user = userByMail(email, populationId); 1807 if (user != null) 1808 { 1809 return user; 1810 } 1811 } 1812 1813 return null; 1814 } 1815 1816 /** 1817 * Get the preview of a url (title, description, image, favico) 1818 * @param url the web link 1819 * @return the url preview 1820 * @throws SAXException If an error occurred while saxing 1821 */ 1822 public static Node urlPreview(String url) throws SAXException 1823 { 1824 try 1825 { 1826 String lang = StringUtils.defaultIfEmpty(lang(), "en"); 1827 UrlPreview urlPreview = _urlPreview.getUrlPreview(url, lang); 1828 DOMBuilder domBuilder = new DOMBuilder(); 1829 1830 urlPreview.toSAX(domBuilder, "preview"); 1831 1832 return domBuilder.getDocument(); 1833 } 1834 catch (IOException e) 1835 { 1836 _logger.error("Unable to get preview URL at " + url, e); 1837 return null; 1838 } 1839 } 1840 1841 /** 1842 * Generates a XML structure to help to creates a complex pagination. 1843 * <br> 1844 * <br>Example: pagination(39, 19, 2, 5, 2) will return 1845 * 1846 * <pre> 1847 * <gotofirstpage enabled="true">1</gotofirstpage> 1848 * <gotopreviouspage enabled="true">18</gotopreviouspage> 1849 * <page>1</page> 1850 * <page>2</page> 1851 * <separator/> 1852 * <page>17</page> 1853 * <page>18</page> 1854 * <current>19</current> 1855 * <page>20</page> 1856 * <page>21</page> 1857 * <separator/> 1858 * <page>38</page> 1859 * <page>39</page> 1860 * <gotonextpage enabled="true">20</gotonextpage> 1861 * <gotolastpage enabled="true">39</gotonextpage> 1862 * </pre> 1863 * 1864 * Example: pagination(5, 2, 2, 5, 2) will return 1865 * 1866 * <pre> 1867 * <gotofirstpage enabled="true">1</gotofirstpage> 1868 * <gotopreviouspage enabled="true">1</gotopreviouspage> 1869 * <page>1</page> 1870 * <current>2</page> 1871 * <page>3</page> 1872 * <page>4</page> 1873 * <page>5</page> 1874 * <space/> 1875 * <space/> 1876 * <space/> 1877 * <space/> 1878 * <gotonextpage enabled="true">3</gotonextpage> 1879 * <gotolastpage enabled="true">5</gotonextpage> 1880 * </pre> 1881 * 1882 * @param nbPages The total number of pages 1883 * @param currentPage The currently displayed page (1 based) 1884 * @param nbFirstPages The max number of pages to display before the 1st separator 1885 * @param nbCentralPages The max number of pages to display around the current page 1886 * @param nbLastPages The max number of pages to display after the 2nd separator 1887 * @return The xml described 1888 */ 1889 public static AmetysNodeList pagination(int nbPages, int currentPage, int nbFirstPages, int nbCentralPages, int nbLastPages) 1890 { 1891 List<Node> elements = new ArrayList<>(); 1892 1893 1894 elements.add(new StringElement("gotofirstpage", "enabled", Boolean.toString(currentPage > 1), "1")); 1895 elements.add(new StringElement("gotopreviouspage", "enabled", Boolean.toString(currentPage > 1), currentPage > 1 ? currentPage - 1 + "" : "")); 1896 1897 int[] pagination = _pagination(nbPages, currentPage, nbFirstPages, nbCentralPages, nbLastPages); 1898 for (int page : pagination) 1899 { 1900 if (page == _PAGINATION_SEPARATOR) 1901 { 1902 elements.add(new StringElement("separator", "")); 1903 } 1904 else if (page == _PAGINATION_SPACE) 1905 { 1906 elements.add(new StringElement("space", "")); 1907 } 1908 else if (page == _PAGINATION_CURRENT) 1909 { 1910 elements.add(new StringElement("current", Integer.toString(currentPage))); 1911 } 1912 else 1913 { 1914 elements.add(new StringElement("page", Integer.toString(page))); 1915 } 1916 } 1917 1918 elements.add(new StringElement("gotonextpage", "enabled", Boolean.toString(currentPage < nbPages), currentPage < nbPages ? currentPage + 1 + "" : "")); 1919 elements.add(new StringElement("gotolastpage", "enabled", Boolean.toString(currentPage < nbPages), nbPages + "")); 1920 1921 return new AmetysNodeList(elements); 1922 } 1923 1924 static int[] _pagination(int nbPages, int currentPage, int nbFirstPages, int nbCentralPages, int nbLastPages) 1925 { 1926 int displayedPages = nbFirstPages + 1 + nbCentralPages + 1 + nbLastPages; // The +1 are the room for separators 1927 1928 int[] values = new int[displayedPages]; 1929 1930 int centerOfCentralPages = (int) Math.ceil(nbCentralPages / 2.0); 1931 int centralCursor = nbFirstPages + 1 + centerOfCentralPages; 1932 boolean firstSeparator = nbPages > displayedPages && currentPage > centralCursor; 1933 boolean secondSeparator = nbPages > displayedPages && currentPage <= nbPages - centralCursor; 1934 1935 int cursor = 1; 1936 1937 // Before first separator 1938 cursor = _paginationFirstPages(nbPages, nbFirstPages, currentPage, values, cursor); 1939 1940 // First separator 1941 cursor = _paginationFirstSeparator(nbPages, firstSeparator, currentPage, values, cursor); 1942 1943 int offset = _paginationComputeOffsetAfterFirstSeparator(nbPages, currentPage, nbCentralPages, nbLastPages, centerOfCentralPages, firstSeparator, secondSeparator, cursor); 1944 1945 // Middle part 1946 cursor = _paginationMiddle(nbPages, currentPage, nbFirstPages, nbCentralPages, values, cursor, offset); 1947 1948 // Second separator 1949 cursor = _paginationSecondSeparator(nbPages, secondSeparator, currentPage, nbLastPages, values, cursor, offset); 1950 1951 // After second separator 1952 cursor = _paginationLastPages(nbPages, currentPage, displayedPages, values, cursor, offset); 1953 1954 return values; 1955 } 1956 1957 private static int _paginationMiddle(int nbPages, int currentPage, int nbFirstPages, int nbCentralPages, int[] values, int cursorP, int offset) 1958 { 1959 int cursor = cursorP; 1960 for (; cursor <= nbFirstPages + 1 + nbCentralPages; cursor++) 1961 { 1962 if (cursor + offset > nbPages) 1963 { 1964 values[cursor - 1] = _PAGINATION_SPACE; 1965 } 1966 else if (cursor + offset == currentPage) 1967 { 1968 values[cursor - 1] = _PAGINATION_CURRENT; 1969 } 1970 else 1971 { 1972 values[cursor - 1] = offset + cursor; 1973 } 1974 } 1975 return cursor; 1976 } 1977 1978 private static int _paginationComputeOffsetAfterFirstSeparator(int nbPages, int currentPage, int nbCentralPages, int nbLastPages, int centerOfCentralPages, boolean firstSeparator, boolean secondSeparator, int cursor) 1979 { 1980 if (!firstSeparator) 1981 { 1982 return 0; 1983 } 1984 else if (!secondSeparator) 1985 { 1986 return nbPages - nbLastPages - nbCentralPages - cursor; 1987 } 1988 else 1989 { 1990 return currentPage + 1 - centerOfCentralPages - cursor; 1991 } 1992 } 1993 1994 private static int _paginationLastPages(int nbPages, int currentPage, int displayedPages, int[] values, int cursorP, int offset) 1995 { 1996 int cursor = cursorP; 1997 for (; cursor <= displayedPages; cursor++) 1998 { 1999 if (cursor > nbPages) 2000 { 2001 values[cursor - 1] = _PAGINATION_SPACE; 2002 } 2003 else if (cursor + offset == currentPage) 2004 { 2005 values[cursor - 1] = _PAGINATION_CURRENT; 2006 } 2007 else 2008 { 2009 values[cursor - 1] = nbPages - (displayedPages - cursor); 2010 } 2011 } 2012 return cursor; 2013 } 2014 2015 private static int _paginationSecondSeparator(int nbPages, boolean secondSeparator, int currentPage, int nbLastPages, int[] values, int cursor, int offset) 2016 { 2017 if (cursor + offset > nbPages) 2018 { 2019 values[cursor - 1] = _PAGINATION_SPACE; 2020 } 2021 else if (currentPage == cursor + offset) 2022 { 2023 values[cursor - 1] = _PAGINATION_CURRENT; 2024 } 2025 else if (secondSeparator) 2026 { 2027 values[cursor - 1] = _PAGINATION_SEPARATOR; 2028 } 2029 else 2030 { 2031 values[cursor - 1] = nbPages - nbLastPages; 2032 } 2033 return cursor + 1; 2034 } 2035 2036 private static int _paginationFirstSeparator(int nbPages, boolean firstSeparator, int currentPage, int[] values, int cursor) 2037 { 2038 if (cursor > nbPages) 2039 { 2040 values[cursor - 1] = _PAGINATION_SPACE; 2041 } 2042 else if (currentPage == cursor) 2043 { 2044 values[cursor - 1] = _PAGINATION_CURRENT; 2045 } 2046 else if (firstSeparator) 2047 { 2048 values[cursor - 1] = _PAGINATION_SEPARATOR; 2049 } 2050 else 2051 { 2052 values[cursor - 1] = cursor; 2053 } 2054 return cursor + 1; 2055 } 2056 2057 private static int _paginationFirstPages(int nbPages, int nbFirstPages, int currentPage, int[] values, int cursorP) 2058 { 2059 int cursor = cursorP; 2060 for (; cursor <= nbFirstPages; cursor++) 2061 { 2062 if (cursor > nbPages) 2063 { 2064 values[cursor - 1] = _PAGINATION_SPACE; 2065 } 2066 else if (cursor == currentPage) 2067 { 2068 values[cursor - 1] = _PAGINATION_CURRENT; 2069 } 2070 else 2071 { 2072 values[cursor - 1] = cursor; 2073 } 2074 } 2075 return cursor; 2076 } 2077 2078 /** 2079 * Get the parameters' values of the current template 2080 * @return the values of template's parameters 2081 */ 2082 public static NodeList templateParameters() 2083 { 2084 List<Node> parameters = new ArrayList<>(); 2085 2086 Page page = _getPageFromRequest(); 2087 if (page != null) 2088 { 2089 Optional<ViewParametersModel> viewParametersModelOptional = _viewParametersManager.getTemplateViewParametersModel(page.getSite().getSkinId(), page.getTemplate()); 2090 if (viewParametersModelOptional.isPresent()) 2091 { 2092 ViewParametersModel viewParametersModel = viewParametersModelOptional.get(); 2093 2094 Collection< ? extends ModelItem> modelItems = viewParametersModel.getModelItems(); 2095 for (ModelItem modelItem : modelItems) 2096 { 2097 Optional<ViewParameterHolder> templateParameterHolderOptional = _viewParametersManager.getTemplateViewParameterHolderWithInheritance(page, modelItem); 2098 if (templateParameterHolderOptional.isPresent()) 2099 { 2100 ViewParameterHolder templateParameterHolder = templateParameterHolderOptional.get(); 2101 List<Node> values = _getNodeValues(templateParameterHolder.getDataHolder(), templateParameterHolder.getPath(), null); 2102 if (values != null) 2103 { 2104 parameters.addAll(values); 2105 } 2106 } 2107 } 2108 } 2109 } 2110 2111 return new AmetysNodeList(parameters); 2112 } 2113 2114 /** 2115 * Returns the value of the given parameter for the current page template, or the empty node if the parameter does not exist. 2116 * @param parameterPath the parameter path. 2117 * @return the value of the given parameter for the current page template. 2118 */ 2119 public static NodeList templateParameter(String parameterPath) 2120 { 2121 return templateParameter(null, parameterPath); 2122 } 2123 2124 /** 2125 * Returns the value of the given parameter for the given page template, or the empty node if the parameter does not exist. 2126 * @param pageId the page id 2127 * @param parameterPath the parameter path. 2128 * @return the value of the given parameter for the given page template. 2129 */ 2130 public static NodeList templateParameter(String pageId, String parameterPath) 2131 { 2132 Page page = StringUtils.isNotBlank(pageId) ? _getPage(pageId) : _getPageFromRequest(); 2133 if (page != null) 2134 { 2135 Optional<ViewParameterHolder> templateParameterHolderOptional = _viewParametersManager.getTemplateViewParameterHolderWithInheritance(page, parameterPath); 2136 if (templateParameterHolderOptional.isPresent()) 2137 { 2138 ViewParameterHolder templateParameterHolder = templateParameterHolderOptional.get(); 2139 List<Node> values = _getNodeValues(templateParameterHolder.getDataHolder(), templateParameterHolder.getPath(), null); 2140 if (values != null) 2141 { 2142 return new AmetysNodeList(values); 2143 } 2144 } 2145 } 2146 2147 return null; 2148 } 2149 2150 /** 2151 * Get the parameters of the current zone 2152 * @return the zone's parameters 2153 */ 2154 public static NodeList zoneParameters() 2155 { 2156 return zoneParameters(null); 2157 } 2158 2159 /** 2160 * Get the parameters of a given zone 2161 * @param zoneName The zone's name. Can be null or empty to get the current zone. 2162 * @return the zone's parameters 2163 */ 2164 public static NodeList zoneParameters(String zoneName) 2165 { 2166 List<Node> parameters = new ArrayList<>(); 2167 2168 Page page = _getPageFromRequest(); 2169 if (page != null) 2170 { 2171 Zone zone = _getZoneForParameter(page, zoneName); 2172 if (zone != null) 2173 { 2174 Optional<ViewParametersModel> viewParametersModelOptional = _viewParametersManager.getZoneViewParametersModel(page.getSite().getSkinId(), page.getTemplate(), zone.getName()); 2175 if (viewParametersModelOptional.isPresent()) 2176 { 2177 ViewParametersModel viewParametersModel = viewParametersModelOptional.get(); 2178 2179 Collection< ? extends ModelItem> modelItems = viewParametersModel.getModelItems(); 2180 for (ModelItem modelItem : modelItems) 2181 { 2182 Optional<ViewParameterHolder> zoneParameterHolderOptional = _viewParametersManager.getZoneViewParameterHolderWithInheritance(page, zone, modelItem); 2183 if (zoneParameterHolderOptional.isPresent()) 2184 { 2185 ViewParameterHolder zoneParameterHolder = zoneParameterHolderOptional.get(); 2186 List<Node> values = _getNodeValues(zoneParameterHolder.getDataHolder(), zoneParameterHolder.getPath(), null); 2187 if (values != null) 2188 { 2189 parameters.addAll(values); 2190 } 2191 } 2192 } 2193 } 2194 } 2195 } 2196 2197 return new AmetysNodeList(parameters); 2198 } 2199 2200 /** 2201 * Returns the value of the given parameter for the current page and current zone, or the empty node if the parameter does not exist. 2202 * @param parameterPath the parameter path. 2203 * @return the value of the given parameter for the current page and current zone. 2204 */ 2205 public static NodeList zoneParameter(String parameterPath) 2206 { 2207 return zoneParameter(null, null, parameterPath); 2208 } 2209 2210 /** 2211 * Returns the value of the given parameter for the current page and given zone, or the empty node if the parameter does not exist. 2212 * @param zoneName the zone name 2213 * @param parameterPath the parameter path. 2214 * @return the value of the given parameter for the current page and given zone. 2215 */ 2216 public static NodeList zoneParameter(String zoneName, String parameterPath) 2217 { 2218 return zoneParameter(null, zoneName, parameterPath); 2219 } 2220 2221 /** 2222 * 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. 2223 * @param pageId the page id 2224 * @param zoneName the zone name 2225 * @param parameterPath the parameter path. 2226 * @return the value of the given parameter for the given page and given zone name. 2227 */ 2228 public static NodeList zoneParameter(String pageId, String zoneName, String parameterPath) 2229 { 2230 Page page = StringUtils.isNotBlank(pageId) ? _getPage(pageId) : _getPageFromRequest(); 2231 if (page != null) 2232 { 2233 Zone zone = _getZoneForParameter(page, zoneName); 2234 if (zone != null) 2235 { 2236 Optional<ViewParameterHolder> zoneParameterHolderOptional = _viewParametersManager.getZoneViewParameterHolderWithInheritance(page, zone, parameterPath); 2237 if (zoneParameterHolderOptional.isPresent()) 2238 { 2239 ViewParameterHolder zoneParameterHolder = zoneParameterHolderOptional.get(); 2240 List<Node> values = _getNodeValues(zoneParameterHolder.getDataHolder(), zoneParameterHolder.getPath(), null); 2241 if (values != null) 2242 { 2243 return new AmetysNodeList(values); 2244 } 2245 } 2246 } 2247 } 2248 2249 return null; 2250 } 2251 2252 /** 2253 * Get the parameters of the current zone item 2254 * @return the zone items's parameters 2255 */ 2256 public static NodeList zoneItemParameters() 2257 { 2258 return zoneItemParameters(null); 2259 } 2260 2261 /** 2262 * Get the parameters of a given zone item 2263 * @param zoneItemId The id of zone item. Can be null or empty to get the current zone item 2264 * @return the zone items's parameters 2265 */ 2266 public static NodeList zoneItemParameters(String zoneItemId) 2267 { 2268 List<Node> parameters = new ArrayList<>(); 2269 2270 ZoneItem zoneItem = StringUtils.isNotBlank(zoneItemId) ? _getZoneItem(zoneItemId) : _getZoneItemFromRequest(); 2271 if (zoneItem != null) 2272 { 2273 Optional<ViewParametersModel> viewParametersModelOptional = _viewParametersManager.getZoneItemViewParametersModel(zoneItem); 2274 if (viewParametersModelOptional.isPresent()) 2275 { 2276 Collection< ? extends ModelItem> modelItems = viewParametersModelOptional.get().getModelItems(); 2277 for (ModelItem modelItem : modelItems) 2278 { 2279 List<Node> values = _getNodeValues(zoneItem.getZoneItemParametersHolder(), modelItem.getPath(), null); 2280 if (values != null) 2281 { 2282 parameters.addAll(values); 2283 } 2284 } 2285 } 2286 } 2287 2288 return new AmetysNodeList(parameters); 2289 } 2290 2291 /** 2292 * Returns the value of the given parameter for the current zone item, or the empty node if the parameter does not exist. 2293 * @param parameterPath the parameter path. 2294 * @return the value of the given parameter for the current zone item. 2295 */ 2296 public static NodeList zoneItemParameter(String parameterPath) 2297 { 2298 return zoneItemParameter(null, parameterPath); 2299 } 2300 2301 /** 2302 * Returns the value of the given parameter for the given zone item, or the empty node if the parameter does not exist. 2303 * @param zoneItemId the zone item id 2304 * @param parameterPath the parameter path. 2305 * @return the value of the given parameter for the given zone item. 2306 */ 2307 public static NodeList zoneItemParameter(String zoneItemId, String parameterPath) 2308 { 2309 ZoneItem zoneItem = StringUtils.isNotBlank(zoneItemId) ? _getZoneItem(zoneItemId) : _getZoneItemFromRequest(); 2310 if (zoneItem != null) 2311 { 2312 ModelAwareDataHolder dataHolder = zoneItem.getZoneItemParametersHolder(); 2313 List<Node> values = _getNodeValues(dataHolder, parameterPath, null); 2314 if (values != null) 2315 { 2316 return new AmetysNodeList(values); 2317 } 2318 } 2319 2320 return null; 2321 } 2322 2323 /** 2324 * Get the parameters of the current service 2325 * @return the service's parameters 2326 */ 2327 public static NodeList serviceViewParameters() 2328 { 2329 List<Node> parameters = new ArrayList<>(); 2330 2331 ZoneItem zoneItem = _getZoneItemFromRequest(); 2332 if (zoneItem != null) 2333 { 2334 if (zoneItem.getType() == ZoneType.SERVICE) 2335 { 2336 Optional<ViewParametersModel> serviceViewParametersModel = _viewParametersManager.getServiceViewParametersModel(zoneItem); 2337 if (serviceViewParametersModel.isPresent()) 2338 { 2339 String viewName = zoneItem.getServiceParameters().getValue(ViewParametersManager.SERVICE_VIEW_DEFAULT_MODEL_ITEM_NAME); 2340 2341 Collection< ? extends ModelItem> modelItems = serviceViewParametersModel.get().getModelItems(); 2342 for (ModelItem modelItem : modelItems) 2343 { 2344 List<Node> values = _getNodeValues(zoneItem.getServiceViewParametersHolder(viewName), modelItem.getPath(), null); 2345 if (values != null) 2346 { 2347 parameters.addAll(values); 2348 } 2349 } 2350 } 2351 } 2352 } 2353 2354 return new AmetysNodeList(parameters); 2355 } 2356 2357 /** 2358 * Returns the value of the given parameter for the current service, or the empty node if the parameter does not exist. 2359 * @param parameterPath the parameter path. 2360 * @return the value of the given parameter for the current service. 2361 */ 2362 public static NodeList serviceViewParameter(String parameterPath) 2363 { 2364 ZoneItem zoneItem = _getZoneItemFromRequest(); 2365 if (zoneItem != null) 2366 { 2367 if (zoneItem.getType() == ZoneType.SERVICE) 2368 { 2369 Optional<ModelAwareDataHolder> serviceViewParametersHolder = _viewParametersManager.getServiceViewParametersHolder(zoneItem); 2370 if (serviceViewParametersHolder.isPresent()) 2371 { 2372 List<Node> values = _getNodeValues(serviceViewParametersHolder.get(), parameterPath, null); 2373 if (values != null) 2374 { 2375 return new AmetysNodeList(values); 2376 } 2377 } 2378 } 2379 } 2380 2381 return null; 2382 } 2383 2384 /** 2385 * Get the parameters of the current content 2386 * @return the content's parameters 2387 */ 2388 public static NodeList contentViewParameters() 2389 { 2390 List<Node> parameters = new ArrayList<>(); 2391 2392 ZoneItem zoneItem = _getZoneItemFromRequest(); 2393 if (zoneItem != null) 2394 { 2395 if (zoneItem.getType() == ZoneType.CONTENT) 2396 { 2397 Content content = _getContentFromRequest(); 2398 Content zoneItemContent = zoneItem.getContent(); 2399 2400 // 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 2401 if (content != null && content.getId().equals(zoneItemContent.getId())) 2402 { 2403 Optional<ViewParametersModel> contentViewParametersModel = _viewParametersManager.getContentViewParametersModel(zoneItem); 2404 if (contentViewParametersModel.isPresent()) 2405 { 2406 String viewName = zoneItem.getViewName(); 2407 Collection< ? extends ModelItem> modelItems = contentViewParametersModel.get().getModelItems(); 2408 for (ModelItem modelItem : modelItems) 2409 { 2410 DataContext context = RepositoryDataContext.newInstance() 2411 .withObject(content); 2412 2413 List<Node> values = _getNodeValues(zoneItem.getContentViewParametersHolder(viewName), modelItem.getPath(), null, context); 2414 if (values != null) 2415 { 2416 parameters.addAll(values); 2417 } 2418 } 2419 } 2420 } 2421 } 2422 } 2423 2424 return new AmetysNodeList(parameters); 2425 } 2426 2427 /** 2428 * Returns the value of the given parameter for the current content, or the empty node if the parameter does not exist. 2429 * @param parameterPath the parameter path. 2430 * @return the value of the given parameter for the current content. 2431 */ 2432 public static NodeList contentViewParameter(String parameterPath) 2433 { 2434 ZoneItem zoneItem = _getZoneItemFromRequest(); 2435 if (zoneItem != null) 2436 { 2437 if (zoneItem.getType() == ZoneType.CONTENT) 2438 { 2439 Content content = _getContentFromRequest(); 2440 Content zoneItemContent = zoneItem.getContent(); 2441 2442 // 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 2443 if (content != null && content.getId().equals(zoneItemContent.getId())) 2444 { 2445 Optional<ModelAwareDataHolder> contentViewParametersHolder = _viewParametersManager.getContentViewParametersHolder(zoneItem); 2446 if (contentViewParametersHolder.isPresent()) 2447 { 2448 DataContext context = RepositoryDataContext.newInstance() 2449 .withObject(content); 2450 2451 List<Node> values = _getNodeValues(contentViewParametersHolder.get(), parameterPath, null, context); 2452 if (values != null) 2453 { 2454 return new AmetysNodeList(values); 2455 } 2456 } 2457 } 2458 } 2459 } 2460 2461 return null; 2462 } 2463 2464 private static Zone _getZoneForParameter(Page page, String zoneName) 2465 { 2466 Zone zone = _getZone(page, zoneName); 2467 if (zone == null) 2468 { 2469 zone = _getZoneFromRequest(page); 2470 if (zone == null) 2471 { 2472 ZoneItem zoneItem = _getZoneItemFromRequest(); 2473 if (zoneItem != null) 2474 { 2475 zone = zoneItem.getZone(); 2476 } 2477 } 2478 } 2479 2480 return zone; 2481 } 2482}