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

/**
 * This class provides the default template controller for rendering pages.
 *
 * @package    lnApp
 * @category   Controllers
 * @author     Deon George
 * @copyright  (c) 2009-2013 Deon George
 * @license    http://dev.leenooks.net/license.html
 */
abstract class lnApp_Controller_TemplateDefault extends Kohana_Controller_Template {
	/**
	 * @var object meta object information as per [meta]
	 */
	protected $meta;
	/**
	 * Controls access to this controller.
	 * Can be set to a string or an array, for example 'login' or array('login', 'admin')
	 * Note that in second(array) example, user must have both 'login' AND 'admin' roles set in database
	 *
	 * @var boolean is authenticate required with this controller
	 */
	protected $auth_required = FALSE;
	/**
	 * If redirecting to a login page, which page to redirect to
	 */
	protected $noauth_redirect = 'login';
	/**
	 * Controls access for separate actions, eg:
	 * 'adminpanel' => 'admin' will only allow users with the role admin to access action_adminpanel
	 * 'moderatorpanel' => array('login', 'moderator') will only allow users with the roles login and moderator to access action_moderatorpanel
	 *
	 * @var array actions that require a valid user
	 */
	protected $secure_actions = array();

	// Our acccount object
	protected $ao;

	public function __construct(Request $request, Response $response) {
		if (Config::theme())
			$this->template = Config::theme().'/page';

		return parent::__construct($request,$response);
	}

	/**
	 * Check and see if this controller needs authentication
	 *
	 * if $this->auth_required is TRUE, then the user must be logged in only.
	 * if $this->auth_required is FALSE, AND $this->secure_actions has an array of
	 * methods set to TRUE, then the user must be logged in AND a member of the
	 * role.
	 *
	 * @return boolean
	 */
	protected function _auth_required() {
		// If our global configurable is disabled, then continue
		if (! Kohana::$config->load('config')->method_security)
			return FALSE;

		return (($this->auth_required !== FALSE && Auth::instance()->logged_in(NULL,get_class($this).'|'.__METHOD__) === FALSE) ||
			(is_array($this->secure_actions) && array_key_exists($this->request->action(),$this->secure_actions) &&
			! Auth::instance()->logged_in($this->secure_actions[$this->request->action()],get_class($this).'|'.__METHOD__)));
	}

	/**
	 * Loads the template [View] object.
	 *
	 * Page information is provided by [meta].
	 * @uses meta
	 */
	public function before() {
		if ($this->auth_required) {
			if (! count($this->secure_actions) OR (! isset($this->secure_actions[Request::current()->action()])))
				throw HTTP_Exception::factory(403,'Class has no security defined :class, or no security configured for :method',array(':class'=>get_class($this),':method'=>Request::current()->action()));

			$this->ao = Auth::instance()->get_user();

			if (! is_null($this->ao) AND (is_string($this->ao) OR ! $this->ao->loaded()))
				throw HTTP_Exception::factory(501,'Account doesnt exist :account ?',array(':account'=>(is_string($this->ao) OR is_null($this->ao)) ? $this->ao : Auth::instance()->get_user()->id));
		}

		// Actions that start with ajax, should only be ajax
		if (! Kohana::$config->load('debug')->ajax AND preg_match('/^ajax/',Request::current()->action()) AND ! Request::current()->is_ajax())
			throw HTTP_Exception::factory(412,_('Unable to fulfil request.'));

		parent::before();

		// Do not template media files
		if ($this->request->action() === 'media') {
			$this->auto_render = FALSE;
			return;
		}

		// Check user auth and role
		if ($this->_auth_required()) {
			if (PHP_SAPI === 'cli')
				throw new Kohana_Exception('Cant run :method, authentication not possible',array(':method'=>$this->request->action()));

			// If auth is required and the user is logged in, then they dont have access.
			// (We have already checked authorisation.)
			if (Auth::instance()->logged_in(NULL,get_class($this).'|'.__METHOD__)) {
				if ($this->request->is_ajax())
					throw HTTP_Exception::factory(403,_('You dont have enough permissions.'));
				else
					if (! Kohana::$config->load('debug')->disabled_noaccess_redirect)
						HTTP::redirect('login/noaccess');
					else
						throw HTTP_Exception::factory(501,'I would redirect you here - no ACCESS');

			} else {
				Session::instance()->set('afterlogin',Request::detect_uri());
				HTTP::redirect($this->noauth_redirect);
			}
		}

		if (! $this->auto_render)
			return;

		// For AJAX calls, we dont need to render the complete page.
		if ($this->request->is_ajax() OR (Kohana::$config->load('debug')->ajax AND preg_match('/^ajax/',Request::current()->action()))) {
			$this->auto_render = FALSE;

			return;
		}

		// Bind our template meta variable
		$this->meta = new Meta;
		View::bind_global('meta',$this->meta);

		// Our default script(s)
		foreach (array('file'=>array_reverse(array(
			))) as $type => $datas) {

			foreach ($datas as $data) {
				Script::add(array(
					'type'=>$type,
					'data'=>$data,
				),TRUE);
			}
		}

		// Initialise our content
		$this->template->shownavbar = TRUE;
		$this->template->content = '';
		$this->template->footer = '';
	}

	public function after() {
		if ($this->auto_render) {
			$this->template->navbar = $this->template->shownavbar ? View::factory('pages/navbar') : '';

			if (empty($this->template->content))
				$this->template->content = Block::factory()->render_all();

			// Adjust our breadcrumb
			if (isset(URL::$method_directory[strtolower($this->request->directory())]))
				BreadCrumb::name(URL::$method_directory[strtolower($this->request->directory())],$this->request->directory());

			// Application Title
			if (class_exists('Model_Module') AND $mo=ORM::factory('Module',array('name'=>Request::current()->controller())) AND $mo->loaded())
				$this->meta->title = sprintf('%s: %s',Kohana::$config->load('config')->appname,$mo->display('name'));
			else
				$this->meta->title = Kohana::$config->load('config')->appname;

			// Description
			$this->meta->description = sprintf('%s::%s',$this->request->controller(),$this->request->action());

		// For any ajax rendered actions, we'll need to capture the content and put it in the response
		} elseif ($this->request->is_ajax()) {
			$output = Style::factory()->render_all();
			$output .= Script::factory()->render_all();

			if (! isset($this->template->content))
				$output .= $this->response->body() ? $this->response->body() : '';
			else
				$output .= $this->template->content;

			$this->response->body($output);
		}

		// Used by our javascript to know what the SITE URL is.
		Script::factory()
			->type('stdin')
			->data('var site_url="'.URL::site('',TRUE).'";');

		parent::after();

		// Generate and check the ETag for this file
		if (Kohana::$environment < Kohana::TESTING OR Kohana::$config->load('debug')->etag)
			$this->check_cache(sha1($this->response->body()));
	}

	/**
	 * Generate a view path to help View::factory() calls
	 *
	 * The purpose of this method is to ensure that we have a consistant
	 * layout for our view files, including those that are needed by
	 * plugins
	 *
	 * @param string Plugin Name (optional)
	 * @deprecated
	 */
	public function viewpath($plugin='') {
		$request = Request::current();

		$path = $request->controller();

		if ($request->directory())
			$path .= ($path ? '/' : '').$request->directory();

		if ($plugin)
			$path .= ($path ? '/' : '').$plugin;

		$path .= ($path ? '/' : '').$request->action();

		return strtolower($path);
	}
}
?>