/** * 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(); } }