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

[erp5_core] Carefull refactoring of Base_edit

parent 5f5aed84
...@@ -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,45 +52,51 @@ except FormValidationError, validation_errors: ...@@ -48,45 +52,51 @@ 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)
for item_url, item_value in listbox.items():
item_value.update(global_attr)
# Form: '' -> ERP5: None # Form: '' -> ERP5: None
encapsulated_editor_list = [] editor_list = []
cleaned_v = {} value_dict = {}
for key, value in v.items(): for key, value in item_value.items():
# for every value decide whether it is an attribute or an editor
if hasattr(value, 'edit'): if hasattr(value, 'edit'):
encapsulated_editor_list.append(value) editor_list.append(value)
else: else:
if value == '': value_dict[key] = value if value != '' else None
value = None
cleaned_v[key] = value
if cleaned_v: if value_dict:
if listbox_edit is None: if listbox_edit is None:
obj = context.restrictedTraverse(url) obj = context.restrictedTraverse(item_url)
obj.edit(edit_order=edit_order, **cleaned_v) obj.edit(edit_order=edit_order, **value_dict)
for editor in editor_list:
editor.edit(obj)
else: else:
listbox_edit(url, edit_order, cleaned_v) listbox_edit(item_url, edit_order, value_dict)
for encapsulated_editor in encapsulated_editor_list:
encapsulated_editor.edit(obj)
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:
return
cell_base_id = matrixbox_field.get_value('cell_base_id') cell_base_id = matrixbox_field.get_value('cell_base_id')
portal_type = matrixbox_field.get_value('cell_portal_type') portal_type = matrixbox_field.get_value('cell_portal_type')
getter_method = matrixbox_field.get_value('getter_method') getter_method = matrixbox_field.get_value('getter_method')
...@@ -94,7 +104,10 @@ def editMatrixBox(matrixbox_field, matrixbox): ...@@ -94,7 +104,10 @@ def editMatrixBox(matrixbox_field, matrixbox):
matrix_context = getattr(context,getter_method)() matrix_context = getattr(context,getter_method)()
else: else:
matrix_context = context matrix_context = context
if matrix_context is not None:
if matrix_context is None:
return
kd = {} kd = {}
kd['portal_type'] = portal_type kd['portal_type'] = portal_type
kd['base_id'] = cell_base_id kd['base_id'] = cell_base_id
...@@ -157,91 +170,76 @@ def editMatrixBox(matrixbox_field, matrixbox): ...@@ -157,91 +170,76 @@ def editMatrixBox(matrixbox_field, matrixbox):
if cell_range != matrixbox_cell_range: if cell_range != matrixbox_cell_range:
matrix_context.setCellRange(base_id=cell_base_id, *matrixbox_cell_range) matrix_context.setCellRange(base_id=cell_base_id, *matrixbox_cell_range)
for k,v 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 matrix_context.hasInRange(*k, **kd): if not matrix_context.hasInRange(*cell_index_tuple, **kd):
c = matrix_context.newCell(*k, **kd) return "Cell %s does not exist" % str(cell_index_tuple)
if c is not None:
c.edit(edit_order=edit_order, **gv) # First update globals which include the def. of property_list cell = matrix_context.newCell(*cell_index_tuple, **kd)
if v.has_key('variated_property'): if cell is None:
return "Could not create cell %s" % str(cell_index_tuple)
cell.edit(edit_order=edit_order, **gv) # First update globals which include the def. of property_list
if cell_value_dict.has_key('variated_property'):
# For Variated Properties # For Variated Properties
value = v['variated_property'] value = cell_value_dict['variated_property']
del v['variated_property'] del cell_value_dict['variated_property']
if gv.has_key('mapped_value_property_list'): if gv.has_key('mapped_value_property_list'):
# Change the property which is defined by the # Change the property which is defined by the
# first element of mapped_value_property_list # first element of mapped_value_property_list
# XXX Kato: What? Why?
# XXX May require some changes with Sets # XXX May require some changes with Sets
key = gv['mapped_value_property_list'][0] key = gv['mapped_value_property_list'][0]
v[key] = value cell_value_dict[key] = value
# Form: '' -> ERP5: None # Form: '' -> ERP5: None
cleaned_v = v.copy() cleaned_v = cell_value_dict.copy()
for key, value in cleaned_v.items(): for key, value in cleaned_v.items():
if value == '': if value == '':
cleaned_v[key] = None cleaned_v[key] = None
c.edit(edit_order=edit_order, **cleaned_v) # and update the cell specific values cell.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): edit_kwargs = {} # keyword arguments for `edit` function on context
""" encapsulated_editor_list = [] # editors placed inside REQUEST object
Parse given form field, to put them in MARKER = [] # placeholder for an empty value
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