<?php
/**
* Libs_Template
*
* @access public
*/
abstract
class
Libs_Template {
/**
* Экземпляр реестра
*
* @access public
* @var mixed
*/
public
$reg;
/**
* Экземпляр контроллера шаблона
*
* @access protected
* @var mixed
*/
protected
$_controller;
/**
* Конфигурация подключаемых шаблонов
*
* @access protected
* @var array
*/
protected
$_config = array();
/**
* Путь к шаблону
*
* @access protected
* @var string
*/
protected
$_template_route = NULL;
/**
* Имя базового шаблона
*
* @access protected
* @var string
*/
protected
$_template_name = NULL;
/**
* CSS файлы страницы
*
* @access public
* @var array
*/
protected
$_css = array();
/**
* JavaScript файлы для вывода в шапке
*
* @access protected
* @var array
*/
protected
$_js_header = array();
/**
* JavaScript файлы для вывода в подвале
*
* @access protected
* @var array
*/
protected
$_js_footer = array();
/**
* Memcache
*
* @access public
* @var object
*/
protected
$_mc = NULL;
/**
* Заголовок страницы
*
* @access public
* @var array
*/
public
$title;
/**
* Конструктор
*
* @access public
* @param string
* @return string
*/
public
function __construct($config) {
$
this
->_config = $config;
if
( CFG_CACHE_ENABLE ) {
$
this
->_mc = Registry::get(
'Cache'
);
}
}
/**
* Запуск метода в контроллере шаблона
*
* @return mixed
*/
public
function __call($method, $args) {
$
this
->_controller = Registry::get(
'TemplateController'
);
return
call_user_func_array(array($
this
->_controller, $method), $args);
}
/**
* Вывод сфорированного шаблона
*
* @access public
* @param string template_route
* @param array data
* @return void
*/
public
function display($template_route, $data = array()) {
$
this
->_template_route = $template_route;
if
( is_null($
this
->_template_name) ) {
$
this
->_template_name = str_replace(
'.'
,
'_'
, $template_route);
}
$config = $
this
->_getConfig();
if
( $config ) {
$
this
->_prepareCss($config);
$
this
->_prepareJs($config);
foreach ( $
this
->_config[
'default'
][
'tpl'
] as $block=>$templates ) {
if
( isset($config[
'tpl'
][$block]) ) {
$templates = $config[
'tpl'
][$block];
}
foreach ($templates as $template) {
if
( $template ) {
$
this
->_fetch($template, $data);
}
}
}
}
else
{
echo
'Шаблон '
.$template_route.
' не подключен'
;
}
}
/**
* Подготовка CSS
*
* @access private
* @param string config
* @return void
*/
private
function _prepareCss($config) {
if
( !empty($
this
->_config[
'default'
][
'css'
]) && empty($
this
->_css) ) {
foreach ( $
this
->_config[
'default'
][
'css'
] as $key=>$val ) {
$
this
->_makeCss($key, $val);
}
}
if
( isset($config[
'css'
]) ) {
foreach ( $config[
'css'
] as $key=>$val ) {
$
this
->_makeCss($key, $val);
}
}
}
/**
* Подготовка JavaScript
*
* @access private
* @param string config
* @return void
*/
private
function _prepareJs($config) {
if
( !empty($
this
->_config[
'default'
][
'js-header'
]) && empty($
this
->_js_header) ) {
foreach ($
this
->_config[
'default'
][
'js-header'
] as $key=>$val ) {
$
this
->_makeJs($key, $val,
'header'
);
}
}
if
( !empty($
this
->_config[
'default'
][
'js-footer'
]) && empty($
this
->_js_footer) ) {
foreach ($
this
->_config[
'default'
][
'js-footer'
] as $key=>$val ) {
$
this
->_makeJs($key, $val,
'footer'
);
}
}
if
( isset($config[
'js-header'
]) ) {
foreach ( $config[
'js-header'
] as $key=>$val ) {
$
this
->_makeJs($key, $val,
'header'
);
}
}
if
( isset($config[
'js-footer'
]) ) {
foreach ( $config[
'js-footer'
] as $key=>$val ) {
$
this
->_makeJs($key, $val,
'footer'
);
}
}
}
/**
* Подключение шаблона по пути и возврат готового HTML
*
* @access public
* @param string module
* @param string template
* @param array data
* @return string
*/
public
function fetch($template_path, $data = array()) {
$returnValue = (string)
''
;
ob_start();
$
this
->_fetch($template_path, $data);
$returnValue = ob_get_contents();
ob_end_clean();
return
(string) $returnValue;
}
/**
* Подключение шаблона по пути и подстановка данных
*
* @access public
* @param string template_path
* @param array data
* @return void
*/
public
function get($template_path, $data = array()) {
$
this
->_fetch($template_path, $data);
}
/**
* Получение конфига нужного шаблона
*
* @access protected
* @return array
*/
protected
function _getConfig() {
$config = array();
$template_route_parts = explode(
'.'
, $
this
->_template_route);
if
(!empty($
this
->_config[$template_route_parts[
0
]])) {
$config = $
this
->_config[$template_route_parts[
0
]];
if
( $template_route_parts >
1
) {
for
($ii=
1
; $ii<count($template_route_parts); $ii++) {
if
( !empty($config[
'children'
][$template_route_parts[$ii]]) ) {
$config = $config[
'children'
][$template_route_parts[$ii]];
}
else
{
$config = array();
break
;
}
}
}
}
return
$config;
}
/**
* Подстановка данных в шаблон
*
* @access protected
* @return void
*/
protected
function _fetch($_template, $_data) {
extract($_data);
if
( is_file(CFG_TEMPLATES_PATH .
'/'
. $_template) ) {
include( CFG_TEMPLATES_PATH .
'/'
. $_template );
}
else
{
echo
'Файл шаблона "'
.CFG_TEMPLATES_PATH .
'/'
. $_template.
'" не найден'
.
"\r\n"
;
}
}
/**
* Операции перед выводом на экран
*
* @access protected
* @return void
*/
public
function callback($buffer) {
$buffer = $
this
->_replaceCss($buffer);
$buffer = $
this
->_replaceJs($buffer);
$buffer = $
this
->_replaceImage($buffer);
$buffer = $
this
->_replaceService($buffer);
$buffer = $
this
->_replaceFreetext($buffer);
if
( defined(
'CFG_SEO_ENABLE'
) && CFG_SEO_ENABLE ) {
if
( Seo::get(
'title'
) ) {
$buffer = preg_replace(
'/<title>.*<\/title>/i'
,
'<title>'
.Seo::get(
'title'
).
'</title>'
, $buffer);
}
if
( Seo::get(
'description'
) ) {
$buffer = str_replace(
"<!--SEO_CONTENT-->"
, Seo::get(
'description'
), $buffer);
}
}
return
trim($buffer);
}
/**
* Замена <!--#CSS#--> подключения CSS
*
* @access protected
* @return string
*/
protected
function _replaceCss($content) {
if
( $
this
->_css ) {
$content = str_replace(
"<!--CSS-->"
, implode(
"\r\n"
, $
this
->_css), $content);
}
if
( defined(
'CFG_CSS_URL'
) ) {
$content = str_replace(
"<!--CSS-URL-->"
, CFG_CSS_URL, $content);
}
return
$content;
}
/**
* Вывод HTML-тегов подключения JavaScript
*
* @access protected
* @return string
*/
protected
function _replaceJs($content) {
if
( $
this
->_js_header ) {
$content = str_replace(
"<!--JS-HEADER-->"
, implode(
"\r\n"
, $
this
->_js_header), $content);
}
if
( $
this
->_js_footer ) {
$content = str_replace(
"<!--JS-FOOTER-->"
, implode(
"\r\n"
, $
this
->_js_footer), $content);
}
if
( defined(
'CFG_JS_URL'
) ) {
$content = str_replace(
"<!--JS-URL-->"
, CFG_JS_URL, $content);
}
return
$content;
}
/**
* Вывод URL подключения images
*
* @access protected
* @return string
*/
protected
function _replaceImage($content) {
if
( defined(
'CFG_IMAGE_URL'
) ) {
$content = str_replace(
"<!--IMAGE-URL-->"
, CFG_IMAGE_URL, $content);
}
return
$content;
}
/**
* Вывод URL подключения к сервисам
*
* @access protected
* @return string
*/
protected
function _replaceService($content) {
if
( defined(
'CFG_SERVICE_ESTATE'
) ) {
$content = str_replace(
"<!--SERVICE-ESTATE-->"
, CFG_SERVICE_ESTATE, $content);
}
if
( defined(
'CFG_SERVICE_NEWS'
) ) {
$content = str_replace(
"<!--SERVICE-NEWS-->"
, CFG_SERVICE_NEWS, $content);
}
if
( defined(
'CFG_SERVICE_OFFICES'
) ) {
$content = str_replace(
"<!--SERVICE-OFFICES-->"
, CFG_SERVICE_OFFICES, $content);
}
if
( defined(
'CFG_SERVICE_DISCOUNT'
) ) {
$content = str_replace(
"<!--SERVICE-DISCOUNT-->"
, CFG_SERVICE_DISCOUNT, $content);
}
if
( defined(
'CFG_SERVICE_IPOTEKA'
) ) {
$content = str_replace(
"<!--SERVICE-IPOTEKA-->"
, CFG_SERVICE_IPOTEKA, $content);
}
if
( defined(
'CFG_SERVICE_BANNERS'
) ) {
$content = str_replace(
"<!--SERVICE-BANNERS-->"
, CFG_SERVICE_BANNERS, $content);
}
return
$content;
}
/**
* Вывод URL подключения к сервисам
*
* @access protected
* @return string
*/
protected
function _replaceFreetext($content) {
if
( defined(
'CFG_FREETEXT'
) ) {
$content = str_replace(
"<!--FREE-TEXT-->"
, CFG_FREETEXT, $content);
}
return
$content;
}
/**
* Генерация CSS файлов
*
* @access protected
* @param string fileName
* @param array cssList
*/
protected
function _makeCss($fileName, $cssList) {
$realFilePath = $
this
->_getFileName($fileName,
'css'
, $cssList);
if
( $realFilePath ) {
$realFilePath = CFG_CSS_URL . $
this
->_getFileName($fileName,
'css'
, $cssList);
if
( preg_match(
'/ie-(?P<pref>.+)?(?P<num>[0-9])/i'
, $realFilePath, $matches) ) {
$css =
'<!--[if '
. (isset($matches[
'pref'
]) ? $matches[
'pref'
].
' '
:
''
) .
'IE '
.$matches[
'num'
].
']>'
.
"\r\n"
;
$css .=
'<link rel="stylesheet" type="text/css" href="'
.$realFilePath."\
" />\r\n"
;
$css .=
'<![endif]-->'
;
} elseif ( preg_match(
'/media-(?P<media>.+).css?/i'
, $realFilePath, $matches) ) {
$css =
'<link rel="stylesheet" type="text/css" href="'
.$realFilePath.
'" media="'
. $matches[
'media'
].
'" />'
;
}
else
{
$css =
'<link rel="stylesheet" type="text/css" href="'
.$realFilePath."\
" />"
;
}
$
this
->_css[] = $css;
}
}
/**
* Генерация JavaScript файлов
*
* @access protected
* @param string fileName
* @param array jsList
*/
protected
function _makeJs($fileName, $jsList, $location) {
$realFilePath = $
this
->_getFileName($fileName,
'js'
, $jsList);
if
( $realFilePath ) {
$realFilePath = CFG_JS_URL . $
this
->_getFileName($fileName,
'js'
, $jsList);
$js =
'<script type="text/javascript" src="'
. $realFilePath . "\
"></script>"
;
if
( $location ==
"header"
) {
$
this
->_js_header[]= $js;
}
else
{
$
this
->_js_footer[]= $js;
}
}
}
/**
* Создание файла
*
* @access protected
* @param string fileName
* @param string fileType
* @param array fileList
* @return string
*/
private
function _getFileName($fileName, $fileType, $fileList) {
$returnValue =
''
;
if
( CFG_TPL_CACHE_ENABLE && $
this
->_mc ) {
$returnValue = $
this
->_mc->get(
'TPL_CACHE_'
.$fileName.$fileType);
}
if
( empty($returnValue) ) {
if
( !CFG_TPL_CACHE_ENABLE ) {
$returnValue = $
this
->_makeFile($fileName, $fileType, $fileList);
}
else
{
$files = scandir(CFG_APP_PATH .
'/'
. $fileType .
'/'
);
for
($ii=
0
; $ii<count($files); $ii++) {
if
( preg_match(
'/^'
. $fileName .
'_(.+)\.'
. $fileType .
'/'
, $files[$ii]) ) {
$returnValue = $fileType .
'/'
. $files[$ii];
break
;
}
}
if
( empty($returnValue) ) {
$returnValue = $
this
->_makeFile($fileName, $fileType, $fileList);
}
}
}
if
( !empty($returnValue) && CFG_TPL_CACHE_ENABLE && $
this
->_mc ) {
$
this
->_mc->set(
'TPL_CACHE_'
.$fileName.$fileType, $returnValue);
}
return
(string) $returnValue;
}
private
function _makeFile($fileName, $fileType, $fileList) {
$returnValue =
''
;
$contents = array();
$dir_path_app= CFG_APP_PATH .
'/'
. $fileType .
'/'
;
$dir_path_pub= CFG_PUBLIC_PATH .
'/'
. $fileType .
'/'
;
foreach ( $fileList as $file ) {
$file_path = $dir_path_app . $file;
if
( is_file($file_path) ) {
$handle = fopen($file_path,
"r"
);
$contents[]= fread($handle, filesize($file_path));
fclose($handle);
}
}
if
( $contents ) {
$contents = implode(
"\r\n"
, $contents);
$md5 = md5($contents);
$handle = fopen($dir_path_pub . $fileName .
'_'
. $md5 .
'.'
. $fileType,
"w+"
);
if
($handle) {
fwrite($handle, $contents);
fclose($handle);
$returnValue = $fileType .
'/'
. $fileName .
'_'
. $md5 .
'.'
. $fileType;
}
}
return
(string) $returnValue;
}
/**
* Получение имени шаблона
*
* @access public
* @return string
*/
public
function getTemplateName() {
return
$
this
->_template_name;
}
public
function formatRuDate($date) {
$date = intval($date);
$months = array(
1
=>
'января'
,
2
=>
'февраля'
,
3
=>
'марта'
,
4
=>
'апреля'
,
5
=>
'мая'
,
6
=>
'июня'
,
7
=>
'июля'
,
8
=>
'августа'
,
9
=>
'сентября'
,
10
=>
'октября'
,
11
=>
'ноября'
,
12
=>
'декабря'
);
return
date(
'd'
, $date).
' '
.$months[date(
'n'
, $date)].
' '
.date(
'Y'
, $date);
}
/**
* Функция возвращает окончание для множественного числа слова на основании числа и массива окончаний
* @param $number Integer Число на основе которого нужно сформировать окончание
* @param $endingsArray Array Массив слов или окончаний для чисел (1, 4, 5),
* например array('яблоко', 'яблока', 'яблок')
* @return String
*/
function getNumEnding($number, $endingArray) {
$number = $number %
100
;
if
( $number>=
11
&& $number<=
19
) {
$ending = $endingArray[
2
];
}
else
{
$i = $number %
10
;
switch
($i) {
case
(
1
): $ending = $endingArray[
0
];
break
;
case
(
2
):
case
(
3
):
case
(
4
): $ending = $endingArray[
1
];
break
;
default
: $ending = $endingArray[
2
];
}
}
return
$ending;
}
/**
* Получение баннеров
*
* @access public
* @param массив с зонами ('zone1_', 'zone2_')
* @return array массив данных баннеров
*/
public
function getBanners($zones, $bnCount=
1
) {
$returnValue = array();
$requestZones = array();
$tempZones = array();
foreach ($zones as $zone) {
$cacheZone = $
this
->_mc->get(
'banner_'
. $zone);
if
( empty($cacheZone) ) {
$requestZones[] = $zone;
}
else
{
$cnt = count($cacheZone) < $bnCount ? count($cacheZone) : $bnCount;
$tempZones[$zone] = $
this
->setTempBanners($cacheZone, array_rand($cacheZone, $cnt));
}
}
if
( !empty($requestZones) ) {
$zoneString = implode(
'^'
, $requestZones);
$bannersData = Http::factory(CFG_SERVICE_BANNERS.
'?tags='
. $zoneString)->sendRequest()->getResponse(
'json'
);
if
( !empty($bannersData) ) {
foreach ($bannersData as $key => $value) {
$cnt = count($value) < $bnCount ? count($value) : $bnCount;
$tempZones[$key] = $
this
->setTempBanners($value, array_rand($value, $cnt));
$
this
->_mc->set(
'banner_'
. $key, $value, CFG_BANNER_CACHE_TIME);
}
}
}
foreach ($zones as $zone) {
$returnValue[$zone] = !empty($tempZones[$zone]) ? $tempZones[$zone] : array();
}
return
$returnValue;
}
private
function setTempBanners($banners, $keys) {
$returnValue = array();
if
( count($keys) >
1
) {
for
($ii=
0
; $ii<count($keys); $ii++) {
$returnValue[]= $banners[$keys[$ii]];
}
}
else
{
$returnValue[] = $banners[$keys];
}
return
$returnValue;
}
/**
* Формат даты для RSS канала
*
* @return string
*/
public
function formatRSSDate($date) {
$date = intval($date);
return
date(
'r'
, $date);
}
/**
* Получение ссылки на уменьшенный вариант картинки
*
* @return string
*/
public
function getResizeImagePath($url, $num) {
$image_sizes = require(CFG_APP_PATH .
"/config/image_sizes.php"
);
$file_path = explode(
'.'
, $url);
$extension = $file_path[sizeof($file_path) -
1
];
unset($file_path[sizeof($file_path) -
1
]);
$file_path = implode(
'.'
, $file_path);
$returnValue = $file_path .
'_'
. $image_sizes[$num] .
'.'
. $extension;
return
$returnValue;
}
/**
* Вывод информации в зависимости от формата
*
* @param array $data Набор данных для отображения пользователю
* @param string $template Путь к шаблону, требуется если формат вывода не JSON
* @return void
*/
public
function getByFormat($data, $template=array(), $encoding=
'utf8'
) {
$request = Registry::get(
'Request'
);
$format = $request->getQuery(
'format'
);
$download= $request->getQuery(
'download'
);
$render =
''
;
$
this
->_setHTTPHeaders($encoding, $format, $download);
switch
($format) {
case
'csv'
:
print $data;
break
;
case
'xml'
:
if
( !empty($template[
'xml'
]) ) {
$render = $
this
->fetch($template[
'xml'
], array(
'data'
=> $data));
}
break
;
case
'json'
:
default
:
$render = Json::encode($data,
false
);
break
;
}
print $
this
->_encode($render, $encoding);
}
private
function _setHTTPHeaders($encoding=
'utf-8'
, $format=
'json'
, $download=FALSE){
switch
($encoding) {
case
'utf-8'
:
case
'utf8'
:
$encoding =
'UTF-8'
;
break
;
case
'win'
:
default
:
$encoding =
'Windows-1251'
;
}
switch
($format) {
case
'xml'
:
$content_type =
'text/xml'
;
break
;
case
'csv'
:
$content_type =
'text/csv'
;
break
;
case
'json'
:
default
:
$content_type =
'application/json'
;
break
;
}
header(
'Content-Type: '
. $content_type .
'; charset='
. $encoding .
''
);
if
( strtolower($download) ==
'true'
) {
$filename = CFG_APP_NAME .
'-'
. date(
'Y-m-d_H-i-s'
) .
'.'
. $format;
header(
'Expires: 0'
);
header(
'Cache-Control: must-revalidate'
);
header(
'Content-Description: File Transfer'
);
header(
'Content-Type: application/'
. $format);
header(
'Content-Disposition: attachment; filename="'
. $filename .
'"'
);
}
}
private
function _encode($output, $encoding=
'utf8'
){
switch
($encoding) {
case
'utf8'
:
break
;
case
'win'
:
default
:
$output = iconv(
'UTF-8'
,
'cp1251'
, $output);
}
return
$output;
}
}
?>