• Publicity: Public Only All

data-procs.tcl

Datatype validation for the ArsDigita Templating System

Location:
packages/acs-templating/tcl/data-procs.tcl
Author:
Karl Goldstein <karlg@arsdigita.com>
CVS Identification:
$Id: data-procs.tcl,v 1.25 2024/09/11 06:15:48 gustafn Exp $

Procedures in this file

Detailed information

template::data::transform (public)

 template::data::transform type value_ref

Dispatch procedure for the transform method. "transformation" in template systemspeak means to convert the submitted data to the custom datatype structure, usually a list for complex datatypes, just the value for simple datatypes. The transform method is called after the datatype is validated.

Parameters:
type (required)
The data type to be transformed.
value_ref (required)

Partial Call Graph (max 5 caller/called nodes):
%3

Testcases:
No testcase defined.

template::data::validate (public)

 template::data::validate type value_ref message_ref

This proc invokes the validation code for a given type.

Parameters:
type (required)
value_ref (required)
message_ref (required)
See Also:

Partial Call Graph (max 5 caller/called nodes):
%3 test_validate_boolean validate_boolean (test acs-templating) template::data::validate template::data::validate test_validate_boolean->template::data::validate test_validate_currency validate_currency (test acs-templating) test_validate_currency->template::data::validate test_validate_date validate_date (test acs-templating) test_validate_date->template::data::validate test_validate_email validate_email (test acs-templating) test_validate_email->template::data::validate test_validate_enumeration validate_enumeration (test acs-templating) test_validate_enumeration->template::data::validate template::data::validate::widget template::data::validate::widget (private) template::data::validate->template::data::validate::widget template::data::validate::currency template::data::validate::currency (public) template::data::validate::currency->template::data::validate template::element::validate template::element::validate (private) template::element::validate->template::data::validate

Testcases:
validate_boolean, validate_email, validate_integer, validate_naturalnum, validate_float, validate_number, validate_text, validate_search, validate_file, validate_keyword, validate_filename, validate_url, validate_url_element, validate_date, validate_enumeration, validate_textdate, validate_oneof, validate_currency

template::data::validate::boolean (public)

 template::data::validate::boolean value_ref message_ref

Validates boolean data types.

Parameters:
value_ref (required)
Reference variable to the submitted value
message_ref (required)
Reference variable for returning an error message
Returns:
True (1) if valid, false (0) if not
Author:
Roberto Mello

Partial Call Graph (max 5 caller/called nodes):
%3 test_validate_boolean validate_boolean (test acs-templating) template::data::validate::boolean template::data::validate::boolean test_validate_boolean->template::data::validate::boolean _ _ (public) template::data::validate::boolean->_

Testcases:
validate_boolean

template::data::validate::date (public)

 template::data::validate::date value_ref message_ref

Validate that a submitted date conforms to the template system's notion of what a date should be.

Parameters:
value_ref (required)
Reference variable to the submitted value
message_ref (required)
Reference variable for returning an error message
Returns:
True (1) if valid, false (0) if not

Partial Call Graph (max 5 caller/called nodes):
%3 test_validate_date validate_date (test acs-templating) template::data::validate::date template::data::validate::date test_validate_date->template::data::validate::date template::util::date::validate template::util::date::validate (public) template::data::validate::date->template::util::date::validate

Testcases:
validate_date

template::data::validate::email (public)

 template::data::validate::email value_ref message_ref

Validate that a submitted email address is syntactically correct.

Parameters:
value_ref (required)
Reference variable to the submitted value
message_ref (required)
Reference variable for returning an error message
Returns:
True (1) if valid, false (0) if not

Partial Call Graph (max 5 caller/called nodes):
%3 test_validate_email validate_email (test acs-templating) template::data::validate::email template::data::validate::email test_validate_email->template::data::validate::email _ _ (public) template::data::validate::email->_ util_email_valid_p util_email_valid_p (public) template::data::validate::email->util_email_valid_p

Testcases:
validate_email

template::data::validate::enumeration (public)

 template::data::validate::enumeration value_ref message_ref

Validate enumeration as a unique csv alphanum list.

Parameters:
value_ref (required)
Reference variable to the submitted value
message_ref (required)
Reference variable for returning an error message
Returns:
True (1) if valid, false (0) if not

Partial Call Graph (max 5 caller/called nodes):
%3 test_validate_enumeration validate_enumeration (test acs-templating) template::data::validate::enumeration template::data::validate::enumeration test_validate_enumeration->template::data::validate::enumeration _ _ (public) template::data::validate::enumeration->_

Testcases:
validate_enumeration

template::data::validate::filename (public)

 template::data::validate::filename value_ref message_ref

Validate that a submitted filename consists of alphanumeric, "_", or "-" characters.

Parameters:
value_ref (required)
Reference variable to the submitted value
message_ref (required)
Reference variable for returning an error message
Returns:
True (1) if valid, false (0) if not

Partial Call Graph (max 5 caller/called nodes):
%3 test_validate_filename validate_filename (test acs-templating) template::data::validate::filename template::data::validate::filename test_validate_filename->template::data::validate::filename _ _ (public) template::data::validate::filename->_

Testcases:
validate_filename

template::data::validate::float (public)

 template::data::validate::float value_ref message_ref

Validate that a submitted fla contains only an optional sign, and a whole part and fractional part.

Parameters:
value_ref (required)
Reference variable to the submitted value
message_ref (required)
Reference variable for returning an error message
Returns:
True (1) if valid, false (0) if not

Partial Call Graph (max 5 caller/called nodes):
%3 test_validate_float validate_float (test acs-templating) template::data::validate::float template::data::validate::float test_validate_float->template::data::validate::float _ _ (public) template::data::validate::float->_

Testcases:
validate_float

template::data::validate::integer (public)

 template::data::validate::integer value_ref message_ref

Validate that a submitted integer contains only an optional sign and the digits 0-9.

Parameters:
value_ref (required)
Reference variable to the submitted value
message_ref (required)
Reference variable for returning an error message
Returns:
True (1) if valid, false (0) if not

Partial Call Graph (max 5 caller/called nodes):
%3 test_validate_integer validate_integer (test acs-templating) template::data::validate::integer template::data::validate::integer test_validate_integer->template::data::validate::integer _ _ (public) template::data::validate::integer->_

Testcases:
validate_integer

template::data::validate::keyword (public)

 template::data::validate::keyword value_ref message_ref

Validate that a submitted keyword consists of alphnumeric or "_" characters.

Parameters:
value_ref (required)
Reference variable to the submitted value
message_ref (required)
Reference variable for returning an error message
Returns:
True (1) if valid, false (0) if not

Partial Call Graph (max 5 caller/called nodes):
%3 test_validate_keyword validate_keyword (test acs-templating) template::data::validate::keyword template::data::validate::keyword test_validate_keyword->template::data::validate::keyword _ _ (public) template::data::validate::keyword->_

Testcases:
validate_keyword

template::data::validate::naturalnum (public)

 template::data::validate::naturalnum value_ref message_ref

Validates natural numbers data types. Will trim leading 0 in order to avoid Tcl interpreting it as octal (code borrowed from ad_page_contract_filter_proc_naturalnum)

Parameters:
value_ref (required)
Reference variable to the submitted value
message_ref (required)
Reference variable for returning an error message
Returns:
True (1) if valid, false (0) if not
Author:
Rocael Hernandez

Partial Call Graph (max 5 caller/called nodes):
%3 test_validate_naturalnum validate_naturalnum (test acs-templating) template::data::validate::naturalnum template::data::validate::naturalnum test_validate_naturalnum->template::data::validate::naturalnum _ _ (public) template::data::validate::naturalnum->_

Testcases:
validate_naturalnum

template::data::validate::nomarkup (public)

 template::data::validate::nomarkup value_ref message_ref

Checks if supplied string contains markup.

Parameters:
value_ref (required)
message_ref (required)
Author:
Guenter Ernst

Partial Call Graph (max 5 caller/called nodes):
%3 _ _ (public) ad_looks_like_html_p ad_looks_like_html_p (public) template::data::validate::nomarkup template::data::validate::nomarkup template::data::validate::nomarkup->_ template::data::validate::nomarkup->ad_looks_like_html_p

Testcases:
No testcase defined.

template::data::validate::number (public)

 template::data::validate::number value_ref message_ref

Validate number - any float - should be any rational number?

Parameters:
value_ref (required)
Reference variable to the submitted value
message_ref (required)
Reference variable for returning an error message
Returns:
True (1) if valid, false (0) if not

Partial Call Graph (max 5 caller/called nodes):
%3 test_validate_number validate_number (test acs-templating) template::data::validate::number template::data::validate::number test_validate_number->template::data::validate::number _ _ (public) template::data::validate::number->_

Testcases:
validate_number

template::data::validate::oneof (public)

 template::data::validate::oneof value_ref message_ref

Checks whether the submitted value is contained in the list of values provided via the "-options" parameter of "::template::element::create". If it is set an error is thrown.

Parameters:
value_ref (required)
Reference variable to the submitted value
message_ref (required)
Reference variable for returning an error message
Returns:
True (1) if valid, false (0) if not
See Also:

Partial Call Graph (max 5 caller/called nodes):
%3 test_validate_oneof validate_oneof (test acs-templating) template::data::validate::oneof template::data::validate::oneof test_validate_oneof->template::data::validate::oneof _ _ (public) template::data::validate::oneof->_

Testcases:
validate_oneof

template::data::validate::search (public)

 template::data::validate::search value_ref message_ref

It was necessary to declare a datatype of "search" in order for the transformation to be applied correctly. In reality, the transformation should be on the element, not on the datatype. DRB: in practice a template form datatype is defined by the presence of a validate procedure for that type.

Parameters:
value_ref (required)
Reference variable to the submitted value
message_ref (required)
Reference variable for returning an error message
Returns:
True (1)

Partial Call Graph (max 5 caller/called nodes):
%3 test_validate_search validate_search (test acs-templating) template::data::validate::search template::data::validate::search test_validate_search->template::data::validate::search

Testcases:
validate_search

template::data::validate::string (public)

 template::data::validate::string value_ref message_ref

Validate that a submitted string is valid. Hmmm ... all submitted strings are valid, that's easy!

Parameters:
value_ref (required)
Reference variable to the submitted value
message_ref (required)
Reference variable for returning an error message
Returns:
True (1)

Partial Call Graph (max 5 caller/called nodes):
%3 test_validate_text validate_text (test acs-templating) template::data::validate::string template::data::validate::string test_validate_text->template::data::validate::string

Testcases:
validate_text

template::data::validate::text (public)

 template::data::validate::text value_ref message_ref

Validate that submitted text is valid. Hmmm ... all submitted text is valid, that's easy!

Parameters:
value_ref (required)
Reference variable to the submitted value
message_ref (required)
Reference variable for returning an error message
Returns:
True (1)

Partial Call Graph (max 5 caller/called nodes):
%3 test_validate_text validate_text (test acs-templating) template::data::validate::text template::data::validate::text test_validate_text->template::data::validate::text template::data::validate::richtext template::data::validate::richtext (public) template::data::validate::richtext->template::data::validate::text template::data::validate::richtext_or_file template::data::validate::richtext_or_file (public) template::data::validate::richtext_or_file->template::data::validate::text

Testcases:
validate_text

template::data::validate::textdate (public)

 template::data::validate::textdate value_ref message_ref

Validate that a submitted textdate if properly formatted.

Parameters:
value_ref (required)
Reference variable to the submitted value.
message_ref (required)
Reference variable for returning an error message.
Returns:
True (1) if valid, false (0) if not.

Partial Call Graph (max 5 caller/called nodes):
%3 test_validate_textdate validate_textdate (test acs-templating) template::data::validate::textdate template::data::validate::textdate test_validate_textdate->template::data::validate::textdate _ _ (public) template::data::validate::textdate->_ template::util::date::get_property template::util::date::get_property (public) template::data::validate::textdate->template::util::date::get_property template::util::textdate_localized_format template::util::textdate_localized_format (public) template::data::validate::textdate->template::util::textdate_localized_format

Testcases:
validate_textdate

template::data::validate::time_of_day (public)

 template::data::validate::time_of_day value_ref message_ref

Validate time of day.

Parameters:
value_ref (required)
Reference variable to the submitted value
message_ref (required)
Reference variable for returning an error message
Returns:
True (1) if valid, false (0) if not

Partial Call Graph (max 5 caller/called nodes):
%3 test_validate_date validate_date (test acs-templating) template::data::validate::time_of_day template::data::validate::time_of_day test_validate_date->template::data::validate::time_of_day template::util::date::validate template::util::date::validate (public) template::data::validate::time_of_day->template::util::date::validate

Testcases:
validate_date

template::data::validate::timestamp (public)

 template::data::validate::timestamp value_ref message_ref

Validate that a submitted date conforms to the template system's notion of what a date should be.

Parameters:
value_ref (required)
Reference variable to the submitted value
message_ref (required)
Reference variable for returning an error message
Returns:
True (1) if valid, false (0) if not

Partial Call Graph (max 5 caller/called nodes):
%3 test_validate_date validate_date (test acs-templating) template::data::validate::timestamp template::data::validate::timestamp test_validate_date->template::data::validate::timestamp template::util::date::validate template::util::date::validate (public) template::data::validate::timestamp->template::util::date::validate

Testcases:
validate_date

template::data::validate::url (public)

 template::data::validate::url value_ref message_ref

Validate that a submitted url is correct. Accepts an optional http:// or https:// prefix, path, and query string.

Parameters:
value_ref (required)
Reference variable to the submitted value
message_ref (required)
Reference variable for returning an error message
Returns:
True (1) if valid, false (0) if not

Partial Call Graph (max 5 caller/called nodes):
%3 test_validate_url validate_url (test acs-templating) template::data::validate::url template::data::validate::url test_validate_url->template::data::validate::url _ _ (public) template::data::validate::url->_ util_url_valid_p util_url_valid_p (public) template::data::validate::url->util_url_valid_p

Testcases:
validate_url

template::data::validate::url_element (public)

 template::data::validate::url_element value_ref message_ref

Beautiful URL elements that may only contain lowercase characters, numbers and hyphens.

Parameters:
value_ref (required)
Reference variable to the submitted value
message_ref (required)
Reference variable for returning an error message
Returns:
True (1) if valid, false (0) if not
Author:
Tilmann Singer
See Also:
  • util_text_to_url if you want to offer auto-generation of URLs based on a pretty name

Partial Call Graph (max 5 caller/called nodes):
%3 test_validate_url_element validate_url_element (test acs-templating) template::data::validate::url_element template::data::validate::url_element test_validate_url_element->template::data::validate::url_element _ _ (public) template::data::validate::url_element->_

Testcases:
validate_url_element
[ hide source ] | [ make this the default ]

Content File Source

ad_library {
    Datatype validation for the ArsDigita Templating System

    @author Karl Goldstein    (karlg@arsdigita.com)

    @cvs-id $Id: data-procs.tcl,v 1.25 2024/09/11 06:15:48 gustafn Exp $
}

# Copyright (C) 1999-2000 ArsDigita Corporation

# This is free software distributed under the terms of the GNU Public
# License.  Full text of the license is available from the GNU Project:
# http://www.fsf.org/copyleft/gpl.html


namespace eval template {}
namespace eval template::data {}
namespace eval template::data::validate {}
namespace eval template::data::transform {}

ad_proc -public template::data::validate { type value_ref message_ref } {
    This proc invokes the validation code for a given type.

    @see template::data::validate::boolean
    @see template::data::validate::date
    @see template::data::validate::email
    @see template::data::validate::enumeration
    @see template::data::validate::filename
    @see template::data::validate::float
    @see template::data::validate::integer
    @see template::data::validate::keyword
    @see template::data::validate::naturalnum
    @see template::data::validate::number
    @see template::data::validate::search
    @see template::data::validate::string
    @see template::data::validate::nomarkup
    @see template::data::validate::text
    @see template::data::validate::textdate
    @see template::data::validate::timestamp
    @see template::data::validate::time_of_day
    @see template::data::validate::url
    @see template::data::validate::oneof
} {
    if {![validate::widget $value_ref $message_ref]} {
        return 0
    } else {
        return [validate::$type $value_ref $message_ref]
    }
}

ad_proc -private template::data::validate::widget { value_ref message_ref } {
    Here we perform the widget-specific validation, which does not
    depend on the datatype itself, but rather on the widget logics.

    @param value_ref Reference variable to the submitted value
    @param message_ref Reference variable for returning an error message

    @return True (1) if valid, false (0) if not
} {
    upvar 2 \
        $message_ref message \
        $value_ref value \
        element element

    if {
        [info exists element(widget)] &&
        $element(widget) in {radio select multiselect}
    } {
        # Make sure widgets that are meant to pick an option from a
        # restricted list of values, actually allow only those values.

        # These widgets MUST specify a list of options. When none is
        # specified, validation will fail.
        set options [expr {[info exists element(options)] ? $element(options) : ""}]

        set valid_p false
        foreach o $options {
            lassign $o option_label option_value
            if {$value eq $option_value} {
                set valid_p true
                break
            }
        }
        if {!$valid_p} {
            set message [_ acs-templating.Invalid_choice]
            return 0
        }
    }

    return 1
}

d_proc -public template::data::validate::integer {
    value_ref
    message_ref
} {
    Validate that a submitted integer contains only an optional sign and
    the digits 0-9.

    @param value_ref Reference variable to the submitted value
    @param message_ref Reference variable for returning an error message

    @return True (1) if valid, false (0) if not
} {

    upvar 2 $message_ref message $value_ref value

    set result [regexp {^[+-]?\d+$} $value]

    if { ! $result } {
        set message "[_ acs-templating.Invalid_integer] \"[ns_quotehtml $value]\""
    }

    return $result
}

d_proc -public template::data::validate::naturalnum {
    value_ref
    message_ref
} {
    Validates natural numbers data types.

    Will trim leading 0 in order to avoid Tcl interpreting it as octal (code borrowed
    from ad_page_contract_filter_proc_naturalnum)

    @author Rocael Hernandez <roc@viaro.net>

    @param value_ref Reference variable to the submitted value
    @param message_ref Reference variable for returning an error message

    @return True (1) if valid, false (0) if not
} {
    upvar 2 $message_ref message $value_ref value

    set result [regexp {^(0*)(([1-9][0-9]*|0))$} $value match zeros value]

    if { ! $result } {
        set message "[_ acs-templating.Invalid_natural_number] \"[ns_quotehtml $value]\""
    }

    return $result
}

d_proc -public template::data::validate::float {
    value_ref
    message_ref
} {
    Validate that a submitted fla contains only an optional sign, and a whole part
    and fractional part.

    @param value_ref Reference variable to the submitted value
    @param message_ref Reference variable for returning an error message

    @return True (1) if valid, false (0) if not
} {

    upvar 2 $message_ref message $value_ref value

    # Not allowing for scientific notation. Would the databases swallow it?
    set result [regexp {^([+-]?)(?=\d|\.\d)\d*(\.\d*)?$} $value]

    if { ! $result } {
        set message "[_ acs-templating.Invalid_decimal_number] \"[ns_quotehtml $value]\""
    }

    return $result
}

d_proc -public template::data::validate::boolean {
    value_ref
    message_ref
} {
    Validates boolean data types.

    @author Roberto Mello <rmello at fslc.usu.edu>

    @param value_ref Reference variable to the submitted value
    @param message_ref Reference variable for returning an error message

    @return True (1) if valid, false (0) if not
} {

    upvar 2 $message_ref message $value_ref value

    set result ""
    set value [::string tolower $value]

    switch -- $value {
        0 -
        1 -
        f -
        t -
        n -
        y -
        no -
        yes -
        false -
        true {
            set result 1
        }
        default {
            set result 0
            set message "[_ acs-templating.Invalid_choice] \"[ns_quotehtml $value]\""
        }
    }

    return $result
}

d_proc -public template::data::validate::text {
    value_ref
    message_ref
} {
    Validate that submitted text is valid.  Hmmm ... all submitted text is valid,
    that's easy!

    @param value_ref Reference variable to the submitted value
    @param message_ref Reference variable for returning an error message

    @return True (1)
} {
    return 1
}

d_proc -public template::data::validate::string {
    value_ref
    message_ref
} {
    Validate that a submitted string is valid.  Hmmm ... all submitted strings are valid,
    that's easy!

    @param value_ref Reference variable to the submitted value
    @param message_ref Reference variable for returning an error message

    @return True (1)
} {
    return 1
}

d_proc -public template::data::validate::nomarkup {
    value_ref
    message_ref
} {
    Checks if supplied string contains markup.

    @author Guenter Ernst <guenter.ernst@wu.ac.at>
} {
    upvar 2 $message_ref message $value_ref value element element

    if { [ad_looks_like_html_p $value] } {
        if {[info exists element(label)]} {
            set name $element(label)
        } else {
            set name $element(name)
        }
        set message [_ acs-tcl.lt_Value_for_name_contai [list name '$name']]
        return 0
    } else {
        return 1
    }
}

d_proc -public template::data::validate::keyword {
    value_ref
    message_ref
} {
    Validate that a submitted keyword consists of alphnumeric or "_" characters.

    @param value_ref Reference variable to the submitted value
    @param message_ref Reference variable for returning an error message

    @return True (1) if valid, false (0) if not
} {

    upvar 2 $message_ref message $value_ref value

    set result [regexp {^[a-zA-Z0-9_]+$} $value]

    if { ! $result } {
        set message "[_ acs-templating.Invalid_keyword] \"[ns_quotehtml $value]\""
    }

    return $result
}

d_proc -public template::data::validate::filename {
    value_ref
    message_ref
} {
    Validate that a submitted filename consists of alphanumeric, "_", or
    "-" characters.

    @param value_ref Reference variable to the submitted value
    @param message_ref Reference variable for returning an error message

    @return True (1) if valid, false (0) if not
} {

    upvar 2 $message_ref message $value_ref value

    set result [regexp {^[a-zA-Z0-9_-]+$} $value]

    if { ! $result } {
        set message "[_ acs-templating.Invalid_filename] \"[ns_quotehtml $value]\""
    }

    return $result
}

d_proc -public template::data::validate::email {
    value_ref
    message_ref
} {
    Validate that a submitted email address is syntactically correct.

    @param value_ref Reference variable to the submitted value
    @param message_ref Reference variable for returning an error message

    @return True (1) if valid, false (0) if not
} {

    upvar 2 $message_ref message $value_ref value

    set result [util_email_valid_p $value]

    if { ! $result } {
        set message "[_ acs-templating.Invalid_email_format] \"[ns_quotehtml $value]\""
    }

    return $result
}

d_proc -public template::data::validate::url {
    value_ref
    message_ref
} {
    Validate that a submitted url is correct.  Accepts an optional http:// or
    https:// prefix, path, and query string.

    @param value_ref Reference variable to the submitted value
    @param message_ref Reference variable for returning an error message

    @return True (1) if valid, false (0) if not
} {

    upvar 2 $message_ref message $value_ref value

    set result [util_url_valid_p -relative $value]

    if { ! $result } {
        set message "[_ acs-templating.Invalid_url] \"[ns_quotehtml $value]\""
    }

    return $result
}

d_proc -public template::data::validate::url_element {
    value_ref
    message_ref
} {

    Beautiful URL elements that may only contain lowercase
    characters, numbers and hyphens.

    <p>


    @see util_text_to_url if you want to offer auto-generation of URLs based on a pretty name

    @author Tilmann Singer

    @param value_ref Reference variable to the submitted value
    @param message_ref Reference variable for returning an error message

    @return True (1) if valid, false (0) if not
} {
    upvar 2 $message_ref message $value_ref value

    set expr {^[a-z0-9-]+$}
    set result [regexp $expr $value]

    if { ! $result } {
        set message "[_ acs-templating.Invalid_url_element [list value [ns_quotehtml $value]]]"
    }

    return $result
}

d_proc -public template::data::validate::date {
    value_ref
    message_ref
} {
    Validate that a submitted date conforms to the template system's notion
    of what a date should be.

    @param value_ref Reference variable to the submitted value
    @param message_ref Reference variable for returning an error message

    @return True (1) if valid, false (0) if not
} {

    upvar 2 $message_ref message $value_ref value

    return [template::util::date::validate $value message]
}

d_proc -public template::data::validate::timestamp {
    value_ref
    message_ref
} {
    Validate that a submitted date conforms to the template system's notion
    of what a date should be.

    @param value_ref Reference variable to the submitted value
    @param message_ref Reference variable for returning an error message

    @return True (1) if valid, false (0) if not
} {

    upvar 2 $message_ref message $value_ref value

    return [template::util::date::validate $value message]
}

d_proc -public template::data::validate::textdate {
    value_ref
    message_ref
} {
    Validate that a submitted textdate if properly formatted.

    @param value_ref Reference variable to the submitted value.
    @param message_ref Reference variable for returning an error message.

    @return True (1) if valid, false (0) if not.
} {

    upvar 2 $message_ref message $value_ref textdate

    set error_msg [list]
    if { [info exists textdate] && $textdate ne "" } {
        if { [regexp {^[0-9]{4}-[0-9]{2}-[0-9]{2}$} $textdate match] } {
            if { [catch { clock scan -format {%Y-%m-%d} "${textdate}" }] } {
                # the textdate is formatted properly the template::data::transform::textdate proc
                # will only return correctly formatted dates in iso format, but the date is not
                # valid so they have entered some info incorrectly
                set datelist [split $textdate "-"]
                set year  [lindex $datelist 0]
                set month [::string trimleft [lindex $datelist 1] 0]
                set day   [::string trimleft [lindex $datelist 2] 0]
                if { $month < 1 || $month > 12 } {
                    lappend error_msg [_ acs-templating.Month_must_be_between_1_and_12]
                } else {
                    set maxdays [template::util::date::get_property days_in_month $datelist]
                    if { $day < 1 || $day > $maxdays } {
                        set month_pretty [template::util::date::get_property long_month_name $datelist]
                        if { $month == 2 } {
                            # February has a different number of days depending on the year
                            append month_pretty ${year}"
                        }
                        lappend error_msg [_ acs-templating.lt_day_between_for_month_pretty]
                    }
                }
            }
        } else {
            # the textdate is not formatted properly
            set format [::string toupper [template::util::textdate_localized_format]]
            lappend error_msg [_ acs-templating.lt_Dates_must_be_formatted_]
        }
    }
    if { [llength $error_msg] > 0 } {
        set message [join $error_msg {<br>}]
        return 0
    } else {
        return 1
    }
}


d_proc -public template::data::validate::search {
    value_ref
    message_ref
} {
    It was necessary to declare a datatype of "search" in order for the
    transformation to be applied correctly.  In reality, the transformation
    should be on the element, not on the datatype.

    DRB: in practice a template form datatype is defined by the presence of a
    validate procedure for that type.

    @param value_ref Reference variable to the submitted value
    @param message_ref Reference variable for returning an error message

    @return True (1)
} {
    return 1
}

d_proc -public template::data::transform {
    type
    value_ref
} {
    Dispatch procedure for the transform method.  "transformation" in template
    systemspeak means to convert the submitted data to the custom datatype structure,
    usually a list for complex datatypes, just the value for simple datatypes.  The
    transform method is called after the datatype is validated.

    @param type The data type to be transformed.
} {

    set proc_name [namespace which ::template::data::transform::$type]
    if { $proc_name ne {} } {
        transform::$type $value_ref
    }
}

d_proc -public template::data::validate::number {
    value_ref
    message_ref
} {
    Validate number - any float - should be any rational number?

    @param value_ref Reference variable to the submitted value
    @param message_ref Reference variable for returning an error message

    @return True (1) if valid, false (0) if not
} {

    upvar 2 $message_ref message $value_ref value

    # Not allowing for scientific notation. Would the databases swallow it?
    set result [regexp {^([+-]?)(?=\d|\.\d)\d*(\.\d*)?$} $value]

    if { ! $result } {
        set message "[_ acs-templating.Invalid_number] \"[ns_quotehtml $value]\""
    }

    return $result
}

d_proc -public template::data::validate::enumeration {
    value_ref
    message_ref
} {
    Validate enumeration as a unique csv alphanum list.

    @param value_ref Reference variable to the submitted value
    @param message_ref Reference variable for returning an error message

    @return True (1) if valid, false (0) if not
} {

    upvar 2 $message_ref message $value_ref value

    # alphanumeric csv
    set result [regexp {^([A-z0-9]+,?)+$} $value]

    if { ! $result } {
        set message "[_ acs-templating.Invalid_enumeration] \"[ns_quotehtml $value]\""
        return $result
    }

    # unique list
    set list [split $value ,]
    set result [expr {[llength $list] == [llength [lsort -unique $list]]}]

    if { ! $result } {
        set message "[_ acs-templating.Invalid_enumeration_duplicate_elements [list value [ns_quotehtml $value]]]"
    }

    return $result
}

d_proc -public template::data::validate::time_of_day {
    value_ref
    message_ref
} {
    Validate time of day.

    @param value_ref Reference variable to the submitted value
    @param message_ref Reference variable for returning an error message

    @return True (1) if valid, false (0) if not
} {

    upvar 2 $message_ref message $value_ref value

    return [template::util::date::validate $value message]
}

d_proc -public template::data::validate::oneof {
    value_ref
    message_ref
} {
    Checks whether the submitted value is contained in the list of values provided via
    the "-options" parameter of "::template::element::create". If it is set an
    error is thrown.

    @param value_ref Reference variable to the submitted value
    @param message_ref Reference variable for returning an error message

    @see template::element::create

    @return True (1) if valid, false (0) if not
} {

    upvar 2 $message_ref message $value_ref value element element values values

    # Note: Parameter "-options" is a list containing two-element lists
    # in the form { {label value} {label value} {label value} ...}
    if {[info exists element(options)] } {
        if {[lsearch -index 1 $element(options) $value] == -1} {

            set message "[_ acs-templating.Invalid_choice] \"[ns_quotehtml $value]\""
            return 0
        }
    } else {
        error "template::element::validate::oneof: No options specified for \
           element $element_id in form $form_id"
    }

    return 1
}

# Local variables:
#    mode: tcl
#    tcl-indent-level: 4
#    indent-tabs-mode: nil
# End: