<?php
/**
 * @version		$Id: validator.php 379 2009-06-17 07:16:53Z eddieajau $
 * @package		JXtended.Libraries
 * @subpackage	Form
 * @copyright	Copyright (C) 2008 - 2009 JXtended, LLC. All rights reserved.
 * @license		GNU General Public License <http://www.gnu.org/copyleft/gpl.html>
 * @link		http://jxtended.com
 */

defined('JPATH_BASE') or die;

/**
 * Form Validator class for JXtended Libraries.
 *
 * @package		JXtended.Libraries
 * @subpackage	Forms
 * @version		2.0
 */
class JXFormValidator extends JObject
{
	/**
	 * Method to validate a group of fields.
	 *
	 * @access	public
	 * @param	array		$fields		An array of fields to validate.
	 * @param	array		$data		The data to validate.
	 * @return	mixed		Array on success, JException on error.
	 * @since	2.0
	 */
	function validate(&$fields, &$data)
	{
		$results = array();

		foreach ($fields as $name => $field)
		{
			// Get the data for the field.
			$value = array_key_exists($name, $data) ? $data[$name] : null;

			// Check if the field is required.
			if ($field->attributes('required') == 'true')
			{
				// Check if the field value is empty.
				if ($value === '')
				{
					// The required field is empty!
					if ($message = $field->attributes('message')) {
						$results[] = new JException($message, 0, E_WARNING);
					} else {
						$results[] = new JException(JText::sprintf('JX_LIBRARIES_FORM_VALIDATOR_FIELD_REQUIRED', JText::_($field->attributes('label'))), 0, E_WARNING);
					}

					// We don't want to display more than one message per field so continue to the next one.
					continue;
				}
			}

			// Run the field validator.
			$return = $this->_isValid($field, $value);

			// Check for an error.
			if (JError::isError($return)) {
				return $return;
			}

			// Check if the field is valid.
			if ($return === false)
			{
				// The field failed validation.
				if ($message = $field->attributes('message')) {
					$results[] = new JException($message, 0, E_WARNING);
				} else {
					$results[] = new JException(JText::sprintf('JX_LIBRARIES_FORM_VALIDATOR_FIELD_INVALID', $field->attributes('title')), 0, E_WARNING);
				}
			}
		}

		return $results;
	}

	/**
	 * Method to test if a value is valid for a field.
	 *
	 * @access	protected
	 * @param	object		$field	The field to validate.
	 * @param	mixed		$value	The value to validate.
	 * @return	mixed		Boolean on success, JException on error.
	 * @since	2.0
	 */
	function _isValid(&$field, $value)
	{
		$result = true;

		// Get the validator type.
		if ($type = $field->attributes('validate'))
		{
			// Get the validator class.
			$class = 'JXFormValidate'.$type;

			if (!class_exists($class))
			{
				jimport('joomla.filesystem.path');

				// Attempt to load the rule file.
				if ($file = JPath::find(JXFormValidator::addRulePath(), $type.'.php')) {
					require_once $file;
				}

				if (!class_exists($class)) {
					return new JException(JText::sprintf('JX_LIBRARIES_FORM_VALIDATOR_RULE_NOT_FOUND', $type), 0, E_ERROR);
				}
			}

			// Run the validator.
			$rule	= new $class;
			$result	= $rule->test($field, $value);
		}

		return $result;
	}

	/**
	 * Method to add a path to the list of rule include paths.
	 *
	 * @access	public
	 * @param	mixed		$new	A path or array of paths to add.
	 * @return	array		The list of paths that have been added.
	 * @since	2.0
	 * @static
	 */
	function addRulePath($new = null)
	{
		static $paths;

		if (!isset($paths)) {
			$paths = array(dirname(__FILE__).DS.'rules');
		}

		// Force path to an array.
		settype($new, 'array');

		// Add the new paths to the list if not already there.
		foreach ($new as $path) {
			if (!in_array($path, $paths)) {
				array_unshift($paths, trim($path));
			}
		}

		return $paths;
	}
}


class JXFormValidatorRegex
{
	var $_regex = null;

	function test(&$field, $value)
	{
		$result = true;
		if (empty($this->_regex)) {
			$result = new JException('Regex is invalid '.get_class($this));
		}
		else
		{
			$name = $field->attributes('name');
			if (!preg_match(chr(1).$this->_regex.chr(1), $value)) {
				$result = false;
			}
		}
		return $result;
	}
}