def _getSourceObjects(self, cb_copy_data, REQUEST): """get the source objects to link""" cp = None if cb_copy_data is not None: cp = cb_copy_data else: if REQUEST and REQUEST.has_key("__cp"): cp = REQUEST["__cp"] if cp is None: raise CopyError, eNoData try: cp = _cb_decode(cp) except: raise CopyError, eInvalid oblist = [] app = self.getPhysicalRoot() for mdata in cp[1]: m = Moniker.loadMoniker(mdata) try: ob = m.bind(app) except: raise CopyError, eNotFound self._verifyObjectLink() oblist.append(ob) return oblist
def manage_pasteObjects(self, cb_copy_data=None, REQUEST=None): """ override normal paste action to see if we're looking at the paste data being stored in cache """ if cb_copy_data is not None: cp = cb_copy_data elif REQUEST is not None and '__cp' in REQUEST: cp = REQUEST['__cp'] else: cp = None if cp is None: raise CopyError(eNoData) try: op, mdatas = _cb_decode(cp) except Exception: raise CopyError(eInvalid) try: if mdatas[0][0].startswith('cache:'): cache_key = mdatas[0][0].replace('cache:', '') new_mdatas = cache.get(cache_key) cdata = _cb_encode((op, new_mdatas)) return self._old_manage_pasteObjects(cdata) except IndexError: pass return self._old_manage_pasteObjects(cb_copy_data, REQUEST)
def useClipboard(self, func, REQUEST, source_paths=None, target_path=None, target_index=None): """Clipboard interaction. """ resp = REQUEST['RESPONSE'] if func in ("cut", "copy"): assert source_paths items = [] # list of path tuples cut = (func == 'cut') for p in str(source_paths).split(':'): items.append(p.split('/')) data = _cb_encode((cut, items)) resp.setCookie('__cp', data, path=cookie_path(REQUEST)) elif func == 'paste': assert target_path assert target_index assert REQUEST is not None data = REQUEST['__cp'] cut, items = _cb_decode(data) self.moveElements( items, target_path, int(target_index), not cut) resp.expireCookie('__cp', path=cookie_path(REQUEST)) else: raise ValueError("Clipboard function %s unknown" % func) resp.redirect(REQUEST["HTTP_REFERER"])
def useClipboard(self, func, REQUEST, source_paths=None, target_path=None, target_index=None): """Clipboard interaction. """ resp = REQUEST['RESPONSE'] if func in ("cut", "copy"): assert source_paths items = [] # list of path tuples cut = (func == 'cut') for p in str(source_paths).split(':'): items.append(p.split('/')) data = _cb_encode((cut, items)) resp.setCookie('__cp', data, path=cookie_path(REQUEST)) elif func == 'paste': assert target_path assert target_index assert REQUEST is not None data = REQUEST['__cp'] cut, items = _cb_decode(data) self.moveElements(items, target_path, int(target_index), not cut) resp.expireCookie('__cp', path=cookie_path(REQUEST)) else: raise ValueError("Clipboard function %s unknown" % func) resp.redirect(REQUEST["HTTP_REFERER"])
def _getSourceObjects(self, cb_copy_data, REQUEST): """get the source objects to link""" cp = None if cb_copy_data is not None: cp = cb_copy_data else: if REQUEST and REQUEST.has_key('__cp'): cp = REQUEST['__cp'] if cp is None: raise CopyError(eNoData) try: cp = _cb_decode(cp) except Exception: raise CopyError(eInvalid) oblist = [] app = self.getPhysicalRoot() for mdata in cp[1]: m = Moniker.loadMoniker(mdata) try: ob = m.bind(app) except Exception: raise CopyError(eNotFound) self._verifyObjectLink() oblist.append(ob) return oblist
def objects_to_async(self, request_key='__cp'): """ get info of files to perform async operation """ newid = self.request.get(request_key) if not newid: raise CopyError(eNoItemsSpecified) try: _op, mdatas = _cb_decode(newid) except: raise CopyError(eInvalid) oblist = [] app = self.context.getPhysicalRoot() for mdata in mdatas: m = loadMoniker(mdata) try: ob = m.bind(app) except ConflictError: raise except: raise CopyError(eNotFound) oblist.append(ob) return oblist
def manage_pasteObjects(self, cp): """ merge another conversation """ try: op, mdatas = _cb_decode(cp) except Exception: raise CopyError("Invalid content") if op == 0: raise ValueError('Not allowed to copy content into conversation') if op != 1: raise ValueError("Invalid operation of content") obj = self.unrestrictedTraverse(mdatas[0]) if IConversation.providedBy(obj): if obj.getParentNode() != self.getParentNode(): raise ValueError("Invalid parent of content") forum = obj.getForum() obj_id = obj.getId() o_list = obj.objectValues() oblist = [Moniker(o1).dump() for o1 in o_list] cp = (1, oblist) cp = _cb_encode(cp) CopyContainer.manage_pasteObjects(self, cp) forum.manage_delObjects([obj_id]) elif IComment.providedBy(obj): return CopyContainer.manage_pasteObjects(self, cp) else: raise ValueError('Invalid type of content')
def moveObjsToTrashcan(self, ids, REQUEST): if self.meta_id == 'ZMSTrashcan': return trashcan = self.getTrashcan() # Set deletion-date. ids_copy = [] for id in ids: try: context = getattr(self, id) context.del_uid = str(REQUEST.get('AUTHENTICATED_USER', None)) context.del_dt = standard.getDateTime(time.time()) ids_copy.append(id) except: standard.writeBlock( self, "[moveObjsToTrashcan]: Attribute Error %s" % (id)) # Use only successfully tried ids ids = ids_copy # Move (Cut & Paste). children = [getattr(self, x) for x in ids] [ standard.triggerEvent(child, 'beforeDeleteObjsEvt') for child in children ] cb_copy_data = _cb_decode(self.manage_cutObjects(ids)) trashcan.manage_pasteObjects(cb_copy_data=_cb_encode(cb_copy_data)) trashcan.normalizeSortIds() trashcan.run_garbage_collection(forced=1) # Sort-IDs. self.normalizeSortIds() [ standard.triggerEvent(child, 'afterDeleteObjsEvt') for child in children ]
def async_move(context, success_event, fail_event, **kwargs): """ Async job """ newid = kwargs.get('newid', '') email = kwargs.get('email', '') anno = IAnnotations(context) job_id = anno.get('async_move_job') if not newid: wrapper = IContextWrapper(context)( error=u'Invalid newid' ) notify(fail_event(wrapper)) raise CopyError(eNoItemsSpecified) try: _op, mdatas = _cb_decode(newid) except: raise CopyError(eInvalid) oblist = [] app = context.getPhysicalRoot() for mdata in mdatas: m = loadMoniker(mdata) try: ob = m.bind(app) except ConflictError: raise except: raise CopyError(eNotFound) oblist.append(ob) wrapper = IContextWrapper(context)( folder_move_from=oblist and aq_parent( aq_inner(oblist[0])).absolute_url(), folder_move_to=context.absolute_url(), folder_move_objects=', '.join([obj.getId() for obj in oblist]), asyncmove_email=email ) try: manage_pasteObjects_no_events(context, cb_copy_data=newid) except Exception, err: logger.exception(err) wrapper.error = err.message wrapper.job_id = job_id notify(fail_event(wrapper)) raise CopyError(MessageDialog( title='Error', message=err.message, action='manage_main', ))
def pasteAsAlias(context, cb_copy_data=None, request=None): """Paste the clipboard contents as an alias. Either pass the data, or a valid request with the __cp key. """ cp = None if cb_copy_data is not None: cp = cb_copy_data elif request and request.has_key("__cp"): cp = request["__cp"] else: cp = None if cp is None: raise ValueError("No clipboard data") try: cp = _cb_decode(cp) except: raise ValueError("Can't decode clipboard: %r" % cp) oblist = [] app = context.getPhysicalRoot() failed = [] success = [] for mdata in cp[1]: m = OFS.Moniker.loadMoniker(mdata) try: ob = m.bind(app) except: raise ValueError("Objects not found in %s" % app) oblist.append(ob) intids = getUtility(IIntIds) for ob in oblist: relation = RelationValue(intids.getId(ob)) alias = createContent("collective.alias", _aliasTarget=relation) notify(ObjectCreatedEvent(alias)) name = INameChooser(context).chooseName(ob.getId(), alias) alias.id = name new_name = context._setObject(name, alias) # XXX: When we move to CMF 2.2, an event handler will take care of this new_object = context._getOb(new_name) new_object.notifyWorkflowCreated() return " ".join(success) + " ".join(failed)
def pasteAsAlias(context, cb_copy_data=None, request=None): """Paste the clipboard contents as an alias. Either pass the data, or a valid request with the __cp key. """ cp = None if cb_copy_data is not None: cp = cb_copy_data elif request and request.has_key('__cp'): cp = request['__cp'] else: cp = None if cp is None: raise ValueError("No clipboard data") try: cp = _cb_decode(cp) except: raise ValueError("Can't decode clipboard: %r" % cp) oblist = [] app = context.getPhysicalRoot() failed = [] success = [] for mdata in cp[1]: m = OFS.Moniker.loadMoniker(mdata) try: ob = m.bind(app) except: raise ValueError("Objects not found in %s" % app) oblist.append(ob) intids = getUtility(IIntIds) for ob in oblist: relation = RelationValue(intids.getId(ob)) alias = createContent('collective.alias', _aliasTarget=relation) notify(ObjectCreatedEvent(alias)) name = INameChooser(context).chooseName(ob.getId(), alias) alias.id = name new_name = context._setObject(name, alias) # XXX: When we move to CMF 2.2, an event handler will take care of this new_object = context._getOb(new_name) new_object.notifyWorkflowCreated() return ' '.join(success) + ' '.join(failed)
def manage_pasteObjects(self, cb_copy_data=None, REQUEST=None): """Paste objects from the clipboard into the current directory. The cb_copy_data parameter, if specified, should be the result of a previous call to manage_cutObjects or manage_copyObjects.""" cp=None if cb_copy_data is not None: cp=cb_copy_data else: if REQUEST and REQUEST.has_key('__lcp'): cp=REQUEST['__lcp'] if cp is None: raise CopyError, eNoData try: cp=_cb_decode(cp) except: raise CopyError, eInvalid oblist=[] m=FileMoniker() op=cp[0] for ids in cp[1]: m.ids=ids try: ob=m.bind(self.root or self) except: raise CopyError, eNotFound self._verifyObjectPaste(ob, REQUEST) oblist.append(ob) if op==0: # Copy operation for ob in oblist: id=self._get_id(absattr(ob.id)) self._copyOb(id, ob) if REQUEST is not None: return self.manage_main(self, REQUEST, update_menu=1, cb_dataValid=1) if op==1: # Move operation for ob in oblist: id = absattr(ob.id) if not sanity_check(self, ob): raise CopyError, 'This object cannot be pasted into itself' id=self._get_id(id) self._moveOb(id, ob) if REQUEST is not None: REQUEST['RESPONSE'].setCookie('cp_', 'deleted', path='%s' % REQUEST['SCRIPT_NAME'], expires='Wed, 31-Dec-97 23:59:59 GMT') return self.manage_main(self, REQUEST, update_menu=1, cb_dataValid=0) return ''
def _get_clipboard_item(self): cp = self.request.get('__cp') op, mdatas = _cb_decode(cp) # see OFS/CopySupport.py # just get the first item on the clipboard mdata = mdatas[0] m = Moniker.loadMoniker(mdata) app = self.context.getPhysicalRoot() try: ob = m.bind(app) except (ConflictError, AttributeError, KeyError, TypeError): return None return ob
def _get_cb_copy_data(self, cb_copy_data=None, REQUEST=None): cp = None if cb_copy_data is not None: cp = cb_copy_data else: if REQUEST and REQUEST.has_key('__cp'): cp = REQUEST['__cp'] if cp is None: raise CopyError, eNoData try: cp = _cb_decode(cp) except: _globals.writeError(self, '[_get_cb_copy_data]: eInvalid') raise CopyError, eInvalid return cp
def _get_cb_copy_data(self, cb_copy_data=None, REQUEST=None): cp = None if cb_copy_data is not None: cp = cb_copy_data else: if REQUEST and '__cp' in REQUEST: cp = REQUEST['__cp'] if cp is None: raise CopyError(eNoData) try: cp = _cb_decode(cp) except: standard.writeError(self, '[CopySupport._get_cb_copy_data]: eInvalid') raise CopyError(eInvalid) return cp
def get_paste_data(req): try: op, mdatas = _cb_decode(req['__cp']) except: raise CopyError(eInvalid) try: if mdatas[0][0].startswith('cache:'): cache_key = mdatas[0][0].replace('cache:', '') mdatas = cache.get(cache_key) except IndexError: pass paths = [] for mdata in mdatas: paths.append('/'.join(mdata)) catalog = api.portal.get_tool('portal_catalog') count = len(catalog(path={'query': paths, 'depth': -1})) return {'paths': paths, 'op': op, 'mdatas': mdatas, 'count': count}
def _get_obs(self, cp): try: cp = _cb_decode(cp) except: standard.writeError(self, '[CopySupport._get_obs]: eInvalid') #raise CopyError, eInvalid oblist = [] op = cp[0] app = self.getPhysicalRoot() for mdata in cp[1]: m = Moniker.loadMoniker(mdata) try: ob = m.bind(app) except: standard.writeError(self, '[CopySupport._get_obs]: eNotFound') #raise CopyError, eNotFound self._verifyObjectPaste(ob) oblist.append(ob) return oblist
def _duplicate(self, cp): try: cp = _cb_decode(cp) except: raise CopyError, 'Clipboard Error' oblist = [] op = cp[0] app = self.getPhysicalRoot() result = [] for mdata in cp[1]: m = Moniker.loadMoniker(mdata) try: ob = m.bind(app) except: raise CopyError, 'Not Found' self._verifyObjectPaste(ob, validate_src=1) oblist.append(ob) if op == 0: for ob in oblist: if not ob.cb_isCopyable(): raise CopyError, 'Not Supported' try: ob._notifyOfCopyTo(self, op=0) except: raise CopyError, 'Copy Error' ob = ob._getCopy(self) orig_id = ob.getId() id = self._get_id(ob.getId()) result.append({'id': orig_id, 'new_id': id}) ob._setId(id) self._setObject(id, ob) ob = self._getOb(id) ob._postCopy(self, op=0) ob._postDuplicate() ob.wl_clearLocks() if op == 1: # Move operation for ob in oblist: id = ob.getId() if not ob.cb_isMoveable(): raise CopyError, 'Not Supported' try: ob._notifyOfCopyTo(self, op=1) except: raise CopyError, 'Move Error' if not sanity_check(self, ob): raise CopyError, 'This object cannot be pasted into itself' # try to make ownership explicit so that it gets carried # along to the new location if needed. ob.manage_changeOwnershipType(explicit=1) aq_parent(aq_inner(ob))._delObject(id) ob = aq_base(ob) orig_id = id id = self._get_id(id) result.append({'id': orig_id, 'new_id': id}) ob._setId(id) self._setObject(id, ob, set_owner=0) ob = self._getOb(id) ob._postCopy(self, op=1) # try to make ownership implicit if possible ob.manage_changeOwnershipType(explicit=0) return result
def cb_dataValid(self): try: _cb_decode(self.REQUEST['__cp']) except: return False return True
def manage_pasteObjects_no_events(self, cb_copy_data=None, REQUEST=None): """Paste previously copied objects into the current object. If calling manage_pasteObjects from python code, pass the result of a previous call to manage_cutObjects or manage_copyObjects as the first argument. Also sends IObjectCopiedEvent and IObjectClonedEvent or IObjectWillBeMovedEvent and IObjectMovedEvent. """ anno = IAnnotations(self) job_id = anno.get('async_move_job') if not REQUEST: # Create a request to work with REQUEST = create_request() if cb_copy_data is not None: cp = cb_copy_data elif REQUEST is not None and REQUEST.has_key('__cp'): cp = REQUEST['__cp'] else: cp = None if cp is None: raise CopyError(eNoData) try: op, mdatas = _cb_decode(cp) except: raise CopyError(eInvalid) oblist = [] app = self.getPhysicalRoot() cat = getToolByName(self, 'portal_catalog') for mdata in mdatas: m = loadMoniker(mdata) try: ob = m.bind(app) except ConflictError: raise except: raise CopyError(eNotFound) # self._verifyObjectPaste(ob, validate_src=op+1) oblist.append(ob) result = [] steps = oblist and int(100/len(oblist)) or 0 notify(AsyncMoveSaveProgress( self, operation='initialize', job_id=job_id, oblist_id=[ (o.getId(), o.Title()) for o in oblist ])) if op == 0: # Copy operation for i, ob in enumerate(oblist): orig_id = ob.getId() if not ob.cb_isCopyable(): raise CopyError(eNotSupported % escape(orig_id)) oid = self._get_id(orig_id) result.append({'id': orig_id, 'new_id': oid}) notify(AsyncMoveSaveProgress( self, operation='sub_progress', job_id=job_id, obj_id=ob.getId(), progress=.25 )) ob = ob._getCopy(self) ob._setId(oid) notify(AsyncMoveSaveProgress( self, operation='sub_progress', job_id=job_id, obj_id=ob.getId(), progress=.50 )) self._setObject(oid, ob) ob = self._getOb(oid) ob.wl_clearLocks() notify(AsyncMoveSaveProgress( self, operation='sub_progress', job_id=job_id, obj_id=ob.getId(), progress=.75 )) ob._postCopy(self, op=0) compatibilityCall('manage_afterClone', ob, ob) notify(AsyncMoveSaveProgress( self, operation='sub_progress', job_id=job_id, obj_id=ob.getId(), progress=1 )) notify(AsyncMoveSaveProgress( self, operation='progress', job_id=job_id, progress=steps*(i+1)/100 )) if op == 1: # Move operation for i, ob in enumerate(oblist): orig_id = ob.getId() if not sanity_check(self, ob): raise CopyError( "This object cannot be pasted into itself") orig_container = aq_parent(aq_inner(ob)) if aq_base(orig_container) is aq_base(self): oid = orig_id else: oid = self._get_id(orig_id) result.append({'id': orig_id, 'new_id': oid}) unindex_object(ob, recursive=1) # try to make ownership explicit so that it gets carried # along to the new location if needed. ob.manage_changeOwnershipType(explicit=1) notify(AsyncMoveSaveProgress( self, operation='sub_progress', job_id=job_id, obj_id=ob.getId(), progress=.25 )) try: obj_path = '/'.join( orig_container.getPhysicalPath()) + '/' + orig_id orig_container._delObject(orig_id, suppress_events=True) uncatalog_path = obj_path try: uncatalog_objs = cat(path=obj_path) for obj_brain in uncatalog_objs: uncatalog_path = obj_brain.getPath() cat.uncatalog_object(uncatalog_path) except AttributeError: logger.warn("%s could not be found", uncatalog_path) except TypeError: orig_container._delObject(orig_id) logger.warn( "%s._delObject without suppress_events is discouraged.", orig_container.__class__.__name__) notify(AsyncMoveSaveProgress( self, operation='sub_progress', job_id=job_id, obj_id=ob.getId(), progress=.50 )) ob = aq_base(ob) ob._setId(oid) try: self._setObject(oid, ob, set_owner=0, suppress_events=True) except TypeError: self._setObject(oid, ob, set_owner=0) logger.warn( "%s._setObject without suppress_events is discouraged.", self.__class__.__name__) ob = self._getOb(oid) ob._postCopy(self, op=1) # try to make ownership implicit if possible ob.manage_changeOwnershipType(explicit=0) notify(AsyncMoveSaveProgress( self, operation='sub_progress', job_id=job_id, obj_id=ob.getId(), progress=.75 )) reindex_object(ob, recursive=1) notify(AsyncMoveSaveProgress( self, operation='sub_progress', job_id=job_id, obj_id=ob.getId(), progress=1 )) notify(AsyncMoveSaveProgress( self, operation='progress', job_id=job_id, progress=steps*(i+1)/100 )) notify(AsyncMoveSaveProgress( self, operation='progress', job_id=job_id, progress=1 )) del anno['async_move_job'] return result
def manage_pasteObjects(self, cb_copy_data=None, is_indexable=True, REQUEST=None): """Paste previously copied objects into the current object. If calling manage_pasteObjects from python code, pass the result of a previous call to manage_cutObjects or manage_copyObjects as the first argument. If is_indexable is False, we will avoid indexing the pasted objects and subobjects """ cp=None if cb_copy_data is not None: cp=cb_copy_data else: if REQUEST and REQUEST.has_key('__cp'): cp=REQUEST['__cp'] if cp is None: raise CopyError, eNoData try: cp=_cb_decode(cp) except: raise CopyError, eInvalid oblist=[] op=cp[0] app = self.getPhysicalRoot() result = [] for mdata in cp[1]: m = Moniker.loadMoniker(mdata) try: ob = m.bind(app) except: raise CopyError, eNotFound self._verifyObjectPaste(ob, validate_src=op+1) oblist.append(ob) if op==0: # Copy operation for ob in oblist: if not ob.cb_isCopyable(): raise CopyError, eNotSupported % escape(ob.getId()) try: ob._notifyOfCopyTo(self, op=0) except: raise CopyError, MessageDialog( title='Copy Error', message=sys.exc_info()[1], action ='manage_main') ob=ob._getCopy(self) orig_id=ob.getId() id=self._get_id(ob.getId()) result.append({'id':orig_id, 'new_id':id}) ob._setId(id) if not is_indexable: ob._setNonIndexable() self._setObject(id, ob) ob = self._getOb(id) ob._postCopy(self, op=0) ob.manage_afterClone(ob) ob.wl_clearLocks() if REQUEST is not None: return self.manage_main(self, REQUEST, update_menu=1, cb_dataValid=1) if op==1: # Move operation for ob in oblist: id=ob.getId() if not ob.cb_isMoveable(): raise CopyError, eNotSupported % escape(id) try: ob._notifyOfCopyTo(self, op=1) except: raise CopyError, MessageDialog( title='Move Error', message=sys.exc_info()[1], action ='manage_main') if not sanity_check(self, ob): raise CopyError, 'This object cannot be pasted into itself' # try to make ownership explicit so that it gets carried # along to the new location if needed. ob.manage_changeOwnershipType(explicit=1) aq_parent(aq_inner(ob))._delObject(id) ob = aq_base(ob) orig_id=id id=self._get_id(id) result.append({'id':orig_id, 'new_id':id }) ob._setId(id) if not is_indexable: ob._setNonIndexable() self._setObject(id, ob, set_owner=0) ob=self._getOb(id) ob._postCopy(self, op=1) # try to make ownership implicit if possible ob.manage_changeOwnershipType(explicit=0) if REQUEST is not None: REQUEST['RESPONSE'].setCookie('__cp', 'deleted', path='%s' % cookie_path(REQUEST), expires='Wed, 31-Dec-97 23:59:59 GMT') REQUEST['__cp'] = None return self.manage_main(self, REQUEST, update_menu=1, cb_dataValid=0) return result
def manage_pasteAsAlias(self, context, cb_copy_data=None): # first check if the user has the proper permissions in the 'context' portal_membership = getToolByName(self, 'portal_membership') if not portal_membership.checkPermission(ADD_ALIAS_PERMISSION, context): msg = "Insufficient priviledge to perform this action. It requires the permission: " + ADD_ALIAS_PERMISSION raise Unauthorized(msg, needed={'permission': ADD_ALIAS_PERMISSION}) cp = None REQUEST = context.REQUEST if cb_copy_data is not None: cp = cb_copy_data elif REQUEST and REQUEST.has_key('__cp'): cp = REQUEST['__cp'] else: cp = None if cp is None: raise ValueError("No clipboard data") try: cp = _cb_decode(cp) except: raise ValueError("can't decode clipboard: %r" % cp) oblist = [] app = self.getPhysicalRoot() failed = '' success = '' types = self.getLinkableTypes() for mdata in cp[1]: m = OFS.Moniker.loadMoniker(mdata) try: ob = m.bind(app) except: raise ValueError("Objects not found in %s" % app) oblist.append(ob) for ob in oblist: if shasattr(ob, 'isReferenceable') and ob.portal_type in types: # create an Alias for this object id = context.generateUniqueId('Alias') new_id = context.invokeFactory(id=id, type_name='Alias') if new_id is None or new_id == '': new_id = id o = getattr(context, new_id, None) # now set the reference o.setAlias(ob.UID()) oid = o._renameAfterCreation() logger.debug("New alias created: %s", str(oid)) o.reindexObject() o = None success = _('Alias(es) created.') else: if failed == '': failed = _('Ignored (not linkable): ') + ob.Title() else: failed = failed + u', ' + ob.Title() return success + failed
def create_version(context, reindex=True): """ Create a new version of an object This is done by copy&pasting the object, then assigning, as versionId, the one from the original object. Additionally, we rename the object using a number based scheme and then clean it up to avoid various problems. """ logger.info("Started creating version of %s", context.absolute_url()) obj_id = context.getId() parent = utils.parent(context) # Adapt version parent (if case) if not IVersionEnhanced.providedBy(context): alsoProvides(context, IVersionEnhanced) # _ = IVersionControl(context).getVersionId() # Create version object # 1. copy object clipb = parent.manage_copyObjects(ids=[obj_id]) # 2. pregenerate new id for the copy new_id = generateNewId(parent, obj_id) # 3. alter the clipboard data and inject the desired new id clipb_decoded = _cb_decode(clipb) clipb = _cb_encode((clipb_decoded[0], clipb_decoded[1], [new_id])) # 4. call paste operation manage_pasteObjects_Version(parent, clipb) # 5. get the version object - no need for a rename anymore ver = parent[new_id] # #31440 apply related items from original object to the new version ver.setRelatedItems(context.getRelatedItems()) # Set effective date today ver.setCreationDate(DateTime()) ver.setEffectiveDate(None) ver.setExpirationDate(None) mtool = getToolByName(context, 'portal_membership') auth_user = mtool.getAuthenticatedMember() auth_username = auth_user.getUserName() auth_username_list = [auth_username] current_creators = ver.Creators() auth_username_list.extend(current_creators) username_list = [] for name in auth_username_list: if name == auth_username and name in username_list: continue else: username_list.append(name) new_creators = tuple(username_list) ver.setCreators(new_creators) # Remove comments if hasNewDiscussion: conversation = IConversation(ver) while conversation.keys(): conversation.__delitem__(conversation.keys()[0]) else: if hasattr(aq_base(ver), 'talkback'): tb = ver.talkback if tb is not None: for obj in tb.objectValues(): obj.__of__(tb).unindexObject() tb._container = PersistentMapping() notify(VersionCreatedEvent(ver, context)) if reindex: ver.reindexObject() # some catalogued values of the context may depend on versions _reindex(context) logger.info("Created version at %s", ver.absolute_url()) return ver
def __duplicate(self, cp, duplicate, is_indexable, reindex_kw, immediate_reindex): try: cp = _cb_decode(cp) except: raise CopyError(eInvalid) oblist = [] op = cp[0] app = self.getPhysicalRoot() for mdata in cp[1]: m = Moniker.loadMoniker(mdata) try: ob = m.bind(app) except: raise CopyError(eNotFound) self._verifyObjectPaste(ob, validate_src=op + 1) oblist.append(ob) result = [] def doMove(self, ob): aq_parent(aq_inner(ob))._delObject(ob.getId()) return aq_base(ob) is_doable_id, notify_error, do_sanity_check, do, set_owner, is_clone = ( ( # 0: Copy 'cb_isCopyable', 'Copy Error', lambda self, ob: True, lambda self, ob: ob._getCopy(self), 1, # Take ownership. True, ), ( # 1: Move 'cb_isMoveable', 'Move Error', sanity_check, doMove, 0, # Retain original ownership. False, ), )[op] for ob in oblist: if not getattr(ob, is_doable_id)(): raise CopyError(eNotSupported % escape(ob.getId())) try: ob._notifyOfCopyTo(self, op=op) except: raise CopyError(MessageDialog( title=notify_error, message=sys.exc_info()[1], action='manage_main', )) if not do_sanity_check(self, ob): raise CopyError('This object cannot be pasted into itself') if not set_owner: # try to make ownership explicit so that it gets carried # along to the new location if needed. ob.manage_changeOwnershipType(explicit=1) new_ob = do(self, ob) orig_id = ob.getId() new_id = self._get_id(orig_id) result.append({'id': orig_id, 'new_id': new_id}) new_ob._setId(new_id) if reindex_kw is not None: new_ob.setDefaultReindexParameterDict(reindex_kw) if is_indexable is not None and not is_indexable: new_ob._setNonIndexable() self._setObject(new_id, new_ob, set_owner=set_owner) new_ob = self._getOb(new_id) new_ob._postCopy(self, op=op) if is_clone: if duplicate: new_ob._postDuplicate() else: new_ob.manage_afterClone(new_ob) new_ob.wl_clearLocks() if not set_owner: # try to make ownership implicit if possible new_ob.manage_changeOwnershipType(explicit=0) method = new_ob.immediateReindexObject if reindex_kw is not None: method = partial(method, **reindex_kw) if isinstance(immediate_reindex, ImmediateReindexContextManager): immediate_reindex.append(method) elif immediate_reindex: # Immediately reindexing document that we just pasted is safe, as no # other transaction can by definition see it, so there cannot be a race # condition leading to stale catalog content. method() return op, result
def manage_pasteObjects(self, cp): """Paste previously copied objects into the current object.""" op, mdatas = _cb_decode(cp) COPY = op == 0 # Otherwise its a paste operation # Copy or paste always fails without write permission here sman = getSecurityManager() if not sman.checkPermission(AddFilesystemObject, self): raise CopyError, 'Insufficient Privileges' oblist = [] app = self.getPhysicalRoot() # Loading and security checks for mdata in mdatas: m = loadMoniker(mdata) try: ob = m.bind(app) except ConflictError: raise except: raise CopyError, 'Item not found' if not IReflectoProxy.providedBy(ob) or IReflector.providedBy(ob): raise CopyError, 'Cannot paste into this object' parent = aq_parent(aq_inner(ob)) if not sman.validate(None, parent, None, ob): raise Unauthorized(ob.getId()) if not COPY: if not sman.checkPermission(DeleteObjects, parent): raise Unauthorized('Delete not allowed') prefix = os.path.commonprefix( (ob.getFilesystemPath(), self.getFilesystemPath())) if prefix == ob.getFilesystemPath(): raise CopyError, "This object cannot be pasted into itself" oblist.append(ob) result = [] problem_ids = [] path = self.getFilesystemPath() for ob in oblist: old = ob.getId() new = self._generate_copy_id(old) result.append(dict(id=old, new_id=new)) oldpath = ob.getFilesystemPath() newpath = os.path.join(path, new) if COPY: try: if IReflectoDirectory.providedBy(ob): shutil.copytree(oldpath, newpath) else: shutil.copy2(oldpath, newpath) notify(ObjectCopiedEvent(self[new], ob)) notify(ObjectClonedEvent(self[new])) except EnvironmentError: problem_ids.append(result.pop()) else: # paste/move oldparent = aq_parent(aq_inner(ob)) notify(ObjectWillBeMovedEvent(ob, oldparent, old, self, new)) if aq_base(self) is aq_base(oldparent): # No need to move from self to self result[-1]['new_id'] = old # Original CopyContainer does emit events for this case notify(ObjectMovedEvent(ob, self, old, self, old)) continue try: shutil.move(oldpath, newpath) indexview = oldparent.unrestrictedTraverse('@@index') indexview.index() notify( ObjectMovedEvent(self[new], oldparent, old, self, new)) notifyContainerModified(oldparent) except EnvironmentError: if os.path.exists(newpath): # partial move try: if os.path.isdir(newpath): shutil.rmtree(newpath) else: os.unlink(newpath) except EnvironmentError: pass # Really weird access issues, time to bail problem_ids.append(result.pop()) if problem_ids: sm = IStatusMessage(getattr(self, 'REQUEST', None), None) if sm is not None: sm.addStatusMessage( 'Failed to copy or paste some files: %s' % problem_ids, 'stop') if result: indexview = self.unrestrictedTraverse('@@index') indexview.index() notifyContainerModified(self) return result
def paste_as_related_items(context, cb_copy_data=None, REQUEST=None, fieldname='relatedItems'): """Paste previously copied objects into the current object as related items. Note that this is additive: no currently related items are removed. If calling this function from python code, pass the result of a previous call to OFS.manage_copyObjects as the first argument. Note that the results from a copy are accepted, not from a cut (move). This function is mostly a stripped down version of manage_pasteObjects from OFS.CopySupport. """ if cb_copy_data is not None: cp = cb_copy_data elif REQUEST is not None and '__cp' in REQUEST.keys(): cp = REQUEST['__cp'] else: cp = None if cp is None: raise CopyError if not context.cb_dataValid: raise CopyError try: op, mdatas = _cb_decode(cp) except: raise CopyError if op != 0: # We only support pasting from a copy operation, not from a move/cut. raise CopyError oblist = [] app = context.getPhysicalRoot() for mdata in mdatas: m = Moniker.loadMoniker(mdata) try: ob = m.bind(app) except ConflictError: raise except: raise CopyError oblist.append(ob) field = context.getField(fieldname) related = field.getRaw(context) new_ids = [] for ob in oblist: uid = ob.UID() if uid not in related: related.append(uid) new_ids.append(ob.getId()) if new_ids: field.set(context, related) # Report back return new_ids
def manage_pasteObjects_Version(self, cb_copy_data=None, REQUEST=None): """Paste previously copied objects into the current object. If calling manage_pasteObjects from python code, pass the result of a previous call to manage_cutObjects or manage_copyObjects as the first argument. Also sends IObjectCopiedEvent and IObjectClonedEvent or IObjectWillBeMovedEvent and IObjectMovedEvent. """ # due to the ticket #14598: the need to also handle a cb_copy_data # structure that contains the desired new id on a copy/paste operation. # this feature will be used when creating a new version for an object. # if there is no new id also incapsulated in the cb_copy_data then # the copy/paste will work as default. # also the cut/paste remains the same. if cb_copy_data is not None: cp = cb_copy_data elif REQUEST is not None and '__cp' in REQUEST: cp = REQUEST['__cp'] else: cp = None if cp is None: raise CopyError(eNoData) try: op, mdatas, newids = _cb_decode(cp) except Exception: try: op, mdatas = _cb_decode(cp) newids = [] except Exception: raise CopyError(eInvalid) else: if len(mdatas) != len(newids): raise CopyError(eInvalid) oblist = [] app = self.getPhysicalRoot() for mdata in mdatas: m = loadMoniker(mdata) try: ob = m.bind(app) except ConflictError: raise except Exception: raise CopyError(eNotFound) self._verifyObjectPaste(ob, validate_src=op + 1) oblist.append(ob) if len(newids) == 0: newids = [''] * len(oblist) result = [] if op == 0: # Copy operation for ob, new_id in zip(oblist, newids): orig_id = ob.getId() if not ob.cb_isCopyable(): raise CopyError(eNotSupported % escape(orig_id)) try: ob._notifyOfCopyTo(self, op=0) except ConflictError: raise except Exception: raise CopyError( MessageDialog(title="Copy Error", message=sys.exc_info()[1], action='manage_main')) if new_id == '': new_id = self._get_id(orig_id) result.append({'id': orig_id, 'new_id': new_id}) orig_ob = ob ob = ob._getCopy(self) ob._setId(new_id) notify(ObjectCopiedEvent(ob, orig_ob)) self._setObject(new_id, ob) ob = self._getOb(new_id) ob.wl_clearLocks() ob._postCopy(self, op=0) compatibilityCall('manage_afterClone', ob, ob) notify(ObjectClonedEvent(ob)) if REQUEST is not None: return self.manage_main(self, REQUEST, update_menu=1, cb_dataValid=1) elif op == 1: # Move operation for ob in oblist: orig_id = ob.getId() if not ob.cb_isMoveable(): raise CopyError(eNotSupported % escape(orig_id)) try: ob._notifyOfCopyTo(self, op=1) except ConflictError: raise except Exception: raise CopyError( MessageDialog(title="Move Error", message=sys.exc_info()[1], action='manage_main')) if not sanity_check(self, ob): raise CopyError("This object cannot be pasted into itself") orig_container = aq_parent(aq_inner(ob)) if aq_base(orig_container) is aq_base(self): new_id = orig_id else: new_id = self._get_id(orig_id) result.append({'id': orig_id, 'new_id': new_id}) notify( ObjectWillBeMovedEvent(ob, orig_container, orig_id, self, new_id)) # try to make ownership explicit so that it gets carried # along to the new location if needed. ob.manage_changeOwnershipType(explicit=1) try: orig_container._delObject(orig_id, suppress_events=True) except TypeError: orig_container._delObject(orig_id) warnings.warn( "%s._delObject without suppress_events is discouraged." % orig_container.__class__.__name__, DeprecationWarning) ob = aq_base(ob) ob._setId(new_id) try: self._setObject(new_id, ob, set_owner=0, suppress_events=True) except TypeError: self._setObject(new_id, ob, set_owner=0) warnings.warn( "%s._setObject without suppress_events is discouraged." % self.__class__.__name__, DeprecationWarning) ob = self._getOb(new_id) notify(ObjectMovedEvent(ob, orig_container, orig_id, self, new_id)) notifyContainerModified(orig_container) if aq_base(orig_container) is not aq_base(self): notifyContainerModified(self) ob._postCopy(self, op=1) # try to make ownership implicit if possible ob.manage_changeOwnershipType(explicit=0) if REQUEST is not None: REQUEST['RESPONSE'].setCookie( '__cp', 'deleted', path='%s' % cookie_path(REQUEST), expires='Wed, 31-Dec-97 23:59:59 GMT') REQUEST['__cp'] = None return self.manage_main(self, REQUEST, update_menu=1, cb_dataValid=0) return result
def manage_pasteObjects(self, cb_copy_data=None, REQUEST=None): """Paste previously copied objects into the current object, making folders into chapters and RhaptosModuleEditors into ContentPointers (and not destroying their originals). Other objects will be as usual. Largely copied from OFS.CopySupport. If calling manage_pasteObjects from python code, pass the result of a previous call to manage_cutObjects or manage_copyObjects as the first argument.""" cp=None if cb_copy_data is not None: cp=cb_copy_data else: if REQUEST and REQUEST.has_key('__cp'): cp=REQUEST['__cp'] if cp is None: raise CopyError, eNoData try: cp=_cb_decode(cp) except: raise CopyError, eInvalid oblist=[] op=cp[0] app = self.getPhysicalRoot() result = [] duplicates = [] for mdata in cp[1]: m = Moniker.loadMoniker(mdata) try: ob = m.bind(app) except: raise CopyError, eNotFound oblist.append(ob) for ob in oblist: self._verifyObjectPaste(ob) if op==0: # Copy operation for ob in oblist: if not ob.cb_isCopyable(): raise CopyError, eNotSupported % ob.getId() try: ob._notifyOfCopyTo(self, op=0) except: raise CopyError, MessageDialog( title='Copy Error', message=sys.exc_info()[1], action ='manage_main') #ob=ob._getCopy(self) orig_id=ob.getId() id=self._get_id(ob.getId()) ob, dupes = self._getTransformCopy(ob, op, id, self) # NEW duplicates.extend(dupes) if ob: result.append({'id':orig_id, 'new_id':id}) #ob._setId(id) #self._setObject(id, ob) #ob = self._getOb(id) ob.manage_afterClone(ob) if REQUEST is not None: return self.manage_main(self, REQUEST, update_menu=1, cb_dataValid=1) if op==1: # Move operation for ob in oblist: id=ob.getId() if not ob.cb_isMoveable(): raise CopyError, eNotSupported % id try: ob._notifyOfCopyTo(self, op=1) except: raise CopyError, MessageDialog( title='Move Error', message=sys.exc_info()[1], action ='manage_main') if not sanity_check(self, ob): raise CopyError, 'This object cannot be pasted into itself' ### NEW BELOW ### if self._transformableType(ob): # do the "copy" procedure orig_id=ob.getId() id=self._get_id(ob.getId()) ob, dupes = self._getTransformCopy(ob, op, id) duplicates.extend(dupes) if ob: result.append({'id':orig_id, 'new_id':id}) ob.manage_afterClone(ob) else: ### NEW ABOVE (below is ++indented compared to original) ### # try to make ownership explicit so that it gets carried # along to the new location if needed. old = ob orig_id=ob.getId() id=self._get_id(ob.getId()) ob, dupes = self._getTransformCopy(ob, op, id) duplicates.extend(dupes) if ob: result.append({'id':orig_id, 'new_id':id}) ob.manage_afterClone(ob) aq_parent(aq_inner(old))._delObject(id) if REQUEST is not None: REQUEST['RESPONSE'].setCookie('__cp', 'deleted', path='%s' % cookie_path(REQUEST), expires='Wed, 31-Dec-97 23:59:59 GMT') REQUEST['__cp'] = None return self.manage_main(self, REQUEST, update_menu=1, cb_dataValid=0) if duplicates: raise "DuplicateError", duplicates return result
def manage_pasteObjects(self, cb_copy_data=None, is_indexable=True, REQUEST=None): """Paste previously copied objects into the current object. If calling manage_pasteObjects from python code, pass the result of a previous call to manage_cutObjects or manage_copyObjects as the first argument. If is_indexable is False, we will avoid indexing the pasted objects and subobjects """ cp = None if cb_copy_data is not None: cp = cb_copy_data else: if REQUEST and REQUEST.has_key('__cp'): cp = REQUEST['__cp'] if cp is None: raise CopyError, eNoData try: cp = _cb_decode(cp) except: raise CopyError, eInvalid oblist = [] op = cp[0] app = self.getPhysicalRoot() result = [] for mdata in cp[1]: m = Moniker.loadMoniker(mdata) try: ob = m.bind(app) except: raise CopyError, eNotFound self._verifyObjectPaste(ob, validate_src=op + 1) oblist.append(ob) if op == 0: # Copy operation for ob in oblist: if not ob.cb_isCopyable(): raise CopyError, eNotSupported % escape(ob.getId()) try: ob._notifyOfCopyTo(self, op=0) except: raise CopyError, MessageDialog(title='Copy Error', message=sys.exc_info()[1], action='manage_main') ob = ob._getCopy(self) orig_id = ob.getId() id = self._get_id(ob.getId()) result.append({'id': orig_id, 'new_id': id}) ob._setId(id) if not is_indexable: ob._setNonIndexable() self._setObject(id, ob) ob = self._getOb(id) ob._postCopy(self, op=0) ob.manage_afterClone(ob) ob.wl_clearLocks() if REQUEST is not None: return self.manage_main(self, REQUEST, update_menu=1, cb_dataValid=1) if op == 1: # Move operation for ob in oblist: id = ob.getId() if not ob.cb_isMoveable(): raise CopyError, eNotSupported % escape(id) try: ob._notifyOfCopyTo(self, op=1) except: raise CopyError, MessageDialog(title='Move Error', message=sys.exc_info()[1], action='manage_main') if not sanity_check(self, ob): raise CopyError, 'This object cannot be pasted into itself' # try to make ownership explicit so that it gets carried # along to the new location if needed. ob.manage_changeOwnershipType(explicit=1) aq_parent(aq_inner(ob))._delObject(id) ob = aq_base(ob) orig_id = id id = self._get_id(id) result.append({'id': orig_id, 'new_id': id}) ob._setId(id) if not is_indexable: ob._setNonIndexable() self._setObject(id, ob, set_owner=0) ob = self._getOb(id) ob._postCopy(self, op=1) # try to make ownership implicit if possible ob.manage_changeOwnershipType(explicit=0) if REQUEST is not None: REQUEST['RESPONSE'].setCookie( '__cp', 'deleted', path='%s' % cookie_path(REQUEST), expires='Wed, 31-Dec-97 23:59:59 GMT') REQUEST['__cp'] = None return self.manage_main(self, REQUEST, update_menu=1, cb_dataValid=0) return result
def __duplicate(self, cp, duplicate, is_indexable, reindex_kw, immediate_reindex): try: cp = _cb_decode(cp) except: raise CopyError(eInvalid) oblist = [] op = cp[0] app = self.getPhysicalRoot() for mdata in cp[1]: m = Moniker.loadMoniker(mdata) try: ob = m.bind(app) except: raise CopyError(eNotFound) self._verifyObjectPaste(ob, validate_src=op + 1) oblist.append(ob) result = [] def doMove(self, ob): aq_parent(aq_inner(ob))._delObject(ob.getId()) return aq_base(ob) is_doable_id, notify_error, do_sanity_check, do, set_owner, is_clone = ( ( # 0: Copy 'cb_isCopyable', 'Copy Error', lambda self, ob: True, lambda self, ob: ob._getCopy(self), 1, # Take ownership. True, ), ( # 1: Move 'cb_isMoveable', 'Move Error', sanity_check, doMove, 0, # Retain original ownership. False, ), )[op] for ob in oblist: if not getattr(ob, is_doable_id)(): raise CopyError(eNotSupported % escape(ob.getId())) try: ob._notifyOfCopyTo(self, op=op) except: raise CopyError( MessageDialog( title=notify_error, message=sys.exc_info()[1], action='manage_main', )) if not do_sanity_check(self, ob): raise CopyError('This object cannot be pasted into itself') if not set_owner: # try to make ownership explicit so that it gets carried # along to the new location if needed. ob.manage_changeOwnershipType(explicit=1) new_ob = do(self, ob) orig_id = ob.getId() new_id = self._get_id(orig_id) result.append({'id': orig_id, 'new_id': new_id}) new_ob._setId(new_id) if reindex_kw is not None: new_ob.setDefaultReindexParameterDict(reindex_kw) if is_indexable is not None and not is_indexable: new_ob._setNonIndexable() if is_clone: # Clear uids before spawning indexation activities, so the activity does # not do an uid check (as the uid is still the old one, and a new one # will be allocated by _postDuplicate, which must run after object gets # a parent). # Note: do not use __recurse as it only iterates over immediate content, # and then stop instead of calling itself into them. It relies on called # methods to call it back, and we do not want that for _setUid . # Basically this block of code is for ERP5ish objects only. todo_list = [new_ob] while todo_list: document = todo_list.pop() todo_list.extend(document.objectValues()) opaqueValues = getattr(document, 'opaqueValues', None) if opaqueValues is not None: todo_list.extend(opaqueValues()) _setUid = getattr(document, '_setUid', None) if _setUid is not None: _setUid(None) self._setObject(new_id, new_ob, set_owner=set_owner) new_ob = self._getOb(new_id) new_ob._postCopy(self, op=op) if is_clone: if duplicate: new_ob._postDuplicate() else: new_ob.manage_afterClone(new_ob) new_ob.wl_clearLocks() if not set_owner: # try to make ownership implicit if possible new_ob.manage_changeOwnershipType(explicit=0) method = new_ob.immediateReindexObject if reindex_kw is not None: method = partial(method, **reindex_kw) if isinstance(immediate_reindex, ImmediateReindexContextManager): immediate_reindex.append(method) elif immediate_reindex: # Immediately reindexing document that we just pasted is safe, as no # other transaction can by definition see it, so there cannot be a race # condition leading to stale catalog content. method() return op, result
def manage_afterClone(self, item): """ Add self to the workflow. (Called when the object is cloned.) """ #LOG("After Clone ",0, "id:%s containes:%s" % (str(item.id), str(container.id))) # Change uid attribute so that Catalog thinks object was not yet catalogued self_base = aq_base(self) #LOG("After Clone ",0, "self:%s item:%s" % (repr(self), repr(item))) #LOG("After Clone ",0, "self:%s item:%s" % (repr(self), repr(self.getPortalObject().objectIds()))) portal = self.getPortalObject() self_base.uid = portal.portal_catalog.newUid() # Give the Owner local role to the current user, zope only does this if no # local role has been defined on the object, which breaks ERP5Security if getattr(self_base, '__ac_local_roles__', None) is not None: user=getSecurityManager().getUser() if user is not None: userid=user.getId() if userid is not None: #remove previous owners local_role_dict = self.__ac_local_roles__ removable_role_key_list = [] for key, value in local_role_dict.items(): if 'Owner' in value: value.remove('Owner') if len(value) == 0: removable_role_key_list.append(key) # there is no need to keep emptied keys after cloning, it makes # unstable local roles -- if object is cloned it can be different when # after being just added for key in removable_role_key_list: local_role_dict.pop(key) #add new owner l=local_role_dict.setdefault(userid, []) l.append('Owner') # Clear the workflow history # XXX This need to be tested again if getattr(self_base, 'workflow_history', _marker) is not _marker: self_base.workflow_history = PersistentMapping() # Pass - need to find a way to pass calls... self.notifyWorkflowCreated() # Add info about copy to edit workflow REQUEST = get_request() pw = portal.portal_workflow if 'edit_workflow' in pw.getChainFor(self)\ and (REQUEST is None or not REQUEST.get('is_business_template_installation', 0)): if REQUEST is not None and REQUEST.get('__cp', None): copied_item_list = _cb_decode(REQUEST['__cp'])[1] # Guess source item for c_item in copied_item_list: if c_item[-1] in item.getId(): source_item = '/'.join(c_item) break else: source_item = '/'.join(copied_item_list[0]) try: pw.doActionFor(self, 'edit_action', wf_id='edit_workflow', comment=translateString('Object copied from ${source_item}', mapping=(dict(source_item=source_item)))) except WorkflowException: pass else: try: pw.doActionFor(self, 'edit_action', wf_id='edit_workflow', comment=translateString('Object copied as ${item_id}', mapping=(dict(item_id=item.getId())))) except WorkflowException: pass self.__recurse('manage_afterClone', item) # Call a type based method to reset so properties if necessary script = self._getTypeBasedMethod('afterClone') if script is not None and callable(script): script()
def manage_pasteObjects_Version(self, cb_copy_data=None, REQUEST=None): """Paste previously copied objects into the current object. If calling manage_pasteObjects from python code, pass the result of a previous call to manage_cutObjects or manage_copyObjects as the first argument. Also sends IObjectCopiedEvent and IObjectClonedEvent or IObjectWillBeMovedEvent and IObjectMovedEvent. """ ### due to the ticket #14598: the need to also handle a cb_copy_data ### structure that contains the desired new id on a copy/paste operation. ### this feature will be used when creating a new version for an object. ### if there is no new id also incapsulated in the cb_copy_data then ### the copy/paste will work as default. ### also the cut/paste remains the same. if cb_copy_data is not None: cp = cb_copy_data elif REQUEST is not None and REQUEST.has_key('__cp'): cp = REQUEST['__cp'] else: cp = None if cp is None: raise CopyError(eNoData) try: op, mdatas, newids = _cb_decode(cp) except Exception: try: op, mdatas = _cb_decode(cp) newids = [] except Exception: raise CopyError(eInvalid) else: if len(mdatas) != len(newids): raise CopyError(eInvalid) oblist = [] app = self.getPhysicalRoot() for mdata in mdatas: m = loadMoniker(mdata) try: ob = m.bind(app) except ConflictError: raise except: raise CopyError(eNotFound) self._verifyObjectPaste(ob, validate_src=op+1) oblist.append(ob) if len(newids) == 0: newids = ['']*len(oblist) result = [] if op == 0: # Copy operation for ob, new_id in zip(oblist, newids): orig_id = ob.getId() if not ob.cb_isCopyable(): raise CopyError(eNotSupported % escape(orig_id)) try: ob._notifyOfCopyTo(self, op=0) except ConflictError: raise except: raise CopyError(MessageDialog( title="Copy Error", message=sys.exc_info()[1], action='manage_main')) if new_id == '': new_id = self._get_id(orig_id) result.append({'id': orig_id, 'new_id': new_id}) orig_ob = ob ob = ob._getCopy(self) ob._setId(new_id) notify(ObjectCopiedEvent(ob, orig_ob)) self._setObject(new_id, ob) ob = self._getOb(new_id) ob.wl_clearLocks() ob._postCopy(self, op=0) compatibilityCall('manage_afterClone', ob, ob) notify(ObjectClonedEvent(ob)) if REQUEST is not None: return self.manage_main(self, REQUEST, update_menu=1, cb_dataValid=1) elif op == 1: # Move operation for ob in oblist: orig_id = ob.getId() if not ob.cb_isMoveable(): raise CopyError(eNotSupported % escape(orig_id)) try: ob._notifyOfCopyTo(self, op=1) except ConflictError: raise except: raise CopyError(MessageDialog( title="Move Error", message=sys.exc_info()[1], action='manage_main')) if not sanity_check(self, ob): raise CopyError( "This object cannot be pasted into itself") orig_container = aq_parent(aq_inner(ob)) if aq_base(orig_container) is aq_base(self): new_id = orig_id else: new_id = self._get_id(orig_id) result.append({'id': orig_id, 'new_id': new_id}) notify(ObjectWillBeMovedEvent(ob, orig_container, orig_id, self, new_id)) # try to make ownership explicit so that it gets carried # along to the new location if needed. ob.manage_changeOwnershipType(explicit=1) try: orig_container._delObject(orig_id, suppress_events=True) except TypeError: orig_container._delObject(orig_id) warnings.warn( "%s._delObject without suppress_events is discouraged." % orig_container.__class__.__name__, DeprecationWarning) ob = aq_base(ob) ob._setId(new_id) try: self._setObject(new_id, ob, set_owner=0, suppress_events=True) except TypeError: self._setObject(new_id, ob, set_owner=0) warnings.warn( "%s._setObject without suppress_events is discouraged." % self.__class__.__name__, DeprecationWarning) ob = self._getOb(new_id) notify(ObjectMovedEvent(ob, orig_container, orig_id, self, new_id)) notifyContainerModified(orig_container) if aq_base(orig_container) is not aq_base(self): notifyContainerModified(self) ob._postCopy(self, op=1) # try to make ownership implicit if possible ob.manage_changeOwnershipType(explicit=0) if REQUEST is not None: REQUEST['RESPONSE'].setCookie('__cp', 'deleted', path='%s' % cookie_path(REQUEST), expires='Wed, 31-Dec-97 23:59:59 GMT') REQUEST['__cp'] = None return self.manage_main(self, REQUEST, update_menu=1, cb_dataValid=0) return result
def _duplicate(self, cp): try: cp = _cb_decode(cp) except: raise CopyError, 'Clipboard Error' oblist=[] op=cp[0] app = self.getPhysicalRoot() result = [] for mdata in cp[1]: m = Moniker.loadMoniker(mdata) try: ob = m.bind(app) except: raise CopyError, 'Not Found' self._verifyObjectPaste(ob, validate_src=1) oblist.append(ob) if op==0: for ob in oblist: if not ob.cb_isCopyable(): raise CopyError, 'Not Supported' try: ob._notifyOfCopyTo(self, op=0) except: raise CopyError, 'Copy Error' ob = ob._getCopy(self) orig_id = ob.getId() id = self._get_id(ob.getId()) result.append({'id':orig_id, 'new_id':id}) ob._setId(id) self._setObject(id, ob) ob = self._getOb(id) ob._postCopy(self, op=0) ob._postDuplicate() ob.wl_clearLocks() if op==1: # Move operation for ob in oblist: id = ob.getId() if not ob.cb_isMoveable(): raise CopyError, 'Not Supported' try: ob._notifyOfCopyTo(self, op=1) except: raise CopyError, 'Move Error' if not sanity_check(self, ob): raise CopyError, 'This object cannot be pasted into itself' # try to make ownership explicit so that it gets carried # along to the new location if needed. ob.manage_changeOwnershipType(explicit=1) aq_parent(aq_inner(ob))._delObject(id) ob = aq_base(ob) orig_id = id id = self._get_id(id) result.append({'id':orig_id, 'new_id':id }) ob._setId(id) self._setObject(id, ob, set_owner=0) ob = self._getOb(id) ob._postCopy(self, op=1) # try to make ownership implicit if possible ob.manage_changeOwnershipType(explicit=0) return result
def cb_dataValid(self): """Return true if clipboard data seems valid.""" try: cp=_cb_decode(self.REQUEST['__lcp']) except: return 0 return 1
def manage_pasteObjects(self, cp): """Paste previously copied objects into the current object.""" op, mdatas = _cb_decode(cp) COPY = op == 0 # Otherwise its a paste operation # Copy or paste always fails without write permission here sman = getSecurityManager() if not sman.checkPermission(AddFilesystemObject, self): raise CopyError, 'Insufficient Privileges' oblist = [] app = self.getPhysicalRoot() # Loading and security checks for mdata in mdatas: m = loadMoniker(mdata) try: ob = m.bind(app) except ConflictError: raise except: raise CopyError, 'Item not found' if not IReflectoProxy.providedBy(ob) or IReflector.providedBy(ob): raise CopyError, 'Cannot paste into this object' parent = aq_parent(aq_inner(ob)) if not sman.validate(None, parent, None, ob): raise Unauthorized(ob.getId()) if not COPY: if not sman.checkPermission(DeleteObjects, parent): raise Unauthorized('Delete not allowed') prefix = os.path.commonprefix((ob.getFilesystemPath(), self.getFilesystemPath())) if prefix == ob.getFilesystemPath(): raise CopyError, "This object cannot be pasted into itself" oblist.append(ob) result = [] problem_ids = [] path = self.getFilesystemPath() for ob in oblist: old = ob.getId() new = self._generate_copy_id(old) result.append(dict(id=old, new_id=new)) oldpath = ob.getFilesystemPath() newpath = os.path.join(path, new) if COPY: try: if IReflectoDirectory.providedBy(ob): shutil.copytree(oldpath, newpath) else: shutil.copy2(oldpath, newpath) notify(ObjectCopiedEvent(self[new], ob)) notify(ObjectClonedEvent(self[new])) except EnvironmentError: problem_ids.append(result.pop()) else: # paste/move oldparent = aq_parent(aq_inner(ob)) notify(ObjectWillBeMovedEvent(ob, oldparent, old, self, new)) if aq_base(self) is aq_base(oldparent): # No need to move from self to self result[-1]['new_id'] = old # Original CopyContainer does emit events for this case notify(ObjectMovedEvent(ob, self, old, self, old)) continue try: shutil.move(oldpath, newpath) indexview = oldparent.unrestrictedTraverse('@@index') indexview.index() notify(ObjectMovedEvent(self[new], oldparent, old, self, new)) notifyContainerModified(oldparent) except EnvironmentError: if os.path.exists(newpath): # partial move try: if os.path.isdir(newpath): shutil.rmtree(newpath) else: os.unlink(newpath) except EnvironmentError: pass # Really weird access issues, time to bail problem_ids.append(result.pop()) if problem_ids: sm = IStatusMessage(getattr(self, 'REQUEST', None), None) if sm is not None: sm.addStatusMessage( 'Failed to copy or paste some files: %s' % problem_ids, 'stop') if result: indexview = self.unrestrictedTraverse('@@index') indexview.index() notifyContainerModified(self) return result
def manage_pasteObjects(self, cb_copy_data=None, REQUEST=None): """Paste previously copied objects into the current object. If calling manage_pasteObjects from python code, pass the result of a previous call to manage_cutObjects or manage_copyObjects as the first argument. Also sends IObjectCopiedEvent or IObjectMovedEvent. """ if cb_copy_data is not None: cp = cb_copy_data elif REQUEST is not None and REQUEST.has_key('__cp'): cp = REQUEST['__cp'] else: cp = None if cp is None: raise CopyError, eNoData try: op, mdatas = _cb_decode(cp) except: raise CopyError, eInvalid oblist = [] app = self.getPhysicalRoot() for mdata in mdatas: m = Moniker.loadMoniker(mdata) try: ob = m.bind(app) except ConflictError: raise except: raise CopyError, eNotFound self._verifyObjectPaste(ob, validate_src=op+1) oblist.append(ob) result = [] if op == 0: # Copy operation for ob in oblist: orig_id = ob.getId() if not ob.cb_isCopyable(): raise CopyError, eNotSupported % escape(orig_id) try: ob._notifyOfCopyTo(self, op=0) except ConflictError: raise except: raise CopyError, MessageDialog( title="Copy Error", message=sys.exc_info()[1], action='manage_main') id = self._get_id(orig_id) result.append({'id': orig_id, 'new_id': id}) orig_ob = ob ob = ob._getCopy(self) ob._setId(id) notify(ObjectCopiedEvent(ob, orig_ob)) self._setObject(id, ob) ob = self._getOb(id) ob.wl_clearLocks() ob._postCopy(self, op=0) compatibilityCall('manage_afterClone', ob, ob) notify(ObjectClonedEvent(ob)) if REQUEST is not None: return self.manage_main(self, REQUEST, update_menu=1, cb_dataValid=1) elif op == 1: # Move operation for ob in oblist: orig_id = ob.getId() if not ob.cb_isMoveable(): raise CopyError, eNotSupported % escape(orig_id) try: ob._notifyOfCopyTo(self, op=1) except ConflictError: raise except: raise CopyError, MessageDialog( title="Move Error", message=sys.exc_info()[1], action='manage_main') if not sanity_check(self, ob): raise CopyError, "This object cannot be pasted into itself" orig_container = aq_parent(aq_inner(ob)) if aq_base(orig_container) is aq_base(self): id = orig_id else: id = self._get_id(orig_id) result.append({'id': orig_id, 'new_id': id}) notify(ObjectWillBeMovedEvent(ob, orig_container, orig_id, self, id)) # try to make ownership explicit so that it gets carried # along to the new location if needed. ob.manage_changeOwnershipType(explicit=1) try: orig_container._delObject(orig_id, suppress_events=True) except TypeError: # BBB: removed in Zope 2.11 orig_container._delObject(orig_id) warnings.warn( "%s._delObject without suppress_events is deprecated " "and will be removed in Zope 2.11." % orig_container.__class__.__name__, DeprecationWarning) ob = aq_base(ob) ob._setId(id) try: self._setObject(id, ob, set_owner=0, suppress_events=True) except TypeError: # BBB: removed in Zope 2.11 self._setObject(id, ob, set_owner=0) warnings.warn( "%s._setObject without suppress_events is deprecated " "and will be removed in Zope 2.11." % self.__class__.__name__, DeprecationWarning) ob = self._getOb(id) notify(ObjectMovedEvent(ob, orig_container, orig_id, self, id)) notifyContainerModified(orig_container) if aq_base(orig_container) is not aq_base(self): notifyContainerModified(self) ob._postCopy(self, op=1) # try to make ownership implicit if possible ob.manage_changeOwnershipType(explicit=0) if REQUEST is not None: REQUEST['RESPONSE'].setCookie('__cp', 'deleted', path='%s' % cookie_path(REQUEST), expires='Wed, 31-Dec-97 23:59:59 GMT') REQUEST['__cp'] = None return self.manage_main(self, REQUEST, update_menu=1, cb_dataValid=0) return result
def manage_pasteObjects(self, cb_copy_data=None, REQUEST=None): """Paste previously copied objects into the current object, making folders into chapters and RhaptosModuleEditors into ContentPointers (and not destroying their originals). Other objects will be as usual. Largely copied from OFS.CopySupport. If calling manage_pasteObjects from python code, pass the result of a previous call to manage_cutObjects or manage_copyObjects as the first argument.""" cp = None if cb_copy_data is not None: cp = cb_copy_data else: if REQUEST and REQUEST.has_key('__cp'): cp = REQUEST['__cp'] if cp is None: raise CopyError, eNoData try: cp = _cb_decode(cp) except: raise CopyError, eInvalid oblist = [] op = cp[0] app = self.getPhysicalRoot() result = [] duplicates = [] for mdata in cp[1]: m = Moniker.loadMoniker(mdata) try: ob = m.bind(app) except: raise CopyError, eNotFound oblist.append(ob) for ob in oblist: self._verifyObjectPaste(ob) if op == 0: # Copy operation for ob in oblist: if not ob.cb_isCopyable(): raise CopyError, eNotSupported % ob.getId() try: ob._notifyOfCopyTo(self, op=0) except: raise CopyError, MessageDialog(title='Copy Error', message=sys.exc_info()[1], action='manage_main') #ob=ob._getCopy(self) orig_id = ob.getId() id = self._get_id(ob.getId()) ob, dupes = self._getTransformCopy(ob, op, id, self) # NEW duplicates.extend(dupes) if ob: result.append({'id': orig_id, 'new_id': id}) #ob._setId(id) #self._setObject(id, ob) #ob = self._getOb(id) ob.manage_afterClone(ob) if REQUEST is not None: return self.manage_main(self, REQUEST, update_menu=1, cb_dataValid=1) if op == 1: # Move operation for ob in oblist: id = ob.getId() if not ob.cb_isMoveable(): raise CopyError, eNotSupported % id try: ob._notifyOfCopyTo(self, op=1) except: raise CopyError, MessageDialog(title='Move Error', message=sys.exc_info()[1], action='manage_main') if not sanity_check(self, ob): raise CopyError, 'This object cannot be pasted into itself' ### NEW BELOW ### if self._transformableType(ob): # do the "copy" procedure orig_id = ob.getId() id = self._get_id(ob.getId()) ob, dupes = self._getTransformCopy(ob, op, id) duplicates.extend(dupes) if ob: result.append({'id': orig_id, 'new_id': id}) ob.manage_afterClone(ob) else: ### NEW ABOVE (below is ++indented compared to original) ### # try to make ownership explicit so that it gets carried # along to the new location if needed. old = ob orig_id = ob.getId() id = self._get_id(ob.getId()) ob, dupes = self._getTransformCopy(ob, op, id) duplicates.extend(dupes) if ob: result.append({'id': orig_id, 'new_id': id}) ob.manage_afterClone(ob) aq_parent(aq_inner(old))._delObject(id) if REQUEST is not None: REQUEST['RESPONSE'].setCookie( '__cp', 'deleted', path='%s' % cookie_path(REQUEST), expires='Wed, 31-Dec-97 23:59:59 GMT') REQUEST['__cp'] = None return self.manage_main(self, REQUEST, update_menu=1, cb_dataValid=0) if duplicates: raise "DuplicateError", duplicates return result
def manage_pasteObjects(self, cb_copy_data=None, REQUEST=None): """Paste previously copied objects into the current object. If calling manage_pasteObjects from python code, pass the result of a previous call to manage_cutObjects or manage_copyObjects as the first argument. Also sends IObjectCopiedEvent or IObjectMovedEvent. """ if cb_copy_data is not None: cp = cb_copy_data elif REQUEST is not None and REQUEST.has_key('__cp'): cp = REQUEST['__cp'] else: cp = None if cp is None: raise CopyError, eNoData try: op, mdatas = _cb_decode(cp) except: raise CopyError, eInvalid oblist = [] app = self.getPhysicalRoot() for mdata in mdatas: m = Moniker.loadMoniker(mdata) try: ob = m.bind(app) except ConflictError: raise except: raise CopyError, eNotFound self._verifyObjectPaste(ob, validate_src=op + 1) oblist.append(ob) result = [] if op == 0: # Copy operation for ob in oblist: orig_id = ob.getId() if not ob.cb_isCopyable(): raise CopyError, eNotSupported % escape(orig_id) try: ob._notifyOfCopyTo(self, op=0) except ConflictError: raise except: raise CopyError, MessageDialog(title="Copy Error", message=sys.exc_info()[1], action='manage_main') id = self._get_id(orig_id) result.append({'id': orig_id, 'new_id': id}) orig_ob = ob ob = ob._getCopy(self) ob._setId(id) notify(ObjectCopiedEvent(ob, orig_ob)) self._setObject(id, ob) ob = self._getOb(id) ob.wl_clearLocks() ob._postCopy(self, op=0) compatibilityCall('manage_afterClone', ob, ob) notify(ObjectClonedEvent(ob)) if REQUEST is not None: return self.manage_main(self, REQUEST, update_menu=1, cb_dataValid=1) elif op == 1: # Move operation for ob in oblist: orig_id = ob.getId() if not ob.cb_isMoveable(): raise CopyError, eNotSupported % escape(orig_id) try: ob._notifyOfCopyTo(self, op=1) except ConflictError: raise except: raise CopyError, MessageDialog(title="Move Error", message=sys.exc_info()[1], action='manage_main') if not sanity_check(self, ob): raise CopyError, "This object cannot be pasted into itself" orig_container = aq_parent(aq_inner(ob)) if aq_base(orig_container) is aq_base(self): id = orig_id else: id = self._get_id(orig_id) result.append({'id': orig_id, 'new_id': id}) notify( ObjectWillBeMovedEvent(ob, orig_container, orig_id, self, id)) # try to make ownership explicit so that it gets carried # along to the new location if needed. ob.manage_changeOwnershipType(explicit=1) try: orig_container._delObject(orig_id, suppress_events=True) except TypeError: # BBB: removed in Zope 2.11 orig_container._delObject(orig_id) warnings.warn( "%s._delObject without suppress_events is deprecated " "and will be removed in Zope 2.11." % orig_container.__class__.__name__, DeprecationWarning) ob = aq_base(ob) ob._setId(id) try: self._setObject(id, ob, set_owner=0, suppress_events=True) except TypeError: # BBB: removed in Zope 2.11 self._setObject(id, ob, set_owner=0) warnings.warn( "%s._setObject without suppress_events is deprecated " "and will be removed in Zope 2.11." % self.__class__.__name__, DeprecationWarning) ob = self._getOb(id) notify(ObjectMovedEvent(ob, orig_container, orig_id, self, id)) notifyContainerModified(orig_container) if aq_base(orig_container) is not aq_base(self): notifyContainerModified(self) ob._postCopy(self, op=1) # try to make ownership implicit if possible ob.manage_changeOwnershipType(explicit=0) if REQUEST is not None: REQUEST['RESPONSE'].setCookie( '__cp', 'deleted', path='%s' % cookie_path(REQUEST), expires='Wed, 31-Dec-97 23:59:59 GMT') REQUEST['__cp'] = None return self.manage_main(self, REQUEST, update_menu=1, cb_dataValid=0) return result