protected function buildOutputFromItems($items, $options) { parent::buildOutputFromItems($items, $options); $xml = new vB_Xml_Builder(); $xml->add_group('rss', array('version' => '0.91')); $xml->add_group('channel'); $xml->add_tag('title', $this->rssinfo['title']); $xml->add_tag('link', $this->rssinfo['link'] . '/', array(), false, true); $xml->add_tag('description', $this->rssinfo['description']); $xml->add_tag('language', $this->defaultLang['languagecode']); $xml->add_group('image'); $xml->add_tag('url', $this->rssinfo['icon']); $xml->add_tag('title', $this->rssinfo['title']); $xml->add_tag('link', $this->rssinfo['link'] . '/', array(), false, true); $xml->close_group('image'); $dateformat = vB::getDatastore()->getOption('dateformat'); $timeformat = vB::getDatastore()->getOption('timeformat'); // gather channel info $channelsInfo = $this->getItemsChannelInfo($items); $items = $this->formatItems($items, $options); foreach ($items as $id => $item) { $item = $item['content']; $xml->add_group('item'); $xml->add_tag('title', $item['external_prefix_plain'] . vB_String::htmlSpecialCharsUni($item['external_title'])); $xml->add_tag('link', vB_Api::instanceInternal('route')->getAbsoluteNodeUrl($item['external_nodeid']), array(), false, true); $xml->add_tag('description', vB_Phrase::fetchSinglePhrase('rss_91_forum_w_posted_by_x_post_time_y_at_z', array($channelsInfo[$item['channelid']]['htmltitle'], $item['authorname'], $this->callvBDate($dateformat, $item['publishdate']), $this->callvBDate($timeformat, $item['publishdate'])))); $xml->close_group('item'); } $xml->close_group('channel'); $xml->close_group('rss'); $output .= '<!DOCTYPE rss PUBLIC "-//RSS Advisory Board//DTD RSS 0.91//EN" "http://www.rssboard.org/rss-0.91.dtd">' . "\r\n"; $output .= $xml->output(); return $xml->fetch_xml_tag() . $output; }
/** sends a batch of emails * * @param mixed array of recipients, or a semicolon-delimited string * @param string subject of the message * @param string content of message * * @return mixed either success => true, or array of sent, failed, errors, and message- the last is suitable for display to user. */ public function send($to, $subject, $message) { //This should only be used by admins if (!vB::getUserContext()->hasAdminPermission('canadminusers')) { throw new vB_Exception_Api('no_permission'); } if (!is_array($to)) { if (strpos($to, ';')) { $to = explode(';', $to); } else { $to = array($to); } } $errors = ''; $sent = array(); $failed = array(); foreach ($to as $toemail) { //The next function returns either true, false or an error string. $result = vB_Mail::vbmail($toemail, $subject, $message, false, '', '', '', true); if (is_string($result)) { $errors .= $result; } else { if ($result) { $sent[] = $toemail; } else { $failed[] = $toemail; } } } if (empty($failed) and empty($errors)) { return array('success' => true); } $message = ''; if (!empty($errors)) { $message = vB_Phrase::fetchSinglePhrase('error_x', $errors) . '. '; } if (!empty($sent)) { $message .= vB_Phrase::fetchSinglePhrase('sent_to_x', implode(',', $sent)); } if (!empty($failed)) { $message .= vB_Phrase::fetchSinglePhrase('send_failed_to_x', implode(',', $failed)); } return array('sent' => $sent, 'failed' => $failed, 'errors' => $errors, 'message' => $message); }
/** * Check whether a user is banned and returns info such as reason and liftdate if possible. * * @param int User id * * @retun mixed Array containing ban liftdate and reason or false is user is not banned. */ public function fetchBannedInfo($userid) { $userid = intval($userid); if (!$userid) { $userid = vB::getCurrentSession()->get('userid'); } $cache = vB_Cache::instance(vB_Cache::CACHE_FAST); // looking up cache for the node $hashKey = 'vbUserBanned_' . $userid; $banned = $cache->read($hashKey); if (!empty($banned)) { // a string false is received if the banning was already checked and the user is not banned if ($banned === 'false') { return false; } return $banned; } if ($this->isBanned($userid)) { $info = array('isbanned' => 1); $banRecord = vB::getDbAssertor()->getRow('vBForum:userban', array('userid' => $userid)); if ($banRecord and empty($banRecord['errors'])) { $info['liftdate'] = $banRecord['liftdate']; $info['reason'] = $banRecord['reason']; $info['admin'] = $this->fetchUserName($banRecord['adminid']); } else { if (!vB::getUserContext()->hasPermission('genericoptions', 'isnotbannedgroup')) { $info['bannedGroup'] = true; $info['admin'] = vB_Phrase::fetchSinglePhrase('administrator'); } } $cache->write($hashKey, $info, 1440, 'userChg_' . $userid); return $info; } else { // false is intentionally passed as string so it can be identified as different from the boolean false returned by the cache if not cached $cache->write($hashKey, 'false', 1440, 'userChg_' . $userid); return false; } }
/** * Do prune/move users (step 1) * * @param array $userids UserID to be pruned or moved * @param string $dowhat 'delete' or 'move' * @param integer $movegroup Usergroup ID that the users are going to be moved */ public function prune($userids, $dowhat, $movegroup = 0) { $this->checkHasAdminPermission('canadminusers'); if (empty($userids)) { throw new vB_Exception_Api('please_complete_required_fields'); } $vboptions = vB::getDatastore()->getValue('options'); if ($dowhat == 'delete') { foreach ($userids as $userid) { $this->delete($userid); } } else { if ($dowhat == 'move') { $group = vB::getDbAssertor()->getRow('user_fetchusergroup', array(vB_dB_Query::TYPE_KEY => vB_dB_Query::QUERY_STORED, 'usergroupid' => $movegroup)); if (!$group) { throw new vB_Exception_Api('invalidid', array(vB_Phrase::fetchSinglePhrase('usergroup'), vB5_Route::buildUrl('contact-us|fullurl'))); } vB::getDbAssertor()->assertQuery('user_updateusergroup', array('usergroupid' => $movegroup, 'userids' => $userids)); } else { throw new vB_Exception_Api('please_complete_required_fields'); } } return true; }
if (defined('IN_CONTROL_PANEL')) { echo "<li><a href=\"{$itemlink}\" target=\"feed\">{$itemtitle}</a></li>"; } $rsslog_insert_sql[] = array('rssfeedid' => $item['rssfeedid'], 'itemid' => $itemid, 'itemtype' => $itemtype, 'uniquehash' => vB::getDbAssertor()->escape_string($uniquehash), 'contenthash' => vB::getDbAssertor()->escape_string($item['contenthash']), 'dateline' => vB::getRequest()->getTimeNow(), 'topicactiontime' => $threadactiontime); $cronlog_items["{$item['rssfeedid']}"][] = "\t<li>{$vbphrase[$itemtype]} <a href=\"{$itemlink}\" target=\"logview\"><em>{$itemtitle}</em></a></li>"; $announcementCache[$feed['nodeid']] = 'vB_Announcements_' . $feed['nodeid']; } break; // insert item as thread // insert item as thread case 'thread': default: $pagetext = $feed['xml']->parse_template($feed['bodytemplate'], $item); $itemtitle = strip_bbcode(convert_wysiwyg_html_to_bbcode($feed['xml']->parse_template($feed['titletemplate'], $item))); if (empty($itemtitle)) { $itemtitle = vB_Phrase::fetchSinglePhrase('rssposter_post_from_x', array($feed['title'])); } $itemAddResult = vB_Library::instance('content_text')->add(array('userid' => $feed['userid'], 'sticky' => $feed['rssoptions'] & $bf_misc_feedoptions['stickthread'] ? 1 : 0, 'parentid' => $feed['nodeid'], 'title' => $itemtitle, 'rawtext' => $pagetext, 'approved' => $feed['rssoptions'] & $bf_misc_feedoptions['moderatethread'] ? 0 : 1, 'showapproved' => $feed['rssoptions'] & $bf_misc_feedoptions['moderatethread'] ? 0 : 1, 'iconid' => !empty($feed['iconid']) ? $feed['iconid'] : 0), array('autoparselinks' => 1, 'nl2br' => $nl2br, 'skipDupCheck' => 1), $convertHtmlToBbcode); $itemid = !empty($itemAddResult['nodeid']) ? $itemAddResult['nodeid'] : false; $threadactiontime = $feed['topicactiondelay'] > 0 ? vB::getRequest()->getTimeNow() + $feed['topicactiondelay'] * 3600 : 0; if ($itemid) { $itemtype = 'topic'; $itemlink = vB_Api::instanceInternal('route')->getAbsoluteNodeUrl($itemid); if (defined('IN_CONTROL_PANEL')) { echo "<li><a href=\"{$itemlink}\" target=\"feed\">{$itemtitle}</a></li>"; } $rsslog_insert_sql[] = array('rssfeedid' => $item['rssfeedid'], 'itemid' => $itemid, 'itemtype' => $itemtype, 'uniquehash' => vB::getDbAssertor()->escape_string($uniquehash), 'contenthash' => vB::getDbAssertor()->escape_string($item['contenthash']), 'dateline' => vB::getRequest()->getTimeNow(), 'topicactiontime' => $threadactiontime); $cronlog_items["{$item['rssfeedid']}"][] = "\t<li>{$vbphrase[$itemtype]} <a href=\"{$itemlink}\" target=\"logview\"><em>{$itemtitle}</em></a></li>"; } break; }
/** This function accepts a user follow request or a channel ownership/moderation/membership request * * @param int the nodeid of the request * * @return bool * **/ public function acceptRequest($nodeid) { /* We do the following - validate the record - call the following api to change the data. - delete the message records */ $userInfo = vB::getCurrentSession()->fetch_userinfo(); $userid = $userInfo['userid']; if (!intval($userid)) { throw new vB_Exception_Api('not_logged_no_permission'); } $message = $this->validateRequest($userid, $nodeid); $resultphrase = ''; //if this is one of the ownership/membership requests, send it to the node api. // If it's a subscriber request (content), handled in else block & send to follow API if (in_array($message['about'], $this->channelRequests) and !in_array($message['about'], $this->channelFollowRequests)) { $result = $this->nodeApi->approveChannelRequest($nodeid); if ($result === true) { switch ($message['about']) { case vB_Api_Node::REQUEST_TAKE_OWNER: case vB_Api_Node::REQUEST_SG_TAKE_OWNER: $resultphrase = 'take_owner_request_accepted'; break; case vB_Api_Node::REQUEST_TAKE_MODERATOR: case vB_Api_Node::REQUEST_SG_TAKE_MODERATOR: $resultphrase = 'take_moderator_request_accepted'; break; case vB_Api_Node::REQUEST_TAKE_MEMBER: case vB_Api_Node::REQUEST_SG_TAKE_MEMBER: $resultphrase = 'take_member_request_accepted'; break; case vB_Api_Node::REQUEST_GRANT_OWNER: case vB_Api_Node::REQUEST_SG_GRANT_OWNER: $resultphrase = 'grant_owner_request_accepted'; break; case vB_Api_Node::REQUEST_GRANT_MODERATOR: case vB_Api_Node::REQUEST_SG_GRANT_MODERATOR: $resultphrase = 'grant_moderator_request_accepted'; break; case vB_Api_Node::REQUEST_GRANT_MEMBER: case vB_Api_Node::REQUEST_SG_GRANT_MEMBER: $resultphrase = 'grant_member_request_accepted'; break; } } } else { // it's a following request $aboutid = $message['aboutid']; $about = $message['about']; $message = vB_Library::instance('node')->getNodeBare($nodeid); $followApi = vB_Api::instanceInternal('follow'); // @TODO we might want to distinguish between follow members and content here... // which implicates adding new approve/deny methods and might need notification message as well. if (in_array($about, $this->channelFollowRequests)) { $followApi->add($aboutid, vB_Api_Follow::FOLLOWTYPE_CONTENT, $message['userid']); } else { $followApi->approveFollowing($message['userid']); } /** HERE IS WHERE FOLLOW NOTIFICATIONS ARE GENERATED!!!! **/ // send ACCEPTEDFOLLOW notification to the requester $notificationData = array('sender' => $userid); $recipients = array($message['userid']); vB_Library::instance('notification')->triggerNotificationEvent('user-accepted-request-follow', $notificationData, $recipients); vB_Library::instance('notification')->insertNotificationsToDB(); $resultphrase = 'follow_request_accepted'; $result = true; } if ($result) { $params = array(); // This relies on $message (initially holding `privatemessage` data) being overwritten by // bare node (`node` data lacking aboutid) data for follow-requests. TODO: Update this if (!empty($message['aboutid'])) { $channel_info = $this->nodeApi->getChannelInfoForNode($message['aboutid']); $node_info = $this->nodeApi->getNode($nodeid); $params[] = $channel_info['title']; $params[] = vB5_Route::buildUrl($channel_info['routeid'] . '|fullurl'); if ($node_info['userid']) { $requesting_user = vB_Api::instanceInternal("User")->fetchUserName($node_info['userid']); $params[] = $requesting_user; $params[] = vB5_Route::buildUrl('profile', array('userid' => $node_info['userid'])); } } //Deletes the records from the node, privatemessage, text, sentto, and closure tables. $this->delete($nodeid); return vB_Phrase::fetchSinglePhrase($resultphrase, $params); } else { return false; } }
/** * Modifies RSS information used for output from given options * * @param array Options. */ private function applyRssOptions($options, $info) { foreach ($this->options as $name => $val) { if (isset($options[$name])) { switch ($name) { case 'nodeid': if (sizeof($options[$name]) == 1) { $channel = $this->assertor->getRow('vBForum:getPageInfoFromChannelId', array('nodeid' => $options[$name])); $info['title'] = vB_Phrase::fetchSinglePhrase('external_x_hyphen_y', array($info['title'], $this->getPhraseFromGuid($channel['guid'], 'title'))); $info['description'] = $this->getPhraseFromGuid($channel['guid'], 'metadesc'); } else { $info['title'] = vB_Phrase::fetchSinglePhrase('external_x_hyphen_y', array($info['title'], implode(', ', $options[$name]))); } break; default: break; } } } return $info; }
if ($user['usergroupid'] == 3) { // only do it if the user is in the correct usergroup // make random number if (empty($user['activationid'])) { //none exists so create one $user['activationid'] = build_user_activation_id($user['userid'], 2, 0); } else { $user['activationid'] = fetch_random_string(40); $assertor->assertQuery('useractivation', array(vB_dB_Query::TYPE_KEY => vB_dB_Query::QUERY_UPDATE, 'dateline' => $timeNow, 'activationid' => $user['activationid'], vB_dB_Query::CONDITIONS_KEY => array('userid' => $user['userid'], 'type' => 0))); } $vboptions = vB::getDatastore()->getValue('options'); $maildata = vB_Api::instanceInternal('phrase')->fetchEmailPhrases('activateaccount', array($user['username'], $vboptions['bbtitle'], $vboptions['frontendurl'], $user['userid'], $user['activationid'], $vboptions['webmasteremail']), array($user['username']), $user['languageid']); vB_Mail::vbmail($user['email'], $maildata['subject'], $maildata['message'], true); } } echo $vbphrase['okay'] . '</p><p><b>' . vB_Phrase::fetchSinglePhrase('emails_sent_successfully') . '</b></p>'; $args['do'] = 'find'; print_cp_redirect2('user', $args, true); } else { eval(standard_error(fetch_error('invalidemail', $vbulletin->options['contactuslink']))); } } // ############################# user change history ######################### if ($_REQUEST['do'] == 'changehistory') { require_once DIR . '/includes/class_userchangelog.php'; require_once DIR . '/includes/functions_misc.php'; $vbulletin->input->clean_array_gpc('r', array('userid' => vB_Cleaner::TYPE_UINT)); if ($vbulletin->GPC['userid']) { // initalize the $user storage $users = false; // create the vb_UserChangeLog instance and set the execute flag (we want to do the query, not just to build)
/** * Retrieves the permissions for the specified file type and upload method * * @param array Data: * uploadFrom *required * extension *required * channelid optional Nodeid of channel which this attachment will be a descendant of * @param bool Imageonly * * @return array $results */ public function getAttachmentPermissions($data) { //Leave for consistency with admincp if (!defined('ATTACH_AS_FILES_NEW')) { define('ATTACH_AS_FILES_NEW', 2); } //Only logged-in-users can upload files $userid = vB::getCurrentSession()->get('userid'); $this->checkPermission($userid); $uploadFrom = !empty($data['uploadFrom']) ? $data['uploadFrom'] : null; $usercontext = vB::getUserContext(); $totalLimit = intval($usercontext->getUsergroupLimit('attachlimit')); $options = vB::getDatastore()->getValue('options'); // Check if we are not exceeding the quota if ($options['attachtotalspace'] > 0) { if ($totalLimit > 0) { $totalLimit = min($totalLimit, $options['attachtotalspace']); } else { $totalLimit = $options['attachtotalspace']; } } //check to see if this user has their limit already. if ($totalLimit > 0) { $usedSpace = intval(vB::getDbAssertor()->getField('vBForum:getUserFiledataFilesizeSum', array('userid' => $userid))); if ($usedSpace > $totalLimit) { return array('errors' => vB_Phrase::fetchSinglePhrase('upload_attachfull_user', $usedSpace - $totalLimit)); } $spaceAvailable = $totalLimit - $usedSpace; } else { $spaceAvailable = false; } $result = array(); // Usergroup permissions if ($uploadFrom === 'profile') { $usergroupattachlimit = $usercontext->getLimit('attachlimit'); $albumpicmaxheight = $usercontext->getLimit('albumpicmaxheight'); $albumpicmaxwidth = $usercontext->getLimit('albumpicmaxwidth'); $result['max_size'] = $usergroupattachlimit; $result['max_height'] = $albumpicmaxheight; $result['max_width'] = $albumpicmaxwidth; if ($spaceAvailable !== false) { $result['max_size'] = min($result['max_size'], $spaceAvailable); $result['attachlimit'] = $totalLimit; } } else { $extension = !empty($data['extension']) ? $data['extension'] : null; if ($extension != null) { // Fetch the parent channel or topic just in case we need to check group in topic. // The actual parent may not exist since we may be creating a new post/topic. $nodeid = !empty($data['parentid']) ? intval($data['parentid']) : false; $attachPerms = $usercontext->getAttachmentPermissions($extension, $nodeid); if ($attachPerms !== false) { $result['max_size'] = $attachPerms['size']; $result['max_height'] = $attachPerms['height']; $result['max_width'] = $attachPerms['width']; if ($spaceAvailable !== false) { $result['max_size'] = min($result['max_size'], $spaceAvailable); $result['attachlimit'] = $totalLimit; } } else { $result['errors'][] = 'invalid_file'; } } else { $result['errors'][] = 'invalid_file'; } } return $result; }
} else { switch ($node['contenttypeid']) { case $contenttypeids['Photo']: case $contenttypeids['Picture']: // todo double check that 'Picture' uses photoid $requestvar = 'photoid'; break; default: $requestvar = 'id'; } } $redirecturl = vB::getDatastore()->getOption('frontendurl') . "/filedata/fetch?{$requestvar}={$node['nodeid']}"; header("Location: {$redirecturl}", true, 301); exit; } } //This script is intended to return a file, not an html document (well now we intend to redirect to a document). //that means this error will only display when troubleshooting since img tags and the like don't display content when //they get a 404. A large 404 page is not only unnecesary but counter productive. // //status is to handle some weirdly configured CGI setups. Probably not needed //in this day and age, but doesn't really hurt. header("HTTP/1.0 404 Not Found"); header("Status: 404 Not Found"); echo vB_Phrase::fetchSinglePhrase('error_404'); /*=========================================================================*\ || ####################################################################### || # Downloaded: 15:45, Tue Sep 8th 2015 || # CVS: $RCSfile$ - $Revision: 84715 $ || ####################################################################### \*=========================================================================*/
/** * Sends emails to moderators configured in admincp */ protected function sendModeratorNotification($nodeid) { // This is the list of ALL mods who have either the newpostemail or the newthreademail option enabled // We'll go through this list and figure out which ones are moderators of the ancestor channels of $nodeid $notify = vB_Cache::instance(vB_Cache::CACHE_STD)->read('vB_Mod_PostNotify'); if ($notify === false) { $library = vB_Library::instance('usergroup'); $smodgroups = $library->getSuperModGroups(); //force to have a non empty array or the query will be unhappy. It's unlikely that a site will //not have any usergroups with the superadmin flag set, but its possible if (!$smodgroups) { $smodgroups = array(0); } $notify = array(); $bitFields = vb::getDatastore()->getValue('bf_misc_moderatorpermissions'); $modQry = $this->assertor->assertQuery('vBForum:modPostNotify', array('bfPost' => $bitFields['newpostemail'], 'bfTopic' => $bitFields['newthreademail'], 'smodgroups' => $smodgroups)); $events = array(); if ($modQry->valid()) { foreach ($modQry as $mod) { $events[$mod['userid']] = 'userChg_' . $mod['userid']; //Every time a moderator changes emails, is deleted, etc, we have to invalidate it. if (!isset($notify[$mod['nodeid']])) { $notify[$mod['nodeid']] = array("posts" => array(), "topics" => array()); } if ($mod['notifypost'] > 0) { $notify[$mod['nodeid']]['posts'][] = $mod['email']; } if ($mod['notifytopic'] > 0) { $notify[$mod['nodeid']]['topics'][] = $mod['email']; } } } // all these user change events could be a lot... $events['vB_ModPostNotifyChg'] = 'vB_ModPostNotifyChg'; vB_Cache::instance(vB_Cache::CACHE_STD)->write('vB_Mod_PostNotify', $notify, 1440, $events); } // grab parents of the added node, and see if we have any moderators on the channel $parents = vB::getDbAssertor()->getRows('vBForum:closure', array('child' => $nodeid)); $notifyList = array(); // the actual list of emails that are associated with this node. $node = vB_Library::instance('node')->getNodeFullContent($nodeid); $node = $node[$nodeid]; if ($node['starter'] == $node['nodeid']) { $notifyKey = "topics"; } else { $notifyKey = "posts"; } foreach ($parents as $closure) { $parentid = $closure['parent']; if (array_key_exists($parentid, $notify)) { // each found list is an array of emails, so we have to merge $notifyList = array_merge($notifyList, $notify[$parentid][$notifyKey]); } } // Global moderators case. At the moment, the global mods in the moderator table has nodeid = 0 so the // closure check above leaves them out. if (!empty($notify[0])) { $notifyList = array_merge($notifyList, $notify[0][$notifyKey]); } $notifyList = array_unique($notifyList); if (empty($notifyList)) { return; } // grab some data for the message $userinfo = vB::getCurrentsession()->fetch_userinfo(); $forumName = vB::getDatastore()->getOption('bbtitle'); $starter = vB_Library::instance('node')->getNodeFullContent($node['starter']); $starter = $starter[$node['starter']]; $threadTitle = $starter['title']; // Below is the call to fetch the url to the thread starter // $threadLink = vB5_Route::buildUrl($starter['routeid'] . '|fullurl', $starter); // If we want the direct link to the post, below is what's needed $routeInfo = array('nodeid' => $nodeid); // Using the normal vB5_Route::buildURL can throw an exception, because it'll likely use the // conversation route which checks permissions on the *current* user in the constructor and // throw an exception. // So we'll use vB5_Route_Node $nodeLink = vB5_Route::buildUrl('node|fullurl', $routeInfo); $message = vB_Phrase::fetchSinglePhrase('new_post_notification_a_b_c_d_e_f', array($userinfo['username'], $node['channeltitle'], $forumName, $threadTitle, $nodeLink, $node['rawtext'])); $subject = vB_Phrase::fetchSinglePhrase('new_post_in_forum_x', $node['channeltitle']); // send emails foreach ($notifyList as $email) { if ($email != $userinfo['email']) { vB_Mail::vbmail($email, $subject, $message, true, '', '', '', TRUE); } } }
/** * Gets the preview for the messages * * @return mixed array of record-up to five each messages, then requests, then notifications */ public function previewMessages() { if (!$this->canUsePmSystem()) { throw new vB_Exception_Api('not_logged_no_permission'); } $userid = vB::getCurrentSession()->get('userid'); $this->library->checkFolders($userid); $folders = $this->library->fetchFolders($userid); $exclude = array($folders['systemfolders'][vB_Library_Content_Privatemessage::TRASH_FOLDER], $folders['systemfolders'][vB_Library_Content_Privatemessage::NOTIFICATION_FOLDER]); $lastnodeidsQry = $this->assertor->getRows('vBForum:lastNodeids', array('userid' => $userid, 'excludeFolders' => $exclude)); // since the above query might not return anything, if there are no privatemessages for the user, add a -1 to prevent // the qryResults query from breaking $lastnodeids = array(-1); foreach ($lastnodeidsQry as $lastnode) { $lastnodeids[] = $lastnode['nodeid']; } $ignoreUsersQry = $this->assertor->getRows('vBForum:getIgnoredUserids', array('userid' => $userid)); $ignoreUsers = array(-1); foreach ($ignoreUsersQry as $ignoreUser) { $ignoreUsers[] = $ignoreUser['userid']; } $qryResults = $this->assertor->assertQuery('vBForum:pmPreview', array(vB_dB_Query::TYPE_KEY => vB_dB_Query::QUERY_STORED, 'userid' => $userid, 'ignoreUsers' => $ignoreUsers, 'excludeFolders' => $exclude, 'nodeids' => $lastnodeids)); $results = array('message' => array('count' => 0, 'title' => vB_Phrase::fetchSinglePhrase('messages'), 'folderid' => 0, 'messages' => array()), 'request' => array('count' => 0, 'title' => vB_Phrase::fetchSinglePhrase('requests'), 'folderid' => 0, 'messages' => array()), 'notification' => array('count' => 0, 'title' => vB_Phrase::fetchSinglePhrase('notifications'), 'folderid' => 0, 'messages' => array())); $messageIds = array(); $nodeIds = array(); $userIds = array(); $userApi = vB_Api::instanceInternal('user'); $receiptDetail = vB::getUserContext()->hasPermission('genericpermissions', 'canseewholiked'); $needLast = array(); if ($qryResults->valid()) { foreach ($qryResults as $result) { if (empty($result['previewtext'])) { $result['previewtext'] = vB_String::getPreviewText($result['rawtext']); } if ($result['titlephrase'] == 'messages') { $messageIds[] = $result['nodeid']; } else { $nodeIds[] = $result['nodeid']; } // privatemessage_requestdetail template requires you to pass back the phrase name for requests. // See listRequests() for more details if ($result['msgtype'] == 'request') { // remove starting sg_ and ending _to from the about string $cleanAboutStr = preg_replace('/(^sg_)?|(_to$)?/', '', $result['about']); $result['phrasename'] = 'received_' . $cleanAboutStr . '_request_from_x_link_y'; // grab channel request types $channelRequests = $this->library->getChannelRequestTypes(); // append correct suffix for channel requests if (in_array($result['about'], $channelRequests)) { // should have a "_to_channel_z" (take request) or "_for_channel_z" (grant request) appended if (strpos($result['about'], '_to') !== false) { $result['phrasename'] .= '_to_channel_z'; } else { $result['phrasename'] .= '_for_channel_z'; } } } $result['senderAvatar'] = $userApi->fetchAvatar($result['userid']); $result['recipients'] = array(); $result['otherRecipients'] = 0; $result['responded'] = 0; $results[$result['msgtype']]['messages'][$result['nodeid']] = $result; $results[$result['msgtype']]['count']++; $userIds[] = $result['userid']; if (intval($result['lastauthorid'])) { $userIds[] = $result['lastauthorid']; } if (!$results[$result['msgtype']]['folderid']) { $results[$result['msgtype']]['folderid'] = $result['folderid']; } // set recipients needed if ($result['msgtype'] == 'message') { if (empty($result['lastauthorid']) or $result['lastauthorid'] == $userid) { $needLast[] = $result['nodeid']; } } } // @TODO check for a way to implement a generic protected library method to fetch recipients instead of cloning code through methods. // drag the needed info if (!empty($needLast)) { $needLast = array_unique($needLast); $neededUsernames = $this->assertor->assertQuery('vBForum:getPMLastAuthor', array(vB_dB_Query::TYPE_KEY => vB_dB_Query::QUERY_STORED, 'nodeid' => $needLast, 'userid' => $userid)); foreach ($neededUsernames as $username) { if (isset($results['message']['messages'][$username['nodeid']])) { $results['message']['messages'][$username['nodeid']]['lastcontentauthor'] = $username['username']; $results['message']['messages'][$username['nodeid']]['lastauthorid'] = $username['userid']; } } } //Now we need to sort out the other recipients for this message. $recipients = array(); if (!empty($nodeIds)) { $recipientQry = $this->assertor->assertQuery('vBForum:getPMRecipients', array('nodeid' => array_unique($nodeIds), 'userid' => $userid)); foreach ($recipientQry as $recipient) { $recipients[$recipient['nodeid']][$recipient['userid']] = $recipient; } } $messageRecipients = array(); if (!empty($messageIds)) { $recipientsInfo = $this->assertor->assertQuery('vBForum:getPMRecipientsForMessage', array(vB_dB_Query::TYPE_KEY => vB_dB_Query::QUERY_STORED, 'nodeid' => $messageIds)); $recipients = array(); if (!empty($recipientsInfo)) { foreach ($recipientsInfo as $recipient) { if (isset($results['message']['messages'][$recipient['starter']])) { if ($recipient['userid'] == $userid) { if (empty($results['message']['messages'][$recipient['starter']]['included'])) { $results['message']['messages'][$recipient['starter']]['included'] = true; } continue; } else { if ($results['message']['messages'][$recipient['starter']]['lastcontentauthor'] == $recipient['username']) { continue; } } if (!isset($results['message']['messages'][$recipient['starter']]['recipients'][$recipient['userid']])) { $results['message']['messages'][$recipient['starter']]['recipients'][$recipient['userid']] = $recipient; } } } } } //Collect the user info. Doing it this way we get a lot of info in one query. $userQuery = $this->assertor->assertQuery('user', array('userid' => array_unique($userIds))); $userInfo = array(); $userApi = vB_Api::instanceInternal('user'); foreach ($userQuery as $userRecord) { //some information we shouldn't pass along. foreach (array('token', 'scheme', 'secret', 'coppauser', 'securitytoken_raw', 'securitytoken', 'logouthash', 'fbaccesstoken', 'passworddate', 'parentemail', 'logintype', 'ipaddress', 'passworddate', 'referrerid', 'ipoints', 'infractions', 'warnings', 'infractiongroupids', 'infractiongroupid') as $field) { unset($userRecord[$field]); } $userRecord['avatar'] = $userApi->fetchAvatar($userRecord['userid'], true, $userRecord); $userInfo[$userRecord['userid']] = $userRecord; } //Now we need to scan the results list and assign the other recipients. foreach ($results as $key => $folder) { foreach ($folder['messages'] as $msgkey => $message) { if ($message['titlephrase'] == 'messages') { // set the first recipient if (!empty($message['lastcontentauthor']) and !empty($message['lastauthorid']) and $message['lastauthorid'] != $userid) { $results[$key]['messages'][$msgkey]['firstrecipient'] = array('userid' => $message['lastauthorid'], 'username' => $message['lastcontentauthor']); } else { if (!empty($message['recipients'])) { $firstrecip = reset($message['recipients']); $results[$key]['messages'][$msgkey]['firstrecipient'] = $firstrecip; unset($results[$key]['messages'][$msgkey]['recipients'][$firstrecip['userid']]); } } $results[$key]['messages'][$msgkey]['otherRecipients'] = count($results[$key]['messages'][$msgkey]['recipients']); } else { if (!empty($recipients[$message['nodeid']])) { $results[$key]['messages'][$msgkey]['recipients'] = $recipients[$message['nodeid']]; $results[$key]['messages'][$msgkey]['otherRecipients'] = count($recipients[$message['nodeid']]); $results[$key]['messages'][$msgkey]['userinfo'] = $userInfo[$message['userid']]; } } if ($message['lastauthorid']) { $results[$key]['messages'][$msgkey]['lastauthor'] = $userInfo[$message['lastauthorid']]['username']; $results[$key]['messages'][$msgkey]['lastcontentauthorid'] = $message['lastauthorid']; $results[$key]['messages'][$msgkey]['lastcontentavatar'] = $userInfo[$message['lastauthorid']]['avatar']; } } if (empty($message['previewtext'])) { $results[$key]['previewtext'] = vB_String::getPreviewText($message['rawtext']); } } } $channelRequests = $this->library->getChannelRequestTypes(); $nodeIds = array(); foreach ($results['request']['messages'] as $message) { if (in_array($message['about'], $channelRequests)) { $nodeIds[] = $message['aboutid']; } } if (!empty($nodeIds)) { $nodesInfo = vB_Library::instance('node')->getNodes($nodeIds); $arrayNodeInfo = array(); foreach ($nodesInfo as $node) { $arrayNodeInfo[$node['nodeid']] = array('title' => $node['title'], 'routeid' => $node['routeid']); } foreach ($results['request']['messages'] as $key => &$val) { if (isset($arrayNodeInfo[$val['aboutid']])) { $val['abouttitle'] = $arrayNodeInfo[$val['aboutid']]['title']; $val['aboutrouteid'] = $arrayNodeInfo[$val['aboutid']]['routeid']; } } } // add notifications $params = array('showdetail' => $receiptDetail, 'perpage' => 5, 'page' => 1, 'sortDir' => "DESC"); $notifications = vB_Library::instance('notification')->fetchNotificationsForCurrentUser($params); $results['notification']['messages'] = $notifications; $results['notification']['count'] = count($notifications); $results['notification']['folderid'] = $folders['systemfolders'][vB_Library_Content_Privatemessage::NOTIFICATION_FOLDER]; return $results; }