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

/**
 * This class supports SSL
 *
 * @package    SSL
 * @category   Models
 * @author     Deon George
 * @copyright  (c) 2009-2013 Open Source Billing
 * @license    http://dev.osbill.net/license.html
 */
class Model_SSL_CA extends ORM_OSB {
	protected $_updated_column = FALSE;

	// Relationships
	protected $_belongs_to = array(
		'parent'=>array('model'=>'ssl_ca','foreign_key'=>'parent_ssl_ca_id'),
	);
	protected $_has_many = array(
		'children'=>array('model'=>'ssl_ca','far_key'=>'id','foreign_key'=>'parent_ssl_ca_id'),
		'service'=>array('through'=>'service__ssl'),
	);

	protected $_display_filters = array(
		'sign_cert'=>array(
			array('SSL::subject',array(':value')),
		),
	);

	public function filters() {
		return array(
			'parent_ssl_ca_id'=>array(
				array(array($this,'filter_getParent')),
			)
		);
	}

	public function rules() {
		return array(
			'sign_cert'=>array(
				array(array($this,'isCert')),
				array(array($this,'isCA')),
			),
			'parent_ssl_ca_id'=>array(
				array(array($this,'rule_parentExist')),
			),
		);
	}

	private $_so = NULL;

	/**
	 * Resolve any queries to certificate details
	 */
	public function __call($name,$args) {
		$m = 'get_'.$name;

		if (is_null($this->_so))
			return NULL;

		if (method_exists($this->_so,$m))
			return $this->_so->{$m}($args);
		else
			throw new Kohana_Exception('Unknown method :method for :class',array(':method'=>$m,':class'=>get_class($this->_so)));
	}

	// We want to inject the SSL object into this Model
	protected function _load_values(array $values) {
		parent::_load_values($values);

		if ($this->sign_cert)
			$this->_so = SSL::instance($this->sign_cert);

		return $this;
	}

	/**
	 * List the child CA certs
	 */
	public function childca($children=FALSE) {
		$result = 0;

		if ($children)
			foreach ($this->list_childca() as $cao)
				$result += $cao->childca($children);

		return $result+$this->list_childca()->count();
	}

	public function childcrt($children=FALSE) {
		$result = 0;

		if ($children)
			foreach ($this->list_childca() as $cao)
				$result += $cao->childcrt($children);

		return $result+$this->list_childcrt()->count();
	}

	/**
	 * Make sure we have our parent in the DB too
	 */
	public function validParent($format=FALSE) {
		$result = NULL;

		// If we are a root cert, we are valid
		if (is_null($this->parent_ssl_ca_id) AND $this->isRoot())
			return StaticList_YesNo::get(TRUE,$format);

		return StaticList_YesNo::get($this->aki_keyid() == $this->parent->ski(),$format);
	}

	// If we change the SSL certificate, we need to reload our SSL object
	public function values(array $values, array $expected = NULL) {
		parent::values($values,$expected);

		if (array_key_exists('sign_cert',$values))
			$this->_so = SSL::instance($this->sign_cert);

		return $this;
	}

	public function filter_getParent() {
		foreach (ORM::factory($this->_object_name)->find_all() as $sco)
			if ($sco->aki_keyid() == $this->aki_keyid())
				return $sco->id;
	}

	public function list_childca() {
		return $this->children->find_all();
	}

	public function list_childcrt() {
		return $this->service->where_active()->find_all();
	}

	public function rule_parentExist() {
		// Our parent_ssl_ca_id should have been populated by filter_GetParent().
		return $this->parent_ssl_ca_id OR $this->isRoot();
	}
}
?>