diff --git a/.gitignore b/.gitignore
index 9f69d63..8cc088f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -7,6 +7,8 @@
.pydevproject
.settings/
bin/
+include/
+lib/
develop-eggs/
parts/
src/*
diff --git a/checkouts.cfg b/checkouts.cfg
index cbc482e..f73c7e3 100644
--- a/checkouts.cfg
+++ b/checkouts.cfg
@@ -8,3 +8,4 @@ auto-checkout +=
plone.dexterity
z3c.form
plone.app.z3cform
+ collective.z3cform.rolefield
diff --git a/setup.py b/setup.py
index 0dab4af..00e2136 100644
--- a/setup.py
+++ b/setup.py
@@ -48,6 +48,7 @@ setup(name='collective.dms.basecontent',
'z3c.blobfile',
'plone.app.relationfield',
'plone.formwidget.contenttree',
+ 'collective.z3cform.rolefield',
],
extras_require={
'test': ['plone.app.testing',
diff --git a/sources.cfg b/sources.cfg
index 3d2c952..f0d9a64 100644
--- a/sources.cfg
+++ b/sources.cfg
@@ -17,6 +17,7 @@ entrouvert_push = git+ssh://git@repos.entrouvert.org
[sources]
collective.dms.thesaurus = git ${remotes:collective}/collective.dms.thesaurus.git pushurl=${remotes:collective_push}/collective.dms.thesaurus.git
collective.dms.basecontent = git ${remotes:collective}/collective.dms.basecontent.git pushurl=${remotes:collective_push}/collective.dms.basecontent.git
+collective.z3cform.rolefield = git ${remotes:collective}/collective.z3cform.rolefield.git pushurl=${remotes:collective_push}/collective.z3cform.rolefield.git
plone.app.z3cform = git ${remotes:plone}/plone.app.z3cform.git pushurl=${remotes:plone_push}/plone.app.z3cform.git
plone.dexterity = git ${remotes:cedricmessiant}/plone.dexterity.git pushurl=${remotes:cedricmessiant_push}/plone.dexterity.git
z3c.form = git ${remotes:zopefoundation}/z3c.form pushurl=${remotes:zopefoundation_push}/z3c.form
diff --git a/src/collective/dms/basecontent/__init__.py b/src/collective/dms/basecontent/__init__.py
index 8248407..a627705 100644
--- a/src/collective/dms/basecontent/__init__.py
+++ b/src/collective/dms/basecontent/__init__.py
@@ -2,8 +2,6 @@ from zope.i18nmessageid import MessageFactory
_ = MessageFactory("collective.dms.basecontent")
-from ._field import LocalRolesToPrincipals
-
def initialize(context):
"""Initializer called when used as a Zope 2 product."""
diff --git a/src/collective/dms/basecontent/_field.py b/src/collective/dms/basecontent/_field.py
deleted file mode 100644
index be7a0d1..0000000
--- a/src/collective/dms/basecontent/_field.py
+++ /dev/null
@@ -1,98 +0,0 @@
-# -*- coding: utf-8 -*-
-from zope.component import adapts
-from zope.interface import implementer
-from zope.interface import Interface
-
-from zope.schema.interfaces import IList
-from zope.schema import List, Tuple
-from zope.interface import Invalid
-
-from z3c.form.datamanager import AttributeField
-
-import logging
-logger = logging.getLogger('collective.dms.basecontent._field')
-
-
-class ILocalRolesToPrincipals(IList):
- """Field that list principals depending on a vocabulary (by default list every available groups)
- and that assign local roles defined in the roles_to_assign attribute."""
-
- # this attribute will contains a tuple of principal to assign when the value is set
- roles_to_assign = Tuple(
- title=u"Roles to assign",
- description=u"""\
- Roles that will be automatically assigned as local roles to selected principals.
- """,
- required=True)
-
-
-@implementer(ILocalRolesToPrincipals)
-class LocalRolesToPrincipals(List):
- """Field that list principals depending on a vocabulary (by default list every available groups)
- and that assign local roles defined in the roles_to_assign attribute."""
-
- def __init__(self, roles_to_assign=(), **kw):
- self.roles_to_assign = roles_to_assign
- super(LocalRolesToPrincipals, self).__init__(**kw)
-
- def validate(self, value):
- """Check that we have roles to assign, this is mendatory and
- that roles we want to assign actually exist."""
- super(LocalRolesToPrincipals, self)._validate(value)
-
- # the field must specify some roles to assign as this is a required value
- if not self.roles_to_assign:
- raise Invalid(u'The field is not configured correctly, roles_to_assign is required. Contact system administrator!')
-
- # check that roles we want to assign actually exist
- existingRoles = [role for role in self.context.acl_users.portal_role_manager.listRoleIds()]
- for role_to_assign in self.roles_to_assign:
- if not role_to_assign in existingRoles:
- raise Invalid(u'The field is not configured correctly, the defined role \'%s\' does not exist. Contact system administrator!' % role_to_assign)
-
-
-class LocalRolesToPrincipalsDataManager(AttributeField):
- """A data manager which set local roles when saving the field."""
- adapts(Interface, ILocalRolesToPrincipals)
-
- def set(self, value):
- """See z3c.form.interfaces.IDataManager"""
- # set local roles before setting the value so we still have access to the old value
- roles_to_assign = self.field.roles_to_assign
- # ---1 --- first find assigned roles to remove
- # it is not that easy to remove local roles because no helper method exists for removing
- # some specific local roles, only a method for removing every local roles for a list of principals...
- old_value = self.field.get(self.context) or ()
- # now check between old_value and value (new value) what is missing
- removed_principals = set(old_value).difference(set(value))
- # remove local_roles for removed_principals
- for local_role in self.context.get_local_roles():
- # a local_role is like ('Administrators', (u'Contributor', u'Reviewer'))
- principal = local_role[0]
- if principal in removed_principals:
- cleaned_local_roles = list(local_role[1])
- for role_to_assign in roles_to_assign:
- try:
- cleaned_local_roles.remove(role_to_assign)
- except ValueError:
- # if a role to remove was already removed (???) pass
- logger.warn("Failed to remove role '%s' for principal '%s' on object '%s'" \
- % (role_to_assign, principal, '/'.join(self.context.getPhysicalPath())))
- # if there are still some local_roles, use manage_setLocalRoles
- if cleaned_local_roles:
- self.context.manage_setLocalRoles(principal, cleaned_local_roles)
- else:
- # either use manage_delLocalRoles
- self.context.manage_delLocalRoles((principal,))
- # ---2 --- now add new local roles
- added_principals = set(value).difference(set(old_value))
- for added_principal in added_principals:
- self.context.manage_addLocalRoles(added_principal, roles_to_assign)
- # finally set the value
- super(LocalRolesToPrincipalsDataManager, self).set(value)
-
-import plone.supermodel.exportimport
-
-LocalRolesToPrincipalsHandler = plone.supermodel.exportimport.BaseHandler(LocalRolesToPrincipals)
-
-
diff --git a/src/collective/dms/basecontent/configure.zcml b/src/collective/dms/basecontent/configure.zcml
index c30e3ae..757442c 100644
--- a/src/collective/dms/basecontent/configure.zcml
+++ b/src/collective/dms/basecontent/configure.zcml
@@ -36,13 +36,4 @@
name="schema_policy_dmsfile"
/>
-
-
-
-
diff --git a/src/collective/dms/basecontent/dmsdocument.py b/src/collective/dms/basecontent/dmsdocument.py
index 281c7ce..fa55c7e 100644
--- a/src/collective/dms/basecontent/dmsdocument.py
+++ b/src/collective/dms/basecontent/dmsdocument.py
@@ -9,7 +9,7 @@ from five import grok
from collective.dms.basecontent.relateddocs import RelatedDocs
from . import _
-from ._field import LocalRolesToPrincipals
+from collective.z3cform.rolefield.field import LocalRolesToPrincipals
from zope.schema.interfaces import IVocabularyFactory
@@ -20,27 +20,27 @@ class IDmsDocument(model.Schema):
notes = schema.Text(
title=_(u"Notes"),
required=False,
- )
+ )
treating_groups = LocalRolesToPrincipals(
title=_(u"Treating groups"),
required=False,
roles_to_assign=('Editor',),
value_type=schema.Choice(vocabulary=u'collective.dms.basecontent.treating_groups',)
- )
+ )
recipient_groups = LocalRolesToPrincipals(
title=_(u"Recipient groups"),
required=False,
roles_to_assign=('Reader',),
value_type=schema.Choice(vocabulary=u'collective.dms.basecontent.recipient_groups',)
- )
+ )
related_docs = RelatedDocs(
title=_(u"Related documents"),
required=False,
- display_backrefs=True)
-
+ display_backrefs=True,
+ )
class DmsDocument(Container):
diff --git a/src/collective/dms/basecontent/profiles/testing/metadata.xml b/src/collective/dms/basecontent/profiles/testing/metadata.xml
index b93fe26..000197f 100644
--- a/src/collective/dms/basecontent/profiles/testing/metadata.xml
+++ b/src/collective/dms/basecontent/profiles/testing/metadata.xml
@@ -1,8 +1,4 @@
0001
-
- profile-plone.app.dexterity:default
- profile-plone.app.relationfield:default
-
diff --git a/src/collective/dms/basecontent/profiles/testing/types.xml b/src/collective/dms/basecontent/profiles/testing/types.xml
deleted file mode 100644
index 44b57c4..0000000
--- a/src/collective/dms/basecontent/profiles/testing/types.xml
+++ /dev/null
@@ -1,5 +0,0 @@
-
-
diff --git a/src/collective/dms/basecontent/profiles/testing/types/testingtype.xml b/src/collective/dms/basecontent/profiles/testing/types/testingtype.xml
deleted file mode 100644
index a0f6f8b..0000000
--- a/src/collective/dms/basecontent/profiles/testing/types/testingtype.xml
+++ /dev/null
@@ -1,55 +0,0 @@
-
-
- TestingType
- None
- string:${portal_url}/folder_icon.png
- testingtype
- string:${folder_url}/++add++testingtype
-
- view
- True
- True
-
-
-
-
- False
- view
-
-
-
- False
- cmf.AddPortalContent
- plone.dexterity.content.Container
-
-
-
-
-
-
-<model xmlns="http://namespaces.plone.org/supermodel/schema">
- <schema>
- <field name="testingField" type="collective.dms.basecontent.LocalRolesToPrincipals">
- <title>testingField</title>
- <required>False</required>
- <roles_to_assign>('Reader',)</roles_to_assign>
- </field>
- </schema>
-</model>
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/src/collective/dms/basecontent/tests/test_fields.py b/src/collective/dms/basecontent/tests/test_fields.py
deleted file mode 100644
index ad879a0..0000000
--- a/src/collective/dms/basecontent/tests/test_fields.py
+++ /dev/null
@@ -1,83 +0,0 @@
-# -*- coding: utf8 -*-
-
-import unittest2 as unittest
-
-from zope.interface import Invalid
-
-from plone.app.testing.helpers import setRoles
-
-from ecreall.helpers.testing.base import BaseTest
-
-from collective.dms.basecontent.testing import DMS_TESTS_PROFILE_FUNCTIONAL
-from collective.dms.basecontent._field import LocalRolesToPrincipalsDataManager
-
-
-class TestFields(unittest.TestCase, BaseTest):
- """Tests adapters"""
-
- layer = DMS_TESTS_PROFILE_FUNCTIONAL
-
- def setUp(self):
- super(TestFields, self).setUp()
- self.portal = self.layer['portal']
-
- def _getTargetClass(self):
- from collective.dms.basecontent._field import LocalRolesToPrincipals
- return LocalRolesToPrincipals
-
- def _makeOne(self, *args, **kw):
- field = self._getTargetClass()(*args, **kw)
- # this is needed to initialize the vocabulary
- return field.bind(self.portal)
-
- def test_roles_to_assign_attribute(self):
- """If the field is not correctly configured, it fails upon validation."""
- field = self._makeOne()
- # the roles_to_assign attribute is required, if empty, validate fails
- self.assertEquals(field.roles_to_assign, ())
- self.assertRaises(Invalid, field.validate, [])
- # if we want to assign role but one does not exist, validate fails too
- field = self._makeOne(roles_to_assign=('Editor', 'WrongRole',))
- self.assertRaises(Invalid, field.validate, [])
- # if we have valid values, it works like a charm ;-)
- field = self._makeOne(roles_to_assign=('Editor', 'Reader',))
- field.validate([])
-
- def test_datamanager(self):
- """Test the local_roles assignment mechanism managed by the datamanager."""
- testingfield = self.portal.portal_types.testingtype.lookupSchema()['testingField']
- testingfield.roles_to_assign = ('Editor', 'Contributor',)
- # first create a sample object
- # make the default user a Manager
- member = self.portal.portal_membership.getAuthenticatedMember()
- setRoles(self.portal, member.getId(), ('Manager',))
- # create an object
- self.portal.invokeFactory('testingtype', id='testingobj')
- testingobj = getattr(self.portal, 'testingobj')
- datamanager = LocalRolesToPrincipalsDataManager(testingobj, testingfield)
- self.failIf('Administrators' in testingobj.__ac_local_roles__.keys())
- datamanager.set(('Administrators',))
- # now we have local_roles for 'Administrators'
- self.failUnless('Administrators' in testingobj.__ac_local_roles__.keys())
- # moreover, local_roles for 'Administrators' are ('Editor', 'Contributor',)
- self.assertEquals(tuple(testingobj.__ac_local_roles__['Administrators']), testingfield.roles_to_assign)
- # add a principal, test that local_roles are adapted
- self.failIf('Reviewers' in testingobj.__ac_local_roles__.keys())
- # the value is now ('Administrators', 'Reviewers',)
- datamanager.set(('Administrators', 'Reviewers',))
- self.failUnless('Reviewers' in testingobj.__ac_local_roles__.keys())
- self.assertEquals(tuple(testingobj.__ac_local_roles__['Reviewers']), testingfield.roles_to_assign)
- # remove a group, check managed roles
- # removing a group is made by passing new value where an existing group is no more present
- self.failUnless('Administrators' in testingobj.__ac_local_roles__.keys())
- datamanager.set(('Reviewers',))
- self.failIf('Administrators' in testingobj.__ac_local_roles__.keys())
- # if an external manipulation added a local_role not managed by the field, it is kept
- # add a local_role for 'Reviewers' not managed by our field
- self.assertEquals(tuple(testingobj.__ac_local_roles__['Reviewers']), testingfield.roles_to_assign)
- testingobj.manage_addLocalRoles('Reviewers', ('Reader',))
- self.assertEquals(tuple(testingobj.__ac_local_roles__['Reviewers']), testingfield.roles_to_assign + ('Reader',))
- # remove the 'Reviewers' local_roles
- datamanager.set(())
- # not managed local_roles are kepts
- self.assertEquals(tuple(testingobj.__ac_local_roles__['Reviewers']), ('Reader',))