ICQ214-697-723 | Emailinfo@mainsource.ru | Телефон(812) 946-31-81
Все контакты
Автор статьи
Синцов Роман
Дорабатываем своими руками модуль «Комментарии» для UMI.CMS

Дорабатываем своими руками модуль «Комментарии» для UMI.CMS. Делаем по новому.

Спустя годы разработки приложений, управляемых на UMI.CMS, я как-то взглянул на одну из своих старых статей, в которой речь шла о выводе комментариев, и понял, что вводил в заблуждение своих читателей, такой вариант реализации без использования API UMI я настоятельно не рекомендую использовать. И сейчас решил исправиться и все-таки написать, как же правильно произвести кастомизацию модуля «Комментарии».

От чего в первую очередь хочу уберечь разработчиков UMI: ни в коем случае не правим код существующих классов и методов, как это было описано в предыдущей статье. Иначе вы мгновенно лишитесь возможности обновить свою систему управления. Почему это важно? Ну... потому что не бывает идеальных продуктов, регулярно выходят обновления, а не давно появился сервис хот-фиксов. А теперь представьте, как будет обидно разработчику, если все его труды будут затёрты при обновлении, а как уж будет обидно владельцу сайта. Поэтому не экономим свое время, а сразу делаем все правильно.

Теперь, давайте вспомним, в чем заключалась наша задача: мы хотим поменять порядок вывода комментариев на странице. Чтобы нам было интереснее, я приведу пример кода для редакции 2.7 и для редакции 2.8 с использованием класса selector.

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

Исходный код модуля комментариев находится в classes/modules/comments. Метод, с работой которого мы будем разбираться, находится в файле class.php. Ищем функцию вставки комментариев:

public function insert($parent_element_id = false, $template = "default") {

Копируем его полностью. Далее, находим в этой же папке файл __custom.php — он как раз предназначен для размещения своей бизнес-логики, подробнее почему и зачем так, вы можете прочитать в документации UMI.CMS. Вставляем в тело класса __custom_comments скопированный нами ранее метод insert.

Теперь мы можем смело редактировать и видоизменять этот метод на свое усмотрение, при обновлении он будет работать. Но для того чтобы у нас не возникло конфликта с уже существующим методом insert, требуется переименовать скопированный нами метод. На самом деле мы могли бы назвать этот метод любым удобным для нас способом, но исходя из собственного опыта, имеет смысл переименовать метод так, чтобы было понятно, что он является «метаморфозой» базового метода данного модуля. Отсюда предлагаю несколько вариантов, которые нравятся лично мне:

custom_insert()
customInsert()
_insert()

Лично я предпочитаю именовать все методы как раз в виде customInsert() (camelCase), но в случае базовых, я использую подчеркивание, так что в нашем примере метод будет называться _insert(). Подробнее о наименованиях можно почитать тут.

Для того, чтобы можно было использовать наш метод, и результат его выполнения был доступен простому посетителю сайта, необходимо добавить соответствующие права на его выполнение, создав в текущей папке файл permissions.custom.php, добавив в него следующий код:

<?php
$permissions = Array('insert' => Array('_insert'));
?>

Поскольку наш основной класс comments наследуется от класса def_module (это также верно и для других модулей), то требуется обязательно это учитывать, так как наш кастомный класс использует методы этого класса. Отсюда: для того, чтобы ваш метод _insert() заработал, необходимо сразу внести правки. Тут возможны два варианта: либо сделать кастомный класс наследуемым от def_module

abstract class __custom_comments extends def_module

либо заменить все указатели self на def_module.
Я предпочитаю вариант добавления для класса extends def_module.

Теперь давайте попробуем разобраться, как нам использовать в шаблонах соответствующий метод. Вот пример для tpl-шаблонизатора:

%comments _insert(%pid%, ‘default’)%

В случае xslt:

<xsl:template match="udata[@module = 'comments' and @method = '_insert']">
</xsl:template>
<xsl:template match="udata[@method = '_insert']/add_form" mode="guest">
</xsl:template>

В случае с tpl у вас должен быть оформленный шаблон для комментариев в папке tpls/comments/default.tpl.

В случае xslt вам нужно в теле шаблона вставить свою верстку, или, если у вас установлен шаблон «современного магазина», взять код из xsltTpls/modules/comments/comments-list.xsl.

Ну, или поиском найти в папке xsltTpls строку вида

udata[@module = 'comments' and @method = 'insert']

и скопировать от туда содержимое, а также содержимое этого шаблона

<xsl:template match="udata[@method = 'insert']/add_form" mode="guest">

Также требуется заменить стандартный вызов списка комментариев

<xsl:apply-templates select="document('udata://comments/insert')" />

на

<xsl:apply-templates select="document('udata://comments/_insert')" />

Если уже есть шаблоны, то можно просто переименовать существующие методы. Более подробно о шаблонах в рамках статьи я не буду рассказывать.

Убедитесь, что после этого комментарии и форма добавления комментариев продолжают отобржаться на сайте так же, как и раньше. Если же этого не происходит, значит что-то вы сделали не верно.

Теперь давайте вернемся к нашему методу _insert(). Для того, чтобы передавать в него параметр для выбора сортировки комментариев (прямого и обратного) добавляем новую переменную — $sort — и установим ей сразу значение по умолчанию.

public function insert($parent_element_id = false, $template = "default", $sort = 0) {

В нашем случае:

  • $sort = 0 — комментарии выводятся в порядке по умолчанию;
  • $sort = 1 — комментарии выводятся в обратном порядке.
Далее давайте рассмотрим два варианта реализации для версии 2.7 (в настоящий момент такой вариант актуален и для 2.8.4.4, пояснения дам ниже).

Находим строчку

$sel->setOrderByProperty($publish_time_field_id, false);

Собственно, если внимательно смотреть документацию по API UMI, вы увидите, что делает этот метод. Чтобы нам реализовать требуемый функционал, удаляем эту строку и добавляем такой код:

$sel->setOrderByProperty($publish_time_field_id, $sort);

Собственно все готово :)

Важно: чтобы эта замечательная вещь работала как в случае xslt, так и в случае tpl, требуется также добавить следующий код в метод, в самое начало:

if (getRequest('sort') != null) $sort = getRequest('sort');

Этот код нам нужен для xslt-шаблонизатора. Если при вызове метода передается параметр sort, то нужно его учитывать. Как это использовать в шаблоне, будет рассказано ниже.

В новой редакции UMI 2.8.4.4 для реализации используется устаревший класс umiSelection & umiSelectionsParser (deprecated). Это вероятно связано с тем, что разработчики не успели переписать код своих методов, но надо понимать, что потенциально при очередном обновлении они могут окончательно отказаться от использования этих классов в пользу selector. В связи с этим рекомендую использовать для своей логики новый класс.

Находим блок кода

$hierarchy_type_id = umiHierarchyTypesCollection::getInstance()->getTypeByName("comments", "comment")->getId();

$sel = new umiSelection;

$sel->setElementTypeFilter();
$sel->addElementType($hierarchy_type_id);
$sel->setHierarchyFilter();
$sel->addHierarchyFilter($parent_element_id);
$sel->setPermissionsFilter();
$sel->addPermissions();

$object_type_id = umiObjectTypesCollection::getInstance()->getBaseType("comments", "comment");
$object_type = umiObjectTypesCollection::getInstance()->getType($object_type_id);

$publish_time_field_id = $object_type->getFieldId('publish_time');

$sel->setOrderFilter();
$sel->setOrderByProperty($publish_time_field_id, false);

$sel->setLimitFilter();
$sel->addLimit($per_page, $curr_page);

$result = umiSelectionsParser::runSelection($sel);
$total = umiSelectionsParser::runSelectionCounts($sel);

И смело его удаляем, а вместо него пишем следующий код:

$sel = new selector('pages');

$sel->types('hierarchy-type')->name('comments', 'comment');
$sel->where('hierarchy')->page($parent_element_id)->childs(1);
$sort = $sort ? 'asc' : 'desc';
$sel->order('publish_time')->$sort();
$sel->limit($curr_page, $per_page);

$result = $sel->result;
$total = $sel->length;

Ощущаете насколько упростился код? Теперь дам краткие пояснения к этой выборке.
Выбираем все элементы иерархии типа комментарии: $sel->types('hierarchy-type')->name('comments', 'comment'). Кроме этого нам нужно выбрать все комментарии для конкретной страницы $sel->where('hierarchy')->page($parent_element_id)->childs(1).
Далее в зависимости от значения sort задаем тип сортировки.

В отличии от предыдущей выборки $result содержит не идентификаторы (id) элементов, а сами элементы, поэтому правим код в цикле по $result.
Было:

foreach($result as $element_id){
line_arr = Array();

$element = $oHierarchy->getElement($element_id);

Меняем на:

foreach($result as $element){
line_arr = Array();

$element_id = $element->getId();

Все готово для использования.

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

%comments insert(%pid%, ‘default’, 1)%

Здесь:

  • pid — вывод комментариев только текущей страницы;
  • default — стандартный шаблон отображения модуля;
  • 1 — режим сортировки.

Для xslt:

<xsl:apply-templates select="document('udata://comments/_insert/?sort=1')" />

Изображение комментариев на UMI (с обратным порядком)
Вы должны увидеть примерно такую картину после изменений.

Что хочется отметить... Да, такой вариант немного более трудоемкий, чем предложенный в предыдущем решении, но зато вы избавлены от проблем потери своего кода после обновлений CMS.

Опубликовано в октябре 2011 года.

Upmix [18.02.2012 23:41]
Зачем городить такие сложности с написание кастомных классов. Сортировка задается в шаблоне с помощью xsl:sort.

Перейти к списку статей

АкцияИнтересные акции и предложения

Эксклюзивный сайт на UMI.CMS — 40 000 рублей, абсолютно все включено! Значительно дешевле!

полный список

Наши специалисты имеют высшее образование в сфере компьютерных технологий, а также многолетний опыт работы по своим направлениям.

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

вакансии Вакансии партнеры Партнеры
отзывы Отзывы сотрудники Сотрудники
faq Вопросы и ответы

Реализованные проекты

vzemle.ru Буровой сайт
Информационный сайт на базе CMS 1С-Битрикс "под ключ".
pro-tours.ru Форум под ключ
Туристический портал для общения, реализованный на популярном движке.

другие

MainSource