<?php defined('SYSPATH') OR die('No direct access allowed.');
/**
* Абстрактный класс шаблона
*
* @package Cerber
* @category Шаблон
* @author Яковлев Сергей (me@klay.me)
* @version 0.1.0.0
* @copyright (c) 2012 Яковлев Сергей
* @license GPLv3
*/
abstract class Cerber_Template extends Controller {
/** @var string Основной шаблон */
public $template = 'template';
/** @var boolean Авторендеринг шаблона */
public $auto_render = TRUE;
/** @var string Название сайта */
public $_site_name;
/** @var string Заголовок страницы */
public $title = NULL;
/** @var string Символ разделяющий заголовок страницы и имя сайта */
public $_title_separator;
/** @var object Объект авторизации */
protected $_auth;
/** @var boolean Это ансинхронный запрос? */
protected $_ajax = FALSE;
/** @var boolean Это внутренний запрос? */
protected $_internal = FALSE;
/** @var Kohana_Config Конфигурация приложения */
protected $_config;
/** @var string Текущий ID страницы, по умолчанию - имя контролера */
protected $_page_id;
/** @var array Профилирование */
protected $_benchmark;
/** @var string Формат ответа на запрос */
protected $_response_format;
/**
* Поддерживаемые форматы ответа для данного контролера
* (accept-type => путь к шаблону формата)
*
* @var array
*/
protected $_accept_formats = array(
'text/html' => '',
'application/xhtml+xml' => '',
'application/json' => 'json',
'*/*' => '', //ie7 ie8
);
/**
* Метод before() всегда запускается перед любым экшеном
*
* @return void
*/
public function before()
{
// Сначало выполнить родительский before()
parent::before();
// Начало профилирования
if (Kohana::$profiling === TRUE)
{
$this->_benchmark = Profiler::start('Cerber', 'Cerber Controller');
}
// Проверка, является ли текущий запрос первым
if (! $this->request->is_initial())
{
$this->_internal = TRUE;
$this->auto_render = FALSE;
}
// Проверка, является ли текущий запрос асинхронным
if ($this->request->is_ajax())
{
$this->_ajax = TRUE;
$this->auto_render = FALSE;
}
// Получение конфигурации
$this->_config = Kohana::$config->load('application');
// Получение инстанса аутентификации
$this->_auth = Auth::instance();
// Получение форматов ответа
$accept_types = Request::accept_type();
$accept_types = Arr::extract($accept_types, array_keys($this->_accept_formats));
// Установка формата ответа по первому совпадению
$this->_response_format = key($accept_types);
if ($this->auto_render)
{
// Генерирует исключение если ожидаемый формат ответа не поддерживается
if(! $accept_types = array_filter($accept_types))
{
throw new HTTP_Exception_415('Тип содержимого не поддерживается', NULL);
}
// Загрузка шаблона
$this->template = View::factory($this->template);
$this->_title_separator = $this->_config->get('title_separator', ' | ');
// Установка переменных сайта
$this->template
->set('site_name', $this->_config->get('site_name', __('Cerber CMS')))
->set('site_slogan', $this->_config->get('site_slogan', __('Innovate IT')))
->set('column_class', '')
->set('head_title', $this->title)
->set('title', $this->title);
// Назначение стилей по умолчанию
Assets::css('bootstrap', 'media/css/vendor/bootstrap.min.css', NULL, array('weight' => -15));
Assets::css('bootstraper', 'media/css/bootstraper.css', array('bootstrap'), array('weight' => -14));
Assets::css('cuprum', 'http://fonts.googleapis.com/css?family=Cuprum:400,700&subset=cyrillic,latin');
Assets::css('global', 'media/css/style.css');
// Назначение JavaScript по умолчанию
Assets::js('jquery', 'media/js/jquery-1.8.3.min.js', NULL, FALSE, array('weight' => -20));
Assets::js('bootstrap', 'media/js/bootstrap-2.2.1.js', array('jquery'), FALSE, array('weight' => -15));
// Установка мета тегов по умолчанию
$this->_set_default_meta_tags();
// Установка мета ссылок по умолнию
$this->_set_default_meta_links();
// Журналирование
if (Kohana::$environment === Kohana::DEVELOPMENT)
{
Kohana::$log->add(LOG::DEBUG, 'Выполнение контролера `:controller` экшен `:action`',
array(
':controller' => $this->request->controller(),
':action' => $this->request->action(),
)
);
}
}
}
/**
* Метод after() запускается после любого вызываемого экшена
*
* @return void
*/
public function after()
{
// Выполнить толко в том случае если это не AJAX
if ($this->auto_render)
{
// Имя контролёря является ID текущей страницы
// если ничего другого не определено
empty($this->_page_id) AND $this->_page_id = $this->request->controller();
// Некоторая магия для формирования класса страницы
$classes = array();
$classes[] = $this->request->controller();
$classes[] = $this->request->action();
$classes[] = ($this->_auth->logged_in()) ? 'logged-in' : 'not-logged-in';
$page_class = implode(' ', array_unique(array_map('trim', $classes)));
// Установка заголовка страницы
$this->_set_head_title();
// Первичное меню
$primary_menu = Menu::links('main-menu', array('class' => 'menus nav'));
$this->template
->set('lang', Cerber::$lang) // Текущий язык страницы
->set('page_id', $this->_page_id) // Текущий ID страницы
->set('page_class', $page_class) // Текущий класс страницы
->set('primary_menu', $primary_menu) // Первичное меню
->set('title', $this->title) // Текущий заголовок страницы
->set('content', $this->response->body());
// Профилирование если режим отладки включен
if (Kohana::$environment === Kohana::DEVELOPMENT)
{
$this->template->profiler = View::factory('profiler/stats');
}
// Установка заголовков сервера по умолчанию
$this->_set_default_server_headers();
// Вывод шаблона в ответе
$this->response->body($this->template);
}
// Если это AJAX запрос
elseif( $this->_ajax === TRUE )
{
// Установка заголовков сервера по умолчанию
$this->_set_default_server_headers();
// Подготовка ответа
$output = $this->response->body();
// Кодирование ответа
if($this->_response_format === 'application/json')
{
$output = JSON::encode($output);
}
// Вывод ответа
$this->response->body($output);
}
// Если это внутренний запрос
elseif( $this->_internal === TRUE )
{
// Установка заголовков сервера по умолчанию
$this->_set_default_server_headers();
// Подготовка ответа
$output = $this->response->body();
// Вывод ответа
$this->response->body( $output );
}
// Если профилирование включено
if (isset($this->_benchmark))
{
// Тут нужно его остановить
Profiler::stop($this->_benchmark);
}
// Выполнить родительский after()
parent::after();
}
/**
* Установка заголовка страницы
*
* @return void
*/
protected function _set_head_title()
{
if ($this->title)
{
$head_title = array(strip_tags($this->title), $this->template->site_name);
}
else
{
$head_title = array($this->template->site_name);
if ($this->template->site_slogan)
{
$head_title[] = $this->template->site_slogan;
}
}
$this->template->head_title = implode($this->_title_separator, $head_title);
}
/**
* Установка заголовков сервера по умолчанию
*
* @return void
*/
protected function _set_default_server_headers()
{
$headers['Content-Type'] = $this->_response_format.'; charset='.Kohana::$charset;
$headers['X-Powered-By'] = Cerber::NAME;
$headers['X-Cerber-Version'] = Cerber::VERSION.' ('.Cerber::CODENAME.')';
$this->_set_server_headers($headers);
}
/**
* Установка заголовков сервера
*
* @param array Ассоциативный массив заголовков сервера
* @return void
*/
protected function _set_server_headers($headers)
{
if (is_array($headers) AND ! empty($headers))
{
$this->response->headers($headers);
}
}
/**
* Установка мета тегов по умолчанию
*
* Используется конфигурация
*
* @return void
*
* @uses Meta::tags Обертка для мета тегов
*/
protected function _set_default_meta_tags()
{
$meta = $this->_config->get('meta', array());
$tags = Arr::get($meta, 'tags');
if ($tags)
{
foreach ($tags as $name => $value)
{
$conditional = NULL;
if (is_array($value))
{
$conditional = Arr::get($value, 'conditional');
$value = Arr::get($value, 'value', '');
}
$attributes = array();
if (isset($conditional))
{
$attributes['conditional'] = $conditional;
}
Meta::tags($name, $value, $attributes);
}
}
}
/**
* Установка мета ссылок по умолчанию
*
* Используется конфигурация
*
* @return void
*
* @uses Meta::tags Обертка для мета ссылок
*/
protected function _set_default_meta_links()
{
$meta = $this->_config->get('meta', array());
$links = Arr::get($meta, 'links');
if ($links)
{
foreach ($links as $url => $attrs)
{
Meta::links($url, $attrs);
}
}
}
}