*/';
protected $_layoutTemplate;
protected $_smarty;
protected $_smartyPluginPaths = [
'lib/Smarty/Smarty/plugins',
'lib/Smarty/app_plugins',
];
protected $_content = [
'htmlAttribs' => [
'xmlns' => 'http://www.w3.org/1999/xhtml',
'class' => 'no-js',
'lang' => 'en-us',
],
'head' => [
'keywords' => '',
'description' => '',
'meta' => [],
'base' => '',
'stylesheet' => [],
'script' => [],
'inlineScript' => [],
'readyFunctions' => [],
'initFunctions' => [],
],
'bodyAttribs' => ['onload' => 'bodyOnLoad()'],
'bodyTemplate' => null,
'menu' => null,
'ctrlMenu' => null,
'ITEMS' => [],
];
protected $_widgets = [];
protected $_titleFormat = '[{title}][{separator}Page {pageNumber}][{titleSuffix}]';
protected $_titleSeparator = ' :: ';
protected $_titleParts = [];
protected $_pageNumber;
protected $_siteName;
protected $_titleSuffix;
protected $_resourcesIgnoredAttribs = [
'skipPacking', // якщо стилю чи скрипту в атрибутах передати 'skipPacking' => true, то Qs_Packer такі ресурси мерджити не буде
];
protected $_defaultGroupName = 'ITEMS';
protected $_groupName;
protected $_smartyPlugins = [
'block' => [],
];
protected $_templateRootPath;
protected $_outFilters = [];
protected $_templateDefines = [
'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 = [
'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 = [];
protected $_optimized = false;
protected $_hasAnalyticsScripts = false;
/**
* Module specific Placeholders e.g.: [
* 'User\\' => [
* 'firstName' => 'John',
* ]
* ]
* @var array
*/
protected $_modulePlaceholders = [];
/**
* @var Qs_Lock_RoleObj
*/
protected $_lockObj;
/** @var array */
protected $_gtmValues = [];
protected $_isPagePreviewMode = false;
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->isPagePreviewMode() && $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 setHasAnalyticsScripts($value = true)
{
$this->_hasAnalyticsScripts = (bool) $value;
return $this;
}
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()
{
if (null === $this->_analyticsType) {
$map = [
'gtmId' => self::ANALYTICS_TYPE_GOOGLE_TAG_MANAGER,
'analyticsCode' => self::ANALYTICS_TYPE_GOOGLE_ANALYTICS,
];
// use cached 'false' value for further method calls in case both codes are empty
$this->_analyticsType = false;
foreach ($map as $field => $type) {
$code = App_Settings_Obj::get($field);
$code = trim($code);
if (!empty($code)) {
$this->_analyticsType = $type;
break;
}
}
}
return $this->_analyticsType;
}
public function isGtmEnabled()
{
return constant('SITE_LIVE') && $this->getAnalyticsType() == self::ANALYTICS_TYPE_GOOGLE_TAG_MANAGER
&& App_Settings_Obj::get('gtmId');
}
public function addGtmValues(array $values)
{
$this->_gtmValues = Qs_Array::mergeRecursive($this->_gtmValues, $values);
return $this;
}
public function setGtmValue($name, $value)
{
$this->_gtmValues[$name] = $value;
return $this;
}
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 prependHeader($suffix)
{
$this->setHeader($suffix . $this->getHeader());
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'] = [];
return $this;
}
public function clearInlineScripts()
{
$this->_content['head']['inlineScript'] = [];
return $this;
}
public function clearInitFunctions()
{
$this->_content['head']['initFunctions'] = [];
return $this;
}
public function clearScripts()
{
$this->_content['head']['script'] = [];
return $this;
}
public function setStylesheets(array $list)
{
$this->clearStylesheets();
$this->addStylesheets($list);
return $this;
}
public function addStylesheets(array $list)
{
foreach ($list as $options) {
if (is_array($options)) {
call_user_func_array([$this, 'addStylesheet'], $options);
} else {
$this->addStylesheet($options);
}
}
return $this;
}
public function addStylesheet($href, $_attribs = [], $name = null)
{
$attribs = [
'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 getStylesheetUrls()
{
return array_column($this->_content['head']['stylesheet'], 'href');
}
public function setScripts(array $list)
{
$this->clearScripts();
$this->addScripts($list);
return $this;
}
public function addScripts(array $list)
{
foreach ($list as $options) {
if (is_array($options)) {
call_user_func_array([$this, 'addScript'], $options);
} else {
$this->addScript($options);
}
}
return $this;
}
public function addScript($src, $_attribs = [], $name = null)
{
$attribs = [
'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 addInlineScript($name, $body, $_attribs = [])
{
$attribs = [
'type' => 'text/javascript',
'beforeScripts' => false,
];
$attribs = array_merge($attribs, $_attribs);
$beforeScripts = (int) $attribs['beforeScripts'];
unset($attribs['beforeScripts']);
$this->_content['head']['inlineScript'][$beforeScripts][$name] = [
'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 getTitleSuffix()
{
if (null === $this->_titleSuffix) {
$this->_titleSuffix = App_Settings_Obj::get('titleSuffix');
}
return $this->_titleSuffix;
}
public function setTitleSuffix($titleSuffix)
{
$this->_titleSuffix = $titleSuffix;
return $this;
}
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,
'titleSuffix' => $this->getTitleSuffix(),
]
);
}
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('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 (['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, [$html, $this]);
}
return $html;
}
public function fetchTemplate($template = null)
{
$this->getSmarty()->assign('view', Qs_View::getInstance());
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;
}
public function fetchItem(array $item)
{
$this->getSmarty()->assign('item', new Qs_Doc_Item($item));
return $this->fetchTemplate($item['tpl']);
}
protected function _beforeDisplay()
{
$this->_initGtmValues();
$this->_initFooter();
return $this;
}
protected function _initGtmValues()
{
if ($this->isGtmEnabled()) {
$values = (array) $this->_gtmValues;
array_walk_recursive($values, function (&$item) {
$item = (string) $item;
});
$values = json_encode($values, JSON_PRETTY_PRINT);
$this->assign('GTM_VALUES', $values);
}
return $this;
}
protected function _initFooter()
{
$data = (array) $this->_getFooterPlaceholders();
$this->assign('FOOTER', Qs_String::fill(App_Settings_Obj::get('footer'), $data));
return $this;
}
protected function _getFooterPlaceholders()
{
return [
'currentYear' => date('Y'),
'widgets' => '',
];
}
public function sendHeaders()
{
header('Content-Type: ' . Qs_Constant::get('CONTENT_TYPE'));
return $this;
}
public function display404($options = [])
{
$notFound = new App_NotFound_View($options);
$notFound->setDoc($this);
$notFound->exec();
return $this;
}
public function display()
{
$this->_beforeDisplay();
$this->sendHeaders();
echo $this->fetch();
return $this;
}
public function __toString()
{
$this->_beforeDisplay();
return $this->fetch();
}
protected function _displayMessageBox(array $messages, $type)
{
$template = $this->getTemplate($type . '.tpl');
foreach ($messages as $message) {
$this->addItem(['tpl' => $template, 'message' => $message]);
}
return $this;
}
public function displayMessage($messages)
{
$messages = (array) $messages;
$this->_displayMessageBox($messages, static::MESSAGE_BOX_MESSAGE);
return $this;
}
public function displayError($errors)
{
$errors = (array) $errors;
$this->_displayMessageBox($errors, static::MESSAGE_BOX_ERROR);
return $this;
}
public function displayAttention($attentions)
{
$attentions = (array) $attentions;
$this->_displayMessageBox($attentions, static::MESSAGE_BOX_ATTENTION);
return $this;
}
public function hasAuth()
{
$file = BASE_PATH . '/' . str_replace(['_', '\\'], '/', $this->_authClassName) . '.php';
return (null !== $this->_auth || (null !== $this->_authClassName && file_exists($file)));
}
public function getAuth()
{
if (null === $this->_auth) {
if (null === $this->_authClassName) {
throw new Qs_Doc_Exception('Auth is undefined');
} else {
$this->_auth = call_user_func($this->_authClassName . '::getInstance');
}
}
return $this->_auth;
}
public function setAuth($auth)
{
if (!($auth instanceof Qs_Auth)) {
throw new Qs_Doc_Exception('Auth is not instance of Qs_Auth');
}
$this->_auth = $auth;
return $this;
}
public function getAuthAdapter()
{
if (null === $this->_authAdapter) {
if (null === $this->_authAdapterClassName) {
if (null == $this->_auth) {
if (null === $this->_authClassName) {
throw new Qs_Doc_Exception('AuthAdapter is undefined');
}
$this->_authAdapterClassName = $this->_authClassName . 'Adapter';
} else {
$this->_authAdapterClassName = get_class($this->_auth) . 'Adapter';
}
}
$this->_authAdapter = new $this->_authAdapterClassName();
}
return $this->_authAdapter;
}
public function setAuthAdapter($authAdaptrer)
{
if (!($authAdaptrer instanceof Zend_Auth_Adapter_Interface)) {
throw new Qs_Doc_Exception('AuthAdapter is not instance of Zend_Auth_Adapter_Interface');
}
$this->_authAdapter = $authAdaptrer;
return $this;
}
public function authenticate()
{
/** @var $result Zend_Auth_Result */
$result = null;
if ($this->getAuth()->hasIdentity()) {
$data = $this->getAuth()->getIdentity();
$this->getAuthAdapter()->setIdentity($data);
$result = $this->getAuth()->authenticate($this->getAuthAdapter());
if ($result->isValid()) {
return true;
} else {
$this->getAuth()->clearIdentity();
}
}
if (Qs_Request::isXmlHttpRequest()) {
$this->_processAjaxFailedAuth();
} else {
$this->getAuth()->setBackUrl(Qs_Request::getUrl());
if ($result) {
$session = new Zend_Session_Namespace($this->getAuth()->getLoginAlias());
$session->{self::MESSAGE_BOX_ERROR} = $result->getMessages();
$session->setExpirationHops(1, self::MESSAGE_BOX_ERROR);
}
Qs_Http::redirect($this->getAuth()->getLoginUrl());
}
return $this;
}
protected function _processAjaxFailedAuth()
{
$this->ajaxResponse([
'isValid' => true,
'sessionExpired' => true,
'loginUrl' => $this->getAuth()->getLoginUrl() . '?' . Qs_Doc::POPUP,
]);
return $this;
}
public function ajaxResponse($response = [])
{
header('Cache-Control: no-store, no-cache, must-revalidate, private');
header('Pragma: no-cache');
header('Content-Type: application/x-javascript; charset=utf-8');
die(json_encode($response));
}
public function getAuthData($field = false, $default = null)
{
if ($this->hasAuth()) {
return $this->getAuth()->getData($field, $default);
}
return $default;
}
public function getAuthIdentity()
{
if ($this->hasAuth()) {
$identity = $this->getAuth()->getIdentity();
if (!empty($identity) && array_key_exists('autologinCode', $identity)) {
if (count($identity) == 1) { // has only 'autologinCode'
$this->authenticate();
$identity = $this->getAuth()->getIdentity();
}
}
return $identity;
}
return false;
}
public function addItem($item, $groupName = null)
{
if (null === $groupName) {
$groupName = $this->getGroupName();
}
$docItem = new Qs_Doc_Item($item);
$this->addItemResources($docItem);
$this->_content[$groupName][] = $docItem;
return $this;
}
public function getGroupName()
{
if (null === $this->_groupName) {
return $this->_defaultGroupName;
}
return $this->_groupName;
}
public function unsetGroupName()
{
$this->_groupName = null;
return $this;
}
public function setGroupName($groupName)
{
$this->_groupName = $groupName;
return $this;
}
public function addReadyFunction($name, $params = [])
{
$this->_content['head']['readyFunctions'][] = [
'name' => $name,
'params' => $params,
];
return $this;
}
public function addReadyObject($name, $params = [], $assign = null)
{
$this->_content['head']['readyFunctions'][] = [
'name' => $name,
'params' => $params,
'assign' => $assign,
'new' => true,
];
return $this;
}
public function addInitFunction($name, $params = [])
{
$this->_content['head']['initFunctions'][] = [
'name' => $name,
'params' => $params,
];
return $this;
}
public function addInitObject($name, $params = [], $assign = null)
{
$this->_content['head']['initFunctions'][] = [
'name' => $name,
'params' => $params,
'assign' => $assign,
'new' => true,
];
return $this;
}
public function getTemplate($template)
{
return Qs_SiteMap::getTemplate($template, $this->getTemplatePath());
}
public function getTemplatePath()
{
if (null === $this->_templatePath) {
$class = get_class($this);
$this->_templatePath = substr($class, 0, strrpos($class, '_'));
if (0 === strpos($this->_templatePath, 'App_')) {
$this->_templatePath = substr($this->_templatePath, 4);
}
}
return $this->_templatePath;
}
/**
* @return Smarty
*/
public function getSmarty()
{
if (null === $this->_smarty) {
if (!class_exists('Smarty')) {
require_once 'lib/Smarty/Smarty/Smarty.class.php';
}
$this->_smarty = new Smarty();
$this->_smarty->compile_check = true;
$this->_smarty->debugging = false;
$this->_smarty->template_dir = $this->getTemplateDirectory();
$this->_smarty->cache_lifetime = 40;
$this->_smarty->force_compile = false;
$this->_smarty->php_handling = SMARTY_PHP_PASSTHRU;
$this->_smarty->compile_dir = Qs_Constant::get('BASE_PATH') . '/tmp/tpl_c';
$this->_smarty->left_delimiter = '{';
$this->_smarty->right_delimiter = '}';
foreach ($this->_smartyPlugins['block'] as $name => $block) {
$this->_smarty->_plugins['block'][$name] = $block;
}
foreach ($this->_smartyPluginPaths as $dir) {
$this->_smarty->plugins_dir[] = Qs_Constant::get('BASE_PATH') . '/' . $dir;
}
}
return $this->_smarty;
}
protected function _createItemObj($item)
{
$separator = (false !== strpos($item['type'], '\\')) ? '\\' : '_';
$class = Qs_SiteMap::getItemTypeClass($item['type'], 'View');
$file = BASE_PATH . '/' . str_replace($separator, '/', $class) . '.php';
if (!file_exists($file)) {
Qs_Debug::log('Cms item "' . $item['type'] . '" not found');
return false;
}
$item['doc'] = $this;
if (array_key_exists('id', $item)) {
$item['idItem'] = $item['id'];
}
return new $class($item);
}
public function renderPageItems($items)
{
$itemObj = [];
$_pageItems = $items;
$indexes = array_keys($items);
while (false !== ($index = current($indexes)) && array_key_exists($index, $items)) {
next($indexes);
$item = $items[$index];
next($items);
/** @var $obj Qs_ViewController */
if (false !== ($obj = $this->_createItemObj($item))) {
$itemObj[$index] = $obj;
} else {
continue;
}
if (method_exists($itemObj[$index], 'preDispatch')) {
$itemObj[$index]->preDispatch($items);
}
}
foreach ($items as $index => $item) {
if (array_key_exists($index, $itemObj)) {
$obj = $itemObj[$index];
} else {
if (false === ($obj = $this->_createItemObj($item))) {
continue;
}
}
if (isset($items[$index]['groupName'])) {
$this->setGroupName($items[$index]['groupName']);
} else {
$this->unsetGroupName();
}
$time = microtime(true);
$obj->exec();
unset($itemObj[$index]);
if (Qs_Constant::get('DEBUG')) {
$_pageItems[$index]['executed'] = true;
$_pageItems[$index]['duration'] = round((microtime(true) - $time) * 1000);
}
}
if (Qs_Constant::get('DEBUG')) {
Zend_Registry::set('_pageItems', $_pageItems);
}
return $this;
}
public function registerSmartyBlock($block, $block_impl, $cacheable = true, $cache_attrs = null)
{
$this->_smartyPlugins['block'][$block] = [$block_impl, null, null, false, $cacheable, $cache_attrs];
return $this;
}
public function removeItem($index, $groupName = null)
{
if (null === $groupName) {
$groupName = $this->getGroupName();
}
if (array_key_exists($index, $this->_content[$groupName])) {
unset($this->_content[$groupName][$index]);
}
return $this;
}
public function setBodyAttribs($attribs)
{
$this->_content['bodyAttribs'] = $attribs;
}
public function setBodyAttrib($name, $value)
{
$this->_content['bodyAttribs'][$name] = $value;
}
public function getBodyAttribs()
{
return $this->_content['bodyAttribs'];
}
public function getMenu()
{
return $this->_content['menu'];
}
public function getCtrlMenu()
{
if (null === $this->_content['ctrlMenu']) {
$filter = ['showInCtrlMenu' => 'y', 'requireSu' => 'n'];
if ($this->hasAuth() && $this->getAuth()->getSuMode()) {
unset($filter['requireSu']);
}
$ctrlMenu = Qs_SiteMap::find($filter);
if ($ctrlMenu) {
$this->_prepareCtrlMenu($ctrlMenu, $filter);
}
$this->_content['ctrlMenu'] = $ctrlMenu;
}
return $this->_content['ctrlMenu'];
}
protected function _prepareCtrlMenu(array &$menu, array $filter)
{
if (!empty($menu)) {
foreach ($menu as $key => &$item) {
if (!empty($filter['requireSu']) && $filter['requireSu'] != $item['requireSu']) {
unset($menu[$key]);
} else if (!empty($item['sub'])) {
$this->_prepareCtrlMenu($item['sub'], $filter);
}
}
$menu = array_merge($menu);
}
return $this;
}
public function getBodyAttrib($name)
{
if (array_key_exists($name, $this->_content['bodyAttribs'])) {
return $this->_content['bodyAttribs'][$name];
}
return null;
}
public function renderScripts($excludedAttribs = null)
{
$html = '';
foreach ($this->_content['head']['script'] as $attribs) {
if (!empty($excludedAttribs)) {
if (is_array($excludedAttribs)) {
foreach ($excludedAttribs as $excluded) {
unset($attribs[$excluded]);
}
} else {
unset($attribs[$excludedAttribs]);
}
}
if (0 === strpos($attribs['src'], 'js/')) {
if (Qs_Constant::get('SITE_REVISION')) {
$attribs['src'] = BASE_URL . '/js-' . Qs_Constant::get('SITE_REVISION') . '/' . substr($attribs['src'], 3);
} else {
$attribs['src'] = BASE_URL . '/' . $attribs['src'];
}
}
$html .= '' . "\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 = [];
$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 = [];
foreach ($options['params'] as $param) {
$json = Zend_Json::encode($param, false, ['enableJsonExprFinder' => true]);
if (constant('DEBUG')) {
$json = Zend_Json::prettyPrint($json, ['indent' => ' ']);
$json = str_replace("\n", "\n" . str_repeat(' ', 2), $json);
}
$params[] = $json;
}
$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 = ['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([$this, 'add' . ucfirst($name)], (array) $params);
}
}
}
return $this;
}
public function addResources(array $resources)
{
foreach ($resources as $type => $list) {
$method = 'add' . $type;
if (method_exists($this, $method)) {
foreach ($list as $arguments) {
call_user_func_array([$this, $method], $arguments);
}
} else {
trigger_error('Undefined resource type');
}
}
return $this;
}
public function getResources()
{
$script = '';
$head = $this->getTemplateVariable('head');
foreach ($head['inlineScript'] as $inlineScript) {
$script .= "{$inlineScript}\n";
}
$script .= "\n" . $this->renderReadyFunctions();
$script .= "\n" . $this->renderInitFunctions();
return $script;
}
public function sendNoindexHeader()
{
header('X-Robots-Tag: noindex, nofollow');
return $this;
}
public function setPagePreviewMode($value = true)
{
$this->_isPagePreviewMode = $value;
return $this;
}
public function isPagePreviewMode()
{
return $this->_isPagePreviewMode;
}
public function getWidgets($placement = null, $default = null)
{
return Qs_Array::get($this->_widgets, $placement, $default);
}
public function setWidgets(array $widgets)
{
$this->_widgets = $widgets;
return $this;
}
public function renderWidgets($placement)
{
return $this->getWidgets($placement, '');
}
public function getModulePlaceholders($module = null)
{
return Qs_Array::get($this->_modulePlaceholders, $module, []);
}
public function setModulePlaceholders($module, $placeholders)
{
$this->_modulePlaceholders[$module] = $placeholders;
return $this;
}
public function hasModulePlaceholders($module)
{
return array_key_exists($module, $this->_modulePlaceholders);
}
}