template::element::validate (private)

 template::element::validate form_id element_id

Defined in packages/acs-templating/tcl/element-procs.tcl

Validates element values according to 3 criteria:

  1. required elements must have a not-null value;
  2. values must match the element's declared datatype;
  3. values must pass all special validation filters specified with the -validate option when the element was created.

If validation fails for any reason, one or more messages are added to the error list for the form, causing the submission to be invalidated and returned to the user for correction.

Parameters:
form_id (required)
The identifier of the form containing the element.
element_id (required)
The unique identifier of the element.

Partial Call Graph (max 5 caller/called nodes):
%3 template::element::create template::element::create (public) template::element::validate template::element::validate template::element::create->template::element::validate template::element::get_opts template::element::get_opts (private) template::element::get_opts->template::element::validate _ _ (public) template::element::validate->_ ad_log ad_log (public) template::element::validate->ad_log template::adp_level template::adp_level (public) template::element::validate->template::adp_level template::data::validate template::data::validate (public) template::element::validate->template::data::validate template::element::querygetall template::element::querygetall (public) template::element::validate->template::element::querygetall

Testcases:
No testcase defined.
Source code:
    set level [template::adp_level]

    # use an array to hold error messages for this form
    upvar #$level $form_id:error formerror $form_id:$element_id element

    # set values [querygetall $element(id) $element(datatype)]
    set values [querygetall element]
    set is_optional [info exists element(optional)]

    # if the element is optional and the value is an empty string, then ignore
    if { $is_optional && [lindex $values 0] eq "" } {
        set values [list]

        # also clobber the value(s) for a submit widget
        if {$element(widget) eq "submit"} {
            if { [info exists element(value)] } { unset element(value) }
            if { [info exists element(values)] } { unset element(values) }
        }
    }

    # if no values were submitted then look for values specified in the
    # declaration (either values or value)
    if { [llength $values] == 0 && [info exists element(values)] } {
        set values $element(values)
    }

    # set a label for use in the template
    set label $element(label)
    if {$label eq ""} {
        set label $element(name)
    }

    # Element shouldn't be validated if it's an inform widget, or the
    # element is not in edit mode.  The element will be in edit mode if
    # its mode is either blank or set to 'edit'.
    set is_inform [expr {$element(widget) eq "inform" || ($element(mode) ne "edit" && $element(mode) ne "" )}]

    # Check for required element
    if { ! $is_inform  && ! $is_optional && ![llength $values] } {

        # no value was submitted for a required element
        set formerror($element_id) [_ acs-templating.Element_is_required]
        set formerror($element_id:required) [_ acs-templating.Element_is_required]

        if {$element(widget) in {hidden submit}} {
            ad_log warning "template::element::validate: No value for $element(widget) element $label"
        }
    }

    # Prepare custom validation filters

    if { [info exists element(validate)] } {

        set v_length [llength $element(validate)]

        if { $v_length == 2 } {

            # a single anonymous validation check was specified
            set element(validate) [linsert $element(validate) 0 "anonymous"]

        } elseif$v_length % 3 } {

            error "Invalid number of parameters to validate option:
             $element(validate) (Length is $v_length)"
        }

    } else {

        set element(validate) [list]
    }

    set v_errors [list]

    foreach value $values {

        #
        # Something was submitted, now check if it is valid.
        #

        if { $is_optional && $value eq "" } {
            #
            # This is an optional field and it's empty... Skip
            # validation (else things like the integer test will
            # fail).
            #
            continue
        }

        if { [info exists element(maxlength)] } {
            #
            # A maximum length was specified for this element. Make
            # sure it is respected first.
            #
            
            # Tcl9 does not include "string bytelength". Use idiom
            # from Rolf Ade's Tcl9 migration guide instead.            
            #set value_bytelength [string bytelength $value]            
            set value_bytelength [string length [encoding convertto utf-8 $value]]
            
            if {  $value_bytelength > $element(maxlength) } {
                #
                # The element is too long.
                #
                set excess_no_bytes [expr { $value_bytelength - $element(maxlength) }]
                if { $excess_no_bytes == 1 } {
                    set message [_ acs-templating.Element_is_too_long_Singular]
                } else {
                    set message [_ acs-templating.Element_is_too_long_Plural]
                }
                lappend v_errors $message
                set formerror($element_id:maxlength$message
            }
        }

        if { ! [template::data::validate $element(datatype) value message] } {
            #
            # The submission is formally invalid according to datatype
            # validation.
            #
            lappend v_errors $message
            set formerror($element_id:data$message

            if { $element(widget) in {hidden submit} } {
                ad_log warning "template::element::validate: Invalid value for $element(widget) element $label: $message"
            }
        } else {
            #
            # The submission is formally valid. Now go through the
            # custom user-defined validation.
            #
            foreach { v_name v_code v_message } $element(validate) {

                if { ! [eval $v_code] } {
                    #
                    # Value is invalid according to custom validation
                    # code.  Do some expansion on $value, ${value},
                    # $label, and ${label}
                    #
                    set v_message [util::var_subst_quotehtml $v_message]
                    lappend v_errors $v_message
                    set formerror($element_id:$v_name$v_message
                }
            }
        }
    }

    if { [llength $v_errors] } {
        # concatenate all validation errors encountered while looping over values
        set formerror($element_id) [join $v_errors "<br>\n"]
    }

    # make the value be the previously submitted value when returning the form
    set element(values) $values

    # be careful not to clobber a default value if one has been specified
    if { [llength $values] || ! [info exists element(value)] } {
        set element(value) [lindex $values 0]
    }
XQL Not present:
Generic, PostgreSQL, Oracle
[ hide source ] | [ make this the default ]
Show another procedure: