KnigaRead.com/

PC Magazine/RE - Журнал PC Magazine/RE №09/2009

На нашем сайте KnigaRead.com Вы можете абсолютно бесплатно читать книгу онлайн PC Magazine/RE, "Журнал PC Magazine/RE №09/2009" бесплатно, без регистрации.
Перейти на страницу:

Поиск других подходящих функций в модуле тоже не дал результата. Остается два пути. Первый – самостоятельно реализовать нужный нам метод. С точки зрения системного подхода, это более правильное решение, но... Здесь могут возникнуть проблемы обратной совместимости. Модуль довольно новый, мало ли что может измениться в недалеком будущем. Второй – получить необходимые данные, скомбинировав результаты нескольких стандартных методов, благо изучение исходных текстов модуля дает четкое представление, как это сделать. Вот и попробуем.

Общая идея выглядит так. Для объектов типа «пользователь» мы получаем списки идентификаторов пользователей-друзей и идентификаторов групп, для сущности «группа» – список идентификаторов пользователей-участников. Далее из списков идентификаторов пользователей исключаем тех, чьи записи не должны войти в «Ленту друзей». Аналогично обрабатываем список идентификаторов групп. Какие именно записи из блогов не должны включаться в ленты, мы выяснили при разборе свойств объектов «пользователь» и «группа». На основе созданных списков пользователей и групп составляем списки идентификаторов блогов, извлекаем необходимые записи и передаем их в шаблон для вывода на Web-странице, откуда был вызван компонент.

Для получения списка записей в блогах будем использовать функцию CBlogPost::GetList(). На первый взгляд, больше подходит функция CBlogUser::GetUserFriendsList(), которая специально предназначена для формирования списка сообщений друзей пользователя, но, к сожалению, она опирается на связи пользователей внутри модуля блогов, а не социальной сети, а это значит, что она нам не подходит. Функция же CBlogPost::GetList() возвращает список записей, соответствующих заданному фильтру, с возможностью сортировки и разбивки на страницы.

Включение в «Ленты» записей собственных блогов (для группы или пользователя) будем рассматривать как необязательное. Для ускорения обработки запросов и уменьшения нагрузки на сервер информацию, независящую от конкретного обратившегося посетителя, будем кэшировать. Итак, основные входящие параметры:

• $arParams['USER_ID'] – ID пользователя для построения ленты;

• $arParams['GROUP_ID'] – ID группы социальной сети для построения ленты;

• $arParams['BLOG_GROUP_ID'] – ID группы блогов, к которой принадлежат все блоги социальной сети;

• $arParams['INC_SELF_MESSAGES'] – включать ли в ленту сообщения из блога сущности.

Определение базовых прав пользователя, которые заодно будут использоваться как дополнительный идентификатор кэша (см. листинг 1). Обратим внимание на структуру $arResult['CURRENT_ACCESS']. В ней задаются права, доступные текущему пользователю по умолчанию. Далее получаем его идентификатор и определяем реальное состояние прав (листинг 2).

Листинг 1

// Определим права текущего пользователя (который в данный

// момент смотрит "Ленту друзей")

$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_ACCESS'] = array(

  'canViewUserFriends' => false,      //можно ли смотреть

                                      // друзей пользователя

  'canViewUserGroups' => false,       // можно ли смотреть

                                      // группы пользователя

  'canViewUserSelfMessages' => false, // можно ли смотреть

                                      // собственные записи

                                      // блога пользователя

  'canViewGroup' => false,            // видима ли группа

  'canViewGroupSelfMessages' => false // можно ли смотреть

                                      // собственные записи

                                      // блога группы

);

Листинг 2

$isModuleAdmin = CSocNetUser::IsCurrentUserModuleAdmin();

$currentUserID = $GLOBALS['USER']->GetID();

if($arResult['ENTITY_TYPE'] == 'G') {

  // для ленты групп проверим право на доступ к ней

  $arResult['GROUP_INFO'] = CSocNetGroup::GetByID($arResult['ENTITY_ID']);

  $arCurrentUserPerms = CSocNetUserToGroup::InitUserPerms($currentUserID, $arResult['GROUP_INFO'], $isModuleAdmin);

  $arResult['CURRENT_ACCESS']['canViewGroup'] = $arCurrentUserPerms['UserCanViewGroup'];

  unset($arCurrentUserPerms);

  if($arParams['INC_SELF_MESSAGES'] && $arResult['CURRENT_ACCESS']['canViewGroup']) {

    $arResult['CURRENT_ACCESS']['canViewGroupSelfMessages'] = CSocNetFeaturesPerms::CanPerformOperation($currentUserID,

      SONET_ENTITY_GROUP, $arResult['ENTITY_ID'], 'blog', 'view_post', $isModuleAdmin);

  }

} else {

  //для ленты пользователя проверим доступ к ней текущего пользователя

  $arCurrentUserPerms = CSocNetUserPerms::InitUserPerms($currentUserID, $arResult['ENTITY_ID'], $isModuleAdmin);

  $arResult['CURRENT_ACCESS']['canViewUserFriends'] = $arCurrentUserPerms['Operations']['viewfriends'];

  $arResult['CURRENT_ACCESS']['canViewUserGroups'] = $arCurrentUserPerms['Operations']['viewgroups'];

  if($arParams['INC_SELF_MESSAGES']) {

    // если не нужно включать в ленту сообщения из своего блога, то и проверять ID пользователя не будем

    // (экономим на количестве кэш-файлов)

    $arResult['CURRENT_ACCESS']['canViewUserSelfMessages'] = $currentUserID == $arResult['ENTITY_ID'];

  }

  unset($arCurrentUserPerms);

}

unset($currentUserID, $isModuleAdmin);

Значение $arResult['CURRENT_ACCESS'] и будет дополнительным идентификатором кэша:

if($this->StartResultCache(false, array($arNavigation,

  $arResult['CURRENT_ACCESS']), $cachePath)) {

  //код компонента

  //подключение шаблона сохранения результатов в кэш.

  $this->IncludeComponentTemplate();

}

где $arNavigation – массив управляющих параметров для постраничной навигации, $cachePath – путь для хранения кэш-файла. Определение идентификаторов друзей и групп для получения по ним ID блогов (исходный текст несколько сокращен для обозримости, листинг 3).

Листинг 3

// массив идентификаторов пользователей, из блогов которых

// будут выбираться записи

$arEntityUsersID = array();

// массив идентификаторов групп, из блогов которых будут

// выбираться записи

$arEntityGroupsID = array();

if($arResult['ENTITY_TYPE'] == 'U') {

  //лента пользователя

  //можно ли смотреть друзей для данного пользователя,

  // доступны ли вообще блоги и друзья

  $getFriends = false;

  if($arResult['CURRENT_ACCESS']['canViewUserFriends']) {

    $getFriends = CPTK_SocialNetwork::IsAllowedFeature

      (SONET_ENTITY_USER, 'blog') &&

      CSocNetUser::IsFriendsAllowed();

  }

  // можно ли смотреть группы для данного пользователя

  // и доступны ли вообще блоги для групп

  if($arResult['CURRENT_ACCESS']['canViewUserGroups']) {

    $getGroups = CPTK_SocialNetwork::IsAllowedFeature

      (SONET_ENTITY_GROUP, 'blog');

  }

Определим ID друзей пользователя (листинг 4).

Листинг 4

if($getFriends) {

  $arOrderUR = array();

  $arFilterUR = array(

    'RELATION' => SONET_RELATIONS_FRIEND,

    'USER_ID' => $arResult['ENTITY_ID'],

  );

  $arGroupByUR = false;

  $arNavigationUR = false;

  $arSelectFieldsUR = array(

    'FIRST_USER_ID',

    'SECOND_USER_ID'

  );

  $rsItems = CSocNetUserRelations::GetList($arOrderUR,

    $arFilterUR, $arGroupByUR, $arNavigationUR,

    $arSelectFieldsUR);

  while($arItem = $rsItems->Fetch())

  {

    $id_ = $arItem['FIRST_USER_ID'] ==

      $arResult['ENTITY_ID'] ?

      intval($arItem['SECOND_USER_ID']) :

      intval($arItem['FIRST_USER_ID']);

    $arEntityUsersID[$id_] = $id_;

  }

  unset($rsItems, $id_, $arOrderUR, $arGroupByUR,

  $arNavigationUR, $arSelectFieldsUR);

}

Код исключения «закрытых» пользователей вынесен в конец модуля (он общий для двух типов лент). Схема довольно проста: добавим ID владельца в массив $arEntityUsersID, если включен режим вывода сообщений из блога владельца ленты. Здесь же важно заполнить записью массив $arEntityUsersID на случай, если пользователь запретил смотреть своих друзей (листинг 5).

Листинг 5

if($arParams['INC_SELF_MESSAGES']) {

  $arEntityUsersID[$arResult['ENTITY_ID']] =

    $arResult['ENTITY_ID'];

}

// Определим ID видимых и НЕзакрытых групп пользователя

if($getGroups)

{

  $arOrderGR = array();

  $arFilterGR = array(

    'USER_ID' => $arResult['ENTITY_ID'],

    '<=ROLE' => SONET_ROLES_USER,

    'GROUP_SITE_ID' => SITE_ID,

    'GROUP_ACTIVE' => 'Y',

    'GROUP_VISIBLE' => 'Y'

  );

  $arGroupByGR = false;

  $arNavigationGR = false;

  $arSelectFieldsGR = array(

    'GROUP_ID',

    'GROUP_NAME'

  );

  $rsItems = CSocNetUserToGroup::GetList($arOrderGR,

    $arFilterGR, $arGroupByGR, $arNavigationGR,

    $arSelectFieldsGR);

  while($arItem = $rsItems->GetNext(false, false)) {

    $id_ = intval($arItem['GROUP_ID']);

    $arEntityGroupsID[$id_] = array(

      'ID' => $id_,

      'NAME' => $arItem['GROUP_NAME']

    );

  }

  unset($rsItems, $id_, $arOrderGR, $arGroupByGR,

    $arNavigationGR, $arSelectFieldsGR);

  if(!empty($arEntityGroupsID)) {

    //Определим группы, у которых блоги имеют статус

    // приватных, и исключим их из списка

    $arExceptGroupEntity = CPTK_SocialNetwork::

      GetByRoleFeaturesIdArray(SONET_ENTITY_GROUP, 'blog',

      'view_post', array('!ROLE' => SONET_ROLES_ALL),

      array('!ROLE' => SONET_ROLES_ALL));

    $arTmp = array_intersect_key($arExceptGroupEntity,

      $arEntityGroupsID);

    unset($arExceptGroupEntity);

    if(!empty($arTmp)) {

      foreach($arTmp as $key) {

        unset($arEntityGroupsID[$key]);

      }

    }

    unset($arTmp);

    //Определим группы, в которых вообще отключены блоги,

    // и исключим их из списка

    $arExceptGroupEntity = CPTK_SocialNetwork::

      GetByRoleFeaturesIdArray(SONET_ENTITY_GROUP, 'blog',

      'view_post', array('FEATURE_ACTIVE' => 'N'),

      array('FEATURE_ACTIVE' => 'N'));

    $arTmp = array_intersect_key($arExceptGroupEntity,

      $arEntityGroupsID);

    unset($arExceptGroupEntity);

    if(!empty($arTmp)) {

      foreach($arTmp as $key) {

        unset($arEntityGroupsID[$key]);

      }

    }

    unset($arTmp);

  }

}

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

Перейти на страницу:
Прокомментировать
Подтвердите что вы не робот:*