<?php defined('SYSPATH') or die('No direct access allowed.');

/**
 * This class overrides Kohana's ORM
 *
 * @package    OSB/Modifications
 * @category   Classes
 * @category   Helpers
 * @author     Deon George
 * @copyright  (c) 2010 Deon George
 * @license    http://dev.leenooks.net/license.html
 */
class ORM extends Kohana_ORM {
	protected $_table_names_plural = false;
	protected $_model_names_plural = false;
	private $_object_formated = array();
	private $_formated = FALSE;
	// Our filters used to display values in a friendly format
	protected $_display_filters = array();

	// Override check() so that it doesnt throw an exception.
	// @todo Need to figure out how to show the items that fail validation
	final public function check(Validation $extra_validation = NULL) {
		// Determine if any external validation failed
		$extra_errors = ($extra_validation AND ! $extra_validation->check());

		// Always build a new validation object
		$this->_validation();

		$array = $this->_validation;

		if (($this->_valid = $array->check()) === FALSE OR $extra_errors)
		{
			return FALSE;
		}

		return $this;
	}

	// Add our OSB site_id to each SELECT query
	final protected function _build($type) {
		// Exclude tables without site ID's
		if (! in_array($this->_table_name,array('setup','country','currency','tax')))
			$this->where($this->_table_name.'.site_id','=',Config::siteid());

		return parent::_build($type);
	}

	/**
	 * Format fields for display purposes
	 *
	 * @param   string  column name
	 * @return  mixed
	 */
	private function _format() {
		foreach ($this->_display_filters as $column => $formats)
			$this->_object_formated[$column] = $this->run_filter($column,$this->__get($column),array($column=>$formats));

		$this->_formated = TRUE;
	}

	/**
	 * Return a formated columns, as per the model definition
	 */
	public function display($column) {
		// Trigger a load of the record.
		$value = $this->__get($column);

		// If some of our fields need to be formated for display purposes.
		if ($this->_loaded AND ! $this->_formated AND $this->_display_filters)
			$this->_format();

		if (isset($this->_object_formated[$column]))
			return $this->_object_formated[$column];
		else
			return HTML::nbsp($value);
	}

	/**
	 * Override KH's ORM has() function, to include our site_id in the query.
	 *
	 * This is a copy of KH's ORM has() function, with the addition of a where
	 * clause to include the site id.
	 */
	public function has($alias, $far_keys) {
		$far_keys = ($far_keys instanceof ORM) ? $far_keys->pk() : $far_keys;

		// We need an array to simplify the logic
		$far_keys = (array) $far_keys;

		// Nothing to check if the model isn't loaded or we don't have any far_keys
		if ( ! $far_keys OR ! $this->_loaded)
			return FALSE;

		$count = (int) DB::select(array('COUNT("*")', 'records_found'))
			->from($this->_has_many[$alias]['through'])
			->where($this->_has_many[$alias]['foreign_key'], '=', $this->pk())
			->where($this->_has_many[$alias]['far_key'], 'IN', $far_keys)
			->where('site_id', '=', Config::siteid())
			->execute($this->_db)->get('records_found');

		// Rows found need to match the rows searched
		return $count === count($far_keys);
	}

	/**
	 * Tests if this object has a relationship to a different model,
	 * or an array of different models.
	 *
	 *     // Check for any of the following roles
	 *     $model->has('roles', array(1, 2, 3, 4));
	 *
	 * @param  string  $alias    Alias of the has_many "through" relationship
	 * @param  mixed   $far_keys An array of primary keys
	 * @return Database_Result
	 */
	public function has_any($alias, array $far_keys) {
		// Nothing to check if the model isn't loaded or we don't have any far_keys
		if ( ! $far_keys)
			return FALSE;

		// Rows found need to match the rows searched
		return (int) DB::select(array('COUNT("*")', 'records_found'))
			->from($this->_has_many[$alias]['through'])
			->where($this->_has_many[$alias]['foreign_key'], '=', $this->pk())
			->where($this->_has_many[$alias]['far_key'], 'IN', $far_keys)
			->execute($this->_db)->get('records_found');
	}
}
?>