PageRenderTime 77ms CodeModel.GetById 37ms RepoModel.GetById 1ms app.codeStats 0ms

/Lib/Base/Dao/User.php

https://github.com/ilyich/iqyou
PHP | 1210 lines | 850 code | 179 blank | 181 comment | 166 complexity | 17ea9d4cff7a615345bc84d9dc1b1ee7 MD5 | raw file
  1. <?php
  2. class Base_Dao_User
  3. {
  4. /*
  5. * Source constants moved to Base_Service_UserSource
  6. */
  7. const TABLE_USER_SETTINGS = 'user_settings';
  8. const MC_USER_SETTINGS = 'userSettings:';
  9. const MC_USER_DELETE_REQUEST_TIME = 'userRequestDelTime:';
  10. const MC_USER_INTERESTPEOPLE = 'userInterestPeople:';
  11. const LKEY_PREVIOUS_TIME_IN = 'userOldTimeIn';
  12. const SHOW_STATUS_DEFAULT = 0;
  13. const SHOW_STATUS_NODATING = 1;
  14. const SHOW_STATUS_NODATING_IN_PEOPLE = 2;
  15. const LASTNAME_STATUS_SHOW = 0;
  16. const LASTNAME_STATUS_HIDE = 1;
  17. private static $requestLog = array();
  18. private static $requestHashes = array();
  19. private static $requestLoaded = array();
  20. private static $requestId = 0;
  21. private static $userToRequest = array();
  22. // const USER_SOURCE_DATING = 633;
  23. // const USER_SOURCE_LETITBIT = 803;
  24. // const USER_SOURCE_TMP_VK = 753;
  25. // const USER_SOURCE_MAILRU = 644;
  26. const DELETE_HISTORY_COME_BACK = -1; // reason в user_delete_history когда юзер возвращается на сайт (анкета восстанавливается)
  27. /**
  28. * Get the site population count
  29. *
  30. * @return int
  31. */
  32. public static function getUsersCount()
  33. {
  34. return Base_Service_Memcache::get('countUsersMain', __METHOD__);
  35. }
  36. /**
  37. * Get the site population count without doubt
  38. * @see CronController::saveUsersCount()
  39. * @return int
  40. */
  41. public static function getUsersCountForSure()
  42. {
  43. return self::getUsersCount() ?: Base_Service_Lemon::get(__METHOD__, 'persistent_all_users_count', 1);
  44. }
  45. /**
  46. * получить ков-ло пользователей online
  47. */
  48. public static function getUsersOnlineCount()
  49. {
  50. return Base_Service_Memcache::get('countUsersOnline', __METHOD__);
  51. }
  52. /**
  53. * обновить кол-во пользователей online
  54. */
  55. public static function updateUsersOnlineCount()
  56. {
  57. $db = Base_Context::getInstance()->getDbConnection();
  58. $count = $db->fetchOne('SELECT COUNT(*) FROM auto_online', __METHOD__);
  59. Base_Service_Memcache::set('countUsersOnline', $count, 432000);
  60. }
  61. /**
  62. * Получаем пользователя по имени страницы
  63. *
  64. * @param string $pageName
  65. * @return array
  66. */
  67. public static function getUserByPageName($pageName)
  68. {
  69. if (!$pageName) {
  70. return ;
  71. }
  72. if (in_array($pageName, Db_User::$loginStopWords)) {
  73. return false;
  74. }
  75. $key = 'userPage:'.$pageName;
  76. $userId = Base_Service_Memcache::get($key, __METHOD__);
  77. if (!$userId) {
  78. $db = Base_Context::getInstance()->getDbConnection();
  79. $user = $db->fetchRow($db->select()->from('user')->where('user_pagename = ?', $pageName), __METHOD__);
  80. if ($user) {
  81. Base_Service_Memcache::set($key, $user['user_id'], 86400);
  82. return $user;
  83. }
  84. $userNew = $db->fetchRow($db->select()->from('user_new')->where('user_pagename = ?', $pageName), __METHOD__);
  85. if ($userNew) {
  86. Base_Service_Memcache::set($key, $userNew['user_id'], 86400);
  87. return $userNew;
  88. }
  89. return false;
  90. }
  91. return self::getUserById($userId);
  92. }
  93. /**
  94. * Загружаем пользователя по ID. Если пользователя нет - вовращает NULL.
  95. *
  96. * @param int $userId
  97. * @return Base_Model_User
  98. */
  99. public static function getFullUserById($userId)
  100. {
  101. if (Db_User::isShortUserEnabled()) {
  102. self::preloadAllUsersWithUser($userId);
  103. }
  104. $userData = Db_User::getMemcachedUser((int)$userId);
  105. return $userData && isset($userData['user_id']) && $userData['user_id'] > 0 ? new Base_Model_User($userData) : null;
  106. }
  107. /**
  108. * Загружаем пользователя по ID. Если пользователя нет - вовращает NULL.
  109. *
  110. * @param int $userId
  111. * @return Base_Model_UserShort
  112. */
  113. public static function getShortUserById($userId)
  114. {
  115. if (!Db_User::isShortUserEnabled()) {
  116. return self::getFullUserById($userId);
  117. }
  118. self::logGetRequest(array($userId));
  119. $userData = Db_User::getMemcachedShortUser((int)$userId);
  120. return $userData && isset($userData['user_id']) && $userData['user_id'] > 0 ? new Base_Model_UserShort($userData) : null;
  121. }
  122. public static function getUserById($userId) {
  123. if (!Db_User::isShortUserEnabled()) {
  124. return self::getFullUserById($userId);
  125. }
  126. return self::getShortUserById($userId);
  127. }
  128. /**
  129. * Возвращает список укороченных моделек пользователей.
  130. * @static
  131. * @param array $userIds иды пользователей
  132. * @param bool $saveSort флаг сохранения порядка пользователей
  133. *
  134. * @return array|Base_Model_User[]
  135. */
  136. public static function getShortUsersByIds(array $userIds, $saveSort = false)
  137. {
  138. if (!Db_User::isShortUserEnabled()) {
  139. return self::getFullUsersByIds($userIds, $saveSort);
  140. }
  141. self::logGetRequest($userIds);
  142. $users = array();
  143. $usersData = Db_User::getMemcachedShortUser($userIds);
  144. if ($saveSort) {
  145. foreach ($userIds as $userId) {
  146. if (!empty($usersData[$userId]['user_id'])) {
  147. $users[$userId] = new Base_Model_UserShort($usersData[$userId]);
  148. }
  149. }
  150. } else {
  151. foreach ($usersData as $k => $data) {
  152. if (!empty($data['user_id'])) {
  153. $users[$k] = new Base_Model_UserShort($data);
  154. }
  155. }
  156. }
  157. return $users;
  158. }
  159. public static function getUsersByIds(array $userIds, $saveSort = false)
  160. {
  161. if (!Db_User::isShortUserEnabled()) {
  162. return self::getFullUsersByIds($userIds, $saveSort);
  163. }
  164. return self::getShortUsersByIds($userIds, $saveSort);
  165. }
  166. /**
  167. * Возвращает список моделек пользователей.
  168. * @static
  169. * @param array $userIds иды пользователей
  170. * @param bool $saveSort флаг сохранения порядка пользователей
  171. *
  172. * @return array|Base_Model_User[]
  173. */
  174. public static function getFullUsersByIds(array $userIds, $saveSort = false)
  175. {
  176. /*
  177. $trace = debug_backtrace(); $trace = $trace[1];
  178. $report = isset($trace['class'])
  179. ? $trace['class']."::".$trace['function'] ." // line: ".$trace['line']
  180. : $trace['file'] ." // " . $trace['line'];
  181. Base_Service_Profiler_Log::dump("guM >> " . $report);
  182. */
  183. $users = array();
  184. $usersData = Db_User::getMemcachedUser($userIds);
  185. if ($saveSort) {
  186. foreach ($userIds as $userId) {
  187. if (!empty($usersData[$userId]['user_id'])) {
  188. $users[$userId] = new Base_Model_User($usersData[$userId]);
  189. }
  190. }
  191. } else {
  192. foreach ($usersData as $k => $data) {
  193. if (!empty($data['user_id'])) {
  194. $users[$k] = new Base_Model_User($data);
  195. }
  196. }
  197. }
  198. return $users;
  199. }
  200. public static function getAdultUsersByIds(array $userIds)
  201. {
  202. $users = self::getShortUsersByIds($userIds);
  203. foreach ($users as $userId => $user) {
  204. if (!$user->isAdult() && $user->getAge()) {
  205. unset($users[$userId]);
  206. }
  207. }
  208. return $users;
  209. }
  210. /**
  211. * @return Base_Model_User
  212. */
  213. public static function getUserByLoginPass($login, $password)
  214. {
  215. if (!$login || $login == Db_User::DEFAULT_EMAIL) {
  216. return null;
  217. }
  218. $passHash = Base_Service_User::getPasswordHash($password);
  219. $userData = null;
  220. $db = Base_Context::getInstance()->getDbConnection();
  221. foreach (array('user', 'user_new') as $table) {
  222. $select = $db->select()->from($table)->where('user_email = ?', $login);
  223. $users = $db->fetchAll($select, __METHOD__);
  224. foreach ($users as $user) {
  225. if (isset($user['password_hash']) && $user['password_hash']) {
  226. if ($user['password_hash'] == $passHash) {
  227. $userData = $user;
  228. }
  229. break;
  230. } elseif (isset($user['user_password']) && $user['user_password'] == $password) {
  231. $userData = $user;
  232. break;
  233. }
  234. }
  235. }
  236. return $userData ? new Base_Model_User($userData) : null;
  237. }
  238. /**
  239. * @return Base_Model_User
  240. */
  241. public static function getUserByLoginPassHash($login, $passwordHash)
  242. {
  243. if (!$login || $login == Db_User::DEFAULT_EMAIL) {
  244. return null;
  245. }
  246. $userData = null;
  247. $db = Base_Context::getInstance()->getDbConnection();
  248. foreach (array('user', 'user_new') as $table) {
  249. $select = $db->select()->from($table)->where('user_email = ?', $login);
  250. $users = $db->fetchAll($select, __METHOD__);
  251. foreach ($users as $user) {
  252. if (isset($user['password_hash']) && $user['password_hash'] == $passwordHash) {
  253. $userData = $user;
  254. break;
  255. }
  256. }
  257. }
  258. return $userData ? new Base_Model_User($userData) : null;
  259. }
  260. /**
  261. * Получение пользователя по номеру телефона и паролю (для авторизации по номеру телефону).
  262. *
  263. * @static
  264. * @param string $phone
  265. * @param string $passwordHash
  266. * @return Base_Model_User|null
  267. */
  268. public static function getUserByPhonePassHash($phone, $passwordHash)
  269. {
  270. if (!$phone) {
  271. return null;
  272. }
  273. $userData = null;
  274. $db = Base_Context::getInstance()->getDbConnection();
  275. foreach (array('user', 'user_new') as $table) {
  276. $select = $db->select()->from($table)->where('user_phone = ?', $phone);
  277. $users = $db->fetchAll($select, __METHOD__);
  278. foreach ($users as $user) {
  279. if (isset($user['password_hash']) && $user['password_hash'] == $passwordHash) {
  280. $userData = $user;
  281. break;
  282. }
  283. }
  284. }
  285. return $userData ? new Base_Model_User($userData) : null;
  286. }
  287. // получение пользователя по номеру телефона
  288. public static function getUserByPhone($phoneNumber, $approvedOnly = true)
  289. {
  290. if (!$phoneNumber) {
  291. return null;
  292. }
  293. $userData = null;
  294. $db = Base_Context::getInstance()->getDbConnection();
  295. foreach (array('user', 'user_new') as $table) {
  296. $where = $approvedOnly ? 'user_phone = ? AND user_phone_approved = 1' : 'user_phone = ?';
  297. $select = $db->select()->from($table)->where($where, $phoneNumber);
  298. $users = $db->fetchAll($select, __METHOD__);
  299. foreach ($users as $user) {
  300. if (isset($user['user_id'])) {
  301. $userData = $user;
  302. break;
  303. }
  304. }
  305. }
  306. return $userData ? new Base_Model_User($userData) : null;
  307. }
  308. public static function updateLastnameExternal($userId, $lastname, $gender=null)
  309. {
  310. $user = self::getUserById($userId);
  311. if($user && $user->getLastName()=='' && (!$gender || $user->getGender()==$gender)) {
  312. $update = array("user_lastname"=>$lastname, "user_lastname_show"=>Base_Dao_User::LASTNAME_STATUS_HIDE);
  313. self::updateUser($user->getId(), $update);
  314. $stats = new Base_Service_Counter_Social();
  315. $stats->increment($user, "socialsearch_lastnameadd");
  316. return true;
  317. }
  318. return false;
  319. }
  320. /**
  321. * @return Base_Model_User
  322. */
  323. public static function getUserByLogin($login)
  324. {
  325. if (!$login || $login == Db_User::DEFAULT_EMAIL) {
  326. return null;
  327. }
  328. $userData = null;
  329. $db = Base_Context::getInstance()->getDbConnection();
  330. foreach (array('user', 'user_new') as $table) {
  331. $select = $db->select()->from($table)->where('user_email = ?', $login);
  332. $users = $db->fetchAll($select, __METHOD__);
  333. foreach ($users as $user) {
  334. if (isset($user['user_id'])) {
  335. $userData = $user;
  336. break;
  337. }
  338. }
  339. if($userData) {
  340. break;
  341. }
  342. }
  343. return $userData ? new Base_Model_User($userData) : null;
  344. }
  345. /**
  346. * получить пользователей по почтам
  347. * $fullLoad - получить модели или просто список userId
  348. */
  349. public static function getUsersByEmails($emails, $fullLoad = true)
  350. {
  351. if(!$emails) {
  352. return null;
  353. }
  354. $searchEmails = array();
  355. foreach ($emails as $email) {
  356. if($email && $email != Db_User::DEFAULT_EMAIL) {
  357. if (!is_object($email)) {
  358. $email = (string) $email;
  359. }
  360. $searchEmails[$email] = $email;
  361. }
  362. }
  363. if(!$searchEmails) {
  364. return null;
  365. }
  366. $users = array();
  367. $db = Base_Context::getInstance()->getDbConnection();
  368. foreach (array('user', 'user_new') as $table) {
  369. if(!$searchEmails) {
  370. break;
  371. }
  372. $sql = $fullLoad ? $db->select()->from($table) : $db->select()->from($table, array('user_email', 'user_id'));
  373. $sql->where('user_email IN (?)', $searchEmails);
  374. if($records = $db->fetchAssoc($sql, __METHOD__)) {
  375. //$users = array_merge($users, $records);
  376. foreach ($records as $id => $record) {
  377. $users[$id] = $record;
  378. unset($searchEmails[$record['user_email']]);
  379. }
  380. }
  381. }
  382. return !$users ? NULL : ($fullLoad ? Base_Dao_User::makeUserModelsFromArray($users) : $users);
  383. }
  384. public static function addDeleteRequest($userId, $reason = '')
  385. {
  386. $user = Base_Dao_User::getUserById($userId);
  387. if (!$user) {
  388. return false;
  389. }
  390. $db = Base_Context::getInstance()->getDbConnection();
  391. $insert = array(
  392. 'user_id' => (int) $userId
  393. );
  394. if ($reason && is_string($reason)) {
  395. $insert['reason'] = $reason;
  396. }
  397. try {
  398. $db->insert('user_delete_request', $insert, __METHOD__);
  399. $user->getNativeProject()->getStatisticClient()->increment($user, 'delete_request', 1);
  400. // @analytics stats
  401. $analytics = new Base_Service_Counter_Analytics();
  402. $analytics->increment($user, 'delete_request');
  403. if (Support_Service_Zendesk::isUserRequest($user->getId())) {
  404. $analytics->increment($user, 'zd_delete_requests');
  405. }
  406. // если юзер снова удаляется, удаляем из трекинга
  407. Support_Dao_NotDeletedStats::deleteRequest(Support_Dao_NotDeletedStats::TABLE_C3, $user->getId());
  408. } catch (Exception $e) {
  409. return false;
  410. }
  411. Base_Service_Lemon2::set(__METHOD__, 'preDeleteSpamSettings', $userId, Base_Service_Spam::getSpamSettings($user), 30 * 24 * 60 * 60);
  412. Base_Service_Spam::unsubscribeAll($user);
  413. Return_Dao_Registry::deleteUserById($userId);
  414. // скроем юзера из поиска
  415. Search_Dao_Base::hideUserFromSearch($user->getId(), Search_Dao_Base::getUserSex($user), true);
  416. // удалим из фоторейтинга
  417. Rating_Service_Base::getInstance()->flushUser($user->getId());
  418. //Удаляем старый ключ (если он вообще был), новый поднимется сам, когда будет нужен
  419. Base_Service_Memcache::delete(self::MC_USER_DELETE_REQUEST_TIME . $userId);
  420. return true;
  421. }
  422. public static function cancelDeleteRequest($userId)
  423. {
  424. $db = Base_Context::getInstance()->getDbConnection();
  425. Base_Service_Memcache::delete(self::MC_USER_DELETE_REQUEST_TIME . $userId);
  426. $res = $db->delete('user_delete_request', $db->qq('user_id = ?', $userId), __METHOD__);
  427. $user = Base_Dao_User::getUserById($userId);
  428. $oldSpamSettings = Base_Service_Lemon2::get(__METHOD__, 'preDeleteSpamSettings', $userId);
  429. if ($oldSpamSettings !== false) {
  430. Base_Service_Spam::setSpamSettings($user, $oldSpamSettings);
  431. $user = Base_Dao_User::getUserById($userId); //TODO: костыль чтобы обновить юзера, потому что предыдущий метод его изменяет
  432. }
  433. Base_Service_Lemon2::delete(__METHOD__, 'preDeleteSpamSettings', $userId);
  434. Return_Dao_Registry::addUser($user);
  435. // вернем юзера в поиск
  436. Base_Service_UserSearch::updateUserInSearch($user->getId());
  437. // ставим на трекинг
  438. $notifySent = Base_Service_Lemon2::get(__METHOD__, Userinfo_Controller_Room::USER_REMOVE_FRIENDS_NOTIFY_KEY, $user->getId());
  439. if ($notifySent) {
  440. Support_Dao_NotDeletedStats::addRequest(Support_Dao_NotDeletedStats::TABLE_C3, $user->getId());
  441. Base_Service_Lemon2::delete(__METHOD__, Userinfo_Controller_Room::USER_REMOVE_FRIENDS_NOTIFY_KEY, $user->getId());
  442. }
  443. /**
  444. * @var $newsfeedInterface Newsfeed_Interface_Base
  445. */
  446. $newsfeedInterface = Base_Interface_Factory::get('Newsfeed');
  447. $newsfeedInterface->deleteEvent($user->getId(), Newsfeed_Dao_Base::EVENT_FRIEND_DELETED, $user->getId());
  448. $stats = new Base_Service_Counter_Main();
  449. $stats->increment($user, 'delete_request_break');
  450. return $res;
  451. }
  452. public static function getDeleteRequestTime($userId)
  453. {
  454. $deletionTime = Base_Service_Memcache::get(self::MC_USER_DELETE_REQUEST_TIME . $userId, __METHOD__);
  455. $deletionTimeCacheTtl = 86400;
  456. if ($deletionTime === false) {
  457. $db = Base_Context::getInstance()->getDbConnection();
  458. $select = $db->select()
  459. ->from('user_delete_request', array('UNIX_TIMESTAMP(request_time)'))
  460. ->where('user_id = ?', $userId);
  461. $deletionTime = $db->fetchOne($select, __METHOD__);
  462. Base_Service_Memcache::set(self::MC_USER_DELETE_REQUEST_TIME . $userId, $deletionTime, $deletionTimeCacheTtl);
  463. }
  464. return $deletionTime;
  465. }
  466. public static function getOnlineUserIds($userIds = array())
  467. {
  468. if (!is_array($userIds)) {
  469. $userIds = array($userIds);
  470. }
  471. if (empty($userIds)) {
  472. return array();
  473. }
  474. $db = Base_Context::getInstance()->getDbConnection();
  475. $query = $db->select()->from('auto_online', 'user_id')->where('user_id IN(?)', $userIds);
  476. return $db->fetchCol($query, __METHOD__);
  477. }
  478. /**
  479. * Обновляет данные в записи в таблице user/user_new и в мемкеше. Обновляет юзера в Base_Context,
  480. * если userId соответсвует залогиненному юзеру.
  481. *
  482. * @static
  483. * @param $userId
  484. * @param array $update
  485. * @return boolean
  486. */
  487. public static function updateUser($userId, array $update /* field => value */)
  488. {
  489. if (array_key_exists('user_email_approved', $update) && !$update['user_email_approved']) {
  490. Base_Service_Log::log('unapprove', array($userId, "\n".implode("\n", Base_Service_Log::getTrace(10))));
  491. }
  492. if (array_key_exists('user_name', $update) && Utf::stripos($update['user_name'], ' ',1)!==false) {
  493. Base_Service_Log::log('name_surname', array($userId, "\n".implode("\n", Base_Service_Log::getTrace(10))));
  494. }
  495. if (isset($update['user_lastname']) && $update['user_lastname'] && Utf::isUtf($update['user_lastname'])) {
  496. Base_Service_Log::log('utflastname', array($userId, "\n".implode("\n", Base_Service_Log::getTrace(10))));
  497. }
  498. $db = Base_Context::getInstance()->getDbConnection();
  499. $dbUpdate = $update;
  500. foreach ($dbUpdate as $key => $val) {
  501. if ($val === null) {
  502. $dbUpdate[$key] = new Zend_Db_Expr('null');
  503. }
  504. // костыль для предотвращения записи "0" вместо "NULL" в БД
  505. else if ($key === 'user_is_hidden' && $val == 0) {
  506. $dbUpdate[$key] = new Zend_Db_Expr('null');
  507. }
  508. }
  509. $rows = $db->update(Db_User::getTb($userId), $dbUpdate, 'user_id = ' . (int)$userId, __METHOD__);
  510. Db_User::updateMemcachedUser($userId, $update);
  511. // если это текущий юзер — обновляем модель
  512. $currentUser = Base_Context::getInstance()->getUser();
  513. if ($currentUser && $currentUser->getId() == $userId) {
  514. $currentUser->update($update);
  515. }
  516. // обновим информацию о пользователе в поиске
  517. if (Search_Dao_Base::hasDaldConfig() && Search_Dao_Base::hasUpdatebleFields(array_keys($update))) {
  518. Base_Service_UserSearch::updateUserInSearch($userId);
  519. }
  520. //обновим информацию о пользователе в свите
  521. if (isset($update['user_is_hidden'])) {
  522. Team_Service_Base::updateBanStatus($userId, $update['user_is_hidden']);
  523. }
  524. return $rows == 1;
  525. }
  526. public static function isPhoneRegistered($phoneNumber, $approvedOnly = true)
  527. {
  528. $db = Base_Context::getInstance()->getDbConnection();
  529. foreach (array('user', 'user_new') as $table) {
  530. $where = $approvedOnly ? 'user_phone = ? AND user_phone_approved = 1' : 'user_phone = ?';
  531. $select = $db->select()->from($table, 'user_id')->where($where, $phoneNumber);
  532. $res = $db->fetchOne($select, __METHOD__);
  533. if (!empty($res)) {
  534. return true;
  535. }
  536. }
  537. return false;
  538. }
  539. public static function approveUserPhone(Base_Model_User $user, $phoneNumber, $updateUserLocation = 1)
  540. {
  541. $reputation = Base_Interface_Factory::get('Reputation'); /* @var $reputation Reputation_Interface_Base */
  542. // Очистим репутацию если телефон не был подтвержден и юзер - гражданин
  543. if (!$user->isPhoneApproved() && $user->getUserClass() == Db_User::USER_CLASS_CITIZEN) {
  544. $reputation->deleteReputation($user->getId());
  545. }
  546. $oldClass = $user->getUserClass();
  547. Base_Dao_User::updateUser($user->getId(), array('user_phone' => $phoneNumber, 'user_phone_approved' => 1));
  548. $reputation->reputationEvent($user->getId(), Reputation_Dao_Base::EVENT_APPROVE_PHONE);
  549. if ($updateUserLocation) {
  550. // Разрешаем доступ с текущего местоположения
  551. $ip = Base_Service_Common::getRealIp();
  552. Antifraud_Service_Location::enableLocationForUser($user->getId(), $ip);
  553. }
  554. // Повышаем класс до гражданина
  555. Userclass_Service::updateUserClass($user, $oldClass);
  556. $db = Base_Context::getInstance()->getDbConnection();
  557. $db->insert('user_phone_approve_log', array('user_id' => $user['user_id'], 'phone' => $phoneNumber,
  558. 'inserted' => new Zend_Db_Expr('NOW()')), __METHOD__);
  559. $user->getNativeProject()->getStatisticClient()->increment($user, 'phone_approve');
  560. }
  561. /**
  562. * Конвертит массив юзеров-массивов в масси юзеров-объектов
  563. * @param array $users
  564. */
  565. public static function makeUserModelsFromArray(array $users)
  566. {
  567. $userModels = array();
  568. foreach ($users as $key => $rawUser) {
  569. if (!isset($rawUser['user_id'])) {
  570. continue;
  571. }
  572. $userModels[$key] = new Base_Model_User($rawUser);
  573. }
  574. return $userModels;
  575. }
  576. /**
  577. * Установка ключа в мемкеш о том, что сегодня телефон менялся
  578. */
  579. public static function setPhoneChangeLimit($idUser)
  580. {
  581. Base_Service_Memcache::set('user_change_phone:' . $idUser, 1, 86400); // ключ на сутки
  582. }
  583. /**
  584. * Проверка, может ли юзер менять телефон (лимит - 1 раз в день)
  585. */
  586. public static function isCanChangePhone($idUser)
  587. {
  588. return !PRODUCTION || !(Base_Service_Memcache::get('user_change_phone:' . $idUser, __METHOD__) == 1);
  589. }
  590. /**
  591. * Возвращает время предыдущего логина.
  592. * @NOTE Доступно только во время пользовательской сессии! (или 12 часов с момента логина)
  593. * @param int $userId
  594. * @return int
  595. */
  596. public static function getPreviousTimeIn($userId)
  597. {
  598. $userId = (int) $userId;
  599. $return = Base_Service_Lemon2::get(__METHOD__, self::LKEY_PREVIOUS_TIME_IN, $userId);
  600. return $return ? (int) $return : 0;
  601. }
  602. /**
  603. * Устанавливает/удаляет время предыдущего логина.
  604. * @param int $userId
  605. * @param int $prevLoginTime
  606. * @return bool
  607. */
  608. public static function setPreviousTimeIn($userId, $prevLoginTime)
  609. {
  610. $userId = (int) $userId;
  611. $prevLoginTime = (int) $prevLoginTime;
  612. if (!$prevLoginTime) {
  613. return Base_Service_Lemon2::delete(__METHOD__, self::LKEY_PREVIOUS_TIME_IN, $userId);
  614. }
  615. return Base_Service_Lemon2::set(__METHOD__, self::LKEY_PREVIOUS_TIME_IN, $userId, $prevLoginTime, 43200 /* 12 hours */);
  616. }
  617. /**
  618. * добавляет строчку в delete_history
  619. *
  620. * @param string $comment - "другая причина"
  621. */
  622. public static function addUserDeleteHistory($userId, $reason, $comment = '')
  623. {
  624. $userId = intval($userId);
  625. $reason = intval($reason);
  626. if (!$userId || !$reason) {
  627. return false;
  628. }
  629. $table = 'user_delete_history';
  630. $db = Base_Context::getInstance()->getDbConnection();
  631. //IGNORE на всякий случай
  632. $db->writeQuery($table, "INSERT IGNORE INTO `" . $table . "` SET `user_id` = '" . $userId . "', `reason` = '" . $reason . "', `date` = NOW(), `comment` = '" . mysql_escape_string($comment) . "' ", __METHOD__);
  633. }
  634. public static function getAllProjectsTitles()
  635. {
  636. return array(
  637. PROJECT_TYPE_VK => 'Петы ВК',
  638. PROJECT_TYPE_OK => 'Петы OК',
  639. PROJECT_TYPE_MAILRU => 'Петы майл',
  640. PROJECT_TYPE_FB => 'Петы FB',
  641. PROJECT_TYPE_DATINGAPP_VK => 'Дейтинг ВК',
  642. PROJECT_TYPE_DATINGAPP_MAILRU => 'Дейтинг майл',
  643. PROJECT_TYPE_DATINGAPP_FB => 'Дейтинг FB',
  644. );
  645. }
  646. public static function getAllProjectsList()
  647. {
  648. return array(
  649. 1 => PROJECT_TYPE_VK,
  650. 2 => PROJECT_TYPE_MAILRU,
  651. 4 => PROJECT_TYPE_OK,
  652. 8 => PROJECT_TYPE_FB,
  653. 16 => PROJECT_TYPE_DATINGAPP_VK,
  654. 32 => PROJECT_TYPE_DATINGAPP_MAILRU,
  655. 64 => PROJECT_TYPE_DATINGAPP_FB,
  656. );
  657. }
  658. public static function getUsingProjectsList($value)
  659. {
  660. $res = array();
  661. $project = self::getAllProjectsList();
  662. foreach ($project as $bitmask => $projectType) {
  663. if ($value & $bitmask) {
  664. $res[] = $projectType;
  665. }
  666. }
  667. return $res;
  668. }
  669. public static function addProjectsToValue($value, $projects)
  670. {
  671. $all = self::getAllProjectsList();
  672. $all = array_flip($all);
  673. foreach ($projects as $projectType) {
  674. $bitmask = isset($all[$projectType]) ? $all[$projectType] : 0;
  675. $value = $value | $bitmask;
  676. }
  677. return $value;
  678. }
  679. public static function deleteProjectsFromValue($value, $projects)
  680. {
  681. $all = self::getAllProjectsList();
  682. $all = array_flip($all);
  683. foreach ($projects as $projectType) {
  684. $bitmask = isset($all[$projectType]) ? $all[$projectType] : 0;
  685. $value = $value & (~$bitmask);
  686. }
  687. return $value;
  688. }
  689. public static function getExtIdFieldNameByProjectType($projectType)
  690. {
  691. $map = array(
  692. PROJECT_TYPE_VK => 'user_vk_id',
  693. PROJECT_TYPE_DATINGAPP_VK => 'user_vk_id',
  694. PROJECT_TYPE_MAILRU => 'user_mailru_id',
  695. PROJECT_TYPE_DATINGAPP_MAILRU => 'user_mailru_id',
  696. PROJECT_TYPE_OK => 'user_ok_id',
  697. PROJECT_TYPE_FB => 'user_fb_id',
  698. PROJECT_TYPE_DATINGAPP_FB => 'user_fb_id'
  699. );
  700. return isset($map[$projectType]) ? $map[$projectType] : false;
  701. }
  702. public static function getExtIdFieldNameByLoginType($loginType)
  703. {
  704. $map = array(
  705. Base_Service_Login_Factory::TYPE_VKONTAKTE => 'user_vk_id',
  706. Base_Service_Login_Factory::TYPE_MAILRU => 'user_mailru_id',
  707. Base_Service_Login_Factory::TYPE_ODNOKLASSNIKI => 'user_ok_id',
  708. Base_Service_Login_Factory::TYPE_FACEBOOK => 'user_fb_id',
  709. );
  710. return isset($map[$loginType]) ? $map[$loginType] : false;
  711. }
  712. /**
  713. * Вернуть настройки уведомлений от приложений
  714. *
  715. * @param int $userId
  716. * @return array
  717. */
  718. public function getAppNotifySettings($userId)
  719. {
  720. $bubbleNotifyMask = Base_Interface_Store::EXTERNAL_MASK_BUBBLE_NOTIFY;
  721. $user = Base_Dao_User::getUserById($userId);
  722. if ($user === null) {
  723. return array();
  724. }
  725. $skipApps = array(
  726. 'Friends', 'Usercontact', 'Favorites', 'Walls', 'communityapp', 'fotoindex', 'supportNotifier'
  727. );
  728. $apps = array();
  729. if (Base_Service_Pacman::isEnabled()) {
  730. $skipApps = array_flip(Base_Interface_Store::getUid($skipApps));
  731. $notifies = Base_Service_Pacman::prepareNotifies(Base_Service_Pacman::getNotifies($userId));
  732. $iApp = new App_Interface_Base();
  733. foreach ($notifies as $appUid => $appModel) {
  734. if (isset($skipApps[$appUid])
  735. || (isset($appModel[Base_Interface_Store::STORE_TESTING_LEVEL]) && $appModel[Base_Interface_Store::STORE_TESTING_LEVEL] != Base_Interface_Store::TESTING_LEVEL_ALL)
  736. ) {
  737. continue;
  738. }
  739. $appName = Utf::strtolower($appModel['app_name']);
  740. // НЕ устранновленные не надо
  741. $access = $iApp->getAccess($appName, $userId);
  742. if (empty($access) || (isset($access['installed']) && !$access['installed'])) {
  743. continue;
  744. }
  745. // Продолжаем набирать
  746. $apps[$appName] = array(
  747. 'name' => $appModel['description'],
  748. 'notify' => true,
  749. 'inPacman'=> true, // Индикатор того, что приложение есть в пакмане
  750. 'bubbleNotify' => !((bool) ((int) $access[0] & $bubbleNotifyMask)),
  751. );
  752. if (isset($appModel[Base_Interface_Store::STORE_ICO_CLASS])) {
  753. $apps[$appName]['ico'] = $appModel[Base_Interface_Store::STORE_ICO_CLASS];
  754. }
  755. if(isset($appModel['mailing_enabled'])) { // вещает ли приложение по мылу?
  756. $apps[$appName]['mailing_enabled'] = $appModel['mailing_enabled'];
  757. }
  758. }
  759. unset($iApp);
  760. } else {
  761. // Еще получим приложения, нотификации которых уже есть
  762. $appNotify = new App_Interface_News();
  763. $apps = Base_Util_Array::extract($appNotify->getAppNewsListForUser($userId, false), 'notify_uniq');
  764. $apps = empty($apps) ? array() : $apps;
  765. $appNotify = Base_Util_Array::extract(Base_Service_Notify::getNotifyByType($userId, Base_Service_Notify::NOTIFY_APP_USERNOTIFY), 'notify_uniq');
  766. $apps = empty($appNotify) ? $apps : array_merge($apps, $appNotify);
  767. $appNotify = Base_Util_Array::extract(Base_Service_Notify::getNotifyByType($userId, Base_Service_Notify::NOTIFY_APPINVITE), 'notify_uniq');
  768. $apps = empty($appNotify) ? $apps : array_merge($apps, $appNotify);
  769. $appNotify = array();
  770. foreach(Base_Util_Array::extract(Usercontact_Service_Base::getGameEventsNotifications($user), 'app') as $appItem) {
  771. if (isset($appItem['app_id'])) {
  772. $appNotify[] = $appItem['app_id'];
  773. }
  774. }
  775. foreach(Base_Util_Array::extract(Usercontact_Service_Base::getGameRequestsNotifications($user), 'app') as $appItem) {
  776. if (isset($appItem['app_id'])) {
  777. $appNotify[] = $appItem['app_id'];
  778. }
  779. }
  780. $appIds = empty($appNotify) ? $apps : array_merge($apps, $appNotify);
  781. $appIds = Base_Interface_Store::getAppsByUids(Base_Util_Array::intvalArray(array_unique($appIds)));
  782. $apps = array();
  783. foreach($appIds as $app) {
  784. $apps[$app['app_name']] = array(
  785. 'name' => $app['description'],
  786. 'notify' => true,
  787. 'inPacman'=> true, // Индикатор того, что приложение есть в пакмане
  788. );
  789. if(isset($app['mailing_enabled'])) { // вещает ли приложение по мылу?
  790. $apps[$app['app_name']]['mailing_enabled'] = $app['mailing_enabled'];
  791. }
  792. }
  793. }
  794. /* @var $appInterface App_Interface_Base */
  795. $appInterface = Base_Interface_Factory::get('App');
  796. $notifyMask = Base_Interface_Store::EXTERNAL_MASK_USERNOTIFY;
  797. $userApps = $appInterface->getUserApps($userId, true, true);
  798. $access = $appInterface->getAccessManyApps($userId, array_keys($userApps), false);
  799. foreach ($userApps as $appId => $app) {
  800. if (!isset($app['app_name']) || isset($skipApps[$appId])) {
  801. continue;
  802. }
  803. $appName = Utf::strtolower($app['app_name']);
  804. // Если есть имя приложения и уровень доступа для всех, или нету поля testing_level (для уже инсталированных приложений)
  805. if (!isset($apps[$appName]) && (!isset($app['testing_level']) || $app['testing_level'] == Base_Interface_Store::TESTING_LEVEL_ALL)) {
  806. $apps[$appName] = array(
  807. 'name' => $app['description'],
  808. 'inPacman'=> false, // Индикатор того, что приложение есть в пакмане
  809. );
  810. if (isset($access[$appId][0])) {
  811. $apps[$appName] += array(
  812. 'notify' => ((int) $access[$appId][0] & $notifyMask) > 0,
  813. 'bubbleNotify' => !((bool) ((int) $access[$appId][0] & $bubbleNotifyMask)),
  814. );
  815. } else {
  816. $apps[$appName] += array(
  817. 'notify' => true,
  818. 'bubbleNotify' => true,
  819. );
  820. }
  821. if (Base_Service_Pacman::isEnabled() && isset($app[Base_Interface_Store::STORE_ICO_CLASS])) {
  822. $apps[$appName]['ico'] = $app[Base_Interface_Store::STORE_ICO_CLASS];
  823. }
  824. if(isset($app['mailing_enabled'])) { // вещает ли приложение по мылу?
  825. $apps[$appName]['mailing_enabled'] = $app['mailing_enabled'];
  826. }
  827. }
  828. }
  829. return $apps;
  830. }
  831. /**
  832. * Установить настройки уведомлений приложений
  833. *
  834. * @param int $userId
  835. * @param string $appName
  836. * @param bool $access
  837. * @return bool
  838. */
  839. public static function setAppNotifySettings($userId, $appName, $open = true, $deleteAllNotifys = true)
  840. {
  841. // New pacman unnotify
  842. if (Base_Service_Pacman::isEnabled()) {
  843. /*if (!$open && $deleteAllNotifys) {
  844. Base_Service_Pacman::removeNotifies($userId, $appName);
  845. }*/
  846. $result = Base_Service_Pacman::userNotifyStatus($userId, $appName, $open);
  847. // Count statistic
  848. $statsFlag = $open ? 'on' : 'off';
  849. $user = Base_Dao_User::getUserById($userId);
  850. $client = new Base_Service_Counter_Main();
  851. $client->increment($user, 'pacman_notify_settings_' . $appName . '_' . $statsFlag);
  852. $client->increment($user, 'pacman_notify_settings_total_apps_' . $statsFlag);
  853. return $result;
  854. }
  855. $notifyMask = Base_Interface_Store::EXTERNAL_MASK_USERNOTIFY;
  856. /** @var $appInterface App_Interface_Base */
  857. $appInterface = Base_Interface_Factory::get('App');
  858. $access = $appInterface->getAccess($appName, $userId);
  859. $appNewsInterface = new App_Interface_News();
  860. $appUid = Base_Interface_Store::getAppNumericId($appName); // Получаем айди приложения
  861. $newAcc = null;
  862. if ($open) {
  863. if (!empty($access[0])) {
  864. $newAcc = $access[0] | $notifyMask;
  865. } else {
  866. $newAcc = Base_Interface_Store::EXTERNAL_MASK_DEFAULT;
  867. foreach (Base_Interface_Store::$appMasks as $mask) {
  868. if ($mask == Base_Interface_Store::EXTERNAL_MASK_SILENT_BILLING && !Base_Interface_Store::isSilentBillingAllowed($appName)) {
  869. continue;
  870. }
  871. $newAcc |= $mask;
  872. }
  873. }
  874. // Подписываемся на новости
  875. $appNewsInterface->markNotifyNewsApp($userId, $appUid);
  876. } else {
  877. $newAcc = Base_Interface_Store::EXTERNAL_MASK_DEFAULT;
  878. foreach (Base_Interface_Store::$appMasks as $mask) {
  879. if ((empty($access[0]) and $mask != $notifyMask) or (isset($access[0]) and ($access[0] & $mask) and $mask != $notifyMask)) {
  880. $newAcc |= $mask;
  881. }
  882. }
  883. // Отписываем от новостей
  884. $appNewsInterface->markUnnotifyNewsApp($userId, $appUid);
  885. // Обнуляем счетчики для меню знакомств
  886. Base_Service_Notify::subNotify($userId, Base_Service_Notify::NOTIFY_APP_COUNTER, $appUid);
  887. if ($deleteAllNotifys) { // Удаляем все нотификации от приложений
  888. foreach (Base_Service_Notify::getNotifyByType($userId, Base_Service_Notify::NOTIFY_GAME_EVENTS) as $notify) { // Получаем все нотификации
  889. if ($notify['udata'][Base_Service_Notify::UDATA_REF_ID] == $appName) {
  890. Base_Service_Notify::subNotify($userId, Base_Service_Notify::NOTIFY_GAME_EVENTS, $notify['notify_uniq']);
  891. }
  892. }
  893. foreach (Base_Service_Notify::getNotifyByType($userId, Base_Service_Notify::NOTIFY_APP_USERNOTIFY) as $notify) { // нотификации от приложений с текстом
  894. if ($notify['notify_uniq'] == $appUid) {
  895. Base_Service_Notify::remove($userId, Base_Service_Notify::NOTIFY_APP_USERNOTIFY, $appUid);
  896. }
  897. }
  898. foreach (Base_Service_Notify::getNotifyByType($userId, Base_Service_Notify::NOTIFY_APPINVITE) as $notify) { // приглашения в приложения
  899. if ($notify['notify_uniq'] == $appUid) {
  900. Base_Service_Notify::subNotify($userId, Base_Service_Notify::NOTIFY_APPINVITE, $appUid);
  901. // удалим вип инвайт
  902. if (App_Service_Vip::isVipApp(Base_Interface_Store::getAppByUid($appUid))) {
  903. App_Service_Vip::deleteInvite($userId, $appUid);
  904. }
  905. }
  906. }
  907. // Получаем все реквесты
  908. foreach (Base_Service_Notify::getNotifyByType($userId, Base_Service_Notify::NOTIFY_GAME_REQUESTS) as $notify) {
  909. // Удаляем реквесты для данного приложения
  910. if ($notify['udata'][Base_Service_Notify::UDATA_REF_ID] == $appName) {
  911. Base_Service_Notify::subNotify($userId, Base_Service_Notify::NOTIFY_GAME_REQUESTS, $notify['notify_uniq']);
  912. }
  913. }
  914. }
  915. }
  916. $user = Base_Dao_User::getUserById($userId);
  917. $client = new Base_Service_Counter_Main();
  918. $client->increment($user, 'pacman_notify_settings_'.$appName.'_'.($open?'on':'off'));
  919. $client->increment($user, 'pacman_notify_settings_total_apps_'.($open?'on':'off'));
  920. return $appInterface->setAccess($appName, $userId, $newAcc, false);
  921. }
  922. /**
  923. * Возвращает массив айдишников юзеров по переданному массиву тел. номеров.
  924. * Используется для поиска друзей на мобильном клиенте фотостраны.
  925. *
  926. * @static
  927. * @param $phones массив номеров телефонов
  928. * @return array айдишники юзеров или пустой массив
  929. */
  930. public static function getUsersByPhones($phones)
  931. {
  932. if(empty($phones)) {
  933. return array();
  934. }
  935. // проверим корректность номеров
  936. $validPhones = array();
  937. foreach ($phones as $phone) {
  938. if (Utf::preg_match('/^[0-9]{7,15}$/', $phone)) {
  939. $validPhones[] = $phone;
  940. }
  941. }
  942. $users = array();
  943. $db = Base_Context::getInstance()->getDbConnection();
  944. foreach (array('user', 'user_new') as $table) {
  945. if(empty($validPhones)) {
  946. break;
  947. }
  948. $sql = $db->select()->from($table, array('user_phone', 'user_id'));
  949. $sql->where('user_phone IN (?)', $validPhones);
  950. if ($records = $db->fetchAll($sql, __METHOD__)) {
  951. $users = array_merge($users, $records);
  952. foreach ($records as $record) {
  953. unset($validPhones[$record['user_phone']]);
  954. }
  955. }
  956. }
  957. return $users;
  958. }
  959. const FAILED_LOGINS_COUNT = 'failedLoginsCount:';
  960. const FAILED_LOGINS_MAX_COUNT = 3;
  961. public static function resetFailedLoginsCount($email)
  962. {
  963. Base_Service_Memcache::delete(self::FAILED_LOGINS_COUNT.crc32($email));
  964. }
  965. public static function getFailedLoginsCount($email)
  966. {
  967. return (int)Base_Service_Memcache::get(self::FAILED_LOGINS_COUNT.crc32($email), __METHOD__);
  968. }
  969. public static function incrFailedLoginsCount($email)
  970. {
  971. $count = self::getFailedLoginsCount($email);
  972. if (!$count) {
  973. Base_Service_Memcache::set(self::FAILED_LOGINS_COUNT.crc32($email), 1, 60*15);
  974. } else {
  975. Base_Service_Memcache::increment(self::FAILED_LOGINS_COUNT.crc32($email));
  976. }
  977. return ++$count;
  978. }
  979. private static function logGetRequest(array $request)
  980. {
  981. $reqs = array();
  982. foreach ($request as $req) {
  983. if (is_array($req) && isset($req['user_id'])) {
  984. $req = $req['user_id']; // WTF???
  985. }
  986. if ($req && !isset($reqs[$req])){
  987. $reqs[$req] = true;
  988. }
  989. }
  990. $reqs = array_keys($reqs);
  991. sort($reqs);
  992. reset($reqs);
  993. $request = $reqs;
  994. $hash = md5(implode("//", $request));
  995. if (isset(self::$requestHashes[$hash])) {return;}
  996. self::$requestHashes[$hash] = 1;
  997. self::$requestLog[self::$requestId] = $request;
  998. foreach ($request as $userId) {
  999. if (!$userId) {
  1000. continue;
  1001. }
  1002. if (!isset(self::$userToRequest[$userId])) {
  1003. self::$userToRequest[$userId] = array();
  1004. }
  1005. self::$userToRequest[$userId][] = self::$requestId;
  1006. }
  1007. self::$requestLoaded[self::$requestId] = false;
  1008. self::$requestId++;
  1009. }
  1010. private static function preloadAllUsersWithUser($userId) {
  1011. $usersToRequest = array();
  1012. if (is_array($userId)) {
  1013. foreach ($userId as $id) {
  1014. foreach (self::$userToRequest[$id] as $req) {
  1015. if (!self::$requestLoaded[self::$requestId]) {
  1016. $usersToRequest += self::$requestLog[$req];
  1017. self::$requestLoaded[self::$requestId] = true;
  1018. }
  1019. }
  1020. }
  1021. } else {
  1022. foreach (self::$userToRequest[$userId] as $req) {
  1023. if (!self::$requestLoaded[$req]) {
  1024. $usersToRequest += self::$requestLog[$req];
  1025. self::$requestLoaded[self::$requestId] = true;
  1026. }
  1027. }
  1028. }
  1029. Base_Dao_User::getFullUsersByIds($usersToRequest);
  1030. }
  1031. }