Commit e8222a8e authored by Julien Muchembled's avatar Julien Muchembled Committed by Eteri

ERP5Form: FormBox improvements

A Form is rendered by assuming the REQUEST is clean and first set 'here' as
the context. Then there may be listboxes with rely on 'here' and set 'cell'
temporarily. At last, for easier configuration of listbox fields, 'cell' has
precedence over 'here' when rendering (in particular since
commit 4fa84233).

Based on this, the only sane solution is to
- clean up the REQUEST (remove 'here' and 'cell')
- render the FormBox in the new context (which sets 'here'): inside a ListBox,
  the context is the cell
- restore 'here' and 'cell' as they were

Which allows FormBox/ListBox inside FormBox/ListBox, recursively
(but obviously no ListBox inside ListBox).

The previous code didn't work in the following case:
- a Order Line and Packing List Line having an identical tab
- the left pane for Order Line information
- the other for Packing List Line information
  (-> empty when there's no related PL)
- a listbox (with subobjects of the PL line)
Which is implemented as follows:
- a Form for the left pane
- a Form for the Packing List Line, with a FormBox
  (to display Order information) and a ListBox
- the Form for the Order Line only has a FormBox, that uses 1 of the 2 other
  Forms depending on the presence of a PL (if there's one, it's rendered in the
  context of the PL)
-> FormBox(FormBox, ListBox)

As you can see, FormBox is used here to factorize forms. Without this patch:
- the outter FormBox crashed on `del REQUEST.other['cell']`
- the inner FormBox was rendered with a wrong 'cell'

Another change is to pass the field & REQUEST to the context method.
parent 72d53981
...@@ -43,8 +43,6 @@ from Products.Formulator.Errors import FormValidationError, ValidationError ...@@ -43,8 +43,6 @@ from Products.Formulator.Errors import FormValidationError, ValidationError
import string import string
from zLOG import LOG, WARNING, DEBUG, PROBLEM
class FormBoxWidget(Widget.Widget): class FormBoxWidget(Widget.Widget):
""" """
A widget that display a form within a form. A widget that display a form within a form.
...@@ -93,50 +91,33 @@ class FormBoxWidget(Widget.Widget): ...@@ -93,50 +91,33 @@ class FormBoxWidget(Widget.Widget):
default="", default="",
required=0) required=0)
def render(self, field, key, value, REQUEST, render_prefix=None):
"""
Render a form in a field
"""
return self._render(field, key, value, REQUEST, render_prefix=render_prefix)
def render_view(self, field, value, REQUEST, render_prefix=None): def render_view(self, field, value, REQUEST, render_prefix=None):
""" """
Render a view form in a field Render a view form in a field
""" """
return self._render(field, None, value, REQUEST, render_prefix=render_prefix) return self.render(field, None, value, REQUEST, render_prefix)
def _render(self, field, key, value, REQUEST, render_prefix=None): def render(self, field, key, value, REQUEST, render_prefix=None):
result = '' """
Render a form in a field
"""
target_id = field.get_value('formbox_target_id') target_id = field.get_value('formbox_target_id')
if target_id not in (None, ''): if target_id:
here = REQUEST['here'] other = REQUEST.other
here = other['here']
context_method_id = field.get_value('context_method_id') context_method_id = field.get_value('context_method_id')
if context_method_id:
REQUEST['original_context'] = original_here = here
REQUEST['here'] = here = getattr(here, context_method_id)()
# If 'cell' is not defined, we define 'cell' just same as 'here', so
# that we can use the same formbox for both ListBox and non-ListBox
# using 'cell' parameter.
if not REQUEST.has_key('cell'):
set_cell = True
REQUEST.set('cell', here)
else:
set_cell = False
try: try:
form = getattr(here, target_id) cell = other.pop('cell', None)
except AttributeError: context = cell or here
LOG('FormBox', WARNING,
'Could not get a form from formbox %s in %s' % \
(field.id, field.aq_parent.id))
else:
result = form(REQUEST=REQUEST, key_prefix=key)
finally:
if context_method_id: if context_method_id:
REQUEST['here'] = original_here context = getattr(context, context_method_id)(
del REQUEST.other['original_context'] field=field, REQUEST=REQUEST)
if set_cell: return getattr(context, target_id)(REQUEST=REQUEST, key_prefix=key)
del REQUEST.other['cell'] finally:
return result other['here'] = here
if cell:
other['cell'] = cell
return ''
class FormBoxEditor: class FormBoxEditor:
""" """
...@@ -186,10 +167,12 @@ class FormBoxValidator(Validator.Validator): ...@@ -186,10 +167,12 @@ class FormBoxValidator(Validator.Validator):
def validate(self, field, key, REQUEST): def validate(self, field, key, REQUEST):
# XXX hardcoded acquisition # XXX hardcoded acquisition
# TODO: Handle 'cell' for validation inside listboxes,
# like it is done for rendering.
here = field.aq_parent.aq_parent here = field.aq_parent.aq_parent
context_method_id = field.get_value('context_method_id') context_method_id = field.get_value('context_method_id')
if context_method_id: if context_method_id:
here = getattr(here, context_method_id)() here = getattr(here, context_method_id)(field=field, REQUEST=REQUEST)
formbox_target_id = field.get_value('formbox_target_id') formbox_target_id = field.get_value('formbox_target_id')
# Get current error fields # Get current error fields
......
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