001/* 002 * Copyright 2021 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.plugins.forms.dao; 017 018import java.time.LocalDate; 019import java.time.ZonedDateTime; 020import java.util.ArrayList; 021import java.util.HashMap; 022import java.util.List; 023import java.util.Map; 024import java.util.Optional; 025import java.util.stream.Collectors; 026 027import javax.jcr.Node; 028import javax.jcr.Repository; 029import javax.jcr.RepositoryException; 030 031import org.apache.avalon.framework.component.Component; 032import org.apache.avalon.framework.service.ServiceException; 033import org.apache.avalon.framework.service.ServiceManager; 034import org.apache.avalon.framework.service.Serviceable; 035import org.apache.commons.lang.StringUtils; 036import org.apache.jackrabbit.util.Text; 037 038import org.ametys.core.right.RightManager; 039import org.ametys.core.right.RightManager.RightResult; 040import org.ametys.core.ui.Callable; 041import org.ametys.core.user.CurrentUserProvider; 042import org.ametys.core.user.UserIdentity; 043import org.ametys.core.util.DateUtils; 044import org.ametys.core.util.I18nUtils; 045import org.ametys.plugins.core.user.UserHelper; 046import org.ametys.plugins.forms.helper.ScheduleOpeningHelper; 047import org.ametys.plugins.forms.repository.Form; 048import org.ametys.plugins.forms.repository.FormDirectory; 049import org.ametys.plugins.forms.repository.FormEntry; 050import org.ametys.plugins.forms.repository.FormFactory; 051import org.ametys.plugins.forms.repository.FormQuestion; 052import org.ametys.plugins.repository.AmetysObject; 053import org.ametys.plugins.repository.AmetysObjectIterable; 054import org.ametys.plugins.repository.AmetysObjectResolver; 055import org.ametys.plugins.repository.ModifiableAmetysObject; 056import org.ametys.plugins.repository.UnknownAmetysObjectException; 057import org.ametys.plugins.repository.jcr.NameHelper; 058import org.ametys.plugins.repository.provider.AbstractRepository; 059import org.ametys.plugins.workflow.support.WorkflowHelper; 060import org.ametys.runtime.i18n.I18nizableText; 061import org.ametys.runtime.model.ElementDefinition; 062import org.ametys.runtime.plugin.component.AbstractLogEnabled; 063import org.ametys.web.parameters.view.ViewParametersManager; 064import org.ametys.web.repository.page.ModifiableZoneItem; 065import org.ametys.web.repository.page.Page; 066import org.ametys.web.repository.page.SitemapElement; 067import org.ametys.web.repository.page.ZoneDAO; 068import org.ametys.web.repository.page.ZoneItem; 069import org.ametys.web.repository.site.SiteManager; 070import org.ametys.web.service.Service; 071import org.ametys.web.service.ServiceExtensionPoint; 072 073/** 074 * The form DAO 075 */ 076public class FormDAO extends AbstractLogEnabled implements Serviceable, Component 077{ 078 /** The Avalon role */ 079 public static final String ROLE = FormDAO.class.getName(); 080 /** The right id to handle forms */ 081 public static final String HANDLE_FORMS_RIGHT_ID = "Plugins_Forms_Right_Handle"; 082 083 /** The Ametys object resolver */ 084 protected AmetysObjectResolver _resolver; 085 /** The current user provider */ 086 protected CurrentUserProvider _userProvider; 087 /** I18n Utils */ 088 protected I18nUtils _i18nUtils; 089 /** The form directory DAO */ 090 protected FormDirectoryDAO _formDirectoryDAO; 091 /** The form page DAO */ 092 protected FormPageDAO _formPageDAO; 093 /** The form entry DAO */ 094 protected FormEntryDAO _formEntryDAO; 095 /** The user helper */ 096 protected UserHelper _userHelper; 097 /** The JCR repository. */ 098 protected Repository _repository; 099 /** The right manager */ 100 protected RightManager _rightManager; 101 /** The service extension point */ 102 protected ServiceExtensionPoint _serviceEP; 103 /** The zone DAO */ 104 protected ZoneDAO _zoneDAO; 105 /** The schedule opening helper */ 106 protected ScheduleOpeningHelper _scheduleOpeningHelper; 107 /** The workflow helper */ 108 protected WorkflowHelper _workflowHelper; 109 /** The site manager */ 110 protected SiteManager _siteManager; 111 112 public void service(ServiceManager manager) throws ServiceException 113 { 114 _resolver = (AmetysObjectResolver) manager.lookup(AmetysObjectResolver.ROLE); 115 _userProvider = (CurrentUserProvider) manager.lookup(CurrentUserProvider.ROLE); 116 _userHelper = (UserHelper) manager.lookup(UserHelper.ROLE); 117 _i18nUtils = (I18nUtils) manager.lookup(I18nUtils.ROLE); 118 _formDirectoryDAO = (FormDirectoryDAO) manager.lookup(FormDirectoryDAO.ROLE); 119 _formPageDAO = (FormPageDAO) manager.lookup(FormPageDAO.ROLE); 120 _formEntryDAO = (FormEntryDAO) manager.lookup(FormEntryDAO.ROLE); 121 _repository = (Repository) manager.lookup(AbstractRepository.ROLE); 122 _rightManager = (RightManager) manager.lookup(RightManager.ROLE); 123 _serviceEP = (ServiceExtensionPoint) manager.lookup(ServiceExtensionPoint.ROLE); 124 _zoneDAO = (ZoneDAO) manager.lookup(ZoneDAO.ROLE); 125 _scheduleOpeningHelper = (ScheduleOpeningHelper) manager.lookup(ScheduleOpeningHelper.ROLE); 126 _workflowHelper = (WorkflowHelper) manager.lookup(WorkflowHelper.ROLE); 127 _siteManager = (SiteManager) manager.lookup(SiteManager.ROLE); 128 } 129 130 /** 131 * Get all forms from a site 132 * @param siteName the site name 133 * @return the list of form 134 */ 135 public List<Form> getForms(String siteName) 136 { 137 String xpathQuery = "//element(" + siteName + ", ametys:site)//element(*, ametys:form)"; 138 return _resolver.query(xpathQuery) 139 .stream() 140 .filter(Form.class::isInstance) 141 .map(Form.class::cast) 142 .collect(Collectors.toList()); 143 } 144 145 /** 146 * Get the form properties 147 * @param formId The form's id 148 * @return The form properties 149 */ 150 @Callable 151 public Map<String, Object> getFormProperties (String formId) 152 { 153 try 154 { 155 Form form = _resolver.resolveById(formId); 156 return getFormProperties(form); 157 } 158 catch (UnknownAmetysObjectException e) 159 { 160 getLogger().warn("Can't find form with id: {}. It probably has just been deleted", formId, e); 161 Map<String, Object> infos = new HashMap<>(); 162 infos.put("id", formId); 163 return infos; 164 } 165 } 166 167 /** 168 * Get the form properties 169 * @param form The form 170 * @return The form properties 171 */ 172 public Map<String, Object> getFormProperties (Form form) 173 { 174 Map<String, Object> infos = new HashMap<>(); 175 176 List<String> fullPath = new ArrayList<>(); 177 fullPath.add(form.getTitle()); 178 179 AmetysObject node = form.getParent(); 180 while (node instanceof FormDirectory && node.getParent() instanceof FormDirectory) // The parent must also be a directory to avoid the root 181 { 182 fullPath.add(0, node.getName()); 183 node = node.getParent(); 184 } 185 List<FormEntry> entries = form.getEntries(); 186 List<SitemapElement> pages = getFormPage(form.getId(), form.getSiteName()); 187 188 infos.put("isForm", true); 189 infos.put("type", "root"); 190 infos.put("id", form.getId()); 191 infos.put("title", form.getTitle()); 192 infos.put("fullPath", String.join(" > ", fullPath)); 193 infos.put("description", form.getDescription()); 194 infos.put("author", _userHelper.user2json(form.getAuthor(), true)); 195 infos.put("contributor", _userHelper.user2json(form.getContributor())); 196 infos.put("lastModificationDate", DateUtils.zonedDateTimeToString(form.getLastModificationDate())); 197 infos.put("creationDate", DateUtils.zonedDateTimeToString(form.getCreationDate())); 198 infos.put("isPublished", !pages.isEmpty()); 199 infos.put("pages", _getPagesInfos(pages)); 200 infos.put("hasEntries", form.hasEntries()); 201 infos.put("nbEntries", form.getActiveEntries().size()); 202 infos.put("entriesAmount", entries.size()); 203 infos.put("lastEntry", _getLastSubmissionDate(entries)); 204 infos.put("hasChildren", form.getPages().size() > 0); 205 206 FormDirectory formDirectoriesRoot = _formDirectoryDAO.getFormDirectoriesRootNode(form.getSiteName()); 207 String parentId = form.getParent().getId().equals(formDirectoriesRoot.getId()) ? FormDirectoryDAO.ROOT_FORM_DIRECTORY_ID : form.getParent().getId(); 208 infos.put("parentId", parentId); 209 210 infos.put("isLimitedToOneEntryByUser", form.isLimitedToOneEntryByUser()); 211 infos.put("isEntriesLimited", form.isEntriesLimited()); 212 Optional<Long> maxEntries = form.getMaxEntries(); 213 if (maxEntries.isPresent()) 214 { 215 infos.put("maxEntries", maxEntries.get()); 216 } 217 infos.put("isQueueEnabled", form.isQueueEnabled()); 218 Optional<Long> queueSize = form.getQueueSize(); 219 if (queueSize.isPresent()) 220 { 221 infos.put("queueSize", queueSize.get()); 222 } 223 224 LocalDate startDate = form.getStartDate(); 225 LocalDate endDate = form.getEndDate(); 226 if (startDate != null || endDate != null) 227 { 228 infos.put("scheduleStatus", _scheduleOpeningHelper.getStatus(form)); 229 if (startDate != null) 230 { 231 infos.put("startDate", DateUtils.localDateToString(startDate)); 232 } 233 if (endDate != null) 234 { 235 infos.put("endDate", DateUtils.localDateToString(endDate)); 236 } 237 } 238 239 infos.put("isConfigured", isFormConfigured(form)); 240 infos.put("receiptAcknowledgement", form.hasValue(Form.RECEIPT_SENDER)); 241 242 String workflowName = form.getWorkflowName(); 243 infos.put("workflowName", workflowName); 244 infos.put("workflowLabel", StringUtils.isNotBlank(workflowName) ? _workflowHelper.getWorkflowLabel(workflowName) : new I18nizableText("plugin.forms", "PLUGINS_FORMS_FORMS_EDITOR_WORKFLOW_NO_WORKFLOW")); 245 246 try 247 { 248 infos.put("path", form.getNode().getPath()); 249 infos.put("uuid", form.getNode().getIdentifier()); 250 } 251 catch (Exception e) 252 { 253 getLogger().error("Can't have JCR property for form id '{}'.", form.getId(), e); 254 } 255 256 UserIdentity currentUser = _userProvider.getUser(); 257 infos.put("canOpenTool", _rightManager.hasRight(currentUser, HANDLE_FORMS_RIGHT_ID, "/cms") == RightResult.RIGHT_ALLOW); 258 infos.put("canRead", hasReadRightOnForm(currentUser, form)); 259 infos.put("canWrite", hasWriteRightOnForm(currentUser, form)); 260 infos.put("canEditRight", hasRightAffectationRightOnForm(currentUser, form)); 261 262 infos.put("isAnonymous", _rightManager.hasAnonymousReadAccess(form)); 263 264 return infos; 265 } 266 267 /** 268 * Creates a {@link Form}. 269 * @param siteName The site name 270 * @param parentId The id of the parent. 271 * @param name name The desired name for the new {@link Form} 272 * @return The id of the created form 273 * @throws Exception if an error occurs during the form creation process 274 */ 275 @Callable 276 public Map<String, String> createForm (String siteName, String parentId, String name) throws Exception 277 { 278 Map<String, String> result = new HashMap<>(); 279 280 FormDirectory rootNode = _formDirectoryDAO.getFormDirectory(siteName, parentId); 281 282 if (!_formDirectoryDAO.hasWriteRightOnFormDirectory(_userProvider.getUser(), rootNode)) 283 { 284 result.put("message", "not-allowed"); 285 return result; 286 } 287 288 // Find unique name 289 String originalName = NameHelper.filterName(name); 290 String uniqueName = originalName; 291 int index = 2; 292 while (rootNode.hasChild(uniqueName)) 293 { 294 uniqueName = originalName + "-" + (index++); 295 } 296 297 Form form = rootNode.createChild(uniqueName, FormFactory.FORM_NODETYPE); 298 299 form.setTitle(name); 300 form.setAuthor(_userProvider.getUser()); 301 form.setCreationDate(ZonedDateTime.now()); 302 form.setLastModificationDate(ZonedDateTime.now()); 303 304 rootNode.saveChanges(); 305 String formId = form.getId(); 306 307 _formPageDAO.createPage(formId, _i18nUtils.translate(new I18nizableText("plugin.forms", "PLUGINS_FORMS_CREATE_PAGE_DEFAULT_NAME"))); 308 309 result.put("id", formId); 310 result.put("name", form.getTitle()); 311 312 return result; 313 } 314 315 /** 316 * Rename a {@link Form} 317 * @param id The id of the form 318 * @param newName The new name for the form 319 * @return A result map 320 */ 321 @Callable 322 public Map<String, String> renameForm (String id, String newName) 323 { 324 Map<String, String> results = new HashMap<>(); 325 326 Form form = _resolver.resolveById(id); 327 328 if (hasWriteRightOnForm(_userProvider.getUser(), form)) 329 { 330 String legalName = Text.escapeIllegalJcrChars(newName); 331 Node node = form.getNode(); 332 try 333 { 334 form.setTitle(newName); 335 form.setContributor(_userProvider.getUser()); 336 form.setLastModificationDate(ZonedDateTime.now()); 337 338 node.getSession().move(node.getPath(), node.getParent().getPath() + '/' + legalName); 339 node.getSession().save(); 340 341 results.put("newName", legalName); 342 } 343 catch (RepositoryException e) 344 { 345 getLogger().warn("Form renaming failed.", e); 346 results.put("message", "cannot-rename"); 347 } 348 } 349 else 350 { 351 results.put("message", "not-allowed"); 352 } 353 354 results.put("id", id); 355 return results; 356 } 357 358 /** 359 * Copies and pastes a form. 360 * @param formDirectoryId The id of the form directory target of the copy 361 * @param formId The id of the form to copy 362 * @return The results 363 */ 364 @Callable 365 public Map<String, String> copyForm(String formDirectoryId, String formId) 366 { 367 Map<String, String> result = new HashMap<>(); 368 369 Form originalForm = _resolver.resolveById(formId); 370 FormDirectory parentFormDirectory = _resolver.resolveById(formDirectoryId); 371 372 if (_rightManager.currentUserHasRight(FormDirectoryDAO.HANDLE_FORM_DIRECTORIES_RIGHT_ID, parentFormDirectory) != RightResult.RIGHT_ALLOW) 373 { 374 result.put("message", "not-allowed"); 375 return result; 376 } 377 378 // Find unique name 379 String originalName = originalForm.getName(); 380 String name = originalName; 381 int index = 2; 382 while (parentFormDirectory.hasChild(name)) 383 { 384 name = originalName + "-" + (index++); 385 } 386 387 Form cForm = originalForm.copyTo(parentFormDirectory, name); 388 originalForm.copyTo(cForm); 389 390 String copyTitle = _i18nUtils.translate(new I18nizableText("plugin.forms", "PLUGIN_FORMS_TREE_COPY_NAME_PREFIX")) + originalForm.getTitle(); 391 cForm.setTitle(copyTitle); 392 cForm.setAuthor(_userProvider.getUser()); 393 cForm.setCreationDate(ZonedDateTime.now()); 394 cForm.setLastModificationDate(ZonedDateTime.now()); 395 396 originalForm.saveChanges(); 397 398 result.put("id", cForm.getId()); 399 400 return result; 401 } 402 403 /** 404 * Deletes a {@link Form}. 405 * @param id The id of the form to delete 406 * @return The id of the form 407 */ 408 @Callable 409 public Map<String, String> deleteForm (String id) 410 { 411 Map<String, String> result = new HashMap<>(); 412 413 Form form = _resolver.resolveById(id); 414 415 List<SitemapElement> pages = getFormPage(form.getId(), form.getSiteName()); 416 if (pages.isEmpty() && hasWriteRightOnForm(_userProvider.getUser(), form)) 417 { 418 ModifiableAmetysObject parent = form.getParent(); 419 form.remove(); 420 parent.saveChanges(); 421 } 422 else 423 { 424 result.put("message", "not-allowed"); 425 } 426 427 result.put("id", id); 428 return result; 429 } 430 431 /** 432 * Moves a {@link Form} 433 * @param siteName name of the site 434 * @param id The id of the form 435 * @param newParentId The id of the new parent directory of the form. 436 * @return A result map 437 */ 438 @Callable 439 public Map<String, Object> moveForm(String siteName, String id, String newParentId) 440 { 441 Map<String, Object> results = new HashMap<>(); 442 Form form = _resolver.resolveById(id); 443 FormDirectory directory = _formDirectoryDAO.getFormDirectory(siteName, newParentId); 444 445 if (hasWriteRightOnForm(_userProvider.getUser(), form) 446 || _formDirectoryDAO.hasWriteRightOnFormDirectory(_userProvider.getUser(), directory)) 447 { 448 _formDirectoryDAO.move(form, siteName, newParentId, results); 449 } 450 else 451 { 452 results.put("message", "not-allowed"); 453 } 454 455 results.put("id", form.getId()); 456 return results; 457 } 458 459 /** 460 * Change workflow of a {@link Form} 461 * @param formId The id of the form 462 * @param workflowName The name of new workflow 463 * @return A result map 464 */ 465 @Callable 466 public Map<String, String> setWorkflow (String formId, String workflowName) 467 { 468 Map<String, String> results = new HashMap<>(); 469 470 Form form = _resolver.resolveById(formId); 471 form.setWorkflowName(workflowName); 472 form.setContributor(_userProvider.getUser()); 473 form.setLastModificationDate(ZonedDateTime.now()); 474 475 form.saveChanges(); 476 477 results.put("id", formId); 478 479 return results; 480 } 481 482 /** 483 * Get the submission date of the last entry to the form 484 * @param entries A list of form entry 485 * @return the date of the last submission 486 */ 487 protected ZonedDateTime _getLastSubmissionDate(List<FormEntry> entries) 488 { 489 ZonedDateTime lastSubmissionDate = null; 490 if (!entries.isEmpty()) 491 { 492 lastSubmissionDate = entries.get(0).getSubmitDate(); 493 for (FormEntry entry : entries) 494 { 495 ZonedDateTime submitDate = entry.getSubmitDate(); 496 if (lastSubmissionDate.isBefore(submitDate)) 497 { 498 lastSubmissionDate = submitDate; 499 } 500 } 501 } 502 return lastSubmissionDate; 503 } 504 505 /** 506 * Get all the page where the form is published 507 * @param formId the form id 508 * @param siteName the site name 509 * @return the list of page 510 */ 511 public List<SitemapElement> getFormPage(String formId, String siteName) 512 { 513 String xpathQuery = "//element(" + siteName + ", ametys:site)//element(*, ametys:zoneItem)[@ametys-internal:service = 'org.ametys.forms.service.Display' and ametys:service_parameters/@ametys:formId = '" + formId + "']"; 514 AmetysObjectIterable<ModifiableZoneItem> zoneItems = _resolver.query(xpathQuery); 515 516 return zoneItems.stream() 517 .map(z -> z.getZone().getSitemapElement()) 518 .collect(Collectors.toList()); 519 } 520 521 /** 522 * Get the page names 523 * @param pages the list of page 524 * @return the list of page name 525 */ 526 protected List<Map<String, Object>> _getPagesInfos(List<SitemapElement> pages) 527 { 528 List<Map<String, Object>> pagesInfos = new ArrayList<>(); 529 for (SitemapElement sitemapElement : pages) 530 { 531 Map<String, Object> info = new HashMap<>(); 532 info.put("id", sitemapElement.getId()); 533 info.put("title", sitemapElement.getTitle()); 534 info.put("isPage", sitemapElement instanceof Page); 535 536 pagesInfos.add(info); 537 } 538 539 return pagesInfos; 540 } 541 542 /** 543 * Get all the view available for the form display service 544 * @param formId the form identifier 545 * @param siteName the site name 546 * @param language the language 547 * @return the views as json 548 * @throws Exception if an error occurred 549 */ 550 @Callable 551 public List<Map<String, Object>> getFormDisplayViews(String formId, String siteName, String language) throws Exception 552 { 553 List<Map<String, Object>> jsonifiedViews = new ArrayList<>(); 554 555 Service service = _serviceEP.getExtension("org.ametys.forms.service.Display"); 556 ElementDefinition viewElementDefinition = (ElementDefinition) service.getParameters().getOrDefault(ViewParametersManager.SERVICE_VIEW_DEFAULT_MODEL_ITEM_NAME, null); 557 558 String xpathQuery = "//element(" + siteName + ", ametys:site)/ametys-internal:sitemaps/" + language 559 + "//element(*, ametys:zoneItem)[@ametys-internal:service = 'org.ametys.forms.service.Display' and ametys:service_parameters/@ametys:formId = '" + formId + "']"; 560 AmetysObjectIterable<ModifiableZoneItem> zoneItems = _resolver.query(xpathQuery); 561 562 Optional<Object> existedServiceView = zoneItems.stream() 563 .map(ZoneItem::getServiceParameters) 564 .map(sp -> sp.getValue(ViewParametersManager.SERVICE_VIEW_DEFAULT_MODEL_ITEM_NAME)) 565 .findFirst(); 566 567 Map<String, I18nizableText> typedEntries = viewElementDefinition.getEnumerator().getTypedEntries(); 568 for (String id : typedEntries.keySet()) 569 { 570 Map<String, Object> viewAsJson = new HashMap<>(); 571 viewAsJson.put("id", id); 572 viewAsJson.put("label", typedEntries.get(id)); 573 574 Boolean isServiceView = existedServiceView.map(s -> s.equals(id)).orElse(false); 575 if (isServiceView || existedServiceView.isEmpty() && id.equals(viewElementDefinition.getDefaultValue())) 576 { 577 viewAsJson.put("isDefault", true); 578 } 579 580 jsonifiedViews.add(viewAsJson); 581 } 582 583 return jsonifiedViews; 584 } 585 586 /** 587 * Check if a user have read rights on a form 588 * @param userIdentity the user 589 * @param form the form 590 * @return true if the user have read rights on a form 591 */ 592 public boolean hasReadRightOnForm(UserIdentity userIdentity, Form form) 593 { 594 return form != null && (userIdentity.equals(form.getAuthor()) || _rightManager.hasReadAccess(userIdentity, form)); 595 } 596 597 /** 598 * Check if a user have write rights on a form 599 * @param userIdentity the user 600 * @param form the form 601 * @return true if the user have write rights on a form 602 */ 603 public boolean hasWriteRightOnForm(UserIdentity userIdentity, Form form) 604 { 605 return form != null && (userIdentity.equals(form.getAuthor()) || _rightManager.hasRight(userIdentity, HANDLE_FORMS_RIGHT_ID, form) == RightResult.RIGHT_ALLOW && _formDirectoryDAO.hasWriteRightOnFormDirectory(userIdentity, form.getParent())); 606 } 607 608 /** 609 * Check if a user have write rights on a form 610 * @param userIdentity the user 611 * @param form the form 612 * @return true if the user have write rights on a form 613 */ 614 public boolean hasRightAffectationRightOnForm(UserIdentity userIdentity, Form form) 615 { 616 return hasWriteRightOnForm(userIdentity, form) || _rightManager.hasRight(userIdentity, "Runtime_Rights_Rights_Handle", "/cms") == RightResult.RIGHT_ALLOW; 617 } 618 619 /** 620 * <code>true</code> if the form is well configured 621 * @param form the form 622 * @return <code>true</code> if the form is well configured 623 */ 624 public boolean isFormConfigured(Form form) 625 { 626 List<FormQuestion> questions = form.getQuestions(); 627 return !questions.isEmpty() && !questions.stream().anyMatch(q -> !q.getType().isQuestionConfigured(q)); 628 } 629 630 /** 631 * Get the dashboard URI 632 * @param siteName the site name 633 * @return the dashboard URI 634 */ 635 public String getDashboardUri(String siteName) 636 { 637 String xpathQuery = "//element(" + siteName + ", ametys:site)//element(*, ametys:zoneItem)[@ametys-internal:service = 'org.ametys.plugins.forms.workflow.service.dashboard']"; 638 AmetysObjectIterable<ModifiableZoneItem> zoneItems = _resolver.query(xpathQuery); 639 640 Optional<Page> dashboardPage = zoneItems.stream() 641 .map(z -> z.getZone().getSitemapElement()) 642 .filter(Page.class::isInstance) 643 .map(Page.class::cast) 644 .findAny(); 645 646 if (dashboardPage.isPresent()) 647 { 648 Page page = dashboardPage.get(); 649 String pagePath = page.getSitemap().getName() + "/" + page.getPathInSitemap() + ".html"; 650 651 String url = _siteManager.getSite(siteName).getUrl(); 652 return url + "/" + pagePath; 653 } 654 655 return StringUtils.EMPTY; 656 } 657 658 /** 659 * Get the admin dashboard URI 660 * @param siteName the site name 661 * @return the admin dashboard URI 662 */ 663 public String getAdminDashboardUri(String siteName) 664 { 665 String xpathQuery = "//element(" + siteName + ", ametys:site)//element(*, ametys:zoneItem)[@ametys-internal:service = 'org.ametys.plugins.forms.workflow.service.admin.dashboard']"; 666 AmetysObjectIterable<ModifiableZoneItem> zoneItems = _resolver.query(xpathQuery); 667 668 Optional<Page> dashboardPage = zoneItems.stream() 669 .map(z -> z.getZone().getSitemapElement()) 670 .filter(Page.class::isInstance) 671 .map(Page.class::cast) 672 .findAny(); 673 674 if (dashboardPage.isPresent()) 675 { 676 Page page = dashboardPage.get(); 677 String pagePath = page.getSitemap().getName() + "/" + page.getPathInSitemap() + ".html"; 678 679 String url = _siteManager.getSite(siteName).getUrl(); 680 return url + "/" + pagePath; 681 } 682 683 return StringUtils.EMPTY; 684 } 685}