model.php 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397
  1. <?php
  2. /**
  3. * The model file of setting module of ZenTaoPMS.
  4. *
  5. * @copyright Copyright 2009-2023 禅道软件(青岛)有限公司(ZenTao Software (Qingdao) Co., Ltd. www.cnezsoft.com)
  6. * @license ZPL(http://zpl.pub/page/zplv12.html) or AGPL(https://www.gnu.org/licenses/agpl-3.0.en.html)
  7. * @author Chunsheng Wang <chunsheng@cnezsoft.com>
  8. * @package setting
  9. * @version $Id: model.php 4976 2013-07-02 08:15:31Z wyd621@gmail.com $
  10. * @link https://www.zentao.net
  11. */
  12. class settingModel extends model
  13. {
  14. //-------------------------------- methods for get, set and delete setting items. ----------------------------//
  15. /**
  16. * 获取配置。
  17. * Get value of an item.
  18. *
  19. * @param string $paramString see parseItemParam();
  20. * @access public
  21. * @return string
  22. */
  23. public function getItem($paramString)
  24. {
  25. return $this->createDAO($this->parseItemParam($paramString), 'select')->fetch('value');
  26. }
  27. /**
  28. * Get some items.
  29. *
  30. * @param string $paramString see parseItemParam();
  31. * @access public
  32. * @return array
  33. */
  34. public function getItems($paramString)
  35. {
  36. return $this->createDAO($this->parseItemParam($paramString), 'select')->fetchAll('id', false);
  37. }
  38. /**
  39. * 保存配置。
  40. * Set value of an item.
  41. *
  42. * @param string $path system.common.global.sn | system.common.sn | system.common.global.sn@rnd
  43. * @param mixed $value
  44. * @param string $delimiter
  45. * @access public
  46. * @return bool
  47. */
  48. public function setItem($path, $value = '', $delimiter = '.')
  49. {
  50. $item = $this->parseItemPath($path, $delimiter);
  51. if(empty($item)) return false;
  52. $item->value = strval($value);
  53. if($item->module == 'feedback') $item->vision = '';
  54. /* 升级的时候,检查 vision 字段是否存在,不存在的话,unset。 */
  55. if(!empty($this->app->upgrading))
  56. {
  57. $firstConfig = $this->dao->select('*')->from(TABLE_CONFIG)->limit(1)->fetch();
  58. if(!isset($firstConfig->vision)) unset($item->vision);
  59. }
  60. $this->dao->replace(TABLE_CONFIG)->data($item)->exec();
  61. return !dao::isError();
  62. }
  63. /**
  64. * 批量保存配置。
  65. * Batch set items, the example:
  66. *
  67. * $path = 'system.mail';
  68. * $items->turnon = true;
  69. * $items->smtp->host = 'localhost';
  70. *
  71. * @param string $path like system.mail
  72. * @param array|object $items the items array or object, can be mixed by one level or two levels.
  73. * @access public
  74. * @return bool
  75. */
  76. public function setItems($path, $items)
  77. {
  78. /* Determine vision of config item. */
  79. $pathVision = explode('@', $path);
  80. $vision = isset($pathVision[1]) ? $pathVision[1] : '';
  81. $path = $pathVision[0];
  82. foreach($items as $key => $item)
  83. {
  84. if(is_array($item) or is_object($item))
  85. {
  86. $section = $key;
  87. foreach($item as $subKey => $subItem)
  88. {
  89. $this->setItem($path . '.' . $section . '.' . $subKey . "@$vision", $subItem);
  90. }
  91. }
  92. else
  93. {
  94. $this->setItem($path . '.' . $key . "@$vision", $item);
  95. }
  96. }
  97. if(!dao::isError()) return true;
  98. return false;
  99. }
  100. /**
  101. * 如果配置项存在则更新,不存在则插入。
  102. * When exists this item then update it. No exists then insert this item.
  103. *
  104. * @param string $path
  105. * @param string|int $value
  106. * @access public
  107. * @return bool
  108. */
  109. public function updateItem($path, $value = '')
  110. {
  111. $item = $this->parseItemPath($path);
  112. if(empty($item)) return false;
  113. if(!isset($item->vision)) $item->vision = '';
  114. $updateID = $this->dao->select('id')->from(TABLE_CONFIG)
  115. ->where('owner')->eq($item->owner)
  116. ->andWhere('vision')->eq($item->vision)
  117. ->andWhere('module')->eq($item->module)
  118. ->andWhere('section')->eq($item->section)
  119. ->andWhere('`key`')->eq($item->key)
  120. ->fetch('id');
  121. if($updateID)
  122. {
  123. $this->dao->update(TABLE_CONFIG)->set('value')->eq($value)->where('id')->eq($updateID)->exec();
  124. return true;
  125. }
  126. $item->value = $value;
  127. $this->dao->insert(TABLE_CONFIG)->data($item)->exec();
  128. return true;
  129. }
  130. /**
  131. * 删除配置项。
  132. * Delete items.
  133. *
  134. * @param string $paramString see parseItemParam();
  135. * @access public
  136. * @return void
  137. */
  138. public function deleteItems($paramString)
  139. {
  140. $this->createDAO($this->parseItemParam($paramString), 'delete')->exec();
  141. }
  142. /**
  143. * 处理传入的配置项,返回标准的配置项对象。
  144. * Parse item path
  145. *
  146. * @param string $path system.common.global.sn | system.common.sn | system.common.global.sn@rnd
  147. * @param string $delimiter
  148. * @access public
  149. * @return object|bool
  150. */
  151. public function parseItemPath($path, $delimiter = '.')
  152. {
  153. /* Determine vision of config item. */
  154. $pathVision = explode('@', $path);
  155. $vision = isset($pathVision[1]) ? $pathVision[1] : '';
  156. $path = $pathVision[0];
  157. /* fix bug when account has dot. */
  158. $account = isset($this->app->user->account) ? $this->app->user->account : '';
  159. $replace = false;
  160. if($account and strpos($path, $account) === 0)
  161. {
  162. $replace = true;
  163. $path = preg_replace("/^{$account}/", 'account', $path);
  164. }
  165. $level = substr_count($path, $delimiter);
  166. $section = '';
  167. if($level <= 1) return false;
  168. if($level == 2) list($owner, $module, $key) = explode($delimiter, $path);
  169. if($level == 3) list($owner, $module, $section, $key) = explode($delimiter, $path);
  170. if($replace) $owner = $account;
  171. $item = new stdclass();
  172. $item->owner = $owner;
  173. $item->module = $module;
  174. $item->section = $section;
  175. $item->key = $key;
  176. $item->vision = $vision;
  177. return $item;
  178. }
  179. /**
  180. * 解析配置项参数。
  181. * Parse the param string for select or delete items.
  182. *
  183. * @param string $paramString owner=xxx&key=sn and so on.
  184. * @access public
  185. * @return array
  186. */
  187. public function parseItemParam($paramString)
  188. {
  189. /* Parse the param string into array. */
  190. parse_str($paramString, $params);
  191. /* Init fields not set in the param string. */
  192. $fields = 'vision,owner,module,section,key';
  193. $fields = explode(',', $fields);
  194. foreach($fields as $field) if(!isset($params[$field])) $params[$field] = '';
  195. return $params;
  196. }
  197. /**
  198. * 创建DAO对象,用于查询或删除多条记录。
  199. * Create a DAO object to select or delete one or more records.
  200. *
  201. * @param array $params the params parsed by parseItemParam() method.
  202. * @param string $method select|delete.
  203. * @access public
  204. * @return object
  205. */
  206. public function createDAO($params, $method = 'select')
  207. {
  208. $params['vision'] = isset($params['vision']) ? $params['vision'] : '';
  209. $params['owner'] = isset($params['owner']) ? $params['owner'] : '';
  210. $params['module'] = isset($params['module']) ? $params['module'] : '';
  211. $params['section'] = isset($params['section']) ? $params['section'] : '';
  212. $params['key'] = isset($params['key']) ? $params['key'] : '';
  213. return $this->dao->$method('*')->from(TABLE_CONFIG)->where('1 = 1')
  214. ->beginIF($params['vision'])->andWhere('vision')->in($params['vision'])->fi()
  215. ->beginIF($params['owner'])->andWhere('owner')->in($params['owner'])->fi()
  216. ->beginIF($params['module'])->andWhere('module')->in($params['module'])->fi()
  217. ->beginIF($params['section'])->andWhere('section')->in($params['section'])->fi()
  218. ->beginIF($params['key'])->andWhere('`key`')->in($params['key'])->fi();
  219. }
  220. /**
  221. * 获取系统和用户的配置。
  222. * Get config of system and one user.
  223. *
  224. * @param string $account
  225. * @access public
  226. * @return array
  227. */
  228. public function getSysAndPersonalConfig($account = '')
  229. {
  230. $owner = 'system,' . ($account ? $account : '');
  231. $records = $this->dao->select('*')->from(TABLE_CONFIG)
  232. ->where('owner')->in($owner)
  233. ->beginIF(!$this->app->upgrading)->andWhere('vision')->in(array('', $this->config->vision))->fi()
  234. ->orderBy('id')
  235. ->fetchAll('id', false);
  236. if(!$records) return array();
  237. $vision = $this->config->vision;
  238. /* Group records by owner and module. */
  239. $config = array();
  240. foreach($records as $record)
  241. {
  242. if(!isset($config[$record->owner])) $config[$record->owner] = new stdclass();
  243. if(!isset($record->module)) return array(); // If no module field, return directly. Since 3.2 version, there's the module field.
  244. if(empty($record->module)) continue;
  245. /* If it`s lite vision unset config requiredFields */
  246. if($vision == 'lite' and $record->key == 'requiredFields' and $record->vision == '') continue;
  247. $config[$record->owner]->{$record->module}[] = $record;
  248. }
  249. return $config;
  250. }
  251. //-------------------------------- methods for version and sn. ----------------------------//
  252. /**
  253. * 获取禅道版本号。
  254. * Get the version of current zentaopms.
  255. *
  256. * Since the version field not saved in db. So if empty, return 0.3 beta.
  257. *
  258. * @access public
  259. * @return void
  260. */
  261. public function getVersion()
  262. {
  263. $version = isset($this->config->global->version) ? $this->config->global->version : '0.3.beta'; // No version, set as 0.3.beta.
  264. if($version == '3.0.stable') $version = '3.0'; // convert 3.0.stable to 3.0.
  265. return $version;
  266. }
  267. /**
  268. * 获取用需、软需的配置。
  269. * Get URSR.
  270. *
  271. * @access public
  272. * @return int
  273. */
  274. public function getURSR()
  275. {
  276. if(isset($this->config->URSR)) return $this->config->URSR;
  277. return $this->getItem('owner=system&module=custom&key=URSR');
  278. }
  279. /**
  280. * 更新禅道版本号。
  281. * Update version
  282. *
  283. * @param string $version
  284. * @access public
  285. * @return void
  286. */
  287. public function updateVersion($version)
  288. {
  289. return $this->setItem('system.common.global.version', $version);
  290. }
  291. /**
  292. * 设置sn。
  293. * Set the sn of current zentaopms.
  294. *
  295. * @access public
  296. * @return string
  297. */
  298. public function setSN()
  299. {
  300. $sn = $this->cookie->sn;
  301. if(!isset($this->config->installed) || !$this->config->installed)
  302. {
  303. if(!$sn) $sn = '';
  304. if($this->snNeededUpdate($sn))
  305. {
  306. $sn = $this->computeSN();
  307. helper::setcookie('sn', $sn, 0);
  308. }
  309. }
  310. else
  311. {
  312. if(!$sn)
  313. {
  314. $sn = $this->getItem('owner=system&module=common&section=global&key=sn');
  315. if($this->snNeededUpdate($sn))
  316. {
  317. $sn = $this->computeSN();
  318. }
  319. }
  320. $this->setItem('system.common.global.sn', $sn);
  321. if(!isset($this->config->global)) $this->config->global = new stdclass();
  322. $this->config->global->sn = $sn;
  323. helper::setcookie('sn', $sn, 0);
  324. }
  325. return $sn;
  326. }
  327. /**
  328. * Compute a SN. Use the server ip, and server software string as seed, and an rand number, two micro time
  329. *
  330. * Note: this sn just to unique this zentaopms. No any private info.
  331. *
  332. * @access public
  333. * @return string
  334. */
  335. public function computeSN()
  336. {
  337. $seed = $this->server->SERVER_ADDR . $this->server->SERVER_SOFTWARE;
  338. $sn = md5(str_shuffle(md5($seed . mt_rand(0, 99999999) . microtime())) . microtime());
  339. return $sn;
  340. }
  341. /**
  342. * 判断是否需要更新sn。
  343. * Judge a sn needed update or not.
  344. *
  345. * @param string $sn
  346. * @access public
  347. * @return bool
  348. */
  349. public function snNeededUpdate($sn)
  350. {
  351. if($sn == '') return true;
  352. if($sn == '281602d8ff5ee7533eeafd26eda4e776') return true;
  353. if($sn == '9bed3108092c94a0db2b934a46268b4a') return true;
  354. if($sn == '8522dd4d76762a49d02261ddbe4ad432') return true;
  355. if($sn == '13593e340ee2bdffed640d0c4eed8bec') return true;
  356. return false;
  357. }
  358. }