MessageRepository.php 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258
  1. <?php
  2. namespace App\Repositories;
  3. use App\Jobs\MessageDoReadJob;
  4. use App\Model\Mongo\MessageModel;
  5. use Carbon\Carbon;
  6. use MongoDB\BSON\ObjectId;
  7. /**
  8. * 站内用户消息,非MySQL
  9. */
  10. class MessageRepository
  11. {
  12. public function coreSend($params)
  13. {
  14. $nowDate = toMongoIsoDate(Carbon::now());
  15. if (!empty($params['created_at'])) {
  16. $createdDate = Carbon::parse($params['created_at']);
  17. } else {
  18. $createdDate = Carbon::now();
  19. }
  20. $createdAt = toMongoIsoDate($createdDate);
  21. // 没有则创建, 系统消息是不能删除的.
  22. $setarr = [
  23. 'subject' => data_get($params, 'subject', ''),
  24. 'struct_type' => data_get($params, 'struct_type', 'text'),
  25. 'receive_uid' => data_get($params, 'receive_uid', ''),
  26. 'receive_type' => data_get($params, 'receive_type', 'user'),
  27. 'from_uid' => data_get($params, 'from_uid', ''),
  28. 'from_type' => data_get($params, 'from_type', 'sys'),
  29. 'sys_msg_uid' => data_get($params, 'sys_msg_uid', ''),
  30. 'content' => data_get($params, 'content', ''),
  31. 'created_at' => $createdAt,
  32. 'updated_at' => $nowDate,
  33. 'read_at' => null, // null代表未阅读
  34. ];
  35. make(MessageModel::class)->db()->insertOne($setarr);
  36. return true;
  37. }
  38. public function sendTextFromSys($receiveUid, $content, $subject = '')
  39. {
  40. $contentStruct = [
  41. 'text' => $content,
  42. ];
  43. $params = [
  44. 'subject' => $subject,
  45. 'content' => $contentStruct,
  46. 'struct_type' => 'text',
  47. 'receive_uid' => $receiveUid,
  48. 'receive_type' => 'user',
  49. 'from_type' => 'sys',
  50. ];
  51. return $this->coreSend($params);
  52. }
  53. public function sendTextFromUser($receiveUid, $fromUid, $content, $subject = '')
  54. {
  55. $contentStruct = [
  56. 'text' => $content,
  57. ];
  58. $params = [
  59. 'subject' => $subject,
  60. 'content' => $contentStruct,
  61. 'struct_type' => 'text',
  62. 'receive_uid' => $receiveUid,
  63. 'receive_type' => 'user',
  64. 'from_uid' => $fromUid,
  65. 'from_type' => 'user',
  66. ];
  67. return $this->coreSend($params);
  68. }
  69. /**
  70. * 根据上一次时间获取分页系统消息数据
  71. * @param $receiveUid
  72. * @param $previousDate
  73. * @param int $limitNum
  74. * @return array
  75. */
  76. public function previousSysPages($receiveUid, $previousDate, $limitNum = 20, $autoRead = false)
  77. {
  78. $createAt = toMongoIsoDate(Carbon::parse($previousDate));
  79. $filters = [
  80. 'receive_uid' => (string)$receiveUid,
  81. 'from_type' => 'sys',
  82. 'created_at' => [
  83. '$lt' => $createAt,
  84. ],
  85. ];
  86. $options = [
  87. 'sort' => [
  88. 'created_at' => -1, // 时间降序
  89. ],
  90. 'limit' => $limitNum,
  91. ];
  92. // $count = make(MessageModel::class)->db()->countDocuments($filters);
  93. $unreadIds = [];
  94. $cursor = make(MessageModel::class)->db()->find($filters, $options);
  95. $data = [];
  96. if (!empty($cursor)) {
  97. $data = $cursor->toArray();
  98. foreach ($data as $k => &$v) {
  99. $v['msg_id'] = $v['_id']->__toString();
  100. if ($autoRead === true) {
  101. if (is_null($v['read_at'])) {
  102. // 未读,自动标记已读
  103. $unreadIds[] = $v['msg_id'];
  104. }
  105. }
  106. $v['created_at'] = mongoIsoDateToCarbonTime($v['created_at'])->toDateTimeString();
  107. $v['updated_at'] = mongoIsoDateToCarbonTime($v['updated_at'])->toDateTimeString();
  108. $v['read_at'] = !empty($v['read_at']) ? mongoIsoDateToCarbonTime($v['read_at'])->toDateTimeString() : null;
  109. unset($v['_id'], $v['from_uid'], $v['from_type']);
  110. }
  111. // $data = array_reverse($data); // 时序反转
  112. }
  113. if ($autoRead === true && !empty($unreadIds)) {
  114. // 异步自动标记已读.
  115. $jobParams = [
  116. 'ids' => $unreadIds,
  117. ];
  118. dispatch_job(new MessageDoReadJob($jobParams));
  119. }
  120. return $data;
  121. }
  122. /**
  123. * 标记一个消息已读.
  124. * @param string $msgId
  125. * @param mixed $receiveUid
  126. * @return bool
  127. */
  128. public function doRead($msgId, $receiveUid = null)
  129. {
  130. $mongoId = new ObjectId($msgId);
  131. $readAt = toMongoIsoDate(Carbon::now());
  132. $filters = [
  133. '_id' => $mongoId,
  134. ];
  135. if (!empty($receiveUid)) {
  136. $filters['receive_uid'] = $receiveUid;
  137. }
  138. $count = make(MessageModel::class)->db()->countDocuments($filters);
  139. if ($count) {
  140. make(MessageModel::class)->db()->updateOne(
  141. $filters,
  142. [
  143. '$set' => [
  144. 'read_at' => $readAt
  145. ]
  146. ]
  147. );
  148. return true;
  149. } else {
  150. return false;
  151. }
  152. }
  153. /**
  154. * 静默删除多个.
  155. * @param $msgIds
  156. * @param null $receiveUid
  157. * @return bool
  158. */
  159. public function slientDelete($msgIds, $receiveUid = null)
  160. {
  161. if (empty($msgIds)) {
  162. return false;
  163. }
  164. if (is_string($msgIds)) {
  165. $msgIds = [$msgIds];
  166. }
  167. $msgIds = array_filter($msgIds);
  168. $msgIds = array_unique($msgIds);
  169. if (empty($msgIds)) {
  170. return false;
  171. }
  172. $arrMongoIds = [];
  173. foreach ($msgIds as $msgId) {
  174. $mongoId = new ObjectId($msgId);
  175. $arrMongoIds[] = $mongoId;
  176. }
  177. $filters = [
  178. '_id' => [
  179. '$in' => $arrMongoIds,
  180. ],
  181. ];
  182. if (!empty($receiveUid)) {
  183. $filters['receive_uid'] = $receiveUid;
  184. }
  185. $lines = make(MessageModel::class)->db()->deleteMany(
  186. $filters
  187. )->getDeletedCount();
  188. if ($lines > 0) {
  189. return true;
  190. } else {
  191. return false;
  192. }
  193. }
  194. /*
  195. * 获取第一条系统消息,包含统计.
  196. */
  197. public function firstSys($receiveUid, $msgType = 'sys')
  198. {
  199. $filters = [
  200. 'receive_uid' => (string)$receiveUid,
  201. 'from_type' => $msgType,
  202. ];
  203. $countAll = make(MessageModel::class)->db()->countDocuments($filters);
  204. $filters = [
  205. 'receive_uid' => (string)$receiveUid,
  206. 'from_type' => $msgType,
  207. 'read_at' => null,
  208. ];
  209. $countUnread = make(MessageModel::class)->db()->countDocuments($filters);
  210. $filters = [
  211. 'receive_uid' => (string)$receiveUid,
  212. 'from_type' => $msgType,
  213. ];
  214. $options = [
  215. 'sort' => [
  216. 'created_at' => -1, // 时间降序
  217. ],
  218. 'limit' => 1,
  219. ];
  220. $firstMsg = make(MessageModel::class)->db()->findOne($filters, $options);
  221. if (!empty($firstMsg->_id)) {
  222. $firstMsg['msg_id'] = $firstMsg['_id']->__toString();
  223. $firstMsg['created_at'] = mongoIsoDateToCarbonTime($firstMsg['created_at'])->toDateTimeString();
  224. $firstMsg['updated_at'] = mongoIsoDateToCarbonTime($firstMsg['updated_at'])->toDateTimeString();
  225. $firstMsg['read_at'] = !empty($firstMsg['read_at']) ? mongoIsoDateToCarbonTime($firstMsg['read_at'])->toDateTimeString() : null;
  226. unset($firstMsg['_id'], $firstMsg['from_type']);
  227. } else {
  228. $firstMsg = null;
  229. }
  230. $result = [
  231. 'first_msg' => $firstMsg,
  232. 'count_all' => $countAll,
  233. 'count_unread' => $countUnread,
  234. ];
  235. return $result;
  236. }
  237. }