ave-cms/functions/func.navigation.php
2017-11-17 12:02:05 +03:00

509 lines
15 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?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'] . "&amp;doc=" . ((!$row['alias']) ? prepare_url($row['title']) : trim($row['alias'], '/')), $item);
//разрешаем слешь в конце ссылки
$item = str_replace('[tag:link]', 'index.php?id=' . $row['document_id'] . "&amp;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 . '<?');
}
// Вставляем все пункты уровня в шаблон уровня
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;
}
?>