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