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.
497 lines
15 KiB
497 lines
15 KiB
8 years ago
|
<?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;
|
||
|
|
||
|
$gen_time = microtime(true);
|
||
|
|
||
|
// извлекаем id из аргумента
|
||
|
$navi_id = $navi_tag[1];
|
||
|
|
||
|
// извлекаем level из аргумента
|
||
|
$navi_print_level = $navi_tag[2];
|
||
|
|
||
|
$navi = '';
|
||
|
|
||
|
$cache_file = BASE_DIR . '/cache/sql/nav/template-' . $navi_id . '.cache';
|
||
|
|
||
|
if(! file_exists(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);
|
||
|
|
||
|
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 = '';
|
||
|
|
||
|
if ($AVE_Core->curentdoc->Id == $doc_active_id)
|
||
|
{
|
||
|
$sql_doc_active_alias = "
|
||
|
OR nav.alias = '" . $alias . "'
|
||
|
OR nav.alias = '/" . $alias . "'
|
||
|
OR nav.alias = '" . $alias . URL_SUFF . "'
|
||
|
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 1:
|
||
|
$navi_parent = 0;
|
||
|
break;
|
||
|
|
||
|
// текущий и родительский уровни
|
||
|
case 0:
|
||
|
$sql_navi_active = ' AND parent_id IN(' . $navi_active_way_str . ') ';
|
||
|
$navi_parent = 0;
|
||
|
break;
|
||
|
|
||
|
// только текущий уровень
|
||
|
case 2:
|
||
|
$sql_navi_level = ' AND level = ' . $navi_active_level . ' ';
|
||
|
$navi_parent = $navi_active_id;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
$cache_items = BASE_DIR . '/cache/sql/nav/items-' . $navi_id . '.cache';
|
||
|
|
||
|
$navi_items = array();
|
||
|
|
||
|
//-- Проверяем есть файл кеша, если есть пропускам запрос к БД
|
||
|
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;
|
||
|
}
|
||
|
|
||
|
file_put_contents($cache_items, serialize($navi_items));
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
$navi_items = unserialize(file_get_contents($cache_items));
|
||
|
}
|
||
|
|
||
|
if($navi_print_level)
|
||
|
{
|
||
|
$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 = microtime(true) - $gen_time;
|
||
|
$GLOBALS['block_generate'][] = array('NAVIGATION_' . $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,1).'; $last_item='.var_export($last_item,1).'?'.'>'.$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 = 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_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 = @str_replace(@$tag,'',$item);
|
||
|
$item = @str_replace($tag_exist, 0, $item);
|
||
|
}
|
||
|
|
||
|
// Подставляем в переменную навигации готовый пункт
|
||
|
if (empty($navi))
|
||
|
$navi = '';
|
||
|
|
||
|
$navi .= $item;
|
||
|
}
|
||
|
|
||
|
// Вставляем все пункты уровня в шаблон уровня
|
||
|
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;
|
||
|
}
|
||
|
?>
|