/** * Re-fetch a discussion's content based on its foreign url. * @param type $DiscussionID */ public function refetchPageInfo($DiscussionID) { // Make sure we are posting back. if (!$this->Request->isAuthenticatedPostBack(true)) { throw permissionException('Javascript'); } // Grab the discussion. $Discussion = $this->DiscussionModel->getID($DiscussionID); if (!$Discussion) { throw notFoundException('Discussion'); } // Make sure the user has permission to edit this discussion. $this->permission('Vanilla.Discussions.Edit', true, 'Category', $Discussion->PermissionCategoryID); $ForeignUrl = valr('Attributes.ForeignUrl', $Discussion); if (!$ForeignUrl) { throw new Gdn_UserException(t("This discussion isn't associated with a url.")); } $Stub = $this->DiscussionModel->fetchPageInfo($ForeignUrl, true); // Save the stub. $this->DiscussionModel->setField($DiscussionID, (array) $Stub); // Send some of the stuff back. if (isset($Stub['Name'])) { $this->jsonTarget('.PageTitle h1', Gdn_Format::text($Stub['Name'])); } if (isset($Stub['Body'])) { $this->jsonTarget("#Discussion_{$DiscussionID} .Message", Gdn_Format::to($Stub['Body'], $Stub['Format'])); } $this->informMessage('The page was successfully fetched.'); $this->render('Blank', 'Utility', 'Dashboard'); }
public function notifyNewDiscussion($DiscussionID) { if (!c('Vanilla.QueueNotifications')) { throw forbiddenException('NotifyNewDiscussion'); } if (!$this->Request->isPostBack()) { throw forbiddenException('GET'); } // Grab the discussion. $Discussion = $this->DiscussionModel->getID($DiscussionID); if (!$Discussion) { throw notFoundException('Discussion'); } if (val('Notified', $Discussion) != ActivityModel::SENT_PENDING) { die('Not pending'); } // Mark the notification as in progress. $this->DiscussionModel->setField($DiscussionID, 'Notified', ActivityModel::SENT_INPROGRESS); $discussionType = val('Type', $Discussion); if ($discussionType) { $Code = "HeadlineFormat.Discussion.{$discussionType}"; } else { $Code = 'HeadlineFormat.Discussion'; } $HeadlineFormat = t($Code, '{ActivityUserID,user} started a new discussion: <a href="{Url,html}">{Data.Name,text}</a>'); $Category = CategoryModel::categories(val('CategoryID', $Discussion)); $Activity = array('ActivityType' => 'Discussion', 'ActivityUserID' => $Discussion->InsertUserID, 'HeadlineFormat' => $HeadlineFormat, 'RecordType' => 'Discussion', 'RecordID' => $DiscussionID, 'Route' => DiscussionUrl($Discussion), 'Data' => array('Name' => $Discussion->Name, 'Category' => val('Name', $Category))); $ActivityModel = new ActivityModel(); $this->DiscussionModel->NotifyNewDiscussion($Discussion, $ActivityModel, $Activity); $ActivityModel->SaveQueue(); $this->DiscussionModel->setField($DiscussionID, 'Notified', ActivityModel::SENT_OK); die('OK'); }
/** * 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(); }
/** * Remove an addon from a discussion. * * @param int $DiscussionID Discussion to remove addon attachment. * @throws Gdn_UserException Discussion not found. */ public function detachFromDiscussion($DiscussionID = null) { $this->permission('Addons.Addon.Manage'); $DiscussionModel = new DiscussionModel(); $Discussion = $DiscussionModel->getID($DiscussionID); if ($Discussion) { $Addon = $this->AddonModel->getID($Discussion->AddonID); $this->Form->setData($Addon); $RedirectUrl = 'discussion/' . $Discussion->DiscussionID; } else { throw notFoundException('Discussion'); } if ($this->Form->authenticatedPostBack()) { if (!$this->Form->getFormValue('DetachConfirm', false)) { $this->Form->addError(t('You must confirm the detachment'), 'DetachConfirm'); } else { $DiscussionModel->setField($DiscussionID, 'AddonID', null); if ($this->deliveryType() === DELIVERY_TYPE_ALL) { redirect($RedirectUrl); } else { $this->informMessage(t('Successfully detached addon')); $this->jsonTarget('.Warning.AddonAttachment', null, 'Remove'); $this->jsonTarget('a.AttachAddonDiscussion.Popup', t('Attach Addon...'), 'Text'); } } } $this->render('detach'); }
/** * Add a method to the ModerationController to handle merging discussions. * * @param Gdn_Controller $Sender */ public function moderationController_mergeDiscussions_create($Sender) { $Session = Gdn::session(); $Sender->Form = new Gdn_Form(); $Sender->title(t('Merge Discussions')); $DiscussionModel = new DiscussionModel(); $CheckedDiscussions = Gdn::userModel()->getAttribute($Session->User->UserID, 'CheckedDiscussions', array()); if (!is_array($CheckedDiscussions)) { $CheckedDiscussions = array(); } $DiscussionIDs = $CheckedDiscussions; $Sender->setData('DiscussionIDs', $DiscussionIDs); $CountCheckedDiscussions = count($DiscussionIDs); $Sender->setData('CountCheckedDiscussions', $CountCheckedDiscussions); $Discussions = $DiscussionModel->SQL->whereIn('DiscussionID', $DiscussionIDs)->get('Discussion')->resultArray(); $Sender->setData('Discussions', $Discussions); // Make sure none of the selected discussions are ghost redirects. $discussionTypes = array_column($Discussions, 'Type'); if (in_array('redirect', $discussionTypes)) { throw Gdn_UserException('You cannot merge redirects.', 400); } // Perform the merge if ($Sender->Form->authenticatedPostBack()) { // Create a new discussion record $MergeDiscussion = false; $MergeDiscussionID = $Sender->Form->getFormValue('MergeDiscussionID'); foreach ($Discussions as $Discussion) { if ($Discussion['DiscussionID'] == $MergeDiscussionID) { $MergeDiscussion = $Discussion; break; } } $RedirectLink = $Sender->Form->getFormValue('RedirectLink'); if ($MergeDiscussion) { $ErrorCount = 0; // Verify that the user has permission to perform the merge. $Category = CategoryModel::categories($MergeDiscussion['CategoryID']); if ($Category && !$Category['PermsDiscussionsEdit']) { throw permissionException('Vanilla.Discussions.Edit'); } $DiscussionModel->defineSchema(); $MaxNameLength = val('Length', $DiscussionModel->Schema->getField('Name')); // Assign the comments to the new discussion record $DiscussionModel->SQL->update('Comment')->set('DiscussionID', $MergeDiscussionID)->whereIn('DiscussionID', $DiscussionIDs)->put(); $CommentModel = new CommentModel(); foreach ($Discussions as $Discussion) { if ($Discussion['DiscussionID'] == $MergeDiscussionID) { continue; } // Create a comment out of the discussion. $Comment = arrayTranslate($Discussion, array('Body', 'Format', 'DateInserted', 'InsertUserID', 'InsertIPAddress', 'DateUpdated', 'UpdateUserID', 'UpdateIPAddress', 'Attributes', 'Spam', 'Likes', 'Abuse')); $Comment['DiscussionID'] = $MergeDiscussionID; $CommentModel->Validation->results(true); $CommentID = $CommentModel->save($Comment); if ($CommentID) { // Move any attachments (FileUpload plugin awareness) if (class_exists('MediaModel')) { $MediaModel = new MediaModel(); $MediaModel->reassign($Discussion['DiscussionID'], 'discussion', $CommentID, 'comment'); } if ($RedirectLink) { // The discussion needs to be changed to a moved link. $RedirectDiscussion = array('Name' => SliceString(sprintf(t('Merged: %s'), $Discussion['Name']), $MaxNameLength), 'Type' => 'redirect', 'Body' => formatString(t('This discussion has been <a href="{url,html}">merged</a>.'), array('url' => DiscussionUrl($MergeDiscussion))), 'Format' => 'Html'); $DiscussionModel->setField($Discussion['DiscussionID'], $RedirectDiscussion); $CommentModel->updateCommentCount($Discussion['DiscussionID']); $CommentModel->removePageCache($Discussion['DiscussionID']); } else { // Delete discussion that was merged. $DiscussionModel->delete($Discussion['DiscussionID']); } } else { $Sender->informMessage($CommentModel->Validation->resultsText()); $ErrorCount++; } } // Update counts on all affected discussions. $CommentModel->updateCommentCount($MergeDiscussionID); $CommentModel->removePageCache($MergeDiscussionID); // Clear selections Gdn::userModel()->saveAttribute($Session->UserID, 'CheckedDiscussions', false); ModerationController::informCheckedDiscussions($Sender); if ($ErrorCount == 0) { $Sender->jsonTarget('', '', 'Refresh'); } } } $Sender->render('MergeDiscussions', '', 'plugins/SplitMerge'); }