Теперь подберем функции, которые будут использоваться для выборки записей блогов с учетом прав доступа и связей пользователей внутри социальной сети. Сначала выясним, не заложены ли в системе уже готовые решения, на базе которых можно сформировать «Ленту друзей» или хотя бы нечто похожее. Первое, что приходит на ум – «если есть компонент ведения журнала событий, то нет ли в нем подходящих функций?». Изучаем список свойств и методов (или код компонента) и видим, что для получения списка событий в нем используется функция CSocNetLogEvents::GetUserLogEvents():
CSocNetLogEvents:: GetUserLogEvents(int userID, array arFilter = Array());
Функция возвращает структуру, содержащую список событий социальной сети по фильтру arFilter. Параметр userID — идентификатор пользователя, в массиве arFilter сохраняется набор параметров для выборки данных из БД. Он имеет структуру вида:
array("фильтруемое поле"=>"значение фильтра" [, ...]),
где фильтруемое поле может принимать значения: ENTITY_TYPE (тип сущности социальной сети, U – пользователь или G - группа), ENTITY_ID – идентификатор сущности социальной сети, EVENT_ID – идентификатор инициатора события (сигнатуры blog, photo, forum или system), LOG_DATE_DAYS – количество дней для выборки журнала. Фактически, количество дней ограничено временем жизни журнала (неделя), очистка выполняется агентом CSocNetLog::ClearOldAgent().
Функция возвращает структуру, содержащую идентификатор события, его тип, дату и время, текстовое описание, заголовок, ссылку на страницу, имеющую отношение к событию, идентификатор модуля, где событие было инициировано, набор данных, определяющих права доступа, данные о пользователе и др. Увы, но, ознакомившись с результатами работы этой функции, делаем вывод, что она не совсем подходит.
Во-первых, функция CSocNetLogEvents::GetUserLogEvents() работает только в контексте пользователя, а нам нужны еще и данные групп. Во-вторых, не передаются типы записей, т. е. записи добавления комментариев и сообщений ничем не отличаются друг от друга, идентифицировать их «по-человечески» не получится. Не возвращаются ID блогов и сообщений, а они нужны, чтобы сформировать нам ссылки. Время жизни записи «Ленты друзей» принудительно ограничивается агентом модуля (это поправимо, но требует вмешательства в обработку соответствующего события, чего делать бы не хотелось). Возможно, в будущих версиях Социальной сети разработчики «Битрикс» предпримут какие-то меры, но на момент написания этого материала и соответствующего компонента, ситуация была такова.
Поиск других подходящих функций в модуле тоже не дал результата. Остается два выхода. Первый — самостоятельно реализовать нужный нам метод. С точки зрения системного подхода, это более правильное решение, но… Здесь могут возникнуть проблемы обратной совместимости. Модуль сравнительно новый, мало ли что может измениться в недалеком будущем. Второй путь — получить необходимые данные, скомбинировав результаты нескольких стандартных методов, благо, изучение исходных текстов модуля дает четкое представление, как это сделать. Вот и попробуем.
Общая идея заключается в следующем. Для объектов типа «пользователь» мы получаем список идентификаторов пользователей-друзей и список идентификаторов групп, для сущности «группа» — список идентификаторов пользователей-участников. Далее из списков идентификаторов пользователей исключаем тех, чьи записи не должны включаться в «Ленту друзей». Аналогично обрабатываем список идентификаторов групп. Какие именно записи из блогов не должны включаться в ленты мы выяснили при разборе свойств объектов «пользователь» и «группа». На основе созданных списков пользователей и групп составляем списки идентификаторов блогов, извлекаем необходимые записи и передаем их в шаблон, для вывода на Web-странице, откуда был вызван компонент.
Для получения списка записей в блогах будем использовать функцию CBlogPost::GetList(). На первый взгляд, больше подходит функция CBlogUser::GetUserFriendsList(), которая специально предназначается для формирования списка сообщений друзей пользователя, но, к сожалению, она опирается на связи пользователей внутри модуля блогов, а не социальной сети, а это значит, что она нам не подходит. Функция же CBlogPost::GetList() возвращает список записей, соответствующих заданному фильтру, с возможностью сортировки и разбивки на страницы.
Включение в «Ленты» записей собственных блогов (для группы или пользователя) будем рассматривать как необязательное. Для ускорения обработки запросов и уменьшения нагрузки на сервер, информацию, которая не зависит от конкретного обратившегося посетителя, будем кэшировать. Итак, основные входящие параметры:
$arParams['USER_ID'] — ID пользователя для построения ленты;
$arParams['GROUP_ID'] — ID группы социальной сети для построения ленты;
$arParams['BLOG_GROUP_ID'] — ID группы блогов, к которой принадлежат все блоги социальной сети;
$arParams['INC_SELF_MESSAGES'] — включать ли в ленту сообщения из блога сущности;
Определение базовых прав пользователя, которые заодно будут использоваться как дополнительный идентификатор кэша, можно реализовать следующим образом.
//Определим права текущего пользователя (который в данный момент смотрит «Ленту друзей»)
$arResult = array();
//$arResult['ENTITY_TYPE'] - тип ленты, U - "лента пользователя", G - "лента группы"
$arResult['ENTITY_TYPE'] = $arParams['USER_ID'] > 0 ? 'U' : 'G';
//$arResult['ENTITY_ID'] - ID пользователя или группы (в зависимости от типа ленты)
$arResult['ENTITY_ID'] = $arResult['ENTITY_TYPE'] == 'U' ? $arParams['USER_ID'] : $arParams['GROUP_ID'];
$arResult['CURRENT_ACCSESS'] = array(
'canViewUserFriends' => false, //можно ли смотреть друзей пользователя
'canViewUserGroups' => false, //можно ли смотреть группы пользователя
'canViewUserSelfMessages' => false, //можно ли смотреть собственные записи блога пользователя
'canViewGroup' => false, //видима ли группа
'canViewGroupSelfMessages' => false //можно ли смотреть собственные записи блога группы
);