def __call__(self): context = aq_inner(self.context) # We want to redirect to a specific template, else we might # end up downloading a file if self.request.form.has_key('form.button.Checkout'): control = getMultiAdapter((context, self.request), name=u"iterate_control") if not control.checkout_allowed(): raise CheckoutException(u"Not allowed") location = self.request.form.get('checkout_location', None) locator = None try: locator = [c['locator'] for c in self.containers() if c['name'] == location][0] except IndexError: IStatusMessage(self.request).addStatusMessage(_("Cannot find checkout location"), type='stop') view_url = context.restrictedTraverse("@@plone_context_state").view_url() self.request.response.redirect(view_url) return policy = ICheckinCheckoutPolicy(context) wc = policy.checkout(locator()) # we do this for metadata update side affects which will update lock info context.reindexObject('review_state') IStatusMessage(self.request).addStatusMessage(_("Check-out created"), type='info') view_url = wc.restrictedTraverse("@@plone_context_state").view_url() self.request.response.redirect(view_url) elif self.request.form.has_key('form.button.Cancel'): view_url = context.restrictedTraverse("@@plone_context_state").view_url() self.request.response.redirect(view_url) else: return self.index()
def test_baselineNoCopyReferences(self): # ensure that custom state is maintained with the no copy adapter # setup the named ref adapter from zope import component from Products.Archetypes.interfaces import IBaseObject from plone.app.iterate import relation, interfaces from plone.app.iterate.tests.utils import CustomReference component.provideAdapter( adapts=(IBaseObject,), provides=interfaces.ICheckinCheckoutReference, factory=relation.NoCopyReferenceAdapter, name="zebra") doc = self.portal.docs.doc1 ref = doc.addReference( self.portal.docs, "zebra", referenceClass=CustomReference) ref.custom_state = "hello world" wc = ICheckinCheckoutPolicy(doc).checkout(self.portal.workarea) self.assertEqual(len(wc.getReferences("zebra")), 0) doc = ICheckinCheckoutPolicy(wc).checkin("updated") self.assertEqual(len(doc.getReferences("zebra")), 1) ref = doc.getReferenceImpl("zebra")[0] self.assert_(hasattr(ref, "custom_state")) self.assertEqual(ref.custom_state, "hello world")
def handle_edit(self): policy = ICheckinCheckoutPolicy(self.context) obj = policy.getWorkingCopy() #baseline = policy.getBaseline() if obj is None: obj = self.context state = get_state(obj) if state in ['private', 'sent']: url = '{0}/edit'.format(obj.absolute_url()) return self.request.response.redirect(url) elif state == 'published': # create copy, go to it wc = self._checkout() url = '{0}/edit'.format(wc.absolute_url()) return self.request.response.redirect(url) elif state == 'pending': # retract object, go to it transition(obj, to_state='sent') url = '{0}/edit'.format(obj.absolute_url()) return self.request.response.redirect(url) raise ValueError ('unknown state')
def _checkout(self): # NOTE: this code is copied from plone.app.iterate.browser.checkout context = aq_inner(self.context) containers = list(self._containers()) location = containers[0]["name"] # We want to redirect to a specific template, else we might # end up downloading a file control = getMultiAdapter((context, self.request), name=u"iterate_control") if not control.checkout_allowed(): raise CheckoutException(u"Not allowed") locator = None try: locator = [c["locator"] for c in containers if c["name"] == location][0] except IndexError: IStatusMessage(self.request).addStatusMessage(_("Cannot find checkout location"), type="stop") view_url = context.restrictedTraverse("@@plone_context_state").view_url() self.request.response.redirect(view_url) return policy = ICheckinCheckoutPolicy(context) wc = policy.checkout(locator()) # we do this for metadata update side affects which will update lock info context.reindexObject("review_state") IStatusMessage(self.request).addStatusMessage(_("Check-out created"), type="info") # view_url = wc.restrictedTraverse("@@plone_context_state").view_url() return wc
def _checkout(self): # NOTE: this code is copied from plone.app.iterate.browser.checkout context = aq_inner(self.context) # containers = list(self._containers()) location = self.context.aq_parent #containers[0]['name'] # We want to redirect to a specific template, else we might # end up downloading a file control = getMultiAdapter((context, self.request), name=u"iterate_control") if not control.checkout_allowed(): raise CheckoutException(u"Not allowed") policy = ICheckinCheckoutPolicy(context) wc = policy.checkout(location) transition(wc, to_state='sent') # we do this for metadata update side affects which will update lock info context.reindexObject('review_state') IStatusMessage(self.request).addStatusMessage(_("Check-out created"), type='info') #view_url = wc.restrictedTraverse("@@plone_context_state").view_url() return wc
def __call__(self): context = aq_inner(self.context) if 'form.button.Checkin' in self.request.form: control = getMultiAdapter( (context, self.request), name=u'iterate_control') if not control.checkin_allowed(): raise CheckinException(u'Not a checkout') message = self.request.form.get('checkin_message', '') policy = ICheckinCheckoutPolicy(context) baseline = policy.checkin(message) IStatusMessage(self.request).addStatusMessage( _('Checked in'), type='info') view_url = baseline.restrictedTraverse( '@@plone_context_state').view_url() self.request.response.redirect(view_url) elif 'form.button.Cancel'in self.request.form: view_url = context.restrictedTraverse( '@@plone_context_state').view_url() self.request.response.redirect(view_url) else: return self.index()
def get_baseline_state(self): policy = ICheckinCheckoutPolicy(self.context) baseline = policy.getBaseline() if baseline is None: baseline = self.context return get_state(baseline)
def checkin_allowed(self): """Check if a checkin is allowed """ context = aq_inner(self.context) checkPermission = getSecurityManager().checkPermission if not interfaces.IIterateAware.providedBy(context): return False archiver = interfaces.IObjectArchiver(context) if not archiver.isVersionable(): return False if not IWorkingCopy.providedBy(context): return False policy = ICheckinCheckoutPolicy(context, None) if policy is None: return False original = policy.getBaseline() if original is None: return False can_modify = checkPermission( Products.CMFCore.permissions.ModifyPortalContent, original, ) if not can_modify: return False return True
def test_folderContents(self): """When an folder is checked out, and item is added, and then the folder is checked back in, the added item is in the new version of the folder. UIDs of contained content are also preserved.""" container = self.portal.docs folder = container[container.invokeFactory( type_name='Folder', id='foo-folder')] existing_doc = folder[folder.invokeFactory( type_name='Document', id='existing-folder-item')] existing_doc_uid = existing_doc.UID() self.repo.save(folder) wc = ICheckinCheckoutPolicy(folder).checkout(container) new_doc = wc[wc.invokeFactory(type_name='Document', id='new-folder-item', text='new folder item text')] new_doc_uid = new_doc.UID() new_folder = ICheckinCheckoutPolicy(wc).checkin("updated") catalog = getToolByName(self.portal, 'portal_catalog') self.assertTrue('existing-folder-item' in new_folder) self.assertEqual( new_folder['existing-folder-item'].UID(), existing_doc_uid) self.assertTrue('new-folder-item' in new_folder) self.assertEqual(new_folder['new-folder-item'].UID(), new_doc_uid) brains = catalog(path='/'.join( new_folder['new-folder-item'].getPhysicalPath())) self.assertTrue(brains) self.assertTrue('new folder item text' in new_folder['new-folder-item'].getText())
def test_wcNewForwardReferencesCopied( self ): # ensure that new wc references are copied back to the baseline on checkin doc = self.portal.docs.doc1 doc.addReference( self.portal.docs ) self.assertEqual( len(doc.getReferences("zebra")), 0) wc = ICheckinCheckoutPolicy( doc ).checkout( self.portal.workarea ) wc.addReference( self.portal.docs.doc2, "zebra") doc = ICheckinCheckoutPolicy( wc ).checkin( "updated" ) self.assertEqual( len(doc.getReferences("zebra")), 1 )
def cancel_allowed(self): """Check to see if the user can cancel the checkout on the given working copy """ policy = ICheckinCheckoutPolicy(self.context, None) if policy is None: return False original = policy.getBaseline() return original is not None
def get_working_copy(self): context = self.context policy = ICheckinCheckoutPolicy(context, None) if policy is None: return False wc = policy.getWorkingCopy() return wc
def test_wcNewBackwardReferencesCopied(self): # ensure that new wc back references are copied back to the baseline on # checkin doc = self.portal.docs.doc1 self.assertEqual(len(doc.getBackReferences('zebra')), 0) wc = ICheckinCheckoutPolicy(doc).checkout(self.portal.workarea) self.portal.docs.doc2.addReference(wc, 'zebra') self.assertEqual(len(wc.getBackReferences('zebra')), 1) doc = ICheckinCheckoutPolicy(wc).checkin('updated') self.assertEqual(len(doc.getBackReferences('zebra')), 1)
def test_cancel_checkout(self): self.setRoles(('Contributor',)) p1 = self.places['1'] self.failUnless('foo' in p1, p1.keys()) wc = ICheckinCheckoutPolicy(p1).checkout(self.places) self.failUnlessEqual(len(wc.keys()), 0, wc.keys()) p1 = ICheckinCheckoutPolicy(wc).cancelCheckout() self.failUnless('foo' in p1, p1.keys()) # A child's history acquires its parent's history history = self.repo.getHistory(p1['foo']) self.failUnlessEqual(len(history), 1)
def __call__(self): policy = ICheckinCheckoutPolicy(self.context) if IBaseline.providedBy(self.context): self.baseline = self.context self.working_copy = policy.getWorkingCopy() elif IWorkingCopy.providedBy(self.context): self.working_copy = self.context self.baseline = policy.getBaseline() else: raise AttributeError('Invalid Context') return self.index()
def checkInIfNeeded(document, event): context = aq_inner(document) workflowTool = getToolByName(context, "portal_workflow") status = workflowTool.getStatusOf("1MX_wiki_workflow", document) if IWorkingCopy.providedBy(context) and status["review_state"] == "internally_published": policy = ICheckinCheckoutPolicy(context) baseline = policy.checkin("") IStatusMessage(context.REQUEST).addStatusMessage( _("Checked in"), type='info') view_url = baseline.unrestrictedTraverse("@@plone_context_state").view_url() transaction.commit() raise Redirect(view_url)
def test_control_cancel_on_original_does_not_delete_original(self): # checkout document doc = self.portal.docs.doc1 policy = ICheckinCheckoutPolicy(self.portal.docs.doc1, None) policy.checkout(self.portal.workarea) # get cancel browser view from plone.app.iterate.browser.cancel import Cancel cancel = Cancel(doc, self.layer['request']) self.layer['request'].form['form.button.Cancel'] = True # check if cancel on original raises the correct exception from plone.app.iterate.interfaces import CheckoutException with self.assertRaises(CheckoutException): cancel()
def test_add_name_to_wc(self): self.setRoles(('Contributor',)) p1 = self.places['1'] self.failUnless('foo' in p1, p1.keys()) wc = ICheckinCheckoutPolicy(p1).checkout(self.places) nid = wc.invokeFactory('Name', 'bar', nameTransliterated=u"Bar") self.failUnless('bar' in wc, wc.keys()) p1 = ICheckinCheckoutPolicy(wc).checkin("updated") self.failUnless('foo' in p1, p1.keys()) self.failUnless('bar' in p1, p1.keys()) # A child's history acquires its parent's history history = self.repo.getHistory(p1['foo']) self.failUnlessEqual(len(history), 2) history = self.repo.getHistory(p1['bar']) self.failUnlessEqual(len(history), 1)
def test_annotation_saved_on_checkin(self): # First we get and save a custom annotation to the existing object obj_annotations = IAnnotations(self.s1) self.assertEqual(obj_annotations, {}) obj_annotations['key1'] = u'value1' obj_annotations = IAnnotations(self.s1) self.assertEqual(obj_annotations, {'key1': u'value1'}) # Now, let's get a working copy for it. locators = getAdapters((self.s1,), IWCContainerLocator) location = u'plone.app.iterate.parent' locator = [c[1] for c in locators if c[0] == location][0] policy = ICheckinCheckoutPolicy(self.s1) wc = policy.checkout(locator()) # Annotations should be the same new_annotations = IAnnotations(wc) self.assertEqual(new_annotations['key1'], u'value1') # Now, let's modify the existing one, and create a new one new_annotations['key1'] = u'value2' new_annotations['key2'] = u'value1' # Check that annotations were stored correctly and original ones were # not overriten new_annotations = IAnnotations(wc) self.assertEqual(new_annotations['key1'], u'value2') self.assertEqual(new_annotations['key2'], u'value1') obj_annotations = IAnnotations(self.s1) self.assertEqual(obj_annotations['key1'], u'value1') self.assertFalse('key2' in obj_annotations) # Now, we do a checkin policy = ICheckinCheckoutPolicy(wc) policy.checkin(u'Commit message') # And finally check that the old object has the same annotations as # its working copy obj_annotations = IAnnotations(self.s1) self.assertTrue('key1' in obj_annotations) self.assertTrue('key2' in obj_annotations) self.assertEqual(obj_annotations['key1'], u'value2') self.assertEqual(obj_annotations['key2'], u'value1')
def test_nothing(self): self.setRoles(('Contributor',)) p1 = self.places['1'] self.failUnless('foo' in p1, p1.keys()) wc = ICheckinCheckoutPolicy(p1).checkout(self.places) state = self.wf.getInfoFor(wc, 'review_state') self.failUnlessEqual(state, 'private') self.failUnlessEqual(len(wc.keys()), 0, wc.keys()) # A child's history acquires its parent's history history = self.repo.getHistory(p1['foo']) self.failUnlessEqual(len(history), 1) p1 = ICheckinCheckoutPolicy(wc).checkin("updated") self.failUnless('foo' in p1, p1.keys()) # A child's history acquires its parent's history history = self.repo.getHistory(p1['foo']) self.failUnlessEqual(len(history), 2)
def checkout_object(self, fileobj, related, mimetype): """Replaces the content of uploaded file/image at the working copy of the related object """ control = getMultiAdapter( (related, self.context.REQUEST), name=u"iterate_control") policy = ICheckinCheckoutPolicy(related) working_copies = related.getBRefs(WorkingCopyRelation.relationship) if control.checkout_allowed(): folder = related.aq_parent working_copy = policy.checkout(folder) elif working_copies: working_copy = working_copies[0] else: raise Exception(u"Can't obtain working copy.") working_copy.update_data(fileobj, mimetype) working_copy.reindexObject() return '/'.join(related.getPhysicalPath())
def test_baselineBrokenReferencesRemoved(self): # When the baseline has a reference to a deleted object, a # checkout should not fail with a ReferenceException. doc = self.portal.docs.doc1 doc.addReference(self.portal.docs.doc2, 'pony') self.portal.docs._delOb('doc2') # _delOb is low level enough that the reference does not get cleaned # up. self.assertEqual(len(doc.getReferences()), 1) wc = ICheckinCheckoutPolicy(doc).checkout(self.portal.workarea) # The working copy has one reference: its original. self.assertEqual(len(wc.getReferences()), 1) self.assertEqual(wc.getReferences()[0].id, 'doc1') doc = ICheckinCheckoutPolicy(wc).checkin('updated') # The checkin removes the broken reference. self.assertEqual(len(doc.getReferences()), 0)
def test_baselineReferencesMaintained(self): # ensure that baseline references are maintained when the object is # checked in copies forward, bkw are not copied, but are maintained. doc = self.portal.docs.doc1 doc.addReference(self.portal.docs, "elephant") self.portal.docs.doc2.addReference(doc) wc = ICheckinCheckoutPolicy(doc).checkout(self.portal.workarea) doc = ICheckinCheckoutPolicy(wc).checkin("updated") # TODO: This fails in Plone 4.1. The new optimized catalog lookups # in the reference catalog no longer filter out non-existing reference # objects. In both Plone 4.0 and 4.1 there's two references, one of # them is a stale catalog entry in the reference catalog. The real fix # is to figure out how the stale catalog entry gets in there self.assertEqual(len(doc.getReferences()), 1) self.assertEqual(len(doc.getBackReferences()), 1)
def __call__(self): context = aq_inner(self.context) if self.request.form.has_key('form.button.Cancel'): control = getMultiAdapter((context, self.request), name=u"iterate_control") if not control.cancel_allowed(): raise CheckoutException(u"Not a checkout") policy = ICheckinCheckoutPolicy(context) baseline = policy.cancelCheckout() baseline.reindexObject() IStatusMessage(self.request).addStatusMessage(_(u"Checkout cancelled"), type='info') view_url = baseline.restrictedTraverse("@@plone_context_state").view_url() self.request.response.redirect(view_url) elif self.request.form.has_key('form.button.Keep'): view_url = context.restrictedTraverse("@@plone_context_state").view_url() self.request.response.redirect(view_url) else: return self.template()
def test_folderOrder(self): """When an item is checked out and then back in, the original folder order is preserved.""" container = self.portal.docs doc = container.doc1 original_position = container.getObjectPosition(doc.getId()) # check that there is another document which could interact with # position of document the test work on doc2_position = container.getObjectPosition('doc2') self.assertTrue(doc2_position > original_position) self.repo.save(doc) wc = ICheckinCheckoutPolicy(doc).checkout(container) wc.text = 'new document text' # check that the copy is put after the second document copy_position = container.getObjectPosition(wc.getId()) self.assertTrue(copy_position > doc2_position) new_doc = ICheckinCheckoutPolicy(wc).checkin('updated') new_position = container.getObjectPosition(new_doc.getId()) self.assertEqual(new_position, original_position)
def checkout_allowed(self): """Check if a checkout is allowed. """ context = aq_inner(self.context) if not interfaces.IIterateAware.providedBy(context): return False archiver = interfaces.IObjectArchiver(context) if not archiver.isVersionable(): return False policy = ICheckinCheckoutPolicy(context, None) if policy is None: return False if policy.getWorkingCopy() is not None: return False # check if its is a checkout if policy.getBaseline() is not None: return False return True
def do_checkout(self): policy = ICheckinCheckoutPolicy(self.obj) working_copy = policy.checkout(self.folder) return working_copy
def do_cancel(self, working_copy): policy = ICheckinCheckoutPolicy(working_copy) policy.cancelCheckout()
def do_checkin(self, working_copy): policy = ICheckinCheckoutPolicy(working_copy) policy.checkin('')
def do_checkout(self, obj): policy = ICheckinCheckoutPolicy(obj) working_copy = policy.checkout(self.folder) return working_copy
def do_checkin(self, working_copy): policy = ICheckinCheckoutPolicy(working_copy) policy.checkin("")
def do_checkin(self, working_copy): policy = ICheckinCheckoutPolicy(working_copy) return policy.checkin('')
''.format(new_domain)) continue out( 'This new reference is cleared for addition; i.e., there ' 'does not appear to be any conflicting reference already in ' 'place.', level=1) valid.append(i) # add the valid references if len(valid) > 0: # check out a working copy and get a dictionary of the current # references container = aq_parent(content) policy = ICheckinCheckoutPolicy(content) working_copy = policy.checkout(container) out('Checked out working copy: {}' ''.format(working_copy.absolute_url_path()), level=1) field = working_copy.getField('referenceCitations') old_values = field.getRaw(working_copy) values = {k: v for k, v in old_values.items() if k != 'size'} old_size = field.getSize(working_copy) # sometimes the references array field returns additional # values beyond its "size" that are either empty or repeats # kill them with fire and impunity if old_size < len(values): # print( # '>>> old_size = {}; len(values) = {}'