BxDolStudioOptions.php 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439
  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 UnaStudio UNA Studio
  7. * @{
  8. */
  9. define('BX_DOL_STUDIO_STG_TYPE_SYSTEM', 'system');
  10. define('BX_DOL_STUDIO_STG_TYPE_DEFAULT', BX_DOL_STUDIO_STG_TYPE_SYSTEM);
  11. define('BX_DOL_STUDIO_STG_GROUP_SYSTEM', 'system');
  12. define('BX_DOL_STUDIO_STG_GROUP_MODULES', 'modules');
  13. define('BX_DOL_STUDIO_STG_GROUP_LANGUAGES', 'languages');
  14. define('BX_DOL_STUDIO_STG_GROUP_TEMPLATES', 'templates');
  15. define('BX_DOL_STUDIO_STG_CATEGORY_SYSTEM', 'system');
  16. define('BX_DOL_STUDIO_STG_CATEGORY_LANGUAGES', 'languages');
  17. define('BX_DOL_STUDIO_STG_CATEGORY_TEMPLATES', 'templates');
  18. define('BX_DOL_STUDIO_STG_CATEGORY_AUDIT', 'audit');
  19. define('BX_DOL_STUDIO_STG_MIX_SYSTEM', 'system');
  20. define('BX_DOL_STUDIO_STG_MIX_DEFAULT', BX_DOL_STUDIO_STG_MIX_SYSTEM);
  21. class BxDolStudioOptions extends BxDol
  22. {
  23. protected $oDb;
  24. protected $sParamPrefix;
  25. protected $sBaseUrl;
  26. protected $sType;
  27. protected $sCategory;
  28. protected $aCategories;
  29. protected $aCustomCategories;
  30. protected $bReadOnly; //--- Enable/Disable ReadOnly mode for system settings. Note. It doesn't affect Editable mixes.
  31. protected $bMixes; //--- Enable/Disable mixes feature.
  32. protected $sMix;
  33. protected $aMix;
  34. protected $sStorage;
  35. protected $sTranscoder;
  36. protected $sErrorMessage;
  37. function __construct($sType = '', $mixedCategory = '', $sMix = '')
  38. {
  39. parent::__construct();
  40. $this->oDb = new BxDolStudioOptionsQuery();
  41. $this->sParamPrefix = 'opt';
  42. $this->sBaseUrl = BX_DOL_URL_STUDIO . 'options.php';
  43. $this->sType = BX_DOL_STUDIO_STG_TYPE_DEFAULT;
  44. if(!empty($sType) && is_string($sType))
  45. $this->sType = $sType;
  46. $this->sCategory = '';
  47. if(!empty($mixedCategory)) {
  48. if(is_array($mixedCategory))
  49. $this->sCategory = $mixedCategory;
  50. else if(is_string($mixedCategory)) {
  51. $this->sCategory = json_decode($mixedCategory);
  52. if(empty($this->sCategory))
  53. $this->sCategory = $mixedCategory;
  54. }
  55. }
  56. $this->bReadOnly = false;
  57. $this->bMixes = false;
  58. $this->sMix = $sMix;
  59. $this->aMix = [];
  60. $this->sStorage = 'sys_images_custom';
  61. $this->sTranscoder = 'sys_custom_images';
  62. $this->sErrorMessage = '';
  63. }
  64. public function checkAction()
  65. {
  66. $sAction = bx_get($this->sParamPrefix . '_action');
  67. if($sAction === false)
  68. return false;
  69. $sAction = bx_process_input($sAction);
  70. $sValue = '';
  71. if(bx_get($this->sParamPrefix . '_value') !== false)
  72. $sValue = bx_process_input(bx_get($this->sParamPrefix . '_value'));
  73. $aResult = ['code' => 0, 'message' => ''];
  74. switch($sAction) {
  75. case 'select-mix':
  76. $aResult = array_merge($aResult, $this->selectMix($sValue));
  77. break;
  78. case 'create-mix':
  79. $aResult = array_merge($aResult, $this->getPopupCodeCreateMix());
  80. break;
  81. case 'import-mix':
  82. $aResult = array_merge($aResult, $this->getPopupCodeImportMix());
  83. break;
  84. case 'export-mix':
  85. $aResult = array_merge($aResult, $this->exportMix((int)$sValue));
  86. break;
  87. case 'download-mix':
  88. $aResult = array_merge($aResult, $this->downloadMix((int)$sValue));
  89. break;
  90. case 'publish-mix':
  91. $aResult = array_merge($aResult, $this->publishMix((int)$sValue));
  92. break;
  93. case 'hide-mix':
  94. $aResult = array_merge($aResult, $this->hideMix((int)$sValue));
  95. break;
  96. case 'delete-mix':
  97. $aResult = array_merge($aResult, $this->deleteMix((int)$sValue));
  98. break;
  99. case 'get-page-by-type':
  100. $this->sType = $sValue;
  101. $aResult['content'] = $this->getPageCode();
  102. break;
  103. }
  104. return $aResult;
  105. }
  106. public function getType()
  107. {
  108. return $this->sType;
  109. }
  110. public function enableReadOnly($bReadOnly = true)
  111. {
  112. $this->bReadOnly = $bReadOnly;
  113. }
  114. public function enableMixes($bMixes = true)
  115. {
  116. $this->bMixes = $bMixes;
  117. }
  118. public function selectMix($sName)
  119. {
  120. $this->oDb->updateMixes(['active' => 0], [
  121. 'type' => $this->sType,
  122. 'category' => is_string($this->sCategory) ? $this->sCategory : '',
  123. 'active' => 1
  124. ]);
  125. $aResult = [];
  126. if($sName == BX_DOL_STUDIO_STG_MIX_SYSTEM || $this->oDb->updateMixes(['active' => 1], ['name' => $sName])) {
  127. $this->clearCache();
  128. $aResult = ['eval' => $this->getJsObject() . '.onMixSelect(oData);'];
  129. }
  130. else
  131. $aResult = ['message' => _t('_adm_stg_err_cannot_perform')];
  132. return $aResult;
  133. }
  134. public function exportMix($iId)
  135. {
  136. $aMix = [];
  137. $this->oDb->getMixes(['type' => 'by_id', 'value' => $iId], $aMix, false);
  138. if(empty($aMix) || !is_array($aMix))
  139. return array('message' => _t('_adm_stg_err_cannot_perform'));
  140. return [
  141. 'url' => bx_append_url_params($this->sBaseUrl, [
  142. $this->sParamPrefix . '_action' => 'download-mix',
  143. $this->sParamPrefix . '_value' => $iId,
  144. ]),
  145. 'eval' => $this->getJsObject() . '.onMixExport(oData);'
  146. ];
  147. }
  148. public function downloadMix($iId)
  149. {
  150. $aMix = [];
  151. $this->oDb->getMixes(['type' => 'by_id', 'value' => $iId], $aMix, false);
  152. if(empty($aMix) || !is_array($aMix))
  153. BxDolStudioTemplate::getInstance()->displayPageNotFound();
  154. $aOptions = [];
  155. $this->oDb->getMixesOptions(['type' => 'by_mix_id_pair_option_value', 'value' => $iId, 'for_export' => 1], $aOptions, false);
  156. $sContent = json_encode([
  157. 'mix' => [
  158. 'type' => $aMix['type'],
  159. 'category' => $aMix['category'],
  160. 'name' => $aMix['name'],
  161. 'title' => $aMix['title']
  162. ],
  163. 'options' => $aOptions
  164. ]);
  165. header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
  166. header("Content-type: application/json");
  167. header("Content-Length: " . strlen($sContent));
  168. header("Content-Disposition: attachment; filename=\"". strtolower($aMix['name']) . ".json\"");
  169. echo $sContent;
  170. exit;
  171. }
  172. public function publishMix($iId)
  173. {
  174. $aResult = [];
  175. if($this->oDb->updateMixes(['published' => 1], ['id' => $iId])) {
  176. $this->clearCache();
  177. $aResult = ['eval' => $this->getJsObject() . '.onMixPublish(oData);'];
  178. }
  179. else
  180. $aResult = ['message' => _t('_adm_stg_err_cannot_perform')];
  181. return $aResult;
  182. }
  183. public function hideMix($iId)
  184. {
  185. $aResult = [];
  186. if($this->oDb->updateMixes(['published' => 0], ['id' => $iId])) {
  187. $this->clearCache();
  188. $aResult = ['eval' => $this->getJsObject() . '.onMixHide(oData);'];
  189. }
  190. else
  191. $aResult = ['message' => _t('_adm_stg_err_cannot_perform')];
  192. return $aResult;
  193. }
  194. public function deleteMix($iId)
  195. {
  196. $aResult = [];
  197. if($this->oDb->deleteMixesOptions(['mix_id' => $iId]) && $this->oDb->deleteMixes(['id' => $iId])) {
  198. $this->clearCache();
  199. $aResult = ['eval' => $this->getJsObject() . '.onMixDelete(oData);'];
  200. }
  201. else
  202. $aResult = ['message' => _t('_adm_stg_err_cannot_perform')];
  203. return $aResult;
  204. }
  205. public function saveChanges(&$oForm)
  206. {
  207. $iMixId = $oForm->getCleanValue('mix_id');
  208. $aCategories = explode(',', $oForm->getCleanValue('categories'));
  209. $sEvalRenewToken = $this->getJsObject() . ".onSubmitted('" . $oForm->getId() . "', '" . $oForm->getCsrfToken() . "', oData);";
  210. foreach ($aCategories as $sCategory) {
  211. $aOptions = [];
  212. $iOptions = $this->oDb->getOptions(['type' => 'by_category_name_full', 'value' => $sCategory], $aOptions);
  213. $aData = [];
  214. foreach($aOptions as $aOption) {
  215. $aData[$aOption['name']] = $this->getSubmittedValue($aOption, $oForm);
  216. if($aData[$aOption['name']] === false && !empty($this->sErrorMessage)) {
  217. $this->sCategory = $sCategory;
  218. return bx_get_js_result([
  219. 'code' => 1,
  220. 'message' => _t('_adm_stg_err_save_error_message', _t($aOption['caption']), _t($this->sErrorMessage)),
  221. 'translate' => false,
  222. 'eval' => $sEvalRenewToken
  223. ]);
  224. }
  225. if(!empty($aOption['check'])) {
  226. $sCheckerHelper = '';
  227. if(!empty($aOption['type_name']) && BxDolRequest::serviceExists($aOption['type_name'], 'get_settings_checker_helper'))
  228. $sCheckerHelper = BxDolService::call($aOption['type_name'], 'get_settings_checker_helper');
  229. if($sCheckerHelper == '') {
  230. bx_import('BxDolStudioForm');
  231. $sCheckerHelper = 'BxDolStudioFormCheckerHelper';
  232. }
  233. $oChecker = new $sCheckerHelper();
  234. $aCheckFunction = [$oChecker, 'check' . bx_gen_method_name($aOption['check'])];
  235. $aCheckFunctionParams = [$aData[$aOption['name']]];
  236. if(!empty($aOption['check_params']))
  237. $aCheckFunctionParams = array_merge($aCheckFunctionParams, array_values(unserialize($aOption['check_params'])));
  238. if(is_callable($aCheckFunction) && !call_user_func_array($aCheckFunction, $aCheckFunctionParams)) {
  239. $this->sCategory = $sCategory;
  240. return bx_get_js_result([
  241. 'code' => 2,
  242. 'message' => _t('_adm_stg_err_save_error_message', _t($aOption['caption']), _t($aOption['check_error'])),
  243. 'translate' => false,
  244. 'eval' => $sEvalRenewToken
  245. ]);
  246. }
  247. }
  248. if(isset($aData[$aOption['name']]))
  249. $aData[$aOption['name']] = $this->getProcessedValue($aOption, $aData[$aOption['name']]);
  250. else
  251. $aData[$aOption['name']] = $this->getEmptyValue($aOption);
  252. $mixedValue = $this->oDb->getParam($aOption['name']);
  253. if($this->oDb->setParam($aOption['name'], $aData[$aOption['name']], $iMixId)) {
  254. $aCategoryInfo = [];
  255. $this->oDb->getCategories(['type' => 'by_name', 'value' => $sCategory], $aCategoryInfo, false);
  256. bx_alert('system', 'save_setting', 0, 0, [
  257. 'category' => $aCategoryInfo,
  258. 'option' => $aOption['name'],
  259. 'value' => $aData[$aOption['name']],
  260. 'value_prior' => $mixedValue
  261. ]);
  262. }
  263. }
  264. }
  265. $this->clearCache();
  266. return bx_get_js_result([
  267. 'code' => 0,
  268. 'message' => '_adm_stg_scs_save',
  269. 'eval' => $sEvalRenewToken
  270. ]);
  271. }
  272. protected function isReadOnly()
  273. {
  274. $bMix = !empty($this->aMix);
  275. return (!$bMix && $this->bReadOnly) || ($bMix && (int)$this->aMix['editable'] == 0);
  276. }
  277. protected function getSubmittedValue($aOption, &$oForm)
  278. {
  279. $mixedValue = '';
  280. switch($aOption['type']) {
  281. case 'image':
  282. $mixedValue = (int)getParam($aOption['name']);
  283. $aIds = $oForm->getCleanValue($aOption['name']);
  284. if(empty($aIds)) {
  285. if(!empty($mixedValue))
  286. $mixedValue = 0;
  287. break;
  288. }
  289. $oStorage = BxDolStorage::getObjectInstance($this->sStorage);
  290. if(!$oStorage)
  291. break;
  292. //--- Concatenation integer values as strings is required to get unique content id
  293. $iContentId = (int)($aOption['id'] . (int)$oForm->getCleanValue('mix_id'));
  294. foreach($aIds as $iId) {
  295. $oStorage->updateGhostsContentId($iId, false, $iContentId);
  296. $mixedValue = $iId;
  297. }
  298. break;
  299. default:
  300. $mixedValue = $oForm->getCleanValue($aOption['name']);
  301. }
  302. return $mixedValue;
  303. }
  304. protected function getProcessedValue($aOption, $mixedValue)
  305. {
  306. $sMethod = 'processCustomValue' . bx_gen_method_name(trim(str_replace($this->sType, '', $aOption['name']), '_'));
  307. if(method_exists($this, $sMethod))
  308. return $this->$sMethod($aOption, $mixedValue);
  309. if(is_array($mixedValue))
  310. $mixedValue = implode(',', $mixedValue);
  311. return $mixedValue;
  312. }
  313. protected function getEmptyValue($aOption)
  314. {
  315. $mixedValue = '';
  316. switch($aOption['type']) {
  317. case 'digit':
  318. $mixedValue = 0;
  319. break;
  320. case 'select':
  321. if (BxDolService::isSerializedService($aOption['extra']))
  322. $aValues = BxDolService::callSerialized($aOption['extra']);
  323. else
  324. $aValues = explode(',', $aOption['extra']);
  325. $mixedValue = $aValues[0];
  326. break;
  327. case 'text':
  328. case 'checkbox':
  329. case 'file':
  330. $mixedValue = "";
  331. break;
  332. }
  333. return $mixedValue;
  334. }
  335. protected function clearCache()
  336. {
  337. BxDolDb::getInstance()->cacheParams(true, true);
  338. $oCacheUtilities = BxDolCacheUtilities::getInstance();
  339. $oCacheUtilities->clear('db');
  340. $oCacheUtilities->clear('css');
  341. }
  342. protected function getCustomValueCurrencySign($aItem, $mixedValue)
  343. {
  344. return htmlspecialchars($mixedValue);
  345. }
  346. protected function processCustomValueCurrencySign($aItem, $mixedValue)
  347. {
  348. return htmlspecialchars_decode($mixedValue);
  349. }
  350. }
  351. /** @} */