znt/module/setting/model.php

399 lines
13 KiB
PHP
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
declare(strict_types=1);
/**
* The model file of setting module of ZenTaoPMS.
*
* @copyright Copyright 2009-2023 禅道软件(青岛)有限公司(ZenTao Software (Qingdao) Co., Ltd. www.cnezsoft.com)
* @license ZPL(http://zpl.pub/page/zplv12.html) or AGPL(https://www.gnu.org/licenses/agpl-3.0.en.html)
* @author Chunsheng Wang <chunsheng@cnezsoft.com>
* @package setting
* @version $Id: model.php 4976 2013-07-02 08:15:31Z wyd621@gmail.com $
* @link https://www.zentao.net
*/
class settingModel extends model
{
//-------------------------------- methods for get, set and delete setting items. ----------------------------//
/**
* 获取配置。
* Get value of an item.
*
* @param string $paramString see parseItemParam();
* @access public
* @return string
*/
public function getItem(string $paramString): string
{
return $this->createDAO($this->parseItemParam($paramString), 'select')->fetch('value');
}
/**
* Get some items.
*
* @param string $paramString see parseItemParam();
* @access public
* @return array
*/
public function getItems(string $paramString): array
{
return $this->createDAO($this->parseItemParam($paramString), 'select')->fetchAll('id', false);
}
/**
* 保存配置。
* Set value of an item.
*
* @param string $path system.common.global.sn | system.common.sn | system.common.global.sn@rnd
* @param mixed $value
* @param string $delimiter
* @access public
* @return bool
*/
public function setItem(string $path, mixed $value = '', string $delimiter = '.'): bool
{
$item = $this->parseItemPath($path, $delimiter);
if(empty($item)) return false;
$item->value = strval($value);
if($item->module == 'feedback') $item->vision = '';
/* 升级的时候,检查 vision 字段是否存在不存在的话unset。 */
if(!empty($this->app->upgrading))
{
$firstConfig = $this->dao->select('*')->from(TABLE_CONFIG)->limit(1)->fetch();
if(!isset($firstConfig->vision)) unset($item->vision);
}
$this->dao->replace(TABLE_CONFIG)->data($item)->exec();
return !dao::isError();
}
/**
* 批量保存配置。
* Batch set items, the example:
*
* $path = 'system.mail';
* $items->turnon = true;
* $items->smtp->host = 'localhost';
*
* @param string $path like system.mail
* @param array|object $items the items array or object, can be mixed by one level or two levels.
* @access public
* @return bool
*/
public function setItems(string $path, array|object $items): bool
{
/* Determine vision of config item. */
$pathVision = explode('@', $path);
$vision = isset($pathVision[1]) ? $pathVision[1] : '';
$path = $pathVision[0];
foreach($items as $key => $item)
{
if(is_array($item) or is_object($item))
{
$section = $key;
foreach($item as $subKey => $subItem)
{
$this->setItem($path . '.' . $section . '.' . $subKey . "@$vision", $subItem);
}
}
else
{
$this->setItem($path . '.' . $key . "@$vision", $item);
}
}
if(!dao::isError()) return true;
return false;
}
/**
* 如果配置项存在则更新,不存在则插入。
* When exists this item then update it. No exists then insert this item.
*
* @param string $path
* @param string|int $value
* @access public
* @return bool
*/
public function updateItem(string $path, string|int $value = ''):bool
{
$item = $this->parseItemPath($path);
if(empty($item)) return false;
if(!isset($item->vision)) $item->vision = '';
$updateID = $this->dao->select('id')->from(TABLE_CONFIG)
->where('owner')->eq($item->owner)
->andWhere('vision')->eq($item->vision)
->andWhere('module')->eq($item->module)
->andWhere('section')->eq($item->section)
->andWhere('`key`')->eq($item->key)
->fetch('id');
if($updateID)
{
$this->dao->update(TABLE_CONFIG)->set('value')->eq($value)->where('id')->eq($updateID)->exec();
return true;
}
$item->value = $value;
$this->dao->insert(TABLE_CONFIG)->data($item)->exec();
return true;
}
/**
* 删除配置项。
* Delete items.
*
* @param string $paramString see parseItemParam();
* @access public
* @return void
*/
public function deleteItems(string $paramString): void
{
$this->createDAO($this->parseItemParam($paramString), 'delete')->exec();
}
/**
* 处理传入的配置项,返回标准的配置项对象。
* Parse item path
*
* @param string $path system.common.global.sn | system.common.sn | system.common.global.sn@rnd
* @param string $delimiter
* @access public
* @return object|bool
*/
public function parseItemPath(string $path, string $delimiter = '.'): object|bool
{
/* Determine vision of config item. */
$pathVision = explode('@', $path);
$vision = isset($pathVision[1]) ? $pathVision[1] : '';
$path = $pathVision[0];
/* fix bug when account has dot. */
$account = isset($this->app->user->account) ? $this->app->user->account : '';
$replace = false;
if($account and strpos($path, $account) === 0)
{
$replace = true;
$path = preg_replace("/^{$account}/", 'account', $path);
}
$level = substr_count($path, $delimiter);
$section = '';
if($level <= 1) return false;
if($level == 2) list($owner, $module, $key) = explode($delimiter, $path);
if($level == 3) list($owner, $module, $section, $key) = explode($delimiter, $path);
if($replace) $owner = $account;
$item = new stdclass();
$item->owner = $owner;
$item->module = $module;
$item->section = $section;
$item->key = $key;
$item->vision = $vision;
return $item;
}
/**
* 解析配置项参数。
* Parse the param string for select or delete items.
*
* @param string $paramString owner=xxx&key=sn and so on.
* @access public
* @return array
*/
public function parseItemParam(string $paramString): array
{
/* Parse the param string into array. */
parse_str($paramString, $params);
/* Init fields not set in the param string. */
$fields = 'vision,owner,module,section,key';
$fields = explode(',', $fields);
foreach($fields as $field) if(!isset($params[$field])) $params[$field] = '';
return $params;
}
/**
* 创建DAO对象用于查询或删除多条记录。
* Create a DAO object to select or delete one or more records.
*
* @param array $params the params parsed by parseItemParam() method.
* @param string $method select|delete.
* @access public
* @return object
*/
public function createDAO(array $params, string $method = 'select'): object
{
$params['vision'] = isset($params['vision']) ? $params['vision'] : '';
$params['owner'] = isset($params['owner']) ? $params['owner'] : '';
$params['module'] = isset($params['module']) ? $params['module'] : '';
$params['section'] = isset($params['section']) ? $params['section'] : '';
$params['key'] = isset($params['key']) ? $params['key'] : '';
return $this->dao->$method('*')->from(TABLE_CONFIG)->where('1 = 1')
->beginIF($params['vision'])->andWhere('vision')->in($params['vision'])->fi()
->beginIF($params['owner'])->andWhere('owner')->in($params['owner'])->fi()
->beginIF($params['module'])->andWhere('module')->in($params['module'])->fi()
->beginIF($params['section'])->andWhere('section')->in($params['section'])->fi()
->beginIF($params['key'])->andWhere('`key`')->in($params['key'])->fi();
}
/**
* 获取系统和用户的配置。
* Get config of system and one user.
*
* @param string $account
* @access public
* @return array
*/
public function getSysAndPersonalConfig(string $account = ''): array
{
$owner = 'system,' . ($account ? $account : '');
$records = $this->dao->select('*')->from(TABLE_CONFIG)
->where('owner')->in($owner)
->beginIF(!$this->app->upgrading)->andWhere('vision')->in(array('', $this->config->vision))->fi()
->orderBy('id')
->fetchAll('id', false);
if(!$records) return array();
$vision = $this->config->vision;
/* Group records by owner and module. */
$config = array();
foreach($records as $record)
{
if(!isset($config[$record->owner])) $config[$record->owner] = new stdclass();
if(!isset($record->module)) return array(); // If no module field, return directly. Since 3.2 version, there's the module field.
if(empty($record->module)) continue;
/* If it`s lite vision unset config requiredFields */
if($vision == 'lite' and $record->key == 'requiredFields' and $record->vision == '') continue;
$config[$record->owner]->{$record->module}[] = $record;
}
return $config;
}
//-------------------------------- methods for version and sn. ----------------------------//
/**
* 获取禅道版本号。
* Get the version of current zentaopms.
*
* Since the version field not saved in db. So if empty, return 0.3 beta.
*
* @access public
* @return void
*/
public function getVersion()
{
$version = isset($this->config->global->version) ? $this->config->global->version : '0.3.beta'; // No version, set as 0.3.beta.
if($version == '3.0.stable') $version = '3.0'; // convert 3.0.stable to 3.0.
return $version;
}
/**
* 获取用需、软需的配置。
* Get URSR.
*
* @access public
* @return int
*/
public function getURSR()
{
if(isset($this->config->URSR)) return $this->config->URSR;
return $this->getItem('owner=system&module=custom&key=URSR');
}
/**
* 更新禅道版本号。
* Update version
*
* @param string $version
* @access public
* @return void
*/
public function updateVersion($version)
{
return $this->setItem('system.common.global.version', $version);
}
/**
* 设置sn。
* Set the sn of current zentaopms.
*
* @access public
* @return string
*/
public function setSN()
{
$sn = $this->cookie->sn;
if(!isset($this->config->installed) || !$this->config->installed)
{
if(!$sn) $sn = '';
if($this->snNeededUpdate($sn))
{
$sn = $this->computeSN();
helper::setcookie('sn', $sn, 0);
}
}
else
{
if(!$sn)
{
$sn = $this->getItem('owner=system&module=common&section=global&key=sn');
if($this->snNeededUpdate($sn))
{
$sn = $this->computeSN();
}
}
$this->setItem('system.common.global.sn', $sn);
if(!isset($this->config->global)) $this->config->global = new stdclass();
$this->config->global->sn = $sn;
helper::setcookie('sn', $sn, 0);
}
return $sn;
}
/**
* Compute a SN. Use the server ip, and server software string as seed, and an rand number, two micro time
*
* Note: this sn just to unique this zentaopms. No any private info.
*
* @access public
* @return string
*/
public function computeSN()
{
$seed = $this->server->SERVER_ADDR . $this->server->SERVER_SOFTWARE;
$sn = md5(str_shuffle(md5($seed . mt_rand(0, 99999999) . microtime())) . microtime());
return $sn;
}
/**
* 判断是否需要更新sn。
* Judge a sn needed update or not.
*
* @param string $sn
* @access public
* @return bool
*/
public function snNeededUpdate(string $sn): bool
{
if($sn == '') return true;
if($sn == '281602d8ff5ee7533eeafd26eda4e776') return true;
if($sn == '9bed3108092c94a0db2b934a46268b4a') return true;
if($sn == '8522dd4d76762a49d02261ddbe4ad432') return true;
if($sn == '13593e340ee2bdffed640d0c4eed8bec') return true;
return false;
}
}