<?PHP
#
#   FILE:  FormField.php
#
#   Part of the Collection Workflow Integration System (CWIS)
#   Copyright 2002-2015 Edward Almasy and Internet Scout Research Group
#   http://scout.wisc.edu/cwis/
#

/**
* Generator for HTML form fields.
* @nosubgrouping
*/
class FormField
{
    # ---- PUBLIC INTERFACE --------------------------------------------------

    /** @name Setup/Initialization */
    /*@{*/

    /**
    * Object Constructor.
    * @param string $Name Internal name for this field, used in the HTML for the
    *     id attribute.
    * @param bool $IsRequired Whether the form field is required.
    * @param string $Label Display label for this field as shown to the user.
    * @param callback $ValidFunc A function to check the validity of input to
    *      this field. The function should return 0 for valid input.
    * @param array $ValidMsgs An array of error messages, corresponding to the
    *      error codes returned by @p $ValidFunc.
    */
    public function __construct($Name, $IsRequired, $Label, $ValidFunc, $ValidMsgs)
    {
        # save field info
        $this->MyName = $Name;
        $this->MyIsRequired = $IsRequired;
        $this->MyLabel = $Label;
        $this->MyValidFunc = $ValidFunc;
        $this->MyValidMsgs = $ValidMsgs;

        # attempt to set value if available
        if (isset($_POST[$this->MyName]))
        {
            $this->MyValue = $_POST[$this->MyName];
        }
        elseif (isset($_GET[$this->MyName]))
        {
            $this->MyValue = $_GET[$this->MyName];
        }
    }
    /*@}*/

    /** @name Accessors */
    /*@{*/

    /**
    * Get or set the name. In other words, the internal name for the id
    * attribute.
    * @param string $NewVal New value for the object's name. This parameter is
    *     optional.
    * @return Returns the current name.
    */
    public function Name($NewVal = NULL)
    {
        return $this->GetOrSet("MyName", $NewVal);
    }

    /** Get/set IsRequired @see Name */

    /**
    * Get or set the value that determines whether the form field is required.
    * @param bool $NewVal TRUE to make the form field required. This parameter
    *     is optional.
    * @return Returns TRUE if the form field is required.
    */
    public function IsRequired($NewVal = NULL)
    {
        return $this->GetOrSet("MyIsRequired", $NewVal);
    }

    /**
    * Get or set the form field label as shown to the user.
    * @param string $NewVal New value for the form field label.
    * @return Returns the current form field label.
    */
    public function Label($NewVal = NULL)
    {
        return $this->GetOrSet("MyLabel", $NewVal);
    }

    /**
    * Get or set the form field value. In other words, the value attribute.
    * @param mixed $NewVal New value for the form field value. This parameter is
    *     optional.
    * @return Returns the current form field value.
    */
    public function Value($NewVal = NULL)
    {
        return $this->GetOrSet("MyValue", $NewVal);
    }

    /**
    * Determine if this form field is a password form field.
    * @return Returns TRUE if this form field is a password field.
    */
    public function IsPassword()
    {
        return method_exists($this, "PasswordFormField");
    }

    /*@}*/

    /** @name Display */
    /*@{*/

    /**
    * Print the form field label and generate input tags for this form field.
    * @param bool $DisplayErrorIndicator Determines whether error associated
    *      with this form field should be displayed. Set it to TRUE to display
    *      errors. This parameter is optional and defaults to FALSE.
    */
    public function PrintField($DisplayErrorIndicator = FALSE)
    {
        $this->PrintLabel($DisplayErrorIndicator);
        $this->PrintInput($DisplayErrorIndicator);
    }

    /**
    * Print the label for this form field without generating the input tags.
    * @param bool $DisplayErrorIndicator Determines whether error associated
    *      with this form field should be displayed. Set it to TRUE to display
    *      errors. This parameter is optional and defaults to FALSE.
    */
    public function PrintLabel($DisplayErrorIndicator = FALSE)
    {
        # print label
        print(($DisplayErrorIndicator ? "<span style=\"color: red;\">" : "")
            ."<label for=\"".$this->MyName."\">".$this->MyLabel."</label>"
            .($DisplayErrorIndicator ? "</span>" : "")
            ."\n");
    }
    /*@}*/

    /** @name Error Checking */
    /*@{*/

    /**
    * Check the validity of the form field's value.
    * @param string $Value Value to check.
    * @return Returns 0 for valid input and a non-zero value for invalid input.
    */
    public function IsInvalidValue($Value)
    {
        # assume value is valid
        $ErrorCode = 0;

        # if custom validation function supplied
        if ($this->MyValidFunc)
        {
            # call custom function and return code
            $ValidFunc = $this->MyValidFunc;
            $ErrorCode = $ValidFunc($this->MyName, $Value);
        }
        else
        {
            # if value is required and none is set
            if ($this->MyIsRequired && !strlen($Value)
                    && !method_exists($this, "PasswordFormField"))
            {
                # return code indicating missing value
                $ErrorCode = 1;
            }
        }

        # return error code (if any) to caller
        return $ErrorCode;
    }

    /**
    * Map an error code from IsInvalidValue to an error message.
    * @param int $ErrorCode Error code assumed to come from IsInvalidValue().
    * @return Returns a text string corresponding to the given error code.
    */
    public function GetInvalidValueMessage($ErrorCode)
    {
        $Messages = array(
                0 => "This value is valid.",
                1 => "%L is a required value.",
                );
        if (isset($this->MyValidMsgs[$ErrorCode]))
        {
            $Message = $this->MyValidMsgs[$ErrorCode];
        }
        else
        {
            $Message = isset($Messages[$ErrorCode])
                    ? $Messages[$ErrorCode] :
                            "INTERNAL ERROR - Invalid Error Code (Field = %N, Code = %C)";
        }
        return $Message;
    }

    /*@}*/

    # ---- PRIVATE INTERFACE -------------------------------------------------

    protected $MyName;
    protected $MyIsRequired;
    protected $MyLabel;
    protected $MyValue;
    protected $MyValidFunc;
    protected $MyValidMsgs;

    /**
    * This is a convenience function to handle getting and setting configuration
    * values for the form field.
    * @param string $ValueName Name of the value to get or set.
    * @param mixed $NewValue New value to set or NULL to get the value only.
    * @return Returns the current value of the configuration value
    */
    private function GetOrSet($ValueName, $NewValue)
    {
        if ($NewValue !== NULL)
        {
            $this->{$ValueName} = $NewValue;
        }
        return $this->{$ValueName};
    }
}
