| | 105 | security.declarePrivate('_getPublishedDocuments') |
|---|
| | 106 | def _getPublishedDocuments(self, rpath, published_docs=True): |
|---|
| | 107 | """Return rpaths of the documents, published or not, through the history |
|---|
| | 108 | of the document specified by the given path. |
|---|
| | 109 | """ |
|---|
| | 110 | portal = self._getPortalObject() |
|---|
| | 111 | portal_ppath = portal.getPhysicalPath() |
|---|
| | 112 | proxy = self._restrictedTraverse(rpath) |
|---|
| | 113 | states_info = proxy.getContentInfo(proxy=proxy, level=2)['states'] |
|---|
| | 114 | published_docs_rpaths = [] |
|---|
| | 115 | for state_info in states_info: |
|---|
| | 116 | state = state_info['review_state'] |
|---|
| | 117 | if (published_docs and state == 'published' |
|---|
| | 118 | or not published_docs and state != 'published'): |
|---|
| | 119 | published_proxy = state_info['proxy'] |
|---|
| | 120 | published_proxy_path = '/'.join( |
|---|
| | 121 | published_proxy.getPhysicalPath()[len(portal_ppath):]) |
|---|
| | 122 | published_docs_rpaths.append(published_proxy_path) |
|---|
| | 123 | return published_docs_rpaths |
|---|
| | 124 | |
|---|
| | 125 | security.declareProtected(View, 'publishDocument') |
|---|
| | 126 | def publishDocument(self, doc_rpath, rpaths_to_publish, |
|---|
| | 127 | wait_for_approval=False, comments=""): |
|---|
| | 128 | """Publish the document specified by the given relative path. |
|---|
| | 129 | |
|---|
| | 130 | document_rpath is of the form "workspaces/doc1" or "workspaces/folder/doc2". |
|---|
| | 131 | |
|---|
| | 132 | rpaths_to_publish is a dictionary. The dictionary keys are the rpath |
|---|
| | 133 | of where to publish the document. The rpath can be the rpath of a |
|---|
| | 134 | section or the rpath of a document. The dictionary values are either the |
|---|
| | 135 | empty string, "before", "after" or "replace". Those values have a |
|---|
| | 136 | meaning only if the rpath is the one of a document. |
|---|
| | 137 | |
|---|
| | 138 | "replace" is to be used so that the published document really replaces |
|---|
| | 139 | another document, be it folder or document. The targeted document is |
|---|
| | 140 | deleted and the document to published is inserted at the position of the |
|---|
| | 141 | now deleted targeted document. |
|---|
| | 142 | |
|---|
| | 143 | Returns a list of published doc full rpaths to keep a trace |
|---|
| | 144 | """ |
|---|
| | 145 | portal = self._getPortalObject() |
|---|
| | 146 | portal_ppath = portal.getPhysicalPath() |
|---|
| | 147 | wftool = self.portal_workflow |
|---|
| | 148 | proxy = self._restrictedTraverse(doc_rpath) |
|---|
| | 149 | |
|---|
| | 150 | doc_id = proxy.getId() |
|---|
| | 151 | context = proxy |
|---|
| | 152 | workflow_action = 'copy_submit' |
|---|
| | 153 | if wait_for_approval: |
|---|
| | 154 | transition = 'submit' |
|---|
| | 155 | else: |
|---|
| | 156 | transition = 'publish' |
|---|
| | 157 | allowed_transitions = wftool.getAllowedPublishingTransitions(context) |
|---|
| | 158 | published_docs_rpaths = self._getPublishedDocuments(doc_rpath) |
|---|
| | 159 | published_doc_ids = [] |
|---|
| | 160 | |
|---|
| | 161 | for target_rpath, placement in rpaths_to_publish.items(): |
|---|
| | 162 | target_doc = None |
|---|
| | 163 | try: |
|---|
| | 164 | object = self._restrictedTraverse(target_rpath) |
|---|
| | 165 | except (KeyError, AttributeError): |
|---|
| | 166 | continue |
|---|
| | 167 | # XXX how to get rid of geidet:section here :( |
|---|
| | 168 | if object.portal_type == 'geidet:section': |
|---|
| | 169 | section_rpath = target_rpath |
|---|
| | 170 | section = object |
|---|
| | 171 | else: |
|---|
| | 172 | try: |
|---|
| | 173 | target_doc = self._restrictedTraverse(target_rpath) |
|---|
| | 174 | target_doc_ppath = target_doc.getPhysicalPath() |
|---|
| | 175 | rppath = target_doc_ppath[len(portal_ppath):] |
|---|
| | 176 | object = self._restrictedTraverse(rppath[:-1]) |
|---|
| | 177 | except (KeyError, AttributeError): |
|---|
| | 178 | continue |
|---|
| | 179 | # XXX how to get rid of geidet:section here :( |
|---|
| | 180 | if object.portal_type == 'geidet:section': |
|---|
| | 181 | section_rpath = '/'.join(object.getPhysicalPath()[len(portal_ppath):]) |
|---|
| | 182 | section = object |
|---|
| | 183 | else: |
|---|
| | 184 | continue |
|---|
| | 185 | |
|---|
| | 186 | published_doc_id = wftool.findNewId(section, doc_id) |
|---|
| | 187 | published_doc_ids.append('%s/%s' % (target_rpath, |
|---|
| | 188 | published_doc_id)) |
|---|
| | 189 | |
|---|
| | 190 | wftool.doActionFor(context, workflow_action, |
|---|
| | 191 | dest_container=section_rpath, |
|---|
| | 192 | initial_transition=transition, |
|---|
| | 193 | comment=comments) |
|---|
| | 194 | # If the rpath provided was the one of a document then we will |
|---|
| | 195 | # consider the placement value to optionally move the document or |
|---|
| | 196 | # make it replace another one. |
|---|
| | 197 | position = None |
|---|
| | 198 | replace = False |
|---|
| | 199 | update = False |
|---|
| | 200 | if target_doc is not None: |
|---|
| | 201 | target_id = target_doc.getId() |
|---|
| | 202 | target_pos = section.getObjectPosition(target_id) |
|---|
| | 203 | if placement == 'before': |
|---|
| | 204 | position = target_pos |
|---|
| | 205 | elif placement == 'after': |
|---|
| | 206 | position = target_pos + 1 |
|---|
| | 207 | elif placement == 'replace': |
|---|
| | 208 | target_doc_rpath = self.portal_url\ |
|---|
| | 209 | .getRelativeContentURL(target_doc) |
|---|
| | 210 | position = target_pos |
|---|
| | 211 | replace = True |
|---|
| | 212 | if target_doc_rpath in published_docs_rpaths: |
|---|
| | 213 | update = True |
|---|
| | 214 | context = target_doc |
|---|
| | 215 | wftool.doActionFor(context, 'unpublish', comment=comments) |
|---|
| | 216 | if position is not None: |
|---|
| | 217 | section.moveObjectToPosition(doc_id, position) |
|---|
| | 218 | else: |
|---|
| | 219 | # the path to publish is section - move document to top |
|---|
| | 220 | # section.moveObjectsToTop(doc_id) |
|---|
| | 221 | pass |
|---|
| | 222 | |
|---|
| | 223 | # Sending events so that subscribers can react on commands sent to the |
|---|
| | 224 | # remote controller tool. |
|---|
| | 225 | info = {'dest_container': section_rpath, |
|---|
| | 226 | 'wait_for_approval': wait_for_approval, |
|---|
| | 227 | 'position': position, |
|---|
| | 228 | # This document comes as a replacement of a different |
|---|
| | 229 | # previous document that was located at the place where this |
|---|
| | 230 | # present document has been published. |
|---|
| | 231 | 'replace': replace, |
|---|
| | 232 | # This document comes as an update of a previous version of |
|---|
| | 233 | # the same document. |
|---|
| | 234 | 'update': update, |
|---|
| | 235 | } |
|---|
| | 236 | evtool = getEventService(self) |
|---|
| | 237 | evtool.notify(EVENT_PUBLISH_DOCUMENT, proxy, info) |
|---|
| | 238 | |
|---|
| | 239 | return published_doc_ids |
|---|