Рейтинговые книги
Читем онлайн Журнал PC Magazine/RE №09/2009 - PC Magazine/RE

Шрифт:

-
+

Интервал:

-
+

Закладка:

Сделать
1 ... 21 22 23 24 25 26 27 28 29 ... 35

    if(!empty($arTmp)) {

      foreach($arTmp as $key) {

        unset($arEntityGroupsID[$key]);

      }

    }

    unset($arTmp);

  }

}

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

Листинг 6

$getMembers = false;

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

  $getMembers = CPTK_SocialNetwork::IsAllowedFeature

    (SONET_ENTITY_USER, 'blog');

}

// Определим ID участников группы

if($getMembers) {

  $arOrderGM = array();

  $arFilterGM = array(

    '<=ROLE' => SONET_ROLES_USER,

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

  );

  $arGroupByGM = false;

  $arNavigationGM = false;

  $arSelectFieldsGM = array(

    'USER_ID'

  );

  $rsItems = CSocNetUserToGroup::GetList($arOrderGM,

    $arFilterGM, $arGroupByGM, $arNavigationGM,

    $arSelectFieldsGM);

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

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

    $arEntityUsersID[$id_] = $id_;

  }

  unset($rsItems, $id_, $arOrderGM, $arGroupByGM,

    $arNavigationGM, $arSelectFieldsGM);

  // код исключения "закрытых" пользователей вынесен в конец

  // модуля (он общий для двух типов лент)

}

// Добавим ID группы в $arEntityGroupsID, если включен вывод

// сообщений из блога группы

if($arParams['INC_SELF_MESSAGES'] &&

    $arResult['CURRENT_ACCESS']['canViewGroup'] &&

    $arResult['CURRENT_ACCESS']['canViewGroupSelfMessages']) {

  //если блоги в группе не отключены

  if(CSocNetFeatures::IsActiveFeature(SONET_ENTITY_GROUP,

      $arResult['ENTITY_ID'], 'blog')) {

    $arEntityGroupsID[$arResult['ENTITY_ID']] = array(

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

      'NAME' => $arResult['GROUP_INFO']['NAME']

    );

  }

}

Чуть выше мы отметили, что код исключения «закрытых» пользователей вынесен в конец компонента. Теперь пришло время определить пользователей, которые запретили просмотр блогов. Уберем их из списка (раз уж они сами этого хотят; листинг 7).

Листинг 7

if(!empty($arEntityUsersID)) {

  $arExceptUserEntity = CPTK_SocialNetwork::

    GetByRoleFeaturesIdArray(SONET_ENTITY_USER, 'blog',

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

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

  $arTmp = array_intersect_key($arExceptUserEntity,

    $arEntityUsersID);

  unset($arExceptUserEntity);

  if(!empty($arTmp)) {

    foreach($arTmp as $key)

    {

      unset($arEntityUsersID[$key]);

    }

  }

  unset($arTmp);

  // Если активный пользователь – владелец ленты, повторно

  // включим его ID, даже если он закрыл свой блог – ему

  // заведомо можно просматривать свои записи

  if($arParams['INC_SELF_MESSAGES'] && $arResult

      ['CURRENT_ACCESS']['canViewUserSelfMessages']) {

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

      $arResult['ENTITY_ID'];

  }

  // Определим пользователей, которые вообще отключили свои

  // блоги, и исключим их из списка

  $arExceptUserEntity = CPTK_SocialNetwork::

    GetByRoleFeaturesIdArray(SONET_ENTITY_USER, 'blog',

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

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

  $arTmp = array_intersect_key($arExceptUserEntity,

    $arEntityUsersID);

  unset($arExceptUserEntity);

  if(!empty($arTmp)) {

    foreach($arTmp as $key) {

      unset($arEntityUsersID[$key]);

    }

  }

  unset($arTmp);

}

Здесь надо обратить внимание на две дополнительные функции, которые не входят в стандартный API ядра «1С-Битрикс: Управление сайтом»: CPTK_SocialNetwork::

GetByRoleFeaturesIdArray() и CPTK_SocialNetwork::IsAllowedFeature(). Они представляют собой часть библиотеки автора, их текст здесь не приводится (при желании библиотеку можно запросить у автора статьи). Первая, CPTK_SocialNetwork::GetByRoleFeaturesIdArray(), возвращает массив идентификаторов объектов по типу объекта, сигнатуре, функциональности и операциям (с возможностью установки дополнительного фильтра). Функция имеет внутреннее кэширование результатов, в ее основе лежит метод CSocNetFeaturesPerms::GetList(). Вторая, CPTK_SocialNetwork::IsAllowedFeature(), проверяет, доступна ли для заданного объекта затребованная возможность (это небольшая оптимизация часто выполняемой операции, опытному разработчику не составит труда реализовать ее самостоятельно).

На этом этапе возникает проблема: при организации группы социальной сети система не создает соответствующие записи в таблицах БД, где хранятся настройки прав доступа к заданным функциям. Эти записи автоматически создаются только после первого изменения прав доступа, до того они определяются системой, средствами PHP. Причем по умолчанию используется режим не «разрешено всем», а «разрешено только участникам». Следовательно, попытка выбрать все записи, у которых в поле ROLE не установлено значение константы SONET_RELATIONS_TYPE_ALL («разрешено всем»; в нашем случае это и будет вызов CPTK_SocialNetwork::GetByRoleFeaturesIdArray() с установленным дополнительным фильтром array('!ROLE' => SONET_RELATIONS_TYPE_ALL), приведет к получению неверного результата. Этот нюанс можно считать досадной ошибкой в архитектуре модуля, но, к счастью, дело поправимо без вмешательства в ядро системы. В нашем случае оказалось достаточно добавить обработчик события OnSocNetGroupAdd, где и выполняются необходимые для корректной записи в БД структуры прав операции. В группах, которые были созданы ранее, эта ошибка была исправлена с помощью «Мастера».

Двигаемся дальше – получаем массив блогов, из которых будут выбираться новые записи (листинг 8).

Листинг 8

$arBlogID = array(); // массив блогов

if(!empty($arEntityUsersID)) { // по владельцу блога

  $arOrderBlog = array();

  $arFilterBlog = array(

    'OWNER_ID' => array_keys($arEntityUsersID),

    'GROUP_ID' => $arParams['BLOG_GROUP_ID'],

    'GROUP_SITE_ID' => SITE_ID,

    'ACTIVE' => 'Y'

  );

  unset($arEntityUsersID);

  $arGroupByBlog = false; $arNavigationBlog = false;

  $arSelectFieldsBlog = array('ID', 'SONET_GROUP_ID');

  $rsItems = CBlog::GetList($arOrderBlog, $arFilterBlog,

    $arGroupByBlog, $arNavigationBlog, $arSelectFieldsBlog);

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

    if(intval($arItem['SONET_GROUP_ID']) <= 0) {

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

      $arBlogID[$id_] = $id_;

    }

  }

  unset($rsItems, $id_, $arOrderBlog, $arGroupByBlog,

    $arNavigationBlog, $arSelectFieldsBlog);

}

if(!empty($arEntityGroupsID)) { // по группе блога в соцсети

  $arOrderBlog = array();

  $arFilterBlog = array(

    'SOCNET_GROUP_ID' => array_keys($arEntityGroupsID),

    'GROUP_ID' => $arParams['BLOG_GROUP_ID'],

    'GROUP_SITE_ID' => SITE_ID,

    'ACTIVE' => 'Y'

  );

  $arGroupByBlog = false; $arNavigationBlog = false;

  $arSelectFieldsBlog = array('ID', 'OWNER_ID');

  $rsItems = CBlog::GetList($arOrderBlog, $arFilterBlog,

    $arGroupByBlog, $arNavigationBlog, $arSelectFieldsBlog);

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

    if(intval($arItem['OWNER_ID']) <= 0) {

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

      $arBlogID[$id_] = $id_;

    }

  }

  unset($rsItems, $id_, $arOrderBlog, $arGroupByBlog,

    $arNavigationBlog, $arSelectFieldsBlog);

}

Здесь все вполне прозрачно, комментарии не требуются. И наконец, выбираем записи из блогов, которые и станут основой для формирования конечного результата – «Ленты друзей» (листинг 9).

Листинг 9

if(!empty($arBlogID)) {

  $arFilter = array(

    'BLOG_ACTIVE' => 'Y',

    'BLOG_GROUP_SITE_ID' => SITE_ID,

    'PUBLISH_STATUS' => BLOG_PUBLISH_STATUS_PUBLISH,

    'BLOG_ID' => array_keys($arBlogID),

    'ACTIVE' => 'Y'

  );

  unset($arBlogID);

  if($arParams['MAX_DAYS_COUNT'] > 0) {

    // задан промежуток времени для выборки сообщений 86400 —

    // кэшируем на сутки

    $from = intval(time() – $arParams['MAX_DAYS_COUNT']*86400);

    $arFilter['>=DATE_PUBLISH'] = ConvertTimeStamp($from,

      'FULL');

  }

  $arGroupBy = false;

  $arSelectFields = array(

    'ID',

    'BLOG_ID',

    'TITLE',

    'DATE_PUBLISH',

    'AUTHOR_ID',

    'DETAIL_TEXT',

    'BLOG_ACTIVE',

    'BLOG_URL',

    'BLOG_GROUP_ID',

    'BLOG_GROUP_SITE_ID',

    'AUTHOR_LOGIN',

    'AUTHOR_NAME',

    'AUTHOR_LAST_NAME',

    'BLOG_USER_ALIAS',

    'BLOG_OWNER_ID',

    'BLOG_USER_AVATAR',

    'NUM_COMMENTS',

    'VIEWS',

    'ATTACH_IMG',

    'BLOG_SOCNET_GROUP_ID'

  );

  $rsItems = CBlogPost::GetList($arOrder, $arFilter,

    $arGroupBy, $arNavParams, $arSelectFields);

  $rsItems->bShowAll = $arParams['PAGER_SHOW_ALL'];

  //создаем объект парсера сообщений блогов

  $obParser = new blogTextParser(false,

    $arParams['PATH_TO_SMILE']);

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

    // здесь код разбора записи блога – ссылки, аватары,

    // картинки, выполняем парсинг текста сообщения и т. д.

  }

  unset($obParser, $arOrder, $arGroupBy, $arSelectFields);

  unset($arEntityGroupsID);

}

На этом содержательная часть работы заканчивается. Далее подключаем шаблон для оформления полученных данных HTML-кодом, и лента сообщений «как в ЖЖ» готова.

Архитектура «Ленты друзей»: проблемы и решения

Легко заметить, что данный компонент не столь совершенен, каким мог бы быть. Скажем, напрашивается вопрос: а нельзя ли в «Ленте друзей» учитывать структуру связей пользователя с группами и другими пользователями социальной сети? Теоретически можно, на практике нагрузка на сервер возрастет в разы (если не на порядки), причем кэшировать что-либо будет невозможно. Причина – необходимость учитывать огромное количество комбинаций настроек, слишком много факторов будут определять итоговый результат.

Посмотрим, как будет влиять на содержимое «Ленты друзей» сложная конфигурация прав доступа. Предположим, что в профиле пользователя имеются настройки:

• «просматривать список друзей могут только друзья» – это означает, что прежде чем включать записи, опубликованные друзьями владельца ленты в блогах социальной сети, нужно выяснить, не является ли «текущий пользователь» («текущий пользователь» – пользователь, который в данный момент смотрит ленту) другом владельца ленты;

• «просматривать список друзей могут только друзья и друзья друзей» – прежде чем включать записи, опубликованные друзьями владельца ленты, нам нужно выяснить, не является ли текущий пользователь другом или другом друга владельца ленты;

1 ... 21 22 23 24 25 26 27 28 29 ... 35
На этой странице вы можете бесплатно читать книгу Журнал PC Magazine/RE №09/2009 - PC Magazine/RE бесплатно.
Похожие на Журнал PC Magazine/RE №09/2009 - PC Magazine/RE книги

Оставить комментарий