Skip to content

Commit

Permalink
Merge pull request #47 from plone/versioning_action_4_0_x
Browse files Browse the repository at this point in the history
Versioning action 4 0 x
  • Loading branch information
jensens authored Mar 15, 2019
2 parents ee00a32 + 6572f25 commit 025ae14
Show file tree
Hide file tree
Showing 5 changed files with 202 additions and 1 deletion.
2 changes: 2 additions & 0 deletions news/44.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Add new action `Version object`.
[gbastien]
30 changes: 30 additions & 0 deletions plone/app/contentrules/actions/configure.zcml
Original file line number Diff line number Diff line change
Expand Up @@ -206,4 +206,34 @@
factory=".mail.MailAction"
/>

<!-- Versioning action -->

<adapter factory=".versioning.VersioningActionExecutor" />

<browser:page
for="plone.app.contentrules.browser.interfaces.IRuleActionAdding"
name="plone.actions.Versioning"
class=".versioning.VersioningAddFormView"
permission="plone.app.contentrules.ManageContentRules"
/>

<browser:page
for="plone.app.contentrules.actions.versioning.IVersioningAction"
name="edit"
class=".versioning.VersioningEditFormView"
permission="plone.app.contentrules.ManageContentRules"
/>

<plone:ruleAction
name="plone.actions.Versioning"
title="Version object"
description="Store a new version of the object"
for="*"
event="*"
addview="plone.actions.Versioning"
editview="edit"
schema=".versioning.IVersioningAction"
factory=".versioning.VersioningAction"
/>

</configure>
95 changes: 95 additions & 0 deletions plone/app/contentrules/actions/versioning.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
# -*- coding: utf-8 -*-
from OFS.SimpleItem import SimpleItem
from plone.app.contentrules import PloneMessageFactory as _
from plone.app.contentrules.actions import ActionAddForm
from plone.app.contentrules.actions import ActionEditForm
from plone.app.contentrules.browser.formhelper import ContentRuleFormWrapper
from plone.contentrules.rule.interfaces import IExecutable
from plone.contentrules.rule.interfaces import IRuleElementData
from Products.CMFCore.utils import getToolByName
from zope import schema
from zope.component import adapter
from zope.interface import implementer
from zope.interface import Interface


class IVersioningAction(Interface):
"""Interface for the configurable aspects of a versioning action.
This is also used to create add and edit forms, below.
"""

comment = schema.TextLine(
title=_(u'Comment'),
description=_(
u'The comment added to the history while versioning the content.'),
required=False,
)


@implementer(IVersioningAction, IRuleElementData)
class VersioningAction(SimpleItem):
"""The actual persistent implementation of the versioning action element.
"""

comment = ''

element = 'plone.actions.Versioning'

@property
def summary(self):
return _(
u'Versioning with comment ${comment}',
mapping=dict(comment=self.comment),
)


@adapter(Interface, IVersioningAction, Interface)
@implementer(IExecutable)
class VersioningActionExecutor(object):
"""The executor for this action.
This is registered as an adapter in configure.zcml
"""

def __init__(self, context, element, event):
self.context = context
self.element = element
self.event = event

def __call__(self):
comment = _(self.element.comment)
pr = getToolByName(self.context, 'portal_repository')
pr.save(obj=self.event.object, comment=comment)
return True


class VersioningAddForm(ActionAddForm):
"""An add form for versioning rule actions.
"""
schema = IVersioningAction
label = _(u'Add Versioning Action')
description = _(u'A versioning action will store a version of a content '
u'no matter versioning is enabled for it or not.')
form_name = _(u'Configure element')
Type = VersioningAction


class VersioningAddFormView(ContentRuleFormWrapper):
form = VersioningAddForm


class VersioningEditForm(ActionEditForm):
"""An edit form for versioning rule actions.
z3c.form does all the magic here.
"""
schema = IVersioningAction
label = _(u'Edit Versioning Action')
description = _(u'A versioning action will store a version of a content '
u'no matter versioning is enabled for it or not.')
form_name = _(u'Configure element')


class VersioningEditFormView(ContentRuleFormWrapper):
form = VersioningEditForm
74 changes: 74 additions & 0 deletions plone/app/contentrules/tests/test_action_versioning.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
# -*- coding: utf-8 -*-
from plone.app.contentrules.actions.versioning import VersioningAction
from plone.app.contentrules.actions.versioning import VersioningEditFormView
from plone.app.contentrules.rule import Rule
from plone.app.contentrules.tests.base import ContentRulesTestCase
from plone.contentrules.engine.interfaces import IRuleStorage
from plone.contentrules.rule.interfaces import IExecutable
from plone.contentrules.rule.interfaces import IRuleAction
from zope.component import getMultiAdapter
from zope.component import getUtility
from zope.interface import implementer
from zope.interface import Interface


@implementer(Interface)
class DummyEvent(object):

def __init__(self, object):
self.object = object


class TestVersioningAction(ContentRulesTestCase):

def afterSetUp(self):
self.request = self.layer['request']

def testRegistered(self):
element = getUtility(IRuleAction, name='plone.actions.Versioning')
self.assertEqual('plone.actions.Versioning', element.addview)
self.assertEqual('edit', element.editview)
self.assertEqual(None, element.for_)
self.assertEqual(None, element.event)

def testInvokeAddView(self):
element = getUtility(IRuleAction, name='plone.actions.Versioning')
storage = getUtility(IRuleStorage)
storage[u'foo'] = Rule()
rule = self.portal.restrictedTraverse('++rule++foo')

adding = getMultiAdapter((rule, self.request), name='+action')
addview = getMultiAdapter((adding, self.request), name=element.addview)

addview.form_instance.update()
content = addview.form_instance.create(data={'comment': 'Hello world'})
addview.form_instance.add(content)

e = rule.actions[0]
self.assertTrue(isinstance(e, VersioningAction))
self.assertEqual('Hello world', e.comment)

def testInvokeEditView(self):
element = getUtility(IRuleAction, name='plone.actions.Versioning')
e = VersioningAction()
editview = getMultiAdapter((e, self.request), name=element.editview)
self.assertTrue(isinstance(editview, VersioningEditFormView))

def testExecute(self):
e = VersioningAction()
e.comment = 'Hello world'

ex = getMultiAdapter(
(self.folder, e, DummyEvent(self.folder)), IExecutable)
# not version for now
pr = self.portal.portal_repository
self.assertEqual(pr.getHistoryMetadata(self.folder), [])

# action will create first version
self.assertEqual(True, ex())
self.assertEqual(
pr.getHistoryMetadata(self.folder).getLength(countPurged=False), 1)
# calling action again will create a second version
ex()
self.assertEqual(
pr.getHistoryMetadata(self.folder).getLength(countPurged=False), 2)
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
namespace_packages=['plone', 'plone.app'],
include_package_data=True,
zip_safe=False,
extras_require={'test': 'plone.app.testing'},
extras_require={'test': ['plone.app.testing', 'plone.app.contenttypes[test]']},
install_requires=[
'setuptools',
'plone.contentrules',
Expand Down

1 comment on commit 025ae14

@jenkins-plone-org
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jensens Jenkins CI reporting about code analysis
See the full report here: https://jenkins.plone.org/job/package-plone.app.contentrules/91/violations

plone/app/contentrules/handlers.py:80:12: P002 found "hasattr", consider replacing it
plone/app/contentrules/handlers.py:82:12: P002 found "hasattr", consider replacing it
plone/app/contentrules/handlers.py:89:8: P002 found "hasattr", consider replacing it
plone/app/contentrules/handlers.py:92:8: P002 found "hasattr", consider replacing it
plone/app/contentrules/tests/test_condition_wftransition.py:71:18: C812 missing trailing comma
plone/app/contentrules/tests/test_condition_wftransition.py:86:18: C812 missing trailing comma
plone/app/contentrules/tests/test_condition_wftransition.py:101:18: C812 missing trailing comma
plone/app/contentrules/tests/test_action_mail.py:93:14: C812 missing trailing comma
plone/app/contentrules/tests/test_action_mail.py:245:73: C812 missing trailing comma
plone/app/contentrules/tests/test_events.py:8:11: T000 Todo note found.
plone/app/contentrules/tests/test_events.py:12:11: T000 Todo note found.
plone/app/contentrules/tests/test_action_workflow.py:74:14: C812 missing trailing comma
plone/app/contentrules/tests/test_action_workflow.py:93:14: C812 missing trailing comma
plone/app/contentrules/actions/logger.py:22:60: C812 missing trailing comma
plone/app/contentrules/actions/logger.py:50:10: C812 missing trailing comma
plone/app/contentrules/actions/logger.py:94:18: C812 missing trailing comma
plone/app/contentrules/actions/copy.py:85:45: C812 missing trailing comma
plone/app/contentrules/actions/copy.py:86:18: C812 missing trailing comma
plone/app/contentrules/actions/copy.py:126:56: C812 missing trailing comma
plone/app/contentrules/actions/mail.py:38:22: C812 missing trailing comma
plone/app/contentrules/actions/mail.py:44:57: C812 missing trailing comma
plone/app/contentrules/actions/mail.py:46:23: C812 missing trailing comma
plone/app/contentrules/actions/mail.py:52:67: C812 missing trailing comma
plone/app/contentrules/actions/mail.py:54:22: C812 missing trailing comma
plone/app/contentrules/actions/mail.py:58:80: C812 missing trailing comma
plone/app/contentrules/actions/mail.py:63:22: C812 missing trailing comma
plone/app/contentrules/actions/mail.py:101:5: C901 'MailActionExecutor.__call__' is too complex (12)
plone/app/contentrules/actions/mail.py:105:74: C812 missing trailing comma
plone/app/contentrules/actions/mail.py:128:78: C812 missing trailing comma
plone/app/contentrules/actions/mail.py:134:80: E501 line too long (81 > 79 characters)
plone/app/contentrules/actions/mail.py:149:19: C812 missing trailing comma
plone/app/contentrules/actions/mail.py:162:19: T000 Todo note found.
plone/app/contentrules/actions/mail.py:173:78: C812 missing trailing comma
plone/app/contentrules/actions/move.py:54:52: C812 missing trailing comma
plone/app/contentrules/actions/move.py:69:5: C901 'MoveActionExecutor.__call__' is too complex (14)
plone/app/contentrules/actions/move.py:91:18: C812 missing trailing comma
plone/app/contentrules/actions/move.py:153:56: C812 missing trailing comma
plone/app/contentrules/conditions/portaltype.py:33:72: C812 missing trailing comma
plone/app/contentrules/conditions/portaltype.py:34:10: C812 missing trailing comma
plone/app/contentrules/conditions/portaltype.py:60:50: C812 missing trailing comma
plone/app/contentrules/conditions/portaltype.py:79:16: P002 found "hasattr", consider replacing it
plone/app/contentrules/conditions/portaltype.py:98:34: C812 missing trailing comma
plone/app/contentrules/conditions/portaltype.py:119:26: C812 missing trailing comma
plone/app/contentrules/conditions/wftransition.py:28:68: C812 missing trailing comma
plone/app/contentrules/conditions/wftransition.py:29:10: C812 missing trailing comma
plone/app/contentrules/conditions/fileextension.py:31:22: C812 missing trailing comma
plone/app/contentrules/conditions/fileextension.py:49:50: C812 missing trailing comma
plone/app/contentrules/conditions/fileextension.py:90:78: C812 missing trailing comma
plone/app/contentrules/conditions/fileextension.py:113:78: C812 missing trailing comma
plone/app/contentrules/conditions/wfstate.py:28:63: C812 missing trailing comma
plone/app/contentrules/conditions/wfstate.py:29:10: C812 missing trailing comma
plone/app/contentrules/conditions/wfstate.py:46:59: C812 missing trailing comma
plone/app/contentrules/conditions/group.py:27:77: C812 missing trailing comma
plone/app/contentrules/conditions/group.py:45:60: C812 missing trailing comma
plone/app/contentrules/conditions/group.py:84:70: C812 missing trailing comma
plone/app/contentrules/conditions/group.py:105:70: C812 missing trailing comma
plone/app/contentrules/conditions/role.py:28:76: C812 missing trailing comma
plone/app/contentrules/conditions/role.py:46:59: C812 missing trailing comma
plone/app/contentrules/conditions/role.py:84:51: C812 missing trailing comma
plone/app/contentrules/conditions/role.py:105:51: C812 missing trailing comma
plone/app/contentrules/browser/elements.py:29:5: C901 'ManageElements.__call__' is too complex (12)
plone/app/contentrules/browser/elements.py:77:45: C812 missing trailing comma
plone/app/contentrules/browser/assignments.py:24:5: C901 'ManageAssignments.__call__' is too complex (14)
plone/app/contentrules/browser/assignments.py:154:54: C812 missing trailing comma
plone/app/contentrules/browser/controlpanel.py:83:18: C812 missing trailing comma
plone/app/contentrules/exportimport/rules.py:30:1: I004 isort found an unexpected blank line in imports
plone/app/contentrules/exportimport/rules.py:138:11: T000 Todo note found.
plone/app/contentrules/exportimport/rules.py:201:5: C901 'RulesXMLAdapter._initRules' is too complex (21)

Follow these instructions to reproduce it locally.

Please sign in to comment.