GroupInfo.php 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386
  1. <?php
  2. /**
  3. * 群组相关
  4. * @author solu
  5. */
  6. class GroupInfo extends Model {
  7. protected $tableName = 'group_info';
  8. protected $dbKey = 'dw_chat';
  9. const OFFICIAL_ID = 10000; // 官方群id
  10. const MAX_ADMIN_COUNT = 6; // 最多管理员数量
  11. const REDIS_GROUP_ID_HASH = 'globals:group_id_hash';
  12. /**
  13. * 加入群组
  14. * @author solu
  15. * @param $userId
  16. * @param $groupId
  17. * @param $group
  18. * @return bool
  19. * @throws Exception
  20. */
  21. public function joinGroup($userId, $groupId, $group = []) {
  22. $where = ['group_id' => $groupId];
  23. !$group && $group = $this->objTable->getRow($where);
  24. if (!$group) {
  25. throw new Exception('group not exists', CODE_PARAM_ERROR);
  26. }
  27. $objUserGroup = new TableHelper('user_group', 'dw_chat');
  28. if ($objUserGroup->getRow(['user_id' => $userId, 'group_id' => $groupId, 'state' => UserGroup::STATE_IN_GROUP])) {
  29. throw new Exception('already joined this group', CODE_PARAM_ERROR);
  30. }
  31. $objSession = new Session();
  32. $objUserGroup->autoCommit(false);
  33. $data = [
  34. 'user_id' => $userId,
  35. 'group_id' => $groupId,
  36. 'join_time' => NOW,
  37. 'state' => UserGroup::STATE_IN_GROUP,
  38. ];
  39. if (!$objUserGroup->replaceObject($data)) {
  40. throw new Exception('join fail', CODE_DB_ERROR);
  41. }
  42. $memberNum = $group['member_num'] + 1;
  43. $where['member_num'] = $group['member_num'];
  44. if (!$this->objTable->updateObject(['member_num' => $memberNum], $where)) {
  45. throw new Exception('update group info fail', CODE_DB_ERROR);
  46. }
  47. $sessData = [
  48. 'user_id' => $userId,
  49. 'session_id' => $groupId,
  50. 'is_group' => 1,
  51. ];
  52. if (!$objSession->objTable->replaceObject($sessData)) {
  53. throw new Exception('create session error', CODE_DB_ERROR);
  54. }
  55. $objUserGroup->commit();
  56. // 给自己发消息订阅新群组
  57. ThirdApi::pushPersonEvent($userId, [
  58. 'type' => 'join_group',
  59. 'group_id' => $groupId,
  60. ]);
  61. $user_info = User::getUserInfoById($userId);
  62. // 给群组发消息有人加入了
  63. ThirdApi::pushGroupEvent($groupId, [
  64. 'type' => 'join',
  65. 'group_id' => $groupId,
  66. 'user_info' => $user_info,
  67. ]);
  68. return true;
  69. }
  70. /**
  71. * 加入群组
  72. * @author solu
  73. * @param $userId
  74. * @param $groupId
  75. * @param $group
  76. * @return bool
  77. * @throws Exception
  78. */
  79. public function appendToGroup($userIds, $groupId) {
  80. $userGroupDatas = [];
  81. $sessDatas = [];
  82. foreach ($userIds as $userId) {
  83. $userGroupDatas[] = [
  84. 'user_id' => $userId,
  85. 'group_id' => $groupId,
  86. 'join_time' => NOW,
  87. 'state' => UserGroup::STATE_IN_GROUP,
  88. ];
  89. $sessDatas[] = [
  90. 'user_id' => $userId,
  91. 'session_id' => $groupId,
  92. 'is_group' => 1,
  93. ];
  94. }
  95. $objUserGroup = new UserGroup();
  96. $objUserGroup->objTable->replaceObjects2($userGroupDatas);
  97. $objSession = new Session();
  98. $objSession->objTable->replaceObjects2($sessDatas);
  99. $where = ['group_id' => $groupId];
  100. $newData = [
  101. 'member_num' => count($userIds),
  102. 'group_name' => $groupId,
  103. ];
  104. $this->objTable->updateObject($newData, $where);
  105. }
  106. /**
  107. * 离开群组
  108. * @author solu
  109. * @param $userId
  110. * @param $groupId
  111. * @param $group
  112. * @return bool
  113. * @throws Exception
  114. */
  115. public function leaveGroup($userId, $groupId, $group = []) {
  116. $groupId = (int) $groupId;
  117. $where = ['group_id' => $groupId];
  118. !$group && $group = $this->objTable->getRow($where);
  119. if (!$group) {
  120. throw new Exception('group not exists', CODE_PARAM_ERROR);
  121. }
  122. $objUserGroup = new UserGroup();
  123. if (!$objUserGroup->inGroup($groupId, $userId)) {
  124. throw new Exception('not in group', CODE_PARAM_ERROR);
  125. }
  126. $groupUserIds = $objUserGroup->getUserIdListSortByAdminAndJoinTime($groupId);
  127. $isCreator = $this->isCreator($groupId, $userId);
  128. $objSession = new Session();
  129. $objUserGroup->objTable->autoCommit(false);
  130. $ugWhere = [
  131. 'user_id' => $userId,
  132. 'group_id' => $groupId,
  133. ];
  134. if (!$objUserGroup->objTable->updateObject(['state' => UserGroup::STATE_LEAVE, 'is_admin' => 0], $ugWhere)) {
  135. throw new Exception('leave fail', CODE_DB_ERROR);
  136. }
  137. $creatorField = '';
  138. if (count($groupUserIds) == 1) { // 最后一个人离开,去掉群主,群解散
  139. $creatorField = ' , creator=0';
  140. } elseif ($isCreator) { // 群主离开, 群主顺移给下一位
  141. $newCreator = 0;
  142. for ($i = 0; $i < count($groupUserIds); $i++) {
  143. if ($groupUserIds[$i] == $userId) {
  144. continue;
  145. }
  146. $newCreator = $groupUserIds[$i];
  147. break;
  148. }
  149. $creatorField = " , creator={$newCreator}";
  150. // 新群主设置成管理员
  151. $objUserGroup->setData($groupId, $newCreator, ['is_admin' => 1]);
  152. }
  153. $sql = "UPDATE group_info SET member_num = member_num - 1 {$creatorField} WHERE group_id = {$groupId}";
  154. $this->objDb->update($sql);
  155. $sessWhere = [
  156. 'user_id' => $userId,
  157. 'session_id' => $groupId,
  158. ];
  159. if (!$objSession->objTable->delObject($sessWhere)) {
  160. throw new Exception('delete session error', CODE_DB_ERROR);
  161. }
  162. $objUserGroup->objTable->commit();
  163. // 给自己发消息订阅新群组
  164. ThirdApi::pushPersonEvent($userId, [
  165. 'type' => 'leave_group',
  166. 'group_id' => $groupId,
  167. ]);
  168. $user_info = User::getUserInfoById($userId);
  169. // 给群组发消息有人离开了
  170. ThirdApi::pushGroupEvent($groupId, [
  171. 'type' => 'leave',
  172. 'group_id' => $groupId,
  173. 'user_id' => $userId,
  174. 'user_info' => $user_info,
  175. ]);
  176. return true;
  177. }
  178. /**
  179. * 更新信息
  180. * @author solu
  181. * @param $userId
  182. * @param $groupId
  183. * @param array $data
  184. * @return bool|int
  185. * @throws Exception
  186. */
  187. public function setData($userId, $groupId, array $data) {
  188. if (!(new UserGroup())->isAdmin($groupId, $userId)) {
  189. throw new Exception('no permission', CODE_NO_PERMITION);
  190. }
  191. $data['update_time'] = NOW;
  192. return $this->objTable->updateObject($data, ['group_id' => $groupId]);
  193. }
  194. /**
  195. * 分享连接
  196. * @author solu
  197. * @param string $name
  198. * @return string
  199. */
  200. public static function genInviteUrl($name) {
  201. if (!$name) {
  202. return '';
  203. }
  204. return sprintf('%s/s/%s', URL_SELF, $name);
  205. }
  206. /**
  207. * 是否群主
  208. * @author solu
  209. * @param $groupId
  210. * @param $userId
  211. * @return bool
  212. */
  213. public function isCreator($groupId, $userId) {
  214. $creator = $this->objTable->getOne(['group_id' => $groupId], ['_field' => 'creator']);
  215. return intval($creator) == $userId;
  216. }
  217. /**
  218. * 设置群管理
  219. * @author solu
  220. * @param $groupId
  221. * @param $creator
  222. * @param $userIds
  223. * @return bool
  224. * @throws Exception
  225. */
  226. public function addAdmin($groupId, $creator, $userIds) {
  227. if (!$this->isCreator($groupId, $creator)) {
  228. throw new Exception('no permission', CODE_NO_PERMITION);
  229. }
  230. $objUserGroup = new UserGroup();
  231. $c = $objUserGroup->objTable->getCount(['group_id' => $groupId, 'is_admin' => 1]);
  232. $c += count($userIds);
  233. if ($c > self::MAX_ADMIN_COUNT) {
  234. throw new Exception('too many admins', CODE_NORMAL_ERROR);
  235. }
  236. if (!$objUserGroup->setData($groupId, $userIds, ['is_admin' => 1])) {
  237. throw new Exception('set admin fail', CODE_NORMAL_ERROR);
  238. }
  239. return true;
  240. }
  241. /**
  242. * 移除管理员
  243. * @author solu
  244. * @param $groupId
  245. * @param $creator
  246. * @param $userId
  247. * @return bool
  248. * @throws Exception
  249. */
  250. public function removeAdmin($groupId, $creator, $userId) {
  251. if (!$this->isCreator($groupId, $creator)) {
  252. throw new Exception('no permission', CODE_NO_PERMITION);
  253. }
  254. if ($userId == $creator) {
  255. throw new Exception('can not remove creator', CODE_NORMAL_ERROR);
  256. }
  257. $objUserGroup = new UserGroup();
  258. if (!$objUserGroup->setData($groupId, $userId, ['is_admin' => 0])) {
  259. throw new Exception('set admin fail', CODE_NORMAL_ERROR);
  260. }
  261. return true;
  262. }
  263. /**
  264. * 搜索群用户信息
  265. * @author solu
  266. * @param $groupId
  267. * @param $keyword
  268. * @return array
  269. */
  270. public function memberSearch($groupId, $keyword) {
  271. $objUserGroup = new UserGroup();
  272. $userIds = $objUserGroup->objTable->getCol(['group_id' => $groupId], ['_field' => 'user_id']);
  273. if (!$userIds) {
  274. return [];
  275. }
  276. $objUserInfo = new TableHelper('user_info', 'dw_chat');
  277. $userInfo = $objUserInfo->getAll(['user_id' => $userIds], [
  278. '_where' => "(user_name like '{$keyword}%' || nick_name like '{$keyword}%')",
  279. '_field' => 'user_id, user_name, nick_name, cover_photo',
  280. '_sortKey' => 'last_login_time DESC',
  281. // '_debug' => true,
  282. ]);
  283. coverReplaceArrImage($userInfo, 'cover_photo');
  284. return $userInfo;
  285. }
  286. /**
  287. * 获取用户名
  288. * @author solu
  289. * @param $groupId
  290. * @return string
  291. */
  292. public static function getGroupNameById($groupId) {
  293. $objRedis = dwRedis::init();
  294. $userName = $objRedis->hGet(self::REDIS_GROUP_ID_HASH, $groupId);
  295. if (!$userName) {
  296. $obj = new GroupInfo();
  297. $userName = $obj->objTable->getOne(['group_id' => $groupId], ['_field' => 'group_title']);
  298. if ($userName) {
  299. self::setGroupNameById($groupId, $userName, $objRedis);
  300. }
  301. }
  302. return $userName;
  303. }
  304. public static function setGroupNameById($groupId, $user_name, $objRedis = null) {
  305. !$objRedis && $objRedis = dwRedis::init();
  306. $objRedis->hSet(self::REDIS_GROUP_ID_HASH, $groupId, $user_name);
  307. }
  308. /**
  309. * 转移群主
  310. * @author solu
  311. * @param $groupId
  312. * @param $old
  313. * @param $new
  314. * @return bool
  315. * @throws Exception
  316. */
  317. public function changeCreator($groupId, $old, $new) {
  318. if (!$this->isCreator($groupId, $old)) {
  319. throw new Exception('no permission', CODE_NO_PERMITION);
  320. }
  321. if ($old == $new) {
  322. throw new Exception('same creator', CODE_NORMAL_ERROR);
  323. }
  324. $this->objTable->updateObject(['creator' => $new], ['group_id' => $groupId]);
  325. (new UserGroup())->setData($groupId, $old, ['is_admin' => 0]);
  326. return true;
  327. }
  328. }