Upd: English version of the article: Joomla: Content filtering by articles, categories and components.


В статьях о привязке соцкнопок и хлебных крошек к определенным страницам Joomla-сайта рассматривалась фильтрация только по материалам. Единственное исключение - во второй из них было также указано, как скрыть навигатор на странице избранных материалов. Но что если нужно привязать модуль либо другое расширение, а в общем случае - любой кусок кода к выбранным категориям, компонентам, определенным страницам компонентов, а то и ко всему перечисленному одновременно? Вы скажете, что модули и так привязываются к пунктам меню, а при использовании более продвинутого менеджера модулей (например, Advanced Module Manager) - и к категориям, статьям, пользователям, компонентам и т. д. Это так; но, чтобы выводить модуль с разными настройками вывода на соответствующих страницах, придется создать несколько его копий, привязанных к этим страницам. Например, на этом сайте модуль последних комментариев выводит список комментариев к материалам тех категорий и компонентов, на странице которых он высвечивается. Поскольку структура сайта достаточно разветвленная, да к тому же он еще и мультиязычный, количество копий модуля - целых 8 (восемь!) только для русской части сайта. Неудобно.

Предлагаемое решение обеспечит гибкость и контекстность вывода контента по заданным критериям. Знание кода желательно, но я постараюсь дать точные рекомендации по его внедрению, что позволит и менее квалифицированным джумловодам его использовать при условии точного выполнения процедуры. К тому же, я попытался в отдельной статье подробно описать структуру внутренних ссылок сайта на Joomla, что призвано облегчить понимание алгоритма. Ну что, по коням?

Я написал функцию и назвал ее content_filter. Код функции - чуть ниже под катом.

Описание и код функции content_filter

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

function content_filter($exception_articles,
                        $exception_categories = null,
                        $exception_category_views = null,
                        $exception_components = null)

Аргументы:

Первые три - простые одномерные массивы вида:

array($value1, $value2, ...)

Элементы массивов:

  • $exception_articles - идентификаторы отдельных материалов;
  • $exception_categories - идентификаторы категорий для страниц вывода материалов;
  • $exception_category_views - идентификаторы категорий для страниц списков или блогов материалов, к этим категориям относящихся.

Эти три массива оперируют материалами и категориями, за вывод которых отвечает базовый компонент Джумлы com_content. Имя компонента - ключ option, а также вид (представление) - ключ view не входят в массивы в явном виде. Значение первого ключа - подразумевается, а вид определяется автоматически.

А вот четвертый массив $exception_components может быть использован для управления выводом страниц других компонентов, имеющих те же ключи, что и com_content. И ключи эти задаются в явном виде:

array(
  array(name => $name1 [, view => $view1][, catid => $catid1][, $id => $id1]),
  array(name => $name2 [, view => $view2][, catid => $catid2][, $id => $id2]),
  ...
)

Элементами являются массивы типа ключ => значение, соответствующие данным отдельного компонента. Ключи внутреннего массива соответствуют параметрам в строке запроса внутренней ссылки на определенную страницу компонента.

Каждый аргумент-массив может получать значение null, означающее, что функция не будет фильтровать содержимое на соответствующих страницах. То же относится и к элементам четвертого массива.

Заполнение аргументов при вызове функции content_filter будет ниже подробно проиллюстрировано примерами.

Возвращаемое функцией значение - true в случае, если выводимая страница сайта соответствует значению хотя бы одного элемента какого-либо из четырех массивов-аргументов.

Код функции content_filter

function content_filter($exception_articles,
                        $exception_categories = null,
                        $exception_category_views = null,
                        $exception_components = null) {
  global $cf_option, $cf_view, $cf_art_cat_id, $cf_cat_id;
 
  //1. if current page is category or article in com_content
  if ($cf_option == 'com_content') {
    if ($cf_view == 'article') {
      // $cf_cat_id is category ID; $cf_art_cat_id is article ID
      //1.1 check article exceptions
      if (isset($exception_articles)) {
        for ($i=0, $n=sizeof($exception_articles); $i<$n; $i++) {
          if ($cf_art_cat_id == $exception_articles[$i])
            return true;
        }
      }
      //1.2 check category exceptions for article view
      if (isset($exception_categories)) {
        for ($i=0, $n=sizeof($exception_categories); $i<$n; $i++) {
          if ($cf_cat_id == $exception_categories[$i])
            return true;
        }
      }
    }
    //1.3 check category exceptions for category view
    // $cf_art_cat_id is category ID
    elseif ($cf_view == 'category' && isset($exception_category_views)) {
      for ($i=0, $n=sizeof($exception_category_views); $i<$n; $i++) {
        if ($cf_art_cat_id == $exception_category_views[$i])
          return true;
      }
    }
  }
  //2. check components
  // $cf_cat_id is component category ID; $cf_art_cat_id is component ID
  if (isset($exception_components)) {
    for ($i=0, $n=sizeof($exception_components); $i<$n; $i++) {
      if ($cf_option == $exception_components[$i][name] &&
         (!isset($exception_components[$i][view]) ||
           $cf_view == $exception_components[$i][view]) &&
         (!isset($exception_components[$i][catid]) ||
           $cf_cat_id == $exception_components[$i][catid]) &&
         (!isset($exception_components[$i][id]) ||
           $cf_art_cat_id == $exception_components[$i][id]))
      return true;
    }
  }
  return false;
}

end faq

Помещение функции content_filter в библиотеку и инициализация глобальных переменных

Куда поместить сию дивную функцию? Можно просто в отдельный файл, а можно добавить в одну из существующих библиотек. Желательно, чтобы это не была библиотека ядра, в этом случае при обновлениях Джумлы функцию придется восстанавливать вручную. В папке моего шаблона, сделанном изначально в Artisteer, нашелся файл functions.php, включенный в самом начале файла индекса шаблона:

<?php
defined('_JEXEC') or die;
 
require_once dirname(__FILE__) . DIRECTORY_SEPARATOR . 'functions.php';

В functions.php я и добавил вышеприведенный код функции content_filter.

Из того самого кода видно также, что функция использует 4 глобальные переменные, соответствующие как раз параметрам выводимой страницы. Сделано так для того, чтобы не инициализировать их каждый раз в случае нескольких вызовов функции с одной и той же страницы. Поэтому инициализация их вынесена в файл индекса активного шаблона. Откройте на редактирование файл templates\[active_template]\index.php, заменив [active_template] на имя вашей папки. Сразу после строки подключения библиотеки, содержащей нашу функцию, вставьте код инициализации глобальных переменных. В результате начало кода в файле index.php приняло такой вид:

<?php
defined('_JEXEC') or die;
 
require_once dirname(__FILE__) . DIRECTORY_SEPARATOR . 'functions.php';
 
//initialize global variables for content_filter()
global $cf_option, $cf_view, $cf_art_cat_id, $cf_cat_id;
 
$jinput = JFactory::getApplication()->input;
 
$cf_option = $jinput->getCmd('option');
$cf_view = $jinput->getCmd('view');
 
$temp = explode(':', $jinput->getCmd('id'));
$cf_art_cat_id = $temp[0] + 0;
 
$temp = $jinput->getInt('catid');
$cf_cat_id = $temp[0] + 0;

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

Вот теперь функция content_filter включена в код страницы сайта. Самое время перейти к примерам ее вызова.

Примеры использования функции content_filter

Пример 1. Отключение хлебных крошек на страницах ошибки 404 для двух языков, а также на страницах компонентов поиска и авторизации. (По сути это - усовершенствованная версия кода фильтрации навигатора из соответствующей статьи.)

if ($view->containsModules('breadcrumb') && 
    !content_filter(
      array(80, 448), //$exception_articles
      null,           //$exception_categories
      null,           //$exception_category_views
      array(
        array(name => 'com_users'),
        array(name => 'com_search')
      )               //$exception_components
    ) //!content_filter
  ) //if
    echo artxPost($view->position('breadcrumb'));

Пример 2. Отключение панели социальных кнопок на страницах материалов, относящихся к категории 1, а также на страницах вывода категорий 1, 3 и 6 в виде списка или блога.

<?php
if (
    !content_filter(
      null,          //$exception_articles
      array(1),      //$exception_categories
      array(1, 3, 6) //$exception_category_views
                     //$exception_components is null by default
    ) //!content_filter
  ) //if
?>
 
    <!-- скрипт вывода кнопок -->
 
<?php } ?>

Пример 3. Вывод баннера только на страницах категорий 6 и 7 компонента JoomGallery, а также на карте сайта, имеющей id=4.

<?php
if (
    content_filter(
      null,          //$exception_articles
      null,          //$exception_categories
      null,          //$exception_category_views
      array(
        array(name => 'com_joomgallery', view => 'category', catid => 6),
        array(name => 'com_joomgallery', view => 'category', catid => 7),
        array(name => 'com_xmap', id => 4)
      )               //$exception_components
    ) //content_filter
  ) { //if
?>
 
    <!-- скрипт вывода баннера -->
 
<?php } ?>

В заключение перечислю несколько ограничений при использовании предложенной версии функции content_filter.

  • Не включен фильтр по избранным материалам.
  • Для представления материалов категории (массив $exception_category_views) не введено условие по дополнительному ключу layout, отвечающему за вывод материалов в одной из двух возможных компоновок - списка или блога.
  • Функция не обрабатывает страницы компонентов, в которых имеются параметры, отличные от четырех основных. Как, например, в VitrueMart - controller и task. Для таких компонентов можно ввести отдельные функции обработки вывода. В случае с тем же VitrueMart пример кода дан в ответе на вопрос, заданный в обсуждении статьи об избирательном выводе хлебных крошек.

Функцию я писал под себя, и все виды фильтров, в нее включенные, удовлетворяют требованиям по избирательному выводу контента на этом сайте к моменту написания статьи. В дальнейшем, по мере возникновения подобных задач в моей практике, равно как и поступления вопросов от любознательных читателей этой площадки, будут писаться статьи с детальным рассмотрением частных случаев применения описанной методики.

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