/** * Save message from form submission. * * @since 2.0.0 * @access public * * @param array $FormPostValues Values submitted via form. * @return int Unique ID of message created or updated. */ public function save($FormPostValues, $Conversation = null, $Options = array()) { $Session = Gdn::session(); // Define the primary key in this model's table. $this->defineSchema(); // Add & apply any extra validation rules: $this->Validation->applyRule('Body', 'Required'); $this->addInsertFields($FormPostValues); $this->EventArguments['FormPostValues'] = $FormPostValues; $this->fireEvent('BeforeSaveValidation'); // Determine if spam check should be skipped. $SkipSpamCheck = !empty($Options['NewConversation']); // Validate the form posted values $MessageID = false; if ($this->validate($FormPostValues) && !$this->checkForSpam('ConversationMessage', $SkipSpamCheck)) { $Fields = $this->Validation->schemaValidationFields(); // All fields on the form that relate to the schema touchValue('Format', $Fields, c('Garden.InputFormatter', 'Html')); $this->EventArguments['Fields'] = $Fields; $this->fireEvent('BeforeSave'); $MessageID = $this->SQL->insert($this->Name, $Fields); $this->LastMessageID = $MessageID; $ConversationID = val('ConversationID', $Fields, 0); if (!$Conversation) { $Conversation = $this->SQL->getWhere('Conversation', array('ConversationID' => $ConversationID))->firstRow(DATASET_TYPE_ARRAY); } $Message = $this->getID($MessageID); $this->EventArguments['Conversation'] = $Conversation; $this->EventArguments['Message'] = $Message; $this->fireEvent('AfterSave'); // Get the new message count for the conversation. $SQLR = $this->SQL->select('MessageID', 'count', 'CountMessages')->select('MessageID', 'max', 'LastMessageID')->from('ConversationMessage')->where('ConversationID', $ConversationID)->get()->firstRow(DATASET_TYPE_ARRAY); if (sizeof($SQLR)) { list($CountMessages, $LastMessageID) = array_values($SQLR); } else { return; } // Update the conversation's DateUpdated field. $DateUpdated = Gdn_Format::toDateTime(); $this->SQL->update('Conversation c')->set('CountMessages', $CountMessages)->set('LastMessageID', $LastMessageID)->set('UpdateUserID', Gdn::session()->UserID)->set('DateUpdated', $DateUpdated)->where('ConversationID', $ConversationID)->put(); // Update the last message of the users that were previously up-to-date on their read messages. $this->SQL->update('UserConversation uc')->set('uc.LastMessageID', $MessageID)->set('uc.DateConversationUpdated', $DateUpdated)->where('uc.ConversationID', $ConversationID)->where('uc.Deleted', '0')->where('uc.CountReadMessages', $CountMessages - 1)->where('uc.UserID <>', $Session->UserID)->put(); // Update the date updated of the users that were not up-to-date. $this->SQL->update('UserConversation uc')->set('uc.DateConversationUpdated', $DateUpdated)->where('uc.ConversationID', $ConversationID)->where('uc.Deleted', '0')->where('uc.CountReadMessages <>', $CountMessages - 1)->where('uc.UserID <>', $Session->UserID)->put(); // Update the sending user. $this->SQL->update('UserConversation uc')->set('uc.CountReadMessages', $CountMessages)->set('Deleted', 0)->set('uc.DateConversationUpdated', $DateUpdated)->where('ConversationID', $ConversationID)->where('UserID', $Session->UserID)->put(); // Find users involved in this conversation $UserData = $this->SQL->select('UserID')->select('LastMessageID')->select('Deleted')->from('UserConversation')->where('ConversationID', $ConversationID)->get()->result(DATASET_TYPE_ARRAY); $UpdateCountUserIDs = array(); $NotifyUserIDs = array(); // Collapse for call to UpdateUserCache and ActivityModel. $InsertUserFound = false; foreach ($UserData as $UpdateUser) { $LastMessageID = val('LastMessageID', $UpdateUser); $UserID = val('UserID', $UpdateUser); $Deleted = val('Deleted', $UpdateUser); if ($UserID == val('InsertUserID', $Fields)) { $InsertUserFound = true; if ($Deleted) { $this->SQL->put('UserConversation', array('Deleted' => 0, 'DateConversationUpdated' => $DateUpdated), array('ConversationID' => $ConversationID, 'UserID' => $UserID)); } } // Update unread for users that were up to date if ($LastMessageID == $MessageID) { $UpdateCountUserIDs[] = $UserID; } // Send activities to users that have not deleted the conversation if (!$Deleted) { $NotifyUserIDs[] = $UserID; } } if (!$InsertUserFound) { $UserConversation = array('UserID' => val('InsertUserID', $Fields), 'ConversationID' => $ConversationID, 'LastMessageID' => $LastMessageID, 'CountReadMessages' => $CountMessages, 'DateConversationUpdated' => $DateUpdated); $this->SQL->insert('UserConversation', $UserConversation); } if (sizeof($UpdateCountUserIDs)) { $ConversationModel = new ConversationModel(); $ConversationModel->updateUserUnreadCount($UpdateCountUserIDs, true); } $this->fireEvent('AfterAdd'); $activityModel = new ActivityModel(); foreach ($NotifyUserIDs as $notifyUserID) { if ($Session->UserID == $notifyUserID) { continue; // don't notify self. } // Notify the users of the new message. $activity = array('ActivityType' => 'ConversationMessage', 'ActivityUserID' => val('InsertUserID', $Fields), 'NotifyUserID' => $notifyUserID, 'HeadlineFormat' => t('HeadlineFormat.ConversationMessage', '{ActivityUserID,user} sent you a <a href="{Url,html}">message</a>'), 'RecordType' => 'Conversation', 'RecordID' => $ConversationID, 'Story' => val('Body', $Fields, ''), 'Format' => val('Format', $Fields, c('Garden.InputFormatter')), 'Route' => "/messages/{$ConversationID}#{$MessageID}"); if (c('Conversations.Subjects.Visible') && val('Subject', $Conversation, '')) { $activity['HeadlineFormat'] = val('Subject', $Conversation, ''); } $activityModel->queue($activity, 'ConversationMessage'); } $activityModel->saveQueue(); } return $MessageID; }
/** * Unban a user. * * @param int $UserID The user to unban. * @param array $Options Options for the unban. * @since 2.1 */ public function unBan($UserID, $Options = []) { $User = $this->getID($UserID, DATASET_TYPE_ARRAY); if (!$User) { throw notFoundException(); } $Banned = $User['Banned']; if (!BanModel::isBanned($Banned, BanModel::BAN_AUTOMATIC | BanModel::BAN_MANUAL)) { throw new Gdn_UserException(t("The user isn't banned.", "The user isn't banned or is banned by some other function.")); } // Unban the user. $NewBanned = BanModel::setBanned($Banned, false, BanModel::BAN_AUTOMATIC | BanModel::BAN_MANUAL); $this->setField($UserID, 'Banned', $NewBanned); // Restore the user's content. if (val('RestoreContent', $Options)) { $BanLogID = $this->getAttribute($UserID, 'BanLogID'); if ($BanLogID) { $LogModel = new LogModel(); try { $LogModel->restore($BanLogID); } catch (Exception $Ex) { if ($Ex->getCode() != 404) { throw $Ex; } } $this->saveAttribute($UserID, 'BanLogID', null); } } // Add an activity for the unbanning. if (val('AddActivity', $Options, true)) { $ActivityModel = new ActivityModel(); $Story = val('Story', $Options, null); // Notify the moderators of the unban. $Activity = ['ActivityType' => 'Ban', 'NotifyUserID' => ActivityModel::NOTIFY_MODS, 'ActivityUserID' => $UserID, 'RegardingUserID' => Gdn::session()->UserID, 'HeadlineFormat' => t('HeadlineFormat.Unban', '{RegardingUserID,You} unbanned {ActivityUserID,you}.'), 'Story' => $Story, 'Data' => ['Unban' => true]]; $ActivityModel->queue($Activity); // Notify the user of the unban. $Activity['NotifyUserID'] = $UserID; $Activity['Emailed'] = ActivityModel::SENT_PENDING; $Activity['HeadlineFormat'] = t('HeadlineFormat.Unban.Notification', "You've been unbanned."); $ActivityModel->queue($Activity, false, ['Force' => true]); $ActivityModel->saveQueue(); } }
/** * 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); } }