001/* 002 * (C) Copyright 2007-2013 Nuxeo SA (http://nuxeo.com/) and others. 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 * Contributors: 017 * Narcis Paslaru 018 * Florent Guillaume 019 * Thierry Martins 020 * Thomas Roger 021 */ 022 023package org.nuxeo.ecm.platform.publisher.web; 024 025import java.io.Serializable; 026import java.util.ArrayList; 027import java.util.Arrays; 028import java.util.Collection; 029import java.util.Collections; 030import java.util.HashMap; 031import java.util.HashSet; 032import java.util.List; 033import java.util.Map; 034import java.util.Set; 035 036import javax.faces.context.FacesContext; 037 038import org.apache.commons.logging.Log; 039import org.apache.commons.logging.LogFactory; 040import org.jboss.seam.ScopeType; 041import org.jboss.seam.annotations.Create; 042import org.jboss.seam.annotations.Destroy; 043import org.jboss.seam.annotations.Factory; 044import org.jboss.seam.annotations.In; 045import org.jboss.seam.annotations.Name; 046import org.jboss.seam.annotations.Observer; 047import org.jboss.seam.annotations.Scope; 048import org.jboss.seam.annotations.intercept.BypassInterceptors; 049import org.jboss.seam.contexts.Contexts; 050import org.jboss.seam.core.Events; 051import org.jboss.seam.faces.FacesMessages; 052import org.jboss.seam.international.StatusMessage; 053import org.nuxeo.ecm.core.api.CoreSession; 054import org.nuxeo.ecm.core.api.DocumentModel; 055import org.nuxeo.ecm.core.api.DocumentRef; 056import org.nuxeo.ecm.core.api.IdRef; 057import org.nuxeo.ecm.core.api.NuxeoException; 058import org.nuxeo.ecm.core.api.PathRef; 059import org.nuxeo.ecm.core.api.UnrestrictedSessionRunner; 060import org.nuxeo.ecm.core.api.event.CoreEventConstants; 061import org.nuxeo.ecm.core.api.event.DocumentEventCategories; 062import org.nuxeo.ecm.core.api.impl.DocumentLocationImpl; 063import org.nuxeo.ecm.core.api.security.SecurityConstants; 064import org.nuxeo.ecm.core.event.Event; 065import org.nuxeo.ecm.core.event.EventProducer; 066import org.nuxeo.ecm.core.event.impl.DocumentEventContext; 067import org.nuxeo.ecm.core.schema.FacetNames; 068import org.nuxeo.ecm.core.schema.SchemaManager; 069import org.nuxeo.ecm.platform.publisher.api.PublicationNode; 070import org.nuxeo.ecm.platform.publisher.api.PublicationTree; 071import org.nuxeo.ecm.platform.publisher.api.PublishedDocument; 072import org.nuxeo.ecm.platform.publisher.api.PublisherService; 073import org.nuxeo.ecm.platform.publisher.api.PublishingEvent; 074import org.nuxeo.ecm.platform.ui.web.util.ComponentUtils; 075import org.nuxeo.ecm.webapp.documentsLists.DocumentsListsManager; 076import org.nuxeo.ecm.webapp.helpers.EventManager; 077import org.nuxeo.ecm.webapp.helpers.EventNames; 078import org.nuxeo.runtime.api.Framework; 079 080/** 081 * This Seam bean manages the publishing tab. 082 * 083 * @author <a href="mailto:troger@nuxeo.com">Thomas Roger</a> 084 */ 085@Name("publishActions") 086@Scope(ScopeType.CONVERSATION) 087public class PublishActionsBean extends AbstractPublishActions implements Serializable { 088 089 public static class PublicationTreeInformation { 090 091 private final String name; 092 093 private final String title; 094 095 public PublicationTreeInformation(String treeName, String treeTitle) { 096 this.name = treeName; 097 this.title = treeTitle; 098 } 099 100 public String getName() { 101 return name; 102 } 103 104 public String getTitle() { 105 return title; 106 } 107 } 108 109 private static final long serialVersionUID = 1L; 110 111 private static final Log log = LogFactory.getLog(PublishActionsBean.class); 112 113 /** 114 * @since 7.3 115 */ 116 public static final List<String> TREE_TYPES_TO_FILTER = Arrays.asList("RootSectionsPublicationTree", "RenditionPublicationCoreTree"); 117 118 @In(create = true) 119 protected transient DocumentsListsManager documentsListsManager; 120 121 @In(create = true, required = false) 122 protected transient FacesMessages facesMessages; 123 124 protected transient PublisherService publisherService; 125 126 protected String currentPublicationTreeNameForPublishing; 127 128 protected PublicationTree currentPublicationTree; 129 130 protected String publishingComment; 131 132 protected static Set<String> sectionTypes; 133 134 protected Map<String, String> publicationParameters = new HashMap<>(); 135 136 @Create 137 public void create() { 138 publisherService = Framework.getService(PublisherService.class); 139 } 140 141 @Destroy 142 public void destroy() { 143 if (currentPublicationTree != null) { 144 currentPublicationTree.release(); 145 currentPublicationTree = null; 146 } 147 } 148 149 protected Map<String, String> filterEmptyTrees(Map<String, String> trees) { 150 151 Map<String, String> filteredTrees = new HashMap<>(); 152 153 List<String> prefilteredTrees = filterEmptyTrees(trees.keySet()); 154 155 for (String ptree : prefilteredTrees) { 156 filteredTrees.put(ptree, trees.get(ptree)); 157 } 158 159 return filteredTrees; 160 } 161 162 protected List<String> filterEmptyTrees(Collection<String> trees) { 163 List<String> filteredTrees = new ArrayList<>(); 164 165 for (String tree : trees) { 166 PublicationTree pTree = publisherService.getPublicationTree(tree, documentManager, null, 167 navigationContext.getCurrentDocument()); 168 if (pTree != null) { 169 if (TREE_TYPES_TO_FILTER.contains(pTree.getTreeType())) { 170 if (pTree.getChildrenNodes().size() > 0) { 171 filteredTrees.add(tree); 172 } 173 } else { 174 filteredTrees.add(tree); 175 } 176 } 177 } 178 return filteredTrees; 179 } 180 181 @Factory(value = "availablePublicationTrees", scope = ScopeType.EVENT) 182 public List<PublicationTreeInformation> getAvailablePublicationTrees() { 183 Map<String, String> trees = publisherService.getAvailablePublicationTrees(); 184 // remove empty trees 185 trees = filterEmptyTrees(trees); 186 List<PublicationTreeInformation> treesInformation = new ArrayList<>(); 187 for (Map.Entry<String, String> entry : trees.entrySet()) { 188 treesInformation.add(new PublicationTreeInformation(entry.getKey(), entry.getValue())); 189 } 190 return treesInformation; 191 } 192 193 public String doPublish(PublicationNode publicationNode) { 194 PublicationTree tree = getCurrentPublicationTreeForPublishing(); 195 return doPublish(tree, publicationNode); 196 } 197 198 public String doPublish(PublicationTree tree, PublicationNode publicationNode) { 199 if (tree == null) { 200 return null; 201 } 202 203 DocumentModel currentDocument = navigationContext.getCurrentDocument(); 204 205 PublishedDocument publishedDocument; 206 try { 207 publishedDocument = tree.publish(currentDocument, publicationNode, publicationParameters); 208 } catch (NuxeoException e) { 209 log.error(e, e); 210 facesMessages.add(StatusMessage.Severity.ERROR, messages.get(e.getMessage())); 211 return null; 212 } 213 214 FacesContext context = FacesContext.getCurrentInstance(); 215 if (publishedDocument.isPending()) { 216 String comment = ComponentUtils.translate(context, "publishing.waiting", publicationNode.getPath(), 217 tree.getConfigName()); 218 // Log event on live version 219 notifyEvent(PublishingEvent.documentWaitingPublication.name(), null, comment, null, currentDocument); 220 Events.instance().raiseEvent(EventNames.DOCUMENT_SUBMITED_FOR_PUBLICATION); 221 facesMessages.add(StatusMessage.Severity.INFO, messages.get("document_submitted_for_publication"), 222 messages.get(currentDocument.getType())); 223 } else { 224 String comment = ComponentUtils.translate(context, "publishing.done", publicationNode.getPath(), 225 tree.getConfigName()); 226 // Log event on live version 227 notifyEvent(PublishingEvent.documentPublished.name(), null, comment, null, currentDocument); 228 Events.instance().raiseEvent(EventNames.DOCUMENT_PUBLISHED); 229 // publish may checkin the document -> change 230 Events.instance().raiseEvent(EventNames.DOCUMENT_CHANGED); 231 facesMessages.add(StatusMessage.Severity.INFO, messages.get("document_published"), 232 messages.get(currentDocument.getType())); 233 } 234 navigationContext.invalidateCurrentDocument(); 235 currentPublicationTree = null; 236 resetCache(); 237 return null; 238 } 239 240 /** 241 * @since 5.9.3 242 */ 243 protected void resetCache() { 244 Contexts.getEventContext().remove("availablePublicationTrees"); 245 Contexts.getEventContext().remove("publishedDocuments"); 246 } 247 248 public void setCurrentPublicationTreeNameForPublishing(String currentPublicationTreeNameForPublishing) 249 { 250 this.currentPublicationTreeNameForPublishing = currentPublicationTreeNameForPublishing; 251 if (currentPublicationTree != null) { 252 currentPublicationTree.release(); 253 currentPublicationTree = null; 254 } 255 currentPublicationTree = getCurrentPublicationTreeForPublishing(); 256 } 257 258 public String getCurrentPublicationTreeNameForPublishing() { 259 if (currentPublicationTreeNameForPublishing == null) { 260 List<String> publicationTrees = new ArrayList<>(publisherService.getAvailablePublicationTree()); 261 publicationTrees = filterEmptyTrees(publicationTrees); 262 if (!publicationTrees.isEmpty()) { 263 currentPublicationTreeNameForPublishing = publicationTrees.get(0); 264 } 265 } 266 return currentPublicationTreeNameForPublishing; 267 } 268 269 /** 270 * Returns a list of publication trees. 271 * <p> 272 * Needed on top of {@link #getCurrentPublicationTreeForPublishing()} because RichFaces tree now requires roots to 273 * be a list. 274 * 275 * @since 6.0 276 */ 277 public List<PublicationTree> getCurrentPublicationTreesForPublishing() { 278 List<PublicationTree> trees = new ArrayList<>(); 279 PublicationTree tree = getCurrentPublicationTreeForPublishing(); 280 if (tree != null) { 281 trees.add(tree); 282 } 283 return trees; 284 } 285 286 public PublicationTree getCurrentPublicationTreeForPublishing() { 287 if (currentPublicationTree == null) { 288 if (getCurrentPublicationTreeNameForPublishing() == null) { 289 return currentPublicationTree; 290 } 291 currentPublicationTree = publisherService.getPublicationTree(currentPublicationTreeNameForPublishing, 292 documentManager, null, navigationContext.getCurrentDocument()); 293 } 294 return currentPublicationTree; 295 } 296 297 public String getCurrentPublicationTreeIconExpanded() { 298 PublicationTree tree = getCurrentPublicationTreeForPublishing(); 299 return tree != null ? tree.getIconExpanded() : ""; 300 } 301 302 public String getCurrentPublicationTreeIconCollapsed() { 303 PublicationTree tree = getCurrentPublicationTreeForPublishing(); 304 return tree != null ? tree.getIconCollapsed() : ""; 305 } 306 307 @Factory(value = "publishedDocuments", scope = ScopeType.EVENT) 308 public List<PublishedDocument> getPublishedDocuments() { 309 PublicationTree tree = getCurrentPublicationTreeForPublishing(); 310 if (tree == null) { 311 return Collections.emptyList(); 312 } 313 314 DocumentModel currentDocument = navigationContext.getCurrentDocument(); 315 return tree.getExistingPublishedDocument(new DocumentLocationImpl(currentDocument)); 316 } 317 318 public List<PublishedDocument> getPublishedDocumentsFor(String treeName) { 319 if (treeName == null || "".equals(treeName)) { 320 return null; 321 } 322 DocumentModel currentDocument = navigationContext.getCurrentDocument(); 323 PublicationTree tree = publisherService.getPublicationTree(treeName, documentManager, null); 324 return tree.getExistingPublishedDocument(new DocumentLocationImpl(currentDocument)); 325 } 326 327 public String unPublish(PublishedDocument publishedDocument) { 328 PublicationTree tree = getCurrentPublicationTreeForPublishing(); 329 if (tree != null) { 330 tree.unpublish(publishedDocument); 331 } 332 // raise event without the container document as user may not have read 333 // rights on it 334 Events.instance().raiseEvent(EventNames.DOCUMENT_CHILDREN_CHANGED); 335 resetCache(); 336 return null; 337 } 338 339 public String rePublish(PublishedDocument publishedDocument) { 340 PublicationTree tree = getCurrentPublicationTreeForPublishing(); 341 if (tree == null) { 342 log.error("Publication tree is null - cannot republish"); 343 facesMessages.add(StatusMessage.Severity.ERROR, messages.get("error.document_republished")); 344 return null; 345 } 346 PublicationNode node = tree.getNodeByPath(publishedDocument.getParentPath()); 347 return doPublish(tree, node); 348 } 349 350 public boolean canPublishTo(PublicationNode publicationNode) { 351 DocumentModel doc = navigationContext.getCurrentDocument(); 352 if (doc == null || documentManager.getLockInfo(doc.getRef()) != null) { 353 return false; 354 } 355 PublicationTree tree = getCurrentPublicationTreeForPublishing(); 356 return tree != null ? tree.canPublishTo(publicationNode) : false; 357 } 358 359 public boolean canUnpublish(PublishedDocument publishedDocument) { 360 PublicationTree tree = getCurrentPublicationTreeForPublishing(); 361 return tree != null ? tree.canUnpublish(publishedDocument) : false; 362 } 363 364 public boolean canRepublish(PublishedDocument publishedDocument) { 365 if (!canUnpublish(publishedDocument)) { 366 return false; 367 } 368 DocumentModel doc = navigationContext.getCurrentDocument(); 369 // version label is different, what means it is a previous version 370 if (!publishedDocument.getSourceVersionLabel().equals(doc.getVersionLabel())) { 371 return true; 372 } 373 // in case it is the same version, we have to check if the current 374 // document has been modified since last publishing 375 if (doc.isDirty()) { 376 return true; 377 } 378 return false; 379 } 380 381 public boolean isPublishedDocument() { 382 return publisherService.isPublishedDocument(navigationContext.getCurrentDocument()); 383 } 384 385 public boolean canManagePublishing() { 386 PublicationTree tree = publisherService.getPublicationTreeFor(navigationContext.getCurrentDocument(), 387 documentManager); 388 PublishedDocument publishedDocument = tree.wrapToPublishedDocument(navigationContext.getCurrentDocument()); 389 return tree.canManagePublishing(publishedDocument); 390 } 391 392 public boolean hasValidationTask() { 393 PublicationTree tree = publisherService.getPublicationTreeFor(navigationContext.getCurrentDocument(), 394 documentManager); 395 PublishedDocument publishedDocument = tree.wrapToPublishedDocument(navigationContext.getCurrentDocument()); 396 return tree.hasValidationTask(publishedDocument); 397 } 398 399 public boolean isPending() { 400 PublicationTree tree = publisherService.getPublicationTreeFor(navigationContext.getCurrentDocument(), 401 documentManager); 402 PublishedDocument publishedDocument = tree.wrapToPublishedDocument(navigationContext.getCurrentDocument()); 403 return publishedDocument.isPending(); 404 } 405 406 public String getPublishingComment() { 407 return publishingComment; 408 } 409 410 public void setPublishingComment(String publishingComment) { 411 this.publishingComment = publishingComment; 412 } 413 414 public class ApproverWithoutRestriction extends UnrestrictedSessionRunner { 415 416 public DocumentModel sourceDocument; 417 418 public DocumentModel liveDocument; 419 420 public String comment; 421 422 public PublishedDocument doc; 423 424 public ApproverWithoutRestriction(PublishedDocument doc, String comment, CoreSession session) { 425 super(session); 426 this.doc = doc; 427 this.comment = comment; 428 } 429 430 @Override 431 public void run() { 432 sourceDocument = session.getDocument(doc.getSourceDocumentRef()); 433 434 // soft dependency on Rendition system 435 if (sourceDocument.hasFacet("Rendition")) { 436 String uid = (String) sourceDocument.getPropertyValue("rend:sourceId"); 437 liveDocument = session.getDocument(new IdRef(uid)); 438 } else { 439 liveDocument = session.getSourceDocument(sourceDocument.getRef()); 440 } 441 sendApprovalEventToSourceDocument(session, sourceDocument, liveDocument, comment); 442 443 } 444 445 protected void sendApprovalEventToSourceDocument(CoreSession session, DocumentModel sourceDocument, 446 DocumentModel liveVersion, String comment) { 447 448 notifyEvent(session, PublishingEvent.documentPublicationApproved.name(), null, comment, null, 449 sourceDocument); 450 451 if (!sourceDocument.getRef().equals(liveVersion.getRef())) { 452 notifyEvent(session, PublishingEvent.documentPublicationApproved.name(), null, comment, null, 453 liveVersion); 454 } 455 } 456 457 } 458 459 public String approveDocument() { 460 DocumentModel currentDocument = navigationContext.getCurrentDocument(); 461 PublicationTree tree = publisherService.getPublicationTreeFor(currentDocument, documentManager); 462 PublishedDocument publishedDocument = tree.wrapToPublishedDocument(currentDocument); 463 tree.validatorPublishDocument(publishedDocument, publishingComment); 464 465 FacesContext context = FacesContext.getCurrentInstance(); 466 String comment = publishingComment != null && publishingComment.length() > 0 ? ComponentUtils.translate( 467 context, "publishing.approved.with.comment", publishedDocument.getParentPath(), tree.getConfigName(), 468 publishingComment) : ComponentUtils.translate(context, "publishing.approved.without.comment", 469 publishedDocument.getParentPath(), tree.getConfigName()); 470 471 ApproverWithoutRestriction approver = new ApproverWithoutRestriction(publishedDocument, comment, 472 documentManager); 473 if (documentManager.hasPermission(publishedDocument.getSourceDocumentRef(), SecurityConstants.WRITE)) { 474 approver.run(); 475 } else { 476 approver.runUnrestricted(); 477 } 478 479 Events.instance().raiseEvent(EventNames.DOCUMENT_PUBLISHED); 480 Events.instance().raiseEvent(EventNames.DOCUMENT_PUBLICATION_APPROVED); 481 return null; 482 } 483 484 public String rejectDocument() { 485 if (publishingComment == null || "".equals(publishingComment)) { 486 facesMessages.addToControl("publishingComment", StatusMessage.Severity.ERROR, 487 messages.get("label.publishing.reject.user.comment.mandatory")); 488 return null; 489 } 490 491 DocumentModel currentDocument = navigationContext.getCurrentDocument(); 492 PublicationTree tree = publisherService.getPublicationTreeFor(currentDocument, documentManager); 493 PublishedDocument publishedDocument = tree.wrapToPublishedDocument(currentDocument); 494 tree.validatorRejectPublication(publishedDocument, publishingComment); 495 496 FacesContext context = FacesContext.getCurrentInstance(); 497 String comment = publishingComment != null && publishingComment.length() > 0 ? ComponentUtils.translate( 498 context, "publishing.rejected.with.comment", publishedDocument.getParentPath(), tree.getConfigName(), 499 publishingComment) : ComponentUtils.translate(context, "publishing.rejected.without.comment", 500 publishedDocument.getParentPath(), tree.getConfigName()); 501 RejectWithoutRestrictionRunner runner = new RejectWithoutRestrictionRunner(documentManager, publishedDocument, 502 comment); 503 504 if (documentManager.hasPermission(publishedDocument.getSourceDocumentRef(), SecurityConstants.READ)) { 505 runner.run(); 506 } else { 507 runner.runUnrestricted(); 508 } 509 Events.instance().raiseEvent(EventNames.DOCUMENT_PUBLICATION_REJECTED); 510 511 return navigationContext.navigateToRef(navigationContext.getCurrentDocument().getParentRef()); 512 } 513 514 public void unpublishDocumentsFromCurrentSelection() { 515 if (!documentsListsManager.isWorkingListEmpty(DocumentsListsManager.CURRENT_DOCUMENT_SECTION_SELECTION)) { 516 unpublish(documentsListsManager.getWorkingList(DocumentsListsManager.CURRENT_DOCUMENT_SECTION_SELECTION)); 517 } else { 518 log.debug("No selectable Documents in context to process unpublish on..."); 519 } 520 log.debug("Unpublish the selected document(s) ..."); 521 } 522 523 protected void unpublish(List<DocumentModel> documentModels) { 524 for (DocumentModel documentModel : documentModels) { 525 PublicationTree tree = publisherService.getPublicationTreeFor(documentModel, documentManager); 526 PublishedDocument publishedDocument = tree.wrapToPublishedDocument(documentModel); 527 tree.unpublish(publishedDocument); 528 } 529 530 Events.instance().raiseEvent(EventNames.DOCUMENT_CHILDREN_CHANGED); 531 532 Object[] params = { documentModels.size() }; 533 // remove from the current selection list 534 documentsListsManager.resetWorkingList(DocumentsListsManager.CURRENT_DOCUMENT_SECTION_SELECTION); 535 facesMessages.add(StatusMessage.Severity.INFO, messages.get("n_unpublished_docs"), params); 536 } 537 538 public boolean isRemotePublishedDocument(PublishedDocument publishedDocument) { 539 return false; 540 } 541 542 public boolean isFileSystemPublishedDocument(PublishedDocument publishedDocument) { 543 return false; 544 } 545 546 public boolean isLocalPublishedDocument(PublishedDocument publishedDocument) { 547 return true; 548 } 549 550 public String publishWorkList() { 551 return publishDocumentList(DocumentsListsManager.DEFAULT_WORKING_LIST); 552 } 553 554 public DocumentModel getDocumentModelFor(String path) { 555 DocumentRef docRef = new PathRef(path); 556 if (documentManager.exists(docRef) && hasReadRight(path)) { 557 return documentManager.getDocument(docRef); 558 } 559 return null; 560 } 561 562 public boolean hasReadRight(String documentPath) { 563 return documentManager.hasPermission(new PathRef(documentPath), SecurityConstants.READ); 564 } 565 566 public String getFormattedPath(String path) { 567 DocumentModel docModel = getDocumentModelFor(path); 568 return docModel != null ? getFormattedPath(docModel) : path; 569 } 570 571 public String publishDocumentList(String listName) { 572 List<DocumentModel> docs2Publish = documentsListsManager.getWorkingList(listName); 573 DocumentModel target = navigationContext.getCurrentDocument(); 574 575 if (!getSectionTypes().contains(target.getType())) { 576 return null; 577 } 578 579 PublicationNode targetNode = publisherService.wrapToPublicationNode(target, documentManager); 580 if (targetNode == null) { 581 return null; 582 } 583 584 int nbPublishedDocs = 0; 585 for (DocumentModel doc : docs2Publish) { 586 if (!documentManager.hasPermission(doc.getRef(), SecurityConstants.READ_PROPERTIES)) { 587 continue; 588 } 589 590 if (doc.isProxy()) { 591 // TODO copy also copies security. just recreate a proxy. 592 documentManager.copy(doc.getRef(), target.getRef(), doc.getName()); 593 nbPublishedDocs++; 594 } else { 595 if (doc.hasFacet(FacetNames.PUBLISHABLE)) { 596 publisherService.publish(doc, targetNode); 597 nbPublishedDocs++; 598 } else { 599 log.info("Attempted to publish non-publishable document " + doc.getTitle()); 600 } 601 } 602 } 603 604 Object[] params = { nbPublishedDocs }; 605 facesMessages.add(StatusMessage.Severity.INFO, "#0 " + messages.get("n_published_docs"), params); 606 607 if (nbPublishedDocs < docs2Publish.size()) { 608 facesMessages.add(StatusMessage.Severity.WARN, messages.get("selection_contains_non_publishable_docs")); 609 } 610 611 EventManager.raiseEventsOnDocumentChildrenChange(target); 612 return null; 613 } 614 615 public Set<String> getSectionTypes() { 616 if (sectionTypes == null) { 617 sectionTypes = getTypeNamesForFacet(FacetNames.PUBLISH_SPACE); 618 if (sectionTypes == null) { 619 sectionTypes = new HashSet<>(); 620 } 621 } 622 return sectionTypes; 623 } 624 625 protected static Set<String> getTypeNamesForFacet(String facetName) { 626 SchemaManager schemaManager = Framework.getService(SchemaManager.class); 627 Set<String> publishRoots = schemaManager.getDocumentTypeNamesForFacet(facetName); 628 if (publishRoots == null || publishRoots.isEmpty()) { 629 return null; 630 } 631 return publishRoots; 632 } 633 634 public Map<String, String> getPublicationParameters() { 635 return publicationParameters; 636 } 637 638 public void notifyEvent(String eventId, Map<String, Serializable> properties, String comment, String category, 639 DocumentModel dm) { 640 notifyEvent(documentManager, eventId, properties, comment, category, dm); 641 } 642 643 public static void notifyEvent(CoreSession session, String eventId, Map<String, Serializable> properties, 644 String comment, String category, DocumentModel dm) { 645 646 // Default category 647 if (category == null) { 648 category = DocumentEventCategories.EVENT_DOCUMENT_CATEGORY; 649 } 650 651 if (properties == null) { 652 properties = new HashMap<>(); 653 } 654 655 properties.put(CoreEventConstants.REPOSITORY_NAME, session.getRepositoryName()); 656 properties.put(CoreEventConstants.SESSION_ID, session.getSessionId()); 657 properties.put(CoreEventConstants.DOC_LIFE_CYCLE, dm.getCurrentLifeCycleState()); 658 659 DocumentEventContext ctx = new DocumentEventContext(session, session.getPrincipal(), dm); 660 661 ctx.setProperties(properties); 662 ctx.setComment(comment); 663 ctx.setCategory(category); 664 665 EventProducer evtProducer = Framework.getService(EventProducer.class); 666 Event event = ctx.newEvent(eventId); 667 evtProducer.fireEvent(event); 668 } 669 670 public String getDomainName(String treeName) { 671 PublicationTree tree = publisherService.getPublicationTree(treeName, documentManager, null); 672 Map<String, String> parameters = publisherService.getParametersFor(tree.getConfigName()); 673 String domainName = parameters.get(PublisherService.DOMAIN_NAME_KEY); 674 return domainName != null ? " (" + domainName + ")" : ""; 675 } 676 677 @Observer(value = { EventNames.DOCUMENT_SELECTION_CHANGED }, create = false) 678 @BypassInterceptors 679 public void documentChanged() { 680 currentPublicationTreeNameForPublishing = null; 681 currentPublicationTree = null; 682 publishingComment = null; 683 } 684 685 /** 686 * @since 9.2 687 */ 688 public void reset() { 689 navigationContext.invalidateCurrentDocument(); 690 currentPublicationTreeNameForPublishing = null; 691 currentPublicationTree = null; 692 } 693 694 class RejectWithoutRestrictionRunner extends UnrestrictedSessionRunner { 695 696 PublishedDocument publishedDocument; 697 698 DocumentModel sourceDocument; 699 700 DocumentModel liveDocument; 701 702 String comment; 703 704 DocumentModel liveVersion; 705 706 public RejectWithoutRestrictionRunner(CoreSession session, PublishedDocument publishedDocument, String comment) { 707 super(session); 708 this.publishedDocument = publishedDocument; 709 this.comment = comment; 710 } 711 712 @Override 713 public void run() { 714 sourceDocument = session.getDocument(publishedDocument.getSourceDocumentRef()); 715 String sourceId = sourceDocument.getSourceId(); 716 // source may be null if the version is placeless (rendition) 717 liveVersion = sourceId == null ? null : session.getDocument(new IdRef(sourceId)); 718 notifyRejectToSourceDocument(); 719 } 720 721 private void notifyRejectToSourceDocument() { 722 notifyEvent(PublishingEvent.documentPublicationRejected.name(), null, comment, null, sourceDocument); 723 if (liveVersion != null && !sourceDocument.getRef().equals(liveVersion.getRef())) { 724 notifyEvent(PublishingEvent.documentPublicationRejected.name(), null, comment, null, liveVersion); 725 } 726 } 727 } 728}