Commit e308b004 authored by Tomáš Peterka's avatar Tomáš Peterka

[erp5_core] Carefull refactoring of Base_edit

parent f7efa99f
...@@ -91,7 +91,10 @@ def editListBox(listbox_field, listbox): ...@@ -91,7 +91,10 @@ def editListBox(listbox_field, listbox):
def editMatrixBox(matrixbox_field, matrixbox): def editMatrixBox(matrixbox_field, matrixbox):
""" Function called to edit a Matrix box """Go through every field in matrix and call edit on it.
Most of the code is just a copy&paste from ERP5Form/MatrixBox:render and
should be in (non-yet-existing) MatrixBoxEditor instead of here (XXX TODO).
""" """
if matrixbox is None: if matrixbox is None:
return return
...@@ -170,7 +173,7 @@ def editMatrixBox(matrixbox_field, matrixbox): ...@@ -170,7 +173,7 @@ def editMatrixBox(matrixbox_field, matrixbox):
matrix_context.setCellRange(base_id=cell_base_id, *matrixbox_cell_range) matrix_context.setCellRange(base_id=cell_base_id, *matrixbox_cell_range)
for cell_index_tuple, cell_value_dict in matrixbox.items(): for cell_index_tuple, cell_value_dict in matrixbox.items():
# Only update cells which still exist # after constructing the cell-range we can edit all existing cells
if not matrix_context.hasInRange(*cell_index_tuple, **kd): if not matrix_context.hasInRange(*cell_index_tuple, **kd):
return "Cell %s does not exist" % str(cell_index_tuple) return "Cell %s does not exist" % str(cell_index_tuple)
...@@ -204,7 +207,7 @@ MARKER = [] # placeholder for an empty value ...@@ -204,7 +207,7 @@ MARKER = [] # placeholder for an empty value
message = Base_translateString("Data updated.") message = Base_translateString("Data updated.")
try: try:
# extract all listbox's object form fields from the request and `edit` the object # Extract all form fields from the request and call `edit` on them
for field in form.get_fields(): for field in form.get_fields():
# Dispatch field either to `edit_kwargs` (in case of simple fields) or to `encapsulated_editor_list` in case of editors # Dispatch field either to `edit_kwargs` (in case of simple fields) or to `encapsulated_editor_list` in case of editors
field_name = field.id if not field.has_value('alternate_name') else (field.get_value('alternate_name') or field.id) field_name = field.id if not field.has_value('alternate_name') else (field.get_value('alternate_name') or field.id)
...@@ -217,6 +220,7 @@ try: ...@@ -217,6 +220,7 @@ try:
edit_kwargs[field_name[len(field_prefix):]] = field_value if field_value != '' else None edit_kwargs[field_name[len(field_prefix):]] = field_value if field_value != '' else None
## XXX We need to find a way not to use meta_type. ## XXX We need to find a way not to use meta_type.
# Kato: can be done simply by implementing 'Editors' for fields which are here
field_meta_type = field.meta_type field_meta_type = field.meta_type
if field_meta_type == 'ProxyField': if field_meta_type == 'ProxyField':
field_meta_type = field.getRecursiveTemplateField().meta_type field_meta_type = field.getRecursiveTemplateField().meta_type
...@@ -235,6 +239,7 @@ try: ...@@ -235,6 +239,7 @@ try:
context.edit(REQUEST=request, edit_order=edit_order, **edit_kwargs) context.edit(REQUEST=request, edit_order=edit_order, **edit_kwargs)
for encapsulated_editor in encapsulated_editor_list: for encapsulated_editor in encapsulated_editor_list:
encapsulated_editor.edit(context) encapsulated_editor.edit(context)
except ActivityPendingError as e: except ActivityPendingError as e:
message = Base_translateString(str(e)) message = Base_translateString(str(e))
......
""" """Handle form - REQUEST interaction.
This script validates a form to the current REQUEST,
processes the REQUEST to extract form data and editors, - Validate a form to the current REQUEST
then updates the current context with the form data - Extract form data and editors from REQUEST,
by calling edit on it or by invoking editors. - Update current context with form data by calling edit or invoking editors
:param silent: int (0|1) means that the edit action is not invoked by a form
submit but rather by an internal code thus the return value
contains as much usefull info as possible
TODO: split the generic form validation logic TODO: split the generic form validation logic
from the context update logic from the context update logic
...@@ -37,7 +41,7 @@ edit_order = form.edit_order ...@@ -37,7 +41,7 @@ edit_order = form.edit_order
try: try:
# Validate # Validate
form.validate_all_to_request(request, key_prefix=key_prefix) form.validate_all_to_request(request, key_prefix=key_prefix)
except FormValidationError, validation_errors: except FormValidationError as validation_errors:
# Pack errors into the request # Pack errors into the request
field_errors = form.ErrorFields(validation_errors) field_errors = form.ErrorFields(validation_errors)
request.set('field_errors', field_errors) request.set('field_errors', field_errors)
...@@ -48,200 +52,194 @@ except FormValidationError, validation_errors: ...@@ -48,200 +52,194 @@ except FormValidationError, validation_errors:
value = request.get(field_id) value = request.get(field_id)
if callable(value): if callable(value):
value(request) value(request)
if silent_mode: return form(request), 'form' if silent_mode:
return form(request), 'form'
return form(request) return form(request)
def editListBox(listbox_field, listbox): def editListBox(listbox_field, listbox):
""" Function called to edit a listbox """Go through every item in the listbox and call its `edit` with modified values."""
""" if listbox is None:
if listbox is not None: return
gv = {}
if listbox_field.has_value('global_attributes'): # extract hidden (global) attributes from request to be used in listbox's update
hidden_attributes = map(lambda x:x[0], listbox_field.get_value('global_attributes')) global_attr = {hidden_key: getattr(request, hidden_key, None)
for k in hidden_attributes: for hidden_key, _ in listbox_field.get_value('global_attributes')} \
gv[k] = getattr(request, k, None) if listbox_field.has_value('global_attributes') \
for url, v in listbox.items(): else {}
v.update(gv)
# Form: '' -> ERP5: None for item_url, item_value in listbox.items():
encapsulated_editor_list = [] item_value.update(global_attr)
cleaned_v = {} # Form: '' -> ERP5: None
for key, value in v.items(): editor_list = []
if hasattr(value, 'edit'): value_dict = {}
encapsulated_editor_list.append(value) for key, value in item_value.items():
else: # for every value decide whether it is an attribute or an editor
if value == '': if hasattr(value, 'edit'):
value = None editor_list.append(value)
cleaned_v[key] = value else:
value_dict[key] = value if value != '' else None
if cleaned_v:
if listbox_edit is None: if value_dict:
obj = context.restrictedTraverse(url) if listbox_edit is None:
obj.edit(edit_order=edit_order, **cleaned_v) obj = context.restrictedTraverse(item_url)
else: obj.edit(edit_order=edit_order, **value_dict)
listbox_edit(url, edit_order, cleaned_v) for editor in editor_list:
editor.edit(obj)
for encapsulated_editor in encapsulated_editor_list: else:
encapsulated_editor.edit(obj) listbox_edit(item_url, edit_order, value_dict)
def editMatrixBox(matrixbox_field, matrixbox): def editMatrixBox(matrixbox_field, matrixbox):
""" Function called to edit a Matrix box """Go through every field in matrix and call edit on it.
Most of the code is just a copy&paste from ERP5Form/MatrixBox:render and
should be in (non-yet-existing) MatrixBoxEditor instead of here (XXX TODO).
""" """
if matrixbox is not None: if matrixbox is None:
cell_base_id = matrixbox_field.get_value('cell_base_id') return
portal_type = matrixbox_field.get_value('cell_portal_type')
getter_method = matrixbox_field.get_value('getter_method') cell_base_id = matrixbox_field.get_value('cell_base_id')
if getter_method not in (None, ''): portal_type = matrixbox_field.get_value('cell_portal_type')
matrix_context = getattr(context,getter_method)() getter_method = matrixbox_field.get_value('getter_method')
if getter_method not in (None, ''):
matrix_context = getattr(context,getter_method)()
else:
matrix_context = context
if matrix_context is None:
return
kd = {}
kd['portal_type'] = portal_type
kd['base_id'] = cell_base_id
gv = {}
if matrixbox_field.has_value('global_attributes'):
hidden_attributes = [x[0] for x in matrixbox_field.get_value('global_attributes')]
for k in hidden_attributes:
gv[k] = getattr(request, k, None)
if matrixbox_field.get_value('update_cell_range'):
as_cell_range_script_id = matrixbox_field.get_value(
'as_cell_range_script_id')
lines = []
columns = []
tabs = []
extra_dimension_list_list = []
if as_cell_range_script_id:
cell_range = getattr(matrix_context,
as_cell_range_script_id)(matrixbox=True, base_id=cell_base_id)
if len(cell_range) == 1:
lines, = cell_range
elif len(cell_range) == 2:
lines, columns = cell_range
elif len(cell_range) == 3:
lines, columns, tabs = cell_range
elif len(cell_range) > 3:
lines = cell_range[0]
columns = cell_range[1]
tabs = cell_range[2]
extra_dimension_list_list = cell_range[3:]
else: else:
matrix_context = context lines = matrixbox_field.get_value('lines')
if matrix_context is not None: columns = matrixbox_field.get_value('columns')
kd = {} tabs = matrixbox_field.get_value('tabs')
kd['portal_type'] = portal_type
kd['base_id'] = cell_base_id column_ids = map(lambda x: x[0], columns)
gv = {} line_ids = map(lambda x: x[0], lines)
if matrixbox_field.has_value('global_attributes'): tab_ids = map(lambda x: x[0], tabs)
hidden_attributes = [x[0] for x in matrixbox_field.get_value('global_attributes')] extra_dimension_category_list_list = [[category for category, label in dimension_list] for dimension_list in extra_dimension_list_list]
for k in hidden_attributes:
gv[k] = getattr(request, k, None) # There are 3 cases
if matrixbox_field.get_value('update_cell_range'): # Case 1: we do 1 dimensional matrix
as_cell_range_script_id = matrixbox_field.get_value( # Case 2: we do 2 dimensional matrix
'as_cell_range_script_id') # Case 3: we do 2 dimensional matrix + tabs
lines = [] # Case 4: we do 2 dimensional matrix + tabs + extra
columns = [] cell_range = matrix_context.getCellRange(base_id = cell_base_id)
tabs = [] if (len(column_ids) == 0) or (column_ids[0] is None):
extra_dimension_list_list = [] matrixbox_cell_range = [line_ids]
if as_cell_range_script_id: if cell_range != matrixbox_cell_range:
cell_range = getattr(matrix_context, matrix_context.setCellRange(line_ids, base_id=cell_base_id)
as_cell_range_script_id)(matrixbox=True, base_id=cell_base_id)
if len(cell_range) == 1: elif (len(tab_ids) == 0) or (tab_ids[0] is None):
lines, = cell_range matrixbox_cell_range = [line_ids, column_ids]
elif len(cell_range) == 2: if cell_range != matrixbox_cell_range:
lines, columns = cell_range matrix_context.setCellRange(line_ids, column_ids, base_id=cell_base_id)
elif len(cell_range) == 3:
lines, columns, tabs = cell_range else:
elif len(cell_range) > 3: matrixbox_cell_range = [line_ids, column_ids, tab_ids]
lines = cell_range[0] if extra_dimension_category_list_list:
columns = cell_range[1] matrixbox_cell_range = matrixbox_cell_range + extra_dimension_category_list_list
tabs = cell_range[2] if cell_range != matrixbox_cell_range:
extra_dimension_list_list = cell_range[3:] matrix_context.setCellRange(base_id=cell_base_id, *matrixbox_cell_range)
else:
lines = matrixbox_field.get_value('lines') for cell_index_tuple, cell_value_dict in matrixbox.items():
columns = matrixbox_field.get_value('columns') # after constructing the cell-range we can edit all existing cells
tabs = matrixbox_field.get_value('tabs') if not matrix_context.hasInRange(*cell_index_tuple, **kd):
return "Cell %s does not exist" % str(cell_index_tuple)
column_ids = map(lambda x: x[0], columns)
line_ids = map(lambda x: x[0], lines) cell = matrix_context.newCell(*cell_index_tuple, **kd)
tab_ids = map(lambda x: x[0], tabs) if cell is None:
extra_dimension_category_list_list = [[category for category, label in dimension_list] for dimension_list in extra_dimension_list_list] return "Could not create cell %s" % str(cell_index_tuple)
# There are 3 cases cell.edit(edit_order=edit_order, **gv) # First update globals which include the def. of property_list
# Case 1: we do 1 dimensional matrix if cell_value_dict.has_key('variated_property'):
# Case 2: we do 2 dimensional matrix # For Variated Properties
# Case 3: we do 2 dimensional matrix + tabs value = cell_value_dict['variated_property']
# Case 4: we do 2 dimensional matrix + tabs + extra del cell_value_dict['variated_property']
cell_range = matrix_context.getCellRange(base_id = cell_base_id) if gv.has_key('mapped_value_property_list'):
if (len(column_ids) == 0) or (column_ids[0] is None): # Change the property which is defined by the
matrixbox_cell_range = [line_ids] # first element of mapped_value_property_list
if cell_range != matrixbox_cell_range: # XXX Kato: What? Why?
matrix_context.setCellRange(line_ids, base_id=cell_base_id) # XXX May require some changes with Sets
key = gv['mapped_value_property_list'][0]
elif (len(tab_ids) == 0) or (tab_ids[0] is None): cell_value_dict[key] = value
matrixbox_cell_range = [line_ids, column_ids] # Form: '' -> ERP5: None
if cell_range != matrixbox_cell_range: cleaned_v = cell_value_dict.copy()
matrix_context.setCellRange(line_ids, column_ids, base_id=cell_base_id) for key, value in cleaned_v.items():
if value == '':
else: cleaned_v[key] = None
matrixbox_cell_range = [line_ids, column_ids, tab_ids] cell.edit(edit_order=edit_order, **cleaned_v) # and update the cell specific values
if extra_dimension_category_list_list:
matrixbox_cell_range = matrixbox_cell_range + extra_dimension_category_list_list
if cell_range != matrixbox_cell_range: edit_kwargs = {} # keyword arguments for `edit` function on context
matrix_context.setCellRange(base_id=cell_base_id, *matrixbox_cell_range) encapsulated_editor_list = [] # editors placed inside REQUEST object
MARKER = [] # placeholder for an empty value
for k,v in matrixbox.items():
# Only update cells which still exist
if matrix_context.hasInRange(*k, **kd):
c = matrix_context.newCell(*k, **kd)
if c is not None:
c.edit(edit_order=edit_order, **gv) # First update globals which include the def. of property_list
if v.has_key('variated_property'):
# For Variated Properties
value = v['variated_property']
del v['variated_property']
if gv.has_key('mapped_value_property_list'):
# Change the property which is defined by the
# first element of mapped_value_property_list
# XXX May require some changes with Sets
key = gv['mapped_value_property_list'][0]
v[key] = value
# Form: '' -> ERP5: None
cleaned_v = v.copy()
for key, value in cleaned_v.items():
if value == '':
cleaned_v[key] = None
c.edit(edit_order=edit_order, **cleaned_v) # and update the cell specific values
else:
return "Could not create cell %s" % str(k)
else:
return "Cell %s does not exist" % str(k)
field_prefix_len = len(field_prefix)
def parseField(f):
"""
Parse given form field, to put them in
kw or in encapsulated_editor_list
"""
k = f.id
if f.has_value('alternate_name'):
k = f.get_value('alternate_name') or f.id
v = getattr(request, k, MARKER)
if hasattr(v, 'edit'):
# This is an encapsulated editor
# call it
encapsulated_editor_list.append(v)
elif v is not MARKER:
if k.startswith(field_prefix):
# We only take into account
# the object attributes
k = k[field_prefix_len:]
# Form: '' -> ERP5: None
if v == '':
v = None
kw[k] = v
# Some initilizations
kw = {}
encapsulated_editor_list = []
MARKER = []
message = Base_translateString("Data updated.") message = Base_translateString("Data updated.")
try: try:
# We process all the field in form and # Extract all form fields from the request and call `edit` on them
# we check if they are in the request,
# then we edit them
for field in form.get_fields(): for field in form.get_fields():
parseField(field) # Dispatch field either to `edit_kwargs` (in case of simple fields) or to `encapsulated_editor_list` in case of editors
field_name = field.id if not field.has_value('alternate_name') else (field.get_value('alternate_name') or field.id)
field_value = getattr(request, field_name, MARKER)
if hasattr(field_value, 'edit'):
# field is an encapsulated editor; call it later
encapsulated_editor_list.append(field_value)
elif field_value is not MARKER and field_name.startswith(field_prefix):
# object own attribute (fix value Form: '' -> ERP5: None)
edit_kwargs[field_name[len(field_prefix):]] = field_value if field_value != '' else None
## XXX We need to find a way not to use meta_type. ## XXX We need to find a way not to use meta_type.
field_meta_type = field.meta_type field_meta_type = field.meta_type
if field_meta_type == 'ProxyField': if field_meta_type == 'ProxyField':
field_meta_type = field.getRecursiveTemplateField().meta_type field_meta_type = field.getRecursiveTemplateField().meta_type
# Kato: following fields should implement 'Editors' so we can delete those lines
if(field_meta_type == 'ListBox'): if(field_meta_type == 'ListBox'):
editListBox(field, request.get(field.id)) editListBox(field, request.get(field.id))
elif(field_meta_type == 'MatrixBox'): if(field_meta_type == 'MatrixBox'):
editMatrixBox(field, request.get(field.id)) editMatrixBox(field, request.get(field.id))
# Return parsed values # Return parsed values
if silent_mode: return (kw, encapsulated_editor_list), 'edit' if silent_mode:
return (edit_kwargs, encapsulated_editor_list), 'edit'
# Maybe we should build a list of objects we need # Maybe we should build a list of objects we need
# Update basic attributes # Update basic attributes
context.edit(REQUEST=request, edit_order=edit_order, **kw) context.edit(REQUEST=request, edit_order=edit_order, **edit_kwargs)
for encapsulated_editor in encapsulated_editor_list: for encapsulated_editor in encapsulated_editor_list:
encapsulated_editor.edit(context) encapsulated_editor.edit(context)
except ActivityPendingError,e:
message = Base_translateString("%s" % e) except ActivityPendingError as e:
message = Base_translateString(str(e))
if message_only: if message_only:
return message return message
...@@ -283,5 +281,6 @@ else: ...@@ -283,5 +281,6 @@ else:
result = request['RESPONSE'].redirect(redirect_url) result = request['RESPONSE'].redirect(redirect_url)
if silent_mode: return result, 'redirect' if silent_mode:
return result, 'redirect'
return result return result
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