PageRenderTime 53ms CodeModel.GetById 22ms RepoModel.GetById 1ms app.codeStats 0ms

/applications/conversations/models/class.conversationmodel.php

https://github.com/ghoppe/Garden
PHP | 336 lines | 243 code | 42 blank | 51 comment | 22 complexity | d29bf94393c0aec8407df8bdfefd5e6b MD5 | raw file
Possible License(s): LGPL-2.1
  1. <?php if (!defined('APPLICATION')) exit();
  2. /*
  3. Copyright 2008, 2009 Vanilla Forums Inc.
  4. This file is part of Garden.
  5. Garden is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
  6. Garden is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  7. You should have received a copy of the GNU General Public License along with Garden. If not, see <http://www.gnu.org/licenses/>.
  8. Contact Vanilla Forums Inc. at support [at] vanillaforums [dot] com
  9. */
  10. class ConversationModel extends Gdn_Model {
  11. /**
  12. * Class constructor.
  13. */
  14. public function __construct() {
  15. parent::__construct('Conversation');
  16. }
  17. public function ConversationQuery($ViewingUserID) {
  18. $this->SQL
  19. ->Select('c.*')
  20. ->Select('uc.LastMessageID, uc.CountReadMessages, uc.DateLastViewed, uc.Bookmarked')
  21. ->Select('c.CountMessages - uc.CountReadMessages', '', 'CountNewMessages')
  22. ->Select('lm.InsertUserID', '', 'LastMessageUserID')
  23. ->Select('lm.DateInserted', '', 'DateLastMessage')
  24. ->Select('lm.Body', '', 'LastMessage')
  25. ->Select('lmu.Name', '', 'LastMessageName')
  26. ->Select('lmu.Photo', '', 'LastMessagePhoto')
  27. //->Select('iu.Name', '', 'InsertName')
  28. // ->Select('uu.Name', '', 'UpdateName')
  29. ->From('Conversation c')
  30. //->Join('User iu', 'c.InsertUserID = iu.UserID')
  31. ->Join('UserConversation uc', "c.ConversationID = uc.ConversationID and uc.UserID = $ViewingUserID and uc.Deleted = 0")
  32. ->Join('ConversationMessage lm', 'uc.LastMessageID = lm.MessageID')
  33. ->Join('User lmu', 'lm.InsertUserID = lmu.UserID');
  34. //->BeginWhereGroup()
  35. //->Where('uc.DateCleared is null')
  36. //->OrWhere('c.DateUpdated >', 'uc.DateCleared', TRUE, FALSE) // Make sure that cleared conversations do not show up unless they have new messages added.
  37. //->EndWhereGroup();
  38. }
  39. public function Get($ViewingUserID, $Offset = '0', $Limit = '', $Wheres = '') {
  40. if ($Limit == '')
  41. $Limit = Gdn::Config('Conversations.Conversations.PerPage', 50);
  42. $Offset = !is_numeric($Offset) || $Offset < 0 ? 0 : $Offset;
  43. $this->ConversationQuery($ViewingUserID);
  44. if (is_array($Wheres))
  45. $this->SQL->Where($Wheres);
  46. $this->FireEvent('BeforeGet');
  47. return $this->SQL
  48. ->OrderBy('c.DateUpdated', 'desc')
  49. ->Limit($Limit, $Offset)
  50. ->Get();
  51. }
  52. public function GetCount($ViewingUserID, $Wheres = '') {
  53. if (is_array($Wheres))
  54. $this->SQL->Where($Wheres);
  55. $Result = $this->SQL
  56. ->Select('uc.UserID', 'count', 'Count')
  57. ->From('UserConversation uc')
  58. ->Where('uc.UserID', $ViewingUserID)
  59. ->Get()->Value('Count', 0);
  60. return $Result;
  61. }
  62. public function GetCountWhere($Wheres = '') {
  63. if (is_array($Wheres))
  64. $this->SQL->Where($Wheres);
  65. $Data = $this->SQL
  66. ->Select('ConversationID', 'count', 'Count')
  67. ->From('Conversation')
  68. ->Get();
  69. if ($Data->NumRows() > 0)
  70. return $Data->FirstRow()->Count;
  71. return 0;
  72. }
  73. public function GetID($ConversationID, $ViewingUserID) {
  74. $this->ConversationQuery($ViewingUserID);
  75. return $this->SQL
  76. ->Where('c.ConversationID', $ConversationID)
  77. ->Get()
  78. ->FirstRow();
  79. }
  80. public function GetRecipients($ConversationID, $IgnoreUserID = '0') {
  81. return $this->SQL
  82. ->Select('uc.UserID, u.Name, uc.Deleted')
  83. ->Select('cm.DateInserted', 'max', 'DateLastActive')
  84. ->From('UserConversation uc')
  85. ->Join('User u', 'uc.UserID = u.UserID')
  86. ->Join('ConversationMessage cm', 'uc.ConversationID = cm.ConversationID and uc.UserID = cm.InsertUserID', 'left')
  87. ->Where('uc.ConversationID', $ConversationID)
  88. // ->Where('uc.UserID <>', $IgnoreUserID)
  89. ->GroupBy('uc.UserID, u.Name')
  90. ->Get();
  91. }
  92. public function Save($FormPostValues, $MessageModel) {
  93. $Session = Gdn::Session();
  94. // Define the primary key in this model's table.
  95. $this->DefineSchema();
  96. $MessageModel->DefineSchema();
  97. // Add & apply any extra validation rules:
  98. $this->Validation->ApplyRule('Body', 'Required');
  99. $MessageModel->Validation->ApplyRule('Body', 'Required');
  100. // Make sure that there is at least one recipient
  101. $this->Validation->AddRule('OneOrMoreArrayItemRequired', 'function:ValidateOneOrMoreArrayItemRequired');
  102. $this->Validation->ApplyRule('RecipientUserID', 'OneOrMoreArrayItemRequired');
  103. // Add insert/update fields
  104. $this->AddInsertFields($FormPostValues);
  105. $this->AddUpdateFields($FormPostValues);
  106. // Validate the form posted values
  107. $ConversationID = FALSE;
  108. if (
  109. $this->Validate($FormPostValues)
  110. && $MessageModel->Validate($FormPostValues)
  111. ) {
  112. $Fields = $this->Validation->ValidationFields(); // All fields on the form that relate to the schema
  113. // Define the recipients, and make sure that the sender is in the list
  114. $RecipientUserIDs = ArrayValue('RecipientUserID', $Fields, 0);
  115. if (!in_array($Session->UserID, $RecipientUserIDs))
  116. $RecipientUserIDs[] = $Session->UserID;
  117. // Also make sure there are no duplicates in the recipient list
  118. $RecipientUserIDs = array_unique($RecipientUserIDs);
  119. sort($RecipientUserIDs);
  120. $Fields = $this->Validation->SchemaValidationFields(); // All fields on the form that relate to the schema
  121. $Fields['Contributors'] = Gdn_Format::Serialize($RecipientUserIDs);
  122. $ConversationID = $this->SQL->Insert($this->Name, $Fields);
  123. $FormPostValues['ConversationID'] = $ConversationID;
  124. $MessageID = $MessageModel->Save($FormPostValues);
  125. $this->SQL
  126. ->Update('Conversation')
  127. ->Set('FirstMessageID', $MessageID)
  128. ->Where('ConversationID', $ConversationID)
  129. ->Put();
  130. // Now that the message & conversation have been inserted, insert all of the recipients
  131. foreach ($RecipientUserIDs as $UserID) {
  132. $CountReadMessages = $UserID == $Session->UserID ? 1 : 0;
  133. $this->SQL->Insert('UserConversation', array(
  134. 'UserID' => $UserID,
  135. 'ConversationID' => $ConversationID,
  136. 'LastMessageID' => $MessageID,
  137. 'CountReadMessages' => $CountReadMessages
  138. ));
  139. }
  140. // And update the CountUnreadConversations count on each user related to the discussion.
  141. $this->SQL
  142. ->Update('User')
  143. ->Set('CountUnreadConversations', 'CountUnreadConversations + 1', FALSE)
  144. ->WhereIn('UserID', $RecipientUserIDs)
  145. ->Where('UserID <>', $Session->UserID)
  146. ->Put();
  147. // Add notifications (this isn't done by the conversationmessagemodule
  148. // because the conversation has not yet been created at the time they are
  149. // inserted)
  150. $UnreadData = $this->SQL
  151. ->Select('uc.UserID')
  152. ->From('UserConversation uc')
  153. ->Where('uc.ConversationID', $ConversationID) // hopefully coax this index.
  154. ->Where('uc.UserID <>', $Session->UserID)
  155. ->Get();
  156. $ActivityModel = new ActivityModel();
  157. foreach ($UnreadData->Result() as $User) {
  158. // Notify the users of the new message.
  159. $ActivityID = $ActivityModel->Add(
  160. $Session->UserID,
  161. 'ConversationMessage',
  162. '',
  163. $User->UserID,
  164. '',
  165. "/messages/$ConversationID#$MessageID",
  166. FALSE
  167. );
  168. $Story = ArrayValue('Body', $FormPostValues, '');
  169. $ActivityModel->SendNotification($ActivityID, $Story);
  170. }
  171. } else {
  172. // Make sure that all of the validation results from both validations are present for view by the form
  173. foreach ($MessageModel->ValidationResults() as $FieldName => $Results) {
  174. foreach ($Results as $Result) {
  175. $this->Validation->AddValidationResult($FieldName, $Result);
  176. }
  177. }
  178. }
  179. return $ConversationID;
  180. }
  181. /**
  182. * Clear a conversation for a specific user id.
  183. */
  184. public function Clear($ConversationID, $ClearingUserID) {
  185. $this->SQL->Update('UserConversation')
  186. ->Set('Deleted', 1)
  187. ->Set('DateLastViewed', Gdn_Format::ToDateTime())
  188. ->Where('UserID', $ClearingUserID)
  189. ->Where('ConversationID', $ConversationID)
  190. ->Put();
  191. }
  192. /**
  193. * Update a conversation as read for a specific user id.
  194. */
  195. public function MarkRead($ConversationID, $ReadingUserID) {
  196. // Update the the read conversation count for the user.
  197. $this->SQL->Update('UserConversation uc')
  198. ->Join('Conversation c', 'c.ConversationID = uc.ConversationID')
  199. ->Set('uc.CountReadMessages', 'c.CountMessages', FALSE)
  200. ->Set('uc.DateLastViewed', Gdn_Format::ToDateTime())
  201. ->Set('uc.LastMessageID', 'c.LastMessageID', FALSE)
  202. ->Where('c.ConversationID', $ConversationID)
  203. ->Where('uc.ConversationID', $ConversationID)
  204. ->Where('uc.UserID', $ReadingUserID)
  205. ->Put();
  206. // Also update the unread conversation count for this user
  207. $CountUnread = $this->SQL
  208. ->Select('c.ConversationID', 'count', 'CountUnread')
  209. ->From('UserConversation uc')
  210. ->Join('Conversation c', 'c.ConversationID = uc.ConversationID and uc.CountReadMessages < c.CountMessages')
  211. ->Where('uc.UserID', $ReadingUserID)
  212. ->Get()->Value('CountUnread', 0);
  213. $this->SQL
  214. ->Update('User')
  215. ->Set('CountUnreadConversations', $CountUnread)
  216. ->Where('UserID', $ReadingUserID)
  217. ->Put();
  218. // Also write through to the current session user.
  219. if($ReadingUserID > 0 && $ReadingUserID == Gdn::Session()->UserID)
  220. Gdn::Session()->User->CountUnreadConversations = $CountUnread;
  221. }
  222. /**
  223. * Bookmark (or unbookmark) a conversation for a specific user id.
  224. */
  225. public function Bookmark($ConversationID, $UserID) {
  226. $Bookmark = FALSE;
  227. $Discussion = $this->GetID($ConversationID, $UserID);
  228. if (is_object($Discussion)) {
  229. $Bookmark = $Discussion->Bookmark == '0' ? '1' : '0';
  230. $this->SQL->Update('UserConversation')
  231. ->Set('Bookmark', $Bookmark)
  232. ->Where('ConversationID', $ConversationID)
  233. ->Where('UserID', $UserID)
  234. ->Put();
  235. $Bookmark == '1' ? TRUE : FALSE;
  236. }
  237. return $Bookmark;
  238. }
  239. public function AddUserToConversation($ConversationID, $UserID) {
  240. if (!is_array($UserID))
  241. $UserID = array($UserID);
  242. // First define the current users in the conversation
  243. $OldContributorData = $this->GetRecipients($ConversationID);
  244. $OldContributorUserIDs = ConsolidateArrayValuesByKey($OldContributorData->ResultArray(), 'UserID');
  245. $AddedUserIDs = array();
  246. // Get some information about this conversation
  247. $ConversationData = $this->SQL
  248. ->Select('LastMessageID')
  249. ->Select('CountMessages')
  250. ->From('Conversation')
  251. ->Where('ConversationID', $ConversationID)
  252. ->Get()
  253. ->FirstRow();
  254. // Add the user(s) if they are not already in the conversation
  255. foreach ($UserID as $NewUserID) {
  256. if (!in_array($NewUserID, $OldContributorUserIDs)) {
  257. $AddedUserIDs[] = $NewUserID;
  258. $this->SQL->Insert('UserConversation', array(
  259. 'UserID' => $NewUserID,
  260. 'ConversationID' => $ConversationID,
  261. 'LastMessageID' => $ConversationData->LastMessageID,
  262. 'CountReadMessages' => 0
  263. ));
  264. }
  265. }
  266. if (count($AddedUserIDs) > 0) {
  267. $Session = Gdn::Session();
  268. // Update the Contributors field on the conversation
  269. $Contributors = array_unique(array_merge($AddedUserIDs, $OldContributorUserIDs));
  270. sort($Contributors);
  271. $this->SQL
  272. ->Update('Conversation')
  273. ->Set('Contributors', Gdn_Format::Serialize($Contributors))
  274. ->Where('ConversationID', $ConversationID)
  275. ->Put();
  276. // NOTIFY ALL NEWLY ADDED USERS THAT THEY WERE ADDED TO THE CONVERSATION
  277. foreach ($AddedUserIDs as $AddedUserID) {
  278. AddActivity(
  279. $Session->UserID,
  280. 'AddedToConversation',
  281. '',
  282. $AddedUserID,
  283. '/messages/'.$ConversationID
  284. );
  285. }
  286. // Update the unread conversation count for each affected user
  287. $this->SQL
  288. ->Update('User')
  289. ->Set('CountUnreadConversations', 'CountUnreadConversations + 1', FALSE)
  290. ->WhereIn('UserID', $AddedUserIDs)
  291. ->Put();
  292. }
  293. }
  294. }