Login / Sign Up


Enter site:
Login: 
Password: 


First time here?
 
Register [?]:
Registering allows you:
  • Purchase products from the product catalog and access them any time.
  • Ask questions to another specialists in IT
  • Publish your own Joomla extensions, soft or other products if you are developer or distributor
  • Add interesting weblinks and access them from any place
  • Watch the updates of the site and have special abilities that guests don't have
  • Watch the news of the service and new articles and get knowledge
Choose login:
Your Email:
Enter the result of operation (in digits):
26 + 4 = ? Update

Адаптируем стороннее меню под Joomla. Делаем свой модуль меню для Joomla 2.5 (Часть 2) PDF Print E-mail
Written by Максим   
Sunday, 03 November 2013 16:44
Liked:
21


Did not like: 0

Эта статья является продолжением предыдущей статьи, в которой мы уже начали рассматривать подход по адаптации внешнего меню и превращению его в полноценный модуль Joomla для Вашего сайта. Итак, мы остановились на том, что написали метод getMenuItems() для нашего класса-помощника modColormenuHelper. Данный метод получает стандартное меню Joomla и его элементы и преобразует каждый пункт меню в структуру класса MenuItem, с которой мы уже также знакомы. На выходе из этого метода у нас будет сформированный массив всех пунктов меню, которые относятся к типу меню, переданному во входном параметре метода - $menutype

Если Вы внимательно посмотрите на тело метода getMenuItems(), то заметите, что внутри мы делаем вызов к методу processJoomlaMenuItem():


// Обработать Jooml-овский пункт меню и 

Эта статья является продолжением предыдущей статьи, в которой мы уже начали рассматривать подход по адаптации внешнего меню и превращению его в полноценный модуль Joomla для Вашего сайта. Итак, мы остановились на том, что написали метод getMenuItems() для нашего класса-помощника modColormenuHelper. Данный метод получает стандартное меню Joomla и его элементы и преобразует каждый пункт меню в структуру класса MenuItem, с которой мы уже также знакомы. На выходе из этого метода у нас будет сформированный массив всех пунктов меню, которые относятся к типу меню, переданному во входном параметре метода - $menutype

Если Вы внимательно посмотрите на тело метода getMenuItems(), то заметите, что внутри мы делаем вызов к методу processJoomlaMenuItem():


// Обработать Jooml-овский пункт меню и
// дополнить наш $mnuItem недостающими данными
$this->processJoomlaMenuItem ( $item, $mnuItem );

Сейчас пришло время написать эту самую реализацию метода processJoomlaMenuItem(). Этот метод будет "превращать" стандартную структуру пункта меню, содержащуюся в переменной $item в нашу структуру MenuItem пункта меню и результат запишет в параметр $mnuItem (поскольку параметры передаются по ссылке, переменная $mnuItem будет изменена внутри нового метода и на выходе мы получим инициализированный экземпляр класса MenuItem).

Итак, смотрим, как реализовать метод processJoomlaMenuItem():


public function processJoomlaMenuItem( & $item, & $mnuItem ) {
	switch ($item->type) {
		case 'separator' :
			$mnuItem->setItemText($item->title);
			$mnuItem->setStartTag('<span class="separator">');
			$mnuItem->setEndTag('</span>');
			return;
			break;
		case 'url' :
			if ((strpos($item->link, 'index.php?') === 0) && (strpos($item->link, 'Itemid=') === false)) {
				$item->url = $item->link.'&amp;Itemid='.$item->id;
			} else {
				$item->url = $item->link;
			}
			break;
		default:
			$app = &JFactory::getApplication();
			$router = $app->getRouter();
			$item->url = $router->getMode() == JROUTER_MODE_SEF ? 'index.php?Itemid='.$item->id : $item->link.'&Itemid='.$item->id;
			break;
		}
	}

	if ($item->url != null) {
		// Обработать SSL-ссылки
		if ($item->home == 1) {
			$item->url = JURI::base();
		} elseif (strcasecmp(substr($item->url, 0, 4), 'http') && (strpos($item->link, 'index.php?') !== false)) {
			$item->url = JRoute::_($item->url, true, 0);
		} else {
			$item->url = str_replace('&', '&amp;', $item->url);
		}
		switch ($item->browserNav) {
			default:
			case 0:
				// _top
				$mnuItem->setItemText($item->title);
				$mnuItem->setStartTag('<a href="'.$item->url.'">');
				$mnuItem->setEndTag('</a>'); 
				break;
			case 1:
				// _blank
				$mnuItem->setItemText($item->title);
				$mnuItem->setStartTag('<a href="'.$item->url.'" target="_blank">');
				$mnuItem->setEndTag('</a>');
				break;
		}
	} else {
		$mnuItem->setItemText($item->title);
		$mnuItem->setStartTag('<a>');
		$mnuItem->setEndTag('</a>');
	}
}

В чем смысл данного метода? А смысл в следующем: большинство кода, которое мы видим в этом методе, а именно развилки if и switch я взял из стандартного модуля mod_mainmenu (для версии Joomla 1.5, для 2.5 - это модуль mod_menu) , который идет в поставке Joomla и всегда присутствует в каталоге /modules/mod_mainmenu Вашего сайта. Т.е. фактически я скопировал часть кода модуля mod_mainmenu (mod_menu  в J2.5), которая отвечает за определение типа для пункта меню и добавил эту часть в helper.php нашего модуля, в метод processJoomlaMenuItem(). Вы спросите - а какие типы пунктов меню могут быть? Пункт меню - это один из следующих вариантов:

  • Тип separator - это разделитель. Это первая case-развилка, если смотреть по коду метода. Разделитель с трудом можно назвать "пунктом меню", т.к. он не несет никакой полезной информации, а просто красиво разделяет пункты между собой. Когда мы наводим мышью на меню, то в выпадающем списке разделитель логически разделяет какие-то пункты меню. Если мы имеем дело с разделителем, то мы не обязаны рисовать никаких гиперссылок типа <a>Какой-то текст</a> в нашем меню. Что мы и делаем: просто обрамляем его в тег <span> с классом "separator". А в CSS-стилях мы потом определим класс separator, который будет рисовать горизонтальную полосу-разделитель, чуть темнее, чем фон выпадающего списка меню. Вы можете увидеть разделитель - если вверху нашего сайта наведете курсор мыши на один из пунктов главного меню, например "Статьи" или "Каталог продуктов". 
  • Тип url. Это основной и самый часто встречающийся тип пункта меню. В основном именно из них будет состоять наши меню. Если мы видим, что тип переданного в наш метод processJoomlaMenuItem() пункта меню равен "url", то мы должны проверить - какой это тип URL? Дело в том, что URL может быть двух видов: внутренний и внешний. Разницу определить очень просто. Внутренние URL ссылаются на другие части Вашего сайта - на компоненты, на другие страницы и статьи и т.д. Внешний тип URL ссылается на сторонний ресурс, или сайт. Так вот, мы должны проверить - если атрибут link пункта меню начинается с подстроки - "index.php?" - значит, мы имеем дело с внутренним URL-ом. При этом мы проверяем, что, если по каким-то причинам он пока НЕ содержит параметра "Itemid". , то мы должны добавить этот параметр вручную в самый конец. Внутренние пункты меню должны содержать этот параметр.

Дальнейшие проверки, которые содержатся внутри if-оператора (if ($item->url != null)?) по сути нужны для установки различных параметров HTML-тега <a> (т.е. гиперссылки меню), а также определения того, по какому протоколу будет открываться URL пункта меню - SSL (https) или обычный http. Еще мы проверяем, нужно ли будет открывать новую страницу в браузере (параметр target="_blank" для ссылки), или нужно будет отображать окно поверх всех окон (target="_top"). Это всё уже нюансы, я бы не стал заострять на них внимания. Тем более, что мы взяли эту логику из стандартного модуля.

Еще раз повторюсь - в общем и целом метод processJoomlaMenuItem() можно рассматривать как часть кода из helper.php стандартного модуля mod_mainmenu (или mod_menu для J2.5), дополненную в нужных местах тремя вызовами

Это вызовы вида:


$mnuItem->setItemText($item->title);
$mnuItem->setStartTag('<a>');
$mnuItem->setEndTag('</a>');
 

 
Не трудно догадаться по названиям методов нашего класса MenuItem, что они делают следующее:
  • setItemText - устанавливает текст пункта меню. Этот текст будет использован при отрисовке пункта меню.
  • setStartTag - задает открывающий HTML-тег для пункта меню
  • setEndTag - задает закрывающий HTML-тег для пункта меню

Это так называемые сеттеры класса MenuItem (от слова set, которое в начале названия каждого из них). Сеттеры устанавливают внутренние скрытые атрибуты класса MenuItem. В данном случае устанавливается состояние для следующих атрибутов класса: текст пункта меню (setItemText), начальный тег (setStartTag), закрывающий тег (setEndTag). Установить-то мы установили. А как пользоватться всем этим? Если присмотритесь к классу MenuItem, там наряду с сеттерами есть геттеры - методы для получения скрытых свойств класса - getItemText(), getStartTag(), getEndTag().  Эти геттеры соответственно возвращают название пункта меню и открывающий и закрывающий HTML-теги для отрисовки пункта меню. Сейчас мы посмотрим, как эти геттеры используются. Настало время написать метод render() в классе MenuItem, который должен рисовать пункт меню.

Метод render() класса MenuItem, или отрисовываем пункт меню

Смотрим, как устроен метод render() в классе MenuItem. Добавим следующий код в конец определения класса:


// Метод возвращает строковое представление пункта меню. Это главный метод отрисовки пункта меню
function render() {
	$output = "";

	if ($this->hasChildren()) {
		if ($this->hasAccessableChildren()) {
			$output = "<li>";
			$enableDrop = $this->getEnableDropSymbol();
			$dropSymb = $this->getDropSymbol();
			$dropText = $enableDrop ? "<span class='child-arrow'>".$dropSymb."</span>" : "";
			$output .= $this->getStartTag();
			$output .= $this->getItemText() . $dropText;
			$output .= $this->getEndTag();
			$output .= "<ul>";
			foreach ($this->children as $child) {
				$output .= "<li>" . $child->render() . "</li>";
			}
			$output .= "</ul>";
			$output .= "</li>";
		}
	} else {
		if ($this->getType() != 'separator') {
			$output .= "<li>";
			$output .= $this->getStartTag();
			$output .= $this->getItemText();
			$output .= $this->getEndTag();
			$output .= "</li>";
		} else {
			$output .= "<li class='separator'>";
			$output .= $this->getStartTag();
			$output .= $this->getEndTag();
			$output .= "</li>";
		}
	}
	return $output;
}

Если мы посмотрим на этот метод, то увидим следующее: переменная $output - это строка, в которой будет "собираться" HTML-разметка для отрисовки пункта меню. Значение, собранное в $output вернётся на выходе из метода. Далее, если мы снова посмотрим на определение класса MenuItem (которое я приводил в предыдущей части статьи) , то увидим, что мы обогатили наш класс MenuItem двумя методами:

  • hasChildren() - метод вернет true, если у данного пункта меню есть дочерние подпункты. Т.е. по сути - если hasChildren() вернул true, значит текущий пункт - родительский. При этом не проверяется, что у пользователя есть доступ к дочерним элементам. Для этой цели есть еще один, специальный метод - hasAccessableChildren()
  • hasAccessableChildren() - возвращает true только тогда, когда у текущего элемента (родителя) есть видимые для пользователя дочерние элементы. Для чего это нужно? Представьте, что Вы в панели администрирования Joomla создали структуру меню, в которой у одного пункта меню есть дочерние пункты меню, доступ для которых установлен в значение "Зарегистрированный" . Это фактически значит, что пользователь должен быть зарегистрированным на Вашем сайте и увидит пункты меню, только войдя под своим логином и паролем на сайт. Для гостя - эти пункты (согласно установленному в админке доступу) должны быть не видны. Вопрос - надо ли рисовать "пустой" родительский пункт меню для гостя? Нет, не надо (Если всё же Вам это потребуется, просто реализуйте самостоятельно ветку else для этой цели). Именно поэтому нам нужно при отрисовке пункта меню проверять - есть ли у него не просто дочерние элементы, а те, к которым у пользователя имеется доступ в соответствии с правами, установленными в панели управления Joomla.

Еще хочу обратить внимание на следующие строки:


$enableDrop = $this->getEnableDropSymbol();
$dropSymb = $this->getDropSymbol();
$dropText = $enableDrop ? "<span class='child-arrow'>".$dropSymb."</span>" : "";
$output .= $this->getStartTag();
$output .= $this->getItemText() . $dropText;
$output .= $this->getEndTag();

В данных строчках происходит следующее - мы получаем признак $enableDrop, который отвечает за отображение спец-символа "стрелки" ( ►) рядом с пунктом меню, у которого есть вложенные (дочерние) пункты меню. В переменную $dropSymb попадает само значение этого символа (либо HTML-код, либо непосредственно символ). Возможность задания символа мы вынесем в параметры модуля - чтобы можно было управлять им из админки Joomla. Если спец-символ отображать надо, то в $enableDrop будет значение true, а в переменную $dropText запишется HTML-разметка для вывода этого символа. Если же символ не нужен, то в $dropText запишется пустая строка "".

После чего мы слепляем строку $output с разметкой нашего пункта меню по правилам:  <Открывающий HTML-тег> + <Текст пункта меню> + <Символ "стрелки" или просто пустая строка> + <Закрывающий HTML-тег>

Я могу поздравить читателя! Мы уже наполовину написали наш модуль меню! Всё то, что осталось сделать дальше, на мой взгляд - дело техники и не так сложно, как то, что мы уже рассмотрели. Давайте вместе посмотрим, что нас ждёт дальше:

  • Нам нужно задать CSS-стили для отрисовки наших выпадающих меню, пунктов меню, разделителей между пунктами, - словом, всего, что будет выводить наш модуль.
  • Мы должны определить параметры модуля в файле XML-дескриптора модуля. В параметрах мы будем задавать цвет фона меню, цвет шрифта и прочие параметры отрисовки меню. Более того, нам предстоит написать свой тип параметра, поскольку нам не будет хватать стандартных типов параметров Joomla. Мы посмотрим, как самому написать класс параметра модуля.
  • Нам предстоит написать реализацию файла "вывода" модуля - default.php. Он расположен в подкаталоге tmpl модуля - tmpl/default.php

Поскольку мы полностью завершили рассмотрение реализации класса-помощника helper.php для нашего модуля меню, я хочу кратко напомнить читателю о том, чего мы уже достигли и чему научились:

  • Мы написали полностью класс помощника modColormenuHelper, наполнили его логикой и методами
  • Написали свой класс для пункта меню - MenuItem, познакомились с методами, которые он содержит, в частности с главным методом render() для отрисовки пункта меню.
  • Мы определили методы хелпера, которые будут выводить настройки и параметры типов меню и пунктов меню, заданных через админку Joomla

Продолжение статьи читаем в части 3.

Скачать заглушку для модуля

Скачать готовый модуль



Last Updated on Monday, 23 December 2013 01:40
 
Автор статьи: Damascus
Всего статей: 62
Рейтинг: 3111
Страница Google+: Google

Found Error?

Система Orphus

Site Statistics

Яндекс.Метрика

Our Pages


Allineed.Ru © 2009-2012 - Allineed.Ru - ответы на IT вопросы, статьи о разработке, IT и программном обеспечении. При использовании материалов сайта ссылка обязательна. Использование данного сайта и любой его части означает принятие условий Пользовательского Соглашения.
Allineed.Ru is not affiliated with or endorsed by the Joomla! Project or Open Source Matters. The Joomla! name and logo is used under a limited license granted by Open Source Matters the trademark holder in the United States and other countries.