'site',
'isSecure' => 'n',
);
protected static $_siteMapXml;
protected static $_siteMapDb;
protected static $_siteMapMenu;
protected static $_siteMapFooter;
protected static $_siteMapUserend;
protected static $_siteMapBackendFull;
protected static $_siteMapBackendMenu;
protected static $_fullSitemap;
protected static function _getFromXml($file = 'sitemap.xml')
{
if (null === Qs_SiteMap::$_siteMapXml) {
$config = new Zend_Config_Xml(BASE_PATH . '/' . $file);
$siteMap = $config->toArray();
Qs_SiteMap::$_siteMapXml = Qs_SiteMap::_prepareSiteMapXml($siteMap);
}
return Qs_SiteMap::$_siteMapXml;
}
public static function reload($file)
{
Qs_SiteMap::$_siteMapXml = null;
Qs_SiteMap::$_siteMapBackendMenu = null;
Qs_SiteMap::_getFromXml($file);
}
public static function loadXml($file = 'sitemap.xml')
{
Qs_SiteMap::_getFromXml($file);
}
public static function getFromDb($options = array())
{
return Qs_SiteMap::_getFromDb($options);
}
protected static function _getFromDb($options = array())
{
if (array_key_exists('select', $options)) {
return App_Cms_Obj::getInstance()->getSiteMap($options);
}
if (null === Qs_SiteMap::$_siteMapDb) {
Qs_SiteMap::$_siteMapDb = App_Cms_Obj::getInstance()->getSiteMap();
}
if (empty($options)) {
return Qs_SiteMap::$_siteMapDb;
} else {
if (empty($options['filter']) || !is_array($options['filter'])) {
$options['filter'] = array();
}
if (!empty($options['idParent'])) {
$siteMap = Qs_Array::treeBranch(Qs_SiteMap::$_siteMapDb, $options['idParent']);
} else {
$siteMap = Qs_SiteMap::$_siteMapDb;
}
return Qs_SiteMap::_siteMapFilter($siteMap, $options);
}
}
/**
* Example:
*
* $filtered = Qs_SiteMap::_siteMapFilter(
* Qs_SiteMap::$_siteMapDb,
* array(
* 'filter' => array('system' => 'n', 'showInSiteMap' => 'y'),
* 'idParent' => 6,
* )
* );
*
* @param array $siteMap
* @param array $options
* @return array
*/
protected static function _siteMapFilter(array $siteMap, array $options)
{
$tree = array();
foreach ($siteMap as $key => $page) {
if (!array_diff_assoc($options['filter'], $page)) {
$tree[$key] = $page;
$sub = Qs_Array::get($page, 'sub', array());
if ($sub) {
unset($tree[$key]['sub']);
$tree[$key]['sub'] = Qs_SiteMap::_siteMapFilter($sub, $options);
}
}
}
return $tree;
}
protected static function _prepareSiteMapXmlPage(&$page, $fullAlias = '')
{
$page['source'] = 'xml';
if (isset($page['item'])) {
if (Qs_Array::isAssoc($page['item'])) {
$page['items'] = array($page['item']);
} else {
$page['items'] = $page['item'];
}
unset($page['item']);
}
if (!isset($page['header']) || empty($page['header'])) {
$page['header'] = Qs_Array::get($page, 'menuTitle');
}
if (!isset($page['title']) || empty($page['title'])) {
$page['title'] = Qs_Array::get($page, 'menuTitle');
}
$page['fullAlias'] = $fullAlias;
$page['alias'] = basename($fullAlias);
if (Qs_SiteMap::isSecurePage($page)) {
$page['url'] = BASE_URL_LANGUAGE_HTTPS . ((empty($page['fullAlias'])) ? '' : '/') . $page['fullAlias'];
} else {
$page['url'] = BASE_URL_LANGUAGE_HTTP . ((empty($page['fullAlias'])) ? '' : '/') . $page['fullAlias'];
}
if (isset($page['sub'])) {
$page['sub'] = Qs_SiteMap::_prepareSiteMapXml($page['sub'], $page['fullAlias']);
}
}
protected static function _prepareSiteMapXml($siteMap, $parentAlias = null)
{
if (method_exists(App_Cms_Obj::getInstance(), 'getDefaultMetaPairs')) {
$defaultMetaValues = App_Cms_Obj::getInstance()->getDefaultMetaPairs();
} else {
$defaultMetaValues = array();
Qs_Debug::log('App_Cms_Obj::getDefaultMetaPairs() is not defined. '
. 'Please update your App_Cms_Obj class mamualy.');
}
foreach ($siteMap as $alias => &$page) {
if (!is_array($page)) {
continue;
}
Qs_SiteMap::_prepareSiteMapXmlPage($page, (($parentAlias) ? $parentAlias . '/' : '') . $alias);
$page = array_merge($defaultMetaValues, (array) $page);
}
return $siteMap;
}
/**
* @param string $page
* @return bool|null
* @throws Qs_Exception
*/
public static function isSecurePage($page)
{
if (is_string($page)) {
$alias = $page;
if (0 === strpos($alias, BASE_URL_HTTP)) {
$alias = (string)substr($alias, strlen(BASE_URL_HTTP) + 1);
} elseif (0 === strpos($alias, BASE_URL_HTTPS)) {
$alias = (string)substr($alias, strlen(BASE_URL_HTTPS) + 1);
} else {
return null;
}
if (!is_array($page = Qs_SiteMap::getPage($alias, false, null, false))) {
return null;
}
} elseif (!is_array($page)) {
throw new Qs_Exception('invalid page parameter');
}
return (isset($page['isSecure']) && $page['isSecure'] == 'y');
}
public static function getPage($alias, $breakIfFinal = true, $defaults = null, $loadItems = true)
{
$siteMap = Qs_SiteMap::_getFromXml();
if (null === $defaults) {
$defaults = Qs_SiteMap::$_defaults;
}
$page = Qs_SiteMap::_getPageEx($alias, $siteMap, $breakIfFinal, $defaults);
if ($page == Qs_SiteMap::NOT_FOUND) {
$siteMap = Qs_SiteMap::_getFromDb();
if (empty($alias) && !empty($siteMap)) {
foreach ($siteMap as $page) {
if ($page['enabled'] != 'n') {
$alias = $page['alias'];
break;
}
}
}
if (is_array($page = Qs_SiteMap::_getPageEx($alias, $siteMap, $breakIfFinal, $defaults))) {
$page = Qs_Array::excludeKey($page, 'sub');
if ($loadItems) {
// load items, keywords and description
$metaData = App_Cms_Obj::getInstance()->getMeta($page['id']);
$filterFunction = function ($value) {
if (is_scalar($value)) {
return (bool) strlen($value);
} else {
return !empty($value);
}
};
$metaData = array_filter($metaData, $filterFunction);
$page = array_merge($page, $metaData);
$page['items'] = App_Cms_Obj::getInstance()->getItemsList($page['id']);
}
}
}
if (is_array($page)) {
if (isset($page['_restAlias'])) {
Qs_SiteMap::_setRestAlias($page, $page['_restAlias']);
unset($page['_restAlias']);
}
}
return $page;
}
public static function filter($siteMap, $filter)
{
return Qs_SiteMap::_filter($siteMap, $filter);
}
protected static function _filter($siteMap, $filter)
{
foreach ($siteMap as $alias => &$page) {
foreach ($filter as $field => $value) {
if (!(isset($page[$field]) && $page[$field] == $value)) {
unset($siteMap[$alias]);
continue 2;
}
}
if (isset($page['sub']) && !empty($page['sub'])) {
$page['sub'] = Qs_SiteMap::_filter($page['sub'], $filter);
}
}
return $siteMap;
}
public static function prepareMobileMenu(array &$menu, $appendItem = null)
{
foreach ($menu as &$menuItem) {
if (array_key_exists('sub', $menuItem) && $menuItem['sub']) {
$parentItem = null;
$hasItems = (array_key_exists('items', $menuItem) && $menuItem['items']);
$hasPageRedirect = ('y' == $menuItem['redirect'] && 'page' == Qs_Array::get($menuItem, 'redirectType'));
if ($hasItems && !$hasPageRedirect || (!$hasItems && !$hasPageRedirect)) {
$parentItem = $menuItem;
unset($parentItem['sub']);
}
$menuItem['url'] = '#';
self::prepareMobileMenu($menuItem['sub'], $parentItem);
}
}
if ($appendItem) {
$menu = array($appendItem['fullAlias'] => $appendItem) + $menu;
}
return true;
}
public static function getMenu()
{
if (null === Qs_SiteMap::$_siteMapMenu) {
Qs_SiteMap::$_siteMapMenu = Qs_SiteMap::_getFromDb(
array('filter' => array('showInMenu' => 'y', 'enabled' => 'y'))
);
}
return Qs_SiteMap::$_siteMapMenu;
}
public static function getFooter()
{
if (null === Qs_SiteMap::$_siteMapFooter) {
Qs_SiteMap::$_siteMapFooter = Qs_SiteMap::_getFromDb(
array('filter' => array('showInFooter' => 'y', 'enabled' => 'y'))
);
}
return Qs_SiteMap::$_siteMapFooter;
}
public static function get4Userend()
{
if (null === Qs_SiteMap::$_siteMapUserend) {
Qs_SiteMap::$_siteMapUserend = Qs_SiteMap::_getFromDb(
array('filter' => array('showInSiteMap' => 'y', 'enabled' => 'y'))
);
}
return Qs_SiteMap::$_siteMapUserend;
}
public static function getBackendSiteMapFull()
{
if (null === Qs_SiteMap::$_siteMapBackendFull) {
$siteMap = Qs_SiteMap::_getFromXml();
Qs_SiteMap::$_siteMapBackendFull = array('admin' => $siteMap['admin']);
}
return Qs_SiteMap::$_siteMapBackendFull;
}
public static function getBackendMenu()
{
if (null === Qs_SiteMap::$_siteMapBackendMenu) {
$siteMap = Qs_SiteMap::_getFromXml();
Qs_SiteMap::$_siteMapBackendMenu = Qs_SiteMap::_filter($siteMap['admin']['sub'], array('showInMenu' => 'y'));
}
return Qs_SiteMap::$_siteMapBackendMenu;
}
protected static function _getPageEx($_alias, $siteMap, $breakIfFinal = true, $defaults = array())
{
$parts = explode('/', $_alias);
$alias = array_shift($parts);
$restAlias = implode('/', $parts);
if (isset($siteMap[$alias])) {
if ($siteMap[$alias]['enabled'] == 'n') {
return Qs_SiteMap::NOT_FOUND;
}
if (!strlen($restAlias)) {
if (empty($parts)) {
return array_merge($defaults, $siteMap[$alias]);
}
return Qs_SiteMap::ENDS_WITH_SLASH;
}
if (isset($siteMap[$alias]['final']) && $siteMap[$alias]['final'] == 'y' && $breakIfFinal) {
$page = array_merge($defaults, $siteMap[$alias]);
$page['_restAlias'] = $restAlias;
$partsCount = count($parts);
if (2 <= $partsCount && empty($parts[$partsCount - 1])) {
return Qs_SiteMap::ENDS_WITH_SLASH;
}
return $page;
}
if (isset($restAlias[0]) && $restAlias[0] == '/') {
return Qs_SiteMap::NOT_FOUND;
}
if (isset($siteMap[$alias]['sub'])) {
$_defaults = array_intersect_key(array_merge($defaults, $siteMap[$alias]), $defaults);
return Qs_SiteMap::_getPageEx($restAlias, $siteMap[$alias]['sub'], $breakIfFinal, $_defaults);
}
}
return Qs_SiteMap::NOT_FOUND;
}
protected static function _setRestAlias(&$page, $restAlias)
{
if (isset($page['items'])) {
foreach ($page['items'] as &$item) {
$item['restAlias'] = $restAlias;
}
}
}
public static function get404Page()
{
return array(
'title' => '404 Not Found',
'handler' => 'speedy',
'items' => array(array('type' => 'NotFound_'))
);
}
public static function templateExists($template)
{
if (file_exists($template) && is_file($template)) {
return true;
}
return false;
}
public static function getTemplate($template, $templatePath = null)
{
if (null !== $templatePath) {
if (is_array($templatePath)) {
foreach ($templatePath as $path) {
$templateName = BASE_PATH . '/tpl/' . $path . '/' . $template;
if (Qs_SiteMap::templateExists($templateName)) {
return $templateName;
}
}
return false;
} else {
$applicationFileName = BASE_PATH . '/tpl/' . $templatePath . '/' . $template;
if (Qs_SiteMap::templateExists($applicationFileName)) {
return $applicationFileName;
}
}
}
$commonFileName = BASE_PATH . '/tpl/' . $template;
if (Qs_SiteMap::templateExists($commonFileName)) {
return $commonFileName;
}
return false;
}
public static function getFull()
{
if (null === Qs_SiteMap::$_fullSitemap) {
Qs_SiteMap::loadXml();
Qs_SiteMap::$_fullSitemap = App_Cms_Obj::getInstance()->getSiteMap();
if (($firstAlias = key(Qs_SiteMap::$_fullSitemap))) {
if (!empty(Qs_SiteMap::$_fullSitemap[$firstAlias]['sub'])) {
Qs_SiteMap::$_fullSitemap[$firstAlias]['sub'] = array_merge(
Qs_SiteMap::$_fullSitemap[$firstAlias]['sub'],
Qs_SiteMap::$_siteMapXml
);
} else {
Qs_SiteMap::$_fullSitemap[$firstAlias]['sub'] = Qs_SiteMap::$_siteMapXml;
}
} else {
Qs_SiteMap::$_fullSitemap = Qs_SiteMap::$_siteMapXml;
}
}
return Qs_SiteMap::$_fullSitemap;
}
/**
* Find first page that match the page options, item options or item config
* @static
* @param array|string|null $page [OPTIONAL] page options or string selector
* @param array|null $item [OPTIONAL] item options
* @param array|null $config [OPTIONAL] item config options
* @param string|null $field [OPTIONAL] field of the page that be returned
* @param array|null $siteMap [OPTIONAL] context to search in
* @return mixed|bool list of pages with matched options or result value (if $field is defined)
*
* Examples:
* - Qs_SiteMap::find(null, array('type' => 'News_'), array('type' => 'default'), 'fullAlias');
* - Qs_SiteMap::find('(final=y)(isSecure=y)[type=default]', 'fullAlias');
*
* String selector structure: [page options](item options){config}
*/
public static function findFirst($page = null, $item = null, $config = null, $field = null, $siteMap = null)
{
if (false !== ($result = Qs_SiteMap::find($page, $item, $config, $field, 1, $siteMap))) {
if (is_string($page)) {
$field = (is_string($item)) ? $item : null;
}
return (null === $field) ? reset($result) : $result;
}
return $result;
}
/**
* Find pages (or page's column) that match the page options, item options or item config.
* If field set - return just field of first item from result
* @static
* @param array|string|null $page [OPTIONAL] page options or string selector
* @param array|null $item [OPTIONAL] item options
* @param array|null $config [OPTIONAL] item config options
* @param string|null $field [OPTIONAL] field of the page that be returned
* @param int|null $limit [OPTIONAL] result limit
* @param array|null $siteMap [OPTIONAL] context to search in
* @return mixed|bool list of pages with matched options or result value (if $field is defined)
*/
public static function find($page = null, $item = null, $config = null, $field = null,
$limit = null, $siteMap = null)
{
$result = static::_findAllPages($page, $item, $config, $field, $limit, $siteMap);
if (empty($result)) {
return false;
}
return (isset($field)) ? Qs_Array::get(reset($result), $field) : $result;
}
/**
* Find pages (or page's column) that match the page options, item options or item config.
* @static
* @param array|string|null $page [OPTIONAL] page options or string selector
* @param array|null $item [OPTIONAL] item options
* @param array|null $config [OPTIONAL] item config options
* @param string|null $field [OPTIONAL] field of the page that be returned
* @param int|null $limit [OPTIONAL] result limit
* @param array|null $siteMap [OPTIONAL] context to search in
* @return mixed|bool list of pages with matched options or result value (if $field is defined)
*/
public static function findAll($page = null, $item = null, $config = null, $field = null,
$limit = null, $siteMap = null)
{
$result = static::_findAllPages($page, $item, $config, $field, $limit, $siteMap);
if (empty($result)) {
return false;
}
return (isset($field)) ? Qs_Array::fetchCol($result, $field) : $result;
}
/**
* Find pages that match the page options, item options or item config.
* @static
* @param array|string|null $page [OPTIONAL] page options or string selector
* @param array|null $item [OPTIONAL] item options
* @param array|null $config [OPTIONAL] item config options
* @param string|null $field [OPTIONAL] field of the page that be returned
* @param int|null $limit [OPTIONAL] result limit
* @param array|null $siteMap [OPTIONAL] context to search in
* @return mixed|bool list of pages with matched options or result value (if $field is defined)
*/
protected static function _findAllPages($page = null, $item = null, $config = null, &$field = null,
$limit = null, $siteMap = null)
{
if (is_string($page)) {
$selector = $page;
$field = (is_string($item)) ? $item : null;
$page = Qs_SiteMap::_selectorToArray($selector, '/\(([^\)]+)\)/');
$item = Qs_SiteMap::_selectorToArray($selector, '/\<([^\>]+)\>/');
$config = Qs_SiteMap::_selectorToArray($selector, '/\[([^\]]+)\]/');
} else {
$page = (is_array($page)) ? $page : array();
$item = (is_array($item)) ? $item : array();
$config = (is_array($config)) ? $config : array();
}
$siteMap = (null === $siteMap) ? Qs_SiteMap::getFull() : $siteMap;
if (empty($siteMap) || !is_array($siteMap) || (empty($page) && empty($item) && empty($config))) {
return false;
}
$result = array();
Qs_SiteMap::_find($siteMap, $page, $item, $config, $result, (null !== $field) ? 1 : $limit);
if (empty($result)) {
return false;
}
return $result;
}
protected static function _selectorToArray($selector, $pattern)
{
$matches = array();
preg_match_all($pattern, $selector, $matches);
$result = array();
if (isset($matches[1])) {
foreach ($matches[1] as $string) {
$parts = explode('=', $string);
$name = array_shift($parts);
$value = array_shift($parts);
$result[$name] = $value;
}
}
return $result;
}
protected static function _find(&$siteMap, $page, $item, $config, &$result, $limit = null)
{
foreach ($siteMap as &$_page) {
$diff = array_diff_assoc($page, $_page);
if (empty($diff)) {
if (empty($item) && empty($config)) {
$result[] = $_page;
} else {
$_page['items'] = (isset($_page['items'])) ? $_page['items'] : array();
foreach ($_page['items'] as &$_item) {
$diff = array_diff_assoc($item, $_item);
if (empty($diff)) {
$_config = (array) Qs_Array::get($_item, 'config');
$diff = array_diff_assoc($config, $_config);
if (empty($diff)) {
$result[] = $_page;
}
}
}
}
}
if (isset($_page['sub']) && (null === $limit || $limit > count($result))) {
Qs_SiteMap::_find($_page['sub'], $page, $item, $config, $result);
}
}
}
public static function getAliasByItem($type)
{
if (false !== ($page = Qs_SiteMap::findFirst(array(), array('type' => $type)))) {
if (isset($page['isRoot']) && 'y' == $page['isRoot']) {
return '';
}
return $page['fullAlias'];
}
return false;
}
public static function createPageItemView($item)
{
$separator = (false !== strpos($item['type'], '\\')) ? '\\' : '_';
$class = 'App' . $separator . $item['type'] . 'View';
$file = BASE_PATH . '/' . str_replace(array('_', '\\'), '/', $class) . '.php';
if (!file_exists($file)) {
Qs_Debug::log('Page item "' . $item['type'] . '" not found');
return false;
}
if (array_key_exists('id', $item)) {
$item['idItem'] = $item['id'];
}
return new $class($item);
}
public static function getSubClass($classNamePrefix, $suffix)
{
$separator = (false !== strpos($classNamePrefix, '\\')) ? '\\' : '_';
return $classNamePrefix . str_replace('_', $separator, $suffix);
}
public static function getItemTypeClass($type, $suffix)
{
$separator = (false !== strpos($type, '\\')) ? '\\' : '_';
return 'App' . $separator . $type . $suffix;
}
/**
* "App\Cms\View" => "Cms\"
* @param string|\Qs_ViewController $class
* @return string
*/
public static function classToType($class)
{
$class = (is_object($class)) ? get_class($class) : (string) $class;
if ('App' === substr($class, 0, 3) && 'View' === substr($class, -4)) {
$class = substr(substr($class, 4), 0, -4);
}
return $class;
}
/**
* @param string|\Qs_ViewController $class
* @return string
*/
public static function classToPath($class)
{
$class = (is_object($class)) ? get_class($class) : (string)$class;
$path = str_replace(array('_', '\\'), '/', $class);
if ('App/' === substr($path, 0, 4)) {
$path = substr($path, 4);
$path = substr($path, 0, strrpos($path, '/'));
}
return rtrim($path, '/');
}
public static function classToId($class)
{
return str_replace('/', '-', strtolower(self::classToPath($class)));
}
}
function SMGetTemplate($template, $templatePath = null)
{
return Qs_SiteMap::getTemplate($template, $templatePath);
}
function SMGetAliasByItem($type)
{
return Qs_SiteMap::getAliasByItem($type);
}