*/';
protected $_layoutTemplate;
protected $_smarty;
protected $_smartyPluginPaths = array(
'lib/Smarty/Smarty/plugins',
'lib/Smarty/app_plugins'
);
protected $_content = array(
'htmlAttribs' => array(
'xmlns' => 'http://www.w3.org/1999/xhtml',
'class' => 'no-js',
),
'head' => array(
'keywords' => '',
'description' => '',
'meta' => array(),
'base' => '',
'stylesheet' => array(),
'script' => array(),
'inlineScript' => array(),
'readyFunctions' => array(),
'initFunctions' => array(),
),
'bodyAttribs' => array('onload' => 'bodyOnLoad()'),
'bodyTemplate' => null,
'menu' => null,
'ctrlMenu' => null,
'ITEMS' => array(),
);
protected $_titleFormat = '[{title}][{separator}Page {pageNumber}]{separator}{siteName}';
protected $_titleSeparator = ' :: ';
protected $_titleParts = [];
protected $_pageNumber;
protected $_siteName;
protected $_resourcesIgnoredAttribs = array(
'skipPacking', // якщо стилю чи скрипту в атрибутах передати 'skipPacking' => true, то Qs_Packer такі ресурси мерджити не буде
);
protected $_defaultGroupName = 'ITEMS';
protected $_groupName;
protected $_smartyPlugins = array(
'block' => array(),
);
protected $_templateRootPath;
protected $_outFilters = array();
protected $_templateDefines = array(
'BASE_URL', 'BASE_URL_LANGUAGE', 'CURRENT_PAGE', 'CURRENT_PAGE_FINAL', 'PARENT_PAGE', 'PARENT_PAGE_FINAL',
'BASE_PATH', 'CURRENT_LANGUAGE', 'SITE_LIVE', 'DEFAULT_LANGUAGE', 'NOINDEX_BEGIN', 'NOINDEX_END',
'SITE_REVISION'
);
protected $_scriptDefines = array(
'BASE_URL', 'BASE_URL_LANGUAGE', 'CURRENT_PAGE', 'CURRENT_PAGE_FINAL', 'SITE_LIVE', 'PARENT_PAGE',
'PARENT_PAGE_FINAL', 'CURRENT_LANGUAGE', 'DEFAULT_LANGUAGE', 'DEBUG', 'SITE_REVISION', 'OPTIMIZE_RESOURCES',
'USE_PACKED_RESOURCES', 'IS_MOBILE'
);
protected $_view;
protected $_authClassName;
protected $_authAdapterClassName;
/**
* @var Qs_Auth
*/
protected $_auth;
/**
* @var Qs_Auth_Adapter_DbTable
*/
protected $_authAdapter;
protected $_hasAuthentication = false;
protected $_options = array();
protected $_optimized = false;
protected $_hasAnalyticsScripts = false;
/**
* @var Qs_Lock_RoleObj
*/
protected $_lockObj;
/** @var array */
protected $_gtmValues = [];
public function __construct($options)
{
$this->setBase(Qs_Constant::get('BASE_URL') . '/');
$this->setOptions($options);
Qs_Options::setConstructorOptions($this);
$this->_init();
}
protected function _init()
{
/** @var $viewRenderer Zend_Controller_Action_Helper_ViewRenderer */
$viewRenderer = Zend_Controller_Action_HelperBroker::getStaticHelper('viewRenderer');
if (null == $viewRenderer->view) {
$viewRenderer->setView(Qs_View::getInstance());
}
$this->_initMessages();
if ($this->_hasAuthentication) {
$this->authenticate();
}
return $this;
}
protected function _initMessages()
{
if (Qs_Request::isXmlHttpRequest()) {
// Don't remove messages in Ajax requests
return $this;
}
$session = new Qs_Session_Namespace(Qs_Constant::get('CURRENT_PAGE'));
if (isset($session->message)) {
$this->displayMessage($session->message);
unset($session->message);
}
if (isset($session->error)) {
$this->displayError($session->error);
unset($session->error);
}
if (isset($session->attention)) {
$this->displayAttention($session->attention);
unset($session->attention);
}
return $this;
}
public function hasAnalyticsScripts()
{
return $this->_hasAnalyticsScripts;
}
public function setAnalyticsType($type)
{
if (!in_array($type, [self::ANALYTICS_TYPE_GOOGLE_ANALYTICS, self::ANALYTICS_TYPE_GOOGLE_TAG_MANAGER])) {
throw new Qs_Exception('Undefined analytics type');
}
$this->_analyticsType = $type;
return $this;
}
public function getAnalyticsType()
{
return $this->_analyticsType;
}
public function addGtmValues(array $values)
{
$this->_gtmValues = array_merge_recursive($this->_gtmValues, $values);
return $this;
}
public function setGtmValue($name, $value)
{
$this->_gtmValues[$name] = $value;
return $this;
}
public function isGtmEnabled()
{
return constant('SITE_LIVE') && $this->getAnalyticsType() == self::ANALYTICS_TYPE_GOOGLE_TAG_MANAGER;
}
public function getGtmValues()
{
return $this->_gtmValues;
}
public function setAuthentication($value)
{
$this->_hasAuthentication = (bool) $value;
return $this;
}
public function getAuthentication()
{
return (bool) $this->_hasAuthentication;
}
public function setOptions($options)
{
if (isset($options['options'])) {
unset($options['options']);
}
foreach ($options as $key => $value) {
$this->setOption($key, $value);
}
return $this;
}
public function getOptions()
{
return $this->_options;
}
public function setOption($name, $value)
{
$method = 'set' . ucfirst($name);
if (method_exists($this, $method)) {
$this->$method($value);
} else {
$this->_options[$name] = $value;
}
return $this;
}
public function getOption($name)
{
if (array_key_exists($name, $this->_options)) {
return $this->_options[$name];
}
return false;
}
public function setDescription($description)
{
$this->_content['head']['description'] = $description;
return $this;
}
public function appendHeader($append)
{
$this->setHeader($this->getHeader() . $append);
return $this;
}
public function setHeader($header)
{
$this->assign('header', $header);
return $this;
}
public function getHeader()
{
return $this->getTemplateVariable('header');
}
public function getTemplateVariables()
{
return $this->_content;
}
public function getTemplateVariable($name)
{
if (array_key_exists($name, $this->_content)) {
return $this->_content[$name];
}
return null;
}
public function setKeywords($keywords)
{
$this->_content['head']['keywords'] = $keywords;
return $this;
}
public function getView()
{
if (null === $this->_view) {
$this->_view = Qs_View::getInstance();
}
return $this->_view;
}
public function clearStylesheets()
{
$this->_content['head']['stylesheet'] = array();
return $this;
}
public function clearInlineScripts()
{
$this->_content['head']['inlineScript'] = array();
return $this;
}
public function clearInitFunctions()
{
$this->_content['head']['initFunctions'] = array();
return $this;
}
public function clearScripts()
{
$this->_content['head']['script'] = array();
return $this;
}
public function setStylesheets(array $list)
{
$this->clearStylesheets();
foreach ($list as $options) {
if (is_array($options)) {
call_user_func_array(array($this, 'addStylesheet'), $options);
} else {
$this->addStylesheet($options);
}
}
return $this;
}
public function addStylesheet($href, $_attribs = array(), $name = null)
{
$attribs = array(
'href' => $href,
'media' => 'all',
'type' => 'text/css',
'rel' => 'stylesheet',
);
if (null === $name) {
if (strncmp($href, 'css/', 4) == 0) {
$name = substr($href, 4);
$name = str_replace('.css', '', $name);
} else {
$name = $href;
}
}
if (isset($this->_content['head']['stylesheet'][$name])) {
return $this;
}
$this->_content['head']['stylesheet'][$name] = array_merge($attribs, $_attribs);
return $this;
}
public function setScripts(array $list)
{
$this->clearScripts();
foreach ($list as $options) {
if (is_array($options)) {
call_user_func_array(array($this, 'addScript'), $options);
} else {
$this->addScript($options);
}
}
return $this;
}
public function addScript($src, $_attribs = array(), $name = null)
{
$attribs = array(
'src' => $src, // Tag is not correctly works in IE8
'type' => 'text/javascript',
//'language' => 'JavaScript',
);
if (null === $name) {
if (strncmp($src, 'js/', 3) == 0) {
$name = substr($src, 3, -3);
} else {
$name = $src;
}
}
if (isset($this->_content['head']['script'][$name])) {
return $this;
}
$this->_content['head']['script'][$name] = array_merge($attribs, $_attribs);
return $this;
}
public function setInlineScript(array $list)
{
$this->clearInlineScripts();
foreach ($list as $options) {
if (is_array($options)) {
call_user_func_array(array($this, 'addInlineScript'), $options);
} else {
$this->addInlineScript($options);
}
}
return $this;
}
public function addInlineScript($name, $body, $_attribs = array())
{
$attribs = array(
'type' => 'text/javascript',
'beforeScripts' => false
);
$attribs = array_merge($attribs, $_attribs);
$beforeScripts = (int) $attribs['beforeScripts'];
unset($attribs['beforeScripts']);
$this->_content['head']['inlineScript'][$beforeScripts][$name] = array(
'attribs' => $attribs,
'body' => $body,
);
return $this;
}
protected function _getHeadPart($part)
{
if (array_key_exists($part, $this->_content['head'])) {
return $this->_content['head'][$part];
}
return null;
}
protected function _setHeadPart($part, $attribs)
{
$this->_content['head'][$part] = $attribs;
return $this;
}
public function appendTitle($append)
{
$this->_titleParts[] = $append;
return $this;
}
public function prependTitle($prepend)
{
array_unshift($this->_titleParts, $prepend);
return $this;
}
public function setTitle($title)
{
$this->_titleParts = [$title];
return $this;
}
/**
* @param string $titleFormat
* @return $this
*/
public function setTitleFormat($titleFormat)
{
$this->_titleFormat = $titleFormat;
return $this;
}
/**
* @return string
*/
public function getTitleFormat()
{
return $this->_titleFormat;
}
/**
* @param array $titleParts
* @return $this
*/
public function setTitleParts($titleParts)
{
$this->_titleParts = $titleParts;
return $this;
}
/**
* @return array
*/
public function getTitleParts()
{
return $this->_titleParts;
}
/**
* @param string $titleSeparator
* @return $this
*/
public function setTitleSeparator($titleSeparator)
{
$this->_titleSeparator = $titleSeparator;
return $this;
}
/**
* @return string
*/
public function getTitleSeparator()
{
return $this->_titleSeparator;
}
/**
* @param mixed $siteName
* @return $this
*/
public function setSiteName($siteName)
{
$this->_siteName = $siteName;
return $this;
}
/**
* @return mixed
*/
public function getSiteName()
{
if (null === $this->_siteName) {
$this->setSiteName(constant('SITE_NAME'));
}
return $this->_siteName;
}
/**
* @param mixed $pageNumber
* @return $this
*/
public function setPageNumber($pageNumber)
{
$this->_pageNumber = (int) $pageNumber;
return $this;
}
/**
* @return mixed
*/
public function getPageNumber()
{
return $this->_pageNumber;
}
public function getTitle()
{
return Qs_String::fill(
$this->getTitleFormat(),
[
'title' => implode($this->getTitleSeparator(), $this->getTitleParts()),
'separator' => $this->getTitleSeparator(),
'pageNumber' => $this->getPageNumber() > 1 ? $this->getPageNumber() : null,
'siteName' => $this->getSiteName()
],
'{}'
);
}
public function setBase($base)
{
return $this->_setHeadPart('base', $base);
}
public function getTemplateDirectory()
{
if (null == $this->_templateRootPath) {
$this->setTemplateRootPath(Qs_Constant::get('BASE_PATH') . '/tpl');
}
return $this->_templateRootPath;
}
public function setTemplateRootPath($directory)
{
$this->_templateRootPath = strval($directory);
if (is_object($this->_smarty)) {
$this->_smarty->template_dir = $this->_templateRootPath;
}
return $this;
}
public function getLayoutTemplate()
{
if (null === $this->_layoutTemplate) {
$this->setLayoutTemplate('index.tpl');
}
return $this->_layoutTemplate;
}
public function setLayoutTemplate($_template)
{
if ('.' === dirname($_template)) {
$template = $this->getTemplate($_template);
} else {
$template = $_template;
}
if (empty($template)) {
$message = 'Invalid layout template "' . $_template . '" not found in paths: "'
. implode('", "', $this->getTemplatePath()) . '".';
throw new Qs_Doc_Exception($message);
}
$this->_layoutTemplate = $template;
return $this;
}
public function getBodyTemplate()
{
if (null === $this->_getHeadPart('bodyTemplate')) {
$this->_setHeadPart('bodyTemplate', $this->getTemplate('Body/default.tpl'));
}
return $this->_getHeadPart('bodyTemplate');
}
public function setBodyTemplate($_template)
{
if ('.' === dirname($_template)) {
$template = $this->getTemplate('Body/' . $_template);
} else {
$template = $_template;
}
if (empty($template)) {
Qs_Debug::log('Body template "' . $_template . '" not found in paths: "'
. implode('", "', $this->getTemplatePath()) . '".');
if (false === ($template = $this->getTemplate('Body/default.tpl'))) {
$message = 'Body template "' . $_template . '" not found in paths: "'
. implode('", "', $this->getTemplatePath()) . '".';
throw new Qs_Doc_Exception($message);
}
}
$this->_setHeadPart('bodyTemplate', $template);
return $this;
}
/**
* @param string $var
* @param mixed $value
* @return Qs_Doc
*/
public function assign($var, $value = false)
{
$this->_content[$var] = $value;
return $this;
}
public function registerOutputFilter($filter)
{
$this->unregisterOutputFilter($filter);
$this->_outFilters[] = $filter;
return $this;
}
public function unregisterOutputFilter($filter)
{
$key = array_search($filter, $this->_outFilters);
if (false !== $key) {
unset($this->_outFilters[$key]);
}
return $this;
}
public function setOptimized($flag = true)
{
$this->_optimized = (bool) $flag;
return $this;
}
public function getOptimized()
{
return $this->_optimized;
}
protected function _optimize()
{
if ($this->_optimized || !Qs_Constant::get('OPTIMIZE_RESOURCES')) {
return $this;
}
if (false !== ($mergedStylesheets = Qs_Packer::getMergedStylesheets($this->_content['head']['stylesheet']))) {
$this->setStylesheets($mergedStylesheets);
}
if (false !== ($mergedScripts = Qs_Packer::getMergedScripts($this->_content['head']['script']))) {
$this->setScripts($mergedScripts);
}
$this->_optimized = true;
return $this;
}
public function fetch($template = null)
{
$this->_optimize();
$this->getSmarty()->assign('view', Qs_View::getInstance());
$this->getSmarty()->assign('AUTH_INFO', $this->getAuthIdentity());
$this->getSmarty()->assign('scriptDefines', $this->_scriptDefines);
$this->addInlineScript(
'isMobile',
'qs.constant("IS_TOUCHSCREEN", ' . ((Qs_Device::isTouchscreen()) ? 'true' : 'false') . ');'
);
if (Qs_Navigation::isEnabled() && false != ($nav = Qs_Navigation::get())) {
$this->getSmarty()->assign('NAVIGATION', $nav);
}
foreach ($this->_resourcesIgnoredAttribs as $attribute) {
foreach (array('stylesheet', 'script') as $resourceType) {
foreach ($this->_content['head'][$resourceType] as &$resource) {
if (array_key_exists($attribute, $resource)) {
unset($resource[$attribute]);
}
}
}
}
$html = $this->fetchTemplate($template);
foreach($this->_outFilters as $filter) {
$html = call_user_func_array($filter, array($html, $this));
}
if ('indexing' == Qs_Request::getHeader('ADAPTA_SPIDER') && 'y' == $this->getOption('isIndexing')) {
$html = $this->_doIndex($html);
}
return $html;
}
public function fetchTemplate($template = null)
{
if (is_array($this->_templateDefines) && !empty($this->_templateDefines)) {
foreach ($this->_templateDefines as $v) {
$this->assign($v, Qs_Constant::get($v));
}
}
$this->getSmarty()->assign($this->getTemplateVariables());
$this->getSmarty()->assign('DOC', $this);
$this->getSmarty()->assign('IS_TOUCHSCREEN', Qs_Device::isTouchscreen());
/** @var $debug Qs_Debug */
$debug = Zend_Registry::get('debug');
$debug->setErrorReporting($debug->getErrorReporting() ^ E_NOTICE);
$html = $this->getSmarty()->fetch((null === $template) ? $this->getLayoutTemplate() : $template);
$debug->restoreErrorReporting();
return $html;
}
protected function _doIndex($html)
{
/* метод поки нічого не робить, повернусь до нього коли буду робити пошук */
/*global $TIMER;
$html = trim($html);
if (!empty($html)) {
$html = preg_replace("/\
.*\<\/head\>/imsUu", '', $html);
$html = preg_replace("/\' . "\n ";
}
return $html;
}
public function renderStylesheets()
{
$html = '';
foreach ($this->_content['head']['stylesheet'] as $attribs) {
if (Qs_Constant::get('SITE_REVISION')) {
if (0 === strpos($attribs['href'], 'css/')) {
$attribs['href'] = 'css-' . Qs_Constant::get('SITE_REVISION') . '/'. substr($attribs['href'], 4);
}
}
$html .= ' $value) {
$html .= ' ' . $name . ' = "' . htmlspecialchars($value, ENT_COMPAT, 'UTF-8'). '"';
}
$html .= '/>' . "\n ";
}
return $html;
}
public function renderInlineScripts($indents = null, $beforeScripts = false)
{
$html = '';
$scriptsHtml = array();
$indents = (!$indents) ? 1 : $indents;
$indent = str_repeat(' ', $indents * 4);
$beforeScripts = (int) $beforeScripts;
if (is_array($this->_content['head']['inlineScript'][$beforeScripts])) {
foreach ($this->_content['head']['inlineScript'][$beforeScripts] as $name => $script) {
$attribs = '';
foreach ($script['attribs'] as $attribute => $attributeValue) {
$attribs .= $attribute . ' = "' . htmlspecialchars($attributeValue, ENT_COMPAT, 'UTF-8'). '" ';
}
$attribs = trim($attribs);
$body = PHP_EOL . '/* Inline Script: ' . $name . ' */' . PHP_EOL . $script['body'];
$scriptsHtml[$attribs] .= str_replace(PHP_EOL, PHP_EOL . $indent . $indent, $body) . PHP_EOL;
}
foreach ($scriptsHtml as $scriptAttribs => $scriptHtml) {
$html = '';
}
}
return $html;
}
protected function _renderInitFunctions(array $functionsSpec = null)
{
$functionsSpec = (null === $functionsSpec)
? $this->_content['head']['initFunctions']
: $functionsSpec;
$html = '';
foreach ($functionsSpec as $options) {
$row = $options['name'];
if (!empty($options['params'])) {
$params = array();
foreach ($options['params'] as $param) {
$params[]= Zend_Json::encode($param, false, array('enableJsonExprFinder' => true));
}
$row .= '(' . implode(', ', $params) . ');';
} else {
$row .= '();';
}
if (isset($options['new']) && $options['new']) {
$row = 'new ' . $row;
}
if (!empty($options['assign'])) {
$row = $options['assign'] . ' = ' . $row;
}
$html .= $row . "\n";
}
return $html;
}
public function renderInitFunctions()
{
return $this->_renderInitFunctions($this->_content['head']['initFunctions']);
}
public function renderReadyFunctions()
{
return $this->_renderInitFunctions($this->_content['head']['readyFunctions']);
}
function setTemplatePath($path)
{
$this->_templatePath = $path;
return $this;
}
public function getUserRole()
{
$role = null;
if ($this->hasAuth()) {
$role = $this->getAuth()->getRole();
}
return $role;
}
public function getUserId()
{
$id = null;
if ($this->hasAuth()) {
$id = $this->getAuth()->getData('id');
}
return $id;
}
public function getLockObj()
{
if (null === $this->_lockObj) {
$this->_lockObj = new Qs_Lock_RoleObj($this->getUserRole(), $this->getUserId(), Zend_Session::getId());
}
return $this->_lockObj;
}
public function setHtmlAttribs(array $attribs)
{
if (!is_array($attribs) || !Qs_Array::isAssoc($attribs)) {
throw new Qs_Exception('Attribs is not associative array');
}
$this->_content['htmlAttribs'] = $attribs;
return $this;
}
public function setHtmlAttrib($name, $value)
{
if (!is_string($name) || '' == $name) {
throw new Qs_Exception('Wrong attribute name');
}
if (!is_string($value) || '' == $value) {
throw new Qs_Exception('Wrong attribute value');
}
$this->_content['htmlAttribs'][$name] = $value;
return $this;
}
public function getHtmlAttrib($name)
{
return isset($this->_content['htmlAttribs'][$name]) ? $this->_content['htmlAttribs'][$name] : null;
}
public function getHtmlAttribs()
{
return $this->_content['htmlAttribs'];
}
public function addItemResources(Qs_Doc_Item $item)
{
$resources = array('script', 'inlineScript', 'stylesheet', 'readyFunction', 'initFunction', 'initObject');
foreach ($resources as $name) {
if (isset($item->{$name}) && is_array($item->{$name})) {
foreach ($item->{$name} as $params) {
call_user_func_array(array($this, 'add' . ucfirst($name)), (array) $params);
}
}
}
return $this;
}
public function getResources()
{
$script = '';
$head = $this->getTemplateVariable('head');
// foreach($head['stylesheet'] as $file) {
// $script .= "qs.resource.load('{$file['href']}');\n";
// }
// foreach ($head['script'] as $file) {
// $script .= "qs.resource.load('{$file['src']}');\n";
// }
foreach ($head['inlineScript'] as $inlineScript) {
$script .= "{$inlineScript}\n";
}
$script .= "\n" . $this->renderReadyFunctions();
$script .= "\n" . $this->renderInitFunctions();
return $script;
}
protected function _sendNoindexHeader()
{
header('X-Robots-Tag: noindex, nofollow');
return $this;
}
}