/** * @uses Get info on every Blog Channel * * @param int Page number * @param int Per page * @param int The userid of the owner or author of the blog channels to fetch. If 0, blog channels for all users are fetched. * * @return mixed array containing the blog channel info we need */ public function getBlogInfo($from = 1, $perpage = 20, $authorid = 0) { $response = array(); $nodeApi = vB_Api::instanceInternal('node'); $blogParentChannel = $this->getBlogChannel(); $channelContentType = vB_Types::instance()->getContentTypeId('vBForum_Channel'); //Get base data $options = array('channel' => $blogParentChannel, 'depth' => 1, 'type' => 'vBForum_Channel', 'nolimit' => 1); if (intval($authorid) > 0) { $options['authorid'] = $authorid; } $nodeContent = vB_Api::instanceInternal('search')->getInitialResults($options, $perpage, $from); //We need the nodeids to collect some data $lastids = array(); $channelids = array(); $pageKeyInfo = array(); $remaining_channelids = array(); foreach ($nodeContent['results'] as $key => $node) { if ($node['lastcontentid'] > 0) { $lastids[] = $node['lastcontentid']; } $channelids[] = $node['nodeid']; $remaining_channelids[] = $node['nodeid']; } if (empty($channelids)) { return array(); } $lastNodes = vB_Api::instanceInternal('node')->getNodes($lastids); //Get contributors $contributorQry = vB::getDbAssertor()->assertQuery('vBForum:groupintopic', array(vB_dB_Query::TYPE_KEY => vB_dB_Query::QUERY_SELECT, 'nodeid' => $channelids, 'groupid' => vB_Api::instanceInternal('usergroup')->getModeratorGroupId())); $userApi = vB_Api::instanceInternal('user'); $contributors = array(); $contributorsAvatarToFetch = array(); $contributorsInfo = array(); foreach ($contributorQry as $contributor) { if (!isset($contributors[$contributor['nodeid']])) { $contributors[$contributor['nodeid']] = array(); } $userInfo = $userApi->fetchUserinfo($contributor['userid'], array(vB_Api_User::USERINFO_AVATAR)); $contributorsAvatarToFetch[] = $userInfo['userid']; $contributorsInfo[$userInfo['userid']] = $userInfo; $contributors[$contributor['nodeid']][$contributor['userid']] = $userInfo; } // Fetching and setting avatar url for contributors $avatarsurl = $userApi->fetchAvatars($contributorsAvatarToFetch, true, $contributorsInfo); foreach ($contributors as $nodeid => $nodeContributors) { foreach ($nodeContributors as $contributorid => $contributor) { if (isset($avatarsurl[$contributorid])) { $contributors[$nodeid][$contributorid]['avatar'] = $avatarsurl[$contributorid]; } } } if (!empty($remaining_channelids)) { $routes = vB::getDbAssertor()->assertQuery('routenew', array('class' => 'vB5_Route_Channel', 'contentid' => $remaining_channelids)); foreach ($routes as $record) { $route = vB5_Route_Channel::getRoute($record['routeid'], @unserialize($record['arguments'])); if ($route and $pageKey = $route->getPageKey()) { $pageKeyInfo[$pageKey] = $record['contentid']; } } } // ... now obtain visits $viewingQry = vB::getDbAssertor()->getRows('session', array(vB_dB_Query::TYPE_KEY => vB_dB_Query::QUERY_SELECT, 'pagekey' => array_keys($pageKeyInfo))); $viewing = array(); foreach ($viewingQry as $viewingUser) { $nodeId = $pageKeyInfo[$viewingUser['pagekey']]; if (!isset($viewing[$nodeId])) { $viewing[$nodeId] = 0; } $viewing[$nodeId]++; } foreach ($nodeContent['results'] as $index => $channel) { $nodeid = $channel['nodeid']; $nodeContent['results'][$index]['contributors'] = $contributors[$nodeid] ? $contributors[$nodeid] : 0; $nodeContent['results'][$index]['viewing'] = $viewing[$nodeid] ? $viewing[$nodeid] : 0; if (!empty($lastNodes[$channel['lastcontentid']])) { $nodeContent['results'][$index]['lastposttitle'] = $lastNodes[$channel['lastcontentid']]['title']; $nodeContent['results'][$index]['lastpost'] = $lastNodes[$channel['lastcontentid']]; } } return $nodeContent; }
/** gets Get info on every SG Channel * * @param array Array of options to filter the info (used to show all/my groups). * @param array Array of route info of the social group parent channel to be used for building pagination URLs. * @return mixed Array containing the social group channel info we need. */ public function getSGInfo($options = array(), $routeInfo = array()) { $response = array(); $nodeApi = vB_Api::instanceInternal('node'); $sgParentChannel = $this->getSGChannel(); if (!empty($options['sgparent']) and intval($options['sgparent']) and intval($options['sgparent'] != $sgParentChannel)) { $sgParent = intval($options['sgparent']); $depth = 1; } else { $sgParent = $sgParentChannel; $depth = 2; } // category check if (!$this->isSGNode($sgParent)) { throw new vB_Exception_Api('invalid_sg_parent'); } //Get base data $channelContentType = vB_Types::instance()->getContentTypeId('vBForum_Channel'); $params = array('starter_only' => 1, 'view' => 'activity', 'depth_exact' => 1, 'nolimit' => 1); $queryParams = array('sgParentChannel' => $sgParent, 'depth' => $depth); if (!empty($options['userid'])) { $queryParams['userid'] = $params['userid'] = intval($options['userid']); } $page = (!empty($options['page']) and intval($options['page'])) ? intval($options['page']) : 1; $perpage = (!empty($options['perpage']) and intval($options['perpage'])) ? intval($options['perpage']) : 20; $cacheParams = array_merge($params, array('page' => $page, 'perpage' => $perpage, 'sgparent' => $sgParent, 'depth' => $depth)); $cacheKey = 'sgResults_' . (vB::getUserContext()->fetchUserId() ? vB::getUserContext()->fetchUserId() : 0) . crc32(serialize($cacheParams)); if ($result = vB_Cache::instance(vB_Cache::CACHE_FAST)->read($cacheKey) or !vB::getUserContext()->hasPermission('socialgrouppermissions', 'canviewgroups')) { //we don't cache the pagination URLs as they may vary for the same content depending on the specified routeInfo (routeId, arguments, queryParameters) $pageInfo = $result['pageInfo']; $paginationURLs = $this->buildPaginationURLs($pageInfo['currentpage'], $pageInfo['totalpages'], $routeInfo); if ($paginationURLs) { $pageInfo = array_merge($pageInfo, $paginationURLs); $result['pageInfo'] = $pageInfo; } return $result; } $nodeContent = $nodeApi->listNodeContent($sgParent, $page, $perpage, $depth, $channelContentType, $params); $totalCount = vB::getDbAssertor()->getRow('vBForum:getSocialGroupsTotalCount', $queryParams); //We need the nodeids to collect some data $cacheEvents = array('nodeChg_' . $sgParent); $lastids = array(); $lastNodes = array(); $channelids = array(); $categories = array(); $contributorIds = array(); $sgCategories = array_keys($this->getCategories()); $sgParentChannel = $this->getSGChannel(); foreach ($nodeContent as $key => $node) { if ($node['parentid'] == $sgParentChannel) { $categories[] = $node['nodeid']; unset($nodeContent[$node['nodeid']]); } else { if ($node['lastcontentid'] > 0) { $lastids[] = $node['lastcontentid']; } if (in_array($node['parentid'], $sgCategories)) { $categories[] = $node['parentid']; } $channelids[] = $node['nodeid']; $contributorIds[] = $node['userid']; $cacheEvents[] = 'nodeChg_' . $node['nodeid']; } } $categories = array_unique($categories); if (empty($channelids)) { //for display purposes, we set totalpages to 1 even if there are no records because we don't want the UI to display Page 1 of 0 $result = array('results' => array(), 'totalcount' => 0, 'pageInfo' => array('currentpage' => $page, 'perpage' => $perpage, 'nexturl' => '', 'prevurl' => '', 'totalpages' => 1, 'totalrecords' => 0, 'sgparent' => $sgParent)); vB_Cache::instance(vB_Cache::CACHE_FAST)->write($cacheKey, $result, 60, array_unique($cacheEvents)); return $result; } $mergedNodes = vB_Library::instance('node')->getNodes($lastids + $categories); foreach ($lastids as $lastid) { if (empty($mergedNodes[$lastid])) { continue; } $lastNodes[$lastid] = $mergedNodes[$lastid]; } foreach ($categories as $category) { if (empty($mergedNodes[$category])) { continue; } $categoriesInfo[$category] = $mergedNodes[$category]; } // update category info foreach ($nodeContent as $key => $node) { // add category info if (isset($categoriesInfo[$node['parentid']])) { $nodeContent[$key]['content']['channeltitle'] = $categoriesInfo[$node['parentid']]['title']; $nodeContent[$key]['content']['channelroute'] = $categoriesInfo[$node['parentid']]['routeid']; $cacheEvents[] = 'nodeChg_' . $node['parentid']; } } $lastTitles = $lastInfo = array(); $lastIds = array(); foreach ($lastNodes as $lastnode) { $lastInfo[$lastnode['nodeid']]['starter'] = $lastnode['starter']; if ($lastnode['starter'] == $lastnode['nodeid']) { $lastInfo[$lastnode['nodeid']]['title'] = $lastnode['title']; $lastInfo[$lastnode['nodeid']]['routeid'] = $lastnode['routeid']; $contributorIds[] = $lastnode['userid']; } else { //We need another query $lastIds[$lastnode['starter']] = $lastnode['starter']; } } //Now get any lastcontent starter information we need if (!empty($lastIds)) { $nodes = vB_Library::instance('node')->getNodes($lastIds); foreach ($nodeContent as $index => $channel) { $nodeid = $lastInfo[$channel['lastcontentid']]['starter']; if (isset($nodes[$nodeid])) { $node =& $nodes[$nodeid]; $lastInfo[$channel['lastcontentid']]['routeid'] = $node['routeid']; $lastInfo[$channel['lastcontentid']]['title'] = $node['title']; } } } if (!empty($options['contributors'])) { //Get contributors $groups = vB::getDbAssertor()->getColumn('vBForum:usergroup', 'usergroupid', array('systemgroupid' => array(vB_Api_UserGroup::CHANNEL_MODERATOR_SYSGROUPID, vB_Api_UserGroup::CHANNEL_MEMBER_SYSGROUPID, vB_Api_UserGroup::CHANNEL_OWNER_SYSGROUPID)), false, 'systemgroupid'); $membersQry = vB::getDbAssertor()->assertQuery('vBForum:groupintopic', array(vB_dB_Query::TYPE_KEY => vB_dB_Query::QUERY_SELECT, 'nodeid' => $channelids, 'groupid' => $groups)); $groupManagers = array(); $contributors = array(); foreach ($membersQry as $record) { if ($record['groupid'] == $groups[vB_Api_UserGroup::CHANNEL_MODERATOR_SYSGROUPID]) { $groupManagers[] = $record; } $contributorIds[$record['userid']] = $record['userid']; $cacheEvents[] = 'sgMemberChg_' . $record['userid']; } $userApi = vB_Api::instanceInternal('user'); $avatarInfo = vB_Api::instanceInternal('user')->fetchAvatars($contributorIds); foreach ($groupManagers as $index => $contributor) { if (!isset($contributors[$contributor['nodeid']])) { $contributors[$contributor['nodeid']] = array(); } $userInfo = $userApi->fetchUserinfo($contributor['userid']); $contributors[$contributor['nodeid']][$contributor['userid']] = $userInfo; $contributors[$contributor['nodeid']][$contributor['userid']]['avatar'] = $avatarInfo[$contributor['userid']]; } } // Obtain keys for sg pages $pageKeyInfo = array(); $routes = vB::getDbAssertor()->getRows('routenew', array('class' => 'vB5_Route_Channel', 'contentid' => $channelids), false, 'routeid'); vB5_Route::preloadRoutes(array_keys($routes)); foreach ($routes as $record) { $route = vB5_Route_Channel::getRoute($record['routeid'], @unserialize($record['arguments'])); if ($route and $pageKey = $route->getPageKey()) { $pageKeyInfo[$pageKey] = $record['contentid']; } } $viewingQry = vB::getDbAssertor()->getRows('session', array(vB_dB_Query::TYPE_KEY => vB_dB_Query::QUERY_SELECT, 'pagekey' => array_keys($pageKeyInfo))); $viewing = array(); foreach ($viewingQry as $viewingUser) { if (!isset($viewing[$viewingUser['nodeid']])) { $viewing[$viewingUser['nodeid']] = 0; } $viewing[$viewingUser['nodeid']]++; } // get the members count $countRecords = vB::getDbAssertor()->assertQuery('vBForum:getChannelMembersCount', array('nodeid' => $channelids, 'groupid' => $groups)); $membersCount = array(); foreach ($countRecords as $count) { $membersCount[$count['nodeid']] = $count; } foreach ($nodeContent as $index => $channel) { $nodeid = $channel['nodeid']; if (!empty($options['contributors'])) { $nodeContent[$index]['contributors'] = !empty($contributors[$nodeid]) ? $contributors[$nodeid] : 0; $nodeContent[$index]['contributorscount'] = !empty($contributors[$nodeid]) ? count($contributors[$nodeid]) : 0; } $nodeContent[$index]['members'] = !empty($membersCount[$nodeid]) ? $membersCount[$nodeid]['members'] : 0; $nodeContent[$index]['viewing'] = !empty($viewing[$nodeid]) ? $viewing[$nodeid] : 0; $nodeContent[$index]['lastposttitle'] = !empty($lastInfo[$channel['lastcontentid']]['title']) ? $lastInfo[$channel['lastcontentid']]['title'] : 0; $nodeContent[$index]['lastpostrouteid'] = !empty($lastInfo[$channel['lastcontentid']]['routeid']) ? $lastInfo[$channel['lastcontentid']]['routeid'] : 0; $nodeContent[$index]['owner_avatar'] = $avatarInfo[$nodeContent[$index]['userid']]; $nodeContent[$index]['lastauthor_avatar'] = $avatarInfo[$nodeContent[$index]['lastauthorid']]; } $total = $totalCount['totalcount']; if ($total > 0) { $pages = ceil($total / $perpage); } else { $pages = 1; //we don't want the UI to display Page 1 of 0 } $pageInfo = array('currentpage' => $page, 'perpage' => $perpage, 'prevurl' => '', 'nexturl' => '', 'totalpages' => $pages, 'totalrecords' => $total, 'sgparent' => $sgParent); $result = array('results' => $nodeContent, 'totalcount' => count($nodeContent), 'pageInfo' => $pageInfo); vB_Cache::instance(vB_Cache::CACHE_FAST)->write($cacheKey, $result, 60, array_unique($cacheEvents)); //we don't cache the pagination URLs as they may vary for the same content depending on the specified routeInfo (routeId, arguments, queryParameters) $paginationURLs = $this->buildPaginationURLs($page, $pages, $routeInfo); if ($paginationURLs) { $pageInfo = array_merge($pageInfo, $paginationURLs); $result['pageInfo'] = $pageInfo; } return $result; }
public function add($data, array $options = array('nodeonly' => false)) { $options += array('skipDupCheck' => true); //Store this so we know whether we should call afterAdd() $skipTransaction = !empty($options['skipTransaction']); // VBV-833: we allow interfaces to not specify a parent. Main channel should be used in that case if (!isset($data['parentid']) or $data['parentid'] <= 0) { $data['parentid'] = vB::getDbAssertor()->getField('vBForum:channel', array(vB_dB_Query::TYPE_KEY => vB_dB_Query::QUERY_SELECT, vB_dB_Query::CONDITIONS_KEY => array('guid' => vB_Channel::DEFAULT_CHANNEL_PARENT))); } else { // if we are not using the default channel parent, we need to check for pagetemplates if (!isset($data['templates'])) { $parent = vB::getDbAssertor()->getRow('vBForum:channel', array(vB_dB_Query::COLUMNS_KEY => array('nodeid', 'guid'), vB_dB_Query::CONDITIONS_KEY => array('nodeid' => $data['parentid']))); switch ($parent['guid']) { case vB_Channel::DEFAULT_SOCIALGROUP_PARENT: // This is done only when saving from activity stream configuration, once it is removed we can get rid of this $data['templates']['vB5_Route_Channel'] = vB_Page::getSGCategoryPageTemplate(); $data['templates']['vB5_Route_Conversation'] = vB_Page::getSGCategoryConversPageTemplate(); $data['category'] = 1; break; case vB_Channel::DEFAULT_ARTICLE_PARENT: // articles $data['templates']['vB5_Route_Channel'] = vB_Page::getArticleChannelPageTemplate(); $data['templates']['vB5_Route_Conversation'] = vB_Page::getArticleConversPageTemplate(); break; default: // use inherited from parent channel break; } } } if (!isset($data['guid'])) { // creating guid $data['guid'] = vB_Xml_Export_Channel::createGUID($data); } // parse options array if (isset($data['options'])) { if (is_array($data['options'])) { $value = $this->buildChannelOptions(0, $data['options']); if ($value !== FALSE) { $data['options'] = $value; } else { // do not update field unset($data['options']); } } else { // should we accept raw ints as updates? unset($data['options']); } } if (empty($data['urlident']) and !empty($data['title'])) { $data['urlident'] = $this->getUniqueUrlIdent($data['title']); } if (!isset($options['nodeonly']) || !$options['nodeonly']) { // if we are going to create pages, verify that prefix/regex generated is valid BEFORE creating the node vB5_Route_Channel::validatePrefix($data); } try { if (!$skipTransaction) { $this->assertor->beginTransaction(); } $options['skipTransaction'] = true; $result = parent::add($data, $options); if (!isset($options['nodeonly']) || !$options['nodeonly']) { $this->nodeLibrary->clearCacheEvents($result['nodeid']); $this->createChannelPages($result['nodeid'], $data); } if (!$skipTransaction) { $this->assertor->commitTransaction(); } } catch (exception $e) { if (!$skipTransaction) { $this->assertor->rollbackTransaction(); } throw $e; } //and announce that the cached channel structure has changed. $result['cacheEvents'][] = 'vB_ChannelStructure_chg'; if (isset($data['filedataid']) and vB::getUserContext()->getChannelPermission('forumpermissions', 'canuploadchannelicon', $result['nodeid'])) { $this->qryAfterAdd[] = array('definition' => 'incrementFiledataRefcountAndMakePublic', 'data' => array('filedataid' => $data['filedataid'])); } if (!$skipTransaction) { //The child classes that have their own transactions all set this to true so afterAdd is always called just once. $this->afterAdd($result['nodeid'], $data, $options, $result['cacheEvents'], $result['nodeVals']); } if (!defined('VB_AREA') or !in_array(VB_AREA, array('Install', 'Upgrade'))) { vB::getUserContext()->rebuildGroupAccess(); vB::getUserContext()->reloadUserPerms(); vB_Channel::rebuildChannelTypes(); } return $result; }