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:
Gaudenz Steinlin 2011-10-17 15:55:33 +02:00 committed by David Glick
parent fd32e11102
commit 2233d0b535
4 changed files with 63 additions and 6 deletions

View File

@ -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
------------------

View File

@ -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

View File

@ -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__)

View File

@ -1,7 +1,7 @@
from setuptools import setup, find_packages
import os
version = '2.0.1.dev0'
version = '2.1.dev0'
setup(name='plone.dexterity',
version=version,