001/* 002 * Copyright 2015 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 */ 016package org.ametys.web.repository.page; 017 018import java.util.ArrayList; 019import java.util.HashMap; 020import java.util.List; 021import java.util.Map; 022import java.util.Set; 023 024import org.apache.avalon.framework.component.Component; 025import org.apache.avalon.framework.service.ServiceException; 026import org.apache.avalon.framework.service.ServiceManager; 027import org.apache.commons.lang3.StringUtils; 028 029import org.ametys.core.right.RightManager; 030import org.ametys.core.right.RightManager.RightResult; 031import org.ametys.core.ui.Callable; 032import org.ametys.core.user.CurrentUserProvider; 033import org.ametys.core.user.UserIdentity; 034import org.ametys.plugins.repository.AmetysObject; 035import org.ametys.plugins.repository.AmetysObjectIterable; 036import org.ametys.plugins.repository.AmetysObjectResolver; 037import org.ametys.plugins.repository.UnknownAmetysObjectException; 038import org.ametys.web.repository.site.Site; 039import org.ametys.web.repository.site.SiteManager; 040import org.ametys.web.repository.sitemap.Sitemap; 041import org.ametys.web.sitemap.SitemapIndicatorsHandler; 042import org.ametys.web.sitemap.SitemapTreeIndicator; 043 044/** 045 * DAO for manipulating pages 046 */ 047public class SitemapDAO extends AbstractSitemapElementsDAO implements Component 048{ 049 /** The component's role */ 050 public static final String ROLE = SitemapDAO.class.getName(); 051 052 private AmetysObjectResolver _resolver; 053 private RightManager _rightManager; 054 private CurrentUserProvider _currentUserProvider; 055 private SiteManager _siteManager; 056 private SitemapIndicatorsHandler _sitemapHandler; 057 058 @Override 059 public void service(ServiceManager smanager) throws ServiceException 060 { 061 super.service(smanager); 062 063 _resolver = (AmetysObjectResolver) smanager.lookup(AmetysObjectResolver.ROLE); 064 _rightManager = (RightManager) smanager.lookup(RightManager.ROLE); 065 _currentUserProvider = (CurrentUserProvider) smanager.lookup(CurrentUserProvider.ROLE); 066 _siteManager = (SiteManager) smanager.lookup(SiteManager.ROLE); 067 _sitemapHandler = (SitemapIndicatorsHandler) smanager.lookup(SitemapIndicatorsHandler.ROLE); 068 } 069 070 /** 071 * Get sitemap properties 072 * @param sitemapId the sitemap ID 073 * @return the sitemap's properties or null if not found 074 */ 075 public Map<String, Object> getSitemap(String sitemapId) 076 { 077 return getSitemap(sitemapId, null, null); 078 } 079 080 /** 081 * Get sitemap properties 082 * @param sitemapId the sitemap ID 083 * @param zoneName The optional zone name to limit informations of zones to that zone. Can be null or empty to avoid limitation. 084 * @param zoneItemId The optional zone item identifier to limit informations of zones to that zone item. Can be null or empty to avoid limitation. 085 * @return the sitemap's properties or null if not found 086 */ 087 @Callable(rights = Callable.NO_CHECK_REQUIRED) // Required by the SitemapMessageTargetFactory 088 public Map<String, Object> getSitemap(String sitemapId, String zoneName, String zoneItemId) 089 { 090 try 091 { 092 Sitemap sitemap = _resolver.resolveById(sitemapId); 093 094 Map<String, Object> infos = new HashMap<>(); 095 096 infos.put("id", sitemap.getId()); 097 infos.put("name", sitemap.getName()); 098 infos.put("siteName", sitemap.getSiteName()); 099 infos.put("isModifiable", true); 100 infos.put("rights", getUserRights(sitemap)); 101 102 String type = sitemap.getTemplate() != null ? "container" : "node"; 103 infos.put("type", type); 104 105 // limitation information 106 if (StringUtils.isNotBlank(zoneName)) 107 { 108 infos.put("zoneName", zoneName); 109 } 110 if (StringUtils.isNotBlank(zoneItemId)) 111 { 112 infos.put("zoneItemId", zoneItemId); 113 } 114 115 switch (type) 116 { 117 case "container": 118 infos.putAll(_sitemapElement2json(sitemap, zoneName, zoneItemId)); 119 break; 120 default: 121 } 122 123 return infos; 124 } 125 catch (UnknownAmetysObjectException e) 126 { 127 return null; 128 } 129 } 130 131 /** 132 * Get properties of a site, sitemap or on sites root node 133 * @param siteName the site name. Set to null to get properties of sites root node 134 * @param lang the sitemap language. Set to null to get properties of site node 135 * @return the properties 136 */ 137 public Map<String, Object> getProperties(String siteName, String lang) 138 { 139 Map<String, Object> result = new HashMap<>(); 140 141 if (StringUtils.isEmpty(siteName)) 142 { 143 // Get information on root sites node 144 AmetysObject root = _siteManager.getRoot(); 145 result.put("id", root.getId()); 146 result.put("name", root.getId()); 147 } 148 else if (StringUtils.isEmpty(lang)) 149 { 150 // Get properties on site node 151 Site site = _siteManager.getSite(siteName); 152 result.put("id", site.getId()); 153 result.put("name", site.getName()); 154 result.put("title", site.getTitle()); 155 } 156 else 157 { 158 // Get properties on sitemap node 159 result = getSitemapProperties(siteName, lang, null); 160 } 161 162 return result; 163 } 164 165 /** 166 * Get the sitemap properties as JSON object 167 * @param siteName the site name. Set to null to get properties of sites root node 168 * @param lang the sitemap language. Set to null to get properties of site node 169 * @param rights If not null, the sitemap properties will contain a 'isAllowed' property based on user rights. Can be null. 170 * @return the sitemap properties 171 */ 172 @Callable(rights = Callable.NO_CHECK_REQUIRED) // required by the select-page widget 173 public Map<String, Object> getSitemapProperties(String siteName, String lang, List<String> rights) 174 { 175 Site site = _siteManager.getSite(siteName); 176 Sitemap sitemap = site.getSitemap(lang); 177 178 return getSitemapProperties(sitemap, rights); 179 } 180 181 /** 182 * Get the sitemap properties into a JSON object 183 * @param sitemap The sitemap 184 * @param rightsToCheck If not null, the sitemap properties will contain a 'isAllowed' property based on user rights. Can be null. 185 * @return the sitemap properties 186 */ 187 public Map<String, Object> getSitemapProperties(Sitemap sitemap, List<String> rightsToCheck) 188 { 189 Map<String, Object> jsonObject = new HashMap<>(); 190 191 jsonObject.put("id", sitemap.getId()); 192 jsonObject.put("name", sitemap.getName()); 193 jsonObject.put("lang", sitemap.getName()); 194 jsonObject.put("siteName", sitemap.getSiteName()); 195 196 if (rightsToCheck != null) 197 { 198 jsonObject.put("isAllowed", isCurrentUserAllowed(sitemap, rightsToCheck)); 199 } 200 201 return jsonObject; 202 } 203 204 /** 205 * Get the properties of a page in order to display it into a sitemap tree 206 * @param pageId The page's id 207 * @return The page's properties 208 */ 209 @Callable(rights = "Web_Rights_Tool_Sitemap") 210 public Map<String, Object> getPageProperties(String pageId) 211 { 212 return getPageProperties((Page) _resolver.resolveById(pageId)); 213 } 214 215 /** 216 * Get the properties of a page in order to display it into a sitemap tree 217 * @param page The page 218 * @return The page's properties 219 */ 220 public Map<String, Object> getPageProperties(Page page) 221 { 222 return getPageProperties(page, null); 223 } 224 225 /** 226 * Get the properties of a page in order to display it into a sitemap tree 227 * @param page The page 228 * @param rightsToCheck If not null, the page properties will contain a 'isAllowed' property based on user rights 229 * @return The page's properties 230 */ 231 public Map<String, Object> getPageProperties(Page page, List<String> rightsToCheck) 232 { 233 boolean hasChild = page.getChildrenPages().iterator().hasNext(); 234 boolean isLocked = page instanceof LockablePage lockablePage && lockablePage.isLocked(); 235 Map<String, Object> jsonObject = new HashMap<>(); 236 237 jsonObject.put("id", page.getId()); 238 jsonObject.put("name", page.getName()); 239 jsonObject.put("siteName", page.getSiteName()); 240 jsonObject.put("lang", page.getSitemapName()); 241 jsonObject.put("title", page.getTitle()); 242 jsonObject.put("longTitle", page.getLongTitle()); 243 jsonObject.put("type", page.getType()); 244 jsonObject.put("template", page.getTemplate()); 245 jsonObject.put("path", page.getPathInSitemap()); 246 jsonObject.put("moveable", page instanceof MoveablePage && !isLocked); 247 jsonObject.put("modifiable", page instanceof ModifiablePage); 248 jsonObject.put("hasChild", hasChild); 249 jsonObject.put("locked", isLocked); 250 251 SitemapTreeIndicator icon = _sitemapHandler.getIcon(page); 252 253 jsonObject.put("iconGlyph", icon.getIconGlyph()); 254 jsonObject.put("iconDecorator", icon.getIconDecorator()); 255 jsonObject.put("iconSmall", icon.getIcon()); 256 257 List<String> decorators = new ArrayList<>(); 258 for (SitemapTreeIndicator decorator : _sitemapHandler.getDecorators(page)) 259 { 260 decorators.add(decorator.getId()); 261 } 262 jsonObject.put("decorators", StringUtils.join(decorators, ",")); 263 264 if (!hasChild) 265 { 266 jsonObject.put("pages", new ArrayList<>()); 267 } 268 269 if (rightsToCheck != null) 270 { 271 jsonObject.put("isAllowed", isCurrentUserAllowed(page, rightsToCheck)); 272 } 273 return jsonObject; 274 } 275 276 /** 277 * Determines if the current user has the requested right on this sitemap element 278 * @param sitemapElement The sitemap element 279 * @param rights The rights to check 280 * @return true if the current user is allowed 281 */ 282 public boolean isCurrentUserAllowed(SitemapElement sitemapElement, List<String> rights) 283 { 284 if (rights == null || rights.isEmpty()) 285 { 286 return true; 287 } 288 289 for (String rightId : rights) 290 { 291 if (_rightManager.currentUserHasRight(rightId, sitemapElement) != RightResult.RIGHT_ALLOW) 292 { 293 return false; 294 } 295 } 296 297 return true; 298 } 299 300 /** 301 * Get the path of pages which match filter regexp 302 * @param id The id of page or sitemap to start search 303 * @param value the value to match 304 * @return the matching paths 305 */ 306 @Callable(rights = Callable.NO_CHECK_REQUIRED) // required by the select-page widget 307 public List<String> filterPagesByRegExp(String id, String value) 308 { 309 List<String> matchingPaths = new ArrayList<>(); 310 311 SitemapElement container = _resolver.resolveById(id); 312 313 String toMatch = StringUtils.stripAccents(value.toLowerCase()).trim(); 314 315 AmetysObjectIterable< ? extends Page> childrenPages = container.getChildrenPages(); 316 for (Page childPage : childrenPages) 317 { 318 _getMatchingPages(childPage, toMatch, matchingPaths); 319 } 320 321 return matchingPaths; 322 } 323 324 private void _getMatchingPages(Page page, String value, List<String> matchingPaths) 325 { 326 String title = StringUtils.stripAccents(page.getTitle().toLowerCase()); 327 if (title.contains(value)) 328 { 329 matchingPaths.add(page.getPathInSitemap()); 330 } 331 332 AmetysObjectIterable< ? extends Page> childrenPages = page.getChildrenPages(); 333 for (Page childPage : childrenPages) 334 { 335 _getMatchingPages (childPage, value, matchingPaths); 336 } 337 } 338 339 /** 340 * Get the sitemap's decorators 341 * @param siteName the site name 342 * @return the list of decorators 343 */ 344 public List<Map<String, Object>> getDecorators (String siteName) 345 { 346 Site site = _siteManager.getSite(siteName); 347 348 List<Map<String, Object>> decorators = new ArrayList<>(); 349 350 for (SitemapTreeIndicator decorator : _sitemapHandler.getDecorators(site)) 351 { 352 Map<String, Object> object = new HashMap<>(); 353 object.put("id", decorator.getId()); 354 object.put("label", decorator.getLabel()); 355 356 if (StringUtils.isNotBlank(decorator.getIcon())) 357 { 358 object.put("icon", decorator.getIcon()); 359 } 360 if (StringUtils.isNotBlank(decorator.getIconGlyph())) 361 { 362 object.put("iconGlyph", decorator.getIconGlyph()); 363 } 364 365 decorators.add(object); 366 } 367 368 return decorators; 369 } 370 371 /** 372 * Get the id of a page from its site name, language and sitemap's path 373 * @param siteName The site name 374 * @param lang The language 375 * @param path the page's path. Can be null to get sitemap's id 376 * @return the page id or null if not found 377 */ 378 @Callable(rights = Callable.NO_CHECK_REQUIRED) 379 public String convertPathToId (String siteName, String lang, String path) 380 { 381 assert lang != null; 382 assert siteName != null; 383 384 Site site = _siteManager.getSite(siteName); 385 assert site != null; 386 387 Sitemap sitemap = site.getSitemap(lang); 388 assert sitemap != null; 389 390 try 391 { 392 if (path != null) 393 { 394 return sitemap.getChild(path).getId(); 395 } 396 else 397 { 398 return sitemap.getId(); 399 } 400 } 401 catch (UnknownAmetysObjectException e) 402 { 403 return null; 404 } 405 } 406 407 408 /** 409 * Get the user rights on a sitemap 410 * @param sitemap the sitemap 411 * @return The user's rights 412 */ 413 protected Set<String> getUserRights (Sitemap sitemap) 414 { 415 UserIdentity user = _currentUserProvider.getUser(); 416 return _rightManager.getUserRights(user, sitemap); 417 } 418}