BxDolStudioLanguagesUtils.php 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472
  1. <?php defined('BX_DOL') or die('hack attempt');
  2. /**
  3. * Copyright (c) BoonEx Pty Limited - http://www.boonex.com/
  4. * CC-BY License - http://creativecommons.org/licenses/by/3.0/
  5. *
  6. * @defgroup TridentStudio Trident Studio
  7. * @{
  8. */
  9. bx_import('BxDolLanguages');
  10. bx_import('BxDolXmlParser');
  11. bx_import('BxDolStudioLanguagesUtilsQuery');
  12. class BxDolStudioLanguagesUtils extends BxDolLanguages implements iBxDolSingleton
  13. {
  14. function __construct()
  15. {
  16. if(isset($GLOBALS['bxDolClasses'][get_class($this)]))
  17. trigger_error ('Multiple instances are not allowed for the class: ' . get_class($this), E_USER_ERROR);
  18. parent::__construct();
  19. $this->oDb = new BxDolStudioLanguagesUtilsQuery();
  20. }
  21. /**
  22. * Prevent cloning the instance
  23. */
  24. public function __clone()
  25. {
  26. if (isset($GLOBALS['bxDolClasses'][get_class($this)]))
  27. trigger_error('Clone is not allowed for the class: ' . get_class($this), E_USER_ERROR);
  28. }
  29. /**
  30. * Get singleton instance of the class
  31. */
  32. public static function getInstance()
  33. {
  34. if(!isset($GLOBALS['bxDolClasses'][__CLASS__]))
  35. $GLOBALS['bxDolClasses'][__CLASS__] = new BxDolStudioLanguagesUtils();
  36. return $GLOBALS['bxDolClasses'][__CLASS__];
  37. }
  38. function getLanguageInfo($sName)
  39. {
  40. $aLanguage = array();
  41. $this->oDb->getLanguagesBy(array('type' => 'by_name', 'value' => $sName), $aLanguage, false);
  42. bx_import('BxDolStudioTemplate');
  43. if(!empty($aLanguage))
  44. $aLanguage['icon'] = BxDolStudioTemplate::getInstance()->getIconUrl('sys_fl_' . $aLanguage['flag'] . '.gif');
  45. return $aLanguage;
  46. }
  47. function getLanguagesInfo($bIdAsKey = false, $bActiveOnly = false)
  48. {
  49. $aLanguages = array();
  50. $this->oDb->getLanguagesBy(array('type' => 'all'), $aLanguages, false);
  51. if(!is_array($aLanguages) || empty($aLanguages))
  52. return $aLanguages;
  53. bx_import('BxDolStudioTemplate');
  54. $oTemplate = BxDolStudioTemplate::getInstance();
  55. foreach($aLanguages as $iKey => $aLanguage)
  56. $aLanguages[$iKey]['icon'] = $oTemplate->getIconUrl('sys_fl_' . $aLanguage['flag'] . '.gif');
  57. return $aLanguages;
  58. }
  59. function readLanguage($sPath, $sType = 'restore')
  60. {
  61. if(!file_exists($sPath))
  62. return array();
  63. $oXmlParser = BxDolXmlParser::getInstance();
  64. $sXmlContent = file_get_contents($sPath);
  65. $aResult = array();
  66. $aResult['name'] = $oXmlParser->getAttribute($sXmlContent, 'resources', 'name');
  67. $aResult['title'] = $oXmlParser->getAttribute($sXmlContent, 'resources', 'title');
  68. if($aResult['title'] === false)
  69. unset($aResult['title']);
  70. $aResult['category'] = $oXmlParser->getAttribute($sXmlContent, 'resources', 'category');
  71. if($aResult['category'] === false)
  72. unset($aResult['category']);
  73. switch($sType) {
  74. case 'restore':
  75. $aResult['strings'] = $oXmlParser->getValues($sXmlContent, 'string');
  76. break;
  77. case 'update':
  78. $aResult['strings_del'] = $oXmlParser->getValues($sXmlContent, 'string_del');
  79. if(empty($aResult['strings_del']) || !is_array($aResult['strings_del']))
  80. unset($aResult['strings_del']);
  81. $aResult['strings_add'] = $oXmlParser->getValues($sXmlContent, 'string_add');
  82. if(empty($aResult['strings_add']) || !is_array($aResult['strings_add']))
  83. unset($aResult['strings_add']);
  84. $aResult['strings_upd'] = $oXmlParser->getValues($sXmlContent, 'string_upd');
  85. if(empty($aResult['strings_upd']) || !is_array($aResult['strings_upd']))
  86. unset($aResult['strings_upd']);
  87. break;
  88. }
  89. return $aResult;
  90. }
  91. function compileLanguage($mixedLang = 0, $bForce = false)
  92. {
  93. $sType = 'all';
  94. if(!empty($mixedLang)) {
  95. if(is_string($mixedLang) && !is_numeric($mixedLang))
  96. $sType = 'all_by_name';
  97. else if(is_numeric($mixedLang) || is_int($mixedLang)) {
  98. $sType = 'all_by_id';
  99. $mixedLang = (int)$mixedLang;
  100. }
  101. }
  102. $aLanguages = array();
  103. $iLanguages = $this->oDb->getLanguagesBy(array('type' => $sType, 'value' => $mixedLang), $aLanguages);
  104. if($iLanguages == 0)
  105. return false;
  106. bx_import('BxDolFile');
  107. $oFile = BxDolFile::getInstance();
  108. $sNewLine = "\r\n";
  109. foreach($aLanguages as $aLanguage) {
  110. if(!$bForce && (int)$aLanguage['enabled'] != 1)
  111. continue;
  112. $aKeys = array();
  113. $this->oDb->getKeysBy(array('type' => 'by_language_id_key_key', 'value' => $aLanguage['id']), $aKeys);
  114. if($aLanguage['name'] != BX_DOL_LANGUAGE_DEFAULT && getParam('lang_subst_from_en') == 'on') {
  115. $aKeysAll = array();
  116. $this->oDb->getKeysBy(array('type' => 'by_language_name_key_key', 'value' => BX_DOL_LANGUAGE_DEFAULT), $aKeysAll);
  117. $aKeys = array_merge($aKeysAll, $aKeys);
  118. }
  119. $sLanguageFile = "lang-" . $aLanguage['name'] . ".php";
  120. $oFile->delete('cache/' . $sLanguageFile);
  121. $rHandle = fopen( BX_DIRECTORY_PATH_CACHE . $sLanguageFile, 'w');
  122. if($rHandle === false)
  123. return false;
  124. $sContent = "<?php{$sNewLine}\$GLOBALS['LANG'] = array(";
  125. foreach($aKeys as $aKey) {
  126. list($sKey, $sString) = str_replace(array("\\", "'"), array("\\\\", "\\'"), array($aKey['key'], $aKey['string']));
  127. $sContent .= "{$sNewLine}\t'$sKey' => '$sString',";
  128. }
  129. $sContent = trim($sContent, ',');
  130. if(fwrite($rHandle, $sContent."{$sNewLine});?>") === false)
  131. return false;
  132. if(fclose($rHandle) === false)
  133. return false;
  134. @chmod( BX_DIRECTORY_PATH_CACHE . "lang-{$aLanguage['name']}.php", 0666);
  135. }
  136. $this->init();
  137. return true;
  138. }
  139. function installLanguage($aLanguageModule, $bRecompile = true)
  140. {
  141. $aLanguage = array();
  142. $this->oDb->getLanguagesBy(array('type' => 'by_name', 'value' => $aLanguageModule['uri']), $aLanguage, false);
  143. if(empty($aLanguage) || !is_array($aLanguage))
  144. return false;
  145. $sPath = BX_DIRECTORY_PATH_MODULES . $aLanguageModule['path'] . 'data/langs/';
  146. if(!($rHandler = opendir($sPath)))
  147. return false;
  148. $bResult = false;
  149. while(($sFileName = readdir($rHandler)) !== false) {
  150. if(substr($sFileName, -3) != 'xml')
  151. continue;
  152. $sModule = substr($sFileName, 0, -4);
  153. $bResult |= $this->_restoreLanguageByModule($aLanguage, $sPath, $sModule);
  154. }
  155. closedir($rHandler);
  156. $bResult |= $this->_restoreLanguageByModule($aLanguage, $sPath, $aLanguageModule);
  157. return $bResult && ($bRecompile ? $this->compileLanguage($aLanguage['id']) : true);
  158. }
  159. function restoreLanguage($mixedLang = 0, $mixedModule = 0, $bRecompile = true)
  160. {
  161. $aLanguages = array();
  162. if(!empty($mixedLang)) {
  163. $sType = is_string($mixedLang) && !is_numeric($mixedLang) ? 'by_name' : 'by_id';
  164. $this->oDb->getLanguagesBy(array('type' => $sType, 'value' => $mixedLang), $aLanguages[0], false);
  165. }
  166. else
  167. $this->oDb->getLanguagesBy(array('type' => 'all'), $aLanguages, false);
  168. $bResult = true;
  169. foreach($aLanguages as $aLanguage) {
  170. if(empty($aLanguage) || !is_array($aLanguage))
  171. continue;
  172. bx_import('BxDolModuleQuery');
  173. $oModuleQuery = BxDolModuleQuery::getInstance();
  174. $aLanguageModule = $oModuleQuery->getModuleByUri($aLanguage['name']);
  175. if(empty($aLanguageModule) || !is_array($aLanguageModule))
  176. continue;
  177. $sPath = BX_DIRECTORY_PATH_MODULES . $aLanguageModule['path'] . 'data/langs/';
  178. if(!empty($mixedModule))
  179. $bResult &= $this->_restoreLanguageByModule($aLanguage, $sPath, $mixedModule);
  180. else {
  181. $aModules = $oModuleQuery->getModules();
  182. foreach($aModules as $aModule)
  183. $bResult &= $this->_restoreLanguageByModule($aLanguage, $sPath, $aModule);
  184. }
  185. if($bRecompile)
  186. $bResult &= $this->compileLanguage($aLanguage['id']);
  187. }
  188. return $bResult;
  189. }
  190. function removeLanguageById($mixedLang = 0, $bRecompile = true)
  191. {
  192. $aLanguages = array();
  193. if(!empty($mixedLang)) {
  194. $sType = is_string($mixedLang) && !is_numeric($mixedLang) ? 'by_name' : 'by_id';
  195. $this->oDb->getLanguagesBy(array('type' => $sType, 'value' => $mixedLang), $aLanguages[0], false);
  196. } else
  197. $this->oDb->getLanguagesBy(array('type' => 'all'), $aLanguages, false);
  198. $bResult = true;
  199. foreach($aLanguages as $aLanguage) {
  200. if(empty($aLanguage) || !is_array($aLanguage))
  201. continue;
  202. $bResult &= (int)$this->oDb->deleteStringsBy(array('type' => 'by_lang', 'language_id' => $aLanguage['id'])) >= 0;
  203. if($bRecompile)
  204. $bResult &= $this->compileLanguage($aLanguage['id']);
  205. }
  206. return $bResult;
  207. }
  208. function removeLanguageByModule($mixedModule, $bRecompile = true)
  209. {
  210. $aModule = $mixedModule;
  211. if(!is_array($mixedModule)) {
  212. $sMethod = is_string($mixedModule) && !is_numeric($mixedModule) ? 'getModuleByUri' : 'getModuleById';
  213. $aModule = BxDolModuleQuery::getInstance()->$sMethod($mixedModule);
  214. }
  215. if(empty($aModule) || !is_array($aModule) || !$aModule['uri'] || !$aModule['lang_category'])
  216. return false;
  217. $aCategory = array();
  218. $this->oDb->getCategoriesBy(array('type' => 'by_name', 'value' => $aModule['lang_category']), $aCategory, false);
  219. if(empty($aCategory) || !is_array($aCategory))
  220. return false;
  221. $bResult = (int)$this->oDb->deleteKeysBy(array('type' => 'by_cat_id', 'value' => $aCategory['id'])) >= 0;
  222. return $bResult && ($bRecompile ? $this->compileLanguage() : true);
  223. }
  224. function getLanguageString($sKey, $iLangId = 0)
  225. {
  226. if($iLangId == 0) {
  227. $aStrings = array();
  228. $this->oDb->getStringsBy(array('type' => 'all_by_key_key_language_id', 'value' => $sKey), $aStrings, false);
  229. return $aStrings;
  230. }
  231. $aString = array();
  232. $this->oDb->getStringsBy(array('type' => 'by_key_language_id', 'key' => $sKey, 'language_id' => $iLangId), $aString, false);
  233. return $aString;
  234. }
  235. function addLanguageString($sKey, $mixedString, $iLangId = 0, $iCategoryId = 0, $bRecompile = true)
  236. {
  237. $iLangId = (int)$iLangId;
  238. $iCategoryId = (int)$iCategoryId;
  239. if($iCategoryId == 0)
  240. $iCategoryId = BX_DOL_LANGUAGE_CATEGORY_CUSTOM;
  241. $sKey = bx_process_input($sKey);
  242. $mixedString = bx_process_input($mixedString);
  243. $aLanguages = array();
  244. $iLanguages = $this->oDb->getLanguagesBy(($iLangId == 0 ? array('type' => 'all') : array('type' => 'all_by_id', 'value' => $iLangId)), $aLanguages);
  245. if(($iKeyId = $this->oDb->addKey($iCategoryId, $sKey)) === false)
  246. return false;
  247. foreach($aLanguages as $aLanguage) {
  248. $sString = '';
  249. if(is_string($mixedString))
  250. $sString = $mixedString;
  251. else if(is_array($mixedString))
  252. $sString = $mixedString[$aLanguage['id']];
  253. if(!$this->oDb->addString($iKeyId, $aLanguage['id'], $sString))
  254. return false;
  255. if($bRecompile)
  256. $this->compileLanguage($aLanguage['id']);
  257. }
  258. return $iKeyId;
  259. }
  260. function updateLanguageString($sKey, $mixedString, $iLangId = 0, $iCategoryId = 0, $bRecompile = true)
  261. {
  262. $sKey = bx_process_input($sKey);
  263. $mixedString = bx_process_input($mixedString);
  264. $iLangId = (int)$iLangId;
  265. $iCategoryId = (int)$iCategoryId;
  266. if(empty($iCategoryId))
  267. $iCategoryId = BX_DOL_LANGUAGE_CATEGORY_CUSTOM;
  268. $aKey = array();
  269. $this->oDb->getKeysBy(array('type' => 'by_name', 'value' => $sKey), $aKey);
  270. if(empty($aKey))
  271. return $this->addLanguageString($sKey, $mixedString, $iLangId, $iCategoryId, $bRecompile);
  272. if((int)$aKey['category_id'] != $iCategoryId)
  273. $this->oDb->updateKeys(array('IDCategory' => $iCategoryId), array('ID' => $aKey['id']));
  274. return $this->updateLanguageStringById($aKey['id'], $mixedString, $iLangId, $bRecompile);
  275. }
  276. function updateLanguageStringById($iKeyId, $mixedString, $iLangId = 0, $bRecompile = true)
  277. {
  278. $iKeyId = (int)$iKeyId;
  279. $mixedString = bx_process_input($mixedString);
  280. $iLangId = (int)$iLangId;
  281. $aLanguages = array();
  282. $iLanguages = $this->oDb->getLanguagesBy(($iLangId == 0 ? array('type' => 'all') : array('type' => 'all_by_id', 'value' => $iLangId)), $aLanguages);
  283. foreach($aLanguages as $aLanguage) {
  284. $sString = '';
  285. if(is_string($mixedString))
  286. $sString = $mixedString;
  287. else if(is_array($mixedString))
  288. $sString = $mixedString[$aLanguage['id']];
  289. if($this->oDb->updateString($iKeyId, $aLanguage['id'], $sString) && $bRecompile)
  290. $this->compileLanguage($aLanguage['id']);
  291. }
  292. return true;
  293. }
  294. function deleteLanguageString($sKey, $iLangId = 0, $bRecompile = true)
  295. {
  296. $iLangId = (int)$iLangId;
  297. $sKey = bx_process_input($sKey);
  298. $aKey = array();
  299. $this->oDb->getKeysBy(array('type' => 'by_name', 'value' => $sKey), $aKey);
  300. if(empty($aKey))
  301. return false;
  302. return $this->deleteLanguageStringById($aKey['id'], $iLangId, $bRecompile);
  303. }
  304. function deleteLanguageStringById($iKeyId, $iLangId = 0, $bRecompile = true)
  305. {
  306. $iKeyId = (int)$iKeyId;
  307. $iLangId = (int)$iLangId;
  308. $aLanguages = array();
  309. $iLanguages = $this->oDb->getLanguagesBy(($iLangId == 0 ? array('type' => 'all') : array('type' => 'all_by_id', 'value' => $iLangId)), $aLanguages);
  310. foreach($aLanguages as $aLanguage) {
  311. if(!$this->oDb->deleteString($iKeyId, $aLanguage['id']))
  312. continue;
  313. if($bRecompile)
  314. $this->compileLanguage($aLanguage['id']);
  315. }
  316. return $this->oDb->deleteKey($iKeyId);
  317. }
  318. function addLanguageCategory($sName)
  319. {
  320. return $this->oDb->addCategory($sName);
  321. }
  322. function deleteLanguageCategory($sName)
  323. {
  324. return $this->oDb->deleteCategory($sName);
  325. }
  326. protected function _restoreLanguageByModule($aLanguage, $sPath, $mixedModule)
  327. {
  328. $oXmlParser = BxDolXmlParser::getInstance();
  329. $aModule = $mixedModule;
  330. if(!is_array($mixedModule)) {
  331. $sMethod = is_string($mixedModule) && !is_numeric($mixedModule) ? 'getModuleByUri' : 'getModuleById';
  332. $aModule = BxDolModuleQuery::getInstance()->$sMethod($mixedModule);
  333. }
  334. if(empty($aModule) || !is_array($aModule) || !$aModule['uri'] || !$aModule['lang_category'])
  335. return true;
  336. $sPath = $sPath . $aModule['uri'] . '.xml';
  337. if(!file_exists($sPath) && isset($aModule['path'])) {
  338. $sPath = BX_DIRECTORY_PATH_MODULES . $aModule['path'] . 'install/langs/' . $aLanguage['name'] . '.xml';
  339. if(!file_exists($sPath))
  340. return true;
  341. }
  342. $aLanguageInfo = $this->readLanguage($sPath);
  343. if(empty($aLanguageInfo['name']) || empty($aLanguageInfo['strings']) || $aLanguageInfo['name'] != $aLanguage['name'])
  344. return false;
  345. $aCategory = array();
  346. $this->oDb->getCategoriesBy(array('type' => 'by_name', 'value' => $aModule['lang_category']), $aCategory, false);
  347. $iCategoryId = 0;
  348. if(empty($aCategory) || !is_array($aCategory)) {
  349. $iCategoryId = $this->addLanguageCategory($aModule['lang_category']);
  350. if(empty($iCategoryId))
  351. return false;
  352. }
  353. else
  354. $iCategoryId = $aCategory['id'];
  355. $bDeleteStringsByKey = !$this->oDb->deleteStringsBy(array('type' => 'by_cat_and_lang', 'category_id' => $iCategoryId, 'language_id' => $aLanguage['id']));
  356. $bResult = true;
  357. foreach($aLanguageInfo['strings'] as $sKey => $sValue)
  358. if($sKey != '') {
  359. if($bDeleteStringsByKey)
  360. $this->oDb->deleteStringsBy(array('type' => 'by_key_and_lang', 'key' => $sKey, 'language_id' => $aLanguage['id']));
  361. $bResult &= $this->addLanguageString($sKey, $sValue, $aLanguage['id'], $iCategoryId, false) > 0;
  362. }
  363. return $bResult;
  364. }
  365. }
  366. /** @} */