BxDolMProfiles.php 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506
  1. <?php defined('BX_DOL') or die('hack attempt');
  2. /**
  3. * Copyright (c) UNA, Inc - https://una.io
  4. * MIT License - https://opensource.org/licenses/MIT
  5. *
  6. * @defgroup DolphinMigration Dolphin Migration
  7. * @ingroup UnaModules
  8. *
  9. * @{
  10. */
  11. bx_import('BxDolProfile');
  12. bx_import('BxDolTranscoderImage');
  13. bx_import('BxDolStorage');
  14. require_once('BxDolMData.php');
  15. class BxDolMProfiles extends BxDolMData
  16. {
  17. private $_sProfileCoverName = '';
  18. private $_sProfileInfoName = '';
  19. private $_aFriendsConnections = array();
  20. private $_aAccounts = array();
  21. private $_aProfiles = array();
  22. public function __construct(&$oMigrationModule, &$mDb)
  23. {
  24. parent::__construct($oMigrationModule, $mDb);
  25. $this -> _sModuleName = 'profiles';
  26. $this -> _sTableWithTransKey = 'sys_accounts';
  27. }
  28. public function getTotalRecords()
  29. {
  30. return (int)$this -> _mDb -> getOne("SELECT COUNT(*) FROM `" . $this -> _oConfig -> _aMigrationModules[$this -> _sModuleName]['table_name'] . "`");
  31. }
  32. public function runMigration()
  33. {
  34. $this -> _sProfileCoverName = $this -> _mDb -> getParam('bx_photos_profile_cover_album_name');
  35. $this -> _sProfileInfoName = $this -> _mDb -> getParam('sys_member_info_name');
  36. if (!$this -> getTotalRecords())
  37. {
  38. $this -> setResultStatus(_t('_bx_dolphin_migration_no_data_to_transfer'));
  39. return BX_MIG_SUCCESSFUL;
  40. }
  41. $this -> setResultStatus(_t('_bx_dolphin_migration_started_migration_profiles'));
  42. $sError = $this -> profilesMigration();
  43. if($sError) {
  44. $this -> setResultStatus($sError);
  45. return BX_MIG_FAILED;
  46. }
  47. $this -> setResultStatus(_t('_bx_dolphin_migration_started_migration_profiles_finished', $this -> _iTransferred));
  48. return BX_MIG_SUCCESSFUL;
  49. }
  50. /**
  51. * Check if account with the same nickname or email already exists
  52. * @param string $sEmail user email
  53. * @return integer account id
  54. */
  55. private function isAccountExisted($sEmail){
  56. if (empty($this -> _aAccounts))
  57. $this -> _aAccounts = $this->_oDb->getAllWithKey("SELECT LOWER(`email`) as `email`, `id` FROM `sys_accounts`", 'email');
  58. return isset($this -> _aAccounts[strtolower($sEmail)]) ? $this -> _aAccounts[strtolower($sEmail)]['id'] : false;
  59. }
  60. /**
  61. * Check if profile with the same nickname already exists
  62. * @param integer $iAccountId account id
  63. * @param string $sFullName name of the user
  64. * @return array person and profile id
  65. */
  66. private function isPersonExisted($iAccountId, $sFullName){
  67. if (empty($this -> _aProfiles))
  68. $this -> _aProfiles = $this -> _oDb -> getAllWithKey("SELECT `s`.`account_id`, `p`.`id`, `p`.`fullname`, `s`.`content_id` as `p_id`
  69. FROM `bx_persons_data` as `p`
  70. LEFT JOIN `sys_profiles` as `s` ON `s`.`id` = `p`.`author`
  71. WHERE `s`.`type` = 'bx_persons'", 'account_id');
  72. return isset($this -> _aProfiles[$iAccountId]) && strcasecmp($this -> _aProfiles[$iAccountId]['fullname'], $sFullName) === 0 ? $this -> _aProfiles[$iAccountId] : false;
  73. }
  74. function profilesMigration()
  75. {
  76. $this -> createMIdField();
  77. // get IDs of the latest transferred profile for UNA Accounts and Dolphin Profiles
  78. $iProfileID = $this -> getLastMIDField();
  79. $sStart = '';
  80. if ($iProfileID)
  81. $sStart = "WHERE `ID` > {$iProfileID}";
  82. else
  83. $this -> addPreValues('Sex', true, 2); // transfer all sex values more then 2 value
  84. $aResult = $this -> _mDb -> getAll("SELECT * FROM `" . $this -> _oConfig -> _aMigrationModules[$this -> _sModuleName]['table_name'] . "` {$sStart} ORDER BY `ID` ASC");
  85. $aSex = $this -> getPreValuesBy('Sex', 'Value', 'Order');
  86. foreach($aResult as $iKey => $aValue)
  87. {
  88. if($aValue['Email'])
  89. {
  90. $sAction = "INSERT INTO";
  91. $sWhere = "";
  92. $bAccountExists = false;
  93. $iAccountId = $this -> isAccountExisted($aValue['Email']);
  94. if ($iAccountId)
  95. {
  96. if ($this -> _oConfig -> _bIsOverwrite) {
  97. $sAction = "UPDATE";
  98. $sWhere = "WHERE `id` = '{$iAccountId}'";
  99. $bAccountExists = true;
  100. }
  101. else
  102. continue;
  103. }
  104. $sQuery = $this -> _oDb -> prepare(
  105. "
  106. {$sAction}
  107. `sys_accounts`
  108. SET
  109. `name` = ?,
  110. `email` = ?,
  111. `password` = ?,
  112. `salt` = ?,
  113. `role` = ?,
  114. `lang_id` = ?,
  115. `added` = ?,
  116. `changed` = ?,
  117. `logged` = ?,
  118. `email_confirmed` = ?,
  119. `receive_updates` = ?,
  120. `receive_news` = ?
  121. {$sWhere}
  122. ",
  123. $aValue['NickName'],
  124. $aValue['Email'],
  125. $aValue['Password'],
  126. $aValue['Salt'],
  127. $aValue['Role'],
  128. $aValue['LangID'],
  129. strtotime($aValue['DateReg']),
  130. strtotime($aValue['DateLastEdit']),
  131. strtotime($aValue['DateLastLogin']),
  132. isset($aValue['Status']) && $aValue['Status'] != 'Unconfirmed' ? 1 : 0,
  133. $aValue['EmailNotify'],
  134. $aValue['EmailNotify']
  135. );
  136. $this -> _oDb -> query($sQuery);
  137. $iAccountId = $iAccountId ? $iAccountId : $this -> _oDb -> lastId();
  138. if (!$iAccountId)
  139. continue;
  140. $iSysProfileId = 0;
  141. if (!$bAccountExists) {
  142. $this->_oDb->query("INSERT INTO `sys_profiles` SET `account_id` = {$iAccountId}, `content_id` = {$iAccountId}, `type` = 'system', `status` = 'active'");
  143. $iSysProfileId = $this->_oDb->lastId();
  144. }
  145. $this -> setMID($iAccountId, $aValue['ID']);
  146. if ($this -> _oConfig -> _bUseNickName)
  147. $sFullName = $aValue['NickName'];
  148. else
  149. {
  150. $sFullName = isset($aValue['FullName']) ? $aValue['FullName'] : "{$aValue['FirstName']} {$aValue['LastName']}";
  151. $sFullName = trim($sFullName) ? $sFullName : $aValue['NickName'];
  152. }
  153. $sAction = "INSERT INTO";
  154. $sWhere = '';
  155. $iProfile = $iProfID = 0;
  156. if ($bAccountExists && ($aPersonInfo = $this -> isPersonExisted($iAccountId, $sFullName))) {
  157. $sAction = "UPDATE";
  158. $sWhere = "WHERE `id` = '{$iProfID}'";
  159. $iProfID = $aPersonInfo['id'];
  160. $iProfile = $aPersonInfo['p_id'];
  161. }
  162. $iDateReg = strtotime($aValue['DateReg']);
  163. $iDateEdit = strtotime($aValue['DateLastEdit']);
  164. $sQuery = $this -> _oDb -> prepare(
  165. "{$sAction}
  166. `bx_persons_data`
  167. SET
  168. `author` = ?,
  169. `added` = ?,
  170. `changed` = ?,
  171. `picture` = 0,
  172. `cover` = 0,
  173. `fullname` = ?,
  174. `birthday` = ?,
  175. `gender` = ?,
  176. `allow_view_to` = ?,
  177. `featured` = ?,
  178. `views` = ?,
  179. `description` = ?
  180. {$sWhere}
  181. ",
  182. $iSysProfileId,
  183. $iDateReg ? $iDateReg : 0,
  184. $iDateEdit ? $iDateEdit : 0,
  185. $sFullName,
  186. isset($aValue['DateOfBirth']) ? $aValue['DateOfBirth'] : 'NULL',
  187. isset($aValue['Sex']) && $aValue['Sex'] ? $aSex[$aValue['Sex']] : 1,
  188. $this -> getPrivacy($aValue['ID'], isset($aValue['allow_view_to']) ? $aValue['allow_view_to'] : 0, '', '', $aValue['PrivacyDefaultGroup']),
  189. isset($aValue['Featured']) ? (int)$aValue['Featured'] : 0,
  190. isset($aValue['Views']) ? (int)$aValue['Views'] : 0,
  191. isset($aValue['DescriptionMe']) && $aValue['DescriptionMe'] ? nl2br(htmlspecialchars_adv($aValue['DescriptionMe'])) : ''
  192. );
  193. $this -> _oDb -> query($sQuery);
  194. $iContentId = $iProfID ? $iProfID : $this -> _oDb -> lastId();
  195. if (!$iProfID) {
  196. $this->_oDb->query("UPDATE `sys_profiles` SET `content_id` = {$iAccountId} WHERE `account_id` = {$iAccountId} AND `type` = 'system'");
  197. $this->_oDb->query("INSERT INTO `sys_profiles` SET `account_id` = {$iAccountId}, `type` = 'bx_persons', `content_id` = {$iContentId}, `status` = 'active'");
  198. $iProfile = $this->_oDb->lastId();
  199. if ($iProfile) {
  200. BxDolAccountQuery::getInstance()->updateCurrentProfile($iAccountId, $iProfile);
  201. if ($aValue['Role'] == 3)
  202. BxDolAcl::getInstance()->setMembership($iProfile, MEMBERSHIP_ID_ADMINISTRATOR);
  203. }
  204. $sQuery = $this->_oDb->prepare("UPDATE `bx_persons_data` SET `author` = ? WHERE `id` = ?", $iProfile, $iContentId);
  205. $this->_oDb->query($sQuery);
  206. if (isset($aValue['Country']) || isset($aValue['City']) || isset($aValue['zip']) || isset($aValue['State'])) {
  207. $this->_oDb->query("INSERT INTO `bx_persons_meta_locations`
  208. SET `object_id`=:object, `country`=:country, `city`=:city, zip = :zip, `state`=:state",
  209. array(
  210. 'object' => $iContentId,
  211. 'country' => isset($aValue['Country']) ? $aValue['Country'] : '',
  212. 'city' => isset($aValue['City']) ? $aValue['City'] : '',
  213. 'zip' => isset($aValue['zip']) ? $aValue['zip'] : '',
  214. 'state' => isset($aValue['State']) ? $aValue['State'] : '',
  215. ));
  216. }
  217. }
  218. $this->exportCover($iProfile, $iContentId, $aValue);
  219. $this->exportAvatar($iProfile, $iContentId, $aValue);
  220. $this -> _iTransferred++;
  221. }
  222. }
  223. if ($this->_iTransferred)
  224. $this->exportFriends();
  225. }
  226. /**
  227. * Get Avatar's image path
  228. * @param array $aProfileInfo profile information
  229. * @return string
  230. */
  231. private function getProfileImage($aProfileInfo)
  232. {
  233. $sAvatarType = $this -> _mDb -> getParam('sys_member_info_thumb');
  234. $sImagePath = $this -> _oDb -> getExtraParam('root') . 'modules' . DIRECTORY_SEPARATOR . 'boonex' . DIRECTORY_SEPARATOR;
  235. if ($sAvatarType == 'bx_photos_thumb')
  236. {
  237. $sAlbumName = $this -> _mDb -> getParam('bx_photos_profile_album_name');
  238. $aReplacement = array(
  239. '{nickname}' => $aProfileInfo['NickName'],
  240. '{fullname}' => $aProfileInfo['NickName']
  241. );
  242. $sAlbumName = str_replace(array_keys($aReplacement), array_values($aReplacement), $sAlbumName);
  243. $sAlbumName = uriFilter($sAlbumName);
  244. $aInfo = $this -> _mDb -> getRow("SELECT `bx_photos_main`.* FROM `bx_photos_main`
  245. LEFT JOIN `sys_albums_objects` ON `sys_albums_objects`.`id_object`=`bx_photos_main`.`ID`
  246. LEFT JOIN `sys_albums` ON `sys_albums`.`ID`=`sys_albums_objects`.`id_album`
  247. WHERE `bx_photos_main`.`Status` ='approved'
  248. AND `bx_photos_main`.`Owner` =:id
  249. AND `sys_albums`.`Status` ='active'
  250. AND `sys_albums`.`Type` ='bx_photos'
  251. AND `sys_albums`.`Uri` = :uri
  252. ORDER BY `obj_order` ASC, `id_object` DESC
  253. LIMIT 1", array('uri' => $sAlbumName, 'id' => $aProfileInfo['ID']));
  254. if (!empty($aInfo) && isset($aInfo['ID']))
  255. $sImagePath = $this -> _sImagePhotoFiles ."{$aInfo['ID']}.{$aInfo['Ext']}";
  256. }
  257. else
  258. {
  259. $iId = $this -> _mDb -> getOne("SELECT `id` FROM `bx_avatar_images` WHERE `author_id` = :id LIMIT 1", array('id' => $aProfileInfo['ID']));
  260. if ($iId)
  261. $sImagePath = $sImagePath . "avatar" . DIRECTORY_SEPARATOR . "data" . DIRECTORY_SEPARATOR . "images" . DIRECTORY_SEPARATOR ."{$iId}b.jpg";
  262. }
  263. if (file_exists($sImagePath))
  264. return $sImagePath;
  265. return false;
  266. }
  267. private function exportCover($iProfileId, $iContentId, $aProfileInfo){
  268. if (!$this -> _sProfileCoverName)
  269. return FALSE;
  270. $sUserName = $aProfileInfo['NickName'];
  271. switch ($this -> _sProfileInfoName) {
  272. case 'sys_username':
  273. $sUserName = $aProfileInfo['NickName'];
  274. break;
  275. case 'sys_full_name':
  276. $sUserName = htmlspecialchars_adv($aProfileInfo['FullName'] ? $aProfileInfo['FullName'] : $aProfileInfo['NickName']);
  277. break;
  278. case 'sys_first_name':
  279. $sUserName = $aProfileInfo['FirstName'] ? $aProfileInfo['FirstName'] : $aProfileInfo['NickName'];
  280. break;
  281. case 'sys_first_name_last_name':
  282. $sUserName = $aProfileInfo['FirstName'] || $aProfileInfo['LastName'] ? $aProfileInfo['FirstName'] . ' ' . $aProfileInfo['LastName'] : $aProfileInfo['NickName'];
  283. break;
  284. case 'sys_last_name_firs_name':
  285. $sUserName = $aProfileInfo['FirstName'] || $aProfileInfo['LastName'] ? $aProfileInfo['LastName'] . ' ' . $aProfileInfo['FirstName'] : $aProfileInfo['NickName'];
  286. }
  287. $aReplacement = array(
  288. '{nickname}' => $sUserName,
  289. '{fullname}' => $aProfileInfo['NickName']
  290. );
  291. $sAlbumName = uriFilter(str_replace(array_keys($aReplacement), array_values($aReplacement), $this -> _sProfileCoverName));
  292. $aCoverInfo = $this -> _mDb -> getRow("SELECT `bx_photos_main`.* FROM `bx_photos_main`
  293. LEFT JOIN `sys_albums_objects` ON `sys_albums_objects`.`id_object`=`bx_photos_main`.`ID`
  294. LEFT JOIN `sys_albums` ON `sys_albums`.`ID`=`sys_albums_objects`.`id_album` AND `sys_albums`.`LastObjId` = `bx_photos_main`.`ID`
  295. WHERE `bx_photos_main`.`Owner` = :owner AND `sys_albums`.`Status` ='active' AND `sys_albums`.`Type` ='bx_photos' AND `sys_albums`.`Uri` =:album", array('owner' => $aProfileInfo['ID'],'album' => $sAlbumName));
  296. if (!empty($aCoverInfo))
  297. {
  298. $sImagePath = $this->_sImagePhotoFiles . "{$aCoverInfo['ID']}.{$aCoverInfo['Ext']}";
  299. if (file_exists($sImagePath)) {
  300. $oStorage = BxDolStorage::getObjectInstance('bx_persons_pictures');
  301. $iId = $oStorage->storeFileFromPath($sImagePath, false, $iProfileId, $iContentId);
  302. if ($iId) {
  303. $sQuery = $this->_oDb->prepare("UPDATE `bx_persons_data` SET `Cover` = ? WHERE `id` = ?", $iId, $iContentId);
  304. $this->_oDb->query($sQuery);
  305. }
  306. }
  307. }
  308. return false;
  309. }
  310. private function exportFriends()
  311. {
  312. $sQuery = $this -> _mDb -> prepare("SELECT * FROM `sys_friend_list` WHERE `ID` <> 0 AND `Profile` <> 0");
  313. $aFriends = $this -> _mDb -> getAll($sQuery);
  314. foreach($aFriends as $iKey => $aValue)
  315. {
  316. $iUserId = $this -> getProfileId($aValue['ID']);
  317. $iFriendId = $this -> getProfileId($aValue['Profile']);
  318. if($iUserId && $iFriendId && !$this -> isFriendExists($iUserId, $iFriendId))
  319. {
  320. $sQuery = $this -> _oDb -> prepare("
  321. INSERT IGNORE INTO
  322. `sys_profiles_conn_friends`
  323. SET
  324. `initiator` = ?,
  325. `content` = ?,
  326. `mutual` = ?,
  327. `added` = UNIX_TIMESTAMP()
  328. ", $iUserId, $iFriendId, $aValue['Check']);
  329. $iResult = $this -> _oDb -> query($sQuery);
  330. // make initiator to follow content
  331. $this->_oDb->query("
  332. INSERT IGNORE INTO
  333. `sys_profiles_conn_subscriptions`
  334. SET
  335. `initiator` =:initiator,
  336. `content` =:content ,
  337. `added` = UNIX_TIMESTAMP()
  338. ", array('initiator' => $iUserId, 'content' => $iFriendId));
  339. $iResult = $this -> _oDb -> query($sQuery);
  340. if ($iResult && (int)$aValue['Check']){
  341. $sQuery = $this->_oDb->prepare("
  342. INSERT IGNORE INTO
  343. `sys_profiles_conn_friends`
  344. SET
  345. `initiator` = ?,
  346. `content` = ?,
  347. `mutual` = ?,
  348. `added` = UNIX_TIMESTAMP()
  349. ", $iFriendId, $iUserId, 1);
  350. $this->_oDb->query($sQuery);
  351. // make content to follow initiator
  352. $this->_oDb->query("
  353. INSERT IGNORE INTO
  354. `sys_profiles_conn_subscriptions`
  355. SET
  356. `initiator` =:initiator,
  357. `content` =:content ,
  358. `added` = UNIX_TIMESTAMP()
  359. ", array('initiator' => $iFriendId, 'content' => $iUserId));
  360. }
  361. }
  362. }
  363. }
  364. private function exportAvatar($iProfileId, $iContentId, $aProfileInfo)
  365. {
  366. $sAvatarPath = $this -> getProfileImage($aProfileInfo);
  367. if($sAvatarPath)
  368. {
  369. $oStorage = BxDolStorage::getObjectInstance('bx_persons_pictures');
  370. $iId = $oStorage->storeFileFromPath($sAvatarPath, false, $iProfileId, $iContentId);
  371. if ($iId)
  372. {
  373. $sQuery = $this -> _oDb -> prepare("UPDATE `bx_persons_data` SET `Picture` = ? WHERE `id` = ?", $iId, $iContentId);
  374. $this -> _oDb -> query($sQuery);
  375. }
  376. }
  377. }
  378. private function isFriendExists($iProfileId, $iFriendId)
  379. {
  380. if (empty($this -> _aFriendsConnections))
  381. $this->_aFriendsConnections = $this->_oDb->getAll("SELECT `initiator`, `content` FROM `sys_profiles_conn_friends`");
  382. if (!empty($this -> _aFriendsConnections))
  383. foreach($this -> _aFriendsConnections as &$aFriends)
  384. if ((int)$aFriends['initiator'] == (int)$iProfileId && (int)$aFriends['content'] == (int)$iFriendId)
  385. return true;
  386. return false;
  387. }
  388. public function removeContent()
  389. {
  390. if (!$this -> _oDb -> isTableExists($this -> _sTableWithTransKey) || !$this -> _oDb -> isFieldExists($this -> _sTableWithTransKey, $this -> _sTransferFieldIdent))
  391. return false;
  392. $iNumber = 0;
  393. $aRecords = $this -> _oDb -> getAll("SELECT * FROM `{$this -> _sTableWithTransKey}` WHERE `{$this -> _sTransferFieldIdent}` !=0");
  394. if (!empty($aRecords))
  395. {
  396. foreach($aRecords as $iKey => $aValue)
  397. {
  398. $oAccount = BxDolAccount::getInstance($aValue['id']);
  399. if ($oAccount)
  400. $oAccount -> delete(true);
  401. $iNumber++;
  402. }
  403. if ($iNumber)
  404. foreach ($this -> _oConfig -> _aMigrationModules as $sName => $aModule)
  405. {
  406. //Create transferring class object
  407. require_once($aModule['migration_class'] . '.php');
  408. $oObject = new $aModule['migration_class']($this -> _oMainModule, $this -> _mDb);
  409. $oObject -> removeContent();
  410. }
  411. }
  412. parent::removeContent();
  413. return $iNumber;
  414. }
  415. /**
  416. * Adds fields list if doesn't exist or value to existed fields list
  417. *
  418. * @param string $sName list name
  419. * @param boolean $bUseOrder use Order field instead of Value as value for profile
  420. * @param int $iStart start value, to show all above it
  421. * @param boolean $bCreate create fields list if doesn't exists
  422. * @return string fields list name
  423. */
  424. private function addPreValues($sName, $bUseOrder = false, $iStart = 0, $bCreate = false)
  425. {
  426. $sKeyField = 'Value';
  427. if ($bUseOrder)
  428. $sKeyField = 'Order';
  429. $aPairs = $this -> getPreValuesBy($sName, $sKeyField, 'LKey', $iStart);
  430. $aValues = array();
  431. foreach($aPairs as $sKey => $sValue)
  432. {
  433. $aTranslations = $this -> getLKeyTranslations($sValue);
  434. $aValues[$sKey] = !empty($aTranslations) && sizeof($aTranslations) > 1 ? $this -> getLKeyTranslations($sValue) : $aTranslations[$this -> getDefaultLang()];
  435. }
  436. return $this -> transferPreValues($sName, $sName, $aValues, true);
  437. }
  438. }
  439. /** @} */