- Любовные романы
- Фантастика и фэнтези
- Ненаучная фантастика
- Ироническое фэнтези
- Научная Фантастика
- Фэнтези
- Ужасы и Мистика
- Боевая фантастика
- Альтернативная история
- Космическая фантастика
- Попаданцы
- Юмористическая фантастика
- Героическая фантастика
- Детективная фантастика
- Социально-психологическая
- Боевое фэнтези
- Русское фэнтези
- Киберпанк
- Романтическая фантастика
- Городская фантастика
- Технофэнтези
- Мистика
- Разная фантастика
- Иностранное фэнтези
- Историческое фэнтези
- LitRPG
- Эпическая фантастика
- Зарубежная фантастика
- Городское фентези
- Космоопера
- Разное фэнтези
- Книги магов
- Любовное фэнтези
- Постапокалипсис
- Бизнес
- Историческая фантастика
- Социально-философская фантастика
- Сказочная фантастика
- Стимпанк
- Романтическое фэнтези
- Ироническая фантастика
- Детективы и Триллеры
- Проза
- Юмор
- Феерия
- Новелла
- Русская классическая проза
- Современная проза
- Повести
- Контркультура
- Русская современная проза
- Историческая проза
- Проза
- Классическая проза
- Советская классическая проза
- О войне
- Зарубежная современная проза
- Рассказы
- Зарубежная классика
- Очерки
- Антисоветская литература
- Магический реализм
- Разное
- Сентиментальная проза
- Афоризмы
- Эссе
- Эпистолярная проза
- Семейный роман/Семейная сага
- Поэзия, Драматургия
- Приключения
- Детская литература
- Загадки
- Книга-игра
- Детская проза
- Детские приключения
- Сказка
- Прочая детская литература
- Детская фантастика
- Детские стихи
- Детская образовательная литература
- Детские остросюжетные
- Учебная литература
- Зарубежные детские книги
- Детский фольклор
- Буквари
- Книги для подростков
- Школьные учебники
- Внеклассное чтение
- Книги для дошкольников
- Детская познавательная и развивающая литература
- Детские детективы
- Домоводство, Дом и семья
- Юмор
- Документальные книги
- Бизнес
- Работа с клиентами
- Тайм-менеджмент
- Кадровый менеджмент
- Экономика
- Менеджмент и кадры
- Управление, подбор персонала
- О бизнесе популярно
- Интернет-бизнес
- Личные финансы
- Делопроизводство, офис
- Маркетинг, PR, реклама
- Поиск работы
- Бизнес
- Банковское дело
- Малый бизнес
- Ценные бумаги и инвестиции
- Краткое содержание
- Бухучет и аудит
- Ораторское искусство / риторика
- Корпоративная культура, бизнес
- Финансы
- Государственное и муниципальное управление
- Менеджмент
- Зарубежная деловая литература
- Продажи
- Переговоры
- Личная эффективность
- Торговля
- Научные и научно-популярные книги
- Биофизика
- География
- Экология
- Биохимия
- Рефераты
- Культурология
- Техническая литература
- История
- Психология
- Медицина
- Прочая научная литература
- Юриспруденция
- Биология
- Политика
- Литературоведение
- Религиоведение
- Научпоп
- Психология, личное
- Математика
- Психотерапия
- Социология
- Воспитание детей, педагогика
- Языкознание
- Беременность, ожидание детей
- Транспорт, военная техника
- Детская психология
- Науки: разное
- Педагогика
- Зарубежная психология
- Иностранные языки
- Филология
- Радиотехника
- Деловая литература
- Физика
- Альтернативная медицина
- Химия
- Государство и право
- Обществознание
- Образовательная литература
- Учебники
- Зоология
- Архитектура
- Науки о космосе
- Ботаника
- Астрология
- Ветеринария
- История Европы
- География
- Зарубежная публицистика
- О животных
- Шпаргалки
- Разная литература
- Зарубежная литература о культуре и искусстве
- Пословицы, поговорки
- Боевые искусства
- Прочее
- Периодические издания
- Фанфик
- Военное
- Цитаты из афоризмов
- Гиды, путеводители
- Литература 19 века
- Зарубежная образовательная литература
- Военная история
- Кино
- Современная литература
- Военная техника, оружие
- Культура и искусство
- Музыка, музыканты
- Газеты и журналы
- Современная зарубежная литература
- Визуальные искусства
- Отраслевые издания
- Шахматы
- Недвижимость
- Великолепные истории
- Музыка, танцы
- Авто и ПДД
- Изобразительное искусство, фотография
- Истории из жизни
- Готические новеллы
- Начинающие авторы
- Спецслужбы
- Подростковая литература
- Зарубежная прикладная литература
- Религия и духовность
- Старинная литература
- Справочная литература
- Компьютеры и Интернет
- Блог
Журнал PC Magazine/RE №09/2009 - PC Magazine/RE
Шрифт:
Интервал:
Закладка:
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).
Листинг 7if(!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).
Листинг 9if(!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-кодом, и лента сообщений «как в ЖЖ» готова.
Архитектура «Ленты друзей»: проблемы и решенияЛегко заметить, что данный компонент не столь совершенен, каким мог бы быть. Скажем, напрашивается вопрос: а нельзя ли в «Ленте друзей» учитывать структуру связей пользователя с группами и другими пользователями социальной сети? Теоретически можно, на практике нагрузка на сервер возрастет в разы (если не на порядки), причем кэшировать что-либо будет невозможно. Причина – необходимость учитывать огромное количество комбинаций настроек, слишком много факторов будут определять итоговый результат.
Посмотрим, как будет влиять на содержимое «Ленты друзей» сложная конфигурация прав доступа. Предположим, что в профиле пользователя имеются настройки:
• «просматривать список друзей могут только друзья» – это означает, что прежде чем включать записи, опубликованные друзьями владельца ленты в блогах социальной сети, нужно выяснить, не является ли «текущий пользователь» («текущий пользователь» – пользователь, который в данный момент смотрит ленту) другом владельца ленты;
• «просматривать список друзей могут только друзья и друзья друзей» – прежде чем включать записи, опубликованные друзьями владельца ленты, нам нужно выяснить, не является ли текущий пользователь другом или другом друга владельца ленты;

