Исправляем баг меню

Автор: neart
Опубликовано: 140 дней назад (11-03-2010 21:32)
Редактировалось: 7 раз — последний 140 дней назад
+5
Голосов: 7
Баг, конечно, не критичный но крайне неприятный для тех, кому нужно многоуровневое меню с разграничениями прав доступа к вложенным пунктам.

Описание бага

Предположим нам нужно сделать многоуровневое меню


Так оно будет выглядеть в свернутом виде


Теперь нам понадобилось скрыть от гостей доступ к одному из разделов


Вот, что гости увидят в итоге



Теперь, отказавшись от предыдущей затеи, скроем пункты в разделе, с надеждой, что после этого раздел превратится в обычную ссылку


В свернутом виде это будет выглядеть так


А в развернутом


Я не рискнул экспериментировать, что получится, если мы захотим одновременно скрыть вышеупомянутые пункты и раздел:)
Еще раз хочу подчеркнуть, что лично я особых ужасов в этом не вижу. Этот баг из разряда неприятностей, которые можно было бы обойти средствами системы, правда, не без некоторых потерь. Но если говорить о том, как это должно выглядеть ПРАВИЛЬНО, то по логике вещей, в развернутом виде примерно так


На всякий случай напомню исходное меню


Устранение бага

Открываем файл /modules/mod_menu/module.php
Строки:
Код PHP:
		while ($row = $inDB->fetch_assoc($rs_rows)){
			if ($row['menu'] == $menu){
Заменяем на:
Код PHP:
        $m_inside    = array();	// массив для подсчета к-ва прямых потомков разделов
        $m_num       = 0;  		// счетчик "актуальных" пунктов меню

		while ($row = $inDB->fetch_assoc($rs_rows)){
			if ( ($row['menu'] == $menu) &
					  (($row['allow_group'] == -1)||($row['allow_group'] == $inUser->group_id)||$inUser->is_admin) & 
						// заносим в массив только "актуальные" пункты меню
					  			(($row['parent_id'] == $root_id)||(isset($m_inside[$row['parent_id']]))) ){
									// отсекаем вложенные пункты, к родительскому разделу которых нет прав доступа
									
					if ( $row['NSRight'] - $row['NSLeft'] != 1 ) { 		// если  не 1 - значит имеются потомки
						$m_inside[$row['id']]['count'] = 0;			// стартовое значение счетчика прямых потомков 
						$m_inside[$row['id']]['num']   = $m_num;	// индекс пункта меню в массиве 
					}
									
					if ( $row['parent_id'] != $root_id ) { 			// если родительский раздел не является корнем
						$m_inside[$row['parent_id']]['count']++;	// счетчик прямых потомков родительского раздела увеличивается на 1
					}
Идем дальше.
Строку:
Код PHP:
                $items[]            = $item;
Заменяем на:
Код PHP:
                $items[$m_num++]  = $item;		// заносим данные в текущую ячейку массива и увеличиваем счетчик на 1
Идем дальше.
ПЕРЕД строкой:
Код PHP:
        $smarty = $inCore->initSmarty('modules', 'mod_menu.tpl');
Вставляем:
Код PHP:
		foreach ( $m_inside as $m_par ) {
			if ( !$m_par['count'] ) {  		// если нет "актуальных потомков"
				 $items[$m_par['num']]['NSRight'] = $items[$m_par['num']]['NSLeft'] + 1; // снимаем статус родителя
			}
		}
Все.
Помним, что после копирования нужно менять кавычки!

Те, кому лень или нет нужды ковырять код, могут скачать патч в каталоге дополнений.

P.S. Если разработчики сочтут целесообразным включить это решение в оф.релиз, то будет не лишним оптимизировать файл шаблона. Из него можно исключить логику отображения скрытых пунктов. Мне не составит труда это сделать.
Юзабилити-меню для InstantCMS | Новый модуль ` Универсальное меню `

Загрузка комментариев...