This class is HEAVILY inspired by CodeIgniter (http://www.codeigniter.com). My hat is off to them.
Author: Mark O'Sullivan
Inheritance: implements IteratorAggregate
 public function __get($Name)
 {
     switch ($Name) {
         case 'CommentData':
             Deprecated('ActivityController->CommentData', "ActivityController->Data('Activities')");
             $Result = new Gdn_DataSet(array(), DATASET_TYPE_OBJECT);
             return $Result;
         case 'ActivityData':
             Deprecated('ActivityController->ActivityData', "ActivityController->Data('Activities')");
             $Result = new Gdn_DataSet($this->Data('Activities'), DATASET_TYPE_ARRAY);
             $Result->DatasetType(DATASET_TYPE_OBJECT);
             return $Result;
     }
 }
Example #2
0
 public function PreloadLikes(Gdn_DataSet $Comments)
 {
     $cache = array();
     while ($CommentID = $Comments->Value('CommentID', FALSE)) {
         $cache[] = $CommentID;
     }
     if (!empty($cache)) {
         $Likes = $this->SQL->Select()->From($this->Name)->WhereIn('CommentID', $cache)->OrderBy('CommentID')->Get()->Result(DATASET_TYPE_OBJECT);
         foreach ($Likes as $Like) {
             if (!$this->Cache[$Like->CommentID]) {
                 $this->Cache[$Like->CommentID] = array();
             }
             $this->Cache[$Like->CommentID][] = $Like;
         }
     }
 }
   public static function &AllBans() {
      if (!self::$_AllBans) {
         self::$_AllBans = Gdn::SQL()->Get('Ban')->ResultArray();
         self::$_AllBans = Gdn_DataSet::Index(self::$_AllBans, array('BanID'));
      }
//      $AllBans =& self::$_AllBans;
      return self::$_AllBans;
   }
Example #4
0
 /**
  * Get and store list of current bans.
  *
  * @since 2.0.18
  * @access public
  */
 public static function &allBans()
 {
     if (!self::$_AllBans) {
         self::$_AllBans = Gdn::sql()->get('Ban')->resultArray();
         self::$_AllBans = Gdn_DataSet::index(self::$_AllBans, array('BanID'));
     }
     //      $AllBans =& self::$_AllBans;
     return self::$_AllBans;
 }
Example #5
0
 public function Search($Search, $Offset = 0, $Limit = 20)
 {
     $BaseUrl = C('Plugins.Solr.SearchUrl', 'http://localhost:8983/solr/select/?');
     if (!$BaseUrl) {
         throw new Gdn_UserException("The search url has not been configured.");
     }
     if (!$Search) {
         return array();
     }
     // Escepe the search.
     $Search = preg_replace('`([][+&|!(){}^"~*?:\\\\-])`', "\\\\\$1", $Search);
     // Add the category watch.
     $Categories = CategoryModel::CategoryWatch();
     if ($Categories === FALSE) {
         return array();
     } elseif ($Categories !== TRUE) {
         $Search = 'CategoryID:(' . implode(' ', $Categories) . ') AND ' . $Search;
     }
     // Build the search url.
     $BaseUrl .= strpos($BaseUrl, '?') === FALSE ? '?' : '&';
     $Query = array('q' => $Search, 'start' => $Offset, 'rows' => $Limit);
     $Url = $BaseUrl . http_build_query($Query);
     // Grab the data.
     $Curl = curl_init($Url);
     curl_setopt($Curl, CURLOPT_RETURNTRANSFER, 1);
     $CurlResult = curl_exec($Curl);
     curl_close($Curl);
     // Parse the result into the form that the search controller expects.
     $Xml = new SimpleXMLElement($CurlResult);
     $Result = array();
     if (!isset($Xml->result)) {
         return array();
     }
     foreach ($Xml->result->children() as $Doc) {
         $Row = array();
         foreach ($Doc->children() as $Field) {
             $Name = (string) $Field['name'];
             $Row[$Name] = (string) $Field;
         }
         // Add the url.
         switch ($Row['DocType']) {
             case 'Discussion':
                 $Row['Url'] = '/discussion/' . $Row['PrimaryID'] . '/' . Gdn_Format::Url($Row['Title']);
                 break;
             case 'Comment':
                 $Row['Url'] = "/discussion/comment/{$Row['PrimaryID']}/#Comment_{$Row['PrimaryID']}";
                 break;
         }
         // Fix the time.
         $Row['DateInserted'] = strtotime($Row['DateInserted']);
         $Result[] = $Row;
     }
     // Join the users into the result.
     Gdn_DataSet::Join($Result, array('table' => 'User', 'parent' => 'UserID', 'prefix' => '', 'Name', 'Photo'));
     return $Result;
 }
 public function __construct($Sender = '', $ApplicationFolder = '')
 {
     $this->Data = FALSE;
     $NoFollowing = TRUE;
     if (C('Vanilla.Categories.Use') == TRUE) {
         // Load categories with respect to view permissions
         $Categories = CategoryModel::Categories();
         $Categories2 = $Categories;
         foreach ($Categories2 as $i => $Category) {
             if (!$Category['PermsDiscussionsView']) {
                 unset($Categories[$i]);
             } elseif (!$Category['Following']) {
                 $NoFollowing = FALSE;
             }
         }
         // delete view filter if no categories are hidden
         $Session = Gdn::Session();
         if ($NoFollowing && $Session->IsValid()) {
             $Session->SetPreference('ShowAllCategories', TRUE);
         }
         // set categories to data
         $Data = new Gdn_DataSet($Categories);
         $Data->DatasetType(DATASET_TYPE_ARRAY);
         $Data->DatasetType(DATASET_TYPE_OBJECT);
         $this->Data['Categories'] = $Data;
         // calculate additional needed data
         $this->Data['CategoryID'] = isset($Sender->CategoryID) ? $Sender->CategoryID : '';
         $this->Data['OnCategories'] = strtolower($Sender->ControllerName) == 'categoriescontroller' && !is_numeric($this->Data['CategoryID']);
         $this->Data['ShowAllCategoriesPref'] = $Session->GetPreference('ShowAllCategories');
         $this->Data['Url'] = Gdn::Request()->Path();
         if ($this->Data['Url'] == '') {
             $this->Data['Url'] = '/';
         }
         $this->Data['ShowAllCategoriesUrl'] = Gdn::Request()->Url('categories/settoggle?ShowAllCategories=true&Target=' . $this->Data['Url']);
         $this->Data['ShowFollowedCategoriesUrl'] = Gdn::Request()->Url('categories/settoggle?ShowAllCategories=false&Target=' . $this->Data['Url']);
         $this->Data['TKey'] = urlencode(Gdn::Session()->TransientKey());
         $this->Data['ValidSession'] = $Session->UserID > 0 && $Session->ValidateTransientKey($this->Data['TKey']);
         $this->Data['MaxDepth'] = C('Vanilla.Categories.MaxDisplayDepth');
         $this->Data['DoHeadings'] = C('Vanilla.Categories.DoHeadings');
     }
     parent::__construct($Sender, $ApplicationFolder);
 }
 /**
  * Get the data for this module.
  */
 protected function getData()
 {
     // Allow plugins to set different data.
     $this->fireEvent('GetData');
     if ($this->Data) {
         return;
     }
     $Categories = CategoryModel::categories();
     $Categories2 = $Categories;
     // Filter out the categories we aren't watching.
     foreach ($Categories2 as $i => $Category) {
         if (!$Category['PermsDiscussionsView'] || !$Category['Following']) {
             unset($Categories[$i]);
         }
     }
     $Data = new Gdn_DataSet($Categories);
     $Data->DatasetType(DATASET_TYPE_ARRAY);
     $Data->DatasetType(DATASET_TYPE_OBJECT);
     $this->Data = $Data;
 }
 public function __construct($Sender = '')
 {
     // Load categories
     $this->Data = FALSE;
     if (C('Vanilla.Categories.Use') == TRUE && !C('Vanilla.Categories.HideModule')) {
         $Categories = CategoryModel::Categories();
         $Categories2 = $Categories;
         // Filter out the categories we aren't watching.
         foreach ($Categories2 as $i => $Category) {
             if (!$Category['PermsDiscussionsView'] || !$Category['Following']) {
                 unset($Categories[$i]);
             }
         }
         $Data = new Gdn_DataSet($Categories);
         $Data->DatasetType(DATASET_TYPE_ARRAY);
         $Data->DatasetType(DATASET_TYPE_OBJECT);
         $this->Data = $Data;
     }
     parent::__construct($Sender);
 }
 /**
  *
  *
  * @return array|null|type
  */
 public function getProviders()
 {
     $this->SQL->select('uap.*')->from('UserAuthenticationProvider uap');
     if (Gdn::session()->isValid()) {
         $UserID = Gdn::session()->UserID;
         $this->SQL->select('ua.ForeignUserKey', '', 'UniqueID')->join('UserAuthentication ua', "uap.AuthenticationKey = ua.ProviderKey and ua.UserID = {$UserID}", 'left');
     }
     $Data = $this->SQL->get()->resultArray();
     $Data = Gdn_DataSet::index($Data, array('AuthenticationKey'));
     foreach ($Data as &$Row) {
         self::calculate($Row);
     }
     return $Data;
 }
Example #10
0
 /**
  *
  *
  * @param array $IDs
  * @param bool $SkipCacheQuery
  * @return array
  * @throws Exception
  */
 public function getIDs($IDs, $SkipCacheQuery = false)
 {
     $DatabaseIDs = $IDs;
     $Data = [];
     if (!$SkipCacheQuery) {
         $Keys = [];
         // Make keys for cache query
         foreach ($IDs as $UserID) {
             if (!$UserID) {
                 continue;
             }
             $Keys[] = formatString(self::USERID_KEY, ['UserID' => $UserID]);
         }
         // Query cache layer
         $CacheData = Gdn::cache()->get($Keys);
         if (!is_array($CacheData)) {
             $CacheData = [];
         }
         foreach ($CacheData as $RealKey => $User) {
             if ($User === null) {
                 $ResultUserID = trim(strrchr($RealKey, '.'), '.');
             } else {
                 $ResultUserID = val('UserID', $User);
             }
             $this->setCalculatedFields($User);
             $Data[$ResultUserID] = $User;
         }
         //echo "from cache:\n";
         //print_r($Data);
         $DatabaseIDs = array_diff($DatabaseIDs, array_keys($Data));
         unset($CacheData);
     }
     // Clean out bogus blank entries
     $DatabaseIDs = array_diff($DatabaseIDs, [null, '']);
     // If we are missing any users from cache query, fill em up here
     if (sizeof($DatabaseIDs)) {
         $DatabaseData = $this->SQL->whereIn('UserID', $DatabaseIDs)->getWhere('User')->result(DATASET_TYPE_ARRAY);
         $DatabaseData = Gdn_DataSet::index($DatabaseData, 'UserID');
         //echo "from DB:\n";
         //print_r($DatabaseData);
         foreach ($DatabaseIDs as $ID) {
             if (isset($DatabaseData[$ID])) {
                 $User = $DatabaseData[$ID];
                 $this->userCache($User, $ID);
                 // Apply calculated fields
                 $this->setCalculatedFields($User);
                 $Data[$ID] = $User;
             } else {
                 $User = null;
                 $this->userCache($User, $ID);
             }
         }
     }
     $this->EventArguments['RequestedIDs'] = $IDs;
     $this->EventArguments['LoadedUsers'] =& $Data;
     $this->fireEvent('AfterGetIDs');
     return $Data;
 }
 /**
  * Add another user to the conversation.
  * 
  * @since 2.0.0
  * @access public
  *
  * @param int $ConversationID Unique ID of conversation effected.
  * @param int $UserID Unique ID of current user.
  */
 public function AddUserToConversation($ConversationID, $UserID)
 {
     if (!is_array($UserID)) {
         $UserID = array($UserID);
     }
     // First define the current users in the conversation
     $OldContributorData = $this->GetRecipients($ConversationID);
     $OldContributorData = Gdn_DataSet::Index($OldContributorData, 'UserID');
     $AddedUserIDs = array();
     // Get some information about this conversation
     $ConversationData = $this->SQL->Select('LastMessageID')->Select('CountMessages')->From('Conversation')->Where('ConversationID', $ConversationID)->Get()->FirstRow();
     // Add the user(s) if they are not already in the conversation
     foreach ($UserID as $NewUserID) {
         if (!array_key_exists($NewUserID, $OldContributorData)) {
             $AddedUserIDs[] = $NewUserID;
             $this->SQL->Insert('UserConversation', array('UserID' => $NewUserID, 'ConversationID' => $ConversationID, 'LastMessageID' => $ConversationData->LastMessageID, 'CountReadMessages' => 0, 'DateConversationUpdated' => $ConversationData['DateUpdated']));
         } elseif ($OldContributorData[$NewUserID]->Deleted) {
             $AddedUserIDs[] = $NewUserID;
             $this->SQL->Put('UserConversation', array('Deleted' => 0), array('ConversationID' => $ConversationID, 'UserID' => $NewUserID));
         }
     }
     if (count($AddedUserIDs) > 0) {
         $Session = Gdn::Session();
         // Update the Contributors field on the conversation
         $Contributors = array_unique(array_merge($AddedUserIDs, array_keys($OldContributorData)));
         sort($Contributors);
         $this->SQL->Update('Conversation')->Set('Contributors', Gdn_Format::Serialize($Contributors))->Where('ConversationID', $ConversationID)->Put();
         $ActivityModel = new ActivityModel();
         foreach ($AddedUserIDs as $AddedUserID) {
             $ActivityModel->Queue(array('ActivityType' => 'AddedToConversation', 'NotifyUserID' => $AddedUserID, 'HeadlineFormat' => T('You were added to a conversation.', '{InsertUserID,user} added {NotifyUserID,you} to a <a href="{Url,htmlencode}">conversation</a>.')), 'ConversationMessage');
         }
         $ActivityModel->SaveQueue();
         $this->UpdateUserUnreadCount($AddedUserIDs);
     }
 }
Example #12
0
 /**
  * Record advanced notifications for users.
  * 
  * @param ActivityModel $ActivityModel
  * @param array $Discussion
  * @param int $CommentID
  * @param array $NotifiedUsers 
  */
 public function RecordAdvancedNotications($ActivityModel, $Discussion, $Comment, &$NotifiedUsers)
 {
     // Grab all of the users that need to be notified.
     $Data = $this->SQL->GetWhere('UserMeta', array('Name' => 'Preferences.Email.NewDiscussion'))->ResultArray();
     // Grab all of their follow/unfollow preferences.
     $UserIDs = ConsolidateArrayValuesByKey($Data, 'UserID');
     $CategoryID = GetValue('CategoryID', $Discussion);
     $UserPrefs = $this->SQL->Select('*')->From('UserCategory')->Where('CategoryID', $CategoryID)->WhereIn('UserID', $UserIDs)->Get()->ResultArray();
     $UserPrefs = Gdn_DataSet::Index($UserPrefs, 'UserID');
     $CommentID = $Comment['CommentID'];
     foreach ($UserIDs as $UserID) {
         //         if ($UserID == $Comment['InsertUserID'])
         //            continue;
         if (in_array($UserID, $NotifiedUsers)) {
             continue;
         }
         if (array_key_exists($UserID, $UserPrefs) && $UserPrefs[$UserID]['Unfollow']) {
             continue;
         }
         $ActivityID = AddActivity($Comment['InsertUserID'], 'NewComment', Gdn_Format::Text(Gdn_Format::To($Comment['Body'], $Comment['Format'])), $UserID, "/discussion/comment/{$CommentID}#Comment_{$CommentID}", TRUE);
         //         $ActivityModel->QueueNotification($ActivityID);
         $NotifiedUsers[] = $UserID;
     }
 }
Example #13
0
 /**
  * Join external records to an array.
  *
  * @param array &$Data The data to join.
  * In order to join records each row must have the a RecordType and RecordID column.
  * @param string $Column The name of the column to put the record in.
  * If this is blank then the record will be merged into the row.
  * @param bool $Unset Whether or not to unset rows that don't have a record.
  * @since 2.3
  */
 function joinRecords(&$Data, $Column = '', $Unset = false)
 {
     $IDs = array();
     $AllowedCats = DiscussionModel::CategoryPermissions();
     if ($AllowedCats === false) {
         // This user does not have permission to view anything.
         $Data = array();
         return;
     }
     // Gather all of the ids to fetch.
     foreach ($Data as &$Row) {
         if (!$Row['RecordType']) {
             continue;
         }
         $RecordType = ucfirst(StringEndsWith($Row['RecordType'], '-Total', true, true));
         $Row['RecordType'] = $RecordType;
         $ID = $Row['RecordID'];
         $IDs[$RecordType][$ID] = $ID;
     }
     // Fetch all of the data in turn.
     $JoinData = array();
     foreach ($IDs as $RecordType => $RecordIDs) {
         if ($RecordType == 'Comment') {
             Gdn::SQL()->Select('d.Name, d.CategoryID')->Join('Discussion d', 'd.DiscussionID = r.DiscussionID');
         }
         $Rows = Gdn::SQL()->Select('r.*')->WhereIn($RecordType . 'ID', array_values($RecordIDs))->Get($RecordType . ' r')->ResultArray();
         $JoinData[$RecordType] = Gdn_DataSet::Index($Rows, array($RecordType . 'ID'));
     }
     // Join the rows.
     $Unsets = array();
     foreach ($Data as $Index => &$Row) {
         $RecordType = $Row['RecordType'];
         $ID = $Row['RecordID'];
         if (!isset($JoinData[$RecordType][$ID])) {
             if ($Unset) {
                 $Unsets[] = $Index;
             }
             continue;
             // orphaned?
         }
         $Record = $JoinData[$RecordType][$ID];
         if ($AllowedCats !== true) {
             // Check to see if the user has permission to view this record.
             $CategoryID = GetValue('CategoryID', $Record, -1);
             if (!in_array($CategoryID, $AllowedCats)) {
                 $Unsets[] = $Index;
                 continue;
             }
         }
         switch ($RecordType) {
             case 'Discussion':
                 $Url = DiscussionUrl($Record, '', '/') . '#latest';
                 break;
             case 'Comment':
                 $Url = CommentUrl($Record, '/');
                 $Record['Name'] = sprintf(T('Re: %s'), $Record['Name']);
                 break;
             default:
                 $Url = '';
         }
         $Record['Url'] = $Url;
         if ($Column) {
             $Row[$Column] = $Record;
         } else {
             $Row = array_merge($Row, $Record);
         }
     }
     foreach ($Unsets as $Index) {
         unset($Data[$Index]);
     }
     // Join the users.
     Gdn::UserModel()->JoinUsers($Data, array('InsertUserID'));
     if (!empty($Unsets)) {
         $Data = array_values($Data);
     }
 }
 /**
  * Join message counts into the discussion list.
  * @param DiscussionModel $Sender
  * @param array $Args
  */
 public function DiscussionModel_AfterAddColumns_Handler($Sender, $Args)
 {
     if (!Gdn::Session()->UserID) {
         return;
     }
     $Data = $Args['Data'];
     $Result =& $Data->Result();
     // Gather the discussion IDs.
     $DiscusisonIDs = array();
     foreach ($Result as $Row) {
         $DiscusisonIDs[] = GetValue('DiscussionID', $Row);
     }
     // Grab all of the whispers associated to the discussions being looked at.
     $Sql = Gdn::SQL()->Select('c.DiscussionID')->Select('c.CountMessages', 'sum', 'CountMessages')->Select('c.DateUpdated', 'max', 'DateLastMessage')->From('Conversation c')->WhereIn('c.DiscussionID', $DiscusisonIDs)->GroupBy('c.DiscussionID');
     if (!Gdn::Session()->CheckPermission('Conversations.Moderation.Manage')) {
         $Sql->Join('UserConversation uc', 'c.ConversationID = uc.ConversationID')->Where('uc.UserID', Gdn::Session()->UserID);
     }
     $Conversations = $Sql->Get()->ResultArray();
     $Conversations = Gdn_DataSet::Index($Conversations, 'DiscussionID');
     foreach ($Result as &$Row) {
         $DiscusisonID = GetValue('DiscussionID', $Row);
         $CRow = GetValue($DiscusisonID, $Conversations);
         if (!$CRow) {
             continue;
         }
         $DateLastViewed = GetValue('DateLastViewed', $Row);
         $DateLastMessage = $CRow['DateLastMessage'];
         $NewWhispers = Gdn_Format::ToTimestamp($DateLastViewed) < Gdn_Format::ToTimestamp($DateLastMessage);
         SetValue('CountWhispers', $Row, $CRow['CountMessages']);
         SetValue('DateLastWhisper', $Row, $DateLastMessage);
         SetValue('NewWhispers', $Row, $NewWhispers);
     }
 }
Example #15
0
 /**
  *
  *
  * @param $Users
  * @param string $UserIDColumn
  * @param string $RolesColumn
  */
 public static function setUserRoles(&$Users, $UserIDColumn = 'UserID', $RolesColumn = 'Roles')
 {
     $UserIDs = array_unique(ConsolidateArrayValuesByKey($Users, $UserIDColumn));
     // Try and get all of the mappings from the cache.
     $Keys = array();
     foreach ($UserIDs as $UserID) {
         $Keys[$UserID] = formatString(UserModel::USERROLES_KEY, array('UserID' => $UserID));
     }
     $UserRoles = Gdn::cache()->get($Keys);
     if (!is_array($UserRoles)) {
         $UserRoles = array();
     }
     // Grab all of the data that doesn't exist from the DB.
     $MissingIDs = array();
     foreach ($Keys as $UserID => $Key) {
         if (!array_key_exists($Key, $UserRoles)) {
             $MissingIDs[$UserID] = $Key;
         }
     }
     if (count($MissingIDs) > 0) {
         $DbUserRoles = Gdn::sql()->select('ur.*')->from('UserRole ur')->whereIn('ur.UserID', array_keys($MissingIDs))->get()->resultArray();
         $DbUserRoles = Gdn_DataSet::Index($DbUserRoles, 'UserID', array('Unique' => false));
         // Store the user role mappings.
         foreach ($DbUserRoles as $UserID => $Rows) {
             $RoleIDs = consolidateArrayValuesByKey($Rows, 'RoleID');
             $Key = $Keys[$UserID];
             Gdn::cache()->store($Key, $RoleIDs);
             $UserRoles[$Key] = $RoleIDs;
         }
     }
     $AllRoles = self::roles();
     // roles indexed by role id.
     // Skip personal info roles
     if (!checkPermission('Garden.PersonalInfo.View')) {
         $AllRoles = array_filter($AllRoles, 'self::FilterPersonalInfo');
     }
     // Join the users.
     foreach ($Users as &$User) {
         $UserID = val($UserIDColumn, $User);
         $Key = $Keys[$UserID];
         $RoleIDs = val($Key, $UserRoles, array());
         $Roles = array();
         foreach ($RoleIDs as $RoleID) {
             if (!array_key_exists($RoleID, $AllRoles)) {
                 continue;
             }
             $Roles[$RoleID] = $AllRoles[$RoleID]['Name'];
         }
         setValue($RolesColumn, $User, $Roles);
     }
 }
Example #16
0
 /**
  * Joins attachments to data
  *
  * <code>
  * <?php
  * $AttachmentModel->JoinAttachments($Discussion, $Comments);
  * ?>
  * </code>
  *
  * @param $Data - Data to which to attach comments
  * @param $Data2 - Optional set of Data to which to attach comments
  *
  */
 public function joinAttachments(&$Data, &$Data2 = null)
 {
     if ($Data == null) {
         return;
     }
     // Gather the Ids.
     $ForeignIDs = array();
     self::gatherIDs($Data, $ForeignIDs);
     if ($Data2) {
         self::gatherIDs($Data2, $ForeignIDs);
     }
     // Get the attachments.
     $Attachments = $this->getWhere(array('ForeignID' => array_keys($ForeignIDs)), 'DateInserted', 'desc')->resultArray();
     $Attachments = Gdn_DataSet::index($Attachments, 'ForeignID', array('Unique' => false));
     // Join the attachments.
     $this->joinAttachmentsTo($Data, $Attachments);
     if ($Data2) {
         $this->joinAttachmentsTo($Data2, $Attachments);
     }
 }
Example #17
0
 /**
  * Rebuilds the category tree. We are using the Nested Set tree model.
  * 
  * @ref http://articles.sitepoint.com/article/hierarchical-data-database/2
  * @ref http://en.wikipedia.org/wiki/Nested_set_model
  *  
  * @since 2.0.0
  * @access public
  */
 public function RebuildTree()
 {
     // Grab all of the categories.
     $Categories = $this->SQL->Get('Category', 'TreeLeft, Sort, Name');
     $Categories = Gdn_DataSet::Index($Categories->ResultArray(), 'CategoryID');
     // Make sure the tree has a root.
     if (!isset($Categories[-1])) {
         $RootCat = array('CategoryID' => -1, 'TreeLeft' => 1, 'TreeRight' => 4, 'Depth' => 0, 'InsertUserID' => 1, 'UpdateUserID' => 1, 'DateInserted' => Gdn_Format::ToDateTime(), 'DateUpdated' => Gdn_Format::ToDateTime(), 'Name' => 'Root', 'UrlCode' => '', 'Description' => 'Root of category tree. Users should never see this.', 'PermissionCategoryID' => -1, 'Sort' => 0, 'ParentCategoryID' => NULL);
         $Categories[-1] = $RootCat;
         $this->SQL->Insert('Category', $RootCat);
     }
     // Build a tree structure out of the categories.
     $Root = NULL;
     foreach ($Categories as &$Cat) {
         if (!isset($Cat['CategoryID'])) {
             continue;
         }
         // Backup category settings for efficient database saving.
         try {
             $Cat['_TreeLeft'] = $Cat['TreeLeft'];
             $Cat['_TreeRight'] = $Cat['TreeRight'];
             $Cat['_Depth'] = $Cat['Depth'];
             $Cat['_PermissionCategoryID'] = $Cat['PermissionCategoryID'];
             $Cat['_ParentCategoryID'] = $Cat['ParentCategoryID'];
         } catch (Exception $Ex) {
         }
         if ($Cat['CategoryID'] == -1) {
             $Root =& $Cat;
             continue;
         }
         $ParentID = $Cat['ParentCategoryID'];
         if (!$ParentID) {
             $ParentID = -1;
             $Cat['ParentCategoryID'] = $ParentID;
         }
         if (!isset($Categories[$ParentID]['Children'])) {
             $Categories[$ParentID]['Children'] = array();
         }
         $Categories[$ParentID]['Children'][] =& $Cat;
     }
     unset($Cat);
     // Set the tree attributes of the tree.
     $this->_SetTree($Root);
     unset($Root);
     // Save the tree structure.
     foreach ($Categories as $Cat) {
         if (!isset($Cat['CategoryID'])) {
             continue;
         }
         if ($Cat['_TreeLeft'] != $Cat['TreeLeft'] || $Cat['_TreeRight'] != $Cat['TreeRight'] || $Cat['_Depth'] != $Cat['Depth'] || $Cat['PermissionCategoryID'] != $Cat['PermissionCategoryID'] || $Cat['_ParentCategoryID'] != $Cat['ParentCategoryID'] || $Cat['Sort'] != $Cat['TreeLeft']) {
             $this->SQL->Put('Category', array('TreeLeft' => $Cat['TreeLeft'], 'TreeRight' => $Cat['TreeRight'], 'Depth' => $Cat['Depth'], 'PermissionCategoryID' => $Cat['PermissionCategoryID'], 'ParentCategoryID' => $Cat['ParentCategoryID'], 'Sort' => $Cat['TreeLeft']), array('CategoryID' => $Cat['CategoryID']));
         }
     }
     $this->SetCache();
 }
 public function GetIDs($IDs, $SkipCacheQuery = FALSE)
 {
     $DatabaseIDs = $IDs;
     $Data = array();
     if (!$SkipCacheQuery) {
         $Keys = array();
         // Make keys for cache query
         foreach ($IDs as $UserID) {
             if (!$UserID) {
                 continue;
             }
             $Keys[] = FormatString(self::USERID_KEY, array('UserID' => $UserID));
         }
         // Query cache layer
         $CacheData = Gdn::Cache()->Get($Keys);
         if (!is_array($CacheData)) {
             $CacheData = array();
         }
         foreach ($CacheData as $RealKey => $User) {
             $ResultUserID = GetValue('UserID', $User);
             $Data[$ResultUserID] = $User;
         }
         //echo "from cache:\n";
         //print_r($Data);
         $DatabaseIDs = array_diff($DatabaseIDs, array_keys($Data));
         unset($CacheData);
     }
     // Clean out bogus blank entries
     $DatabaseIDs = array_diff($DatabaseIDs, array(NULL, ''));
     // If we are missing any users from cache query, fill em up here
     if (sizeof($DatabaseIDs)) {
         $DatabaseData = $this->SQL->WhereIn('UserID', $DatabaseIDs)->GetWhere('User')->Result(DATASET_TYPE_ARRAY);
         $DatabaseData = Gdn_DataSet::Index($DatabaseData, 'UserID');
         //echo "from DB:\n";
         //print_r($DatabaseData);
         foreach ($DatabaseData as $DatabaseUserID => $DatabaseUser) {
             $Data[$DatabaseUserID] = $DatabaseUser;
             $this->SetCalculatedFields($DatabaseUser);
             $Result = $this->UserCache($DatabaseUser);
         }
     }
     $this->EventArguments['RequestedIDs'] = $IDs;
     $this->EventArguments['LoadedUsers'] =& $Data;
     $this->FireEvent('AfterGetIDs');
     return $Data;
 }
 public function JoinParticipants(&$Data) {
    $this->SQL
       ->From('UserConversation uc')
       ->Join('User u', 'u.UserID = uc.UserID');
    
    Gdn_DataSet::Join($Data, array('alias' => 'uc', 'parent' => 'ConversationID', 'column' => 'Participants', 'UserID', 'u.Name', 'u.Photo'), array('sql' => $this->SQL));
 }
 /**
  * Form to ask for the destination of the move, confirmation and permission check.
  */
 public function ConfirmDiscussionMoves($DiscussionID = NULL)
 {
     $Session = Gdn::Session();
     $this->Form = new Gdn_Form();
     $DiscussionModel = new DiscussionModel();
     $this->Title(T('Confirm'));
     if ($DiscussionID) {
         $CheckedDiscussions = (array) $DiscussionID;
         $ClearSelection = FALSE;
     } else {
         $CheckedDiscussions = Gdn::UserModel()->GetAttribute($Session->User->UserID, 'CheckedDiscussions', array());
         if (!is_array($CheckedDiscussions)) {
             $CheckedDiscussions = array();
         }
         $ClearSelection = TRUE;
     }
     $DiscussionIDs = $CheckedDiscussions;
     $CountCheckedDiscussions = count($DiscussionIDs);
     $this->SetData('CountCheckedDiscussions', $CountCheckedDiscussions);
     // Check for edit permissions on each discussion
     $AllowedDiscussions = array();
     $DiscussionData = $DiscussionModel->SQL->Select('DiscussionID, Name, DateLastComment, CategoryID')->From('Discussion')->WhereIn('DiscussionID', $DiscussionIDs)->Get();
     $DiscussionData = Gdn_DataSet::Index($DiscussionData->ResultArray(), array('DiscussionID'));
     foreach ($DiscussionData as $DiscussionID => $Discussion) {
         $Category = CategoryModel::Categories($Discussion['CategoryID']);
         if ($Category && $Category['PermsDiscussionsEdit']) {
             $AllowedDiscussions[] = $DiscussionID;
         }
     }
     $this->SetData('CountAllowed', count($AllowedDiscussions));
     $CountNotAllowed = $CountCheckedDiscussions - count($AllowedDiscussions);
     $this->SetData('CountNotAllowed', $CountNotAllowed);
     if ($this->Form->AuthenticatedPostBack()) {
         // Retrieve the category id
         $CategoryID = $this->Form->GetFormValue('CategoryID');
         $Category = CategoryModel::Categories($CategoryID);
         $RedirectLink = $this->Form->GetFormValue('RedirectLink');
         // User must have add permission on the target category
         if (!$Category['PermsDiscussionsAdd']) {
             throw ForbiddenException('@' . T('You do not have permission to add discussions to this category.'));
         }
         // Iterate and move.
         foreach ($AllowedDiscussions as $DiscussionID) {
             // Create the shadow redirect.
             if ($RedirectLink) {
                 $Discussion = GetValue($DiscussionID, $DiscussionData);
                 $DiscussionModel->DefineSchema();
                 $MaxNameLength = GetValue('Length', $DiscussionModel->Schema->GetField('Name'));
                 $RedirectDiscussion = array('Name' => SliceString(sprintf(T('Moved: %s'), $Discussion['Name']), $MaxNameLength), 'DateInserted' => $Discussion['DateLastComment'], 'Type' => 'redirect', 'CategoryID' => $Discussion['CategoryID'], 'Body' => FormatString(T('This discussion has been <a href="{url,html}">moved</a>.'), array('url' => DiscussionUrl($Discussion))), 'Format' => 'Html', 'Closed' => TRUE);
                 $RedirectID = $DiscussionModel->Save($RedirectDiscussion);
                 if (!$RedirectID) {
                     $this->Form->SetValidationResults($DiscussionModel->ValidationResults());
                     break;
                 }
             }
             $DiscussionModel->SetField($DiscussionID, 'CategoryID', $CategoryID);
         }
         // Clear selections.
         if ($ClearSelection) {
             Gdn::UserModel()->SaveAttribute($Session->UserID, 'CheckedDiscussions', FALSE);
             ModerationController::InformCheckedDiscussions($this);
         }
         if ($this->Form->ErrorCount() == 0) {
             $this->JsonTarget('', '', 'Refresh');
         }
     }
     $this->Render();
 }
 /**
  * Do code checks on an uploaded addon.
  *
  * @param int $AddonID Addon to check.
  * @param bool|false $SaveVersionID Whether to save the version id.
  * @throws Exception Addon not found.
  */
 public function check($AddonID, $SaveVersionID = false)
 {
     $this->permission('Addons.Addon.Manage');
     if ($SaveVersionID !== false) {
         // Get the version data.
         $Version = $this->AddonModel->SQL->getWhere('AddonVersion', array('AddonVersionID' => $SaveVersionID))->firstRow(DATASET_TYPE_ARRAY);
         $this->AddonModel->save($Version);
         $this->Form->setValidationResults($this->AddonModel->validationResults());
     }
     $Addon = $this->AddonModel->getID($AddonID, false, ['GetVersions' => true]);
     $AddonTypes = Gdn::sql()->get('AddonType')->resultArray();
     $AddonTypes = Gdn_DataSet::index($AddonTypes, 'AddonTypeID');
     if (!$Addon) {
         throw notFoundException('Addon');
     }
     // Get the data for the most recent version of the addon.
     $upload = new Gdn_Upload();
     // Also used per version below.
     $Path = $upload->copyLocal($Addon['File']);
     $AddonData = arrayTranslate((array) $Addon, array('AddonID', 'AddonKey', 'Name', 'Type', 'Description', 'Requirements', 'Checked'));
     try {
         $FileAddonData = UpdateModel::analyzeAddon($Path);
         if ($FileAddonData) {
             $AddonData = array_merge($AddonData, arrayTranslate($FileAddonData, array('AddonKey' => 'File_AddonKey', 'Name' => 'File_Name', 'File_Type', 'Description' => 'File_Description', 'Requirements' => 'File_Requirements', 'Checked' => 'File_Checked')));
             $AddonData['File_Type'] = valr($FileAddonData['AddonTypeID'] . '.Label', $AddonTypes, 'Unknown');
         }
         $upload->delete($Path);
     } catch (Exception $Ex) {
         $AddonData['File_Error'] = $Ex->getMessage();
     }
     $this->setData('Addon', $AddonData);
     // Go through the versions and make sure we get the versions to check out.
     $Versions = array();
     foreach ($Addon['Versions'] as $Version) {
         $Version = $Version;
         $Path = $upload->copyLocal($Version['File']);
         try {
             $VersionData = arrayTranslate((array) $Version, array('AddonVersionID', 'Version', 'AddonKey', 'Name', 'MD5', 'FileSize', 'Checked'));
             $FileVersionData = UpdateModel::analyzeAddon($Path);
             $FileVersionData = arrayTranslate($FileVersionData, array('Version' => 'File_Version', 'AddonKey' => 'File_AddonKey', 'Name' => 'File_Name', 'MD5' => 'File_MD5', 'FileSize' => 'File_FileSize', 'Checked' => 'File_Checked'));
             $upload->delete($Path);
         } catch (Exception $Ex) {
             $FileVersionData = array('File_Error' => $Ex->getMessage());
         }
         $Versions[] = array_merge($VersionData, $FileVersionData);
     }
     $this->setData('Versions', $Versions);
     $this->addModule('AddonHelpModule');
     $this->render();
 }
   public static function SetUserRoles(&$Users, $UserIDColumn = 'UserID', $RolesColumn = 'Roles') {
      $UserIDs = ConsolidateArrayValuesByKey($Users, $UserIDColumn);
      $UserRoles = Gdn::SQL()
         ->Select('ur.UserID, ur.RoleID, r.Name')
         ->From('UserRole ur')
         ->Join('Role r', 'ur.RoleID = r.RoleID')
         ->WhereIn('ur.UserID', $UserIDs)
         ->Get()->ResultArray();

      $UserRoles = Gdn_DataSet::Index($UserRoles, 'UserID', array('Unique' => FALSE));
      foreach ($Users as &$User) {
         $UserID = GetValue($UserIDColumn, $User);
         $Roles = GetValue($UserID, $UserRoles, array());
         $Roles = ConsolidateArrayValuesByKey($Roles, 'RoleID', 'Name');
         SetValue($RolesColumn, $User, $Roles);
      }
   }
Example #23
0
 public static function Messages($ID = FALSE)
 {
     if ($ID === NULL) {
         Gdn::Cache()->Remove('Messages');
         return;
     }
     $Messages = Gdn::Cache()->Get('Messages');
     if ($Messages === Gdn_Cache::CACHEOP_FAILURE) {
         $Messages = Gdn::SQL()->Get('Message', 'Sort')->ResultArray();
         $Messages = Gdn_DataSet::Index($Messages, array('MessageID'));
         Gdn::Cache()->Store('Messages', $Messages);
     }
     if ($ID === FALSE) {
         return $Messages;
     } else {
         return GetValue($ID, $Messages);
     }
 }
 /**
  * Get all of the global permissions for one or more roles.
  *
  * @param int|array $RoleID The role(s) to get the permissions for.
  * @param string $LimitToSuffix Whether or not to limit the permissions to a suffix.
  * @return Returns an
  */
 public function getGlobalPermissions($RoleID, $LimitToSuffix = '')
 {
     $RoleIDs = (array) $RoleID;
     // Get the global permissions.
     $Data = $this->SQL->select('*')->from('Permission p')->whereIn('p.RoleID', array_merge($RoleIDs, array(0)))->where('p.JunctionTable is null')->orderBy('p.RoleID')->get()->resultArray();
     $this->_MergeDisabledPermissions($Data);
     $Data = Gdn_DataSet::Index($Data, 'RoleID');
     $DefaultRow = $Data[0];
     unset($Data[0], $DefaultRow['RoleID'], $DefaultRow['JunctionTable'], $DefaultRow['JunctionColumn'], $DefaultRow['JunctionID']);
     $DefaultRow = $this->StripPermissions($DefaultRow, $DefaultRow, $LimitToSuffix);
     if ($RoleID) {
         // When editing a role make sure the default permissions are false so as not to be misleading.
         $DefaultRow = array_fill_keys(array_keys($DefaultRow), 0);
     }
     foreach ($RoleIDs as $ID) {
         if (isset($Data[$ID])) {
             $Data[$ID] = array_intersect_key($Data[$ID], $DefaultRow);
         } else {
             $Data[$ID] = $DefaultRow;
             $Data[$ID]['PermissionID'] = null;
         }
     }
     if (count($RoleIDs) === 1) {
         return array_pop($Data);
     } else {
         return $Data;
     }
 }
Example #25
0
 /**
  * Get all messages or one message.
  *
  * @param int|bool $ID ID of message to get.
  * @return array|null
  */
 public static function messages($ID = false)
 {
     if ($ID === null) {
         Gdn::cache()->remove('Messages');
         return;
     }
     $Messages = Gdn::cache()->get('Messages');
     if ($Messages === Gdn_Cache::CACHEOP_FAILURE) {
         $Messages = Gdn::sql()->get('Message', 'Sort')->resultArray();
         $Messages = Gdn_DataSet::index($Messages, array('MessageID'));
         Gdn::cache()->store('Messages', $Messages);
     }
     if ($ID === false) {
         return $Messages;
     } else {
         return val($ID, $Messages);
     }
 }
Example #26
0
 /**
  * @param type $Activities 
  * @since 2.1
  */
 public function JoinComments(&$Activities)
 {
     // Grab all of the activity IDs.
     $ActivityIDs = array();
     foreach ($Activities as $Activity) {
         if ($ID = GetValue('CommentActivityID', $Activity['Data'])) {
             // This activity shares its comments with another activity.
             $ActivityIDs[] = $ID;
         } else {
             $ActivityIDs[] = $Activity['ActivityID'];
         }
     }
     $ActivityIDs = array_unique($ActivityIDs);
     $Comments = $this->GetComments($ActivityIDs);
     $Comments = Gdn_DataSet::Index($Comments, array('ActivityID'), array('Unique' => FALSE));
     foreach ($Activities as &$Activity) {
         $ID = GetValue('CommentActivityID', $Activity['Data']);
         if (!$ID) {
             $ID = $Activity['ActivityID'];
         }
         if (isset($Comments[$ID])) {
             $Activity['Comments'] = $Comments[$ID];
         } else {
             $Activity['Comments'] = array();
         }
     }
 }
 /**
  * Add another user to the conversation.
  *
  * @since 2.0.0
  * @access public
  *
  * @param int $ConversationID Unique ID of conversation effected.
  * @param int $UserID Unique ID of current user.
  */
 public function addUserToConversation($ConversationID, $UserID)
 {
     if (!is_array($UserID)) {
         $UserID = array($UserID);
     }
     // First define the current users in the conversation
     $OldContributorData = $this->getRecipients($ConversationID);
     $OldContributorData = Gdn_DataSet::index($OldContributorData, 'UserID');
     $AddedUserIDs = array();
     // Get some information about this conversation
     $ConversationData = $this->SQL->select('LastMessageID')->select('DateUpdated')->select('CountMessages')->from('Conversation')->where('ConversationID', $ConversationID)->get()->firstRow();
     // Add the user(s) if they are not already in the conversation
     foreach ($UserID as $NewUserID) {
         if (!array_key_exists($NewUserID, $OldContributorData)) {
             $AddedUserIDs[] = $NewUserID;
             $this->SQL->insert('UserConversation', array('UserID' => $NewUserID, 'ConversationID' => $ConversationID, 'LastMessageID' => $ConversationData->LastMessageID, 'CountReadMessages' => 0, 'DateConversationUpdated' => $ConversationData->DateUpdated));
         } elseif ($OldContributorData[$NewUserID]->Deleted) {
             $AddedUserIDs[] = $NewUserID;
             $this->SQL->put('UserConversation', array('Deleted' => 0), array('ConversationID' => $ConversationID, 'UserID' => $NewUserID));
         }
     }
     if (count($AddedUserIDs) > 0) {
         $ActivityModel = new ActivityModel();
         foreach ($AddedUserIDs as $AddedUserID) {
             $ActivityModel->queue(array('ActivityType' => 'AddedToConversation', 'NotifyUserID' => $AddedUserID, 'HeadlineFormat' => t('You were added to a conversation.', '{ActivityUserID,User} added you to a <a href="{Url,htmlencode}">conversation</a>.'), 'Route' => '/messages/' . $ConversationID), 'ConversationMessage');
         }
         $ActivityModel->saveQueue();
         $this->updateUserUnreadCount($AddedUserIDs);
         $this->updateParticipantCount($ConversationID);
     }
 }
 /**
  * Add the tag input to the discussion form.
  * @param Gdn_Controller $Sender
  */
 public function PostController_AfterDiscussionFormOptions_Handler($Sender)
 {
     if (in_array($Sender->RequestMethod, array('discussion', 'editdiscussion', 'question'))) {
         // Setup, get most popular tags
         $TagModel = TagModel::instance();
         $Tags = $TagModel->GetWhere(array('Type' => array_keys($TagModel->defaultTypes())), 'CountDiscussions', 'desc', C('Plugins.Tagging.ShowLimit', 50))->Result(DATASET_TYPE_ARRAY);
         $TagsHtml = count($Tags) ? '' : T('No tags have been created yet.');
         $Tags = Gdn_DataSet::Index($Tags, 'FullName');
         ksort($Tags);
         // The tags must be fetched.
         if ($Sender->Request->IsPostBack()) {
             $tag_ids = TagModel::SplitTags($Sender->Form->GetFormValue('Tags'));
             $tags = TagModel::instance()->GetWhere(array('TagID' => $tag_ids))->ResultArray();
             $tags = ConsolidateArrayValuesByKey($tags, 'FullName', 'TagID');
         } else {
             // The tags should be set on the data.
             $tags = ConsolidateArrayValuesByKey($Sender->Data('Tags', array()), 'TagID', 'FullName');
             $xtags = $Sender->Data('XTags', array());
             foreach (TagModel::instance()->defaultTypes() as $key => $row) {
                 if (isset($xtags[$key])) {
                     $xtags2 = ConsolidateArrayValuesByKey($xtags[$key], 'TagID', 'FullName');
                     foreach ($xtags2 as $id => $name) {
                         $tags[$id] = $name;
                     }
                 }
             }
         }
         echo '<div class="Form-Tags P">';
         // Tag text box
         echo $Sender->Form->Label('Tags', 'Tags');
         echo $Sender->Form->TextBox('Tags', array('data-tags' => json_encode($tags)));
         // Available tags
         echo Wrap(Anchor(T('Show popular tags'), '#'), 'span', array('class' => 'ShowTags'));
         foreach ($Tags as $Tag) {
             $TagsHtml .= Anchor(htmlspecialchars($Tag['FullName']), '#', 'AvailableTag', array('data-name' => $Tag['Name'], 'data-id' => $Tag['TagID'])) . ' ';
         }
         echo Wrap($TagsHtml, 'div', array('class' => 'Hidden AvailableTags'));
         echo '</div>';
     }
 }
 /**
  * Called to prepare data grab, and then cache the results on the software level for the request.
  *
  * This will call PreloadDiscussionMedia, which will either query the db, or query memcached.
  *
  * @param mixed $Sender
  */
 protected function cacheAttachedMedia($Sender)
 {
     if ($Sender->data('Conversation')) {
         $ConversationMessageIDList = $this->getConversationMessageIDList(val('ConversationID', $Sender->data('Conversation')));
         if (count($ConversationMessageIDList)) {
             $MediaData = $this->preloadDiscussionMedia(val('ConversationID', $Sender->data('Conversation')), $ConversationMessageIDList, 'conversation');
         }
         $this->mediaCache = $MediaData;
         return;
     }
     if ($Sender->data('Messages')) {
         $Message = $Sender->data('Messages')->result();
         $MessageID = val(0, $Message)->MessageID;
         $MessageIDList = array($MessageID);
         if (count($MessageIDList)) {
             $MediaData = $this->preloadDiscussionMedia(val('ConversationID', $Sender->data('Messages')), $MessageIDList, 'conversation');
         }
         $this->mediaCache = $MediaData;
         return;
     }
     $DiscussionID = null;
     $Comments = $Sender->data('Comments');
     if ($answers = $Sender->data('Answers')) {
         $commentsArray = $Comments->resultObject();
         $commentsArray = array_merge($answers, $commentsArray);
         $commentsData = new Gdn_DataSet();
         $commentsData->importDataset($commentsArray);
         $Comments = $commentsData;
     }
     $CommentIDList = array();
     $MediaData = array();
     if ($Sender->data('Discussion.DiscussionID')) {
         $DiscussionID = $Sender->data('Discussion.DiscussionID');
     }
     if (is_null($DiscussionID) && !empty($Comments)) {
         $DiscussionID = $Comments->firstRow()->DiscussionID;
     }
     if ($DiscussionID) {
         if ($Comments instanceof Gdn_DataSet && $Comments->numRows()) {
             $Comments->dataSeek(-1);
             while ($Comment = $Comments->nextRow()) {
                 $CommentIDList[] = $Comment->CommentID;
             }
         } elseif (!empty($Sender->Discussion)) {
             $CommentIDList[] = $Sender->DiscussionID = $Sender->Discussion->DiscussionID;
         }
         if (isset($Sender->Comment) && isset($Sender->Comment->CommentID)) {
             $CommentIDList[] = $Sender->Comment->CommentID;
         }
         // TODO
         // Added note for caching here because it was the CommentIDList that is the main problem.
         // Note about memcaching:
         // Main problem with this is when a new comment is posted. It will only
         // have that current comment in the list, which, after calling
         // PreloadDiscussionMedia, means it will be the only piece of data added
         // to the cache, which prevents all the rest of the comments from loading
         // their own attachments. Consider either adding to the cache when a new
         // file is uploaded, or just getting a list of all comments for a discussion.
         // This is why memcaching has been disabled for now. There are a couple
         // ways to prevent this, but they all seem unnecessary.
         if (count($CommentIDList)) {
             $MediaData = $this->preloadDiscussionMedia($DiscussionID, $CommentIDList);
         }
         $this->mediaCache = $MediaData;
     }
 }
 /**
  * Form to ask for the destination of the move, confirmation and permission check.
  */
 public function confirmDiscussionMoves($DiscussionID = null)
 {
     $Session = Gdn::session();
     $this->Form = new Gdn_Form();
     $DiscussionModel = new DiscussionModel();
     $CategoryModel = new CategoryModel();
     $this->title(t('Confirm'));
     if ($DiscussionID) {
         $CheckedDiscussions = (array) $DiscussionID;
         $ClearSelection = false;
     } else {
         $CheckedDiscussions = Gdn::userModel()->getAttribute($Session->User->UserID, 'CheckedDiscussions', array());
         if (!is_array($CheckedDiscussions)) {
             $CheckedDiscussions = array();
         }
         $ClearSelection = true;
     }
     $DiscussionIDs = $CheckedDiscussions;
     $CountCheckedDiscussions = count($DiscussionIDs);
     $this->setData('CountCheckedDiscussions', $CountCheckedDiscussions);
     // Check for edit permissions on each discussion
     $AllowedDiscussions = array();
     $DiscussionData = $DiscussionModel->SQL->select('DiscussionID, Name, DateLastComment, CategoryID, CountComments')->from('Discussion')->whereIn('DiscussionID', $DiscussionIDs)->get();
     $DiscussionData = Gdn_DataSet::Index($DiscussionData->resultArray(), array('DiscussionID'));
     foreach ($DiscussionData as $DiscussionID => $Discussion) {
         $Category = CategoryModel::categories($Discussion['CategoryID']);
         if ($Category && $Category['PermsDiscussionsEdit']) {
             $AllowedDiscussions[] = $DiscussionID;
         }
     }
     $this->setData('CountAllowed', count($AllowedDiscussions));
     $CountNotAllowed = $CountCheckedDiscussions - count($AllowedDiscussions);
     $this->setData('CountNotAllowed', $CountNotAllowed);
     if ($this->Form->authenticatedPostBack()) {
         // Retrieve the category id
         $CategoryID = $this->Form->getFormValue('CategoryID');
         $Category = CategoryModel::categories($CategoryID);
         $RedirectLink = $this->Form->getFormValue('RedirectLink');
         // User must have add permission on the target category
         if (!$Category['PermsDiscussionsAdd']) {
             throw forbiddenException('@' . t('You do not have permission to add discussions to this category.'));
         }
         $AffectedCategories = array();
         // Iterate and move.
         foreach ($AllowedDiscussions as $DiscussionID) {
             $Discussion = val($DiscussionID, $DiscussionData);
             // Create the shadow redirect.
             if ($RedirectLink) {
                 $DiscussionModel->defineSchema();
                 $MaxNameLength = val('Length', $DiscussionModel->Schema->GetField('Name'));
                 $RedirectDiscussion = array('Name' => SliceString(sprintf(t('Moved: %s'), $Discussion['Name']), $MaxNameLength), 'DateInserted' => $Discussion['DateLastComment'], 'Type' => 'redirect', 'CategoryID' => $Discussion['CategoryID'], 'Body' => formatString(t('This discussion has been <a href="{url,html}">moved</a>.'), array('url' => DiscussionUrl($Discussion))), 'Format' => 'Html', 'Closed' => true);
                 // Pass a forced input formatter around this exception.
                 if (c('Garden.ForceInputFormatter')) {
                     $InputFormat = c('Garden.InputFormatter');
                     saveToConfig('Garden.InputFormatter', 'Html', false);
                 }
                 $RedirectID = $DiscussionModel->save($RedirectDiscussion);
                 // Reset the input formatter
                 if (c('Garden.ForceInputFormatter')) {
                     saveToConfig('Garden.InputFormatter', $InputFormat, false);
                 }
                 if (!$RedirectID) {
                     $this->Form->setValidationResults($DiscussionModel->validationResults());
                     break;
                 }
             }
             $DiscussionModel->setField($DiscussionID, 'CategoryID', $CategoryID);
             if (!isset($AffectedCategories[$Discussion['CategoryID']])) {
                 $AffectedCategories[$Discussion['CategoryID']] = array(-1, -$Discussion['CountComments']);
             } else {
                 $AffectedCategories[$Discussion['CategoryID']][0] -= 1;
                 $AffectedCategories[$Discussion['CategoryID']][1] -= $Discussion['CountComments'];
             }
             if (!isset($AffectedCategories[$CategoryID])) {
                 $AffectedCategories[$CategoryID] = array(1, $Discussion['CountComments']);
             } else {
                 $AffectedCategories[$CategoryID][0] += 1;
                 $AffectedCategories[$CategoryID][1] += $Discussion['CountComments'];
             }
         }
         // Update recent posts and counts on all affected categories.
         foreach ($AffectedCategories as $CategoryID => $Counts) {
             $CategoryModel->SetRecentPost($CategoryID);
             $CategoryModel->SQL->update('Category')->set('CountDiscussions', 'CountDiscussions' . ($Counts[0] < 0 ? ' - ' : ' + ') . abs($Counts[0]), false)->set('CountComments', 'CountComments' . ($Counts[1] < 0 ? ' - ' : ' + ') . abs($Counts[1]), false)->where('CategoryID', $CategoryID)->put();
         }
         // Clear selections.
         if ($ClearSelection) {
             Gdn::userModel()->saveAttribute($Session->UserID, 'CheckedDiscussions', false);
             ModerationController::InformCheckedDiscussions($this);
         }
         if ($this->Form->errorCount() == 0) {
             $this->jsonTarget('', '', 'Refresh');
         }
     }
     $this->render();
 }