Get data for a single discussion by ID.
public getID ( integer $DiscussionID, string $DataSetType = DATASET_TYPE_OBJECT, array $Options = [] ) : object | ||
$DiscussionID | integer | Unique ID of discussion to get. |
$DataSetType | string | One of the **DATASET_TYPE_*** constants. |
$Options | array | An array of extra options for the query. |
return | object | SQL result. |
/** * 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 pluginController_quoteMention_create($sender, $discussionID, $commentID, $username) { $sender->deliveryMethod(DELIVERY_METHOD_JSON); $user = Gdn::userModel()->getByUsername($username); $discussionModel = new DiscussionModel(); $discussion = $discussionModel->getID($discussionID); if (!$user || !$discussion) { throw notFoundException(); } // Make sure this endpoint can't be used to snoop around. $sender->permission('Vanilla.Discussions.View', true, 'Category', $discussion->PermissionCategoryID); // Find the previous comment of the mentioned user in this discussion. $item = Gdn::sql()->getWhere('Comment', ['DiscussionID' => $discussion->DiscussionID, 'InsertUserID' => $user->UserID, 'CommentID <' => $commentID], 'CommentID', 'desc', 1)->firstRow(); // The items ID in the DOM used for highlighting. if ($item) { $target = '#Comment_' . $item->CommentID; // The mentioned user might be the discussion creator. } elseif ($discussion->InsertUserID == $user->UserID) { $item = $discussion; $target = '#Discussion_' . $item->DiscussionID; } if (!$item) { // A success response code always means that a comment was found. $sender->statusCode(404); } $sender->renderData($item ? ['html' => nl2br(sliceString(Gdn_Format::plainText($item->Body, $item->Format), c('QuoteMention.MaxLength', 400))), 'target' => $target] : []); }
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'); }
/** * Insert or update meta data about the comment. * * Updates unread comment totals, bookmarks, and activity. Sends notifications. * * @since 2.0.0 * @access public * * @param array $CommentID Unique ID for this comment. * @param int $Insert Used as a boolean for whether this is a new comment. * @param bool $CheckExisting Not used. * @param bool $IncUser Whether or not to just increment the user's comment count rather than recalculate it. */ public function save2($CommentID, $Insert, $CheckExisting = true, $IncUser = false) { $Session = Gdn::session(); $UserModel = Gdn::userModel(); // Load comment data $Fields = $this->getID($CommentID, DATASET_TYPE_ARRAY); // Clear any session stashes related to this discussion $DiscussionModel = new DiscussionModel(); $DiscussionID = val('DiscussionID', $Fields); $Discussion = $DiscussionModel->getID($DiscussionID); $Session->Stash('CommentForForeignID_' . GetValue('ForeignID', $Discussion)); // Make a quick check so that only the user making the comment can make the notification. // This check may be used in the future so should not be depended on later in the method. if (Gdn::controller()->deliveryType() === DELIVERY_TYPE_ALL && $Fields['InsertUserID'] != $Session->UserID) { return; } // Update the discussion author's CountUnreadDiscussions (ie. // the number of discussions created by the user that s/he has // unread messages in) if this comment was not added by the // discussion author. $this->UpdateUser($Fields['InsertUserID'], $IncUser && $Insert); // Mark the user as participated. $this->SQL->replace('UserDiscussion', array('Participated' => 1), array('DiscussionID' => $DiscussionID, 'UserID' => val('InsertUserID', $Fields))); if ($Insert) { // UPDATE COUNT AND LAST COMMENT ON CATEGORY TABLE if ($Discussion->CategoryID > 0) { $Category = CategoryModel::categories($Discussion->CategoryID); if ($Category) { $CountComments = val('CountComments', $Category, 0) + 1; if ($CountComments < self::COMMENT_THRESHOLD_SMALL || $CountComments < self::COMMENT_THRESHOLD_LARGE && $CountComments % self::COUNT_RECALC_MOD == 0) { $CountComments = $this->SQL->select('CountComments', 'sum', 'CountComments')->from('Discussion')->where('CategoryID', $Discussion->CategoryID)->get()->firstRow()->CountComments; } } $CategoryModel = new CategoryModel(); $CategoryModel->setField($Discussion->CategoryID, array('LastDiscussionID' => $DiscussionID, 'LastCommentID' => $CommentID, 'CountComments' => $CountComments, 'LastDateInserted' => $Fields['DateInserted'])); // Update the cache. $CategoryCache = array('LastTitle' => $Discussion->Name, 'LastUserID' => $Fields['InsertUserID'], 'LastUrl' => DiscussionUrl($Discussion) . '#latest'); CategoryModel::SetCache($Discussion->CategoryID, $CategoryCache); } // Prepare the notification queue. $ActivityModel = new ActivityModel(); $HeadlineFormat = t('HeadlineFormat.Comment', '{ActivityUserID,user} commented on <a href="{Url,html}">{Data.Name,text}</a>'); $Category = CategoryModel::categories($Discussion->CategoryID); $Activity = array('ActivityType' => 'Comment', 'ActivityUserID' => $Fields['InsertUserID'], 'HeadlineFormat' => $HeadlineFormat, 'RecordType' => 'Comment', 'RecordID' => $CommentID, 'Route' => "/discussion/comment/{$CommentID}#Comment_{$CommentID}", 'Data' => array('Name' => $Discussion->Name, 'Category' => val('Name', $Category))); // Allow simple fulltext notifications if (c('Vanilla.Activity.ShowCommentBody', false)) { $Activity['Story'] = val('Body', $Fields); $Activity['Format'] = val('Format', $Fields); } // Pass generic activity to events. $this->EventArguments['Activity'] = $Activity; // Notify users who have bookmarked the discussion. $BookmarkData = $DiscussionModel->GetBookmarkUsers($DiscussionID); foreach ($BookmarkData->result() as $Bookmark) { // Check user can still see the discussion. if (!$UserModel->GetCategoryViewPermission($Bookmark->UserID, $Discussion->CategoryID)) { continue; } $Activity['NotifyUserID'] = $Bookmark->UserID; $Activity['Data']['Reason'] = 'bookmark'; $ActivityModel->Queue($Activity, 'BookmarkComment', array('CheckRecord' => true)); } // Notify users who have participated in the discussion. $ParticipatedData = $DiscussionModel->GetParticipatedUsers($DiscussionID); foreach ($ParticipatedData->result() as $UserRow) { if (!$UserModel->GetCategoryViewPermission($UserRow->UserID, $Discussion->CategoryID)) { continue; } $Activity['NotifyUserID'] = $UserRow->UserID; $Activity['Data']['Reason'] = 'participated'; $ActivityModel->Queue($Activity, 'ParticipateComment', array('CheckRecord' => true)); } // Record user-comment activity. if ($Discussion != false) { $InsertUserID = val('InsertUserID', $Discussion); // Check user can still see the discussion. if ($UserModel->GetCategoryViewPermission($InsertUserID, $Discussion->CategoryID)) { $Activity['NotifyUserID'] = $InsertUserID; $Activity['Data']['Reason'] = 'mine'; $ActivityModel->Queue($Activity, 'DiscussionComment'); } } // Record advanced notifications. if ($Discussion !== false) { $Activity['Data']['Reason'] = 'advanced'; $this->RecordAdvancedNotications($ActivityModel, $Activity, $Discussion); } // Notify any users who were mentioned in the comment. $Usernames = GetMentions($Fields['Body']); foreach ($Usernames as $i => $Username) { $User = $UserModel->GetByUsername($Username); if (!$User) { unset($Usernames[$i]); continue; } // Check user can still see the discussion. if (!$UserModel->GetCategoryViewPermission($User->UserID, $Discussion->CategoryID)) { continue; } $HeadlineFormatBak = $Activity['HeadlineFormat']; $Activity['HeadlineFormat'] = t('HeadlineFormat.Mention', '{ActivityUserID,user} mentioned you in <a href="{Url,html}">{Data.Name,text}</a>'); $Activity['NotifyUserID'] = $User->UserID; $Activity['Data']['Reason'] = 'mention'; $ActivityModel->Queue($Activity, 'Mention'); $Activity['HeadlineFormat'] = $HeadlineFormatBak; } unset($Activity['Data']['Reason']); // Throw an event for users to add their own events. $this->EventArguments['Comment'] = $Fields; $this->EventArguments['Discussion'] = $Discussion; $this->EventArguments['NotifiedUsers'] = array_keys(ActivityModel::$Queue); $this->EventArguments['MentionedUsers'] = $Usernames; $this->EventArguments['ActivityModel'] = $ActivityModel; $this->fireEvent('BeforeNotification'); // Send all notifications. $ActivityModel->SaveQueue(); } }
/** * * * @param $Type * @param $ID * @param $QuoteData * @param bool $Format */ protected function formatQuote($Type, $ID, &$QuoteData, $Format = false) { // Temporarily disable Emoji parsing (prevent double-parsing to HTML) $emojiEnabled = Emoji::instance()->enabled; Emoji::instance()->enabled = false; if (!$Format) { $Format = c('Garden.InputFormatter'); } $Type = strtolower($Type); $Model = false; switch ($Type) { case 'comment': $Model = new CommentModel(); break; case 'discussion': $Model = new DiscussionModel(); break; default: break; } //$QuoteData = array(); if ($Model) { $Data = $Model->getID($ID); $NewFormat = $Format; if ($NewFormat == 'Wysiwyg') { $NewFormat = 'Html'; } $QuoteFormat = $Data->Format; if ($QuoteFormat == 'Wysiwyg') { $QuoteFormat = 'Html'; } // Perform transcoding if possible $NewBody = $Data->Body; if ($QuoteFormat != $NewFormat) { if (in_array($NewFormat, array('Html', 'Wysiwyg'))) { $NewBody = Gdn_Format::to($NewBody, $QuoteFormat); } elseif ($QuoteFormat == 'Html' && $NewFormat == 'BBCode') { $NewBody = Gdn_Format::text($NewBody, false); } elseif ($QuoteFormat == 'Text' && $NewFormat == 'BBCode') { $NewBody = Gdn_Format::text($NewBody, false); } else { $NewBody = Gdn_Format::plainText($NewBody, $QuoteFormat); } if (!in_array($NewFormat, array('Html', 'Wysiwyg'))) { Gdn::controller()->informMessage(sprintf(t('The quote had to be converted from %s to %s.', 'The quote had to be converted from %s to %s. Some formatting may have been lost.'), htmlspecialchars($QuoteFormat), htmlspecialchars($NewFormat))); } } $Data->Body = $NewBody; // Format the quote according to the format. switch ($Format) { case 'Html': // HTML $Quote = '<blockquote class="Quote" rel="' . htmlspecialchars($Data->InsertName) . '">' . $Data->Body . '</blockquote>' . "\n"; break; case 'BBCode': $Author = htmlspecialchars($Data->InsertName); if ($ID) { $IDString = ';' . htmlspecialchars($ID); } $QuoteBody = $Data->Body; // TODO: Strip inner quotes... // $QuoteBody = trim(preg_replace('`(\[quote.*/quote\])`si', '', $QuoteBody)); $Quote = <<<BQ [quote="{$Author}{$IDString}"]{$QuoteBody}[/quote] BQ; break; case 'Markdown': case 'Display': case 'Text': $QuoteBody = $Data->Body; // Strip inner quotes and mentions... $QuoteBody = self::_stripMarkdownQuotes($QuoteBody); $QuoteBody = self::_stripMentions($QuoteBody); $Quote = '> ' . sprintf(t('%s said:'), '@' . $Data->InsertName) . "\n" . '> ' . str_replace("\n", "\n> ", $QuoteBody) . "\n"; break; case 'Wysiwyg': $Attribution = sprintf(t('%s said:'), userAnchor($Data, null, array('Px' => 'Insert'))); $QuoteBody = $Data->Body; // TODO: Strip inner quotes... // $QuoteBody = trim(preg_replace('`(<blockquote.*/blockquote>)`si', '', $QuoteBody)); $Quote = <<<BLOCKQUOTE <blockquote class="Quote"> <div class="QuoteAuthor">{$Attribution}</div> <div class="QuoteText">{$QuoteBody}</div> </blockquote> BLOCKQUOTE; break; } $QuoteData = array_merge($QuoteData, array('status' => 'success', 'body' => $Quote, 'format' => $Format, 'authorid' => $Data->InsertUserID, 'authorname' => $Data->InsertName, 'type' => $Type, 'typeid' => $ID)); } // Undo Emoji disable. Emoji::instance()->enabled = $emojiEnabled; }
/** * * * @param $Sender * @param $Args * @throws Gdn_UserException */ public function commentModel_afterSaveComment_handler($Sender, $Args) { if (!$this->socialSharing()) { return; } if (!$this->accessToken()) { return; } $ShareFacebook = valr('FormPostValues.ShareFacebook', $Args); if ($ShareFacebook) { $Row = $Args['FormPostValues']; $DiscussionModel = new DiscussionModel(); $Discussion = $DiscussionModel->getID(val('DiscussionID', $Row)); if (!$Discussion) { die('no discussion'); } $Url = DiscussionUrl($Discussion, '', true); $Message = SliceParagraph(Gdn_Format::plainText($Row['Body'], $Row['Format']), 160); if ($this->accessToken()) { $R = $this->api('/me/feed', array('link' => $Url, 'message' => $Message)); } } }
/** * Get a record from the database. * * @param string $recordType The type of record to get. This is usually the un-prefixed table name of the record. * @param int $id The ID of the record. * @param bool $throw Whether or not to throw an exception if the record isn't found. * @return array|false Returns an array representation of the record or false if the record isn't found. * @throws Exception Throws an exception with a 404 code if the record isn't found and {@link $throw} is true. * @throws Gdn_UserException Throws an exception when {@link $recordType} is unknown. */ function getRecord($recordType, $id, $throw = false) { $Row = false; switch (strtolower($recordType)) { case 'discussion': $Model = new DiscussionModel(); $Row = $Model->getID($id); $Row->Url = DiscussionUrl($Row); $Row->ShareUrl = $Row->Url; if ($Row) { return (array) $Row; } break; case 'comment': $Model = new CommentModel(); $Row = $Model->getID($id, DATASET_TYPE_ARRAY); if ($Row) { $Row['Url'] = Url("/discussion/comment/{$id}#Comment_{$id}", true); $Model = new DiscussionModel(); $Discussion = $Model->getID($Row['DiscussionID']); if ($Discussion) { $Discussion->Url = DiscussionUrl($Discussion); $Row['ShareUrl'] = $Discussion->Url; $Row['Name'] = $Discussion->Name; $Row['Discussion'] = (array) $Discussion; } return $Row; } break; case 'activity': $Model = new ActivityModel(); $Row = $Model->getID($id, DATASET_TYPE_ARRAY); if ($Row) { $Row['Name'] = formatString($Row['HeadlineFormat'], $Row); $Row['Body'] = $Row['Story']; return $Row; } break; default: throw new Gdn_UserException('Unknown record type requested.'); } if ($throw) { throw NotFoundException(); } else { return false; } }
/** * * * @param $Sender * @param $Args * @throws Gdn_UserException */ public function commentModel_afterSaveComment_handler($Sender, $Args) { if (!$this->socialSharing() || !$this->accessToken()) { return; } $Share = valr('FormPostValues.ShareTwitter', $Args); if ($Share && $this->accessToken()) { $Row = $Args['FormPostValues']; $DiscussionModel = new DiscussionModel(); $Discussion = $DiscussionModel->getID(val('DiscussionID', $Row)); if (!$Discussion) { return; } $Url = DiscussionUrl($Discussion, '', true); $Message = SliceTwitter(Gdn_Format::plainText($Row['Body'], $Row['Format'])) . ' ' . $Url; $R = $this->API('/statuses/update.json', array('status' => $Message), 'POST'); } }
/** * Give point(s) to the current user if the right conditions are met. * * @param CommentModel $sender Sending controller instance. * @param array $args Event arguments. */ public function commentModel_afterSaveComment_handler($sender, $args) { if (!c('QnA.Points.Enabled', false) || !$args['Insert']) { return; } $discussionModel = new DiscussionModel(); $discussion = $discussionModel->getID($args['CommentData']['DiscussionID'], DATASET_TYPE_ARRAY); $isCommentAnAnswer = $discussion['Type'] === 'Question'; $isQuestionResolved = $discussion['QnA'] === 'Accepted'; $isCurrentUserOriginalPoster = $discussion['InsertUserID'] == GDN::session()->UserID; if (!$isCommentAnAnswer || $isQuestionResolved || $isCurrentUserOriginalPoster) { return; } $userAnswersToQuestion = $sender->getWhere(array('DiscussionID' => $args['CommentData']['DiscussionID'], 'InsertUserId' => GDN::session()->UserID)); // Award point(s) only for the first answer to the question if ($userAnswersToQuestion->count() > 1) { return; } UserModel::givePoints(GDN::session()->UserID, c('QnA.Points.Answer', 1), 'QnA'); }
/** * Handle flagging process in a discussion. */ public function discussionController_flag_create($Sender) { // Signed in users only. if (!($UserID = Gdn::session()->UserID)) { return; } $UserName = Gdn::session()->User->Name; $Arguments = $Sender->RequestArgs; if (sizeof($Arguments) != 5) { return; } list($Context, $ElementID, $ElementAuthorID, $ElementAuthor, $EncodedURL) = $Arguments; $URL = htmlspecialchars(base64_decode(str_replace('-', '=', $EncodedURL))); $Sender->setData('Plugin.Flagging.Data', array('Context' => $Context, 'ElementID' => $ElementID, 'ElementAuthorID' => $ElementAuthorID, 'ElementAuthor' => $ElementAuthor, 'URL' => $URL, 'UserID' => $UserID, 'UserName' => $UserName)); if ($Sender->Form->authenticatedPostBack()) { $SQL = Gdn::sql(); $Comment = $Sender->Form->getValue('Plugin.Flagging.Reason'); $Sender->setData('Plugin.Flagging.Reason', $Comment); $CreateDiscussion = c('Plugins.Flagging.UseDiscussions'); if ($CreateDiscussion) { // Category $CategoryID = c('Plugins.Flagging.CategoryID'); // New discussion name if ($Context == 'comment') { $Result = $SQL->select('d.Name')->select('c.Body')->from('Comment c')->join('Discussion d', 'd.DiscussionID = c.DiscussionID', 'left')->where('c.CommentID', $ElementID)->get()->firstRow(); } elseif ($Context == 'discussion') { $DiscussionModel = new DiscussionModel(); $Result = $DiscussionModel->getID($ElementID); } $DiscussionName = val('Name', $Result); $PrefixedDiscussionName = t('FlagPrefix', 'FLAG: ') . $DiscussionName; // Prep data for the template $Sender->setData('Plugin.Flagging.Report', array('DiscussionName' => $DiscussionName, 'FlaggedContent' => val('Body', $Result))); // Assume no discussion exists $this->DiscussionID = null; // Get discussion ID if already flagged $FlagResult = Gdn::sql()->select('DiscussionID')->from('Flag fl')->where('ForeignType', $Context)->where('ForeignID', $ElementID)->get()->firstRow(); if ($FlagResult) { // New comment in existing discussion $DiscussionID = $FlagResult->DiscussionID; $ReportBody = $Sender->fetchView($this->getView('reportcomment.php')); $SQL->insert('Comment', array('DiscussionID' => $DiscussionID, 'InsertUserID' => $UserID, 'Body' => $ReportBody, 'Format' => 'Html', 'DateInserted' => date('Y-m-d H:i:s'))); $CommentModel = new CommentModel(); $CommentModel->updateCommentCount($DiscussionID); } else { // New discussion body $ReportBody = $Sender->fetchView($this->getView('report.php')); $DiscussionID = $SQL->insert('Discussion', array('InsertUserID' => $UserID, 'UpdateUserID' => $UserID, 'CategoryID' => $CategoryID, 'Name' => $PrefixedDiscussionName, 'Body' => $ReportBody, 'Format' => 'Html', 'CountComments' => 1, 'DateInserted' => date('Y-m-d H:i:s'), 'DateUpdated' => date('Y-m-d H:i:s'), 'DateLastComment' => date('Y-m-d H:i:s'))); // Update discussion count $DiscussionModel = new DiscussionModel(); $DiscussionModel->updateDiscussionCount($CategoryID); } } try { // Insert the flag $SQL->insert('Flag', array('DiscussionID' => $DiscussionID, 'InsertUserID' => $UserID, 'InsertName' => $UserName, 'AuthorID' => $ElementAuthorID, 'AuthorName' => $ElementAuthor, 'ForeignURL' => $URL, 'ForeignID' => $ElementID, 'ForeignType' => $Context, 'Comment' => $Comment, 'DateInserted' => date('Y-m-d H:i:s'))); } catch (Exception $e) { } // Notify users with permission who've chosen to be notified if (!$FlagResult) { // Only send if this is first time it's being flagged. $Sender->setData('Plugin.Flagging.DiscussionID', $DiscussionID); $Subject = isset($PrefixedDiscussionName) ? $PrefixedDiscussionName : t('FlagDiscussion', 'A discussion was flagged'); $EmailBody = $Sender->fetchView($this->getView('reportemail.php')); $NotifyUsers = c('Plugins.Flagging.NotifyUsers', array()); // Send emails $UserModel = new UserModel(); foreach ($NotifyUsers as $UserID) { $User = $UserModel->getID($UserID); $Email = new Gdn_Email(); $Email->to($User->Email)->subject(sprintf(t('[%1$s] %2$s'), Gdn::config('Garden.Title'), $Subject))->message($EmailBody); try { $Email->send(); } catch (Exception $e) { if (debug()) { throw $e; } } } } $Sender->informMessage(t('FlagSent', "Your complaint has been registered.")); } $Sender->render($this->getView('flag.php')); }
/** * 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'); }
/** * Form to confirm that the administrator wants to delete the selected * comments (and has permission to do so). */ public function confirmCommentDeletes($DiscussionID = '') { $Session = Gdn::session(); $this->Form = new Gdn_Form(); $DiscussionModel = new DiscussionModel(); $Discussion = $DiscussionModel->getID($DiscussionID); if (!$Discussion) { return; } // Verify that the user has permission to perform the delete $PermissionCategory = CategoryModel::categories($Discussion->CategoryID); $this->permission('Vanilla.Comments.Delete', true, 'Category', val('PermissionCategoryID', $PermissionCategory)); $this->title(t('Confirm')); $CheckedComments = Gdn::userModel()->getAttribute($Session->User->UserID, 'CheckedComments', array()); if (!is_array($CheckedComments)) { $CheckedComments = array(); } $CommentIDs = array(); $DiscussionIDs = array(); foreach ($CheckedComments as $DiscID => $Comments) { foreach ($Comments as $Comment) { if (substr($Comment, 0, 11) == 'Discussion_') { $DiscussionIDs[] = str_replace('Discussion_', '', $Comment); } elseif ($DiscID == $DiscussionID) { $CommentIDs[] = str_replace('Comment_', '', $Comment); } } } $CountCheckedComments = count($CommentIDs); $this->setData('CountCheckedComments', $CountCheckedComments); if ($this->Form->authenticatedPostBack()) { // Delete the selected comments $CommentModel = new CommentModel(); foreach ($CommentIDs as $CommentID) { $CommentModel->delete($CommentID); } // Clear selections unset($CheckedComments[$DiscussionID]); Gdn::userModel()->saveAttribute($Session->UserID, 'CheckedComments', $CheckedComments); ModerationController::InformCheckedComments($this); $this->RedirectUrl = 'discussions'; } $this->render(); }
/** * Add a method to the ModerationController to handle splitting comments out to a new discussion. */ public function moderationController_splitComments_create($Sender) { $Session = Gdn::session(); $Sender->Form = new Gdn_Form(); $Sender->title(t('Split Comments')); $Sender->Category = false; $DiscussionID = val('0', $Sender->RequestArgs, ''); if (!is_numeric($DiscussionID)) { return; } $DiscussionModel = new DiscussionModel(); $Discussion = $DiscussionModel->getID($DiscussionID); if (!$Discussion) { return; } // Verify that the user has permission to perform the split $Sender->permission('Vanilla.Discussions.Edit', true, 'Category', $Discussion->PermissionCategoryID); $CheckedComments = Gdn::userModel()->getAttribute($Session->User->UserID, 'CheckedComments', array()); if (!is_array($CheckedComments)) { $CheckedComments = array(); } $CommentIDs = array(); foreach ($CheckedComments as $DiscID => $Comments) { foreach ($Comments as $Comment) { if ($DiscID == $DiscussionID) { $CommentIDs[] = str_replace('Comment_', '', $Comment); } } } // Load category data. $Sender->ShowCategorySelector = (bool) c('Vanilla.Categories.Use'); $CountCheckedComments = count($CommentIDs); $Sender->setData('CountCheckedComments', $CountCheckedComments); // Perform the split if ($Sender->Form->authenticatedPostBack()) { // Create a new discussion record $Data = $Sender->Form->formValues(); $Data['Body'] = sprintf(t('This discussion was created from comments split from: %s.'), anchor(Gdn_Format::text($Discussion->Name), 'discussion/' . $Discussion->DiscussionID . '/' . Gdn_Format::url($Discussion->Name) . '/')); $Data['Format'] = 'Html'; $Data['Type'] = 'Discussion'; $NewDiscussionID = $DiscussionModel->save($Data); $Sender->Form->setValidationResults($DiscussionModel->validationResults()); if ($Sender->Form->errorCount() == 0 && $NewDiscussionID > 0) { // Re-assign the comments to the new discussion record $DiscussionModel->SQL->update('Comment')->set('DiscussionID', $NewDiscussionID)->whereIn('CommentID', $CommentIDs)->put(); // Update counts on both discussions $CommentModel = new CommentModel(); $CommentModel->updateCommentCount($DiscussionID); // $CommentModel->UpdateUserCommentCounts($DiscussionID); $CommentModel->updateCommentCount($NewDiscussionID); $CommentModel->removePageCache($DiscussionID, 1); // Clear selections unset($CheckedComments[$DiscussionID]); Gdn::userModel()->saveAttribute($Session->UserID, 'CheckedComments', $CheckedComments); ModerationController::informCheckedComments($Sender); $Sender->RedirectUrl = url('discussion/' . $NewDiscussionID . '/' . Gdn_Format::url($Data['Name'])); } } else { $Sender->Form->setValue('CategoryID', val('CategoryID', $Discussion)); } $Sender->render($this->getView('splitcomments.php')); }
/** * Insert a SPAM Queue entry for the specified record and delete the record, if possible. * * @param string $recordType The type of record we're flagging: Discussion or Comment. * @param int $id ID of the record we're flagging. * @param object|array $data Properties used for updating/overriding the record's current values. * * @throws Exception If an invalid record type is specified, throw an exception. */ protected static function flagForReview($recordType, $id, $data) { // We're planning to purge the spammy record. $deleteRow = true; /** * We're only handling two types of content: discussions and comments. Both need some special setup. * Error out if we're not dealing with a discussion or comment. */ switch ($recordType) { case 'Comment': $model = new CommentModel(); $row = $model->getID($id, DATASET_TYPE_ARRAY); break; case 'Discussion': $model = new DiscussionModel(); $row = $model->getID($id, DATASET_TYPE_ARRAY); /** * If our discussion has more than three comments, it might be worth saving. Hold off on deleting and * just flag it. If we have between 0 and 3 comments, save them along with the discussion. */ if ($row['CountComments'] > 3) { $deleteRow = false; } elseif ($row['CountComments'] > 0) { $comments = Gdn::database()->sql()->getWhere('Comment', array('DiscussionID' => $id))->resultArray(); if (!array_key_exists('_Data', $row)) { $row['_Data'] = array(); } $row['_Data']['Comment'] = $comments; } break; default: throw notFoundException($recordType); } $overrideFields = array('Name', 'Body'); foreach ($overrideFields as $fieldName) { if (($fieldValue = val($fieldName, $data, false)) !== false) { $row[$fieldName] = $fieldValue; } } $logOptions = array('GroupBy' => array('RecordID')); if ($deleteRow) { // Remove the record to the log. $model->deleteID($id); } LogModel::insert('Spam', $recordType, $row, $logOptions); }
/** * Outputs a formatted comment. * * Prior to 2.1, this also output the discussion ("FirstComment") to the browser. * That has moved to the discussion.php view. * * @param DataSet $Comment . * @param Gdn_Controller $Sender . * @param Gdn_Session $Session . * @param int $CurrentOffet How many comments into the discussion we are (for anchors). */ function writeComment($Comment, $Sender, $Session, $CurrentOffset) { // Whether to order the name & photo with the latter first. static $UserPhotoFirst = null; if ($UserPhotoFirst === null) { $UserPhotoFirst = c('Vanilla.Comment.UserPhotoFirst', true); } $Author = Gdn::userModel()->getID($Comment->InsertUserID); //UserBuilder($Comment, 'Insert'); $Permalink = val('Url', $Comment, '/discussion/comment/' . $Comment->CommentID . '/#Comment_' . $Comment->CommentID); // Set CanEditComments (whether to show checkboxes) if (!property_exists($Sender, 'CanEditComments')) { $Sender->CanEditComments = $Session->checkPermission('Vanilla.Comments.Edit', true, 'Category', 'any') && c('Vanilla.AdminCheckboxes.Use'); } // Prep event args $CssClass = cssClass($Comment, $CurrentOffset); $Sender->EventArguments['Comment'] =& $Comment; $Sender->EventArguments['Author'] =& $Author; $Sender->EventArguments['CssClass'] =& $CssClass; $Sender->EventArguments['CurrentOffset'] = $CurrentOffset; $Sender->EventArguments['Permalink'] = $Permalink; // Needed in writeCommentOptions() if ($Sender->data('Discussion', null) === null) { $discussionModel = new DiscussionModel(); $discussion = $discussionModel->getID($Comment->DiscussionID); $Sender->setData('Discussion', $discussion); } // DEPRECATED ARGUMENTS (as of 2.1) $Sender->EventArguments['Object'] =& $Comment; $Sender->EventArguments['Type'] = 'Comment'; // First comment template event $Sender->fireEvent('BeforeCommentDisplay'); ?> <li class="<?php echo $CssClass; ?> " id="<?php echo 'Comment_' . $Comment->CommentID; ?> "> <div class="Comment"> <?php // Write a stub for the latest comment so it's easy to link to it from outside. if ($CurrentOffset == Gdn::controller()->data('_LatestItem')) { echo '<span id="latest"></span>'; } ?> <div class="Options"> <?php writeCommentOptions($Comment); ?> </div> <?php $Sender->fireEvent('BeforeCommentMeta'); ?> <div class="Item-Header CommentHeader"> <div class="AuthorWrap"> <span class="Author"> <?php if ($UserPhotoFirst) { echo userPhoto($Author); echo userAnchor($Author, 'Username'); } else { echo userAnchor($Author, 'Username'); echo userPhoto($Author); } echo FormatMeAction($Comment); $Sender->fireEvent('AuthorPhoto'); ?> </span> <span class="AuthorInfo"> <?php echo ' ' . wrapIf(htmlspecialchars(val('Title', $Author)), 'span', array('class' => 'MItem AuthorTitle')); echo ' ' . wrapIf(htmlspecialchars(val('Location', $Author)), 'span', array('class' => 'MItem AuthorLocation')); $Sender->fireEvent('AuthorInfo'); ?> </span> </div> <div class="Meta CommentMeta CommentInfo"> <span class="MItem DateCreated"> <?php echo anchor(Gdn_Format::date($Comment->DateInserted, 'html'), $Permalink, 'Permalink', array('name' => 'Item_' . $CurrentOffset, 'rel' => 'nofollow')); ?> </span> <?php echo DateUpdated($Comment, array('<span class="MItem">', '</span>')); ?> <?php // Include source if one was set if ($Source = val('Source', $Comment)) { echo wrap(sprintf(t('via %s'), t($Source . ' Source', $Source)), 'span', array('class' => 'MItem Source')); } // Include IP Address if we have permission if ($Session->checkPermission('Garden.PersonalInfo.View')) { echo wrap(ipAnchor($Comment->InsertIPAddress), 'span', array('class' => 'MItem IPAddress')); } $Sender->fireEvent('CommentInfo'); $Sender->fireEvent('InsideCommentMeta'); // DEPRECATED $Sender->fireEvent('AfterCommentMeta'); // DEPRECATED ?> </div> </div> <div class="Item-BodyWrap"> <div class="Item-Body"> <div class="Message"> <?php echo formatBody($Comment); ?> </div> <?php $Sender->fireEvent('AfterCommentBody'); writeReactions($Comment); if (val('Attachments', $Comment)) { writeAttachments($Comment->Attachments); } ?> </div> </div> </div> </li> <?php $Sender->fireEvent('AfterComment'); }