Комментарии

Получение оптимально соответствующего пункта меню
( 0 Голосов )

В методе getCategoryRoute () из файла helpers/route.php обнаруживается пункт меню, оптимально соответствующий идентификатору текущей категории. Как же это происходит? Сначала проверяется наличие пункта меню единственной категории для данной категории. Если такой пункт меню имеется, то возвращается URL, указывающий на этот пункт меню, и все. А если соответствующий пункт меню отсутствует, то осуществляется поиск пункта меню веб-ссылок, указывающего на одну из родительских категорий (родительскую, прародительскую и т.д.) для текущей категории.

Для этого создается массив всех ее родительских категорий, а затем каждая из них проверяется по списку пунктов меню веб-ссылок. Сначала проверяются представления единственных категорий, поскольку они подходят лучше, чем представления многих категорий. Если представление единственной категории не удастся найти для любой из родительских категорий, то проверяются пункты меню, соответствующие представлениям многих категорий. И наконец, если не удастся найти ни один из пунктов меню веб-ссылок или категорий, соответствующих любой из родительских категорий, то для создания ссылки просто выбирается активный в настоящий момент пункт меню.

А теперь перейдем непосредственно к коду. В первой части метода getCategory Route () для текущей категории получается объект типа JCategoryNode. Главной в этой части является следующая строка кода:

$category = JCategories::getlnstance('Weblinks')->get($id);

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

$needles = array( 'category' => array($id)
($item = self::_findltem($needles)) {
$link = 'index.php?Itemid='.$item; }

Именно здесь и делается попытка найти точное соответствие. Для этого сначала создается массив из представления категории и ее идентификатора, а затем проверяется, соответствует ли она одному из существующих пунктов меню, для чего вызывается метод _findltem ().

Обратите внимание на то, что для вызова метода _findltem() вместо выражения $this-> используется префикс self: :, поскольку этот метод является статическим. Ключевое слово self означает "этот класс", тогда как переменная $this ссылается на "этот объект". Таким образом, для вызова статических методов или обращения к статическим полям в том классе, где они определены, необходимо пользоваться ключевым словом self. Это ключевое слово было внедрено в версии 5 языка РНР.

Если обнаружено точное соответствие категории существующему пункту меню, то поставленная задача считается выполненной. В противном случае выполняется приведенный ниже фрагмент кода.

//  создать  ссылку
$link =   'index.php?option=com weblinks&view=category&id='.$id;
if ($category) {
$catids = array_reverse($category->getPath()); $needles = array(
'category' => $catids,
'categories' => $catids );
if ($item = self::_findltem($needles)) {
$link .= '&Itemid=*.$item; } else if ($item = self::_findltem()) {
$link .= '&Itemid='.$itera; } }

В этом фрагменте кода сначала создается ссылка, кроме идентификатора категории. А затем составляется список идентификаторов родительских категорий для идентификатора текущей категории, для чего вызывается метод get Path () из класса JCategoryNode. Напомним, что в данном примере родительской для категории с идентификатором 33 (Other Resources) является категория с идентификатором 32 (Joomla Specific Links), а для нее родительской — категория с идентификатором 18 (Sample Data-Weblinks). Метод getPath () возвращает все родительские категории, обнаруженные в массиве, используя для этого формат <идентификатор> + <псевдоним>. Так, для категории с идентификатором 33 из этого метода возвращается следующий результат:

=> 18:sample-data-weblinks
=> 32:joomla-specific-links
=> 33:other-resources

Содержимое массива просто обращается с помощью функции array_reverse (), чтобы идентификатор 33 стал нулевым элементом, а идентификатор 18 — третьим элементом данного массива, как показано ниже.

=> 33:other-resources
=> 32:joomla-specific-links
=> 18:sample-data-weblinks

Полученный результат сохраняется в переменной $catids.

Затем создается массив $needles, предназначенный для сравнения по списку пунктов меню веб-ссылок. Этот массив является ассоциативным и состоит из двух элементов с ключами category и categories, значением для которых является массив $catids.

Далее метод self: :_findltem($needles) вызывается еще раз. На этот раз поиск расширяется, включая любую родительскую категорию и пункт меню категорий. Первым ключом в ассоциативном массиве $needles является категория, и поэтому сначала среди всех пунктов меню веб-ссылок ищется пункт меню единственной категории, чтобы выяснить, соответствует ли идентификатор этой категории одному из идентификаторов родительских категорий. Если соответствие не будет найдено, то повторяется процесс проверки пунктов меню веб-ссылок с представлением, равным категориям.

Ниже приведен первый фрагмент кода из метода _findltem ().

protected static function_findltem($needles = null) {
$app = JFactory::getApplication();
$menus = $app->getMenu('site');
// подготовить массив к поиску в  обратном порядке if (self::$lookup === null) { self::$lookup = array();
$component = JComponentHelper:rgetComponent('com_weblinks'); $items = $menus->getltems('component_id', $component->id); foreach ($items as $item) {
(isset($item->query) && isset($item->query['view'])) {
$view = $item->query['view'];
(!isset(self::$lookup[$view])) { self::$lookup[$view] = array();
(isset($item->query['id'])) {
self::$lookup[$view][$item->query['id']] = $item->id;

В переменной $menus хранится объект типа JMenuSite. В классе Web links Helper Route имеется статическое поле $lookup. А поскольку оно статическое, то значение в нем достаточно установить лишь один раз. До тех пор пока этот класс находится в оперативной памяти, его статические поля остаются определенными. В первом условном операторе if из приведенного выше фрагмента кода проверяется, установлено ли данное поле. Если оно установлено, то делать этого больше не нужно.

Для организации массива $ items из всех пунктов меню компонента Weblinks вызывается метод getl terns () из класса JMenuSite. Этот метод возвращает массив объектов стандартных классов с полями для хранения отдельных пунктов меню веб-ссылок. Затем организуется циклическое обращение к пунктам меню веб-ссылок в данном массиве и создается ассоциативный массив $ lookup, ключом к которому служит преставление, извлекаемое из запроса пункта меню, а значением — еще один ассоциативный массив. Ключом к этому массиву служит извлекаемый из запроса идентификатор (т.е. идентификатор категории), а значением — идентификатор пункта меню. В рассматриваемом здесь примере с загруженными выборочными данными содержимое массива $ lookup определяется следующим образом:

=> array (0 => 438, 18 => 227) category => array(32 => 274, 31 => 296)

Следует заметить, что конкретные идентификаторы могут отличаться в зависимости от изменений в выборочных данных, но описанный выше принцип остается неизменным. Как видите, в данном массиве определены четыре пункта меню веб-ссылок: два — для выбора предствления многих категорий и еще два — для выбора предствления единственной категории. Пункты меню многих категорий обозначаются значением 438, указывающим на категорию с идентификатором 0 (т.е. корневую категорию для всей таблицы), а значение 227 указывает на категорию с идентификатором 18 (Sample Data-Weblinks). Пункты меню единственных категорий обозначаются значением 274, указывающим на категорию с идентификатором 32, а значение 296 указывает на категорию с идентификатором 31.

После того как массив $ lookup будет определен, можно попытаться найти оптимальное соответствие для текущей категории, используя массив $needles. Исходный код, необходимый для этой цели, приведен ниже.

($needles) {
($needles as $view =>  $ids) {
(isset(self::$lookup[$view])) { foreach($ids as $id) {
(isset(self::$lookup[$view][(int)$id])) { return self::$lookup[$view][(int)$id]; } }

Циклическое обращение к массиву $ needles производится по искомому представлению. Сначала в нем ищется представление единственной категории, а затем представление многих категорий. Поочередно просматривается каждый идентификатор $ids в иерархии категорий. Напомним, что порядок следования элементов данного массива изменен на обратный, и поэтому текущая категория (с идентификатором 33) располагается в нем первой, затем следует родительская категория (с идентификатором 32), далее — прародительская категория (с идентификатором 18) и т.д. Следовательно, поиск происходит в установленном порядке предпочтений. И как только будет найдено точное соответствие представления идентификатору категории (в выделенной выше полужирным строке кода), возвращается идентификатор соответствующего пункта меню, который в данном случае является значением, извлекаемым из элемента массива $ lookup. После выполнения команды return происходит немедленный возврат из данного метода.

Напомним, что среди прочих значений в массиве $needles находится псевдоним категории (например, "33: other resources"), а следовательно, значение переменной $id будет представлено в таком формате. Именно поэтому в рассматриваемом здесь коде используется оператор приведения (int), чтобы преобразовать значение переменной $id в идентификатор категории (например, 33) при обращении к массиву $lookup.

А теперь осталось лишь рассмотреть случай, когда соответствие не найдено. В этом случае просто возвращается идентификатор активного в текущий момент пункта меню. После возврата к методу getCategoryRoute () идентификатор пункта меню присоединяется к ссылке (например, " & Itemid=27 4 "), которая и возвращается. В итоге получается ссылка, указывающая на пункт меню веб-сайта, в наибольшей степени соответствующий идентификатору текущей категории. Им оказывается один из следующих пунктов меню в порядке очередности.

Пользовательская часть компонента Weblinks

  • Пункт меню единичной категории веб-ссылок для выбора данной категории.
  • Пункт меню единичной категории веб-ссылок для выбора одной из родительских категорий данной категории.
  • Пункт меню многих категорий веб-ссылок для выбора одной из родительских категорий данной категории.
  • Активный в текущий момент пункт меню.

Понравился материал? Пригодилась информация? Плюсани в социалки!


 
Похожие новости