Fix Form.proxifyField creating inconsistent proxy fields
When Form.proxifyField
is used to make a proxy field from a field which has only a TALES and no value, it creates a proxy field with inconsistent internal data structures where has_value
method does not work as expected. As a consequence, proxy fields to list fields are often broken in the ods/odt rendering.
Here is a scenario to reproduce the problem:
- add
Base_viewDummyFieldLibrary
ERP5 Form - add a
LinesField
, with idyour_test_base_field
. Changesize
to 1 (not really required but I did this in screenshots here) - add another
LinesField
, with idyour_test_field
and in this field: - So far, when this is rendered as ODS, everything is fine: this is also what we see in html style view:
- use the proxify action, to make
your_test_field
be a proxy field toyour_test_base_field
- result of proxify action looks good, both for values: and for TALES:
- but after this rendering the form with ODS becomes broken: even though it looks fine with html views.
erp5_ods_style
knows how to render list fields and it uses the "display" (two) and not the "value" (2), this is done here with a check depending on field.has_value("items")
.
has_value
is implemented like this for proxy fields:
def has_value(self, id):
"""
Return true if the field defines such a value.
"""
result = None
if (id in self.widget.property_names) or \
(not self.is_delegated(id)):
result = ZMIField.has_value(self, id)
else:
proxy_field = self.getTemplateField()
if proxy_field is not None:
result = proxy_field.has_value(id)
return result
and like this for traditional fields:
def has_value(self, id):
"""Return true if the field defines such a value.
"""
if self.values.has_key(id) or self.form.has_field(id):
return 1
else:
return 0
when the value is defined on the proxy field and not delegated to template field, the condition is self.values.has_key(id)
.
But Form.proxifyField
when transforming a traditional field in a proxy field does not keep the id
in self.values
if it's only needed in self.tales
. This is the root cause of this problem, if we inspect the field, it is something like this:
(Pdb) self
<ProxyField at /erp5/portal_skins/custom/Base_viewDummyFieldLibrary/your_test_field>
(Pdb) pp self.tales
{'field_id': '',
'form_id': '',
'items': <Products.Formulator.TALESField.TALESMethod object at 0x7ffa705c7450 oid 0x572626 in <Connection at 7ffa42c1a610>>}
(Pdb) pp self.values
{'default': '2',
'field_id': 'your_test_base_field',
'form_id': 'Base_viewDummyFieldLibrary',
'title': 'Test Field'}
(Pdb) self.has_value('items')
0
(Pdb)
If we edit the proxy field, it will repair itself, because the proxy field edit method maintain self.tales
and self.values
consistent, but this is not the case withForm.proxifyField
, which mutate directly .tales
and .values
and can make them have different keys - which is not supposed to happen.
The problem is that most of the proxy fields we have have been generated by Form.proxifyField
, so for most of our fields the XML data of business template has this inconsistency. We could have took the easy way and make change ProxyField.has_value
to understand this case, but it's probably better to fix the data.
erp5_hal_json
also uses field.has_value
in some places, so it's better to fix at field level and not to address this in erp5_ods_style
and erp5_odt_style
.
These changes:
- add a little more test coverage for
ProxyField.has_value
( at first I thought the problem was only inhas_value
) - Fix
Form.proxifyField
- add a
ProxyField.checkConsistency
to check that.values
and.tales
are in sync - or more exactly that all entries from.tales
are also in.values
, because this is what cause the problem withhas_value
. - re-export all proxy fields after cleaning up their
.values
and.tales
, usingcheckConsistency(fixit=True)
on all proxy fields.