/** * Create a blog channel. * * @param array $input * @param int $channelid * @param int $channelConvTemplateid * @param int $channelPgTemplateId * @param int $ownerSystemGroupId * * @return int The nodeid of the new blog channel */ public function createChannel($input, $channelid, $channelConvTemplateid, $channelPgTemplateId, $ownerSystemGroupId) { $input['parentid'] = $channelid; $input['inlist'] = 1; // we don't want it to be shown in channel list, but we want to move them $input['protected'] = 0; if (empty($input['userid'])) { $input['userid'] = vB::getCurrentSession()->get('userid'); } if (!isset($input['publishdate'])) { $input['publishdate'] = vB::getRequest()->getTimeNow(); } $input['templates']['vB5_Route_Channel'] = $channelPgTemplateId; $input['templates']['vB5_Route_Conversation'] = $channelConvTemplateid; // add channel node $channelLib = vB_Library::instance('content_channel'); $input['page_parentid'] = 0; $result = $channelLib->add($input, array('skipFloodCheck' => true, 'skipDupCheck' => true)); //Make the current user the channel owner. $userApi = vB_Api::instanceInternal('user'); $usergroup = vB::getDbAssertor()->getRow('usergroup', array('systemgroupid' => $ownerSystemGroupId)); if (empty($usergroup) or !empty($usergroup['errors'])) { //This should never happen. It would mean an invalid parameter was passed throw new vB_Exception_Api('invalid_request'); } vB_User::setGroupInTopic($input['userid'], $result['nodeid'], $usergroup['usergroupid']); vB_Cache::allCacheEvent(array('nodeChg_' . $this->blogChannel, "nodeChg_{$channelid}")); vB::getUserContext()->rebuildGroupAccess(); vB_Channel::rebuildChannelTypes(); // clear follow cache vB_Api::instanceInternal('follow')->clearFollowCache(array($input['userid'])); return $result['nodeid']; }
/** * Create an article category channel. This function works basically like the blog library's version * * @param array $input data array, should have standard channel data like title, parentid, * @param int $channelid parentid that the new channel should fall under. * @param int $channelConvTemplateid "Conversation" level pagetemplate to use. Typically vB_Page::getArticleConversPageTemplate() * @param int $channelPgTemplateId "Channel" level pagetemplate to use. Typically vB_Page::getArticleChannelPageTemplate() * @param int $ownerSystemGroupId * * @return int The nodeid of the new blog channel */ public function createChannel($input, $channelid, $channelConvTemplateid, $channelPgTemplateId, $ownerSystemGroupId) { if (!isset($input['parentid']) or intval($input['parentid']) < 1) { $input['parentid'] = $channelid; } $input['inlist'] = 1; // we don't want it to be shown in channel list, but we want to move them $input['protected'] = 0; if (empty($input['userid'])) { $input['userid'] = vB::getCurrentSession()->get('userid'); } if (!isset($input['publishdate'])) { $input['publishdate'] = vB::getRequest()->getTimeNow(); } $input['templates']['vB5_Route_Channel'] = $channelPgTemplateId; $input['templates']['vB5_Route_Article'] = $channelConvTemplateid; $input['childroute'] = 'vB5_Route_Article'; // add channel node $channelLib = vB_Library::instance('content_channel'); $input['page_parentid'] = 0; $result = $channelLib->add($input, array('skipNotifications' => true, 'skipFloodCheck' => true, 'skipDupCheck' => true)); //Make the current user the channel owner. $userApi = vB_Api::instanceInternal('user'); $usergroup = vB::getDbAssertor()->getRow('usergroup', array('systemgroupid' => $ownerSystemGroupId)); vB_Cache::allCacheEvent(array('nodeChg_' . $this->articleHomeChannel, "nodeChg_{$channelid}")); vB::getUserContext()->rebuildGroupAccess(); vB_Channel::rebuildChannelTypes(); // clear follow cache vB_Api::instanceInternal('follow')->clearFollowCache(array($input['userid'])); return $result['nodeid']; }
/** * Clears follow in class cache */ public function clearFollowCache($userIds) { foreach ($userIds as $user) { unset($this->followers[$user]); unset($this->userFollowers[$user]); unset($this->userFollowing[$user]); unset($this->subscriptions[$user]); vB_Cache::allCacheEvent("followChg_{$user}"); } $this->userListCache = array(); }
/** * Rebuild the style datastore. */ public function buildStyleDatastore() { $this->setCssDate(); $stylecache = $this->fetchStyles(true, false, array('themes' => true)); foreach ($stylecache as $key => $style) { // VBV-4174: we don't want stylevars in the datastore if (isset($style['newstylevars'])) { unset($stylecache[$key]['newstylevars']); } } vB::getDatastore()->build('stylecache', serialize($stylecache), 1); vB_Cache::allCacheEvent('vbCachedFullPage'); vB_Library::instance('template')->rebuildTextonlyDS(); return $stylecache; }
/** * Additional data to update after a save call (such as denormalized values in other tables). * In batch updates, is executed once after all records are updated. * * @param boolean Do the query? */ function post_save_once($doquery = true) { parent::post_save_once($doquery); if (!empty($this->moderator['userid'])) { vB_Cache::allCacheEvent('userChg_' . $this->moderator['userid']); } vB::getUserContext()->rebuildGroupAccess(); }
/** * 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; }
/** This grants a user additional permissions in a specific channel, by adding to the groupintopic table * * @param int * @param mixed integer or array of integers * @param int * * @return bool ***/ public static function setGroupInTopic($userid, $nodeids, $usergroupid) { //check the data. if (!is_numeric($userid) or !is_numeric($usergroupid)) { throw new vB_Exception_Api('invalid_data'); } if (!is_array($nodeids)) { $nodeids = array($nodeids); } else { $nodeids = array_unique($nodeids); } //We don't do a permission check. It's essential that the api's do that before calling here. //let's get the current channels in which the user already is set for that group. //Then remove any for which they already are set. $assertor = vB::getDbAssertor(); $existing = $assertor->assertQuery('vBForum:groupintopic', array(vB_dB_Query::TYPE_KEY => vB_dB_Query::QUERY_SELECT, 'userid' => $userid, 'groupid' => $usergroupid)); foreach ($existing as $permission) { $index = array_search($permission['nodeid'], $nodeids); if ($index !== false) { unset($nodeids[$index]); } } //and do the inserts foreach ($nodeids as $nodeid) { $assertor->assertQuery('vBForum:groupintopic', array(vB_dB_Query::TYPE_KEY => vB_dB_Query::QUERY_INSERT, 'userid' => $userid, 'nodeid' => $nodeid, 'groupid' => $usergroupid)); } vB_Cache::allCacheEvent(array("userPerms_{$userid}", "userChg_{$userid}", "followChg_{$userid}", "sgMemberChg_{$userid}")); vB_Api::instanceInternal('user')->clearChannelPerms($userid); vB::getUserContext($userid)->reloadGroupInTopic(); vB::getUserContext()->clearChannelPermissions(); //if we got here all is well. return true; }
/** * Checks if the current node should be counted in the user post count for the author. * * @param array The node * @param (unpublish|unapprove) The action that was just carried out on the node * * @return boolean Whether or not the node should be counted in user post count. */ protected function countInUserPostCount(array $node, $action = '') { // NOTICE: How we determine if a post counts in user post count here needs to // match the criteria used in admincp/misc.php?do=updateposts // If you update in one place, please update in the other // check if this content type counts as a "post" // We have to jump through a bunch of hoops to not count VMs, PMs, // reports, and other items in user post count // @todo - VMs and comments should probably be their own content types // extended from the Text content type. if (!$this->includeInUserPostCount or $this->isVisitorMessage($node['nodeid'])) { return false; } if (!isset($node['starter'])) { //force a reload vB_Cache::allCacheEvent('nodeChg_' . $node['nodeid']); $node = vB_Library::instance('node')->getNodeFullContent($node['nodeid'], $node['contenttypeid']); } return !$this->isComment($node['nodeid'], $node) and ($action == 'unapprove' or $node['approved']) and ($action == 'unpublish' or $node['showpublished'] and !$node['deleteuserid']); }
protected static function updateContentRoute($oldRouteInfo, $newRouteInfo) { $db = vB::getDbAssertor(); $events = array(); // update redirect301 fields $updateIds = $db->assertQuery('get_update_route_301', array('oldrouteid' => $oldRouteInfo['routeid'])); if (!empty($updateIds)) { $routeIds = array(); foreach ($updateIds as $route) { $routeid = $route['routeid']; $events[] = "routeChg_{$routeid}"; $routeIds[] = $routeid; } $db->update('routenew', array('redirect301' => $newRouteInfo['routeid'], 'name' => vB_dB_Query::VALUE_ISNULL), array('routeid' => $routeIds)); } // don't modify the routeid for default pages, as it will still be used $updateIds = $db->assertQuery('page', array(vB_dB_Query::TYPE_KEY => vB_dB_Query::QUERY_SELECT, vB_dB_Query::COLUMNS_KEY => array('pageid'), vB_dB_Query::CONDITIONS_KEY => array('routeid' => $oldRouteInfo['routeid'], 'pagetype' => vB_Page::TYPE_CUSTOM))); if (!empty($updateIds)) { $pageIds = array(); foreach ($updateIds as $page) { $pageid = $page['pageid']; $events[] = "pageChg_{$pageid}"; $pageIds[] = $pageid; } $db->update('page', array('routeid' => $newRouteInfo['routeid']), array('pageid' => $pageIds)); } vB_Cache::allCacheEvent($events); }
$pfcs[] = $pfc['profilefieldcategoryid']; } if (!in_array($vbulletin->GPC['profilefield']['profilefieldcategoryid'], $pfcs)) { $vbulletin->GPC['profilefield']['profilefieldcategoryid'] = 0; } if (empty($vbulletin->GPC['profilefieldid'])) { // insert /*insert query*/ $vbulletin->GPC['profilefieldid'] = vB::getDbAssertor()->insert('vBForum:profilefield', $vbulletin->GPC['profilefield']); $vbulletin->GPC['profilefieldid'] = is_array($vbulletin->GPC['profilefieldid']) ? array_pop($vbulletin->GPC['profilefieldid']) : $vbulletin->GPC['profilefieldid']; $vbulletin->db->query_write("ALTER TABLE " . TABLE_PREFIX . "userfield ADD field{$vbulletin->GPC['profilefieldid']} MEDIUMTEXT NOT NULL"); $vbulletin->db->query_write("OPTIMIZE TABLE " . TABLE_PREFIX . "userfield"); } else { vB::getDbAssertor()->update('vBForum:profilefield', $vbulletin->GPC['profilefield'], array('profilefieldid' => $vbulletin->GPC['profilefieldid'])); } vB_Cache::allCacheEvent('vBProfileFieldsChg'); $vbulletin->db->query_write("\n\t\tREPLACE INTO " . TABLE_PREFIX . "phrase\n\t\t\t(languageid, fieldname, varname, text, product, username, dateline, version)\n\t\tVALUES\n\t\t\t(\n\t\t\t\t0,\n\t\t\t\t'cprofilefield',\n\t\t\t\t'field" . $vbulletin->db->escape_string($vbulletin->GPC['profilefieldid']) . "_title',\n\t\t\t\t'" . $vbulletin->db->escape_string($vbulletin->GPC['title']) . "',\n\t\t\t\t'vbulletin',\n\t\t\t\t'" . $vbulletin->db->escape_string($vbulletin->userinfo['username']) . "',\n\t\t\t\t" . TIMENOW . ",\n\t\t\t\t'" . $vbulletin->db->escape_string($vbulletin->options['templateversion']) . "'\n\t\t\t),\n\t\t\t(\n\t\t\t\t0,\n\t\t\t\t'cprofilefield',\n\t\t\t\t'field" . $vbulletin->db->escape_string($vbulletin->GPC['profilefieldid']) . "_desc',\n\t\t\t\t'" . $vbulletin->db->escape_string($vbulletin->GPC['description']) . "',\n\t\t\t\t'vbulletin',\n\t\t\t\t'" . $vbulletin->db->escape_string($vbulletin->userinfo['username']) . "',\n\t\t\t\t" . TIMENOW . ",\n\t\t\t\t'" . $vbulletin->db->escape_string($vbulletin->options['templateversion']) . "'\n\t\t\t)\n\t"); require_once DIR . '/includes/adminfunctions_language.php'; build_language(); build_profilefield_cache(); if ($vbulletin->GPC['modifyfields']) { $args = array('do' => 'modifycheckbox', 'profilefieldid' => $vbulletin->GPC['profilefieldid']); } else { $args = array('do' => 'modify'); } print_stop_message2(array('saved_x_successfully', htmlspecialchars_uni($vbulletin->GPC['title'])), 'profilefield', $args); } // ###################### Start add ####################### if ($_REQUEST['do'] == 'add' or $_REQUEST['do'] == 'edit') { $vbulletin->input->clean_array_gpc('r', array('type' => vB_Cleaner::TYPE_STR)); if ($_REQUEST['do'] == 'add') {
/** * Updates the user record with infractions, warnings, and ipoints * * @param int User id */ protected function updateDenormalizedUserData($userid) { $userInfractions = $this->getUserInfractions($userid, 0, 1); $data = array('infractions' => $userInfractions ? intval($userInfractions['statistics']['total_infractions']) : 0, 'warnings' => $userInfractions ? intval($userInfractions['statistics']['total_warnings']) : 0, 'ipoints' => $userInfractions ? intval($userInfractions['statistics']['points']) : 0); $conditions = array('userid' => $userid); $changed = $this->assertor->update('user', $data, $conditions); vB_Cache::allCacheEvent('userChg_' . $userid); return $changed == 1; }
protected static function updateContentRoute($oldRouteInfo, $newRouteInfo) { $db = vB::getDbAssertor(); $events = array(); $events[] = "vB_ChannelStructure_chg"; // invalidate vB_ChTree... record so that channels' routes are updated // update redirect301 fields $updateIds = $db->assertQuery('get_update_route_301', array('oldrouteid' => $oldRouteInfo['routeid'])); if (!empty($updateIds)) { $routeIds = array(); foreach ($updateIds as $route) { $routeid = $route['routeid']; $events[] = "routeChg_{$routeid}"; $routeIds[] = $routeid; } $db->update('routenew', array('redirect301' => $newRouteInfo['routeid'], 'name' => vB_dB_Query::VALUE_ISNULL), array('routeid' => $routeIds)); } // update routeid in nodes table $updateIds = $db->assertQuery('vBForum:node', array(vB_dB_Query::TYPE_KEY => vB_dB_Query::QUERY_SELECT, vB_dB_Query::COLUMNS_KEY => array('nodeid'), vB_dB_Query::CONDITIONS_KEY => array('routeid' => $oldRouteInfo['routeid']))); if (!empty($updateIds)) { $nodeIds = array(); foreach ($updateIds as $node) { $nodeid = $node['nodeid']; // this does not affect parents, so we don't need to clear they cache $events[] = "nodeChg_{$nodeid}"; $nodeIds[] = $nodeid; } $db->update('vBForum:node', array('routeid' => $newRouteInfo['routeid']), array('nodeid' => $nodeIds)); } // don't modify the routeid for default pages, as it will still be used $updateIds = $db->assertQuery('page', array(vB_dB_Query::TYPE_KEY => vB_dB_Query::QUERY_SELECT, vB_dB_Query::COLUMNS_KEY => array('pageid'), vB_dB_Query::CONDITIONS_KEY => array('routeid' => $oldRouteInfo['routeid'], 'pagetype' => vB_Page::TYPE_CUSTOM))); if (!empty($updateIds)) { $pageIds = array(); foreach ($updateIds as $page) { $pageid = $page['pageid']; $events[] = "pageChg_{$pageid}"; $pageIds[] = $pageid; } $db->update('page', array('routeid' => $newRouteInfo['routeid']), array('pageid' => $pageIds)); } /* The code below implies that multiple conversation routes could exist under a single channel. However, I don't know * when this might be the case. When moving channels/topics, the routes are untouched. Topic redirects are handled by * the redirect & node tables. */ // update conversation generic route $routes = $db->getRows('routenew', array(vB_dB_Query::TYPE_KEY => vB_dB_Query::QUERY_SELECT, vB_dB_Query::CONDITIONS_KEY => array(array('field' => 'class', 'value' => array('vB5_Route_Conversation', 'vB5_Route_Article')), array('field' => 'prefix', 'value' => $oldRouteInfo['prefix']), array('field' => 'contentid', 'value' => $oldRouteInfo['channelid']), array('field' => 'redirect301', 'operator' => vB_dB_Query::OPERATOR_ISNULL)))); foreach ($routes as $route) { $events[] = "routeChg_{$route['routeid']}"; //if the old route has a name, clear it. Only one route should ever have a name and it belongs to the route //we are about to create. if ($route['name']) { $db->update('routenew', array('name' => vB_dB_Query::VALUE_ISNULL), array('routeid' => $route['routeid'])); } // create new conversation route using most of the old route's data $newConversationRoute = $route; unset($newConversationRoute['routeid']); unset($newConversationRoute['redirect301']); $newConversationRoute['prefix'] = $newRouteInfo['prefix']; // special case, if prefix is empty (i.e. this is a new home page) then we must leave out the leading '/', // or selectBestRoute will not be able to match the path (which never has a leading '/') to regex. $newConversationRoute['regex'] = ($newRouteInfo['prefix'] === '' ? '' : preg_quote($newRouteInfo['prefix']) . '/') . vB5_Route_Conversation::REGEXP; // save the new route. If you need to call validInput(), be sure to unset prefix first, otherwise it'll think it's // a custom conversation url (as opposed to custom channel url, which this is) $newConversationRouteid = vB5_Route_Conversation::saveRoute($newConversationRoute); if (is_array($newConversationRouteid)) { $newConversationRouteid = (int) array_pop($newConversationRouteid); } // then update old convo route's redirect301 $db->update('routenew', array('redirect301' => $newConversationRouteid), array('routeid' => $route['routeid'])); // update routeids for conversation nodes // Copied from the channel node updates above. $updateIds = $db->assertQuery('vBForum:node', array(vB_dB_Query::TYPE_KEY => vB_dB_Query::QUERY_SELECT, vB_dB_Query::COLUMNS_KEY => array('nodeid'), vB_dB_Query::CONDITIONS_KEY => array('routeid' => $route['routeid']))); if (!empty($updateIds)) { $nodeIds = array(); foreach ($updateIds as $node) { $nodeid = $node['nodeid']; // this does not affect parents, so we don't need to clear they cache $events[] = "nodeChg_{$nodeid}"; $nodeIds[] = $nodeid; } // if there are ever cases of multiple conversation routes per channel, and they're sizable, it might be // worth creating a method query to handle all node updates at once instead of per conversation route. $db->update('vBForum:node', array('routeid' => $newConversationRouteid), array('nodeid' => $nodeIds)); } } vB_Cache::allCacheEvent($events); }
/** * Clear user cached info for given userids. * There's currently cached info in several places (vB_Session, vB_User and vB_Cache implementations) * this makes sure they all properly cleared. * * @param array List of users to clear cache. * * @param bool Cache was cleared or not. **/ public function clearUserInfo($userids) { if (empty($userids) or !is_array($userids)) { return false; } $events = array(); $userids = array_unique($userids); $session = vB::getCurrentSession(); $currentuser = $session->get('userid'); $updatecurrent = false; foreach ($userids as $userid) { // update current user? if ($currentuser == $userid) { $updatecurrent = true; } vB_User::clearUsersCache($userid); $events[] = 'userChg_' . $userid; } vB_Cache::allCacheEvent($events); if ($updatecurrent) { $session->clearUserInfo(); } return true; }
/** * Initializes the user context with the permissions for the selected user. * * This is used for the initial constructor and can be used to refresh permissions * if they have changed. * * @param boolean $forceReload -- Do not use cached permissions * */ public function reloadUserPerms($forceReload = false) { if (!$forceReload) { $cached = vB_Cache::instance(vB_Cache::CACHE_LARGE)->read('vB_UserPerms' . $this->userid); } if (!empty($cached)) { $this->groupInTopic = $cached['groupintopic']; $this->usergroups = $cached['usergroups']; $this->moderatorPerms = $cached['moderatorperms']; $this->channelAccess = $cached['channelAccess']; $this->permissionContext = new vB_PermissionContext($this->datastore, $cached['primary'], $cached['secondary'], $cached['infraction']); $this->canModerate = $cached['canmoderate']; $this->superMod = $cached['superMod']; } else { //make sure we clear the stored session data. if ($forceReload) { vB_Cache::allCacheEvent('userPerms_' . $this->userid); } $this->superMod = array('moderatorpermissions' => 0, 'moderatorpermissions2' => 0); // fetch user groups $userLib = vB_Library::instance('user'); if ($this->userid > 0) { try { $result = $userLib->fetchUserGroups($this->userid); } catch (vB_Exception_Api $e) { $errors = $e->get_errors(); if ($errors[0][0] == 'invalid_user_specified') { //note that we can't get here on the second call because the userid is 0 //we need to make sure we don't infinitely recurse here $this->userid = 0; return $this->reloadUserPerms($forceReload); } throw $e; } } else { $result = false; } if ($result) { $primary_group_id = $result['groupid']; $secondary_group_ids = $result['secondary']; $infraction_group_ids = $result['infraction']; } else { $primary_group_id = self::USERGROUP_GUESTS; $secondary_group_ids = array(); $infraction_group_ids = array(); } //We can't call the user api function getGroupInTopic(), because that does a permission check. Which causes a recursion loop //We have to do a try-catch block here. During an upgrade we check permissions although the groupintopic table doesn't exist. try { if ($this->userid > 0) { $this->reloadGroupInTopic(); } } catch (exception $e) { //Nothing to do here. Just continue } // ignore secondary usergroups if allowmembergroups is set to "No" $bf_ugp_genericoptions = $this->datastore->get_value('bf_ugp_genericoptions'); $usergroupCache = $this->datastore->get_value('usergroupcache'); //vB::getDatastore()->getValue('usergroupcache'); if (!($usergroupCache[$primary_group_id]['genericoptions'] & $bf_ugp_genericoptions['allowmembergroups'])) { $this->usergroups = array($primary_group_id); } else { $this->usergroups = array_merge(array($primary_group_id), $secondary_group_ids); } $this->permissionContext = new vB_PermissionContext($this->datastore, $primary_group_id, $secondary_group_ids, $infraction_group_ids); //Add any permissions from the moderator table. if ($this->userid) { // Since moderator perms are based on the moderator table, I'm leaving this independent of the usergroup option 'allowmembergroups' $this->moderatorPerms = $userLib->fetchModerator($this->userid); if ($this->hasPermission('adminpermissions', 'ismoderator') and !empty($this->moderatorPerms[0])) { if (!isset($this->moderatorPerms[0]['permissions'])) { $this->moderatorPerms[0]['permissions'] = 0; } if (!isset($this->moderatorPerms[0]['permissions2'])) { $this->moderatorPerms[0]['permissions2'] = 0; } $this->superMod = array('moderatorpermissions' => $this->moderatorPerms[0]['permissions'], 'moderatorpermissions2' => $this->moderatorPerms[0]['permissions2']); } } else { $this->moderatorPerms = array(); } vB_Cache::instance(vB_Cache::CACHE_LARGE)->write('vB_UserPerms' . $this->userid, array('groupintopic' => $this->groupInTopic, 'usergroups' => $this->usergroups, 'moderatorperms' => $this->moderatorPerms, 'primary' => $primary_group_id, 'secondary' => $secondary_group_ids, 'infraction' => $infraction_group_ids, 'channelAccess' => $this->getAllChannelAccess(), 'canmoderate' => $this->getCanModerate(), 'superMod' => $this->superMod), 1440, array('userPerms_' . $this->userid, 'userChg_' . $this->userid, 'perms_changed', 'vB_ChannelStructure_chg')); } }
/** * Extracts the thumbnail from og:image meta data * * @param string url of video * @param int optional nodeid of video node * * @return mixed url string or false */ public function getVideoThumbnail($url, $nodeid = false) { //Note that this is called from the template, and often there will be no ndeid if (!empty($nodeid)) { $video = $this->getContent($nodeid); if (!empty($video)) { $video = array_pop($video); } } if (empty($video)) { //Try to get from cache first. $cacheKey = 'vB_Vid' . md5($url); $check = vB_Cache::instance(vB_Cache::CACHE_LARGE)->read($cacheKey); if (!empty($check)) { return $check; } $video = $this->assertor->getRow('vBForum:video', array('url' => $url)); } //check if we have the thumbnail in the video if (!empty($video) and !empty($video['thumbnail']) and !empty($video['thumbnail_date']) and $video['thumbnail_date'] >= vB::getRequest()->getTimeNow() - self::THUMBNAIL_TTL) { return $video['thumbnail']; } $data = vB_Api::instance('content_link')->parsePage($url); if (!empty($data['images'])) { $thumbnail = $data['images']; // only return the first image. May want to change this later after product audit? if (is_array($thumbnail)) { $thumbnail = $thumbnail[0]; } //save the thumbnail so we don't have to fetch it next time it's needed if (!empty($video)) { //there is a video record. Put it there. $this->assertor->update('vBForum:video', array('thumbnail' => $thumbnail, 'thumbnail_date' => vB::getRequest()->getTimeNow()), array('nodeid' => $video['nodeid'])); vB_Cache::allCacheEvent('nodeChg_' . $video['nodeid']); } else { //put into cache if (empty($cacheKey)) { $cacheKey = 'vB_Vid' . md5($url); } vB_Cache::instance(vB_Cache::CACHE_LARGE)->write($cacheKey, $thumbnail, self::THUMBNAIL_TTL); } return $thumbnail; } // we should probably have a default placeholder // we can return in case no image is found.. return false; }
/** * Updates data after user being deleted. * */ protected function updateDeletedUserData() { $phrase = vB_Api::instanceInternal('phrase')->fetch('guest'); $guestPhrase = $phrase['guest']; unset($phrase); // node data update $events = array(); $nodes = $this->assertor->getRows('vBForum:node', array('userid' => $this->existing['userid'])); foreach ($nodes as $node) { $events[$node['nodeid']] = 'nodeChg_' . $node['nodeid']; } $this->assertor->update('vBForum:node', array('userid' => 0, 'authorname' => $guestPhrase), array('userid' => $this->existing['userid'])); // node last data update $nodes = $this->assertor->getRows('vBForum:node', array('lastauthorid' => $this->existing['userid'])); foreach ($nodes as $node) { $events[$node['nodeid']] = 'nodeChg_' . $node['nodeid']; } $this->assertor->update('vBForum:node', array('lastauthorid' => 0, 'lastcontentauthor' => $guestPhrase), array('lastauthorid' => $this->existing['userid'])); // vms $nodes = $this->assertor->getRows('vBForum:node', array('setfor' => $this->existing['userid'])); foreach ($nodes as $node) { $events[$node['nodeid']] = 'nodeChg_' . $node['nodeid']; } $this->assertor->update('vBForum:node', array('setfor' => 0), array('setfor' => $this->existing['userid'])); if (!empty($events)) { vB_Cache::allCacheEvent($events); } }
/** * Delete a user * * @param integer int The ID of user to be deleted * @param bool boolean Whether to transfer the Groups and Blogs owned by the user to current logged-in admininstrator */ public function delete($userid, $transfer_groups = true) { $this->checkHasAdminPermission('canadminusers'); require_once DIR . '/includes/adminfunctions.php'; // check user is not set in the $undeletable users string if (is_unalterable_user($userid)) { throw new vB_Exception_Api('user_is_protected_from_alteration_by_undeletableusers_var'); } else { $info = vB_User::fetchUserInfo($userid); if (!$info) { throw new vB_Exception_Api('invalid_user_specified'); } $events = array(); if ($transfer_groups) { $adminuserid = vB::getCurrentSession()->fetch_userinfo_value('userid'); // Admin userid $this->library->transferOwnership($userid, $adminuserid); } else { $nodeidsforuser = array(); $groups = vB_Api::instanceInternal('socialgroup')->getSGInfo(array('userid' => $userid, 'perpage' => 100)); if (!empty($groups['results'])) { foreach ($groups['results'] as $groupnodeid => $group) { $nodeidsforuser[] = $groupnodeid; $events[] = 'nodeChg_' . $groupnodeid; } } $blogs = vB_Api::instanceInternal('blog')->getBlogInfo(1, 100, $userid); if (!empty($blogs['results'])) { foreach ($blogs['results'] as $blognodeid => $blog) { $nodeidsforuser[] = $blognodeid; $events[] = 'nodeChg_' . $blognodeid; } } foreach ($nodeidsforuser as $nodeid) { vB_Api::instanceInternal('content_channel')->delete($nodeid); } } $userdm = new vB_Datamanager_User(vB_DataManager_Constants::ERRTYPE_ARRAY_UNPROCESSED); $userdm->set_existing($info); $userdm->delete(); if ($userdm->has_errors(false)) { throw $userdm->get_exception(); } $events[] = 'userChg_' . $userid; vB_Cache::allCacheEvent($events); return true; } }
$sql = "UPDATE " . TABLE_PREFIX . "node \nSET displayorder = CASE \n"; $events = array(); foreach ($nodes as $node) { $nodeid = $node['nodeid']; $displayorder = $node['displayorder']; if ($displayorders[$nodeid] === $displayorder) { unset($displayorders[$nodeid]); } else { $sql .= "\tWHEN nodeid = " . $nodeid . " THEN " . $displayorders[$nodeid] . "\n"; $events[] = 'nodeChg_' . $nodeid; } } $sql .= "ELSE displayorder \nEND \nWHERE nodeid IN (" . implode(',', array_keys($displayorders)) . ")"; if (!empty($displayorders)) { $vbulletin->db->query_write($sql); vB_Cache::allCacheEvent($events); } } print_cp_redirect2('cms', array('do' => $gobackto), 1); } // for everything else, there has to be selected nodes... if (!is_array($vbulletin->GPC['select_node']) or empty($vbulletin->GPC['select_node'])) { print_stop_message2('nothing_to_do'); } // grab nodeids, make sure they're int $nodeids = array(); foreach ($vbulletin->GPC['select_node'] as $nodeid => $nothing) { $nodeid = intval($nodeid); if ($nodeid > 0) { $nodeids[$nodeid] = $nodeid; }
public static function updateRoute($routeId, $data) { $assertor = vB::getDbAssertor(); $oldRouteInfo = $assertor->getRow('routenew', array('routeid' => $routeId)); if (!$oldRouteInfo) { return false; } if (isset($oldRouteInfo['arguments']) and !empty($oldRouteInfo['arguments'])) { $arguments = unserialize($oldRouteInfo['arguments']); foreach ($arguments as $key => $val) { $oldRouteInfo[$key] = $val; } } $class = $oldRouteInfo['class']; $new_data = array_merge($oldRouteInfo, $data); unset($new_data['routeid']); // When we're updating a conversation route for a topic that was previously under a channel with a custom URL, // the old route has a redirect301 that causes a redirect loop. unset($new_data['redirect301']); if (!call_user_func_array(array($class, 'validInput'), array(&$new_data))) { throw new Exception('Invalid route data'); } if (isset($new_data['prefix']) and $new_data['prefix'] !== $oldRouteInfo['prefix']) { $conditions = array('prefix' => $new_data['prefix'], 'class' => $class); // used for cache invalidation below $deletedRoutes = $assertor->getRows('routenew', $conditions); // Overwrite any related record with the same regex. // If you need to validate the prefix before calling this method: use vB5_Route::isPrefixUsed (see vB_Api_Page::savePage). // VBV-11372, in order to delete the "home" route (which has an empty regex), we cannot rely on regex for deletion. $assertor->delete('routenew', $conditions); //if the old route has a name, clear it. Only one route should ever have a name and it belongs to the route //we are about to create. if ($oldRouteInfo['name']) { $assertor->update('routenew', array('name' => vB_dB_Query::VALUE_ISNULL), array('routeid' => $oldRouteInfo['routeid'])); } // url has changed: create a new route and update old ones and page record $newrouteid = self::saveRoute($new_data); if (is_array($newrouteid)) { $newrouteid = (int) array_pop($newrouteid); } $new_data['routeid'] = $newrouteid; call_user_func(array($class, 'updateContentRoute'), $oldRouteInfo, $new_data); $result = $newrouteid; } else { // url has not changed, so there is no need to create a new route unset($new_data['prefix']); unset($new_data['regex']); unset($new_data['arguments']); self::saveRoute($new_data, array('routeid' => $oldRouteInfo['routeid'])); $result = $oldRouteInfo['routeid']; } // invalidate cache $events[$oldRouteInfo['routeid']] = "routeChg_" . $oldRouteInfo['routeid']; foreach ($deletedRoutes as $route) { $events[$route['routeid']] = "routeChg_" . $route['routeid']; } // check if a common route was modified. $common = self::fetchCommonRoutes(); foreach ($common as $route) { if (array_key_exists($route['routeid'], $events)) { $events[] = 'vB_routesChgMultiple'; break; } } vB_Cache::allCacheEvent($events); return $result; }
protected static function updateContentRoute($oldRouteInfo, $newRouteInfo) { $db = vB::getDbAssertor(); $events = array(); $arguments = unserialize($newRouteInfo['arguments']); // update routeid in nodes table $db->update('vBForum:node', array('routeid' => $newRouteInfo['routeid']), array('nodeid' => $arguments['nodeid'])); $events[] = "nodeChg_{$arguments['nodeid']}"; // don't modify the routeid for default pages, as it will still be used $updateIds = $db->assertQuery('page', array(vB_dB_Query::TYPE_KEY => vB_dB_Query::QUERY_SELECT, vB_dB_Query::COLUMNS_KEY => array('pageid'), vB_dB_Query::CONDITIONS_KEY => array('routeid' => $oldRouteInfo['routeid'], 'pagetype' => vB_Page::TYPE_CUSTOM))); if (!empty($updateIds)) { $pageIds = array(); foreach ($updateIds as $page) { $pageid = $page['pageid']; $events[] = "pageChg_{$pageid}"; $pageIds[] = $pageid; } $db->update('page', array('routeid' => $newRouteInfo['routeid']), array('pageid' => $pageIds)); } vB_Cache::allCacheEvent($events); }