BxDolMProfilesFields.php 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386
  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. require_once('BxDolMData.php');
  12. bx_import('BxDolStudioLanguagesUtils');
  13. class BxDolMProfilesFields extends BxDolMData
  14. {
  15. /**
  16. * @var $_aProfileFields profile fields for transfer
  17. */
  18. private $_aProfileFields = array();
  19. /**
  20. * @var array $_aFiltered exclude listed fields from migration list
  21. */
  22. private $_aFiltered = array(
  23. 'ID', 'NickName', 'Email', 'Password',
  24. 'Role', 'LangID', 'DateLastNav', 'DateReg',
  25. 'DateLastEdit', 'DateLastLogin', 'Sex',
  26. 'DateOfBirth', 'EmailNotify', 'Avatar', 'allow_view_to',
  27. 'Featured', 'DescriptionMe', 'FullName'
  28. );
  29. /**
  30. * @var $_oAssocFields list of the fields from Dolphin
  31. */
  32. private $_oAssocFields = null;
  33. public function __construct($oMigrationModule, &$mDb)
  34. {
  35. parent::__construct($oMigrationModule, $mDb);
  36. $this -> _sModuleName = 'profile_fields';
  37. $this -> _sTableWithTransKey = 'sys_form_inputs';
  38. }
  39. public function getTotalRecords()
  40. {
  41. $this -> _oAssocFields = $this -> getAssocFields();
  42. foreach($this -> _oAssocFields as $sKey => $aValue)
  43. {
  44. if (in_array($aValue['name'], $this -> _aFiltered) || (!$aValue['add'] && !$aValue['edit'] && !$aValue['view']))
  45. continue;
  46. $this -> _aProfileFields[$aValue['name']] = array(
  47. 'name' => $aValue['name'],
  48. 'type' => $this -> getConvertToUnaType($aValue['type']),
  49. 'caption' => $this -> getLKeyTranslations($aValue['title']),
  50. 'required' => $aValue['required'],
  51. 'add' => $aValue['add'],
  52. 'edit' => $aValue['edit'],
  53. 'view' => $aValue['view'],
  54. 'values' => $this -> getFieldValues($sKey)
  55. );
  56. }
  57. return sizeof($this -> _aProfileFields);
  58. }
  59. /**
  60. * Convert Dolphin's fields types to UNA format
  61. *
  62. * @param int $sType Dolphin's field
  63. * @return array
  64. */
  65. private function getConvertToUnaType($sType)
  66. {
  67. $aM2UNATypes = array(
  68. 'text' => array(
  69. 'type' => 'text',
  70. 'db_pass' => 'Xss',
  71. 'sql' => "varchar(255) default ''",
  72. ),
  73. 'system' => array(
  74. 'type' => 'text',
  75. 'db_pass' => 'Xss',
  76. 'sql' => "varchar(255) default ''",
  77. ),
  78. 'html_area' => array(
  79. 'type' => 'textarea',
  80. 'db_pass' => 'XssMultiline',
  81. 'sql' => "text default ''",
  82. ),
  83. 'area' => array(
  84. 'type' => 'textarea',
  85. 'db_pass' => 'XssMultiline',
  86. 'sql' => "text default ''",
  87. ),
  88. 'select_one' => array(
  89. 'type' => 'select',
  90. 'db_pass' => 'Xss',
  91. 'sql' => "varchar(255) default NULL",
  92. ),
  93. 'date' => array(
  94. 'type' => 'date',
  95. 'db_pass' => 'Date',
  96. 'sql' => "date default NULL",
  97. ),
  98. 'num' => array(
  99. 'type' => 'text',
  100. 'db_pass' => 'Int',
  101. 'sql' => "int(10) default NULL",
  102. ),
  103. 'bool' => array(
  104. 'type' => 'checkbox',
  105. 'db_pass' => 'Xss',
  106. 'sql' => "varchar(255) default NULL",
  107. ),
  108. 'select_set' => array(
  109. 'type' => 'checkbox_set',
  110. 'db_pass' => 'Set',
  111. 'sql' => "bigint(20) default NULL",
  112. ),
  113. 'pass' => array(
  114. 'type' => 'password',
  115. 'sql' => "varchar(40) default NULL",
  116. ),
  117. 'range' => array(
  118. 'type' => 'doublerange',
  119. 'db_pass' => 'Xss',
  120. 'sql' => "varchar(255) default NULL",
  121. )
  122. );
  123. return $aM2UNATypes[$sType] ? $aM2UNATypes[$sType] : $aM2UNATypes['text'];
  124. }
  125. public function runMigration()
  126. {
  127. if (!$this -> getTotalRecords())
  128. {
  129. $this -> setResultStatus(_t('_bx_dolphin_migration_no_data_to_transfer'));
  130. return BX_MIG_SUCCESSFUL;
  131. }
  132. $this -> createMIdField();
  133. $this -> setResultStatus(_t('_bx_dolphin_migration_started_migration_profile_fields'));
  134. $i = 0;
  135. foreach($this -> _aProfileFields as $sKey => $aItem)
  136. {
  137. if (!$this -> _oDb -> isFieldExists('bx_persons_data', $sKey))
  138. {
  139. if (!$this -> _oDb -> query("ALTER TABLE `bx_persons_data` ADD `{$sKey}` {$aItem['type']['sql']}")){
  140. $this -> setResultStatus(_t('_bx_dolphin_migration_started_migration_profile_field_can_not_be_transferred'));
  141. return BX_MIG_FAILED;
  142. }
  143. }
  144. //continue;
  145. if ($this -> isFieldTransferred($sKey))
  146. continue;
  147. $iKeyID = time() + $i++; // unique language keys postfix
  148. $sQuery = $this -> _oDb -> prepare("
  149. INSERT INTO `{$this -> _sTableWithTransKey}` SET
  150. `object` = 'bx_person',
  151. `module` = 'custom',
  152. `values` = ?,
  153. `name` = ?,
  154. `db_pass` = ?,
  155. `type` = ?,
  156. `required` = ?,
  157. `caption_system` = ?,
  158. `caption` = ?",
  159. $this -> transferPreValues($sKey, $aItem['name'], $aItem['values']),
  160. $sKey,
  161. $aItem['type']['db_pass'],
  162. $aItem['type']['type'],
  163. $aItem['required'],
  164. '_sys_form_txt_field_caption_system_' . $iKeyID,
  165. '_sys_form_txt_field_caption_' . $iKeyID
  166. );
  167. if (!$this -> _oDb -> query($sQuery))
  168. {
  169. $this -> setResultStatus(_t('_bx_dolphin_migration_started_migration_profile_field_can_not_be_transferred'));
  170. return BX_MIG_FAILED;
  171. }
  172. $iFieldId = $this -> _oDb -> lastId();
  173. $this -> setMID($iFieldId, $iFieldId);
  174. // create form fields
  175. $this -> _oDb -> query($sQuery);
  176. $sQueryDisplay = "INSERT INTO `sys_form_display_inputs` (`id`, `display_name`, `input_name`, `visible_for_levels`, `active`, `order`) VALUES";
  177. if ($aItem['view'])
  178. $sQueryDisplay .= "(NULL, 'bx_person_view', '{$sKey}', 2147483647, 1, 0),";
  179. if ($aItem['add'])
  180. $sQueryDisplay .= "(NULL, 'bx_person_add', '{$sKey}', 2147483647, 1, 0),";
  181. if ($aItem['edit'])
  182. $sQueryDisplay .= "(NULL, 'bx_person_edit', '{$sKey}', 2147483647, 1, 0),";
  183. // add display for view and add forms
  184. $this -> _oDb -> query(trim($sQueryDisplay, ','));
  185. // add language keys with translations
  186. foreach($this -> _aLanguages as $sLangKey => $sValue)
  187. {
  188. $sTitle = isset($aItem['caption'][$sLangKey]) ? $aItem['caption'][$sLangKey] : $sKey;
  189. $this -> _oLanguage -> addLanguageString('_sys_form_txt_field_caption_system_' . $iKeyID, $sTitle, $this -> _aLanguages[$sLangKey], 0, false);
  190. $this -> _oLanguage -> addLanguageString('_sys_form_txt_field_caption_' . $iKeyID, $sTitle, $this -> _aLanguages[$sLangKey]);
  191. }
  192. $this -> _iTransferred++;
  193. }
  194. $this -> migrateProfileFieldsInfo();
  195. $this -> setResultStatus(_t('_bx_dolphin_migration_started_migration_profile_fields_finished', $this -> _iTransferred));
  196. return BX_MIG_SUCCESSFUL;
  197. }
  198. private function isFieldTransferred($sName)
  199. {
  200. $sQuery = $this -> _oDb -> prepare("SELECT COUNT(*) FROM `sys_form_inputs` WHERE `object` = 'bx_person' AND `module` = 'custom' AND `name` = ?", $sName);
  201. return (int)$this -> _oDb -> getOne($sQuery) > 0;
  202. }
  203. /**
  204. * Returns Una profile fields list
  205. * @param int $iProfileId profile ID
  206. * @return array
  207. */
  208. private function getPersonsFieldValues($iProfileId)
  209. {
  210. return $this -> _oDb -> getRow("SELECT * FROM `bx_persons_data` WHERE `id` = {$iProfileId} LIMIT 1");
  211. }
  212. /**
  213. * Builds value for multivalues type fields
  214. *
  215. * @param array $aFiled fields params
  216. * @param string $sFiledValue value
  217. * @return int value
  218. */
  219. private function convertValues($aFiled, $sFiledValue)
  220. {
  221. $aOriginalFields = $this -> getAssocFields();
  222. if (!$aOriginalFields[$aFiled['name']]['values'] ||
  223. ($aOriginalFields[$aFiled['name']]['values'] && substr($aOriginalFields[$aFiled['name']]['values'], 0, 2) != '#!')
  224. || $aOriginalFields[$aFiled['name']]['type'] !== 'select_set')
  225. return $sFiledValue;
  226. $aItems = explode(',', $sFiledValue);
  227. $aPairs = $this -> getPreValuesBy(substr($aOriginalFields[$aFiled['name']]['values'], 2), 'Value', 'Order');
  228. $iResult = 0;
  229. foreach($aItems as $iKey => $sValue)
  230. $iResult += pow(2, (int)$aPairs[$sValue] - 1);
  231. return $iResult ? $iResult : $sFiledValue;
  232. }
  233. /**
  234. * Migrate profile fields values for transferred profiles
  235. *
  236. * @return void
  237. */
  238. private function migrateProfileFieldsInfo()
  239. {
  240. $sQuery = "SELECT * FROM `" . $this -> _oConfig -> _aMigrationModules['profiles']['table_name'] . "`";
  241. $aProfiles = $this -> _mDb -> getAll($sQuery);
  242. foreach($aProfiles as $iKey => $aProfile)
  243. {
  244. if (!($iProfileId = $this -> getContentId($aProfile['ID'])))
  245. continue;
  246. $aValues = array();
  247. $sNewField = '';
  248. $aCurrentMembersValues = $this -> getPersonsFieldValues($iProfileId);
  249. foreach($this -> _aProfileFields as $sFieldName => $aItem)
  250. {
  251. if (!(isset($aProfile[$sFieldName]) && $aProfile[$sFieldName] && empty($aCurrentMembersValues[$sFieldName])))
  252. continue;
  253. $sNewField .= "`{$aItem['name']}` = :{$aItem['name']},";
  254. $aValues[$sFieldName] = $this -> convertValues($aItem, $aProfile[$sFieldName]);
  255. }
  256. if ($sNewField)
  257. {
  258. $sNewField = trim($sNewField, ',');
  259. $sQuery =
  260. "
  261. UPDATE
  262. `bx_persons_data`
  263. SET
  264. {$sNewField}
  265. WHERE
  266. `id` = {$iProfileId}
  267. ";
  268. $this -> _oDb -> query($sQuery, $aValues);
  269. }
  270. }
  271. }
  272. /**
  273. * Builds list for fields lists with translations
  274. *
  275. * @param int $sField fields list's name
  276. * @param boolean $bGetKeyIfExists dont add values if list exists.
  277. * @return mixed array with fields list or pre values key list name
  278. */
  279. public function getFieldValues($sField, $bGetKeyIfExists = true)
  280. {
  281. $sValues = $this -> _mDb -> getOne("SELECT `Values` FROM `sys_profile_fields` WHERE `name` = :name", array('name' => $sField));
  282. if (empty($sValues))
  283. return '';
  284. $aItems = array();
  285. if (substr($sValues, 0, 2) == '#!')
  286. {
  287. $sKey = substr($sValues, 2);
  288. if ($this -> isKeyPreKeyExits($sKey) && $bGetKeyIfExists)
  289. return $sValues;
  290. $aValues = $this -> getPreValuesBy($sKey, 'Value');
  291. foreach($aValues as $mixedKey => $sValue) {
  292. $aItems[$mixedKey] = $this -> getLKeyTranslations($sValue);
  293. $aItems[$mixedKey] = $aItems[$mixedKey] ? $aItems[$mixedKey] : $sValue;
  294. }
  295. }
  296. else
  297. {
  298. $aValues = preg_split('/\r\n|\n|\r/', $sValues);
  299. foreach($aValues as $iKey => $sValue)
  300. $aItems[$sValue] = $this -> getLKeyTranslations("_FieldValues_{$sValue}");
  301. }
  302. return $aItems;
  303. }
  304. public function removeContent()
  305. {
  306. if (!$this -> _oDb -> isTableExists($this -> _sTableWithTransKey) || !$this -> _oDb -> isFieldExists($this -> _sTableWithTransKey, $this -> _sTransferFieldIdent))
  307. return false;
  308. $aRecords = $this -> _oDb -> getAll("SELECT * FROM `sys_form_inputs` WHERE `object` = 'bx_person' AND `{$this -> _sTransferFieldIdent}` != 0");
  309. $iNumber = 0;
  310. if (!empty($aRecords))
  311. {
  312. foreach($aRecords as $iKey => $aValue)
  313. {
  314. $sSql = $this -> _oDb -> prepare("DELETE `td`, `tdi` FROM `sys_form_display_inputs` AS `tdi` LEFT JOIN `sys_form_inputs` AS `td` ON `tdi`.`input_name`=`td`.`name` WHERE `td`.`object`='bx_person' AND `td`.`name` = ?", $aValue['name']);
  315. if ($this-> _oDb -> query($sSql))
  316. {
  317. $oLanguage = BxDolStudioLanguagesUtils::getInstance();
  318. if(!empty($aValue['caption']))
  319. $oLanguage->deleteLanguageString($aValue['caption']);
  320. if(!empty($aValue['caption_system']))
  321. $oLanguage->deleteLanguageString($aValue['caption_system']);
  322. if(!empty($aValue['info']))
  323. $oLanguage->deleteLanguageString($aValue['info']);
  324. if(!empty($aValue['checker_error']))
  325. $oLanguage->deleteLanguageString($aValue['checker_error']);
  326. if ($this -> _oDb -> isFieldExists('bx_persons_data', $aValue['name']))
  327. $this -> _oDb -> query("ALTER TABLE `bx_persons_data` DROP `{$aValue['name']}`");
  328. $iNumber++;
  329. }
  330. }
  331. }
  332. parent::removeContent();
  333. return $iNumber;
  334. }
  335. }
  336. /** @} */