/** * * This gets the information needed for a user's profile. Only public information unless this is an admin or the user. */ public function fetchProfileInfo($userid = false) { $options = vB::getDatastore()->getValue('options'); $currentUserid = vB::getCurrentSession()->get('userid'); if (empty($userid)) { $userid = $currentUserid; } else { $userid = intval($userid); } if ($userid < 1) { throw new vB_Exception_Api('invalid_data_w_x_y_z', array($userid, 'userid', __CLASS__, __FUNCTION__)); } $hashKey = 'vBProfileUser_' . $userid; $fastCache = vB_Cache::instance(vB_Cache::CACHE_FAST); $userInfo = $fastCache->read($hashKey); if (empty($userInfo)) { $userInfo = vB_User::fetchUserinfo($userid, array(vB_Api_User::USERINFO_AVATAR, vB_Api_User::USERINFO_PROFILEPIC, vB_Api_User::USERINFO_ADMIN, vB_Api_User::USERINFO_SIGNPIC)); // Some things even admins shouldn't see foreach (array('token', 'scheme', 'secret', 'coppauser', 'securitytoken_raw', 'securitytoken', 'logouthash', 'fbaccesstoken') as $field) { unset($userInfo[$field]); } try { $this->checkHasAdminPermission('canadminusers'); // If this doesn't throw an exception, the other data is visible to an admin. } catch (Exception $e) { if (vB::getCurrentSession()->get('userid') != $userid) { foreach (array('passworddate', 'parentemail', 'logintype', 'ipaddress', 'passworddate', 'email', 'referrerid', 'ipoints', 'infractions', 'warnings', 'infractiongroupids', 'infractiongroupid') as $field) { $userInfo[$field] = ''; } } } /** * * Fields for the user's profile pages */ $assertor = vB::getDbAssertor(); //see if we have a cached userfield $fields = vB_Cache::instance(vB_Cache::CACHE_FAST)->read("userFields_{$userid}"); if ($fields == false) { $fields = $assertor->getRow('vBForum:userfield', array('userid' => $userid)); vB_Cache::instance(vB_Cache::CACHE_FAST)->write("userFields_{$userid}", $fields, 1440, "userData_{$userid}"); } $customFields = array(); if (!empty($fields)) { // Show hidden fields only if the user views his own profile or if it has the permission to see them $hidden = array(0); $showHidden = ($currentUserid == $userid or vB_Api::instanceInternal('user')->hasPermissions('genericpermissions', 'canseehiddencustomfields')); $fieldsInfo = vB::getDatastore()->getValue('profilefield'); if (is_array($fieldsInfo) and array_key_exists('all', $fieldsInfo)) { $fieldsInfo = $fieldsInfo['all']; } else { $fieldsInfo = array(); } foreach ($fieldsInfo as $customField) { if ($customField['hidden'] == 0 or $showHidden) { $catNameString = $customField['profilefieldcategoryid'] ? 'category' . $customField['profilefieldcategoryid'] . '_title' : 'default'; $fieldNameString = 'field' . $customField['profilefieldid'] . '_title'; $customFields[$catNameString][$fieldNameString] = array('val' => $this->getCustomFieldValue($customField, $fields), 'hidden' => $customField['hidden']); } } } $userInfo['customFields'] = $customFields; /** * Check whether user has permission to use friends list (follow users) */ $userInfo['canusefriends'] = vB::getUserContext($userid)->hasPermission('genericpermissions2', 'canusefriends'); $userInfo['canviewmembers'] = vB::getUserContext($userid)->hasPermission('genericpermissions', 'canviewmembers'); /** * * User counts */ $followApi = vB_Api::instanceInternal('follow'); if ($currentUserid == $userid or $userInfo['canusefriends']) { $follows = $followApi->getFollowing($userid); $userInfo['followsCount'] = $follows['paginationInfo']['totalcount']; } $followers = $followApi->getFollowers($userid); $userInfo['followersCount'] = $followers['paginationInfo']['totalcount']; $userInfo['socialGroupsCount'] = 10; if (isset($this->referrals[$userid])) { $referrals = $this->referrals[$userid]; } else { $referrals = $assertor->getRow('vBForum:getReferralsCount', array('userid' => $userid)); $this->referrals[$userid] = $referrals; } $userInfo['birthdayTimestamp'] = 0; $userInfo['referralsCount'] = $referrals['referrals']; if ($userInfo['birthday_search']) { list($year, $month, $day) = explode("-", $userInfo['birthday_search']); $userInfo['birthdayTimestamp'] = mktime(0, 0, 0, $month, $day, $year); $userInfo['age'] = date("md") < $month . $day ? date("Y") - $year - 1 : date("Y") - $year; } /** * Get vms info */ $vms = $assertor->getRows('vBForum:node', array(vB_dB_Query::TYPE_KEY => vB_dB_Query::QUERY_SELECT, 'setfor' => $userid), array('field' => 'publishdate', 'direction' => vB_dB_Query::SORT_DESC)); vB_Library_Content::writeToCache($vms, vB_Library_Content::CACHELEVEL_NODE); $userInfo['vmCount'] = count($vms); $userInfo['vmMostRecent'] = $userInfo['vmCount'] ? $vms[0]['publishdate'] : 0; /** * Let's get posts per day */ $timeIn = (vB::getRequest()->getTimeNow() - $userInfo['joindate']) / (24 * 60 * 60); if ($timeIn >= 1 and $userInfo['posts'] > 0) { $userInfo['postPerDay'] = vb_number_format($userInfo['posts'] / $timeIn, 2); } else { $userInfo['postPerDay'] = $userInfo['posts']; } $fastCache->write($hashKey, $userInfo, 1440, 'userChg_' . $userid); } // add current user flags // if user is the profile owner.. $userInfo['showAvatar'] = 1; if ($currentUserid == $userid) { if (vB::getUserContext()->hasPermission('genericpermissions', 'canuseavatar')) { $userInfo['canuseavatar'] = 1; $userInfo['avatarmaxwidth'] = vB::getUserContext()->getLimit('avatarmaxwidth'); $userInfo['avatarmaxheight'] = vB::getUserContext()->getLimit('avatarmaxheight'); $userInfo['avatarmaxsize'] = vB::getUserContext()->getLimit('avatarmaxsize') / 1024; } else { $userInfo['canuseavatar'] = 0; } //Are there any default avatars this user could assign? $avatars = vB_Api::instanceInternal('profile')->getDefaultAvatars(); $userInfo['defaultAvatarCount'] = count($avatars); if ($userInfo['defaultAvatarCount'] or $userInfo['canuseavatar'] > 0) { $userInfo['showAvatarOptions'] = 1; } else { $userInfo['showAvatarOptions'] = 0; } if ($userInfo['profilepic']) { if ($options['usefileavatar']) { $userInfo['profilepicturepath'] = $options['bburl'] . '/' . $options['profilepicurl'] . "/profilepic{$currentUserid}" . '_' . $userInfo['profilepicrevision'] . '.gif'; } else { $userInfo['profilepicturepath'] = $options['bburl'] . "/image.php?u={$currentUserid}&type=profile&dateline=" . $userInfo['profilepicdateline']; } } } else { $userInfo['canuseavatar'] = $userInfo['showAvatarOptions'] = 0; //Check the privacy settings and see if this user has hidden his if ($userInfo['privacy_options'] and vB::getUserContext($userid)->hasPermission('usercsspermissions', 'caneditprivacy')) { switch ($userInfo['privacy_options']['profile_picture']) { case 1: //visible only if the current user is a subscriber. if ($currentUserid == 0 or vB_Api::instanceInternal('follow')->isFollowingUser($userid) != vB_Api_Follow::FOLLOWING_YES) { $userInfo['showAvatar'] = 0; } break; case 2: //visible only if the current user is a registered user. if ($currentUserid == 0) { $userInfo['showAvatar'] = 0; } break; } // switch } $userInfo['profilepicturepath'] = ''; } $this->setCurrentUserFlags($userInfo); // Add online status require_once DIR . '/includes/functions_bigthree.php'; fetch_online_status($userInfo); return $userInfo; }
/** * See base class for information */ public function getIndexableFromNode($node, $include_attachments = true) { $indexableContent = parent::getIndexableFromNode($node, $include_attachments); if (!empty($node['description'])) { $indexableContent['description'] = $node['description']; } return $indexableContent; }
/** * Undelete a set of nodes * @param array $nodeids * @param boolean is rebuild needed * @throws vB_Exception_Api * @return array - the nodeids that have been deleted */ public function undeleteNodes($nodeids, $needRebuild = false) { if (empty($nodeids)) { return false; } $errors = array(); $events = array(); $loginfo = array(); $counts = $updates = array(); $nodeids = array_unique($nodeids); $assertor = vB::getDbAssertor(); $result = $assertor->assertQuery('vBForum:node', array('nodeid' => $nodeids, 'deleteuserid' => 0, 'deletereason' => '', 'unpublishdate' => 0, 'showpublished' => 1, vB_db_Query::TYPE_KEY => vB_db_Query::QUERY_UPDATE)); if (!empty($result['errors'])) { $errors[] = $result['errors']; } $searchAPI = vB_Api::instanceInternal('Search'); foreach ($nodeids as $nodeid) { $events[] = $nodeid; $result = $this->publishChildren($nodeid); if (!empty($result['errors'])) { $errors[] = $result['errors']; } // Clear cache for this node or user post count won't update vB_Cache::allCacheEvent('nodeChg_' . $nodeid); $node = $this->getNode($nodeid); // Update user post count (un(soft)delete) vB_Library_Content::getContentLib($node['contenttypeid'])->incrementUserPostCount($node); $loginfo[] = array('nodeid' => $node['nodeid'], 'nodetitle' => $node['title'], 'nodeusername' => $node['authorname'], 'nodeuserid' => $node['userid']); $parents = $this->fetchClosureParent($nodeid); foreach ($parents as $parent) { $nodeInfo = $this->getNodeBare($parent['parent']); if ($nodeInfo['contenttypeid'] == $this->channelTypeId) { $result = $this->fixNodeLast($parent['parent']); } else { $result = $assertor->assertQuery('vBForum:updateLastData', array('parentid' => $parent['parent'], 'timenow' => vB::getRequest()->getTimeNow())); } if (!empty($result['errors'])) { $errors[] = $result['errors']; } switch ($parent['depth']) { case 0: // Actual node. vB_Node::fixNodeCount($parent['parent']); break; case 1: // Immediate parent. $parentinfo = $this->getNodeBare($parent['parent']); $counts = array('totalcount' => $parentinfo['totalcount'], 'totalunpubcount' => $parentinfo['totalunpubcount']); vB_Node::fixNodeCount($parent['parent']); $parentinfo = $this->getNodeBare($parent['parent']); $counts = array('totalcount' => $parentinfo['totalcount'] - $counts['totalcount'], 'totalunpubcount' => $parentinfo['totalunpubcount'] - $counts['totalunpubcount']); break; default: // Higher parents. $updates['totalcount'][$parent['parent']] = $counts['totalcount']; $updates['totalunpubcount'][$parent['parent']] = $counts['totalunpubcount']; break; } } $assertor->assertQuery('vBForum:updateNodeTotals', array(vB_dB_Query::TYPE_KEY => vB_dB_Query::QUERY_METHOD, 'updates' => $updates)); $searchAPI->attributeChanged($nodeid); } $searchAPI->purgeCacheForCurrentUser(); if ($needRebuild) { vB::getUserContext()->rebuildGroupAccess(); vB_Channel::rebuildChannelTypes(); } $this->clearCacheEvents($nodeids); $this->clearChildCache($nodeids); if (!empty($errors)) { return array('errors' => $errors); } vB_Library_Admin::logModeratorAction($loginfo, 'node_restored_by_x'); return $nodeids; }
function exec_digest($type = 2) { // type = 2 : daily // type = 3 : weekly $lastdate = mktime(0, 0); // midnight today if ($type == 2) { // daily // yesterday midnight $lastdate -= 24 * 60 * 60; } else { // weekly // last week midnight $lastdate -= 7 * 24 * 60 * 60; } if (trim(vB::getDatastore()->getOption('globalignore')) != '') { $coventry = preg_split('#\\s+#s', vB::getDatastore()->getOption('globalignore'), -1, PREG_SPLIT_NO_EMPTY); } else { $coventry = array(); } require_once DIR . '/includes/class_bbcode_alt.php'; $vbulletin =& vB::get_registry(); $plaintext_parser = new vB_BbCodeParser_PlainText($vbulletin, fetch_tag_list()); vB_Mail::vbmailStart(); $bf_misc_useroptions = vB::get_datastore()->get_value('bf_misc_useroptions'); $bf_ugp_genericoptions = vB::get_datastore()->get_value('bf_ugp_genericoptions'); $bf_ugp_forumpermissions = vB::get_datastore()->get_value('bf_ugp_forumpermissions'); // we want to fetch all language records at once and using cache if possible $defaultLanguage = false; $languageIds = array(); // get new threads (Topic Subscription) $threads = vB::getDbAssertor()->getRows('getNewThreads', array('dstonoff' => $bf_misc_useroptions['dstonoff'], 'hasaccessmask' => $bf_misc_useroptions['hasaccessmask'], 'isnotbannedgroup' => $bf_ugp_genericoptions['isnotbannedgroup'], 'lastdate' => intval($lastdate))); // grab all forums / subforums for given subscription (Channel Subscription) $forums = vB::getDbAssertor()->assertQuery('getNewForums', array('dstonoff' => $bf_misc_useroptions['dstonoff'], 'hasaccessmask' => $bf_misc_useroptions['hasaccessmask'], 'type' => intval($type), 'lastdate' => intval($lastdate), 'channelcontenttype' => vB_Api::instanceInternal('contenttype')->fetchContentTypeIdFromClass('Channel'), 'isnotbannedgroup' => $bf_ugp_genericoptions['isnotbannedgroup'])); // Let's see which languageids we wanna fetch foreach ($threads as $thread) { if ($thread['languageid'] == 0) { if (!$defaultLanguage) { $defaultLanguage = intval(vB::getDatastore()->getOption('languageid')); $languageIds[] = $defaultLanguage; } } else { $languageIds[] = $thread['languageid']; } } foreach ($forums as $forum) { if ($forum['languageid'] == 0) { if (!$defaultLanguage) { $defaultLanguage = intval(vB::getDatastore()->getOption('languageid')); $languageIds[] = $defaultLanguage; } } else { $languageIds[] = $forum['languageid']; } } // fetch languages $languages = vB_Library::instance('language')->fetchLanguages($languageIds); // process threads foreach ($threads as $thread) { $postbits = ''; // Make sure user have correct email notification settings. if ($thread['emailnotification'] != $type) { continue; } if ($thread['lastauthorid'] != $thread['userid'] and in_array($thread['lastauthorid'], $coventry)) { continue; } $usercontext = vB::getUserContext($thread['userid']); if (!$usercontext->getChannelPermission('forumpermissions', 'canview', $thread['nodeid']) or !$usercontext->getChannelPermission('forumpermissions', 'canviewthreads', $thread['nodeid']) or $thread['lastauthorid'] != $thread['userid'] and !$usercontext->getChannelPermission('forumpermissions', 'canviewothers', $thread['nodeid'])) { continue; } $langInfo =& $languages[$thread['languageid']]; $userinfo = array('lang_locale' => $langInfo['locale'], 'dstonoff' => $thread['dstonoff'], 'timezoneoffset' => $thread['timezoneoffset']); $thread['lastreplydate'] = vbdate($langInfo['dateoverride'] ? $langInfo['dateoverride'] : vB::getDatastore()->getOption('dateformat'), $thread['lastcontent'], false, true, true, false, $userinfo); $thread['lastreplytime'] = vbdate($langInfo['timeoverride'] ? $langInfo['timeoverride'] : vB::getDatastore()->getOption('timeformat'), $thread['lastcontent'], false, true, true, false, $userinfo); $thread['htmltitle'] = unhtmlspecialchars($thread['htmltitle']); $thread['username'] = unhtmlspecialchars($thread['username']); $thread['postusername'] = unhtmlspecialchars($thread['authorname']); $thread['lastposter'] = unhtmlspecialchars($thread['lastcontentauthor']); $thread['newposts'] = 0; //not currently used and probably needs rethinking, but don't want to remove until this code gets rewritten //$thread['auth'] = md5($thread['userid'] . $thread['subscribediscussionid'] . $thread['secret'] . vB_Request_Web::$COOKIE_SALT); if ($thread['prefixid']) { // need prefix in correct language $phraseAux = vB_Api::instanceInternal('phrase')->fetch(array("prefix_{$thread['prefixid']}_title_plain")); $thread['prefix_plain'] = $phraseAux["prefix_{$thread['prefixid']}_title_plain"] . ' '; } else { $thread['prefix_plain'] = ''; } // Note: closure.depth = 1 on the where clause means getNewPosts only grabs replies, not comments. // get posts $posts = vB::getDbAssertor()->getRows('getNewPosts', array('threadid' => intval($thread['nodeid']), 'lastdate' => intval($lastdate))); // compile $haveothers = false; foreach ($posts as $post) { if ($post['userid'] != $thread['userid'] and in_array($post['userid'], $coventry)) { continue; } if ($post['userid'] != $thread['userid']) { $haveothers = true; } $thread['newposts']++; $post['htmltitle'] = unhtmlspecialchars($post['htmltitle']); $post['postdate'] = vbdate($langInfo['dateoverride'] ? $langInfo['dateoverride'] : vB::getDatastore()->getOption('dateformat'), $post['publishdate'], false, true, true, false, $userinfo); $post['posttime'] = vbdate($langInfo['timeoverride'] ? $langInfo['timeoverride'] : vB::getDatastore()->getOption('timeformat'), $post['publishdate'], false, true, true, false, $userinfo); $post['postusername'] = unhtmlspecialchars($post['authorname']); $plaintext_parser->set_parsing_language($thread['languageid']); $contentAPI = vB_Library_Content::getContentApi($post['contenttypeid']); $contents = $contentAPI->getContent($post['nodeid']); $post['pagetext'] = $plaintext_parser->parse($contents[$post['nodeid']]['rawtext'], $thread['parentid']); $postlink = vB5_Route::buildUrl($post['routeid'] . '|bburl', array('nodeid' => $post['nodeid'])); /*$postlink = fetch_seo_url('thread|nosession|bburl', array('threadid' => $thread['nodeid'], 'title' => htmlspecialchars_uni($thread['title']))) . "#post$post[nodeid]";*/ // Legacy Hook 'digest_thread_post' Removed // $phrases = vB_Api::instanceInternal('phrase')->fetch('digestpostbit', $thread['languageid']); $postbits .= sprintf($phrases['digestpostbit'], $post['htmltitle'], $postlink, $post['postusername'], $post['postdate'], $post['posttime'], $post['pagetext']); } // Legacy Hook 'digest_thread_process' Removed // // Don't send an update if the subscriber is the only one who posted in the thread. if ($haveothers) { // make email // magic vars used by the phrase eval $threadlink = vB5_Route::buildUrl($thread['routeid'] . '|fullurl', array('nodeid' => $thread['nodeid'])); //$threadlink = fetch_seo_url('thread|nosession|bburl', array('threadid' => $thread['threadid'], 'title' => htmlspecialchars_uni($thread['title']))); //this link probably doesn't do what the author thinks it does, need to validate. $unsubscribelink = vB5_Route::buildUrl('subscription|fullurl', array('tab' => 'subscriptions', 'userid' => $thread['userid'])); $maildata = vB_Api::instanceInternal('phrase')->fetchEmailPhrases('digestthread', array($thread['username'], $thread['prefix_plain'], $thread['htmltitle'], $thread['postusername'], $thread['newposts'], $thread['lastposter'], $threadlink, $postbits, vB::getDatastore()->getOption('bbtitle'), $unsubscribelink), array($thread['prefix_plain'], $thread['htmltitle']), $thread['languageid']); vB_Mail::vbmail($thread['email'], $maildata['subject'], $maildata['message']); } } unset($plaintext_parser); // process forums foreach ($forums as $forum) { $langInfo =& $languages[$forum['languageid']]; $userinfo = array('lang_locale' => $langInfo['locale'], 'dstonoff' => $forum['dstonoff'], 'timezoneoffset' => $forum['timezoneoffset']); $newthreadbits = ''; $newthreads = 0; $updatedthreadbits = ''; $updatedthreads = 0; $forum['username'] = unhtmlspecialchars($forum['username']); $forum['title_clean'] = unhtmlspecialchars($forum['title_clean']); //not currently used and probably needs rethinking, but don't want to remove until this code gets rewritten //$forum['auth'] = md5($forum['userid'] . $forum['subscribeforumid'] . $forum['secret'] . vB_Request_Web::$COOKIE_SALT); $threads = vB::getDbAssertor()->assertQuery('fetchForumThreads', array('forumid' => intval($forum['forumid']), 'lastdate' => intval($lastdate))); foreach ($threads as $thread) { if ($thread['postuserid'] != $forum['userid'] and in_array($thread['postuserid'], $coventry)) { continue; } // allow those without canviewthreads to subscribe/receive forum updates as they contain not post content $usercontext = vB::getUserContext($thread['userid']); if (!$usercontext->getChannelPermission('forumpermissions', 'canview', $thread['nodeid']) or $thread['lastauthorid'] != $thread['userid'] and !$usercontext->getChannelPermission('forumpermissions', 'canviewothers', $thread['nodeid'])) { continue; } $thread['forumhtmltitle'] = unhtmlspecialchars($thread['forumhtmltitle']); $thread['lastreplydate'] = vbdate($langInfo['dateoverride'] ? $langInfo['dateoverride'] : vB::getDatastore()->getOption('dateformat'), $thread['lastpost'], false, true, true, false, $userinfo); $thread['lastreplytime'] = vbdate($langInfo['timeoverride'] ? $langInfo['timeoverride'] : vB::getDatastore()->getOption('timeformat'), $thread['lastpost'], false, true, true, false, $userinfo); $thread['htmltitle'] = unhtmlspecialchars($thread['htmltitle']); $thread['postusername'] = unhtmlspecialchars($thread['postusername']); $thread['lastposter'] = unhtmlspecialchars($thread['lastposter']); if ($thread['prefixid']) { // need prefix in correct language $phraseAux = vB_Api::instanceInternal('phrase')->fetch(array("prefix_{$thread['prefixid']}_title_plain")); $thread['prefix_plain'] = $phraseAux["prefix_{$thread['prefixid']}_title_plain"] . ' '; } else { $thread['prefix_plain'] = ''; } $threadlink = vB5_Route::buildUrl($thread['routeid'] . '|fullurl', array('nodeid' => $thread['threadid'])); // Legacy Hook 'digest_forum_thread' Removed // $maildata = vB_Api::instanceInternal('phrase')->fetchEmailPhrases('digestthreadbit', array($thread['prefix_plain'], $thread['htmltitle'], $threadlink, $thread['forumhtmltitle'], $thread['postusername'], $thread['lastreplydate'], $thread['lastreplytime']), array(), $forum['languageid']); if ($thread['dateline'] > $lastdate) { // new thread $newthreads++; $newthreadbits .= $maildata['message']; } else { $updatedthreads++; $updatedthreadbits .= $maildata['message']; } } // Legacy Hook 'digest_forum_process' Removed // if (!empty($newthreads) or !empty($updatedthreadbits)) { // make email // magic vars used by the phrase eval //$forumlink = fetch_seo_url('forum|nosession|bburl', $forum); $forumlink = vB5_Route::buildUrl($forum['routeid'] . '|fullurl', array('nodeid' => $forum['forumid'])); //this link probably doesn't do what the author thinks it does. Need to validate. $unsubscribelink = vB5_Route::buildUrl('subscription|fullurl', array('tab' => 'subscriptions', 'userid' => $forum['userid'])); $maildata = vB_Api::instanceInternal('phrase')->fetchEmailPhrases('digestforum', array($forum['username'], $forum['title_clean'], $newthreads, $updatedthreads, $forumlink, $newthreadbits, $updatedthreadbits, vB::getDatastore()->getOption('bbtitle'), $unsubscribelink), array($forum['title_clean']), $forum['languageid']); vB_Mail::vbmail($forum['email'], $maildata['subject'], $maildata['message'], true); } } // ******* Social Group Digests ********** $bf_misc_socnet = vB::get_datastore()->get_value('bf_misc_socnet'); if (vB::getDatastore()->getOption('socnet') & $bf_misc_socnet['enable_groups']) { require_once DIR . '/includes/functions_socialgroup.php'; /** @todo review this part*/ /** @todo if we reenable this code, we need to prefetch language records as for threads and forums */ /* $groups = vB::getDbAssertor()->assertQuery('fetchSocialGroupDigests', array( 'dstonoff' => $bf_misc_useroptions['dstonoff'], 'hasaccessmask' => $bf_misc_useroptions['hasaccessmask'], 'languageid' => intval(vB::getDatastore()->getOption('languageid')), 'type' => $type == 2 ? 'daily' : 'weekly', 'lastdate' => intval($lastdate), 'isnotbannedgroup' => $bf_ugp_genericoptions['isnotbannedgroup'] )); foreach ($groups as $group) { $userperms = cache_permissions($group, false); if (!($userperms['forumpermissions'] & $vbulletin->bf_ugp_forumpermissions['canview']) OR !($userperms['socialgrouppermissions'] & $vbulletin->bf_ugp_socialgrouppermissions['canviewgroups']) ) { continue; } if ($group['options'] & $vbulletin->bf_misc_socialgroupoptions['join_to_view'] AND $vbulletin->options['sg_allow_join_to_view']) { if ($group['membertype'] != 'member' AND !($userperms['socialgrouppermissions'] & $vbulletin->bf_ugp_socialgrouppermissions['canalwayspostmessage']) AND !($userperms['socialgrouppermissions'] & $vbulletin->bf_ugp_socialgrouppermissions['canalwascreatediscussion']) ) { continue; } } $userinfo = array( 'lang_locale' => $group['lang_locale'], 'dstonoff' => $group['dstonoff'], 'timezoneoffset' => $group['timezoneoffset'], ); $new_discussion_bits = ''; $new_discussions = 0; $updated_discussion_bits = ''; $updated_discussions = 0; $group['username'] = unhtmlspecialchars($group['username']); $group['name'] = unhtmlspecialchars($group['name']); $discussions = vB::getDbAssertor()->assertQuery('fetchGroupDiscussions', array( 'groupid' => $group['groupid'], 'lastdate' => intval($lastdate) )); foreach ($discussions as $discussion) { $discussion['lastreplydate'] = vbdate($group['lang_dateoverride'] ? $group['lang_dateoverride'] : $vbulletin->options['default_dateformat'], $discussion['lastpost'], false, true, true, false, $userinfo); $discussion['lastreplytime'] = vbdate($group['lang_timeoverride'] ? $group['lang_timeoverride'] : $vbulletin->options['default_timeformat'], $discussion['lastpost'], false, true, true, false, $userinfo); $discussion['title'] = unhtmlspecialchars($discussion['title']); $discussion['postusername'] = unhtmlspecialchars($discussion['postusername']); $discussion['lastposter'] = unhtmlspecialchars($discussion['lastposter']); // Legacy Hook 'digest_group_discussion' Removed // //magic variables that will be picked up by the phrase eval $discussionlink = fetch_seo_url('groupdiscussion', $discussion); $maildata = vB_Api::instanceInternal('phrase') ->fetchEmailPhrases('digestgroupbit', array($discussion['htmltitle'], $discussionlink, $group['name'], $discussion['postusername'], $discussion['lastreplydate'], $discussion['lastreplytime']), array(), $group['languageid']); if ($discussion['dateline'] > $lastdate) { // new discussion $new_discussions++; $new_discussion_bits .= $maildata['message']; } else { $updated_discussions++; $updated_discussion_bits .= $maildata['message']; } } // Legacy Hook 'digest_group_process' Removed // if (!empty($new_discussion_bits) OR !empty($updated_discussion_bits)) { //magic variables that will be picked up by the phrase eval $grouplink = fetch_seo_url('group|nosession|bburl', $group); // make email $maildata = vB_Api::instanceInternal('phrase') ->fetchEmailPhrases('digestgroup', array($group['username'], $group['name'], $new_discussions, $updated_discussions, $grouplink, $new_discussion_bits, $updated_discussion_bits, $vbulletin->options['bbtitle']), array($group['name']), $group['languageid']); vB_Mail::vbmail($group['email'], $maildata['subject'], $maildata['message']); } } */ } vB_Mail::vbmailEnd(); }
protected function sendLegacyEmailNotification($data) { $options = vB::getDatastore()->getValue('options'); if (isset($options['enableemail']) and !$options['enableemail']) { return; // email notifications are globally disabled } /* * Save some data for this page load. Since we can potentially fetch a bunch of the same * data over and over if multiple users are getting notifications about the same content * that was just created, let's get rid of the redundant calls when this function is called * in a loop. * Todo: we should write a bulk-send-email-notification function * * I can't actually think of a case where a single content creation that triggers a number * of email notifications will have different contentnodeid in its group of notifications, * but let's just be safe and allow for that possibility. */ static $recipientIndependentDataArray; $contentnodeid = isset($data['contentnodeid']) ? $data['contentnodeid'] : 0; if (!empty($contentnodeid) and empty($recipientIndependentDataArray[$contentnodeid])) { //we need to load this using the correct library class or things get weird. //note that if we load it from cache here it will be in the local memory cache //when we load the full content and we won't do it twice. $cached = vB_Library_Content::fetchFromCache(array($contentnodeid), vB_Library_Content::CACHELEVEL_FULLCONTENT); if (isset($cached['found'][$contentnodeid])) { $contenttypeid = $cached['found'][$contentnodeid]['contenttypeid']; } else { $row = $this->assertor->getRow('vBForum:node', array(vB_dB_Query::TYPE_KEY => vB_dB_Query::QUERY_SELECT, vB_dB_Query::COLUMNS_KEY => array('contenttypeid'), 'nodeid' => $contentnodeid)); $contenttypeid = $row['contenttypeid']; } $contentLib = vB_Library_Content::getContentLib($contenttypeid); $currentNode = $contentLib->getContent($contentnodeid); $currentNode = $currentNode[$contentnodeid]; /* * These data are static & independent of the recipient of this message, assuming that * we're not trying to hide any data. If we are going to check permissions for each * recipient, we should probably check view perms & remove from the recipients list * BEFORE we ever get to this function, and just not send them a notification instead of * hiding data. */ $recipientIndependentDataArray[$contentnodeid] = array('authorname' => $currentNode['userinfo']['username'], 'nodeurl' => vB5_Route::buildUrl('node|fullurl', array('nodeid' => $contentnodeid)), 'previewtext' => vB_String::getPreviewText($currentNode['rawtext']), 'nodeid' => $currentNode['nodeid'], 'starter' => $currentNode['starter'], 'startertitle' => isset($currentNode['startertitle']) ? $currentNode['startertitle'] : '', 'parentid' => $currentNode['parentid'], 'channeltitle' => $currentNode['channeltitle'], 'channeltype' => $currentNode['channeltype']); } // additional data used for subscription notifications if (isset($data['subscriptionnodeid'])) { $subId = $data['subscriptionnodeid']; if (!isset($recipientIndependentDataArray[$contentnodeid]['add_sub_data'][$subId])) { //we need to load this using the correct library class or things get weird. //note that if we load it from cache here it will be in the local memory cache //when we load the full content and we won't do it twice. $cached = vB_Library_Content::fetchFromCache(array($subId), vB_Library_Content::CACHELEVEL_FULLCONTENT); if (isset($cached['found'][$subId])) { $contenttypeid = $cached['found'][$subId]['contenttypeid']; } else { $row = $this->assertor->getRow('vBForum:node', array(vB_dB_Query::TYPE_KEY => vB_dB_Query::QUERY_SELECT, vB_dB_Query::COLUMNS_KEY => array('contenttypeid'), 'nodeid' => $subId)); $contenttypeid = $row['contenttypeid']; } if ($contenttypeid) { $contentLib = vB_Library_Content::getContentLib($contenttypeid); $subbedNode = $contentLib->getContent($subId); $subbedNode = $subbedNode[$subId]; $channelTypeId = vB_Types::instance()->getContentTypeID('vBForum_Channel'); if ($subbedNode['contenttypeid'] == $channelTypeId) { $nodetype = 'channel'; } else { $nodetype = 'post'; } $recipientIndependentDataArray[$contentnodeid]['add_sub_data'][$subId] = array('title' => $subbedNode['title'], 'nodetype' => $nodetype); } } // We only expect channeltype_forum, channeltype_article, channeltype_blog, channeltype_group, but // a channeltype_<> phrase for each of vB_Channel::$channelTypes should exist, so we can do this $channeltype = "channeltype_" . $recipientIndependentDataArray[$contentnodeid]['channeltype']; $nodetype = $recipientIndependentDataArray[$contentnodeid]['add_sub_data'][$subId]['nodetype']; // While phrases are dependent on languageid, it's not really recipient or userid // dependent and is shared/static among different recipients, so let's keep track // of them. if (!isset($phrases[$data['languageid']])) { $phrases[$data['languageid']] = vB_Api::instanceInternal('phrase')->fetch(array($channeltype, $nodetype), $data['languageid']); } } // keep track of the about strings that are for "content" notifications $temporary = array(vB_Library_Content_Privatemessage::NOTIFICATION_TYPE_REPLY, vB_Library_Content_Privatemessage::NOTIFICATION_TYPE_COMMENT, vB_Library_Content_Privatemessage::NOTIFICATION_TYPE_THREADCOMMENT, vB_Library_Content_Privatemessage::NOTIFICATION_TYPE_SUBSCRIPTION, vB_Library_Content_Privatemessage::NOTIFICATION_TYPE_USERMENTION); $contentNotificationAboutStrings = array(); foreach ($temporary as $aboutString) { $contentNotificationAboutStrings[$aboutString] = $aboutString; } if ($data['about'] == vB_Library_Content_Privatemessage::NOTIFICATION_TYPE_VM) { // A VM should have only 1 recipient, so no good reason to cache this like other URLs. Also // VMs don't seem to work with the /node/ route, so we can't rely on that. $vmURL = vB5_Route::buildUrl('visitormessage|fullurl', array('nodeid' => $contentnodeid)); $maildata = vB_Api::instanceInternal('phrase')->fetchEmailPhrases('visitormessage', array($data['username'], $recipientIndependentDataArray[$contentnodeid]['authorname'], $vmURL, $recipientIndependentDataArray[$contentnodeid]['previewtext'], $options['bbtitle']), array(), $data['languageid']); } elseif ($data['about'] == vB_Library_Content_Privatemessage::NOTIFICATION_TYPE_VOTE) { // Vote notifications have their own section because their phrases aren't in the same format as the others // Since a vote doesn't have a node associated with it, we don't have a "currentnode" data. // Note that the poll library sets aboutid & contentid both to the nodeid of the poll-post $maildata = vB_Api::instanceInternal('phrase')->fetchEmailPhrases('vote', array($data['username'], vB_Api::instanceInternal('user')->fetchUserName(vB::getCurrentSession()->get('userid')), $recipientIndependentDataArray[$contentnodeid]['nodeurl'], $options['bbtitle']), array($recipientIndependentDataArray[$contentnodeid]['startertitle']), $data['languageid']); } elseif (isset($contentNotificationAboutStrings[$data['about']])) { // Normally the subject would contain the topic title, but if it's a subscription let's pass in the // title of the actual subscription node whether it's a channel, thread, blog etc. $emailSubjectVars = array($recipientIndependentDataArray[$contentnodeid]['startertitle']); // Since subscription email subjects don't have a title, we'll include the title in // the email body as a 7th variable. $emailBodyVars = array($data['username'], $recipientIndependentDataArray[$contentnodeid]['authorname'], $recipientIndependentDataArray[$contentnodeid]['nodeurl'], $recipientIndependentDataArray[$contentnodeid]['previewtext'], $options['bbtitle'], $options['frontendurl'] . '/member/' . $data['userid'] . '/subscriptions'); // blog & social groups have special phrases, unless it's a subscription notification or a user mention. // If the latter, just send the generic subscription or user mention email. // As of 5.1.4, we do not expect to hit this block for blogs, because the people who *would* // receive this (the blog poster) are automatically subscribed to the blog channel, and // subscription notifications always trump other types of notifications. See VBV-13466 if ($recipientIndependentDataArray[$contentnodeid]['channeltype'] == 'blog' and $data['about'] != vB_Library_Content_Privatemessage::NOTIFICATION_TYPE_SUBSCRIPTION and $data['about'] != vB_Library_Content_Privatemessage::NOTIFICATION_TYPE_USERMENTION) { $mailPhrase = 'comment_blogentry'; } else { if ($recipientIndependentDataArray[$contentnodeid]['channeltype'] == 'group' and $data['about'] != vB_Library_Content_Privatemessage::NOTIFICATION_TYPE_SUBSCRIPTION and $data['about'] != vB_Library_Content_Privatemessage::NOTIFICATION_TYPE_USERMENTION) { $mailPhrase = 'comment_grouptopic'; } else { switch ($data['about']) { case vB_Library_Content_Privatemessage::NOTIFICATION_TYPE_REPLY: $mailPhrase = 'reply_thread'; break; case vB_Library_Content_Privatemessage::NOTIFICATION_TYPE_COMMENT: $mailPhrase = 'comment_post'; break; case vB_Library_Content_Privatemessage::NOTIFICATION_TYPE_THREADCOMMENT: $mailPhrase = 'comment_thread'; break; case vB_Library_Content_Privatemessage::NOTIFICATION_TYPE_SUBSCRIPTION: $mailPhrase = 'subscribed_thread'; // $subId, $nodetype, $channeltype aer set above as long as 'subscriptionnodeid' was passed in. if (!empty($subId)) { // A new post in your {2} {3} subscription: {1} $emailSubjectVars = array($recipientIndependentDataArray[$contentnodeid]['add_sub_data'][$subId]['title'], $phrases[$data['languageid']][$channeltype], $phrases[$data['languageid']][$nodetype]); // Since we removed the starter title from the subject, add it to the message. $emailBodyVars[] = $recipientIndependentDataArray[$contentnodeid]['startertitle']; } break; case vB_Library_Content_Privatemessage::NOTIFICATION_TYPE_USERMENTION: $mailPhrase = 'usermention_post'; // subject: <username> mentioned you in <content item title> $emailSubjectVars = array($recipientIndependentDataArray[$contentnodeid]['authorname'], $recipientIndependentDataArray[$contentnodeid]['startertitle']); break; default: if ($recipientIndependentDataArray[$contentnodeid]['starter'] == $recipientIndependentDataArray[$contentnodeid]['parentid']) { $mailPhrase = 'reply_thread'; } else { $mailPhrase = 'reply_post'; } break; } } } $maildata = vB_Api::instanceInternal('phrase')->fetchEmailPhrases($mailPhrase, $emailBodyVars, $emailSubjectVars, $data['languageid']); } elseif ($data['about'] == vB_Library_Content_Privatemessage::NOTIFICATION_TYPE_RATE) { $node = $recipientIndependentDataArray[$contentnodeid]; // It doesn't make sense to call blog & article starters as "threads", so just go with "post" if ($node['nodeid'] == $node['starter'] and ($node['channeltype'] == 'forum' or $node['channeltype'] == 'group')) { $mailPhrase = 'like_thread'; } else { $mailPhrase = 'like_post'; } $maildata = vB_Api::instanceInternal('phrase')->fetchEmailPhrases($mailPhrase, array($data['username'], vB_Api::instanceInternal('user')->fetchUserName($data['senderid']), $node['nodeurl'], $options['bbtitle']), array($options['bbtitle'])); } elseif ($data['about'] == vB_Library_Content_Privatemessage::NOTIFICATION_TYPE_FOLLOW) { // the use of vB5_Route::buildUrl() below should be ok performant wise, because we're not expecting to send a bulk email for this // notification type. We should avoid hacky hacks (see above in the content notification section for avoiding vB5_Route::buildUrl() // to each recipient's subscription page) when forgivable. $maildata = vB_Api::instanceInternal('phrase')->fetchEmailPhrases('follow_approve', array($data['username'], vB_Api::instanceInternal('user')->fetchUserName($data['senderid']), vB5_Route::buildUrl('profile|fullurl', array('userid' => $data['senderid'], 'tab' => 'subscribed')), $options['bbtitle']), array($options['bbtitle'])); } elseif ($data['about'] == vB_Library_Content_Privatemessage::NOTIFICATION_TYPE_FOLLOWING) { /* Per dev chat discussion, this never existed. Since there doesn't seem to be a strong customer request for this, I'm gonna leave it out. I'm leaving this section in so that it's trivial to add in the future. */ $maildata = array(); } else { // We don't know how to handle this. $maildata = array(); } if (!empty($data['email']) and !empty($maildata)) { // Send the email vB_Mail::vbmail($data['email'], $maildata['subject'], $maildata['message'], false); } }
/** returns the category list- direct children of the social group channel * * @return mixed array of nodeid => title */ public function getCategories() { $cache = vB_Cache::instance(vB_Cache::CACHE_FAST); $categories = $cache->read('vbSGChannels'); if (!empty($categories)) { return $categories; } $sgChannel = $this->getSGChannel(); $categories = vB::getDbAssertor()->getRows('vBForum:node', array(vB_dB_Query::TYPE_KEY => vB_dB_Query::QUERY_SELECT, 'parentid' => $sgChannel, 'contenttypeid' => vB_Types::instance()->getContentTypeID('vBForum_Channel')), 'title', 'nodeid'); $return = array(); $userContext = vB::getUserContext(); $events = array(); vB_Library::instance('node')->fetchClosureParent(array_keys($categories)); foreach ($categories as $category) { if ($userContext->getChannelPermission('forumpermissions', 'canview', $category['nodeid'], false, $sgChannel)) { $return[$category['nodeid']] = array('title' => $category['title'], 'htmltitle' => $category['htmltitle'], 'routeid' => $category['routeid'], 'content' => $category['content']); $events[] = 'routeChg_' . $category['routeid']; $events[] = 'nodeChg_' . $category['content']; } vB_Library_Content::writeToCache(array($category), vB_Library_Content::CACHELEVEL_NODE); } $cache->write('vbSGChannels', $return, 1440, $events); return $return; }
/** * Determines if the logged-in user can infract the (author of) the given node * * @param int Node ID * @param array Node record, if you have it * * @return bool The node (user) can be infracted by current user (or not) */ public function canInfractNode($nodeid, array $node = null) { $nodeid = (int) $nodeid; $infractionContentTypeId = null; if ($infractionContentTypeId === null) { $infractionContentTypeId = vB_Types::instance()->getContentTypeID('vBForum_Infraction'); } if ($node === null or !is_array($node)) { // needs getNodeFullContent to pull the node[infraction] field $nodeBare = vB_Library::instance('node')->getNodeBare($nodeid); $node = vB_Library_Content::getContentLib($nodeBare['contenttypeid'])->getBareContent($nodeid); $node = array_pop($node); } return empty($node['infraction']) and $node['contenttypeid'] != $infractionContentTypeId and $this->canInfractUser($node['userid']); }
/** * Delete the records without updating the parent info. It is used when deleting a whole channel and it's children need to be removed * @param array $childrenIds - list of node ids */ public function deleteChildren($childrenIds) { foreach ($childrenIds as $photoId) { $fileDataRecord = $this->fetchFileDataRecord($photoId); $refCount = $fileDataRecord["refcount"] - 1; $data = array(vB_dB_Query::TYPE_KEY => vB_dB_Query::QUERY_UPDATE, vB_dB_Query::CONDITIONS_KEY => array('filedataid' => $fileDataRecord["filedataid"]), 'refcount' => $refCount); $this->assertor->assertQuery("vBForum:filedata", $data); } //delete the main tables parent::deleteChildren($childrenIds); }
public function canViewPostHistory($nodeid) { $postedithistory = vB::getDatastore()->getOption('postedithistory'); $node = vB_Library::instance('node')->getNodeBare($nodeid); return (bool) $postedithistory and vB_Library_Content::getContentLib($node['contenttypeid'])->getCanEdit($node); }
/** * Gets the damaged nodeids */ public function getDamagedNodes($params, $db, $check_only = false) { if ($check_only) { return isset($params['start']) and isset($params['end']) and isset($params['contenttypeid']); } else { $cleaner = vB::getCleaner(); $params = $cleaner->cleanArray($params, array('start' => vB_Cleaner::TYPE_UINT, 'end' => vB_Cleaner::TYPE_UINT, 'contenttypeid' => vB_Cleaner::TYPE_UINT)); $contentLib = vB_Library_Content::getContentLib($params['contenttypeid']); $tables = $contentLib->fetchTableName(); $sql = "SELECT DISTINCT node.nodeid FROM " . TABLE_PREFIX . "node AS node \n"; $where = array(); foreach ($tables as $table) { $sql .= "LEFT JOIN " . TABLE_PREFIX . "{$table} AS {$table} ON {$table}.nodeid = node.nodeid\n"; $where[] = "{$table}.nodeid IS NULL\n"; } $sql .= "WHERE (" . implode(' OR ', $where) . ")\n AND node.contenttypeid = " . $params['contenttypeid'] . " AND node.nodeid >= " . $params['start'] . " AND node.nodeid <=" . $params['end'] . "\n/**" . __FUNCTION__ . (defined('THIS_SCRIPT') ? '- ' . THIS_SCRIPT : '') . "**/"; $resultclass = 'vB_dB_' . $this->db_type . '_result'; $config = vB::getConfig(); if (isset($config['Misc']['debug_sql']) and $config['Misc']['debug_sql']) { echo "sql: {$sql}<br />\n"; } $result = new $resultclass($db, $sql); return $result; } }
/** * Return whether the user can delete the node or not. Used by createcontent controller * * @param array $node Existing node data array including nodeid, starter, channelid, contenttypeid * @param boolean $specific (OPTIONAL) Whether to specifically check for hard delete or soft delete. By default * it is false, meaning it will check whether user can soft OR hard delete the node * @param boolean $hard (OPTIONAL) Only used if $specific is true. Whether it's checking if user can hard * delete (true) or soft delete (false) * * @return array key 'candelete': * boolean true if they can delete the node */ public function getCanDeleteForEdit($node, $specific = false, $hard = false) { // This function is only meant to be called from the createcontent controller's actionLoadEditor() // It's not meant to be very versatile. if (!is_array($node) or empty($node['nodeid']) or empty($node['starter']) or empty($node['channelid']) or empty($node['userid']) or empty($node['contenttypeid'])) { return array('candelete' => false); } // Let's grab some params that getCanDelete() requires if we want to use the $hard param. $userContext = vB::getUserContext(); $starter = vB_Library::instance('node')->getNodeBare($node['starter']); $channelid = $starter['parentid']; $channelPerms = vB::getUserContext()->fetchPermsForChannels(array($channelid)); $thisChannelPerms = $channelPerms[$channelid]; $thisChannelPerms['global'] = $channelPerms['global']; $contentLib = vB_Library_Content::getContentLib($node['contenttypeid']); if ($specific) { $canDelete = $contentLib->getCanDelete($node, $userContext, $thisChannelPerms, $hard); } else { $canDelete = ($contentLib->getCanDelete($node, $userContext, $thisChannelPerms, false) or $contentLib->getCanDelete($node, $userContext, $thisChannelPerms, true)); } return array("candelete" => $canDelete); }
protected function isFlood($data) { $isFlood = false; $node = vB::getDbAssertor()->getRow('vBForum:node', array(vB_dB_Query::TYPE_KEY => vB_dB_Query::QUERY_SELECT, vB_dB_Query::CONDITIONS_KEY => array(array('field' => 'userid', 'value' => $data['userid'], 'operator' => vB_dB_Query::OPERATOR_EQ), array('field' => 'created', 'value' => vB::getRequest()->getTimeNow() - $this->options['floodchecktime'], 'operator' => vB_dB_Query::OPERATOR_GT), array('field' => 'contenttypeid', 'value' => $this->contenttypeid, 'operator' => vB_dB_Query::OPERATOR_EQ))), array('field' => array('created'), 'direction' => array(vB_dB_Query::SORT_DESC))); if (!empty($node)) { $lastPostElapsed = vB::getRequest()->getTimeNow() - $node['created']; if ($lastPostElapsed < $this->options['floodchecktime']) { $isFlood = true; } vB_Library_Content::writeToCache(array($node), vB_Library_Content::CACHELEVEL_NODE); } if ($isFlood) { return $lastPostElapsed; } return false; }
public function assembleContent(&$content, $permissions = false) { $nodesContent = parent::assembleContent($content, $permissions); $results = array(); $type = vB_Api_External::TYPE_RSS2; $rssinfo = vB_Library::instance('external')->getExternalDataForChannels(array_keys($nodesContent), $type); foreach ($nodesContent as $record) { $results[$record['nodeid']] = $record; $results[$record['nodeid']]['rss_enabled'] = $rssinfo[$record['nodeid']][$type . '_enabled']; $results[$record['nodeid']]['rss_route'] = $rssinfo[$record['nodeid']][$type . '_route']; } return $results; }
/** * Assembles the response for detailed content * * @param mixed assertor response object * @param mixed optional array of permissions * * @return mixed formatted data */ public function assembleContent(&$content, $permissions = false) { $nodesContent = parent::assembleContent($content, $permissions); $results = array(); //If we don't already have ancestry, we need to add it for the canEditThreadTitle check. $needParents = array(); foreach ($nodesContent as $record) { if (empty($record['parents']) and !empty($record['nodeid'])) { $needParents[$record['nodeid']] = $record['nodeid']; } } if (!empty($needParents)) { $parents = vB_Library::instance('node')->getParents($needParents); foreach ($nodesContent as $key => $content) { if (!empty($content['nodeid']) and !empty($parents[$content['nodeid']])) { $nodesContent[$key]['parents'] = $parents[$content['nodeid']]; } } } $userid = vB::getCurrentSession()->get('userid'); foreach ($nodesContent as $record) { if (isset($record['nodeid'])) { if ($record['starter'] == $record['nodeid'] and $userid > 0 and vB_Library::instance('node')->canEditThreadTitle($record['nodeid'], $record)) { $record['canedittitle'] = 1; } else { $record['canedittitle'] = 0; } $results[$record['nodeid']] = $record; } } return $results; }
protected function getTitleAndText($node, $propagate = true) { try { $indexableContent = vB_Library_Content::getContentLib($node['contenttypeid'])->getIndexableContent($node, $propagate); } catch (Exception $e) { //whatever the reason, just ignore and move on $indexableContent = array(); } $title = ""; if (!empty($indexableContent['title'])) { $title = strtolower($indexableContent['title']); unset($indexableContent['title']); } //need to put a space between segments or we could concatenate words and distort our index $text = implode(' ', $indexableContent); $text = strtolower($text); return array($title, $text); }