Example #1
0
 /**
  * Merges "posted" info into the topics array, used by the display_Topics template.
  * This adds the "content.posted" element to the node record. The value is the number of
  * times the current user has posted in the topic (replies and comments); zero if none.
  *
  * @param  array  Nodes
  *
  * @return array  Same array of nodes, with the "posted" element added to the "content" sub-array
  */
 public function mergePostedStatusForTopics($nodes)
 {
     $user = vB::getCurrentSession()->fetch_userinfo();
     $userid = $user['userid'];
     return $this->library->mergePostedStatusForTopics($nodes, $userid);
 }
Example #2
0
 /**
  * 	Takes an array of node information and adds contentInfo
  *	@param	integer	The node id of the parent where we are listing
  *	@param	integer	page number to return
  *	@param	integer	items per page
  *	@param	integer	depth- 0 means no stopping, otherwise 1= direct child, 2= grandchild, etc
  *	@param	mixed	if desired, will only return specific content types.
  *	@param	mixed	'sort', or 'exclude' recognized.
  *
  * 	@return	mixed	array of id's
  ***/
 public function addFullContentInfo($nodeList, $options = array())
 {
     //Now separate by content type	$contenttypes = array();
     if (empty($nodeList)) {
         return array();
     }
     $nodeIds = array();
     $needVote = array();
     $cacheVote = array();
     $needRead = array();
     $parentids = array();
     $attachCounts = array();
     $photoCounts = array();
     $channels = array();
     $grabAttachCounts = array();
     $cache = vB_Cache::instance(vB_Cache::CACHE_FAST);
     $userids = array();
     foreach ($nodeList as $key => $node) {
         if (empty($node['nodeid'])) {
             continue;
         }
         if (!isset($contenttypes[$node['contenttypeid']])) {
             $contenttypes[$node['contenttypeid']] = array();
         }
         $contenttypes[$node['contenttypeid']][$key] = $node['nodeid'];
         $nodeIds[] = $node['nodeid'];
         if ($this->channelTypeId != $node['contenttypeid']) {
             // only fetch attachments for non channels.
             $grabAttachCounts[] = $node['nodeid'];
         }
         if (!isset($node['nodeVoted'])) {
             $needVote[] = $node['nodeid'];
         } else {
             $cacheVote[$node['nodeid']] = $node['nodeVoted'];
         }
         if (!isset($node['readtime'])) {
             $needRead[$node['nodeid']] = $node['nodeid'];
             $nodeList[$key]['readtime'] = 0;
         }
         $parentids[$node['parentid']] = $node['parentid'];
         $needRead = array_merge($parentids, $needRead);
         if (!isset($userids[$node['userid']])) {
             $userids[$node['userid']] = $node['userid'];
         }
     }
     vB_Library::instance('user')->preloadUserInfo($userids);
     // pre-cache parents
     $parents = $this->getNodes($parentids);
     $parentrouteids = array();
     foreach ($parents as $parent) {
         $parentrouteids[] = $parent['routeid'];
     }
     //pre-load parent routes
     vB5_Route::preloadRoutes($parentrouteids);
     // get votes
     $nodeVotes = empty($needVote) ? array() : $this->getNodeVotes($needVote);
     if (!empty($cacheVote)) {
         $this->cacheNodeVotes($cacheVote);
     }
     if (!empty($nodeIds)) {
         $attachments = $this->fetchNodeAttachments($nodeIds);
         $nodeAttachments = array();
         foreach ($attachments as $key => $attach) {
             $nodeAttachments[$attach['parentid']][$attach['filedataid']] =& $attachments[$key];
         }
     }
     // Fetch read marking data
     $threadmarking = vB::getDatastore()->getOption('threadmarking');
     $userid = vB::getCurrentSession()->get('userid');
     if ($threadmarking and $userid and !empty($nodeIds) and !empty($needRead)) {
         $reads = vB::getDbAssertor()->getRows('noderead', array('userid' => $userid, 'nodeid' => $needRead));
         $parentsreads = array();
         foreach ($reads as $read) {
             if (!empty($nodeList[$read['nodeid']])) {
                 $nodeList[$read['nodeid']]['readtime'] = $read['readtime'];
             } else {
                 $parentsreads[$read['nodeid']] = $read['readtime'];
             }
         }
         foreach ($nodeList as $nodeid => $node) {
             if (empty($parentsreads[$node['parentid']])) {
                 $parentsreads[$node['parentid']] = 0;
             }
             $nodeList[$nodeid]['parentreadtime'] = $parentsreads[$node['parentid']];
         }
     }
     //For each type, get the content detail.
     if (!empty($grabAttachCounts)) {
         $attachCountQry = vB::getDbAssertor()->getRows('vBForum:getDescendantAttachCount', array('nodeid' => $grabAttachCounts));
         foreach ($attachCountQry as $count) {
             $attachCounts[$count['nodeid']] = $count['count'];
         }
         $photoCountQry = vB::getDbAssertor()->getRows('vBForum:getDescendantPhotoCount', array('nodeid' => $grabAttachCounts, 'photoTypeid' => vB_Types::instance()->getContentTypeID('vBForum_Photo')));
         foreach ($photoCountQry as $count) {
             $photoCounts[$count['nodeid']] = $count['count'];
         }
     }
     // precache closure
     $this->fetchClosureParent($nodeIds);
     $optionMask = vB_Api::instanceInternal('node')->getOptions();
     foreach ($contenttypes as $contenttypeid => $nodes) {
         if (!empty($nodes)) {
             $contentLib = vB_Library_Content::getContentLib($contenttypeid);
             $contentList = $contentLib->getFullContent($nodes);
             foreach ($nodes as $key => $nodeid) {
                 if (isset($contentList[$nodeid])) {
                     if (!empty($contentList[$nodeid]['node_no_permission'])) {
                         unset($nodeList[$nodeid]);
                         continue;
                     }
                     if (isset($nodeList[$key]['nodeVoted'])) {
                         // node came into the function with nodeVoted already set
                         $contentList[$nodeid]['nodeVoted'] = $nodeList[$key]['nodeVoted'];
                     } else {
                         // node came into this function w/o nodeVoted set so getNodeVotes retrieved it up there^
                         $contentList[$nodeid]['nodeVoted'] = in_array($nodeid, $nodeVotes) ? 1 : 0;
                     }
                     $nodeList[$key]['content'] = $contentList[$nodeid];
                     if (!empty($contentList[$nodeid]['contenttypeclass'])) {
                         $nodeList[$key]['contenttypeclass'] = $contentList[$nodeid]['contenttypeclass'];
                     }
                     if ($contentList[$nodeid]['contenttypeid'] == $this->channelTypeId) {
                         $channels[$contentList[$nodeid]['nodeid']] = $contentList[$nodeid]['nodeid'];
                     } else {
                         if (!empty($contentList[$nodeid]['channelid']) and !isset($channels[$contentList[$nodeid]['channelid']])) {
                             $channels[$contentList[$nodeid]['channelid']] = $contentList[$nodeid]['channelid'];
                         }
                     }
                 }
                 foreach ($optionMask as $bitname => $bitmask) {
                     $nodeList[$key][$bitname] = $bitmask & $node['nodeoptions'] ? 1 : 0;
                 }
                 if (isset($nodeAttachments[$nodeid])) {
                     $nodeList[$key]['content']['attachments'] =& $nodeAttachments[$nodeid];
                 } else {
                     $nodeList[$key]['content']['attachments'] = array();
                 }
                 if (empty($attachCounts[$nodeid])) {
                     $nodeList[$key]['attachcount'] = 0;
                 } else {
                     $nodeList[$key]['attachcount'] = $attachCounts[$nodeid];
                 }
                 if (!empty($photoCounts[$nodeid])) {
                     $nodeList[$key]['attachcount'] += $photoCounts[$nodeid];
                 }
             }
         }
     }
     // censor textual node items
     vB_Library_Node::censorNodes($nodeList);
     $this->addOptionalContentInfo($nodeList, $options);
     //Note- it is essential that the parentids be passed along with the nodeList. This allows all the permissions to
     // be pulled in one function call, and saves a lot of processing in the usercontext object.
     $this->markSubscribed($nodeList);
     $this->markJoined($nodeList);
     return $nodeList;
 }
Example #3
0
 /**
  * Assembles the response for detailed content
  *
  *	@param	Array	$content	getRawContent() response array. Each element is a nodeid-keyed array. Each
  *								subarray must have the following data at minimum: nodeid, channelid,
  *								contenttypeid, starter, showopen, userid, setfor (if VM), nodeoptions
  *
  *	@return	Array	Nodeid-keyed array of the $content data, plus additional data such as contenttypeclass,
  *					createpermissions, moderatorperms, channeltype, permissions, etc, @TODO: complete this list
  *					Also the expanded nodeoptions of:
  *						allow_post, moderate_comments, approve_membership, invite_only, autoparselinks,
  *						disablesmilies, disable_bbcode, hide_title, hide_author, hide_publishdate,
  *						display_fullincategory, display_pageviews, hide_comment_count
  */
 public function assembleContent(&$content)
 {
     // get the class name for this content type to add to results
     $contentTypeClass = vB_Types::instance()->getContentTypeClass($this->contenttypeid);
     $userContext = vB::getUserContext();
     $languageid = vB::getCurrentSession()->get('languageid');
     //We can save some time by saving, for a page load, the list of
     // channels we already know the current user can't post.
     static $noComment = array();
     $results = array();
     $needUserRep = array();
     $cache = vB_Cache::instance(vB_Cache::CACHE_STD);
     $fastCache = vB_Cache::instance(vB_Cache::CACHE_FAST);
     $thisUserid = vB::getCurrentSession()->get('userid');
     //pre-cache channels
     $channelids = $nodeids = array();
     $canUseRep = $userContext->hasPermission('genericpermissions', 'canuserep');
     foreach ($content as $key => $record) {
         if (!$this->checkComplete($record)) {
             unset($content[$key]);
         }
         if (!empty($record['channelid'])) {
             $channelids[$record['channelid']] = $record['channelid'];
         } else {
             if ($record['contenttypeid'] == $this->channelTypeId) {
                 $content[$key]['channelid'] = $record['nodeid'];
                 $channelids[$record['nodeid']] = $record['nodeid'];
             } else {
                 $starter = vB_Library::instance('node')->getNodeBare($record['starter']);
                 $content[$key]['channelid'] = $starter['parentid'];
                 $channelids[$starter['parentid']] = $starter['parentid'];
             }
         }
         $nodeids[] = $record['nodeid'];
     }
     // preload closure
     vB_Library::instance('node')->fetchClosureParent($nodeids);
     $channels = vB_Library::instance('node')->getNodes($channelids);
     //and preload channel permission data
     $channelPerms = vB::getUserContext()->fetchPermsForChannels($channelids);
     $needOnlineStatus = array();
     $needReputation = array();
     $contentUserids = array();
     $channelTypes = vB::getDatastore()->getValue('vBChannelTypes');
     //we can comment if there is at least one content type we can create, and the channel (in case this is a blog or
     //social group) doesn't have comments disabled, and either it's your and you have canreply
     $userid = vB::getCurrentSession()->get('userid');
     $commentsEnabled = vB::getDatastore()->getOption('postcommentthreads');
     $canmanageownprofile = $channelPerms['global']['canmanageownprofile'];
     foreach ($content as $key => $record) {
         $record['contenttypeclass'] = $contentTypeClass;
         $channelid = $record['channelid'];
         $thisChannelPerms = $channelPerms[$channelid];
         //$record['createpermissions'] = $thisChannelPerms['cancreate'];
         /*
          *	I'm making the assumption that the 'createpermissions' here is only used in the templates to check
          *	whether a REPLY to this specific node can be created or not. For an example, refer to their use in
          *	the contententry template. Note that if what we need is NOT supposed to be permissions to reply to
          *	this node, we need to fetch the correct permissions at that time. For an example, refer to the
          *	createcontent controller's loadEditor(), where it calls getCreatepermissionsForEdit().
          *	Since the permissions for replying to this node might be different from replying to the channel,
          *	we don't want to rely on the channel perm's 'cancreate'.
          *	PS. Never use these for "real" permission checking ("real" permission checking is in content api's validate())
          */
         $record['createpermissions'] = vB::getUserContext()->getCanCreate($record['nodeid']);
         $record['moderatorperms'] = $thisChannelPerms['moderate'];
         //channeltype
         if (isset($channelTypes[$channelid])) {
             $record['channeltype'] = $channelTypes[$channelid];
         } else {
             $record['channeltype'] = '';
         }
         $thisChannelPerms['global'] = $channelPerms['global'];
         if ($this->getCanEdit($record, $userContext, $thisChannelPerms)) {
             $record['canedit'] = 1;
         } else {
             $record['canedit'] = 0;
         }
         $record['canview'] = $thisChannelPerms['canview'];
         //There are four moderator-like permissions. Let's start setting them to zero. If the user has that
         // permissions we'll enable it soon.
         foreach (array('canmove', 'candeleteposts', 'candeletethread', 'canopenclose') as $permName) {
             $record[$permName] = 0;
         }
         if ($record['contenttypeid'] == $this->channelTypeId) {
             $record['canundeleteposts'] = $record['canremove'] = false;
             // TODO: GET RID OF $record['canremove']
         } else {
             $record['canremove'] = $thisChannelPerms['canremoveposts'];
             // TODO: GET RID OF $record['canremove']
             // Only the soft-delete mod permission grants undelete permission.
             // A user could get soft-delete permissions *without* undelete, which is why we leave
             // candeleteposts to be set by getCanDelete() below
             $record['canundeleteposts'] = $thisChannelPerms['moderate']['candeleteposts'];
             // TODO, update above with the new, real moderator permission when we work on VBV-12234
         }
         // showUnpublishedNotice is used by display_Topics_item template to show the X Unpublished notice
         // in channel view. Because we muck around with the "moderator-like" permissions, including
         // candeleteposts, we can't rely on just that in the templates, so we have to do this.
         // For reference, VBV-12177
         $record['showUnpublishedNotice'] = $thisChannelPerms['moderate']['candeleteposts'];
         // Hard delete & soft delete permissions can be independent.
         // For ex. canremoveposts doesn't give you soft-delete permissions, but does allow you to physically delete
         // The following values may be determined here in addition to 'candeletethread' & 'candeleteposts':
         $record['canharddeleteposts'] = 0;
         $record['moderatorperms']['canremoveposts'] = 0;
         // hard delete
         if ($this->getCanDelete($record, $userContext, $thisChannelPerms, true)) {
             // can hard delete
             $record['canharddeleteposts'] = 1;
             $record['moderatorperms']['canremoveposts'] = 1;
             // is this node a starter? That means they can delete the thread.
             if ($record['starter'] == $record['nodeid']) {
                 $record['candeletethread'] = 1;
             }
         }
         // soft delete
         if ($this->getCanDelete($record, $userContext, $thisChannelPerms, false)) {
             // can soft delete
             $record['candeleteposts'] = 1;
             // 'cansoftdeleteposts' is used just to ensure $record['canmoderate'] will be set to 1 below
             // so that topics will have a checkbox in channel view, VBV-12183. It's not used for anything else.
             // we can't just set $record['moderatorperms']['canremoveposts'], because that value is used for
             // physical-delete specific things in the templates.
             $record['moderatorperms']['cansoftdeleteposts'] = 1;
             // is this node a starter? That means they can delete the thread.
             if ($record['starter'] == $record['nodeid']) {
                 $record['candeletethread'] = 1;
             }
         }
         $record['moderate']['candeleteposts'] = $thisChannelPerms['moderate']['canundeleteposts'] = 0;
         // TODO: figure out what this does and remove if it does nothing
         $thisChannelPerms['canmoderateposts'] = $this->getCanModerate($record, $userContext, $thisChannelPerms);
         if ($thisChannelPerms['canmoderateposts']) {
             $record['canmoderate'] = $record['canmoderateposts'] = 1;
             $record['moderate']['canmoderateposts'] = $thisChannelPerms['moderate']['canmoderateposts'] = 1;
             // TODO: figure out what this does and remove if it does nothing
         } else {
             $record['canmoderate'] = 0;
         }
         //check the four 'my own' moderator-like permissions
         if ($record['showopen'] and $record['userid'] == $thisUserid) {
             //and the four moderator-like permissions for node owners.
             //move is for the topic, not replies & comments
             if ($record['nodeid'] == $record['starter'] and $thisChannelPerms['canmove']) {
                 $record['moderatorperms']['canmove'] = 1;
                 $record['moderatorperms']['canmovethread'] = 1;
             }
             if ($record['nodeid'] == $record['starter'] and $thisChannelPerms['canopenclose']) {
                 $record['moderatorperms']['canopenclose'] = 1;
             }
             // TODO: figure out a way to combine this & the following if blocks into the
             // getCanDelete() checks we do above.
             // Note, this is probably redundant due to 'cansoftdeleteposts' above.
             if ($record['nodeid'] == $record['starter'] and $thisChannelPerms['candeleteownthread']) {
                 // I don't think user_candeleteownpost is actually used in any templates. It seems to be used
                 // just so that $record['canmoderate'] will be set to 1 below, so that inline mod will be enabled.
                 // I'm leaving this alone for now, but there's probably a better way to do this.
                 $record['moderatorperms']['user_candeleteownpost'] = 1;
             }
             if ($record['nodeid'] != $record['starter'] and $thisChannelPerms['candeleteownpost']) {
                 $record['moderatorperms']['candeleteposts'] = 1;
             }
             if ($thisChannelPerms['caneditown']) {
                 $record['moderatorperms']['caneditpost'] = 1;
             }
         }
         // allow the receiver to manage their VMs if they have permission
         if (!empty($record['setfor']) and $record['setfor'] == $userid and $canmanageownprofile) {
             $record['canmoderateposts'] = 1;
             $record['candeleteposts'] = 1;
             $thisChannelPerms['moderate']['canmoderateposts'] = 1;
             // TODO: figure out what this does and remove if it does nothing
         }
         if ($this->textCountChange > 0 and $this->isPublished($record)) {
             $record['textcount_1'] = $record['textcount'] + 1;
             $record['totalcount_1'] = $record['totalcount'] + 1;
             if ($record['canmoderate']) {
                 $record['textcount_1'] += $record['textunpubcount'];
                 $record['totalcount_1'] += $record['totalunpubcount'];
             }
         } else {
             $record['textcount_1'] = $record['textcount'];
             $record['totalcount_1'] = $record['totalcount'];
         }
         // Add userinfo for reputation - is there a cached version?
         if ($record['userid'] > 0 and $record['contenttypeid'] != $this->channelTypeId) {
             $needReputation['vBUserRep_' . $record['userid']] = 'vBUserRep_' . $record['userid'];
         }
         $record['allow_post'] = $record['nodeoptions'] & vB_Api_Node::OPTION_ALLOW_POST ? 1 : 0;
         $record['moderate_comments'] = $record['nodeoptions'] & vB_Api_Node::OPTION_MODERATE_COMMENTS ? 1 : 0;
         $record['approve_membership'] = $record['nodeoptions'] & vB_Api_Node::OPTION_AUTOAPPROVE_MEMBERSHIP ? 1 : 0;
         $record['invite_only'] = $record['nodeoptions'] & vB_Api_Node::OPTION_NODE_INVITEONLY ? 1 : 0;
         $record['autoparselinks'] = $record['nodeoptions'] & vB_Api_Node::OPTION_NODE_PARSELINKS ? 1 : 0;
         $record['disablesmilies'] = $record['nodeoptions'] & vB_Api_Node::OPTION_NODE_DISABLE_SMILIES ? 1 : 0;
         $record['disable_bbcode'] = $record['nodeoptions'] & vB_Api_Node::OPTION_NODE_DISABLE_BBCODE ? 1 : 0;
         $record['hide_title'] = $record['nodeoptions'] & vB_Api_Node::OPTION_NODE_HIDE_TITLE ? 1 : 0;
         $record['hide_author'] = $record['nodeoptions'] & vB_Api_Node::OPTION_NODE_HIDE_AUTHOR ? 1 : 0;
         $record['hide_publishdate'] = $record['nodeoptions'] & vB_Api_Node::OPTION_NODE_HIDE_PUBLISHDATE ? 1 : 0;
         $record['display_fullincategory'] = $record['nodeoptions'] & vB_Api_Node::OPTION_NODE_DISPLAY_FULL_IN_CATEGORY ? 1 : 0;
         $record['display_pageviews'] = $record['nodeoptions'] & vB_Api_Node::OPTION_NODE_DISPLAY_PAGEVIEWS ? 1 : 0;
         $record['hide_comment_count'] = $record['nodeoptions'] & vB_Api_Node::OPTION_NODE_HIDE_COMMENT_COUNT ? 1 : 0;
         $record['can_flag'] = intval($userid) ? 1 : 0;
         //If this is not a channel, we need the user information to check reputation.
         if ($record['contenttypeid'] != $this->channelTypeId) {
             $contentUserids[] = $record['userid'];
             // these cache keys are set by vB_Library_User::preloadUserInfo
             $needOnlineStatus[$record['userid']] = "vb_UserInfo_{$record['userid']}_{$languageid}";
             //Now the moderator-type permissions
             if (!empty($record['moderatorperms'])) {
                 foreach ($record['moderatorperms'] as $key => $perm) {
                     if ($perm > 0 and $key != 'caneditpost') {
                         $record['canmoderate'] = 1;
                         break;
                     }
                 }
             }
         }
         $infractionLibrary = vB_Library::instance('content_infraction');
         $record['caninfract'] = $infractionLibrary->canInfractNode($record['nodeid'], $record) ? 1 : 0;
         $record['canviewnodeinfraction'] = $infractionLibrary->canViewNodeInfraction($record['nodeid'], $record) ? 1 : 0;
         $record['canseewholiked'] = $userContext->hasPermission('genericpermissions', 'canseewholiked') ? 1 : 0;
         // Let's make sure that these two are always set, so we don't run into undefine indices downstream somewhere.
         // Note that 'createpermissions' is instantiated above, near the beginning of this foreach body
         $record['can_comment'] = 0;
         $record['canreply'] = 0;
         //the channel permissions don't seem to use  vB_Api_Node::OPTION_ALLOW_POST and it appears to have
         //some special meaning for channels regarding comments so we'll handle channels seperately
         //If this is a channel we need to check canpostnew is the proper permission for channels
         if ($record['contenttypeid'] == $this->channelTypeId) {
             if (!$thisChannelPerms['canpostnew']) {
                 $record['createpermissions'] = false;
             }
             if (($record['nodeoptions'] & vB_Api_Node::OPTION_ALLOW_POST) > 0) {
                 $record['can_comment'] = (int) ($thisChannelPerms['cancomment'] and $commentsEnabled);
                 $record['canreply'] = $thisChannelPerms['canreply'];
             }
         } else {
             if ($record['starter'] == $record['nodeid']) {
                 $record['canreply'] = 0;
                 if (!$thisChannelPerms['canreply']) {
                     $record['createpermissions'] = false;
                 } else {
                     $record['canreply'] = ($record['nodeoptions'] & vB_Api_Node::OPTION_ALLOW_POST) > 0 ? 1 : 0;
                 }
             } else {
                 // per VBV-4523, commenting requires BOTH cancomment AND canreply
                 if (!($thisChannelPerms['cancomment'] and $thisChannelPerms['canreply'])) {
                     $record['createpermissions'] = false;
                 }
                 //if comments are disabled, then ... don't allow comments.
                 if (($record['nodeoptions'] & vB_Api_Node::OPTION_ALLOW_POST) > 0 and $commentsEnabled) {
                     $record['can_comment'] = ($thisChannelPerms['cancomment'] and $thisChannelPerms['canreply']) ? 1 : 0;
                     if ($thisChannelPerms['cancomment'] and !empty($record['starter'])) {
                         //If we were called with fullcontent then we already have the channel.
                         if (empty($record['channelid'])) {
                             $thisParent = $this->nodeApi->getNode($record['starter']);
                             $record['channelid'] = $thisParent['parentid'];
                         }
                         if (empty($channels[$record['channelid']])) {
                             $channels[$record['channelid']] = $this->nodeApi->getNode($record['channelid']);
                         }
                         //special interpretation of vB_Api_Node::OPTION_ALLOW_POST) for channels if that's not
                         //set then replies in this channel shouldn't allow comments.
                         //We need to check the nodeoptions field.
                         if (($channels[$record['channelid']]['nodeoptions'] & vB_Api_Node::OPTION_ALLOW_POST) == 0) {
                             $record['can_comment'] = 0;
                         }
                     }
                 }
             }
         }
         /*
          * Note 2014-02-19: We should remove 'canremove'. It doesn't really do anything outside of unit tests
          *	currently. Not to confuse this with the 'canremove' checked in editor_contenttype_Text_comment template.
          *	That's set in the createcontent controller.
          *	I haven't removed it yet because it would cause a bunch of unit test failures, since they still check for
          *	this even though it's not used anymore.
          */
         $record['permissions'] = array('canedit' => $record['canedit'], 'canmoderate' => $record['canmoderate'], 'canvote' => $thisChannelPerms['canvote'] ? 1 : 0, 'canuserep' => $canUseRep ? 1 : 0, 'canremove' => $record['canremove'], 'can_flag' => $record['can_flag'], 'canviewthreads' => $thisChannelPerms['canviewthreads'], 'canviewothers' => $thisChannelPerms['canviewothers'], 'caninfract' => $record['caninfract'], 'canviewnodeinfraction' => $record['canviewnodeinfraction'], 'canseewholiked' => $record['canseewholiked'], 'can_comment' => $record['can_comment']);
         // can't like an infraction
         if ($record['permissions']['canuserep'] and $this->contenttype == 'vBForum_Infraction') {
             $record['permissions']['canuserep'] = 0;
         }
         $record['moderatorperms']['canharddeleteposts'] = (int) $record['canharddeleteposts'];
         $record['moderatorperms']['candeleteposts'] = (int) $record['candeleteposts'];
         $record['moderatorperms']['canundeleteposts'] = (int) $record['canundeleteposts'];
         $record['moderatorperms']['candeletethread'] = empty($record['candeletethread']) ? 0 : 1;
         $record['moderatorperms']['canmoderateposts'] = empty($record['canmoderateposts']) ? 0 : 1;
         $results[$record['nodeid']] = $record;
     }
     if (!empty($contentUserids)) {
         vB_Library::instance('user')->preloadUserInfo($contentUserids);
         // Add online status
         require_once DIR . '/includes/functions_bigthree.php';
         // we just preloaded this info, so there must be a cache hit
         $cached = $fastCache->read($needOnlineStatus);
         $loadedSigPerm = array();
         foreach ($results as $key => $record) {
             if ($record['userid'] == 0) {
                 continue;
             }
             $cache_key = "vb_UserInfo_{$record['userid']}_{$languageid}";
             $authorInfo = $cached[$cache_key];
             $results[$key]['signature'] = $authorInfo['signature'];
             if (!empty($authorInfo['signature'])) {
                 if (empty($loadedSigPerm[$record['userid']])) {
                     $loadedSigPerm[$record['userid']] = vB::getUserContext($record['userid'])->hasPermission('genericpermissions', 'canusesignature');
                 }
                 $results[$key]['canSign'] = $loadedSigPerm[$record['userid']] ? 1 : 0;
             }
             $results[$key]['musername'] = vB_Api::instanceInternal("user")->fetchMusername($authorInfo);
             if (!isset($authorInfo['online'])) {
                 fetch_online_status($authorInfo);
             }
             $results[$key]['online'] = $authorInfo['online'];
             $options = vB::getDatastore()->getValue('options');
             if (!empty($options['postelements']) and $options['postelements'] == 4 and ($authorInfo['ipoints'] or $authorInfo['warnings'] or $authorInfo['infractions']) and ($userContext->hasPermission('genericpermissions', 'canreverseinfraction') or $userContext->hasPermission('genericpermissions', 'canseeinfraction') or $userContext->hasPermission('genericpermissions', 'cangiveinfraction') or vB::getCurrentSession()->get('userid') == $authorInfo['userid'])) {
                 $results[$key]['postelements'] = $options['postelements'];
                 $results[$key]['ipoints'] = $authorInfo['ipoints'];
                 $results[$key]['warnings'] = $authorInfo['warnings'];
                 $results[$key]['infractions'] = $authorInfo['infractions'];
             }
         }
     }
     if (!empty($needReputation)) {
         $cached = $cache->read($needReputation);
         foreach ($content as $record) {
             // Add userinfo for reputation - is there a cached version?
             if ($record['userid'] > 0 and $record['contenttypeid'] != $this->channelTypeId) {
                 if ($cached['vBUserRep_' . $record['userid']] !== false) {
                     $cacheitem = $cached['vBUserRep_' . $record['userid']];
                     $results[$record['nodeid']]['reputation'] = $cacheitem['reputation'];
                     $results[$record['nodeid']]['showreputation'] = $cacheitem['showreputation'];
                     $results[$record['nodeid']]['reputationlevelid'] = $cacheitem['reputationlevelid'];
                     $results[$record['nodeid']]['reputationpower'] = $cacheitem['reputationpower'];
                     $results[$record['nodeid']]['reputationimg'] = $cacheitem['reputationimg'];
                 } else {
                     $needUserRep[$record['nodeid']] = $record['userid'];
                 }
             }
         }
     }
     //Now add reputation for any users for which we didn't have a cached value.
     if (!empty($needUserRep)) {
         $reputationLib = vB_Library::instance('reputation');
         $userInfo = $this->assertor->assertQuery('user', array(vB_dB_Query::TYPE_KEY => vB_dB_Query::QUERY_SELECT, 'userid' => $needUserRep));
         $bf_misc_useroptions = vB::getDatastore()->getValue('bf_misc_useroptions');
         $userReps = array();
         //build the reputation information
         foreach ($userInfo as $authorInfo) {
             $userid = $authorInfo['userid'];
             $userReps[$userid] = array();
             $userReps[$userid]['reputation'] = $authorInfo['reputation'];
             $userReps[$userid]['showreputation'] = $authorInfo['options'] & $bf_misc_useroptions['showreputation'];
             $userReps[$userid]['reputationlevelid'] = $authorInfo['reputationlevelid'];
             $userReps[$userid]['reputationpower'] = $reputationLib->fetchReppower($authorInfo);
             $userReps[$userid]['reputationimg'] = $reputationLib->fetchReputationImageInfo($authorInfo);
             //cache this for a day
             $cache->write('vBUserRep_' . $userid, $userReps[$userid], 1440, array("fUserContentChg_{$userid}", "userChg_{$userid}"));
         }
         foreach ($needUserRep as $nodeid => $userid) {
             if (!empty($userReps[$userid])) {
                 foreach ($userReps[$userid] as $field => $val) {
                     $results[$nodeid][$field] = $val;
                 }
             }
         }
     }
     // censor textual node items
     vB_Library_Node::censorNodes($results);
     return $results;
 }