<?php
/*** formUtils.php ***
 * Utility funtions for HTML forms in PHP
 *
 * Check form $values ***
 * Ensure fields in $required have values
 * Check fields in $validate array conform to their type. Allowed types:
 *   email = valid email address
 *   others?.. 
 *
 * Return an array of field=>error pairs, 
 * Return the string "valid" if no problems were found
 ***/
include_once($_SERVER['DOCUMENT_ROOT']."/inc/utils.php");

function validateForm($values, $required, $validate, $verify = array()) {
    $errors = array();

    // Validation pattens:
    $emailPattern = "^[_A-Za-z0-9-]+(\\.[_A-Za-z0-9-]+)*@[A-Za-z0-9-]+(\\.[A-Za-z0-9-]+)+$";

    // Check required fields have a value
    while(list($key,$field) = each($required)) {
        //print($field.", ".$values[$field]."<br>");
        if ($values[$field] == '') {
            $errors[$field] = "required";
        }
    }

    // Check validation fields
    if(in_array('email', $verify)) {
        // We have two email address inputs for the same value, to check for mis-keying - compare them.
        if ($values['email'] != $values['email_check']) {
            $errors['email'] = "emailConflict";
            $errors['email_check'] = "emailConflict";
        }
    }

    if(in_array('password', $verify)) {
        // We have two email password inputs for the same value, to check for mis-keying - compare them.
        if ($values['password'] != $values['password_check']) {
            $errors['password'] = "passwordConflict";
            $errors['password_check'] = "passwordConflict";
        }
    }

    // It's ok to overwrite error array "required" entries with more specific type validation,
    // as we only look at (and overwrite) fields with data in them using: `if ($values[$field] != "")`
    while(list($field,$type) = each($validate)) {
        //print($field.", ".$type."<br>");
        // If value is non-empty
        if ($values[$field] != "") {
            switch ($type) {
                case 'bit':
                    // 0/1 from a checkbox
                    if (!($values[$field] == '0' || $values[$field] == '1')) {
                        $errors[$field] = "bit";
                    }
                    break;

                case 'email':
                    // Email address
                    if (!ereg($emailPattern, $values[$field])) {
                        $errors[$field] = "email";
                    }
                    break;

                case 'dob':
                    // Date of birth - in format "yyyy-mm-dd".
                    // TODO: Set some limits relating to age - e.g. disallow 1 year-olds.
                    $y = substr($values[$field], 0, 4);
                    $m = substr($values[$field], 5, 2);
                    $d = substr($values[$field], 8, 2);
                    
                    if (!( ctype_digit($d) && ctype_digit($m) && ctype_digit($y) && checkdate($m, $d, $y) )) {
                        $errors[$field] = "dob";
                    }
                    break;

                case 'existing_email':
                    // Check the database for an existing login_name
                    include_once ($_SERVER['DOCUMENT_ROOT']."/db/checkUser.php");
                    if (!emailExists($values[$field])) {
                        $errors[$field] = "noExistingEmail";
                    }
                    break;

                case 'existing_user':
                    // Check the database for an existing login_name
                    include_once ($_SERVER['DOCUMENT_ROOT']."/db/checkUser.php");
                    if (usernameExists($values[$field])) {
                        $errors[$field] = "existingUser";
                    }
                    break;

                case 'gender':
                    // Gender
                    if (!ereg("[M|F]", $values[$field])) {
                        $errors[$field] = "gender";
                    }
                    break;

                case 'telNo':
                    // Telephone numbers
                    if (!preg_match("/\+?[() \d]+$/", $values[$field])) {
                        $errors[$field] = "telNo";
                    }
                    break;

                case 'password':
                    // Telephone numbers
                    if (strlen($values[$field]) < 6 || !ctype_alnum($values[$field])) {
                        $errors[$field] = "passwordQuality";
                    }
                    break;
                // Others?..
            }
        }
    }

    if (sizeof($errors)) {
        return $errors;
    } else{
        return "valid";
    }
}

/*** Check if $field is in $validateResults ***
 * If it is it represents a validation error, so write a message saying how it needs correcting
 ***/
function fieldValidMessage($field, $validateResult) {
    //print($field);
    //print_r($validateResult);
    if ($validateResult != 'valid' && array_key_exists($field, $validateResult)) {
        // Field listed, so is invalid - how so?
        switch ($validateResult[$field]) {
            case "required":
                return "<span class=\"error\">This field is required.</span>";
                break;
            case "bit":
                return "<span class=\"error\">Invalid data.</span>";
                break;
            case "email":
                return "<span class=\"error\">Valid email address required.</span>";
                break;
            case "emailConflict":
                return "<span class=\"error\">Email addresses must match.</span>";
                break;
            case "existingUser":
                return "<span class=\"error\">That username is not available.</span>";
                break;
            case "dob":
                return "<span class=\"error\">Valid date of birth required.</span>";
                break;
            case "gender":
                return "<span class=\"error\">Please state your gender.</span>";
                break;
            case "noExistingEmail":
                return "<span class=\"error\">Email address not found.</span>";
                break;
            case "noUser":
                return "<span class=\"error\">User does not exist.</span>";
                break;
            case "telNo":
                return "<span class=\"error\">Invalid telephone number, only numbers and <em><strong>+()</strong></em> permitted.</span>";
                break;
            case "passwordConflict":
                return "<span class=\"error\">Passwords must match.</span>";
                break;
            case "passwordQuality":
                return "<span class=\"error\">Password not valid.</span>";
                break;
        }
    }
}

/***
 * Insert asterisk for required fields
 ***/
function fieldMarkRequired($field, $requiredFields) {
    //echo $field;
    //echo $requiredFields;
    if (in_array($field, $requiredFields)) {
        return " *";
        //return true;
    }
}

/**
 * Encodes HTML safely (without UTF-8). Use instead of htmlentities.
 *
 * @param string $var
 * @return string
 */
function html_encode($var) {
    // See http://website-tickets.conted.ox.ac.uk/cgi-bin/trac.cgi/ticket/227
    //echo "encode: ".$var."<br/>";
    return htmlentities($var, ENT_QUOTES, 'UTF-8') ;
}
?>