mirror of
https://github.com/Oreolek/ifhub.club.git
synced 2024-07-02 22:45:02 +03:00
934 lines
26 KiB
PHP
934 lines
26 KiB
PHP
<?php
|
||
/*-------------------------------------------------------
|
||
*
|
||
* LiveStreet Engine Social Networking
|
||
* Copyright © 2008 Mzhelskiy Maxim
|
||
*
|
||
*--------------------------------------------------------
|
||
*
|
||
* Official site: www.livestreet.ru
|
||
* Contact e-mail: rus.engine@gmail.com
|
||
*
|
||
* GNU General Public License, version 2:
|
||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||
*
|
||
---------------------------------------------------------
|
||
*/
|
||
|
||
require_once(Config::Get('path.root.engine').'/lib/external/Smarty-2.6.19/libs/Smarty.class.php');
|
||
require_once(Config::Get('path.root.engine').'/lib/external/CSSTidy-1.3/class.csstidy.php');
|
||
require_once(Config::Get('path.root.engine').'/lib/external/JSMin-1.1.1/jsmin.php');
|
||
|
||
/**
|
||
* Модуль обработки шаблонов используя шаблонизатор Smarty
|
||
*
|
||
*/
|
||
class LsViewer extends Module {
|
||
/**
|
||
* Объект Smarty
|
||
*
|
||
* @var Smarty
|
||
*/
|
||
protected $oSmarty;
|
||
/**
|
||
* Коллекция(массив) блоков
|
||
*
|
||
* @var array
|
||
*/
|
||
protected $aBlocks=array();
|
||
/**
|
||
* Массив правил организации блоков
|
||
*
|
||
* @var array
|
||
*/
|
||
protected $aBlockRules = array();
|
||
/**
|
||
* Стандартные настройки вывода js, css файлов
|
||
*
|
||
* @var array
|
||
*/
|
||
protected $aFilesDefault=array(
|
||
'js' => array(),
|
||
'css' => array()
|
||
);
|
||
/**
|
||
* Правила переопределение массивов js и css
|
||
*
|
||
* @var array
|
||
*/
|
||
protected $aFileRules=array();
|
||
/**
|
||
* Список JS, которые нужно добавить в начало и в конец
|
||
*
|
||
* @var array
|
||
*/
|
||
protected $aJsInclude = array(
|
||
'append' => array(),
|
||
'prepand' => array()
|
||
);
|
||
/**
|
||
* Список CSS, которые нужно добавить в начало и в конец
|
||
*
|
||
* @var array
|
||
*/
|
||
protected $aCssInclude = array(
|
||
'append' => array(),
|
||
'prepand' => array()
|
||
);
|
||
/**
|
||
* Каталог для кешировния js,css файлов
|
||
*
|
||
* @var string
|
||
*/
|
||
protected $sCacheDir='';
|
||
/**
|
||
* Объект CSSTidy для компрессии css-файлов
|
||
*
|
||
* @var csstidy
|
||
*/
|
||
protected $oCssCompressor = null;
|
||
/**
|
||
* Заголовок HTML страницы
|
||
*
|
||
* @var unknown_type
|
||
*/
|
||
protected $sHtmlTitle;
|
||
/**
|
||
* SEO ключевые слова страницы
|
||
*
|
||
* @var unknown_type
|
||
*/
|
||
protected $sHtmlKeywords;
|
||
/**
|
||
* SEO описание страницы
|
||
*
|
||
* @var unknown_type
|
||
*/
|
||
protected $sHtmlDescription;
|
||
|
||
/**
|
||
* Разделитель заголовка HTML страницы
|
||
*
|
||
* @var unknown_type
|
||
*/
|
||
protected $sHtmlTitleSeparation=' / ';
|
||
|
||
/**
|
||
* Альтернативный адрес страницы по RSS
|
||
*
|
||
* @var array
|
||
*/
|
||
protected $aHtmlRssAlternate=null;
|
||
|
||
/**
|
||
* Html код для подключения js,css
|
||
*
|
||
* @var string
|
||
*/
|
||
protected $sHtmlHeadFiles='';
|
||
|
||
/**
|
||
* Переменные для отдачи при ajax запросе
|
||
*
|
||
* @var unknown_type
|
||
*/
|
||
protected $aVarsAjax=array();
|
||
/**
|
||
* Определяет тип ответа при ajax запросе
|
||
*
|
||
* @var unknown_type
|
||
*/
|
||
protected $sResponseAjax=null;
|
||
/**
|
||
* Инициализация модуля
|
||
*
|
||
*/
|
||
public function Init() {
|
||
/**
|
||
* Заголовок HTML страницы
|
||
*/
|
||
$this->sHtmlTitle=Config::Get('view.name');
|
||
/**
|
||
* SEO ключевые слова страницы
|
||
*/
|
||
$this->sHtmlKeywords=Config::Get('view.keywords');
|
||
/**
|
||
* SEO описание страницы
|
||
*/
|
||
$this->sHtmlDescription=Config::Get('view.description');
|
||
|
||
/**
|
||
* Создаём объект Smarty и устанавливаем необходиму параметры
|
||
*/
|
||
$this->oSmarty = new Smarty();
|
||
$this->oSmarty->template_dir=Config::Get('path.smarty.template');
|
||
$this->oSmarty->compile_dir=Config::Get('path.smarty.compiled');
|
||
$this->oSmarty->cache_dir=Config::Get('path.smarty.cache');
|
||
$this->oSmarty->plugins_dir=array(Config::Get('path.smarty.plug'),'plugins');
|
||
/**
|
||
* Подключаем к Smarty небольшой плагинчик форматирования даты
|
||
*/
|
||
$this->oSmarty->register_function("date_format", "func_date_smarty");
|
||
/**
|
||
* Получаем настройки блоков
|
||
*/
|
||
$this->InitBlockParams();
|
||
/**
|
||
* Получаем настройки JS, CSS файлов
|
||
*/
|
||
$this->InitFileParams();
|
||
$this->sCacheDir = Config::Get('path.smarty.cache');
|
||
}
|
||
|
||
/**
|
||
* Выполняет загрузку необходимый(возможно даже системный :)) переменных в шалон
|
||
*
|
||
*/
|
||
public function VarAssign() {
|
||
/**
|
||
* Загружаем весь $_REQUEST, предварительно обработав его функцией func_htmlspecialchars()
|
||
*/
|
||
$aRequest=$_REQUEST;
|
||
func_htmlspecialchars($aRequest);
|
||
$this->Assign("_aRequest",$aRequest);
|
||
/**
|
||
* Параметры стандартной сессии
|
||
*/
|
||
$this->Assign("_sPhpSessionName",session_name());
|
||
$this->Assign("_sPhpSessionId",session_id());
|
||
/**
|
||
* Загружаем часть конфигурации
|
||
*/
|
||
$aConfig=Config::Get();
|
||
foreach ((array)Config::Get('view.no_assign') as $sGroup) {
|
||
unset($aConfig[$sGroup]);
|
||
}
|
||
$this->Assign("aConfig",$aConfig);
|
||
|
||
/**
|
||
* Загружаем роутинг с учетом правил rewrite
|
||
*/
|
||
$aRouter=array();
|
||
foreach ($aConfig['router']['page'] as $sPage=>$aAction) {
|
||
$aRouter[$sPage]=Router::GetPath($sPage);
|
||
}
|
||
$this->Assign("aRouter",$aRouter);
|
||
/**
|
||
* Загружаем в шаблон блоки
|
||
*/
|
||
$this->Assign("aBlocks",$this->aBlocks);
|
||
/**
|
||
* Загружаем HTML заголовки
|
||
*/
|
||
$this->Assign("sHtmlTitle",htmlspecialchars($this->sHtmlTitle));
|
||
$this->Assign("sHtmlKeywords",htmlspecialchars($this->sHtmlKeywords));
|
||
$this->Assign("sHtmlDescription",htmlspecialchars($this->sHtmlDescription));
|
||
$this->Assign("sHtmlHeadFiles",$this->sHtmlHeadFiles);
|
||
$this->Assign("aHtmlRssAlternate",$this->aHtmlRssAlternate);
|
||
|
||
}
|
||
|
||
/**
|
||
* Выводит на экран(браузер) обработанный шаблон
|
||
*
|
||
* @param string $sTemplate
|
||
*/
|
||
public function Display($sTemplate) {
|
||
if ($this->sResponseAjax) {
|
||
$this->DisplayAjax($this->sResponseAjax);
|
||
}
|
||
/**
|
||
* Если шаблон найден то выводим, иначе ошибка
|
||
*/
|
||
if ($this->TemplateExists($sTemplate)) {
|
||
$this->oSmarty->display($sTemplate);
|
||
} else {
|
||
throw new Exception($this->Lang_Get('system_error_template').': '.$sTemplate);
|
||
}
|
||
}
|
||
/**
|
||
* Ответ на ajax запрос
|
||
*
|
||
* @param unknown_type $sType - jsHttpRequest или json
|
||
*/
|
||
public function DisplayAjax($sType='jsHttpRequest') {
|
||
/**
|
||
* Загружаем статус ответа и сообщение
|
||
*/
|
||
$bStateError=false;
|
||
$sMsgTitle='';
|
||
$sMsg='';
|
||
$aMsgError=$this->Message_GetError();
|
||
$aMsgNotice=$this->Message_GetNotice();
|
||
if (count($aMsgError)>0) {
|
||
$bStateError=true;
|
||
$sMsgTitle=$aMsgError[0]['title'];
|
||
$sMsg=$aMsgError[0]['msg'];
|
||
}
|
||
if (count($aMsgNotice)>0) {
|
||
$sMsgTitle=$aMsgNotice[0]['title'];
|
||
$sMsg=$aMsgNotice[0]['msg'];
|
||
}
|
||
$this->AssignAjax('sMsgTitle',$sMsgTitle);
|
||
$this->AssignAjax('sMsg',$sMsg);
|
||
$this->AssignAjax('bStateError',$bStateError);
|
||
if ($sType=='jsHttpRequest') {
|
||
foreach ($this->aVarsAjax as $key => $value) {
|
||
$GLOBALS['_RESULT'][$key]=$value;
|
||
}
|
||
} elseif ($sType=='json') {
|
||
if (!headers_sent()) {
|
||
header('Content-type: application/json');
|
||
}
|
||
echo json_encode($this->aVarsAjax);
|
||
}
|
||
exit();
|
||
}
|
||
/**
|
||
* Устанавливает тип отдачи при ajax запросе, если null то выполняется обычный вывод шаблона в браузер
|
||
*
|
||
* @param unknown_type $sResponseAjax
|
||
*/
|
||
public function SetResponseAjax($sResponseAjax='jsHttpRequest') {
|
||
/**
|
||
* Проверка на безопасную обработку ajax запроса
|
||
*/
|
||
if ($sResponseAjax) {
|
||
if ($sResponseAjax=='jsHttpRequest') {
|
||
require_once(Config::Get('path.root.engine')."/lib/external/JsHttpRequest/JsHttpRequest.php");
|
||
$JsHttpRequest = new JsHttpRequest("UTF-8");
|
||
}
|
||
$this->Security_ValidateSendForm();
|
||
}
|
||
$this->sResponseAjax=$sResponseAjax;
|
||
}
|
||
/**
|
||
* Загружает переменную в шаблон
|
||
*
|
||
* @param string $sName
|
||
* @param unknown_type $value
|
||
*/
|
||
public function Assign($sName,$value) {
|
||
$this->oSmarty->assign($sName, $value);
|
||
}
|
||
/**
|
||
* Загружаем переменную в ajax ответ
|
||
*
|
||
* @param unknown_type $sName
|
||
* @param unknown_type $value
|
||
*/
|
||
public function AssignAjax($sName,$value) {
|
||
$this->aVarsAjax[$sName]=$value;
|
||
}
|
||
/**
|
||
* Возвращает обработанный шаблон
|
||
*
|
||
* @param string $sTemplate
|
||
* @return string
|
||
*/
|
||
public function Fetch($sTemplate) {
|
||
return $this->oSmarty->fetch($sTemplate);
|
||
}
|
||
/**
|
||
* Проверяет существование шаблона
|
||
*
|
||
* @param string $sTemplate
|
||
* @return bool
|
||
*/
|
||
public function TemplateExists($sTemplate) {
|
||
return $this->oSmarty->template_exists($sTemplate);
|
||
}
|
||
/**
|
||
* Инициализируем параметры отображения блоков
|
||
*/
|
||
protected function InitBlockParams() {
|
||
$this->aBlockRules = Config::Get('block');
|
||
}
|
||
/**
|
||
* Добавляет блок для отображения
|
||
*
|
||
* @param string $sGroup
|
||
* @param string $sName
|
||
* @param array $aParams - параметры блока, которые будут переданы обработчику блока
|
||
* @param int $iPriority
|
||
* @return bool
|
||
*/
|
||
public function AddBlock($sGroup,$sName,$aParams=array(),$iPriority=5) {
|
||
/**
|
||
* Если смогли определить тип блока то добавляем его
|
||
*/
|
||
$sType=$this->DefineTypeBlock($sName);
|
||
if ($sType=='undefined') {
|
||
return false;
|
||
}
|
||
$this->aBlocks[$sGroup][$sName]=array(
|
||
'type' => $sType,
|
||
'name' => $sName,
|
||
'params' => $aParams,
|
||
'priority' => $iPriority,
|
||
);
|
||
return true;
|
||
}
|
||
|
||
/**
|
||
* Добавляет список блоков
|
||
*
|
||
* @param array $aBlocks
|
||
*/
|
||
public function AddBlocks($sGroup,$aBlocks) {
|
||
/**
|
||
* Удаляем ранее добавленые блоки
|
||
*/
|
||
$this->ClearBlocks($sGroup);
|
||
foreach ($aBlocks as $sBlock) {
|
||
$this->AddBlock($sGroup,$sBlock);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Удаляет блоки группы
|
||
*
|
||
*/
|
||
public function ClearBlocks($sGroup) {
|
||
$this->aBlocks[$sGroup]=array();
|
||
}
|
||
/**
|
||
* Удаляет блоки всех групп
|
||
*
|
||
* @param unknown_type $sGroup
|
||
*/
|
||
public function ClearBlocksAll() {
|
||
foreach ($this->aBlocks as $sGroup => $aBlock) {
|
||
$this->aBlocks[$sGroup]=array();
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Определяет тип блока
|
||
*
|
||
* @param string $sName
|
||
* @return string('block','template','undefined')
|
||
*/
|
||
protected function DefineTypeBlock($sName) {
|
||
if ($this->TemplateExists('block.'.$sName.'.tpl')) {
|
||
/**
|
||
* Если найден шаблон вида block.name.tpl то считаем что тип 'block'
|
||
*/
|
||
return 'block';
|
||
} elseif ($this->TemplateExists($sName)) {
|
||
/**
|
||
* Если найден шаблон по имени блока то считаем его простым шаблоном
|
||
*/
|
||
return 'template';
|
||
} else {
|
||
/**
|
||
* Считаем что тип не определен
|
||
*/
|
||
throw new Exception($this->Lang_Get('system_error_template_block').': '.$sName);
|
||
return 'undefined';
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Анализируем правила и наборы массивов
|
||
* получаем окончательные списки блоков
|
||
*/
|
||
protected function BuildBlocks() {
|
||
$sAction = strtolower(Router::GetAction());
|
||
$sEvent = strtolower(Router::GetActionEvent());
|
||
|
||
foreach($this->aBlockRules as $sName=>$aRule) {
|
||
$bUse=false;
|
||
/**
|
||
* Если в правиле не указан список блоков, нам такое не нужно
|
||
*/
|
||
if(!array_key_exists('blocks',$aRule)) continue;
|
||
/**
|
||
* Если не задан action для исполнения,
|
||
* или текущий не входит в перечисленные в правиле
|
||
* то выбираем следующее правило
|
||
*/
|
||
if(!$aRule['action']) continue;
|
||
if(in_array($sAction, (array)$aRule['action'])) $bUse=true;
|
||
if(array_key_exists($sAction,(array)$aRule['action'])) {
|
||
/**
|
||
* Если задан список event`ов и текущий в него не входит,
|
||
* переходи к следующему действию. Если список не задан,
|
||
* считаем что правило действует для всех event`ов.
|
||
*/
|
||
if(!$sEvent) {
|
||
$bUse=true;
|
||
} else {
|
||
foreach ((array)$aRule['action'][$sAction] as $sEventPreg) {
|
||
if(substr($sEventPreg,0,1)!='/') {
|
||
/**
|
||
* значит это название event`a
|
||
*/
|
||
if($sEvent==$sEventPreg) { $bUse=true; break; }
|
||
} else {
|
||
/**
|
||
* это регулярное выражение
|
||
*/
|
||
if(preg_match($sEventPreg,$sEvent)) { $bUse=true; break; }
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
if($bUse){
|
||
/**
|
||
* Добавляем все блоки, указанные в параметре blocks
|
||
*/
|
||
foreach ($aRule['blocks'] as $sGroup => $aBlocks) {
|
||
foreach ((array)$aBlocks as $sName=>$aParams) {
|
||
/**
|
||
* Если $aParams не являются массивом, значит передано только имя блока
|
||
*/
|
||
if(!is_array($aParams)) {
|
||
$this->AddBlock($sGroup,$aParams);
|
||
} else {
|
||
$this->AddBlock(
|
||
$sGroup,$sName,
|
||
isset($aParams['params']) ? $aParams['params'] : array(),
|
||
isset($aParams['priority']) ? $aParams['priority'] : 5
|
||
);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
/**
|
||
* Теперь сортируем блоки по приоритетности
|
||
*/
|
||
foreach($this->aBlocks as $sGroup=>$aBlocks) {
|
||
uasort($aBlocks,array(&$this,'SortBlocks'));
|
||
$this->aBlocks[$sGroup] = array_reverse($aBlocks);
|
||
}
|
||
return true;
|
||
}
|
||
|
||
/**
|
||
* Вспомагательная функция для сортировки блоков по приоритетности
|
||
*
|
||
* @param array $a
|
||
* @param array $b
|
||
* @return int
|
||
*/
|
||
protected function SortBlocks($a,$b) {
|
||
return ($a["priority"]-$b["priority"]);
|
||
}
|
||
/**
|
||
* Инициализирует параметры вывода js- и css- файлов
|
||
*/
|
||
protected function InitFileParams() {
|
||
$this->aFilesDefault = Config::Get('head.default');
|
||
$this->aFileRules = Config::Get('head.rules');
|
||
}
|
||
/**
|
||
* Создает css-компрессор и инициализирует его конфигурацию
|
||
*
|
||
* @return bool
|
||
*/
|
||
protected function InitCssCompressor() {
|
||
/**
|
||
* Получаем параметры из конфигурации
|
||
*/
|
||
$aParams = Config::Get('compress.css');
|
||
$this->oCssCompressor =($aParams['use']) ? new csstidy() : null;
|
||
/**
|
||
* Если компрессор не создан, завершаем работу инициализатора
|
||
*/
|
||
if(!$this->oCssCompressor) return false;
|
||
/**
|
||
* Устанавливаем параметры
|
||
*/
|
||
$this->oCssCompressor->set_cfg('case_properties', $aParams['case_properties']);
|
||
$this->oCssCompressor->set_cfg('merge_selectors', $aParams['merge_selectors']);
|
||
$this->oCssCompressor->set_cfg('optimise_shorthands', $aParams['optimise_shorthands']);
|
||
$this->oCssCompressor->set_cfg('remove_last_;', $aParams['remove_last_;']);
|
||
$this->oCssCompressor->set_cfg('css_level', $aParams['css_level']);
|
||
$this->oCssCompressor->load_template($aParams['template']);
|
||
|
||
return true;
|
||
}
|
||
|
||
/**
|
||
* Функции добавления js-скриптов и css-каскадов
|
||
*/
|
||
public function AppendScript($sJs) {
|
||
$this->aJsInclude['append'][] = $sJs;
|
||
}
|
||
public function PrepandScript($sJs) {
|
||
$this->aJsInclude['prepend'][] = $sJs;
|
||
}
|
||
public function AppendStyle($sCss) {
|
||
$this->aCssInclude['append'][] = $sCss;
|
||
}
|
||
public function PrepandStyle($sCss) {
|
||
$this->aCssInclude['prepend'][] = $sCss;
|
||
}
|
||
|
||
/**
|
||
* Строит массив для подключения css и js,
|
||
* преобразовывает их в строку для HTML
|
||
*
|
||
* @return bool
|
||
*/
|
||
protected function BuildHeadFiles() {
|
||
$aPath = Router::GetPathWebCurrent();
|
||
$aPath = rtrim($aPath,"/")."/";
|
||
|
||
/**
|
||
* По умолчанию имеем дефаултовые настройки
|
||
*/
|
||
$aResult = $this->aFilesDefault;
|
||
|
||
foreach((array)$this->aFileRules as $sName => $aRule) {
|
||
if(!$aRule['path']) continue;
|
||
|
||
foreach((array)$aRule['path'] as $sRulePath) {
|
||
$sPattern = "~".str_replace(array('/','*'),array('\/','[\w+]'), $sRulePath)."~";
|
||
if(preg_match($sPattern, $aPath)) {
|
||
/**
|
||
* Преобразование JS
|
||
*/
|
||
if(isset($aRule['js']['empty']) && $aRule['js']['empty']) $aResult['js']=array();
|
||
if(isset($aRule['js']['exclude']) && is_array($aRule['js']['exclude'])) $aResult['js']=array_diff($aResult['js'],$aRule['js']['exclude']);
|
||
if(isset($aRule['js']['include']) && is_array($aRule['js']['include'])) $aResult['js']=array_merge($aResult['js'],$aRule['js']['include']);
|
||
|
||
/**
|
||
* Преобразование CSS
|
||
*/
|
||
if(isset($aRule['css']['empty']) && $aRule['css']['empty']) $aResult['css']=array();
|
||
if(isset($aRule['css']['exclude']) && is_array($aRule['css']['exclude'])) $aResult['css']=array_diff($aResult['css'],$aRule['css']['exclude']);
|
||
if(isset($aRule['css']['include']) && is_array($aRule['css']['include'])) $aResult['css']=array_merge($aResult['css'],$aRule['css']['include']);
|
||
|
||
/**
|
||
* Продолжаем поиск
|
||
*/
|
||
if(isset($aRule['stop'])) {
|
||
break(2);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Добавляем скрипты и css из массивов
|
||
*/
|
||
$aResult['js'] = array_values(
|
||
array_merge(
|
||
(array)$this->aJsInclude['append'],
|
||
(array)$aResult['js'],
|
||
(array)$this->aJsInclude['prepand']
|
||
)
|
||
);
|
||
$aResult['css'] = array_values(
|
||
array_merge(
|
||
(array)$this->aCssInclude['append'],
|
||
(array)$aResult['css'],
|
||
(array)$this->aCssInclude['prepand']
|
||
)
|
||
);
|
||
|
||
/**
|
||
* Сливаем файлы в один
|
||
*/
|
||
$aResult['js'] = array($this->Compress($aResult['js'],'js'));
|
||
$aResult['css'] = array($this->Compress($aResult['css'],'css'));
|
||
/**
|
||
* Получаем HTML код
|
||
*/
|
||
$sHtmlHeadFiles = $this->BuildHtmlHeadFiles($aResult);
|
||
$this->SetHtmlHeadFiles($sHtmlHeadFiles);
|
||
return true;
|
||
}
|
||
|
||
/**
|
||
* Сжимает все переданные файлы в один,
|
||
* использует файловое кеширование
|
||
*
|
||
* @param array $aFiles
|
||
* @param string $sType
|
||
* @return array
|
||
*/
|
||
protected function Compress($aFiles,$sType) {
|
||
$sCacheName = $this->sCacheDir."/".md5(serialize($aFiles).'_head').".{$sType}";
|
||
$sPathServer = Config::Get('path.root.server');
|
||
$sPathWeb = Config::Get('path.root.web');
|
||
/**
|
||
* Если кеш существует, то берем из кеша
|
||
*/
|
||
if(!file_exists($sCacheName)) {
|
||
/**
|
||
* Считываем содержимое
|
||
*/
|
||
ob_start();
|
||
foreach ($aFiles as $sFile) {
|
||
$sFile=str_replace($sPathWeb,$sPathServer,$sFile);
|
||
list($sFile,)=explode('?',$sFile,2);
|
||
/**
|
||
* Если файл существует, обрабатываем
|
||
*/
|
||
if(file_exists($sFile)) {
|
||
$sFileContent = file_get_contents($sFile);
|
||
if($sType=='css'){
|
||
$sFileContent = $this->ConvertPathInCss($sFileContent,$sFile);
|
||
$sFileContent = $this->CompressCss($sFileContent);
|
||
} elseif($sType=='js') {
|
||
$sFileContent = $this->CompressJs($sFileContent);
|
||
}
|
||
print $sFileContent;
|
||
}
|
||
}
|
||
$sContent = ob_get_contents();
|
||
ob_end_clean();
|
||
|
||
/**
|
||
* Создаем новый файл и сливаем туда содержимое
|
||
*/
|
||
file_put_contents($sCacheName,$sContent);
|
||
}
|
||
/**
|
||
* Возвращаем имя файла, заменяя адрес сервера на веб-адрес
|
||
*/
|
||
return str_replace($sPathServer,$sPathWeb,$sCacheName);
|
||
}
|
||
|
||
/**
|
||
* Выполняет преобразование CSS файлов
|
||
*
|
||
* @param string $sContent
|
||
* @return string
|
||
*/
|
||
protected function CompressCss($sContent) {
|
||
$this->InitCssCompressor();
|
||
if(!$this->oCssCompressor) return $sContent;
|
||
/**
|
||
* Парсим css и отдаем обработанный результат
|
||
*/
|
||
$this->oCssCompressor->parse($sContent);
|
||
$output=$this->oCssCompressor->print->plain();
|
||
|
||
return $output;
|
||
}
|
||
|
||
/**
|
||
* Конвертирует относительные пути в css файлах в абсолютные
|
||
*
|
||
* @param string $content
|
||
* @param string $path
|
||
* @return string
|
||
*/
|
||
protected function ConvertPathInCss($sContent,$sPath) {
|
||
preg_match_all( "/url\((.*?)\)/is",$sContent,$aMatches);
|
||
if(count($aMatches[1])==0) return $sContent;
|
||
|
||
/**
|
||
* Обрабатываем список файлов
|
||
*/
|
||
$aFiles = array_unique($aMatches[1]);
|
||
$sDir = dirname($sPath)."/";
|
||
|
||
foreach($aFiles as $sFilePath) {
|
||
/**
|
||
* Don't touch data URIs
|
||
*/
|
||
if(strstr($sFilePath,"data:")) {
|
||
continue;
|
||
}
|
||
$sFilePathAbsolute = preg_replace("@'|\"@","",trim($sFilePath));
|
||
/**
|
||
* Если путь является абсолютным, необрабатываем
|
||
*/
|
||
if(substr($sFilePathAbsolute,0,1) == "/" || substr($sFilePathAbsolute,0,5) == "http:") {
|
||
continue;
|
||
}
|
||
/**
|
||
* Обрабатываем относительный путь
|
||
*/
|
||
$sFilePathAbsolute = $this->GetWebPath(realpath($sDir.$sFilePathAbsolute));
|
||
/**
|
||
* Заменяем относительные пути в файле на абсолютные
|
||
*/
|
||
$sContent = str_replace($sFilePath,$sFilePathAbsolute,$sContent);
|
||
}
|
||
return $sContent;
|
||
}
|
||
|
||
/**
|
||
* Выполняет преобразование JS файла
|
||
*
|
||
* @param string $sContent
|
||
* @return string
|
||
*/
|
||
protected function CompressJs($sContent) {
|
||
$sContent = (Config::Get('compress.js.use'))
|
||
? JSMin::minify($sContent)
|
||
: $sContent;
|
||
/**
|
||
* Добавляем разделитель в конце файла
|
||
* с расчетом на возможное их слияние в будущем
|
||
*/
|
||
return rtrim($sContent,";").";".PHP_EOL;
|
||
}
|
||
|
||
/**
|
||
* Преобразует абсолютный путь к файлу в WEB-вариант
|
||
*
|
||
* @param string $sFile
|
||
* @return string
|
||
*/
|
||
protected function GetWebPath($sFile) {
|
||
$sFile=str_replace(DIRECTORY_SEPARATOR,'/',$sFile);
|
||
return str_replace(Config::Get('path.root.server'),Config::Get('path.root.web'),$sFile);
|
||
}
|
||
|
||
/**
|
||
* Строит HTML код по переданному массиву файлов
|
||
*
|
||
* @param array $aFileList
|
||
* @return string
|
||
*/
|
||
protected function BuildHtmlHeadFiles($aFileList) {
|
||
$sHeader='';
|
||
|
||
foreach ((array)$aFileList['css'] as $sCss) {
|
||
$sHeader.="<link rel='stylesheet' type='text/css' href='{$sCss}' />".PHP_EOL;
|
||
}
|
||
foreach((array)$aFileList['js'] as $sJs) {
|
||
$sHeader.="<script type='text/javascript' src='{$sJs}'></script>".PHP_EOL;
|
||
}
|
||
|
||
return $sHeader;
|
||
}
|
||
|
||
public function SetHtmlHeadFiles($sText) {
|
||
$this->sHtmlHeadFiles=$sText;
|
||
}
|
||
|
||
/**
|
||
* Устанавливаем заголовок страницы(тег <title>)
|
||
*
|
||
* @param string $sText
|
||
*/
|
||
public function SetHtmlTitle($sText) {
|
||
$this->sHtmlTitle=$sText;
|
||
}
|
||
/**
|
||
* Добавляет часть заголовка страницы через разделитель
|
||
*
|
||
* @param string $sText
|
||
*/
|
||
public function AddHtmlTitle($sText) {
|
||
$this->sHtmlTitle=$sText.$this->sHtmlTitleSeparation.$this->sHtmlTitle;
|
||
}
|
||
/**
|
||
* Возвращает текущий заголовок страницы
|
||
*
|
||
* @return unknown
|
||
*/
|
||
public function GetHtmlTitle() {
|
||
return $this->sHtmlTitle;
|
||
}
|
||
/**
|
||
* Устанавливает ключевые слова keywords
|
||
*
|
||
* @param string $sText
|
||
*/
|
||
public function SetHtmlKeywords($sText) {
|
||
$this->sHtmlKeywords=$sText;
|
||
}
|
||
/**
|
||
* Устанавливает описание страницы desciption
|
||
*
|
||
* @param string $sText
|
||
*/
|
||
public function SetHtmlDescription($sText) {
|
||
$this->sHtmlDescription=$sText;
|
||
}
|
||
/**
|
||
* Устанавливает альтернативный адрес страницы по RSS
|
||
*
|
||
* @param string $sText
|
||
*/
|
||
public function SetHtmlRssAlternate($sUrl,$sTitle) {
|
||
$this->aHtmlRssAlternate['title']=htmlspecialchars($sTitle);
|
||
$this->aHtmlRssAlternate['url']=htmlspecialchars($sUrl);
|
||
}
|
||
/**
|
||
* Формирует постраничный вывод
|
||
*
|
||
* @param int $iCount
|
||
* @param int $iCurrentPage
|
||
* @param int $iCountPerPage
|
||
* @param int $iCountPageLine
|
||
* @param string $sBaseUrl
|
||
* @param array(name=>value) $aGetParamsList
|
||
* @return array()
|
||
*/
|
||
public function MakePaging($iCount,$iCurrentPage,$iCountPerPage,$iCountPageLine,$sBaseUrl,$aGetParamsList=array()) {
|
||
if ($iCount==0) {
|
||
return false;
|
||
}
|
||
|
||
$iCountPage=ceil($iCount/$iCountPerPage);
|
||
if (!preg_match("/^[1-9]\d*$/i",$iCurrentPage)) {
|
||
$iCurrentPage=1;
|
||
}
|
||
if ($iCurrentPage>$iCountPage) {
|
||
$iCurrentPage=$iCountPage;
|
||
}
|
||
|
||
$aPagesLeft=array();
|
||
$iTemp=$iCurrentPage-$iCountPageLine;
|
||
$iTemp = $iTemp<1 ? 1 : $iTemp;
|
||
for ($i=$iTemp;$i<$iCurrentPage;$i++) {
|
||
$aPagesLeft[]=$i;
|
||
}
|
||
|
||
$aPagesRight=array();
|
||
for ($i=$iCurrentPage+1;$i<=$iCurrentPage+$iCountPageLine and $i<=$iCountPage;$i++) {
|
||
$aPagesRight[]=$i;
|
||
}
|
||
|
||
$iNextPage = $iCurrentPage<$iCountPage ? $iCurrentPage+1 : false;
|
||
$iPrevPage = $iCurrentPage>1 ? $iCurrentPage-1 : false;
|
||
|
||
$sGetParams='';
|
||
foreach ($aGetParamsList as $sName => $sValue) {
|
||
$sGetParams.=$sName.'='.urlencode($sValue).'&';
|
||
}
|
||
if ($sGetParams!='') {
|
||
$sGetParams='?'.trim($sGetParams,'&');
|
||
}
|
||
|
||
$aPaging=array(
|
||
'aPagesLeft' => $aPagesLeft,
|
||
'aPagesRight' => $aPagesRight,
|
||
'iCountPage' => $iCountPage,
|
||
'iCurrentPage' => $iCurrentPage,
|
||
'iNextPage' => $iNextPage,
|
||
'iPrevPage' => $iPrevPage,
|
||
'sBaseUrl' => $sBaseUrl,
|
||
'sGetParams' => $sGetParams,
|
||
);
|
||
return $aPaging;
|
||
}
|
||
/**
|
||
* Загружаем переменные в шаблон при завершении модуля
|
||
*
|
||
*/
|
||
public function Shutdown() {
|
||
/**
|
||
* Добавляем блоки по предзагруженным правилам
|
||
*/
|
||
$this->BuildBlocks();
|
||
/**
|
||
* Добавляем JS и CSS по предписанным правилам
|
||
*/
|
||
$this->BuildHeadFiles();
|
||
$this->VarAssign();
|
||
}
|
||
}
|
||
?>
|