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

Как известно, модули 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 Закачек 467 Скачать

Здесь же в коде класса, расположенном чуть ниже под катом, я укажу только сами измененные части (блоки) кода. Каждый из двух блоков я сопроводил в комментариях номерами строк, соответствующих началу и концу заменяемого блока кода в изначальном файле. Для наглядности присутствуют и кликабельные скриншоты результатов сравнения в 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 и примеры их применения", призвана помочь вам в этом.

Комментарии  

post-235
0 # post-235 01.11.2022 18:48
Hello there! I know this is kinda off topic however I'd
figured I'd ask. Would you be interested in exchanging links or maybe guest writing
a blog post or vice-versa? My blog covers a lot of the same subjects as yours and I feel
we could greatly benefit from each other. If you are interested feel free to shoot me an e-mail.

I look forward to hearing from you! Fantastic blog by the way!
Ответить | Ответить с цитатой | Цитировать
post-235
0 # post-235 08.11.2022 14:34
Link exchange is nothing else however it is just placing the other person's weblog link on your page at
proper place and other person will also do similar for you.
Ответить | Ответить с цитатой | Цитировать
euroopera.org
0 # euroopera.org 16.11.2022 08:17
I'm gone to say to my little brother, that
he should also go to see this website on regular basis to take updated from
hottest information.
Ответить | Ответить с цитатой | Цитировать
Sue
0 # Sue 17.11.2022 09:31
I have to thank you for the efforts you've put in penning this website.
I really hope to view the same high-grade content from you
in the future as well. In truth, your creative writing abilities
has motivated me to get my very own website now ;)
Ответить | Ответить с цитатой | Цитировать
https://pornax.net
0 # https://pornax.net 27.11.2022 18:38
Красиво написано, информативно было для меня!
Ответить | Ответить с цитатой | Цитировать
tb naptár 2021
0 # tb naptár 2021 29.11.2022 04:35
Hey this is kind of of off topic but I was wondering
if blogs use WYSIWYG editors or if you have to manually code with HTML.
I'm starting a blog soon but have no coding expertise so I wanted to get advice from someone with experience.

Any help would be enormously appreciated!

My website ... tb naptár 2021
Ответить | Ответить с цитатой | Цитировать
https://pornax.net
0 # https://pornax.net 02.12.2022 23:32
Вы реально безошибочно мните.

Хорошо, что я сюда забежал.
Благодарность!
Ответить | Ответить с цитатой | Цитировать
top online casinos
0 # top online casinos 05.12.2022 21:39
Hi there thіs iis kind of ⲟf off topic but I was ѡanting to knjow іf blogs ᥙse WYSIWYG editors or
if yoս have to manually code ԝith HTML. I'm starting
a blog ѕoon butt hɑve no coding skills so І wɑnted to get advice frߋm someߋne with experience.
Аny helkp woulⅾ bbe enormously appreciated!


Ⅿy page ... top online casinos
Ответить | Ответить с цитатой | Цитировать

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


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