Commit 459093f3 authored by Jérome Perrin's avatar Jérome Perrin

ERP5Form: implement a basic checkConsistency for ProxyField

For now this only checks that every entries in .tales are also in .values
so that .has_value works as expected. This also supports repairing the
structures with fixit argument.

We could check more, because there are other problems with proxy fields
internal structures:
 - sometimes some keys are in .values / .tales but not in .delegated_list
   this seem to happen after changing the target to a field of a different
   type, with different keys.
 - .delegated_list are not always sorted
parent 4068924a
...@@ -115,7 +115,7 @@ class TestProxify(ERP5TypeTestCase): ...@@ -115,7 +115,7 @@ class TestProxify(ERP5TypeTestCase):
self.assertEqual(field.get_value('items'), [('Male', 'Male'), ('Female', 'Female')]) self.assertEqual(field.get_value('items'), [('Male', 'Male'), ('Female', 'Female')])
field_value_cache.clear() field_value_cache.clear()
self.assertFalse(field.checkConsistency())
def test_multi_level_proxify(self): def test_multi_level_proxify(self):
self.address_view.proxifyField({'my_region':'Base_view.my_list_field'}) self.address_view.proxifyField({'my_region':'Base_view.my_list_field'})
...@@ -146,6 +146,7 @@ class TestProxify(ERP5TypeTestCase): ...@@ -146,6 +146,7 @@ class TestProxify(ERP5TypeTestCase):
template_field = self.address_view.my_region template_field = self.address_view.my_region
template_field.values['title'] = 'Region' template_field.values['title'] = 'Region'
self.assertEqual(field.get_value('title'), 'Region') self.assertEqual(field.get_value('title'), 'Region')
self.assertFalse(field.checkConsistency())
def test_force_delegate(self): def test_force_delegate(self):
self.person_view.proxifyField({'my_name':'Base_view.my_string_field'}, self.person_view.proxifyField({'my_name':'Base_view.my_string_field'},
...@@ -159,6 +160,7 @@ class TestProxify(ERP5TypeTestCase): ...@@ -159,6 +160,7 @@ class TestProxify(ERP5TypeTestCase):
self.assertEqual(field.is_delegated('size'), True) self.assertEqual(field.is_delegated('size'), True)
self.assertEqual(field.is_delegated('enabled'), True) self.assertEqual(field.is_delegated('enabled'), True)
self.assertEqual(field.is_delegated('description'), True) self.assertEqual(field.is_delegated('description'), True)
self.assertFalse(field.checkConsistency())
def test_keep_empty_value(self): def test_keep_empty_value(self):
#Non editable fields #Non editable fields
...@@ -183,6 +185,7 @@ class TestProxify(ERP5TypeTestCase): ...@@ -183,6 +185,7 @@ class TestProxify(ERP5TypeTestCase):
self.assertEqual(field.get_value('title'), 'Description') self.assertEqual(field.get_value('title'), 'Description')
self.assertEqual(field.is_delegated('editable'), True) self.assertEqual(field.is_delegated('editable'), True)
self.assertEqual(field.get_value('editable'), 0) self.assertEqual(field.get_value('editable'), 0)
self.assertFalse(field.checkConsistency())
def test_unproxify(self): def test_unproxify(self):
#Proxify First #Proxify First
...@@ -207,3 +210,4 @@ class TestProxify(ERP5TypeTestCase): ...@@ -207,3 +210,4 @@ class TestProxify(ERP5TypeTestCase):
self.assertEqual(field.meta_type, 'RelationStringField') self.assertEqual(field.meta_type, 'RelationStringField')
self.assertEqual(field.get_value('title'), 'Organisation') self.assertEqual(field.get_value('title'), 'Organisation')
self.assertEqual(field.get_value('proxy_listbox_ids'), [('OrganisationModule_viewOrganisationList/listbox', 'Organisation')]) self.assertEqual(field.get_value('proxy_listbox_ids'), [('OrganisationModule_viewOrganisationList/listbox', 'Organisation')])
self.assertFalse(field.checkConsistency())
...@@ -1387,6 +1387,12 @@ class ERP5Form(Base, ZMIForm, ZopePageTemplate): ...@@ -1387,6 +1387,12 @@ class ERP5Form(Base, ZMIForm, ZopePageTemplate):
addMessage( addMessage(
'erp5-Guideline.Use.Correct.Names.For.Simulation.And.Validation.Titles', 'erp5-Guideline.Use.Correct.Names.For.Simulation.And.Validation.Titles',
'Workflow state fields should be named my_translated_${state_variable}_title') 'Workflow state fields should be named my_translated_${state_variable}_title')
# check fields, if they implement _checkConsistency
for field in self.objectValues():
if hasattr(aq_base(field), 'checkConsistency'):
message_list.extend(field.checkConsistency(fixit=fixit))
return message_list return message_list
......
...@@ -35,6 +35,7 @@ from Products.Formulator.Errors import ValidationError ...@@ -35,6 +35,7 @@ from Products.Formulator.Errors import ValidationError
from Products.Formulator import MethodField from Products.Formulator import MethodField
from Products.ERP5Type.Utils import convertToUpperCase from Products.ERP5Type.Utils import convertToUpperCase
from Products.ERP5Type.TransactionalVariable import getTransactionalVariable from Products.ERP5Type.TransactionalVariable import getTransactionalVariable
from Products.ERP5Type.ObjectMessage import ObjectMessage
from Products.PageTemplates.PageTemplateFile import PageTemplateFile from Products.PageTemplates.PageTemplateFile import PageTemplateFile
...@@ -790,6 +791,30 @@ class ProxyField(ZMIField): ...@@ -790,6 +791,30 @@ class ProxyField(ZMIField):
return cache.__of__(parent) return cache.__of__(parent)
raise KeyError raise KeyError
security.declareProtected('Change Formulator Fields', 'checkConsistency')
def checkConsistency(self, fixit=False):
"""Check the proxy field internal data structures are consistent
"""
object_relative_url = '/'.join(self.getPhysicalPath())[len(self.getPortalObject().getPath()):]
difference = set(self.tales).difference(self.values)
if difference:
if fixit:
for key in difference:
if key in self.delegated_list:
self.values[key] = self.get_recursive_orig_value(key, include=0)
else:
self.tales.pop(key)
# XXX since we are modifying the field, let's take this opportunity
# to sort delegated_list if it was not sorted.
self.delegated_list = sorted(self.delegated_list)
self._p_changed = True
return [
ObjectMessage(
object_relative_url=object_relative_url,
message="Internal proxy field data structures are inconsistent. "
"Differences: {}".format(difference))]
return []
# #
# get_value exception dict # get_value exception dict
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment