FormBroker — Form broker object creator
The command returns a reference to a form broker object by creating a representation of the form data using the list of variable descriptors passed to method create. Each descriptor is a list of parameter or parameter-value pairs that must begin with the {variable_name variable_type} pair as only requirement. A formbroker object provide native support for integer, unsigned integer, string, boolean and email data types. The programmer can defined new data types and provide in the descriptor a reference to a validation procedure for that type.
The optional ?-quoting quoting_procedure? switch defines an external procedure to quote or reformat the response values. The quoting procedure is any procedure accepting a single string argument and returning its quoted value. A most basic example is the FormBroker default quoting procedure
proc force_quote {str} { return "'$str'" }
Other parameters of a descriptors are
An example of a form accepting four variable, one for each native type of a form broker object
% set fbroker [::FormBroker create {var1 integer} {var2 unsigned} {var3 string} {var4 integer bounds {-10 100}}] ::FormBroker::form0
The central method of a form broker object is validate
formBroker_object
validate ?-forcequote? response ?response copy
?-forcequote
causes the
variable values to be rewritten and quoted. If the optional argument response copy
is present the validated response is copied in this array instead of the input response
array.
% package require formbroker % set fbroker [::FormBroker create {var1 integer} {var2 unsigned} {var3 string} {var4 integer bounds {-10 100}}] ::FormBroker::form0 % ::rivet::load_response % parray response response(var1) = -10 response(var2) = 20 response(var3) = a string response(var4) = 50 # let's keep a copy of the response % array set response_copy [array get response] # form data validation % $fbroker validate response true % $fbroker validate -forcequote response % parray response response(var1) = '-10' response(var2) = '20' response(var3) = 'a string' response(var4) = '50' # restore response original value % array set response [array get response_copy] % $fbroker validate -forcequote response response_copy true % parray response response(var1) = -10 response(var2) = 20 response(var3) = a string response(var4) = 50 % parray response_copy response_copy(var1) = '-10' response_copy(var2) = '20' response_copy(var3) = 'a string' response_copy(var4) = '50' # a form object has to be destroyed if it's not needed anymore % $fbroker destroy
formBroker_object
failing % package require formbroker 1.0 % set fbroker [::FormBroker create {var1 integer} \ {var2 unsigned} \ {var3 string} \ {var4 integer}] ::FormBroker::form0 % ::rivet::load_response # let's suppose we have an incomplete response % parray response response(var1) = '100' response(var2) = '20' response(var3) = 'a string' % $fbroker validate response false $fbroker failing var4 MISSING_VAR # this can be prevented by assigning a variable a default value % set fbroker [::FormBroker create {var1 integer} \ {var2 unsigned} \ {var3 string} \ {var4 integer default 0}] ::FormBroker::form1 % $fbroker validate response true % parray response response(var1) = 100 response(var2) = 20 response(var3) = a string response(var4) = 0 % set fbroker [::FormBroker create {var1 integer} \ {var2 unsigned} \ {var3 string length 10 constrain} \ {var4 integer bounds {-10 100}}] ::FormBroker::form2 % ::rivet::load_response # this time the response has invalid data % parray response response(var1) = 'aaaaa' response(var2) = '-20' response(var3) = 'a longer string that breaks the 10 chars max limit imposed' response(var4) = '150' % $fbroker validate response false % $fbroker failing var1 NOT_INTEGER var2 FB_OUT_OF_BOUNDS var4 FB_OUT_OF_BOUNDS
% package require formbroker % set fbroker [::FormBroker create {var1 integer bounds 10 constrain} \ {var2 unsigned constrain} \ {var3 string length 10 constrain} \ {var4 integer bounds {-10 100} constrain}] ::FormBroker::form0 % ::rivet::load_response % parray response response(var1) = abcdef response(var2) = -20 response(var3) = a longer string that breaks the 10 chars max limit imposed response(var4) = 150 % $fbroker validate response response_copy false % $fbroker failing var1 NOT_INTEGER % parray response_copy response_copy(var2) = 0 response_copy(var3) = a longer s response_copy(var4) = 100
formBroker_object
response ?response_array_name?set fbroker [::FormBroker create {var1 integer default 0} \ {var2 unsigned default 1} \ {var3 string} \ {var4 integer default 0}] % $fbroker response a % parray a a(var1) = 0 a(var2) = 1 a(var4) = 0
formBroker_object
reset The form broker is by no means restricted to work only with its native data types: you may define your own form variable types and have them validated with their own variable validator.
A validator is a function accepting a dictionary as single argument and must return either FB_OK, if the variable value is valid, or any other used defined error code. The dictionary argument stores the variable descriptor used internally by the form broker.
Suppose you're writing a form text entry that demands as input a network interface MAC address. A MAC address is represented by 6 hexadecimal octets separated by either a “-” (Windows convention) or “:” (Unix, Mac convention). The procedure validate_mac checks the validity of the mac address and if validation is successful it transforms its representation into the Unix form. By setting the key “constrain” in the dictionary mac_address_d the procedure is telling the form broker to copy the transformed value back in the input response array
proc validate_mac {_mac_address_d} { upvar $_mac_address_d mac_address_d dict with mac_address_d { set var [string trim $var] if {[regexp {^[[:xdigit:]]{2}([:-][[:xdigit:]]{2}){5}$} $var]} { set var [string tolower $var] # we normalize the mac address to the Unix form. # The dash '-' characters in the windows representation # are replaced by columns ':' set var [regsub -all -- {-} $var :] # the 'constrain' field is bidirectional: # it tells the validator to curb/change the value # within bonds/forms/representation. By setting it the # validator tells the FormBroker to copy the value # back in the response array set constrain 1 return FB_OK } else { return FB_WRONG_MAC } } } % set fbroker [::FormBroker create {mac mac_address validator validate_mac}] % ::rivet::load_response r % parray r r(mac) = 00-A1-B2-C3-D4-C5 % $fbroker validate r true % parray r r(mac) = 00:a1:b2:c3:d4:c5