Skip to content

Commit

Permalink
Merge pull request #58 from plone/fix-issue-with-schma-suffix
Browse files Browse the repository at this point in the history
 Fix issue where versioning dynamic content types with blob fields broke after a schema update
  • Loading branch information
ale-rt authored May 3, 2021
2 parents 5d9d4f4 + 770ed1e commit 30bd3c6
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 1 deletion.
2 changes: 2 additions & 0 deletions news/57.bugfix
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Fix issue where versioning dynamic content types with blob fields broke after a schema update due to change in dynamic schema identifiers since plone.dexterity >= 2.10.0
[datakurre]
9 changes: 8 additions & 1 deletion plone/app/versioningbehavior/modifiers.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
from plone.behavior.registration import BehaviorRegistrationNotFound
from plone.behavior.registration import lookup_behavior_registration
from plone.dexterity.interfaces import IDexterityContent
from plone.dexterity.schema import SCHEMA_CACHE
from plone.dexterity.schema import schemaNameToPortalType
from plone.dexterity.utils import iterSchemata
from plone.dexterity.utils import resolveDottedName
from plone.namedfile.interfaces import INamedBlobFileField
Expand Down Expand Up @@ -170,6 +172,7 @@ def reattachReferencedAttributes(self, obj, attrs_dict):
obj = aq_base(obj)
for name, blob in six.iteritems(attrs_dict):
iface_name, f_name = name.rsplit('.', 1)
generated_prefix = 'plone.dexterity.schema.generated.'
# In case the field is provided via a behavior:
# Look up the behavior via dotted name.
# If the behavior's dotted name was changed, we might still have
Expand All @@ -182,7 +185,11 @@ def reattachReferencedAttributes(self, obj, attrs_dict):
iface = behavior.interface
except BehaviorRegistrationNotFound:
# Not a behavior - fetch the interface directly
iface = resolveDottedName(iface_name)
if iface_name.startswith(generated_prefix):
portal_type = schemaNameToPortalType(iface_name)
iface = SCHEMA_CACHE.get(portal_type)
else:
iface = resolveDottedName(iface_name)
field = iface.get(f_name)
if field is not None: # Field may have been removed from schema
adapted_field = field.get(iface(obj))
Expand Down
54 changes: 54 additions & 0 deletions plone/app/versioningbehavior/tests/test_modifiers.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@
from plone.app.testing import TEST_USER_ROLES
from plone.app.versioningbehavior.modifiers import CloneNamedFileBlobs
from plone.app.versioningbehavior.modifiers import SkipRelations
from plone.app.versioningbehavior.testing import PLONE_APP_VERSIONINGBEHAVIOR_FUNCTIONAL_TESTING
from plone.app.versioningbehavior.testing import PLONE_APP_VERSIONINGBEHAVIOR_INTEGRATION_TESTING
from plone.autoform.interfaces import IFormFieldProvider
from plone.dexterity.fti import DexterityFTI
from plone.dexterity.schema import portalTypeToSchemaName
from plone.dexterity.utils import createContent
from plone.dexterity.utils import createContentInContainer
from plone.namedfile import field
Expand All @@ -24,6 +26,7 @@
from zope.interface import Interface
from zope.intid.interfaces import IIntIds

import transaction
import unittest


Expand Down Expand Up @@ -352,3 +355,54 @@ class Dummy(object):

self.assertFalse(hasattr(repo_clone, 'single'))
self.assertFalse(hasattr(repo_clone, 'multiple'))


class TestModifiersFunctional(unittest.TestCase):

layer = PLONE_APP_VERSIONINGBEHAVIOR_FUNCTIONAL_TESTING

def setUp(self):
self.portal = self.layer['portal']
self.request = self.layer['request']
# we need to have the Manager role to be able to add things
# to the portal root
setRoles(self.portal, TEST_USER_ID, ['Manager'])

def testCloneNamedFileBlobsInUpdatedSchema(self):
file_fti = DexterityFTI(
'BlobFile',
model_source="""
<model xmlns="http://namespaces.plone.org/supermodel/schema">
<schema>
<field name="file"
type="plone.namedfile.field.NamedBlobFile">
<title>File</title>
<required>True</required>
</field>
</schema>
</model>
""")
self.portal.portal_types._setObject('BlobFile', file_fti)

# Sets _p_mtime on FTI used in schema suffix in p.dexterity >= 2.10.0
transaction.commit()

file1 = createContentInContainer(self.portal, 'BlobFile')
file1.file = NamedBlobFile('dummy test data', filename=u'test.txt')
modifier = CloneNamedFileBlobs('modifier', 'Modifier')
attrs_dict = modifier.getReferencedAttributes(file1)
schema_name = portalTypeToSchemaName(
'BlobFile',
suffix=str(self.portal.portal_types.BlobFile._p_mtime)
)
attr = "plone.dexterity.schema.generated." + schema_name + ".file"
self.assertTrue(attr in attrs_dict)
blob = list(attrs_dict.values())[0]
self.assertTrue(IBlob.providedBy(blob))

# Update _p_mtime on FTI
self.portal.portal_types.BlobFile._p_changed = True
transaction.commit()

# Test that modifier can attach after schema suffix has changed
modifier.reattachReferencedAttributes(file1, attrs_dict)

0 comments on commit 30bd3c6

Please sign in to comment.