PHP Classes
elePHPant
Icontem

File: validation.class.php

Recommend this page to a friend!
  Classes of Jeff Williams  >  Easy PHP Validation  >  validation.class.php  >  Download  
File: validation.class.php
Role: Class source
Content type: text/plain
Description: Class File
Class: Easy PHP Validation
Validate and fetch request and other value types.
Author: By
Last change: Added more functionality to check and format phone numbers, social security numbers, zip codes, convert dates and calculate difference, list timezones for a country, validate credit cards, filter and compare strings, get a valid IP address (even if the client is using a proxy), calculate times between dates, and much more.
Date: 8 months ago
Size: 62,187 bytes
 

Contents

Class file image Download
<?php
/**
 * This class encapsulates various validation functionality.
 *
 * PHP developers should always validate data on the server side to prevent
 * vulnerabilities and bugs. JavaScript alone is not adequate data validation
 * because it can easily be bypassed or turned off altogether.
 *
 * Feb 20, 2007 - Initial Release
 * Feb 28, 2007 - Vitaliy Bogdanets contributed regular expressions
 * Mar 12, 2007 - Restructured/renamed class, made static, added functionality
 * Mar 27, 2007 - Added GetBooleanValue method
 * Jun 19, 2007 - Added functionality and bug fix for getBooleanValue
 * Jun 29, 2007 - Changed checkMinimumLength to isTooShort and fixed help
 * Aug 18, 2010 - Added getRequestValue, getCurrentPageURL, and getCurrentPageName methods
 * Apr 04, 2018 - Added trim and minor code updates
 * Apr 22, 2018 - Added various useful formatting and validation functions
 * Apr 30, 2018 - Added credit card validation and other string/integer functions
 * May 17, 2018 - Added DateDifferenceDays, DateDifferenceMonths, DateDifferenceYears
 * May 23, 2018 - Added compareValues and containsValues that use arrays
 * May 28, 2018 - Added beginsWith, formatTitleCase, truncate, counts, plus fixes
 * Jul 02, 2018 - Added date and form functions and fixed some minor bugs
 *
 * @version 3.1
 * @author Jeff L. Williams
 */
class valid {

	// Default time zone used as a default parameter for date functions
	// Time zones are listed here: http://php.net/manual/en/timezones.php
	const DEFAULT_TIMEZONE = 'UTC'; // UTC?00:00 Coordinated Universal Time
	// const DEFAULT_TIMEZONE = 'America/New_York';    // Eastern
	// const DEFAULT_TIMEZONE = 'America/Chicago';     // Central
	// const DEFAULT_TIMEZONE = 'America/Denver';      // Mountain
	// const DEFAULT_TIMEZONE = 'America/Phoenix';     // Mountain no DST
	// const DEFAULT_TIMEZONE = 'America/Los_Angeles'; // Pacific

	/**
	 * Determines if a string begins with another string
	 *
	 * @param string $string The subject of the search
	 * @param string $find The string to look for
	 * @param boolean $caseSensitive Case sensitive?
	 * @return boolean TRUE if yes and FALSE if not
	 */
	public static function beginsWith($string, $find, $caseSensitive = true) {
		if (strlen($find) == 0) {
			return true;
		} else {
			if ($caseSensitive) {
				return (substr($string, strlen($find)) === $find);
			} else {
				return (strtoupper(substr($string, strlen($find)))
					=== strtoupper($find));
			}
		}
	}

	/**
	 * Converts the case of all keys in a multidimensional array to upper or lower
	 *
	 * @param array $array The array to modify
	 * @param integer $case [OPTIONAL] Use either CASE_UPPER or CASE_LOWER (default)
	 * @return array The array with keys changed
	 */
	public static function changeArrayKeyCaseRecursive($array, $case = CASE_LOWER) {
		return array_map(function ($item) use ($case) {
			if (is_array($item)) {
				$item = self::changeArrayKeyCaseRecursive($item, $case);
			}
			return $item;
		}, array_change_key_case($array, $case));
	}

	/**
	 * Returns a character at a given position
	 *
	 * @param string $string The subject of the search
	 * @param string $position The position of the character
	 * @return string The character at the specified position
	 */
	public static function charAt($string, $position) {
		if ($position < 0 || strlen($string) <= $position) {
			return '';
		} else {
			return $string[$position];
		}
	}

	/**
	 * Checks the length of a value
	 *
	 * @param string  $value The value to check
	 * @param integer $maxLength The maximum allowable length of the value
	 * @param integer $minLength [OPTIONAL] The minimum allowable length
	 * @return boolean TRUE if the requirements are met, FALSE if not
	 */
	public static function checkLength($value, $maxLength, $minLength = 0) {
		if (!(strlen($value) > $maxLength) && !(strlen($value) < $minLength)) {
			return true;
		} else {
			return false;
		}
	}

	/**
	 * Checks to make sure a folder path ends in a slash and add only if needed
	 *
	 * @param string  $value The value to check
	 * @return string Returns a path with a trailing slash
	 */
	public static function checkPathEndingSlash($path) {
		$is_unix = (strpos($path, '\\') === 0) ? false : true;
		$last_char  = substr($path, strlen($path) - 1, 1);
		if ($last_char != '/' && $last_char != '\\') {
			$path .= ($is_unix) ? '/' : '\\';
		}
		return $path;
	}

	/**
	 * Compares two values for equality
	 *
	 * @param string  $value1 First value to compare
	 * @param string  $value2 Second value to compare
	 * @param boolean $caseSensitive [OPTIONAL] TRUE if compare is case sensitive
	 * @return boolean TRUE if the values are equal and FALSE if not
	 */
	public static function compare($value1, $value2, $caseSensitive = false) {
		if ($caseSensitive) {
			return ($value1 == $value2 ? true : false);
		} else {
			if (strtoupper($value1) == strtoupper($value2)) {
				return true;
			} else {
				return false;
			}
		}
	}

	/**
	 * Determines if a string matches any item in a list of strings
	 *
	 * @example $match = compareValues('Blue', true, 'red', 'green', 'blue');
	 * @example $match = compareValues('blue', false, array('red', 'blue'));
	 *
	 * @param string $string The string to match
	 * @param boolean $ignoreCase TRUE if this is a case insensitive match
	 * @param array $find Either an array or list of one or more extra parameters
	 * @return boolean TRUE if found and FALSE if not
	 */
	public static function compareValues($string, $caseSensitive, $find) {

		// If no find array was used then use a list of parameters...
		if (!is_array($find)) {

			// If there are enough parameters to search with...
			if (func_num_args() > 2) {

				// Create the new $find_array variable using a list of parameters
				$find_array = func_get_args();

				// Remove the first two parameters
				array_shift($find_array);
				array_shift($find_array);

			} else { // Not enough parameters either

				// Create an empty array
				$find_array = array();

			}

		} else { // An array was specified to search with...

			// Set the array to the one passed in
			$find_array = $find;

		}

		if ($caseSensitive) {

			// Do a case-sensitive search
			return in_array($string, $find_array);

		} else {

			// Do a case-insensitive search
			return in_array(strtolower($string), array_map('strtolower', $find_array));

		}
	}

	/**
	 * Determines if a string contains another
	 *
	 * @param string $string The subject of the search
	 * @param string $find The string to look for
	 * @param boolean $caseSensitive Case sensitive?
	 * @return boolean TRUE if yes and FALSE if not
	 */
	public static function contains($string, $find, $caseSensitive = true) {
		if (strlen($find) == 0) {
			return true;
		} else {
			if ($caseSensitive) {
				return (strpos($string, $find) !== false);
			} else {
				return (strpos(strtoupper($string), strtoupper($find)) !== false);
			}
		}
	}

	/**
	 * Determines if a list of partial matches can be found in a string
	 *
	 * @example $match = containsValues('RED', true, 'ed', 'ee', 'ue');
	 * @example $match = containsValues('blue', false, array('ed', 'ee', 'ue'));
	 *
	 * @param string $string The string to search
	 * @param boolean $ignoreCase TRUE if this is a case insensitive match
	 * @param array $find Either an array or list of one or more extra parameters
	 * @return boolean TRUE if found and FALSE if not
	 */
	public static function containsValues($string, $caseSensitive, $find) {
		// If no find array was used then use a list of parameters...
		if (!is_array($find)) {

			// If there are enough parameters to search with...
			if (func_num_args() > 2) {

				// Create the new $find_array variable using a list of parameters
				$find_array = func_get_args();

				// Remove the first two parameters
				array_shift($find_array);
				array_shift($find_array);

			} else { // Not enough parameters either

				// Create an empty array
				$find_array = array();

			}

		} else { // An array was specified to search with...

			// Set the array to the one passed in
			$find_array = $find;

		}

		// Set the default values
		$return = false;

		// Loop through the array
		foreach ($find_array as $value) {

			// Case sensitive search
			if ($caseSensitive) {
				if (strpos($string, $value) !== false) {
					$return = true;
				}
			} else { // Case insensitive search
				if (strpos(strtoupper($string), strtoupper($value)) !== false) {
					$return = true;
				}
			}
		}

		// Return the outcome
		return $return;
	}

	/**
	 * Safely returns a value with a specified data type
	 *
	 * @param mixed $value The value to convert
	 * @param string $datatype [OPTIONAL] The datatype to return
	 * @param string $return_null [OPTIONAL] Returns null if value is null/empty
	 * @return mixed The return value
	 */
	public static function convertDataType($value, $datatype = '', $empty_to_null = true) {
		$return = null;
		if ($empty_to_null &&
			($value == null ||
			strtolower(trim($value)) == 'null' ||
			strlen(trim($value)) == 0)) {
			$return = null;
		} else {
			switch (strtolower(trim($datatype))) {
				case 'array':
				if (is_array($value)) {
					$return = $value;
				} else {
					$return = array($value);
				}
				break;

				case 'text':
				case 'string':
				$return = trim("$value");
				break;

				case 'int':
				case 'integer':
				$return = intval($value);
				break;

				case 'float':
				case 'double':
				case 'decimal':
				$return = self::getFloatValue($value);
				break;

				case 'bool':
				case 'boolean':
				$return = self::getBooleanValue($value);
				break;

				case 'date':
				case 'datetime':
				$return = self::convertToDate($value);
				if (empty($return)) {
					$return = null;
				}
				break;

				default:
				$return = $value;
				break;
			}
		}
		return $return;
	}

	/**
	 * Converts any English textual datetimes into a date object
	 *
	 * @param string $date Date string
	 * @param string $timezone [OPTIONAL] Default timezone
	 * @param boolean $forceFixDate [OPTIONAL] Force fixing all dates with dashes
	 * (this might be incompatible with some countries and may default to false)
	 * @return date Date if valid and false if not
	 */
	public static function convertToDate($date,
		$timezone = self::DEFAULT_TIMEZONE, $forceFixDate = true) {

		// If the input was already a DateTime object
		if ($date instanceof DateTime) {

			// Return the original DateTime object
			return $date;

		} else {

			// Set the timezone to default
			date_default_timezone_set($timezone);

			// If we need to use the date fix for United States dates
			// and there are characters as in 02-JAN-03 then...
			if ($forceFixDate || self::isTimeZoneInCountry($timezone, 'US')) {

				// U.S. dates with '-' do not convert correctly so replace them with '/'
				$datestring = self::fixUSDateString($date);

			} else { // No fix needed...

				// Use the date passed in
				$datestring = $date;

			}

			// Convert the string into a linux time stamp
			$timestamp = strtotime($datestring);

			// If this was a valid date
			if ($timestamp) {

				// Convert the UNIX time stamp into a date object
				$date = DateTime::createFromFormat('U', $timestamp);

			} else { // Not a valid date

				// This was not a valid date
				$date = false;

			}

			// Return the date object or false if invalid
			return $date;
		}
	}

	/**
	 * Count the number of characters in a string
	 *
	 * @param string $string The string to process
	 * @return integer Returns the count as a number
	 */
	public static function countCharacters($string) {
		return strlen($string);
	}

	/**
	 * Count the number of paragraphs (line breaks) in a string
	 *
	 * @param string $string The string to process
	 * @return integer Returns the count as a number
	 */
	public static function countParagraphs($string) {
		return preg_match_all('/([^\r\n]*[^ \r\n]+[^\r\n]*((\r|\n|\r\n)[^\r\n]*[^ \r\n]+[^\r\n]*)*)/m', $string);
	}

	/**
	 * Count the number of sentences in a string
	 *
	 * @param string $string The string to process
	 * @return integer Returns the count as a number
	 */
	public static function countSentences($string) {
		return preg_match_all('/[^\s](\.|\!|\?)(?!\w)/', $string);
	}

	/**
	 * Count the number of words in a string
	 *
	 * @param string $string The string to process
	 * @return integer Returns the count as a number
	 */
	public static function countWords($string) {
		return str_word_count($string);
	}

	/**
	 * Get the interval of time between two dates
	 *
	 * @param DateTime/String $date1 First date
	 * @param DateTime/String $date2 Second date
	 * @return interval Returns an interval object
	 */
	private static function dateDifference($date1, $date2) {
		// Make sure our dates are DateTime objects
		$datetime1 = self::convertToDate($date1);
		$datetime2 = self::convertToDate($date2);

		// If both variables were valid dates...
		if ($datetime1 && $datetime2) {

			// Get the time interval between the two dates
			return $datetime1->diff($datetime2);

		// The dates were invalid
		} else {

			// Return false
			return false;
		}
	}

	/**
	 * Get the number of days between two dates
	 *
	 * @param DateTime/String $date1 First date
	 * @param DateTime/String $date2 Second date
	 * @return integer Returns the number of days or false if invalid dates
	 */
	public static function dateDifferenceDays($date1, $date2) {
		// Get the difference between the two dates
		$interval = self::dateDifference($date1, $date2);
		if ($interval) {
			// Return the number of days
			return $interval->days;
		} else {
			// The passed in values were not dates
			return false;
		}
	}

	/**
	 * Get the number of hours between two dates
	 *
	 * @param DateTime/String $date1 First date
	 * @param DateTime/String $date2 Second date
	 * @return integer Returns the number of hours or false if invalid dates
	 */
	public static function dateDifferenceHours($date1, $date2) {
		// Get the difference between the two dates
		$interval = self::dateDifference($date1, $date2);
		if ($interval) {
			// Return the number of hours
			return ($interval->days * 24) + $interval->h;
		} else {
			// The passed in values were not dates
			return false;
		}
	}

	/**
	 * Get the number of minutes between two dates
	 *
	 * @param DateTime/String $date1 First date
	 * @param DateTime/String $date2 Second date
	 * @return integer Returns the number of minutes or false if invalid dates
	 */
	public static function dateDifferenceMinutes($date1, $date2) {
		// Get the difference between the two dates
		$interval = self::dateDifference($date1, $date2);
		if ($interval) {
			// Return the number of minutes
			return ((($interval->days * 24) + $interval->h) * 60) + $interval->i;
		} else {
			// The passed in values were not dates
			return false;
		}
	}

	/**
	 * Get the number of months between two dates
	 *
	 * @param DateTime/String $date1 First date
	 * @param DateTime/String $date2 Second date
	 * @return integer Returns the number of months or false if invalid dates
	 */
	public static function dateDifferenceMonths($date1, $date2) {
		// Get the difference between the two dates
		$interval = self::dateDifference($date1, $date2);
		if ($interval) {
			// Return the number of months
			return ($interval->y * 12) + $interval->m;
		} else {
			// The passed in values were not dates
			return false;
		}
	}

	/**
	 * Get the number of seconds between two dates
	 *
	 * @param DateTime/String $date1 First date
	 * @param DateTime/String $date2 Second date
	 * @return integer Returns the number of seconds or false if invalid dates
	 */
	public static function dateDifferenceSeconds($date1, $date2) {
		// Get the difference between the two dates
		$interval = self::dateDifference($date1, $date2);
		if ($interval) {
			// Return the number of minutes
			return ((((($interval->days * 24) + $interval->h) * 60) +
				$interval->i) * 60)  + $interval->s;
		} else {
			// The passed in values were not dates
			return false;
		}
	}

	/**
	 * Get the number of years between two dates
	 *
	 * @param DateTime/String $date1 First date
	 * @param DateTime/String $date2 Second date
	 * @return integer Returns the number of years or false if invalid dates
	 */
	public static function dateDifferenceYears($date1, $date2) {
		// Get the difference between the two dates
		$interval = self::dateDifference($date1, $date2);
		if ($interval) {
			// Return the number of years
			return $interval->y;
		} else {
			// The passed in values were not dates
			return false;
		}
	}

	/**
	 * HTML Encode a string value or array of values
	 * to stop any cross-site scripting attacks
	 * (STATIC method - use Template::encodeHTML)
	 *
	 * @param string/array $value The value(s) to encode
	 * @param string [OPTIONAL] $encoding The type of encoding
	 * @param string [OPTIONAL] $dateFormat Default date format for date values
	 * @return string/array HTML encoded value(s)
	 */
	public static function encodeHTML($value, $encoding = 'UTF-8', $dateFormat = 'm/d/Y') {
		if (is_array($value)) {
			$return = array();
			foreach ($value as $key => $data) {
					$return[$key] = self::encodeHTML($data, $encoding, $dateFormat);
			}
		} else {
			if (is_string($value)) {
				$return = htmlentities(trim($value),
					ENT_QUOTES | ENT_HTML5, $encoding);

			} elseif (is_bool($value)) {
				$return = ($value) ? 'true' : 'false';

			} elseif (is_numeric($value)) {
				$return = htmlentities("$value",
					ENT_QUOTES | ENT_HTML5, $encoding);

			} elseif ($value instanceof DateTime) {
				$return = htmlentities($value->format($dateFormat),
					ENT_QUOTES | ENT_HTML5, $encoding);

			} elseif (empty($value)) {
				$return = '';

			} else {
				$return = $value;
			}
		}
		return $return;
	}

	/**
	 * URL Encode a string value or array of values
	 * (STATIC method - use Template::encodeURL)
	 *
	 * @param string/array $value The value(s) to encode
	 * @param boolean [OPTIONAL] $raw TRUE for RFC 3986; FALSE use + for spaces
	 * @param string [OPTIONAL] $dateFormat Default date format for date values
	 * @return string/array HTML encoded value(s)
	 */
	public static function encodeURL($value, $raw = false, $dateFormat = 'Y-m-d') {
		if (is_array($value)) {
			$return = array();
			foreach ($value as $key => $data) {
					$return[$key] = self::encodeURL($data, $encoding, $dateFormat);
			}
		} else {
			if (is_string($value)) {
				if ($raw) {
					$return = rawurlencode(trim($value));
				} else {
					$return = urlencode(trim($value));
				}

			} elseif (is_bool($value)) {
				$return = ($value) ? 'yes' : 'no';

			} elseif (is_numeric($value)) {
				if ($raw) {
					$return = rawurlencode($value);
				} else {
					$return = urlencode($value);
				}

			} elseif ($value instanceof DateTime) {
				if ($raw) {
					$return = rawurlencode($value->format($dateFormat));
				} else {
					$return = urlencode($value->format($dateFormat));
				}

			} elseif (empty($value)) {
				return '';

			} else {
				$return = $value;
			}
		}
		return $return;
	}

	/**
	 * Determines if a string ends with another string
	 *
	 * @param string $string The subject of the search
	 * @param string $find The string to look for
	 * @param boolean $caseSensitive Case sensitive?
	 * @return boolean TRUE if yes and FALSE if not
	 */
	public static function endsWith($string, $find, $caseSensitive = true) {
		if (strlen($find) == 0) {
			return true;
		} else {
			if ($caseSensitive) {
				return (substr($string, -strlen($find)) === $find);
			} else {
				return (strtoupper(substr($string, -strlen($find)))
					=== strtoupper($find));
			}
		}
	}

	/**
	 * U.S. dates with - do not convert correctly in PHP so replace them with /
	 * (See comments http://php.net/manual/en/function.strtotime.php)
	 *
	 * @param string $date A date string
	 * @return string If the passed in value is a string, returns fixed date
	 *	               otherwise return the value passed in to the function
	 */
	public static function fixUSDateString($date) {
		// If the passed in value is a string and there are not alpha
		// characters that hold month names (as in 02-JAN-03) then...
		if (is_string($date) && !preg_match('/[a-z]/i', $date)) {

			// Replace '-' with '/'
			$return = str_replace('-', '/', $date);

		} else { // No fix needed...

			// Use the date passed in
			$return = $date;

		}
		return $return;
	}

	/**
	 * Formats a date
	 *
	 * @param string/date $date A string or date object
	 * @param string $format A valid PHP date format
	 *                       http://php.net/manual/en/function.date.php
	 * @param string $timezone [OPTIONAL] The timezone to use
	 * @return string The date formatted as a string or false if not a date
	 */
	public static function formatDate($date, $format, $timezone = self::DEFAULT_TIMEZONE) {

		// If the input is a date object
		if ($date instanceof DateTime) {

			// Format the date
			$output = $date->format($format);

		} else { // Treat it as a string

			// Convert the string to a date
			$new_date = self::convertToDate((string)$date, $timezone);

			// If the string was successfully converted into a date
			if ($new_date) {

				// Format it
				$output = $new_date->format($format);

			} else {

				// Return false
				$output = false;

			}
		}
		return $output;
	}

	/**
	 * Formats a phone number
	 *
	 * @param string $numbers An unformatted value
	 * @return string Returns the formatted value
	 */
	public static function formatPhoneNumber($numbers) {
		$numbers = self::stripNonNumeric($numbers);
		if (!$numbers) {
			return $numbers;
		} else {
			$regex  = '/^1?(?:[- .])?(\d{3})(?:[- .])?(\d{3})(?:[- .])?(\d{4})$/';
			$format = '($1) $2-$3';
			return preg_replace($regex, $format, $numbers);
		}
	}

	/**
	 * Formats a social security number
	 *
	 * @param string $numbers An unformatted value
	 * @return string Returns the formatted value
	 */
	public static function formatSSN($numbers) {
		$numbers = self::stripNonNumeric($numbers);
		$ssn     = '';
		if (strlen($numbers) > 3) {
			$ssn = substr($numbers, 0, 3) . '-' . substr($numbers, 3, 2);
		} else {
			$ssn = $numbers;
		}
		if (strlen($numbers) > 5) {
			$ssn .= '-' . substr($numbers, 5, 4);
		}
		return $ssn;
	}

	/**
	 * Formats text to be proper title case like news article titles
	 *
	 * @param string $title The string to capitalize
	 * @return string The formatted string
	 */
	public static function formatTitleCase($title) {

		// Our array of 'small words' which shouldn't be capitalized if
		// they aren't the first word
		$smallwordsarray = array(
			'a','an','and','as','at','but','by','en','for','if','in','nor','of','on','or','per','the','to');

		// Split the string into separate words
		$words = explode(' ', $title);

		foreach ($words as $key => $word) {
			// If this word is the first and not one of our small words, capitalize it
			if ($key == 0 or !in_array($word, $smallwordsarray)) {
				$words[$key] = ucwords($word);
			}
		}

		// Join the words back into a string
		return implode(' ', $words);
	}

	/**
	 * Formats a zip code
	 *
	 * @param string $numbers An unformatted value
	 * @return string Returns the formatted value
	 */
	public static function formatZipCode($numbers) {
		$numbers = self::stripNonNumeric($numbers);
		if (strlen($numbers) > 5) {
			return substr($numbers, 0, 5) . '-' . substr($numbers, 5, 4);
		} else {
			return $numbers;
		}
	}

	/**
	 * Combine first, middle, and last names without extra spaces in-between
	 *
	 * @param string $first First name
	 * @param string $middle Middle name or initial
	 * @param string $last Last Name
	 * @return string The full name
	 */
	public static function fullName($first, $middle, $last) {
		If (strlen(trim($middle)) == 1) {
			$middle = trim($middle) . '.';
		}
		$full = trim($first . ' ' . $middle . ' ' . $last);
		return self::stripExcessWhitespace($full);
	}

	/**
	 * Generate a random string of specified length from a set of specified characters
	 *
	 * @param integer $size Default size is 30 characters.
	 * @param string $chars The characters to use for randomization.
	 * @return string Returns the random generated string
	 */
	public static function generateRandomString($size = 30,
		$chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789') {

		$string = '';
		$length = strlen($chars);
		for ($i = 0; $i < $size; $i++) {
			$string .= $chars{rand(0, $length)};
		}
		return $string;
	}

	/**
	 * Get the age of a person using their birth date
	 *
	 * @param string/object $dob Date string or DateTime object
	 * @param string $timezone Default timezone
	 * @return int The age in number of years
	 */
	public static function getAge($dob, $timezone = self::DEFAULT_TIMEZONE) {
		$date     = self::convertToDate($dob, $timezone);
		$now      = new DateTime();
		$interval = $now->diff($date);
		return $interval->y;
	}

	/**
	 * Safely returns an array element with a specified data type
	 * without generating any warning if an element doesn't exist
	 *
	 * @param array $array The array to use
	 * @param string $key The array key to use
	 * @param string $datatype [OPTIONAL] The datatype to return
	 * @return mixed The return value
	 */
	public static function getArrayElementValue($array, $key, $datatype = '') {
		$return = null;
		if (isset($array[$key])) {
			$return = convertDataType($array[$key], $datatype, false);
		}
		return $return;
	}

	/**
	 * Converts any value of any datatype into boolean (true or false)
	 *
	 * @param any $value Value to analyze for TRUE or FALSE
	 * @param any $includeTrueValue [OPTIONAL] return TRUE if the value equals this
	 * @param any $includeFalseValue [OPTIONAL] return FALSE if the value equals this
	 * @return boolean Returns TRUE or FALSE
	 */
	public static function getBooleanValue($value, $includeTrueValue = null, $includeFalseValue = null) {

		if (!(is_null($includeTrueValue)) && $value == $includeTrueValue) {
			return true;
		} elseif (!(is_null($includeFalseValue)) && $value == $includeFalseValue) {
			return false;
		} else {
			if (is_array($value)) {
				return empty($value);
			} elseif (gettype($value) == 'boolean') {
				if ($value == true) {
					return true;
				} else {
					return false;
				}
			} elseif (is_numeric($value)) {
				if ($value > 0) {
					return true;
				} else {
					return false;
				}
			} else {
				$cleaned = strtoupper(self::trim($value));

				if ($cleaned == 'ON') {
					return true;
				} elseif ($cleaned == 'SELECTED' || $cleaned == 'CHECKED') {
					return true;
				} elseif ($cleaned == 'YES' || $cleaned == 'Y') {
					return true;
				} elseif ($cleaned == 'TRUE' || $cleaned == 'T') {
					return true;
				} else {
					return false;
				}
			}
		}
	}

	/**
	 * Get the IP address of the current client (must be used on a server).
	 * $_SERVER['REMOTE_ADDR'] sometimes does not returns the correct ip address
	 * of the visitor. This can be occur due to reasons like the user is behind a
	 * proxy, your apache server is behind a reverse proxy (e.g. varnish), etc.
	 *
	 * @return string Returns the IP address of the visitor
	 */
	public static function getClientIPAddress() {
		if (!empty($_SERVER['HTTP_CLIENT_IP'])) {
			$ipaddress = $_SERVER['HTTP_CLIENT_IP'];
		} else if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
			$ipaddress = $_SERVER['HTTP_X_FORWARDED_FOR'];
		} else if (!empty($_SERVER['HTTP_X_FORWARDED'])) {
			$ipaddress = $_SERVER['HTTP_X_FORWARDED'];
		} else if (!empty($_SERVER['HTTP_FORWARDED_FOR'])) {
			$ipaddress = $_SERVER['HTTP_FORWARDED_FOR'];
		} else if (!empty($_SERVER['HTTP_FORWARDED'])) {
			$ipaddress = $_SERVER['HTTP_FORWARDED'];
		} else if (!empty($_SERVER['REMOTE_ADDR'])) {
			$ipaddress = $_SERVER['REMOTE_ADDR'];
		} else {
			$ipaddress = 'UNKNOWN';
		}
		return $ipaddress;
	}

	/**
	 * Get the value for a cookie by the cookie name
	 *
	 * @param string  $name The name of the cookie
	 * @param string  $default [OPTIONAL] A default if the value is empty
	 * @return string The cookie value
	 */
	public static function getCookieValue($name, $default = '') {
		if (isset($_COOKIE[$name])) {
			return self::trim($_COOKIE[$name]);
		} else {
			return $default;
		}
	}

	/**
	 * Validates a credit card and returns what type of card it is
	 *
	 * @param string $cardnumber The credit card number with or without dashes/spaces
	 * @return string/boolean Returns the card type if valid, otherwise FALSE
	 */
	public static function getCreditCardType($cardnumber) {
		// Strip all non-numeric input
		$number = preg_replace('/[^0-9]/i', '', $cardnumber);

		// Set our regex for each card type
		$cardtypes = array(
			'visa' => '/^4[0-9]{12}(?:[0-9]{3})?$/',
			'mastercard' => '/^(?:5[1-5][0-9]{2}|222[1-9]|22[3-9][0-9]|2[3-6][0-9]{2}|27[01][0-9]|2720)[0-9]{12}$/',
			'amex' => '/^3[47][0-9]{13}$/',
			'discover' => '/^6(?:011|5[0-9]{2})[0-9]{12}$/',
			'jcb' => '/^(?:2131|1800|35\d{3})\d{11}$/',
			'maestro' => '/^(?:5[0678]\d\d|6304|6390|67\d\d)\d{8,15}$/',
			'solo' => '/^((?:6334|6767)\d{12}(?:\d\d)?\d?)$/',
			'switch' => '/^(?:(?:(?:4903|4905|4911|4936|6333|6759)\d{12})|(?:(?:564182|633110)\d{10})(\d\d)?\d?)$/',
			'dinersclub' => '/^3(?:0[0-5]|[68][0-9])[0-9]{11}$/'
		);

		// Set the default type if none found
		$type = false;

		// Loop through the card types
		foreach ($cardtypes as $cardtype => $regex) {

			// If a match is found...
			if (preg_match($regex, $number)) {

				// Save the type of card
				$type = $cardtype;

				// No need to keep processing regex
				break;
			}
		}

		// Return the result
		return $type;
	}

	/**
	 * Returns the name of the current page (i.e. sample.php)
	 *
	 * @return string The page name
	 */
	public static function getCurrentPageName($lowercase = false, $extension = true) {
		if ($extension) {
			$return = pathinfo($_SERVER['PHP_SELF'], PATHINFO_BASENAME);
		} else {
			$return = pathinfo($_SERVER['PHP_SELF'], PATHINFO_FILENAME);
		}
		return ($lowercase ? strtolower($return) : $return);
	}

	/**
	 * Returns the name of the current URL (i.e. https://example.com/dir/sample.php)
	 *
	 * @return string The URL path
	 */
	public static function getCurrentPageURL($lowercase = false) {
		$pageURL = self::getCurrentSite() . $_SERVER['REQUEST_URI'];
		return ($lowercase ? strtolower($pageURL) : $pageURL);
	}

	/**
	 * Returns the name of the current URL (i.e. https://example.com
	 *
	 * @return string The URL path
	 */
	public static function getCurrentSite($lowercase = false) {
		$url = 'http';
		if (isset($_SERVER['HTTPS'])) {
			if ($_SERVER['HTTPS'] == 'on') {
				$url .= 's';
			}
		}
		$url .= '://';
		if ($_SERVER['SERVER_PORT'] != '80' && $_SERVER['SERVER_PORT'] != '443') {
			$url .= $_SERVER['SERVER_NAME'] . ':' . $_SERVER['SERVER_PORT'];
		} else {
			$url .= $_SERVER['SERVER_NAME'];
		}
		return ($lowercase ? strtolower($url) : $url);
	}

	/**
	 * Returns the value if one exists, otherwise returns a default value
	 * (This also works on NULL values)
	 *
	 * @param string  $name The value to check
	 * @param string  $default A default if the value is empty
	 * @return string Returns the original value unless this value is
	 *                empty - in which the default is returned
	 */
	public static function getDefaultOnEmpty($value, $default) {
		if (self::hasValue($value)) {
			return $value;
		} else {
			return $default;
		}
	}

	/**
	 * Converts a string into a floating point value
	 *
	 * example echo getFloatValue('$1,234,567.89');
	 *
	 * @param string $string String to modify
	 * @return string Modified string
	 */
	public static function getFloatValue($string) {
		$value = preg_replace('/[^0-9.]/i', '', $string);
		if (is_numeric($value)) {
			return floatval($value);
		} else {
			return 0;
		}
	}

	/**
	 * Get a POST or GET value by a form element name
	 *
	 * @param string $name The name of the POST or GET data
	 * @param string $default [OPTIONAL] A default if the value is empty
	 * @param string $method [OPTIONAL] INPUT_GET, INPUT_POST, or INPUT_REQUEST for both
	 * @return string The value of the form element
	 */
	public static function getFormValue($name, $default = '', $method = INPUT_REQUEST) {
		if ($method != INPUT_GET && isset($_POST[$name])) {
			return self::trim($_POST[$name]);
		} else {
			if ($method != INPUT_POST && isset($_GET[$name])) {
				return self::trim($_GET[$name]);
			} else {
				return $default;
			}
		}
	}

	/**
	 * Get a GET value by a form element name
	 *
	 * @param string $name The name of the GET data
	 * @param string $default [OPTIONAL] A default if the value is empty
	 * @return string The value of the form element
	 */
	public static function getFormGet($name, $default = '') {
		return this::getFormValue($name, $default, INPUT_GET);
	}

	/**
	 * Get a POST value by a form element name
	 *
	 * @param string $name The name of the POST data
	 * @param string $default [OPTIONAL] A default if the value is empty
	 * @return string The value of the form element
	 */
	public static function getFormPost($name, $default = '') {
		return this::getFormValue($name, $default, INPUT_POST);
	}

	/**
	 * Returns the last day of this month or for a given date
	 *
	 * @param string/DateTime $date [OPTIONAL] A date
	 * @return integer The number of the last day of the month
	 */
	public static function getLastDayOfMonth($date = 'Today') {
		$datetime = self::convertToDate($date);
		if ($datetime) {
			$return = intval($datetime->format('t'));
		} else {
			$return = false;
		}
		return $return;
	}

	/**
	 * Checks an array to see if required keys exist and returns missing keys
	 *
	 * @param array $array The array to check
	 * @param array $required_keys An array holding a list of required keys
	 * @param boolean [OPTIONAL] $keys_uppercase If CASE_UPPER or CASE_LOWER,
	 *	the $required_keys parameter will be converted to uppercase or lowercase
	 * @return array An array containing any missing fields
	 *	             Empty array() if no keys were found missing
	 *	             False if not an array
	 */
	public static function getMissingArrayKeys($array, $required_keys, $keys_case = false) {
		$keys = array();
		if (!is_array($array) || !is_array($required_keys)) {
			$keys = false;
		} else {
			foreach ($required_keys as $key) {
				if ($keys_case == CASE_UPPER) {
					if (!array_key_exists(strtoupper($key), $array)) {
						$keys[] = $key;
					}
				} elseif ($keys_case == CASE_LOWER) {
					if (!array_key_exists(strtolower($key), $array)) {
						$keys[] = $key;
					}
				} else {
					if (!array_key_exists($key, $array)) {
						$keys[] = $key;
					}
				}
			}
		}
		return $keys;
	}

	/**
	 * Get the value for a request
	 *
	 * @param string  $name The name of the request item
	 * @param string  $default [OPTIONAL] A default if the value is empty
	 * @return string The request value
	 */
	public static function getRequestValue($name, $default = '') {
		if (isset($_REQUEST[$name])) {
			return self::trim($_REQUEST[$name]);
		} else {
			return $default;
		}
	}

	/**
	 * Get the value for a session by the session name
	 *
	 * @param string  $name The name of the session
	 * @param string  $default [OPTIONAL] A default if the value is empty
	 * @return string The session value
	 */
	public static function getSessionValue($name, $default = '') {
		if (isset($_SESSION[$name])) {
			return self::trim($_SESSION[$name]);
		} else {
			return $default;
		}
	}

	/**
	 * Get a list of time zones for a specified country
	 *
	 * @param string $country The name of the country
	 * @return array Returns an array with a list of valid time zones
	 */
	public static function getTimeZonesInCountry($country) {
		// Get an array of all the timezones for the specified country
		return DateTimeZone::listIdentifiers(DateTimeZone::PER_COUNTRY, $country);
	}

	/**
	 * Get an array of unique characters used in a string.
	 * (Also works with multibyte characters)
	 *
	 * @param string $string String to modify
	 * @param boolean $returnAsArray True if results should be returned as array
	 * @return string/array Modified string
	 */
	public static function getUniqueChars($string, $returnAsArray = true) {
		$unique = array_unique(preg_split('/(?<!^)(?!$)/u', $string));
		if (!$returnAsArray) {
			$unique = implode('', $unique);
		}
		return $unique;
	}

	/**
	 * Get a POST, GET, Cookie, or Session value by name
	 * (in that order - if one doesn't exist, the next is tried)
	 *
	 * @param string  $name The name of the POST, GET, Session, or Cookie
	 * @param string  $default [OPTIONAL] A default if the value is empty
	 * @return string The value from that element
	 */
	public static function getValue($name, $default = '') {
		if (isset($_REQUEST[$name])) {
			return self::trim($_REQUEST[$name]);
		} else {
			if (isset($_SESSION[$name])) {
				return self::trim($_SESSION[$name]);
			} else {
				return $default;
			}
		}
	}

	/**
	 * Checks an array to see if required keys exist
	 *
	 * @param array $array The array to check
	 * @param array $required_keys An array holding a list of required keys
	 * @param boolean [OPTIONAL] $keys_uppercase If CASE_UPPER or CASE_LOWER,
	 *	the $required_keys parameter will be converted to uppercase or lowercase
	 * @return boolean TRUE if all keys are found, otherwise FALSE
	 */
	public static function hasArrayKeys($array, $required_keys, $keys_case = false) {
		$valid = true;
		if (!is_array($array)) {
			$valid = false;
		} else {
			foreach ($required_keys as $key) {
				if ($keys_case == CASE_UPPER) {
					if (!array_key_exists(strtoupper($key), $array)) {
						$valid = false;
					}
				} elseif ($keys_case == CASE_LOWER) {
					if (!array_key_exists(strtolower($key), $array)) {
						$valid = false;
					}
				} else {
					if (!array_key_exists($key, $array)) {
						$valid = false;
					}
				}
			}
		}
		return $valid;
	}

	/**
	 * Checks to see if a variable contains a value
	 *
	 * @param string  $value The value to check
	 * @return boolean TRUE if a value exists, FALSE if empty
	 */
	public static function hasValue($value) {
		return !(self::isEmpty($value));
	}

	/**
	 * Determines if a string is alpha only
	 *
	 * @param string $value The value to check for alpha (letters) only
	 * @param string $allow Any additional allowable characters
	 * @return boolean
	 */
	public static function isAlpha($value, $allow = '') {
		if (preg_match('/^[a-zA-Z' . $allow . ']+$/', $value)) {
			return true;
		} else {
			return false;
		}
	}

	/**
	 * Determines if a string is alpha-numeric
	 *
	 * @param string $value The value to check
	 * @return boolean TRUE if there are letters and numbers, FALSE if other
	 */
	public static function isAlphaNumeric($value) {
		if (preg_match('/^[A-Za-z0-9 ]+$/', $value)) {
			return true;
		} else {
			return false;
		}
	}

	/**
	 * Determines if a string contains a valid date
	 *
	 * @param string $value The value to inspect
	 * @param boolean $us_fix Fix U.S. dates?
	 * @return boolean TRUE if the value is a date, FALSE if not
	 */
	public static function isDate($value, $timezone = self::DEFAULT_TIMEZONE) {

		// If it's a date time object...
		if ($value instanceof DateTime) {

			// It's a date
			$return = true;

		} else {

			// If we need to use the date fix for United States dates
			// and there are no characters as in 02-JAN-03 then...
			if (self::isTimeZoneInCountry($timezone, 'US') &&
				is_string($value) && !preg_match('/[a-z]/i', $value)) {

				// U.S. dates with '-' do not convert correctly so replace them with '/'
				$date = str_replace('-', '/', $value);

			} else { // No fix needed...

				// Use the date passed in
				$date = $value;

			}

			// Try to convert it as a string
			$return = (bool)strtotime((string)$date);
		}

		return $return;
	}

	/**
	 * Checks for a valid email address
	 *
	 * @param string  $email The value to validate as an email address
	 * @return boolean TRUE if it is a valid email address, FALSE if not
	 */
	public static function isEmail($email) {
		$pattern = '/^([a-zA-Z0-9])+([\.a-zA-Z0-9_-])*@([a-zA-Z0-9_-])+(\.[a-zA-Z0-9_-]+)+/';

		if (preg_match($pattern, $email)) {
			return true;
		} else {
			return false;
		}
	}

	/**
	 * Checks to see if a variable contains no value (not even a zero)
	 *
	 * @param string  $value The value to check
	 * @return boolean TRUE if a value exists, FALSE if empty
	 */
	public static function isEmpty($value) {
		if (!isset($value)) {
			return true;
		} elseif (is_null($value)) {
			return true;
		} elseif (is_string($value) && strlen($value) == 0) {
			return true;
		} elseif (is_array($value) && count($value) == 0) {
			return true;
		} else {
			return false;
		}
	}

	/**
	 * Checks to see if a variable is a floating point number
	 *
	 * @param float $number The value to check
	 * @return boolean TRUE if the value is a number, FALSE if not
	 */
	public static function isFloat($number) {
		if (is_float($number)) {
			return true;
		} else {
			$pattern = '/^[-+]?(((\\\\d+)\\\\.?(\\\\d+)?)|\\\\.\\\\d+)([eE]?[+-]?\\\\d+)?$/';
    		return (!is_bool($number) &&
				(is_float($number) || preg_match($pattern, trim($number))));
		}
	}

	/**
	 * Checks for a valid internet URL
	 *
	 * @param string $value The value to check
	 * @return boolean TRUE if the value is a valid URL, FALSE if not
	 */
	public static function isInternetURL($value) {
		if (preg_match('/^http(s)?:\/\/([\w-]+\.)+[\w-]+(\/[\w- .\/?%&=]*)?$/i', $value)) {
			return true;
		} else {
			return false;
		}
	}

	/**
	 * Checks for a valid IP Address
	 *
	 * @param string $value The value to check
	 * @return boolean TRUE if the value is an IP address, FALSE if not
	 */
	public static function isIPAddress($value) {
		$pattern = '/^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.'
			. '(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.'
			. '(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.'
			. '(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/i';
		if (preg_match($pattern, $value)) {
			return true;
		} else {
			return false;
		}
	}

	/**
	 * Checks to see if a variable is a number
	 *
	 * @param integer $number The value to check
	 * @return boolean TRUE if the value is a number, FALSE if not
	 */
	public static function isNumber($number) {
		if (preg_match('/^\-?\+?[0-9e1-9]+$/', $number)) {
			return true;
		} else {
			return false;
		}
	}

	/**
	 * Checks for a valid US phone number
	 *
	 * @param string $value The value to inspect
	 * @return boolean TRUE if the value is a phone number or FALSE if not
	 */
	public static function isPhoneNumber($value) {
		if (preg_match(
			'/^(?:(?:\+?1\s*(?:[.-]\s*)?)?(?:\(\s*([2-9]1[02-9]|' .
			'[2-9][02-8]1|[2-9][02-8][02-9])\s*\)|([2-9]1[02-9]|' .
			'[2-9][02-8]1|[2-9][02-8][02-9]))\s*(?:[.-]\s*)?)?' .
			'([2-9]1[02-9]|[2-9][02-9]1|[2-9][02-9]{2})\s*(?:[.-]\s*)?' .
			'([0-9]{4})(?:\s*(?:#|x\.?|ext\.?|extension)\s*(\d+))?$/i', $value)) {
			return true;
		} else {
			return false;
		}
	}

	/**
	 * Checks to see if a variable is a social security number
	 *
	 * @param integer $ssn The value to check
	 * @param integer $strict If true, there are additional checks
	 * @return boolean TRUE if the value is a social security number, FALSE if not
	 */
	public static function isSSN($ssn, $strict = false) {
		if (preg_match('/^\d{3}\-?\d{2}\-?\d{4}$/', $ssn)) {
			if ($strict) {
				// None of the digit groups can be all zeros.
				// Area number 666 is unassigned.
				// Numbers from 987-65-4320 to 987-65-4329 are reserved for use in advertisements.
				// Many SSNs have been invalidated by use in advertising.
				// Numbers above 772 are currently unassigned.
				$regex = '/^((000|666)\-?\d{2}\-?\d{4}|\d{3}\-?00\-?\d{4}|\d{3}\-?' .
					'\d{2}\-?0000|987\-?65\-?432\d{1}|042\-?10\-?3580|062\-?36\-?' .
					'0749|078\-?05\-?1120|095\-?07\-?3645|128\-?03\-?6045|135\-?01\-?' .
					'6629|141\-?18\-?6941|165\-?(16|18|20|22|24)\-?7999|189\-?09\-?' .
					'2294|212\-?09\-?(7694|9999|219\-?09\-?9999|306\-?30\-?' .
					'2348|308\-?12\-?5070|468\-?28\-?8779|549\-?24\-?1889)$/';
				if (preg_match($regex, $ssn) || substr($ssn, 0, 3) > 772) {
					return false;
				} else {
					return true;
				}
			} else {
				return true;
			}
		} else {
			return false;
		}
	}

	/**
	 * Checks for a two character state abbreviation
	 *
	 * @param string $value The value to inspect
	 * @return boolean TRUE if the value is a 2 letter state abbreviation
	 *                 FALSE if the value is anything else
	 */
	public static function isStateAbbreviation($value) {
		if (preg_match('/^[A-Z][A-Z]$/i', $value)) {
			return true;
		} else {
			return false;
		}
	}

	/**
	 * Determines if a time zone is in the specified country
	 *
	 * @param string $timezone Time zone from http://php.net/manual/en/timezones.php
	 * @param string $country The name of the country
	 * @return boolean TRUE if in the country and FALSE if not
	 */
	public static function isTimeZoneInCountry($timezone, $country) {
		// Get an array of all the timezones in the U.S.
		$timezone_identifiers = array_map('strtolower',
			DateTimeZone::listIdentifiers(DateTimeZone::PER_COUNTRY, $country));

		// Determine if the passed in time zone is in that list
		return in_array(strtolower(trim($timezone)), $timezone_identifiers);
	}

	/**
	 * Check to see if a string length is too long
	 *
	 * @param string $value The string value to check
	 * @param integer $maximumLength The maximum allowed length
	 * @return boolean TRUE if the length is too long
	 *                 FALSE if the length is acceptable
	 */
	public static function isTooLong($value, $maximumLength) {
		if (strlen($value) > $maximumLength) {
			return true;
		} else {
			return false;
		}
	}

	/**
	 * Check to see if a string length is too short
	 *
	 * @param string $value The string value to check
	 * @param integer $maximumLength The minimum allowed length
	 * @return boolean TRUE if the length is too short
	 *                 FALSE if the length is acceptable
	 */
	public static function isTooShort($value, $minimumLength) {
		if (strlen($value) < $minimumLength) {
			return true;
		} else {
			return false;
		}
	}

	/**
	 * Checks to see if a variable is an unsigned number
	 *
	 * @param integer $number The value to inspect
	 * @return boolean TRUE if the value is a number without a sign
	 *                 and FALSE if a sign exists
	 */
	public static function isUnsignedNumber($number) {
		if (preg_match('/^\+?[0-9]+$/', $number)) {
			return true;
		} else {
			return false;
		}
	}

	/**
	 * Checks a credit card number to see if it is valid using the Luhn checksum
	 *
	 * @param string $cardnumber The credit card number with or without dashes/spaces
	 * @return boolean TRUE if card checksum passes and FALSE if otherwise
	 */
	public static function isValidCreditCardNumber($cardnumber) {
		// Strip all non-numeric input
		$number    = preg_replace('/[^0-9]/i', '', $cardnumber);
		$length    = strlen($number);

		// Reverse the order of the number
		$revNumber = strrev($number);

		// Loop through and calculate the Luhn checksum
		$sum       = '';
		for ($i = 0; $i < $length; $i++) {
			$sum .= $i & 1 ? $revNumber[$i] * 2 : $revNumber[$i];
		}

		// Return the result as a boolean
		return array_sum(str_split($sum)) % 10 === 0;
	}

	/**
	 * Checks to see if a variable is a valid JSON string
	 *
	 * @param string $string The value to check
	 * @return boolean TRUE if the value is JSON, FALSE if not
	 */
	public static function isValidJSON($string) {
		@json_decode($string);
		return (json_last_error() == JSON_ERROR_NONE);
	}

	/**
	 * Checks to see if a string contains valid XML
	 *
	 * @param string $string The value to check
	 * @return boolean TRUE if the value is XML, FALSE if not
	 */
	public static function isValidXML($string) {
		libxml_use_internal_errors(true);
		$doc = false;
		$doc = @simplexml_load_string($string);
		if ($doc !== false) {
			$errors = false;
		} else {
			// $errors = libxml_get_errors();
			$errors = true;
		}
	   	libxml_clear_errors();
		return (!$errors);
	}

	/**
	 * Checks to see if a value contains a 5 or 9 digit zip code
	 *
	 * @param string $value The value to inspect
	 * @return boolean TRUE if zip code, otherwise FALSE
	 */
	public static function isZipCode($value) {
		$numbers = self::stripNonNumeric($value);
		if (strlen($numbers) == 5 || strlen($numbers) == 9) {
			$formatted = self::formatZipCode($numbers);
			if ($value == $numbers || $value == $formatted) {
				return true;
			} else {
				return false;
			}
		} else {
			return false;
		}
	}

	/**
	 * Returns the left part of a string
	 *
	 * @param string $string The string to be divided
	 * @param int $length The number of characters to return
	 * @return string The extracted string
	 */
	public static function left($string, $length) {
		return substr($string, 0, $length);
	}

	/**
	 * Builds a DateTime object from date parts
	 *
	 * @param integer $day [OPTIONAL] The day or if not specified today
	 * @param integer $month [OPTIONAL] The month or if not specified this month
	 * @param integer $year [OPTIONAL] The year or if not specified this year
	 * @return DateTime Returns a DateTime object with the specified date
	 */
	public static function makeDate($day = false, $month = false, $year = false) {
		if ($day === false || $month === false || $year === false) {
			$date_parts  = explode('-', self::convertToDate('Today')->format('d-m-Y'));
			if ($day === false) {
				$day = $date_parts[0];
			}
			if ($month === false) {
				$month = $date_parts[1];
			}
			if ($year === false) {
				$year =  $date_parts[2];
			}
		}
		return self::convertToDate($year . '/' . $month . '/' . $day);
	}

	/**
	 * Returns the current date and time as a DateTime object or formatted string
	 *
	 * @param string $format [OPTIONAL] If specified, will format the date as a string
	 *                       If not specified, returns a DateTime object
	 *	                     (example: 'Y-m-d H:i:s')
	 * @param string $timezone [OPTIONAL] Default timezone
	 * @return DateTime/string The DateTime object or a formatted string
	 */
	public static function now($format = false, $timezone = self::DEFAULT_TIMEZONE) {
		$now = self::convertToDate('Now', $timezone);
		if ($format) {
			return $now->format($format);
		} else {
			return $now;
		}
	}

	/**
	 * Adds th, st, nd, rd, th to the end of a number
	 *
	 * @param integer $number A number
	 * @return string A string with the modified number
	 */
	public static function ordinal($number) {
		$test_c = abs($number) % 10;
		$ext    = ((abs($number) % 100 < 21 && abs($number) % 100 > 4) ? 'th'
			: (($test_c < 4) ? ($test_c < 3) ? ($test_c < 2) ? ($test_c < 1)
				? 'th' : 'st' : 'nd' : 'rd' : 'th'));
		return $number . $ext;
	}

	/**
	 * Replace the last occurrence of a string.
	 *
	 * @param string $search String to search for
	 * @param string $replace String to replace with
	 * @param string $subject String to operate on
	 * @return string Replaces text
	 */
	public static function replaceLast($search, $replace, $subject) {
		$lenOfSearch = strlen($search);
		$posOfSearch = strrpos($subject, $search);
		return substr_replace($subject, $replace, $posOfSearch, $lenOfSearch);
	}

	/**
	 * Returns the right part of a string
	 *
	 * @param string $string The string to be divided
	 * @param int $length The number of characters to return
	 * @return string The extracted string
	 */
	public static function right($string, $length) {
		if ($length < 1) {
			return '';
		} else {
			return substr($string, -$length);
		}
	}

	/**
	 * [This function is depreciated - Use formatDate instead]
	 * Formats a date without errors
	 *
	 * @param string/date $date A string or date object
	 * @param string $format A valid PHP date format
	 *                       http://php.net/manual/en/function.date.php
	 * @param boolean $us_fix Fix U.S. dates?
	 * @return string The date formatted as a string
	 */
	public static function safeDateFormat($date, $format, $timezone = self::DEFAULT_TIMEZONE) {
		// This function is depreciated - Use formatDate instead
		return self::formatDate($date, $format, $timezone);
	}

	/**
	 * [This function is depreciated - Use encodeHTML instead]
	 * HTML Encode a string value or array of values
	 * to stop any cross-site scripting attacks
	 *
	 * @param string/array $value The value(s) to encode
	 * @param string [OPTIONAL] $encoding The type of encoding
	 * @return string/array HTML encoded value(s)
	 */
	public static function safeEncode($value, $encoding = 'UTF-8') {
		// This function is depreciated - Use encodeHTML instead
		return self::encodeHTML($value, $encoding);
	}


	/**
	 * [This function is depreciated - Use trim instead]
	 * Trims a value if it is a string
	 *
	 * @param unknown_type $value A value to trim
	 * @return unknown_type The value passed in; if a string, then it is trimmed
	 */
	public static function safeTrim($value) {
		// This function is depreciated - Use trim instead
		return self::trim($value);
	}

	/**
	 * Removes any dangerous javascript, HTML, or CSS code in a string
	 *
	 * @param String $input String to be sanitized
	 * @return String Sanitized string
	 */
	public static function sanitize($input) {
		$search = array(
			'@<script[^>]*?>.*?</script>@si',   // Strip out javascript
			'@<[\/\!]*?[^<>]*?>@si',            // Strip out HTML tags
			'@<style[^>]*?>.*?</style>@siU',    // Strip style tags properly
			'@<![\s\S]*?--[ \t\n\r]*>@'         // Strip multi-line comments
		);
		return preg_replace($search, '', $input);
	}

	/**
	 * Determines if a string starts with another string
	 *
	 * @param string $string The subject of the search
	 * @param string $find The string to look for
	 * @param boolean $caseSensitive Case sensitive?
	 * @return boolean TRUE if yes and FALSE if not
	 */
	public static function startsWith($string, $find, $caseSensitive = true) {
		$length = strlen($find);
		if ($caseSensitive) {
			return !strncmp($string, $find, $length);
		} else {
			return !strncmp(strtoupper($string), strtoupper($find), $length);
		}
	}

	/**
	 * Transform two or more spaces into just one space.
	 *
	 * @param string $string String to modify
	 * @return string Modified string
	 */
	public static function stripExcessWhitespace($string) {
		return preg_replace('/  +/', ' ', $string);
	}

	/**
	 * Remove all characters except letters.
	 *
	 * @param string $string String to modify
	 * @return string Modified string
	 */
	public static function stripNonAlpha($string) {
		return preg_replace('/[^a-z]/i', '', $string);
	}

	/**
	 * Remove all characters except letters, hyphens, and spaces.
	 * (Most commonly used for names)
	 *
	 * @param string $string String to modify
	 * @return string Modified string
	 */
	public static function stripNonAlphaHyphenSpaces($string) {
		return preg_replace('/[^a-z\- ]/i', '', $string);
	}

	/**
	 * Remove all characters except letters and numbers.
	 *
	 * @param string $string String to modify
	 * @return string Modified string
	 */
	public static function stripNonAlphaNumeric($string) {
		return preg_replace('/[^a-z0-9]/i', '', $string);
	}

	/**
	 * Remove all characters except letters, numbers, hyphens, and spaces.
	 * (Most commonly used for city names)
	 *
	 * @param string $string String to modify
	 * @return string Modified string
	 */
	public static function stripNonAlphaNumericHyphenSpaces($string) {
		return preg_replace('/[^a-z0-9\- ]/i', '', $string);
	}

	/**
	 * Remove all characters except letters, numbers, and spaces.
	 *
	 * @param string $string String to modify
	 * @return string Modified string
	 */
	public static function stripNonAlphaNumericSpaces($string) {
		return preg_replace('/[^a-z0-9 ]/i', '', $string);
	}

	/**
	 * Remove all characters except numbers.
	 *
	 * @param string $string String to modify
	 * @return string Modified string
	 */
	public static function stripNonNumeric($string) {
		return preg_replace('/[^0-9]/', '', $string);
	}

	/**
	 * Returns the current date (not time) as a DateTime object or formatted string
	 *
	 * @param string $format [OPTIONAL] If specified, will format the date as a string
	 *                       If not specified, returns a DateTime object
	 *	                     (example: 'Y-m-d')
	 * @param string $timezone [OPTIONAL] Default timezone
	 * @return DateTime/string The DateTime object or a formatted string
	 */
	public static function today($format = false, $timezone = self::DEFAULT_TIMEZONE) {
		$today = self::convertToDate('Today', $timezone);
		if ($format) {
			return $today->format($format);
		} else {
			return $today;
		}
	}

	/**
	 * Trims a value if it is a string
	 *
	 * @param unknown_type $value The value to trim
	 * @param string $mask The characters used for trim
	 * @return unknown_type The value passed in; if a string, then it is trimmed
	 */
	public static function trim($value, $mask = ' ') {
		if (is_string($value)) {
			return trim($value, $mask);
		} elseif (is_null($value)) {
			return '';
		} else {
			return $value;
		}
	}

	/**
	 * Removes the decimal point in a float without rounding up or down
	 *
	 * example echo truncate('This is too long', 10, '...');
	 *
	 * @param string $string The string to truncate
	 * @param int $length The number of max character
	 * @return string The truncated string
	 */
	public static function truncate($string, $length, $dots = '') {
		if (strlen($string) > $length) {
			return substr($string, 0, $length - strlen($dots)) . $dots;
		} else {
			return $string;
		}
	}

	/**
	 * Removes the decimal point in a float without rounding up or down
	 *
	 * example echo truncateDecimal(1234.5678);
	 *
	 * @param float $float Floating point decimal number
	 * @param int $precision [OPTIONAL] The number of decimal points to keep
	 * @return float The truncated floating point number
	 */
	public static function truncateDecimal($float, $precision = 0) {
		$pow     = pow(10, $precision);
		$precise = (int) ($float * $pow);
		return (float) ($precise / $pow);
	}

	/**
	 * Check to see if a password is string and meets basic requirements
	 *
	 * @param string $password Password
	 * @param string $confirm Confirmed password
	 * @param string $email Username
	 * @param string $username Email
	 * @param boolean $forceUpperLower True if password must contain both a
	 *                                 lower and uppercase character
	 * @return string Contains an HTML list of problems or FALSE if valid
	 */
	public static function validatePassword($password, $confirm, $email = '',
		$username = '', $forceUpperLower = false, $returnArray = false) {

		// Create a variable to contain potential problems
		$problem = '';

		if ($password != $confirm) {
			$problem .= 'Password and confirm password fields did not match.' . "<br>\n";
		}

		if (strlen($password) < 8) {
			$problem .= 'Password must be at least 8 characters long.' . "<br>\n";
		}

		if ($email) {
			if (strpos(strtoupper($password), strtoupper($email)) !== false
				|| strpos(strtoupper($password), strtoupper(strrev($email))) !== false) {
				$problem .= 'Password cannot contain the email address.' . "<br>\n";
			}
		}

		if ($username) {
			if (strpos(strtoupper($password), strtoupper($username)) !== false
				|| strpos(strtoupper($password), strtoupper(strrev($username))) !== false) {
				$problem .= 'Password cannot contain the username (or reversed username).' . "<br>\n";
			}
		}

		if (!preg_match('#[0-9]+#', $password)) {
			$problem .= 'Password must contain at least one number.' . "<br>\n";
		}

		if ($forceUpperLower) {
			if (!preg_match('#[a-z]+#', $password)) {
				$problem .= 'Password must contain at least one lowercase letter.' . "<br>\n";
			}
			if (!preg_match('#[A-Z]+#', $password)) {
				$problem .= 'Password must contain at least one uppercase letter.' . "<br>\n";
			}
		} else {
			if (!preg_match('#[a-zA-Z]+#', $password)) {
				$problem .= 'Password must contain at least one letter.' . "<br>\n";
			}
		}

		// Fix the return result
		if (strlen($problem) == 0) {
			$problem = false;
		} elseif ($returnArray) {
			$problem = explode("<br>\n", trim($problem, "<br>\n"));
		} else {
			// $problem = trim($problem, "<br>\n");
		}

		return $problem;
	}
}
?>