Use IConstrainTypes adapters for dexterity content
Overrride allowedContentTypes and invokeFactory from PortalFolder to mimic the behavior of Archetypes based folders. This allows the registration of IConstrainTypes adapters to actually have the expected effect.
This commit is contained in:
parent
fd32e11102
commit
2233d0b535
|
@ -1,8 +1,14 @@
|
|||
Changelog
|
||||
=========
|
||||
|
||||
2.0.1 (unreleased)
|
||||
------------------
|
||||
2.1 (unreleased)
|
||||
----------------
|
||||
|
||||
* Overrride allowedContentTypes and invokeFactory from PortalFolder
|
||||
to mimic the behavior of Archetypes based folders. This allows the
|
||||
registration of IConstrainTypes adapters to actually have the
|
||||
expected effect.
|
||||
[gaudenzius]
|
||||
|
||||
- The default attribute accessor now also looks through subtypes
|
||||
(behaviors) to find a field default.
|
||||
|
@ -34,7 +40,6 @@ Changelog
|
|||
* Update package dependencies and imports as appropriate for Zope 2.12 & 2.13.
|
||||
[davisagli]
|
||||
|
||||
|
||||
1.1.2 - 2012-02-20
|
||||
------------------
|
||||
|
||||
|
|
|
@ -31,6 +31,7 @@ import Products.CMFCore.permissions
|
|||
from Products.CMFCore.PortalContent import PortalContent
|
||||
from Products.CMFCore.PortalFolder import PortalFolderBase
|
||||
from Products.CMFCore.CMFCatalogAware import CMFCatalogAware
|
||||
from Products.CMFPlone.interfaces import IConstrainTypes
|
||||
|
||||
from Products.CMFDefault.DublinCore import DefaultDublinCoreImpl
|
||||
from Products.CMFDefault.utils import tuplize
|
||||
|
@ -347,6 +348,30 @@ class Container(DAVCollectionMixin, BrowserDefaultMixin, CMFCatalogAware, CMFOrd
|
|||
"Do not have permissions to remove this object")
|
||||
return super(Container, self).manage_delObjects(ids, REQUEST=REQUEST)
|
||||
|
||||
# override PortalFolder's allowedContentTypes to respect IConstrainTypes
|
||||
# adapters
|
||||
def allowedContentTypes(self, context=None):
|
||||
if not context:
|
||||
context = self
|
||||
|
||||
constrains = IConstrainTypes(context, None)
|
||||
if not constrains:
|
||||
return super(Container, self).allowedContentTypes()
|
||||
|
||||
return constrains.allowedContentTypes()
|
||||
|
||||
# override PortalFolder's invokeFactory to respect IConstrainTypes
|
||||
# adapters
|
||||
def invokeFactory(self, type_name, id, RESPONSE=None, *args, **kw):
|
||||
"""Invokes the portal_types tool
|
||||
"""
|
||||
constrains = IConstrainTypes(self, None)
|
||||
|
||||
if constrains and not type_name in [fti.getId() for fti in constrains.allowedContentTypes()]:
|
||||
raise ValueError('Subobject type disallowed by IConstrainTypes adapter: %s' % type_name)
|
||||
|
||||
return super(Container, self).invokeFactory(type_name, id, RESPONSE, *args, **kw)
|
||||
|
||||
|
||||
def reindexOnModify(content, event):
|
||||
"""When an object is modified, re-index it in the catalog
|
||||
|
|
|
@ -3,11 +3,13 @@ import unittest
|
|||
from plone.mocktestcase import MockTestCase
|
||||
|
||||
from zope.interface import Interface, alsoProvides
|
||||
from zope.component import provideAdapter
|
||||
from zope.component import provideAdapter, getUtility
|
||||
|
||||
import zope.schema
|
||||
|
||||
from plone.dexterity.interfaces import IDexterityFTI
|
||||
from Products.CMFPlone.interfaces import IConstrainTypes
|
||||
|
||||
from plone.dexterity.interfaces import IDexterityFTI, IDexterityContainer
|
||||
|
||||
from plone.dexterity.fti import DexterityFTI
|
||||
from plone.dexterity.schema import SCHEMA_CACHE
|
||||
|
@ -678,6 +680,31 @@ class TestContent(MockTestCase):
|
|||
container.manage_delObjects(['test'])
|
||||
self.assertFalse('test' in container)
|
||||
|
||||
def test_iconstraintypes_adapter(self):
|
||||
|
||||
class DummyConstrainTypes(object):
|
||||
|
||||
def __init__(self, context):
|
||||
self.context = context
|
||||
|
||||
def allowedContentTypes(self):
|
||||
fti = getUtility(IDexterityFTI, name=u"testtype")
|
||||
return [fti]
|
||||
|
||||
self.mock_adapter(DummyConstrainTypes, IConstrainTypes, (IDexterityContainer, ))
|
||||
|
||||
# FTI mock
|
||||
fti_mock = self.mocker.proxy(DexterityFTI(u"testtype"))
|
||||
self.expect(fti_mock.getId()).result(u"testtype")
|
||||
self.mock_utility(fti_mock, IDexterityFTI, name=u"testtype")
|
||||
|
||||
self.replay()
|
||||
|
||||
folder = Container(id="testfolder")
|
||||
|
||||
self.assertEquals(folder.allowedContentTypes(), [fti_mock])
|
||||
self.assertRaises(ValueError, folder.invokeFactory, u"disallowed_type", id="test")
|
||||
|
||||
|
||||
def test_suite():
|
||||
return unittest.defaultTestLoader.loadTestsFromName(__name__)
|
||||
|
|
Reference in New Issue