mirror of https://github.com/avecms/AVE.cms.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
573 lines
17 KiB
573 lines
17 KiB
<?php |
|
|
|
/** |
|
* AVE.cms |
|
* |
|
* @package AVE.cms |
|
* @version 3.x |
|
* @filesource |
|
* @copyright © 2007-2014 AVE.cms, http://www.ave-cms.ru |
|
* |
|
* @license GPL v.2 |
|
*/ |
|
|
|
/** |
|
* Функция обработки навигации |
|
* |
|
* @param int $navi_tag - идентификатор меню навигации |
|
* @return mixed|string |
|
*/ |
|
function parse_navigation($navi_tag) |
|
{ |
|
global $AVE_DB, $AVE_Core; |
|
|
|
// Извлекаем id из аргумента |
|
$navi_id = $navi_tag[1]; |
|
|
|
Debug::startTime('NAVIAGTION_' . $navi_id); |
|
|
|
// Достаем для проверки тип меню |
|
$sql = " |
|
SELECT |
|
# NAVIGATION = $navi_id |
|
expand_ext |
|
FROM |
|
".PREFIX."_navigation |
|
WHERE |
|
navigation_id = '" . $navi_id . "' |
|
OR |
|
alias = '" . $navi_id . "' |
|
"; |
|
|
|
$expnad_ext = $AVE_DB->Query($sql, -1, 'nav_' . $navi_id, true, '.naviagtion')->GetCell(); |
|
|
|
// извлекаем level из аргумента |
|
$navi_print_level = (! empty($navi_tag[2])) |
|
? $navi_tag[2] |
|
: ''; |
|
|
|
$navi = ''; |
|
|
|
$cache_file = BASE_DIR . '/tmp/cache/sql/navigations/' . $navi_id . '/template.cache'; |
|
|
|
// Если включен DEV MODE, то отключаем кеширование запросов |
|
if (defined('DEV_MODE') AND DEV_MODE || $expnad_ext != 1) |
|
$cache_file = null; |
|
|
|
if (! is_dir(dirname($cache_file))) |
|
mkdir(dirname($cache_file), 0766, true); |
|
|
|
// получаем меню навигации по id, |
|
// и если такой не существует, выводим сообщение |
|
|
|
if (file_exists($cache_file)) |
|
{ |
|
$navi_menu = unserialize(file_get_contents($cache_file)); |
|
} |
|
else |
|
{ |
|
$navi_menu = get_navigations($navi_id); |
|
|
|
if ($cache_file) |
|
file_put_contents($cache_file, serialize($navi_menu)); |
|
} |
|
|
|
if (! $navi_menu) |
|
{ |
|
echo 'Menu ', $navi_id, ' not found!'; |
|
return ''; |
|
} |
|
|
|
// выставляем гостевую группу по дефолту |
|
if (! defined('UGROUP')) |
|
define('UGROUP', 2); |
|
|
|
// выходим, если навиг. не предназначена для текущей группы |
|
if (! in_array(UGROUP, $navi_menu->user_group)) |
|
return false; |
|
|
|
// Находим активный пункт (связь текущего открытого документа и навигации). Нас интересуют: |
|
// 1) документы, которые сами связаны с пунктом меню |
|
// 2) пункты навигации, у которых ссылка совпадает с алиасом дока |
|
// 3) текущий level, текущий id |
|
// возвращаем в $navi_active через запятую id пунктов: |
|
// 1) активный пункт |
|
// 2) родители активного пункта |
|
// после ; через запятую все level-ы текущего пути, чтобы потом взять max |
|
// после ; id текущего пункта |
|
|
|
// id текущего документа. Если не задан, то главная страница |
|
$doc_active_id = (int)(($_REQUEST['id']) |
|
? $_REQUEST['id'] |
|
: 1); |
|
|
|
// алиас текущего документа |
|
$alias = ltrim(isset($AVE_Core->curentdoc->document_alias) |
|
? $AVE_Core->curentdoc->document_alias |
|
: ''); |
|
|
|
// запрос для выборки по текущему алиасу |
|
$sql_doc_active_alias = ''; |
|
|
|
$url_suff = ''; |
|
|
|
if (defined('URL_SUFF') AND URL_SUFF) |
|
{ |
|
$url_suff = " |
|
OR nav.alias = '" . $alias . URL_SUFF . "' |
|
OR nav.alias = '/" . $alias . URL_SUFF . "' |
|
"; |
|
} |
|
|
|
if ($AVE_Core->curentdoc->Id == $doc_active_id) |
|
{ |
|
$sql_doc_active_alias = " |
|
OR nav.alias = '" . $alias . "' |
|
OR nav.alias = '/" . $alias . "' |
|
" . $url_suff . " |
|
"; |
|
} |
|
|
|
$navi_active = $AVE_DB->Query(" |
|
SELECT |
|
CONCAT_WS( |
|
';', |
|
CONCAT_WS(',', nav.navigation_item_id, nav.parent_id, nav2.parent_id), |
|
CONCAT_WS(',', nav.level), |
|
nav.navigation_item_id |
|
) |
|
FROM |
|
" . PREFIX . "_navigation_items AS nav |
|
JOIN |
|
" . PREFIX . "_documents AS doc |
|
LEFT JOIN |
|
" . PREFIX . "_navigation_items AS nav2 |
|
ON |
|
nav2.navigation_item_id = nav.parent_id |
|
WHERE |
|
nav.status = 1 |
|
AND |
|
nav.navigation_id = '" . $navi_menu->navigation_id . "' |
|
AND |
|
doc.Id = " . $doc_active_id . " |
|
AND ( |
|
nav.document_id = '" . $doc_active_id . "'" . |
|
$sql_doc_active_alias . " |
|
OR |
|
nav.navigation_item_id = doc.document_linked_navi_id |
|
) |
|
")->GetCell(); |
|
|
|
$navi_active = @explode(';', $navi_active); |
|
|
|
// готовим 2 переменные с путём |
|
if ($navi_active[0]) |
|
$navi_active_way = @explode(',', $navi_active[0]); |
|
|
|
$navi_active_way[] = '0'; |
|
|
|
$navi_active_way_str = implode(',', $navi_active_way); |
|
|
|
// текущий уровень |
|
$navi_active_level = (int)max(@explode(',', (isset($navi_active[1]) |
|
? (int)$navi_active[1] |
|
: 0)))+1; |
|
|
|
// текущий id |
|
$navi_active_id = (isset($navi_active[2]) |
|
? (int)$navi_active[2] |
|
: 0); |
|
|
|
// если просят вывести какие-то конкретные уровни: |
|
$sql_navi_level = ''; |
|
$sql_navi_active = ''; |
|
|
|
if ($navi_print_level) |
|
{ |
|
$sql_navi_level = ' AND level IN (' . $navi_print_level . ') '; |
|
$sql_navi_active = ' AND parent_id IN (' . $navi_active_way_str . ') '; |
|
} |
|
|
|
// обычное использование навигации |
|
else |
|
{ |
|
switch ($navi_menu->expand_ext) |
|
{ |
|
// текущий и родительский уровни |
|
case 0: |
|
$sql_navi_active = ' AND parent_id IN (' . $navi_active_way_str . ') '; |
|
$navi_parent = 0; |
|
break; |
|
|
|
// все уровни |
|
case 1: |
|
$navi_parent = 0; |
|
break; |
|
|
|
// только текущий уровень |
|
case 2: |
|
$sql_navi_level = ' AND level = ' . $navi_active_level . ' '; |
|
$navi_parent = $navi_active_id; |
|
break; |
|
} |
|
} |
|
|
|
$cache_items = BASE_DIR . '/tmp/cache/sql/navigations/' . $navi_id . '/items.cache'; |
|
|
|
$navi_items = array(); |
|
|
|
// Если включен DEV MODE, то отключаем кеширование запросов |
|
if (defined('DEV_MODE') AND DEV_MODE || $expnad_ext != 1) |
|
$cache_items = null; |
|
|
|
if (empty($navi_print_level)) |
|
{ |
|
//-- Проверяем есть файл кеша, если есть пропускам запрос к БД |
|
if (! file_exists($cache_items)) |
|
{ |
|
//-- Запрос пунктов меню |
|
$sql = " |
|
SELECT |
|
* |
|
FROM |
|
" . PREFIX . "_navigation_items |
|
WHERE |
|
status = '1' |
|
AND |
|
navigation_id = '" . $navi_menu->navigation_id . "'" . |
|
$sql_navi_level . |
|
$sql_navi_active . " |
|
ORDER BY |
|
position ASC |
|
"; |
|
|
|
$sql_navi_items = $AVE_DB->Query($sql); |
|
|
|
while ($row_navi_items = $sql_navi_items->FetchAssocArray()) |
|
$navi_items[$row_navi_items['parent_id']][] = $row_navi_items; |
|
|
|
if ($cache_items) |
|
file_put_contents($cache_items, serialize($navi_items)); |
|
} |
|
else |
|
{ |
|
$navi_items = unserialize(file_get_contents($cache_items)); |
|
} |
|
} |
|
else |
|
{ |
|
//-- Запрос пунктов меню |
|
$sql = " |
|
SELECT |
|
* |
|
FROM |
|
" . PREFIX . "_navigation_items |
|
WHERE |
|
status = '1' |
|
AND |
|
navigation_id = '" . $navi_menu->navigation_id . "'" . |
|
$sql_navi_level . " |
|
ORDER BY |
|
position ASC |
|
"; |
|
|
|
$sql_navi_items = $AVE_DB->Query($sql); |
|
|
|
while ($row_navi_items = $sql_navi_items->FetchAssocArray()) |
|
{ |
|
$navi_items[$row_navi_items['parent_id']][] = $row_navi_items; |
|
} |
|
|
|
$keys = array_keys($navi_items); |
|
$navi_parent = ! empty($keys) |
|
? $keys[0] |
|
: 0; |
|
} |
|
|
|
// Парсим теги в шаблонах пунктов |
|
$navi_item_tpl = array( |
|
1 => array( |
|
'inactive' => $navi_menu->level1, |
|
'active' => $navi_menu->level1_active |
|
), |
|
2 => array( |
|
'inactive' => $navi_menu->level2, |
|
'active' => $navi_menu->level2_active |
|
), |
|
3 => array( |
|
'inactive' => $navi_menu->level3, |
|
'active' => $navi_menu->level3_active |
|
) |
|
); |
|
|
|
// запускаем рекурсивную сборку навигации |
|
if ($navi_items) |
|
$navi = printNavi($navi_menu, $navi_items, $navi_active_way, $navi_item_tpl, $navi_parent); |
|
|
|
// преобразуем все ссылке в коде |
|
$navi = rewrite_link($navi); |
|
|
|
// удаляем переводы строк и табуляции |
|
$navi = preg_replace("/(^[\r\n]*|[\r\n]+)[\s\t]*[\r\n]+/", "\n", $navi); |
|
$navi = str_replace(array("\n","\r"),'',$navi); |
|
|
|
$gen_time = Debug::endTime('NAVIAGTION_' . $navi_id); |
|
|
|
$GLOBALS['block_generate']['NAVIAGTIONS'][$navi_id] = $gen_time; |
|
|
|
return $navi; |
|
} |
|
|
|
|
|
/** |
|
* Рекурсивная функция для формирования меню навигации |
|
* |
|
* @param object $navi_menu меню (шаблоны, параметры) |
|
* @param array $navi_items (пункты по родителям) |
|
* @param array $navi_active_way ("активный путь") |
|
* @param array $navi_item_tpl (шаблоны пунктов) |
|
* @param int $parent (исследуемый родитель, изначально 0 - верхний уровень) |
|
* @return string $navi - готовый код навигации |
|
*/ |
|
function printNavi($navi_menu, $navi_items, $navi_active_way, $navi_item_tpl, $parent = 0) |
|
{ |
|
// выясняем уровень |
|
$navi_item_level = $navi_items[$parent][0]['level']; |
|
|
|
// собираем каждый пункт в данном родителе -> в переменной $item |
|
|
|
$x = 0; |
|
$items_count = count($navi_items[$parent]); |
|
|
|
foreach ($navi_items[$parent] as $row) |
|
{ |
|
$x++; |
|
$last_item = ($x == $items_count ? true : false); |
|
$item_num = $x; |
|
|
|
// Проверяем пункт меню на принадлежность к "активному пути" и выбираем шаблон |
|
$item = (in_array($row['navigation_item_id'], $navi_active_way)) |
|
? $navi_item_tpl[$navi_item_level]['active'] |
|
: $navi_item_tpl[$navi_item_level]['inactive']; |
|
|
|
################### ПАРСИМ ТЕГИ ################### |
|
// id |
|
@$item = str_replace('[tag:linkid]', $row['navigation_item_id'], $item); |
|
// название |
|
@$item = str_replace('[tag:linkname]', $row['title'], $item); |
|
//Путь |
|
$item = str_replace('[tag:path]', ABS_PATH, $item); |
|
// ссылка |
|
if ($row['document_id']) |
|
{ |
|
//запрещаем слешь в конце ссылки |
|
//$item = str_replace('[tag:link]', 'index.php?id=' . $row['document_id'] . "&doc=" . ((!$row['alias']) ? prepare_url($row['title']) : trim($row['alias'], '/')), $item); |
|
//разрешаем слешь в конце ссылки |
|
$item = str_replace('[tag:link]', 'index.php?id=' . $row['document_id'] . "&doc=" . ((!$row['alias']) ? prepare_url($row['title']) : trim($row['alias'])), $item); |
|
|
|
$item = str_ireplace('"//"', '"/"', str_ireplace('///', '/', rewrite_link($item))); |
|
} |
|
else |
|
{ |
|
$item = str_replace('[tag:link]', $row['alias'], $item); |
|
} |
|
|
|
if (start_with('www.', $row['alias'])) |
|
$item = str_replace('www.', 'http://www.', $item); |
|
|
|
// target |
|
$item = str_replace('[tag:target]', $row['target'], $item); |
|
// описание |
|
@$item = str_replace('[tag:desc]', stripslashes($row['description']), $item); |
|
// изображение |
|
@$item = str_replace('[tag:img]', stripslashes($row['image']), $item); |
|
|
|
if ($row['image'] != '') |
|
{ |
|
@$img = explode('.', $row['image']); |
|
@$row['image_act'] = $img[0] . "_act.".$img[1]; |
|
@$item = str_replace('[tag:img_act]', stripslashes($row['image_act']), $item); |
|
} |
|
|
|
if ($row['css_id'] != '') |
|
{ |
|
@$item = str_replace('[tag:css_id]', stripslashes($row['css_id']), $item); |
|
} |
|
else |
|
{ |
|
@$item = str_replace('[tag:css_id]', '', $item); |
|
} |
|
|
|
if ($row['css_class'] != '') |
|
{ |
|
@$item = str_replace('[tag:css_class]', stripslashes($row['css_class']), $item); |
|
} |
|
else |
|
{ |
|
@$item = str_replace('[tag:css_class]', '', $item); |
|
} |
|
|
|
if ($row['css_style'] != '') |
|
{ |
|
@$item = str_replace('[tag:css_style]', stripslashes($row['css_style']), $item); |
|
} |
|
else |
|
{ |
|
@$item = str_replace('[tag:css_style]', '', $item); |
|
} |
|
|
|
$item = '<'.'?php $item_num = ' . var_export($item_num, true) . '; ?'.'>' . $item; |
|
$item = '<'.'?php $last_item = ' . var_export($last_item, true) . '; ?'.'>' . $item; |
|
|
|
$item = str_replace('[tag:if_first]', '<'.'?php if(isset($item_num) && $item_num===1) { ?'.'>', $item); |
|
$item = str_replace('[tag:if_not_first]', '<'.'?php if(isset($item_num) && $item_num!==1) { ?'.'>', $item); |
|
|
|
$item = str_replace('[tag:if_last]', '<'.'?php if(isset($last_item) && $last_item) { ?'.'>', $item); |
|
$item = str_replace('[tag:if_not_last]', '<'.'?php if(isset($item_num) && !$last_item) { ?'.'>', $item); |
|
|
|
$item = str_replace('[tag:if_sub_level]', '<'.'?php if (isset($exist_level) && $exist_level) { ?'.'>', $item); |
|
$item = str_replace('[tag:if_no_sub_level]', '<'.'?php if (isset($exist_level) && !$exist_level) { ?'.'>', $item); |
|
|
|
$item = preg_replace('/\[tag:if_every:([0-9-]+)\]/u', '<'.'?php if(isset($item_num) && !($item_num % $1)){ '.'?'.'>', $item); |
|
$item = preg_replace('/\[tag:if_not_every:([0-9-]+)\]/u', '<'.'?php if(isset($item_num) && ($item_num % $1)){ '.'?'.'>', $item); |
|
|
|
$item = str_replace('[tag:/if]', '<'.'?php } ?>', $item); |
|
$item = str_replace('[tag:if_else]', '<'.'?php }else{ ?>', $item); |
|
|
|
################### //ПАРСИМ ТЕГИ ################## |
|
|
|
// Удаляем ошибочные теги |
|
@$item = preg_replace('/\[tag:([a-zA-Z0-9-_]+)\]/', '', $item); |
|
|
|
// Определяем тег для вставки следующего уровня |
|
switch ($navi_item_level) |
|
{ |
|
case 1 : |
|
$tag = '[tag:level:2]'; |
|
$tag_exist = '[tag:level:2:exist]'; |
|
break; |
|
|
|
case 2 : |
|
$tag = '[tag:level:3]'; |
|
$tag_exist = '[tag:level:3:exist]'; |
|
break; |
|
|
|
default: |
|
$tag = ''; |
|
$tag_exist = 0; |
|
} |
|
|
|
// Если есть подуровень, то заново запускаем для него функцию и вставляем вместо тега |
|
if (! empty($navi_items[$row['navigation_item_id']])) |
|
{ |
|
$item = '<'.'?php $exist_level = true; ?'.'>' . $item; |
|
$item_sublevel = printNavi($navi_menu, $navi_items, $navi_active_way, $navi_item_tpl, $row['navigation_item_id']); |
|
$item = @str_replace($tag, $item_sublevel, $item); |
|
$item = @str_replace($tag_exist, 1, $item); |
|
} |
|
// Если нет подуровня, то удаляем тег |
|
else |
|
{ |
|
$item = '<'.'?php $exist_level = false; ?'.'>' . $item; |
|
$item = @str_replace(@$tag,'',$item); |
|
$item = @str_replace($tag_exist, 0, $item); |
|
} |
|
|
|
// Подставляем в переменную навигации готовый пункт |
|
if (empty($navi)) |
|
$navi = ''; |
|
|
|
$navi .= eval2var(' ?'.'>' . $item . '<'.'?php '); |
|
} |
|
|
|
// Вставляем все пункты уровня в шаблон уровня |
|
switch ($navi_item_level) |
|
{ |
|
case 1 : |
|
$navi = str_replace("[tag:content]", $navi, $navi_menu->level1_begin); |
|
break; |
|
case 2 : |
|
$navi = str_replace("[tag:content]", $navi, $navi_menu->level2_begin); |
|
break; |
|
case 3 : |
|
$navi = str_replace("[tag:content]", $navi, $navi_menu->level3_begin); |
|
break; |
|
} |
|
|
|
// Возвращаем сформированный уровень |
|
return $navi; |
|
} |
|
|
|
|
|
/** |
|
* Возвращает меню навигации |
|
* |
|
* @param int $id идентификатор меню навигации |
|
* @return string|mixed объект с навигацией по id, либо массив всех навигаций |
|
*/ |
|
function get_navigations($id = null) |
|
{ |
|
global $AVE_DB; |
|
|
|
$navigations = array(); |
|
|
|
if ($id) |
|
{ |
|
$sql = $AVE_DB->Query(" |
|
SELECT |
|
* |
|
FROM |
|
" . PREFIX . "_navigation |
|
WHERE |
|
" . (is_numeric($id) ? 'navigation_id' : 'alias') . " = '" . $id . "' |
|
"); |
|
} |
|
else |
|
{ |
|
$sql = $AVE_DB->Query(" |
|
SELECT |
|
* |
|
FROM |
|
" . PREFIX . "_navigation |
|
"); |
|
} |
|
|
|
while ($row = $sql->FetchRow()) |
|
{ |
|
$row->user_group = explode(',', $row->user_group); |
|
|
|
if ($id) |
|
$navigations[$id] = $row; |
|
else |
|
$navigations[$row->navigation_id] = $row; |
|
} |
|
|
|
if ($id) |
|
return $navigations[$id]; |
|
else |
|
return $navigations; |
|
} |
|
|
|
|
|
/** |
|
* Проверка прав доступа к навигации по группе пользователя |
|
* |
|
* @param int $id идентификатор меню навигации |
|
* @return boolean |
|
*/ |
|
function check_navi_permission($id) |
|
{ |
|
$navigation = get_navigations($id); |
|
|
|
if (empty($navigation->user_group)) |
|
return false; |
|
|
|
if (! defined('UGROUP')) |
|
define('UGROUP', 2); |
|
|
|
if (! in_array(UGROUP, $navigation->user_group)) |
|
return false; |
|
|
|
return true; |
|
} |
|
?>
|