Как иногда начинают свой монолог неопытные стендаперы: «У всех в жизни было такое …», когда вывел на главную страницу сайта список пользователей, а там половина – серые тени новичков, не подтвердивших регистрацию. Давайте в качестве ещё одного примера по использованию хуков уберём их оттуда, оставив только реальных пользователей.
Есть два способа это сделать по-простому.
1. Добавить одну строку в код дефолтного виджета «Новые пользователи» для фильтрации по признаку блокирования пользователя. Но это хак, который слетит при обновлении движка. Помнить об этом хаке и следить за обновлением файла очень не хочется.
2. Создать копию этого виджета и внести правку туда. Новый виджет при обновлении не слетит, но и обновлять его придётся вручную. Тоже не подходит.
Попробуем сделать всё без хаков движка.
Включим «Требовать подтверждения e-mail при регистрации», зарегистрируем нового пользователя с ником «Новенький». Переключим стиль виджета на «Список». К Администратору добавился неподтверждённый Новенький, что логично, но нам бы хотелось его скрыть.
Если вы ещё не знаете что такое события/хуки, для чего они нужны и как работают, то перед тем как читать этот пост дальше, прочитайте Что такое события и хуки (без PHP и с картинками)
(В этом месте можете почитать Что такое фильтры в отладке и как ими пользоваться))
Парой кликов включим трассировку событий хотя бы на три уровня и сразу увидим, что эти события возникают в строках 20 и 67 нашего виджета /system/controllers/users/widgets/list/widget.php.
В строке 20 файла виджета видим событие, которое передаёт в хук поля профиля и модель компонента пользователей. Это уже хорошо. Да и по названию события видно, что это для фильтра списка пользователей.
В событии в строке 67 этого же файла передаются уже готовый список пользователей и список выводимых в виджете полей.
Нам лучше подойдёт первый хук, в котором к модели списка пользователей можно будет применить дополнительный фильтр по отключённым пользователям и сразу получить нужное количество активных пользователей. При использовании второго хука нам придётся в цикле перебрать отобранных пользователей и оставить только подтверждённых – их суммарное количество может измениться, а нам это не нужно.
Если изучить код этого файла, то можно найти в нём пару событий, которые возвращают/обрабатывают список пользователей и о которых мы уже говорили выше. Логика выбора остаётся той же. В данном случае поиск событий по коду оказался очень простым, но так бывает не всегда.
Первое, что видно, в событие действительно передаётся массив описаний полей и объект modelUsers. Это нам подходит.
Второе, это то, что событие ‘profiles_list_filter’ происходит на странице дважды: в нашем виджете «Новые пользователи» и в виджете «Сейчас онлайн». Поиск по коду движка говорит, что это событие возникает в пяти местах: в двух виджетах, в обработке подписок и в списках пользователей, полученных через метод renderProfilesList() компонента Users.
Добавим языковые константы в файл \system\languages\ru\controllers\webman\webman.php
В нём сначала присваиваем элементы массива $data отдельным переменным: описанию полей $fields и модели пользователей $model_users.
Потом проверяем включение опции 'users_no_locked'.
И если она включена, то добавляем к модели пользователей фильтр: только пользователей, у которых поле 'is_locked' равно null, то есть пользователь не заблокирован.
И в конце возвращаем объединённые в массив входные переменные $fields и $model_users, чтобы их могли обработать другие такие же хуки или код после хука в точке его вызова.
Добавляем хук в манифест /system/controllers/webman/manifest.php
Отлично! Заблокированный пользователь исчез из списков в виджете и на странице пользователей.
В этом варианте дополнительно получаем массив трассировки вызовов в переменную $backtrace. Перебираем его элементы $line и ищем в них класс 'widgetUsersList'. Если находим, то присваиваем переменной $found значение true, которое является разрешением для добавления нашего фильтра пользователей.
Проверяем. Теперь в виджете «Новые пользователи» остался только Администратор – только активные пользователи. А в списке пользователей на странице httр://site/users показывает и активных, и заблокированных пользователей. Всё как мы и хотели, наш фильтр применяется только при вызове из одного виджета.
Тогда строка проверки класса в хуке может выглядеть как-то так:
Для ленивых ссылка на готовый пакет обновления webman_update_1.2.0.zip.
Есть два способа это сделать по-простому.
1. Добавить одну строку в код дефолтного виджета «Новые пользователи» для фильтрации по признаку блокирования пользователя. Но это хак, который слетит при обновлении движка. Помнить об этом хаке и следить за обновлением файла очень не хочется.
2. Создать копию этого виджета и внести правку туда. Новый виджет при обновлении не слетит, но и обновлять его придётся вручную. Тоже не подходит.
Попробуем сделать всё без хаков движка.
Подготовка
Чтобы использовать хуки нужно иметь свой компонент для них. Если у вас уже такой есть – отлично. Если нет, можете себе создать компонент для хуков — мы всё будем делать на примере компонента из этого поста.Включим «Требовать подтверждения e-mail при регистрации», зарегистрируем нового пользователя с ником «Новенький». Переключим стиль виджета на «Список». К Администратору добавился неподтверждённый Новенький, что логично, но нам бы хотелось его скрыть.
Ищем событие для изменения списка пользователей
Начнём с выяснения, откуда в виджете берётся список пользователей и есть ли подходящее событие, чтобы его изменить.Если вы ещё не знаете что такое события/хуки, для чего они нужны и как работают, то перед тем как читать этот пост дальше, прочитайте Что такое события и хуки (без PHP и с картинками)
Смотрим события отладкой
Используем простой и наглядный вариант поиска событий. В «Расширенной отладке» включим вывод в лог виджетов и в их фильтре напишем имя виджета «Новые пользователи». Также включим вывод событий в лог.(В этом месте можете почитать Что такое фильтры в отладке и как ими пользоваться))
После обновления главной страницы демо увидим, во-первых, что из всех виджетов в логе остался только один наш, во-вторых, внутри виджета есть три события ‘profiles_list_filter’, ‘profiles_before_list’ и ‘render_widget_users_list_list’.
Третье событие нам не интересно – по названию видно, что там происходит рендеринг html-кода виджета. А вот первые два надо бы изучить…
Парой кликов включим трассировку событий хотя бы на три уровня и сразу увидим, что эти события возникают в строках 20 и 67 нашего виджета /system/controllers/users/widgets/list/widget.php.
Теперь нужно узнать, передаётся ли в этих событиях что-то, что мы можем использовать?
В строке 20 файла виджета видим событие, которое передаёт в хук поля профиля и модель компонента пользователей. Это уже хорошо. Да и по названию события видно, что это для фильтра списка пользователей.
В событии в строке 67 этого же файла передаются уже готовый список пользователей и список выводимых в виджете полей.
list($profiles, $show_fields) = cmsEventsManager::hook('profiles_before_list', [$profiles, $show_fields]);
Ищем события в коде
Самый главный вопрос при любом поиске: "Где искать?". Если вы читали «официальную документацию по виджетам» или мой пост «Как работают виджеты (без PHP и с картинками)», то ответите на него легко. Виджет (widget) «Новые пользователи» принадлежит контроллеру (controllers) "Пользователи" (users), а значит находится в его папке /system/controllers/users/widgets. Там мы видим только три виджета: avatar, list и online. Понятно, что нас интересует list — список. Итого получаем имя файла /system/controllers/users/widgets/list/widget.phpЕсли изучить код этого файла, то можно найти в нём пару событий, которые возвращают/обрабатывают список пользователей и о которых мы уже говорили выше. Логика выбора остаётся той же. В данном случае поиск событий по коду оказался очень простым, но так бывает не всегда.
Событие ‘profiles_list_filter’
На всякий случай посмотрим, что реально передаётся в первом событии. Включим «Выводить в лог данные событий». И впишем в строку фильтра по имени события ‘profiles_list_filter’. В выпадающем списке его нет, так как там только события от зарегистрированных хуков, а это событие никто не обрабатывает, хука нет.Смотрим, что передаётся в хуки в первом событии:
Первое, что видно, в событие действительно передаётся массив описаний полей и объект modelUsers. Это нам подходит.
Второе, это то, что событие ‘profiles_list_filter’ происходит на странице дважды: в нашем виджете «Новые пользователи» и в виджете «Сейчас онлайн». Поиск по коду движка говорит, что это событие возникает в пяти местах: в двух виджетах, в обработке подписок и в списках пользователей, полученных через метод renderProfilesList() компонента Users.
Это значит, что если мы будем менять список пользователей в обработке этого события, то не подтверждённые пользователи будут исключены во всех местах, где оно происходит. Для некоторых проектов это как раз подходит, а для других придётся придумать проверку, из какого места был сделан вызов хука, и фильтровать только в нужном виджете.
Добавляем опцию
В компоненте «Хуки-хухуки» уже есть вкладка «Виджеты». Так как наш хук относится к пользователям, то добавим в файл \system\controllers\webman\backend\forms\form_options.php ещё одну вкладку «Пользователи» с опцией 'users_no_locked' «Исключать неактивных пользователей из списков».
'type' => 'fieldset', 'title' => LANG_WEBMAN_OPT_TAB_USERS, 'title' => LANG_WEBMAN_OPT_USERS_NO_LOCKED, )), ) ),
<?php class formWebmanOptions extends cmsForm { public $is_tabbed = true; public function init() { 'type' => 'fieldset', 'title' => LANG_WEBMAN_OPT_TAB_WIDGETS, 'title' => LANG_WEBMAN_OPT_WD_TITLE_LINK, )), ) ), 'type' => 'fieldset', 'title' => LANG_WEBMAN_OPT_TAB_USERS, 'title' => LANG_WEBMAN_OPT_USERS_NO_LOCKED, )), ) ), ); } }
<?php
Создаём хук
Создадим новый файл с именем обрабатываемого события /system/controllers/webman/hooks/profiles_list_filter.php.
<?php class onWebmanProfilesListFilter extends cmsAction { public function run($data){ // --- Поле ссылки под заголовком виджета ------------------------------ if ($this->options['users_no_locked']) { // Добавляем к модели пользователей фильтр, исключающий заблокированных пользователей $model_users->filterIsNull('is_locked'); } return [$fields, $model_users]; } }
Потом проверяем включение опции 'users_no_locked'.
И если она включена, то добавляем к модели пользователей фильтр: только пользователей, у которых поле 'is_locked' равно null, то есть пользователь не заблокирован.
И в конце возвращаем объединённые в массив входные переменные $fields и $model_users, чтобы их могли обработать другие такие же хуки или код после хука в точке его вызова.
Добавляем хук в манифест /system/controllers/webman/manifest.php
И разрешаем добавить наш хук в список хуков («Админка – Компоненты — Управление событиями»).
Отлично! Заблокированный пользователь исчез из списков в виджете и на странице пользователей.
Фильтр только в виджете
Если мы хотим фильтровать список пользователей только в нашем виджете, то нужно в хуке проверять, откуда сделан его вызов. Я не нашёл в движке стандартного способа получить эту информацию, поэтому используем небольшой лафхак – поищем класс нашего виджета 'widgetUsersList' в трассировке вызовов PHP из функции debug_backtrace()
<?php class onWebmanProfilesListFilter extends cmsAction { public function run($data){ // --- Поле ссылки под заголовком виджета ------------------------------ if ($this->options['users_no_locked']) { // Получаем трассировку // Ищем в трассировке имя класса нужного виджета $found = false; foreach ($backtrace as $line) { if ($line['class'] == 'widgetUsersList') { $found = true; break; } } if ($found) { // Добавляем к модели пользователей фильтр, исключающий заблокированных пользователей $model_users->filterIsNull('is_locked'); } } return [$fields, $model_users]; } }
Проверяем. Теперь в виджете «Новые пользователи» остался только Администратор – только активные пользователи. А в списке пользователей на странице httр://site/users показывает и активных, и заблокированных пользователей. Всё как мы и хотели, наш фильтр применяется только при вызове из одного виджета.
Расширение функционала
Вы можете самостоятельно расширить возможности этого хука. Например, добавить в опции строковое поле с перечнем классов через запятую без пробелов, при вызове из которых нужно добавлять фильтр по заблокированным пользователям. Это позволит гибко управлять фильтром без программирования.Тогда строка проверки класса в хуке может выглядеть как-то так:
Пакет обновления компонента
Создание пакета обновления компонента описано в предыдущей части про Добавление ссылки под заголовки виджетов.Для ленивых ссылка на готовый пакет обновления webman_update_1.2.0.zip.
Не забывайте, что имя webman везде нужно заменить на своё имя компонента с сохранением регистров символов
Реклама #
Make 3 года назад #
T34 3 года назад #
Scythian 3 года назад #
Dark Space 3 года назад #