11from collective .volto .formsupport .interfaces import IFormDataStore
2+ from collective .volto .formsupport .utils import get_blocks
3+ from copy import deepcopy
24from io import StringIO
35from plone .restapi .serializer .converters import json_compatible
46from plone .restapi .services import Service
@@ -23,12 +25,37 @@ def __init__(self, context, request):
2325 block_type = block .get ("@type" , "" )
2426 if block_type == "form" :
2527 self .form_block = block
28+ self .form_block_id = id
2629
2730 if self .form_block :
2831 for field in self .form_block .get ("subblocks" , []):
2932 field_id = field ["field_id" ]
3033 self .form_fields_order .append (field_id )
3134
35+ def get_form_fields (self ):
36+ blocks = get_blocks (self .context )
37+
38+ if not blocks :
39+ return {}
40+ form_block = {}
41+ for id , block in blocks .items ():
42+ if id != self .form_block_id :
43+ continue
44+ block_type = block .get ("@type" , "" )
45+ if block_type == "form" :
46+ form_block = deepcopy (block )
47+ if not form_block :
48+ return {}
49+
50+ subblocks = form_block .get ("subblocks" , [])
51+
52+ # Add the 'custom_field_id' field back in as this isn't stored with each subblock
53+ for index , field in enumerate (subblocks ):
54+ if form_block .get (field ["field_id" ]):
55+ subblocks [index ]["custom_field_id" ] = form_block .get (field ["field_id" ])
56+
57+ return subblocks
58+
3259 def get_ordered_keys (self , record ):
3360 """
3461 We need this method because we want to maintain the fields order set in the form.
@@ -61,37 +88,57 @@ def render(self):
6188 data = data .encode ("utf-8" )
6289 self .request .response .write (data )
6390
64- def get_fields_labels (self , item ):
65- return item .attrs .get ("fields_labels" , {})
91+ def get_fields_labels (self ):
92+ return {
93+ x ["field_id" ]: x .get ("custom_field_id" , x .get ("label" , x ["field_id" ]))
94+ for x in self .get_form_fields ()
95+ if x .get ("field_type" , "" ) != "static_text"
96+ }
6697
6798 def get_data (self ):
6899 store = getMultiAdapter ((self .context , self .request ), IFormDataStore )
69100 sbuf = StringIO ()
70101 fixed_columns = ["date" ]
71102 columns = []
72-
103+ legacy_columns = []
73104 rows = []
105+ fields_labels = self .get_fields_labels ()
106+
74107 for item in store .search ():
75108 data = {}
76- fields_labels = self . get_fields_labels ( item )
109+
77110 for k in self .get_ordered_keys (item ):
78111 if k in SKIP_ATTRS :
79112 continue
113+
80114 value = item .attrs .get (k , None )
81- label = fields_labels .get (k , k )
82- if label not in columns and label not in fixed_columns :
83- columns .append (label )
115+ label = {** item .attrs .get ("fields_labels" , {}), ** fields_labels }.get (
116+ k , k
117+ )
118+
119+ if k not in self .form_fields_order and label not in legacy_columns :
120+ legacy_columns .append (label )
121+
84122 data [label ] = json_compatible (value )
123+
85124 for k in fixed_columns :
86125 # add fixed columns values
87126 value = item .attrs .get (k , None )
88127 data [k ] = json_compatible (value )
128+
89129 rows .append (data )
130+
131+ columns .extend (fields_labels .values ())
90132 columns .extend (fixed_columns )
133+ columns .extend (sorted (legacy_columns ))
134+
91135 writer = csv .DictWriter (sbuf , fieldnames = columns , quoting = csv .QUOTE_ALL )
92136 writer .writeheader ()
137+
93138 for row in rows :
94139 writer .writerow (row )
140+
95141 res = sbuf .getvalue ()
96142 sbuf .close ()
143+
97144 return res
0 commit comments