Во вступлении к статье о фильтрации контента по материалам, категориям и компонентам я упомянул, что для избирательной привязки модуля последних комментариев требуется создавать некоторое количество его копий. На сайте, достаточно разветвленном по структуре и тематике, а особенно - в случае многоязычности, это количество может исчисляться десятками. Каждая копия имеет свои настройки, устанавливаемые в менеджере модулей. Если нужно изменить какие-либо параметры во всех или даже нескольких копиях модуля, предстоит кропотливая и нудная работа в админке сайта - открывать страницу каждой копии и вручную вносить изменения. Можно, конечно, объединять комментарии к нескольким смежным темам в один общий модуль, но не лучше ли найти гибкое решение, позволяющее и рыбку съесть - четко отфильтровать комменты к каждой теме или даже подтеме, и манту не замочить - свести количество копий модуля к минимуму, а то и к одной-единственной. Я, как мне кажется, таковое решение нашел, и помогло мне в этом знание структуры внутренних ссылок страниц приложений, формируемых движком Джумлы.

Как известно, модули Joomla привязываются к пунктам меню. В случае mod_jcomments_latest введена также привязка к компонентам. Есть еще и дополнительная фильтрация по категориям, но лишь для случая, когда в списке компонентов выбран ТОЛЬКО com_content. Соответственно, нужны отдельные копии модуля для каждой категории основного компонента Joomla, а также для каждого дополнительного приложения. В пределах копии можно объединять категории com_content или несколько компонентов. Нет возможности объединить, например, комментарии к категориям и комментарии к приложениям, отличным от com_content, в один блок. Мой метод позволяет в пределах блока фильтровать комментарии к категориям и отдельным материалам приложения com_content и одновременно - к другим компонентам и их структурным элементам. Подробно и с примерами объясню принцип такой гибкой фильтрации.

Кастомизация кода модуля mod_jcomments_latest

Изменения требуется внести в код класса помощника данного модуля, который стандартно расположен в файле [корень_сайта]\modules\mod_jcomments_latest\helper.php. Рассматривается билд 3.0.4 - новейший на время написания статьи. (Кстати, на русскоязычной части сайта производителя пакета JComments на странице закачки модулей - http://www.joomlatune.ru/jcomments-modules.html - почему-то последний билд - 3.0.3, тогда как на англоязычной - http://www.joomlatune.com/jcomments-modules.html - 3.0.4. Имейте это в виду и не удивляйтесь.)

Все кастомизации вносятся в код ключевого и самого первого метода класса modJCommentsLatestHelper. Метод этот - getList. Вы можете скачать архив, содержащий две версии файла помощника - оригинальную и мною отредактированную, - и сравнить содержимое каким-нибудь инструментом (например, WinMerge):

Original & Customised helper.php of mod_jcomments_latest
Дата 2016-06-23 Система  Windows Размер файла 7.5 KB Закачек 333 Скачать

Здесь же в коде класса, расположенном чуть ниже под катом, я укажу только сами измененные части (блоки) кода. Каждый из двух блоков я сопроводил в комментариях номерами строк, соответствующих началу и концу заменяемого блока кода в изначальном файле. Для наглядности присутствуют и кликабельные скриншоты результатов сравнения в WinMerge с подсветкой изменений (справа - оригинальный код, слева - кастомизированный).

Измененный код функции getList

public static function getList(&$params) {
/*
  cut 1
*/
 
//Customization #1 ==BEGIN== (lines 27 - 36 in original file)
  switch ($params->get('ordering', '')) {
    case 'vote':
      $orderBy = '(isgood-ispoor) DESC';
      break;
 
    case 'date':
    default:
      $orderBy = 'date DESC';
      break;
  }
//Customization #1 --END--
 
/*
  cut 2
*/
 
//Customization #2 ==BEGIN== (lines 100 - 134 in original file)
  $categories = '';
  $components = array();
  getCommentsFilter($categories, $components);
 
  $query = '';
  $union = false;
  for ($i = 0; $i <= 1; $i++) { //1st for com_content, 2nd for other components
    $joins = array();
    $where_i = $where; //resets $where_i for each iteration
    if ($i == 0 && !empty($categories)) { //1st iteration
      $joins[] = 'JOIN #__content AS cc ON cc.id = o.object_id';
      if ($categories != 'all')
        $joins[] = 'LEFT JOIN #__categories AS ct ON ct.id = cc.catid';
 
      $where_i[] = "(cc.publish_up = '0000-00-00 00:00:00' OR cc.publish_up <= '$now')";
      $where_i[] = "(cc.publish_down = '0000-00-00 00:00:00' OR cc.publish_down >= '$now')";
      $where_i[] = "(c.object_group = " . $db->Quote('com_content') . ($categories != 'all' ? " AND cc.catid IN (" . $categories . ")" : "") . ")";
    }
    elseif ($i == 1 && !empty($components)) { //2nd iteration
      $where_cmp = array();
      for ($j = 0, $nj = sizeof($components); $j < $nj; $j++)
        $where_cmp[] = '(c.object_group LIKE ' . $db->Quote($components[$j] . '%') . ')';
      $where_i[] = '(' . implode(' OR ', $where_cmp) . ')';
    }
    else
      continue;
 
    $union = $i == 1 && !empty($query); //2nd iteration, 1st query filtering by categories was built
    if ($union)
      $query = '(' . $query . ') UNION (';
 
    $query .= "SELECT c.id, c.userid, c.comment, c.title, c.name, c.username, c.email, c.date, c.object_id, c.object_group, '' as avatar" . ", o.title AS object_title, o.link AS object_link, o.access AS object_access, o.userid AS object_owner" . " FROM #__jcomments AS c" . " JOIN #__jcomments_objects AS o ON c.object_id = o.object_id AND c.object_group = o.object_group AND c.lang = o.lang" . (count($joins) ? ' ' . implode(' ', $joins) : '') . (count($where_i) ? ' WHERE ' . implode(' AND ', $where_i) : '');
  }
 
  $list = array();
  if (!empty($query)) {
    $query .= ($union ? ")" : "") . " ORDER BY " . $orderBy; //adds common ordering for both queries in union (if any) of just for one quey
    $db->setQuery($query, 0, $params->get('count'));
    $list = $db->loadObjectList();
 
    if (!is_array($list)) {
      $list = array();
    }
  }
//Customization #2 --END--
 
/*
  cut 3
*/
}

end faq

Изменение 1:

Единая фильтрация вывода модуля mod_jcomments_latest - кастомизация 1

Как видим, здесь просто убраны все вхождения префикса алиаса таблицы для предложения сортировки ORDER BY sql-запроса (query). Зачем - будет ясно далее.

Изменение 2 - глобальное:

Единая фильтрация вывода модуля mod_jcomments_latest - кастомизация 2

Не буду подробно разбирать код строка за строкой; кому интересно - может разобраться сам, в чем помогут комментарии внутри кода. Я же изложу идею и реализацию.

В коде формируется запрос к таблицам комментариев, долженствующий выдавать список комментариев по условиям привязки. Условия - строковая переменная $categories и массив $components, заполняемые в функции getCommentsFilter, о которой ниже. В оригинале результат фильтрует альтернативно либо комменты к статьям и категориям компонента com_content, либо ко всем страницам отличных от него приложений. В моем варианте эти два результата могут быть скомбинированы в единый общий, а до комплекту - для ВСЕХ, в том числе сторонних, приложений становится возможной привязка к отдельным страницам этих компонентов по более избирательному фильтру.

Для этого реализованы два прохода (итерации): первая - для com_content, вторая - для прочих компонентов. Результаты запросов затем объединены с помощью оператора UNION, после чего уже совокупный результат сортируется через ORDER BY. И вот тут и становится ясен смысл первой кастомизации: при наличии псевдонимов (алиасов) таблиц MySQL выдает ошибку, поскольку они определены только внутри каждого из объединяемых запросов и недоступны для объединенного запроса.

Также предусмотрен вариант отсутствия в условии привязки либо по com_content, либо по прочим компонентам. В этом случае соответствующая итерация пропускается и объединение не производится.

Функция getCommentsFilter

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

  • $cf_option - имя компонента (с префиксом com_);
  • $cf_view - вид (представление) конкретной страницы компонента;
  • $cf_art_cat_id - идентификатор материала или категории в зависимости от текущего представления (см. здесь);
  • $cf_cat_id - идентификатор категории, в которую входит выводимый материал (в случае, когда cf_view==article);
  • $cf_lang - язык страницы (для мультиязычного сайта).

Как описано здесь, код функции можно разместить в одной из существующих библиотек, лучше всего - в файле functions.php активного шаблона. Код инициализации глобальных переменных лучше всего поместить в файл индекса шаблона templates\[active_template]\index.php ниже строки подключения библиотеки. Начало кода в моем файле index.php выглядит следующим образом:

defined('_JEXEC') or die;
 
require_once dirname(__FILE__) . DIRECTORY_SEPARATOR . 'functions.php';
 
$app = JFactory::getApplication();
$jinput = $app->input;
 
global $cf_option, $cf_view, $cf_art_cat_id, $cf_cat_id, $cf_lang;
 
$cf_option   = $jinput->getCmd('option');
$cf_view   = $jinput->getCmd('view');
 
$temp   = explode(':', $jinput->getCmd('id'));
$cf_art_cat_id   = $temp[0] + 0;
 
$temp   = explode(':', $jinput->getCmd('catid'));
$cf_cat_id = $temp[0] + 0;
 
$cf_lang = substr(JFactory::getLanguage()->getTag(),0,2);

Определение функции getCommentsFilter имеет следующий вид:

function getCommentsFilter(&$categories, &$components)

Аргументами функции являются две вышеупомянутые переменные - строковая $categories и массив $components, передаваемые из кастомизированного нами метода getList класса помощника модуля mod_jcomments_latest по ссылке, о чем свидетельствуют знаки амперсанд (&) перед их именами. В функции они заполняются значениями: первый - списком идентификаторов категорий, разделенных запятой, второй - списком имен компонентов; затем передаются обратно в метод getList и используются как условия выборки в предложении WHERE соответствующего sql-запроса.

Ниже под катом - код функции getCommentsFilter, используемый на момент написания статьи на этом сайте:

Код функции getCommentsFilter

function getCommentsFilter(&$categories, &$components) {
  global $cf_option, $cf_view, $cf_art_cat_id, $cf_cat_id, $cf_lang;
 
  if ($cf_lang == 'ru') {
    $hebro_cats = array(69, 71, 72, 73, 75, 76, 77, 83, 84, 85);
    $reg_cats = array(25, 26, 27, 48, 86);
    $tech_cats_str = '26,27';
 
    if ($cf_option == 'com_content') {
      if ($cf_view == 'article') {
        if (in_array($cf_art_cat_id, array(783, 307))) // Glavnaya, obratnaya-svyaz
          $categories = 'all';
        elseif (in_array($cf_cat_id, $reg_cats)) // Blog, chinim-kompy, stroim-sajty, trudoustrojstvo-zapiski-posvyashchennogo, sovety-doktora-aleny
          $categories = $cf_cat_id;
        elseif ($cf_cat_id == 28) // guitar
          $categories = 'guitar';
        elseif (in_array($cf_art_cat_id, array(614, 454, 603, 694)) || in_array($cf_cat_id, $hebro_cats)) // Hebroman
          $categories = 'hebroman';
        elseif (in_array($cf_art_cat_id, array(433, 434, 724, 957))) //video
          $categories = 'all';
      } elseif ($cf_view == 'category') {
        if (in_array($cf_art_cat_id, $reg_cats)) // Blog, chinim-kompy, stroim-sajty, trudoustrojstvo-zapiski-posvyashchennogo, sovety-doktora-aleny
          $categories = $cf_art_cat_id;
        elseif ($cf_art_cat_id == 28) // guitar
          $categories = 'guitar';
        elseif (in_array($cf_art_cat_id, $hebro_cats)) // Hebroman
          $categories = 'hebroman';
      }
    } elseif ($cf_option == 'com_muscol') // TiALP
      $categories = 'guitar';
    elseif ($cf_option == 'com_bt_portfolio') { // portfolio
      $categories = $tech_cats_str; // fixing-comps, building-sites
      $components[] = 'com_bt_portfolio';
    } elseif ($cf_option == 'com_joomgallery') // fotogalereya
      $components[] = 'com_joomgallery';
    elseif ($cf_option == 'com_jdownloads') {
      if (in_array($cf_cat_id, array(8, 9, 11))) // Hebroman
        $categories = 'hebroman';
      elseif ($cf_cat_id == 3) // Attachments
        $categories = $tech_cats_str; // chinim-kompy, stroim-sajty
      elseif ($cf_cat_id == 4) // Comp
        $categories = '26'; // chinim-kompy
      elseif ($cf_cat_id == 5) // Joomla
        $categories = '27'; // stroim-sajty
    } elseif ($cf_option == 'com_xmap') {
      if ($cf_art_cat_id == 1) // karta-sajta
        $categories = 'all';
      elseif ($cf_art_cat_id == 4) // karta-hebroman
        $categories = 'hebroman';
    }
 
    if ($categories == 'guitar') {
      $categories = '28';
      $components[] = 'com_muscol';
    } elseif ($categories == 'hebroman')
      $categories = implode(',', $hebro_cats);
  } elseif ($cf_lang == 'en') {
    $reg_cats = array(42, 43, 54);
    $tech_cats_str = '42,43';
 
    if ($cf_option == 'com_content') {
      if ($cf_view == 'article') {
        if (in_array($cf_art_cat_id, array(784, 306))) // home, feedback
          $categories = 'all';
        elseif (in_array($cf_cat_id, $reg_cats)) // fixing-comps, building-sites, employment-notes-of-the-initiate
          $categories = $cf_cat_id;
      } elseif ($cf_view == 'category') {
        if (in_array($cf_art_cat_id, $reg_cats)) // fixing-comps, building-sites, employment-notes-of-the-initiate
          $categories = $cf_art_cat_id;
      }
    } elseif ($cf_option == 'com_muscol') // TiALP
      $components[] = 'com_muscol';
    elseif ($cf_option == 'com_bt_portfolio') { // portfolio
      $categories = $tech_cats_str; // fixing-comps, building-sites
      $components[] = 'com_bt_portfolio';
    } elseif ($cf_option == 'com_joomgallery') // photogallery
      $components[] = 'com_joomgallery';
    elseif ($cf_option == 'com_jdownloads') {
      if ($cf_cat_id == 3) // Attachments
        $categories = $tech_cats_str; // fixing-comps, building-sites
      elseif ($cf_cat_id == 4) // Comp
        $categories = '42'; // fixing-comps
      elseif ($cf_cat_id == 5) // Joomla
        $categories = '43'; // building-sites
    } elseif ($cf_option == 'com_xmap') {
      if ($cf_art_cat_id == 2) // site-map
        $categories = 'all';
    }
  }
}

end faq

Как из него видно, первым делом идет привязка к языкам. Для каждого языка фильтруются комменты к статьям и категориям компонента com_content, а затем - к остальным компонентам. Некоторые из этих компонентов (в частности, com_jdownloads и com_xmap) также имеют категории, и привязка осуществляется отдельно к каждой из них в соответствии с ее тематикой. В случае многоуровневой (древовидной) структуры категорий комментарии дочерних категорий объединяются для привязки к категории-родителю. Пример - обработка страниц категорий компонента com_jdownloads. В случае гитарной директории объединяются комментарии к страницам самой директории (компонент com_muscol) и категории 'Гитара' (id==28) компонента com_content - в представлениях как блога категории, так и каждого материала, к ней относящегося.

Для случая, когда выводятся последние комменты ко всем страницам компонента com_content, функция передает в вызывающий ее код значение 'all' переменной $categories. В моем случае, например - для Главной страницы, формы обратной связи, страниц категории 'Видео' в обоих представлениях, а также всех карт сайта. Когда же нет необходимости в фильтрации комментариев к страницам прочих приложений, массив $components остается пустым.

Таким образом, в моем случае обработаны все разделы сайта для каждого языка:

  • Отдельные страницы - Главная, Обратная связь.
  • 8 разделов в русской и 3 в английской частях сайта. Каждый раздел включает страницы в представлении материалов и блогов одной или нескольких категорий.
  • По 5 прочих приложений для каждого языка:
    • Гитарная директория com_muscol - комменты к ней объединены с таковыми к категории 'Гитара' компонента com_content;
    • Компонент портфолио com_bt_portfolio - объединены комменты к страницам самого приложения и к страницам двух технических категорий;
    • Компонент для скачивания файлов com_jdownloads - обработаны 4 категории в русской части, 3 - в английской;
    • Карта сайта com_xmap - обработаны 2 карты в русской, 1 - в английской;
    • Галерея изображений com_joomgallery - обычная привязка ко всем страницам приложения.

Итого: для привязки последних комментариев до кастомизации я использовал около 20 (двадцати!) копий модуля mod_jcomments_latest. При этом отсутствовала возможность объединять комменты к страницам компонента com_content и других приложений. Теперь же я могу объединить комменты к ЛЮБЫМ страницам ЛЮБЫХ приложений. На данный момент у меня всего две копии модуля - для каждого из языков сайта, привязанные в админке по умолчанию - реальная привязка осуществляется в измененном коде.

Какой минус? При изменении структуры и условий привязки требуется вносить изменения в код модуля. Лично для меня это давно не является проблемой, как не является ею и сохранение кастомизаций при обновлении расширений разработчиками. Можно, конечно, усовершенствовать административную часть модуля, добавив функционал для подобной гибкой привязки и получая на фронт-энде условия фильтрации из параметров модуля. Но вот это уже - целый проект, игра не стоит свеч. А вот разобраться в структуре внутренних ссылок Joomla и утилизировать приобретенные знания для повышения гибкости привязки кода к избранным страницам сайта - дело весьма полезное. Эта статья, как и предыдущие (и, надеюсь, последующие) статьи цикла "Внутренние ссылки Joomla и примеры их применения", призвана помочь вам в этом.

Комментарии  

dildok3
# dildok3 25.10.2020 10:49
Appreciation to my father who told me regarding
this web site, this web site is genuinely awesome.


Also visit my homepage - dildok3
Ответить | Ответить с цитатой | Цитировать
o
# o 07.11.2020 23:02
First of all I want to say awesome blog! I had a
quick question which I'd like to ask if you do not mind. I was interested to know how you
center yourself and clear your mind prior to writing. I have had a tough time clearing my
mind in getting my ideas out there. I truly do take pleasure
in writing but it just seems like the first 10 to 15 minutes tend to be
wasted just trying to figure out how to begin. Any ideas or hints?
Thank you!

Also visit my website :: o
Ответить | Ответить с цитатой | Цитировать
f
# f 08.11.2020 07:10
Hiya! Quick question that's entirely off topic. Do you
know how to make your site mobile friendly? My site looks weird when viewing from my iphone 4.
I'm trying to find a template or plugin that might be able to resolve this issue.
If you have any recommendations, please share. Thanks!

Look into my web blog: f
Ответить | Ответить с цитатой | Цитировать
8
# 8 08.11.2020 07:39
I'm really enjoying the design and layout of your site.
It's a very easy on the eyes which makes it much more enjoyable for me to
come here and visit more often. Did you hire out a developer to create your theme?

Fantastic work!

Visit my web blog 8
Ответить | Ответить с цитатой | Цитировать

Добавить комментарий


Работая с этим сайтом, вы даете свое согласие на использование файлов cookie, необходимых для сохранения выбранных вами настроек, а также для нормального функционирования сервисов Google.