Merge branch 'master' into story

This commit is contained in:
sunguangming
2024-05-09 15:04:07 +08:00
5881 changed files with 215209 additions and 408159 deletions
+8 -5
View File
@@ -20,7 +20,7 @@ class entry extends baseEntry
if($this->app->action == 'options') throw EndResponseException::create($this->send(204));
if(!isset($this->app->user) or $this->app->user->account == 'guest') throw EndResponseException::create($this->sendError(401, 'Unauthorized'));
if(!$this->loadModel('user')->isLogon()) throw EndResponseException::create($this->sendError(401, 'Unauthorized'));
$this->dao = $this->loadModel('common')->dao;
}
@@ -219,11 +219,11 @@ class baseEntry
* Send error response
*
* @param int $code
* @param string $msg
* @param string|object $msg
* @access public
* @return string
*/
public function sendError(int $code, string $msg)
public function sendError(int $code, string|object $msg)
{
$response = new stdclass();
$response->error = $msg;
@@ -495,7 +495,10 @@ class baseEntry
{
foreach($data as $object) $this->formatFields($object, $fields);
}
$this->formatFields($data, $fields);
else
{
$this->formatFields($data, $fields);
}
return $data;
}
@@ -705,7 +708,7 @@ class baseEntry
$method = $this->app->getMethodName();
if($module and $method and !$this->loadModel('common')->isOpenMethod($module, $method) and !commonModel::hasPriv($module, $method))
{
return $this->send(403, array('error' => 'Access not allowed'));
die($this->send(403, array('error' => 'Access not allowed')));
}
}
+6 -5
View File
@@ -685,8 +685,8 @@ class baseControl
unset($this->view->pager->lang);
$output['status'] = is_object($this->view) ? 'success' : 'fail';
$output['data'] = json_encode($this->view);
$output['md5'] = md5(json_encode($this->view));
$output['data'] = json_encode($this->view) ? json_encode($this->view) : '';
$output['md5'] = md5($output['data']);
$this->output = json_encode($output);
}
@@ -1006,7 +1006,8 @@ class baseControl
* 设置 zin 渲染上下文数据。
*/
$context = \zin\context();
$context->data = (array)$this->view;
$context->control = $this;
$context->data = (array)$this->view;
$context->data['zinDebug'] = array();
if($this->config->debug && $this->config->debug >= 2 && $this->config->installed)
@@ -1032,7 +1033,7 @@ class baseControl
ob_start();
include $viewFile;
if(!$context->rendered) \zin\render();
if(!$context->rendered) \zin\renderPage();
$content = ob_get_clean();
ob_start();
@@ -1085,7 +1086,7 @@ class baseControl
{
print(urldecode(json_encode($data)));
$response = helper::removeUTF8Bom(ob_get_clean());
return helper::end($response);
return print($response);
}
/* Zand will use ob_get_clean() to print, so cannot clean so early. */
+32 -10
View File
@@ -15,6 +15,26 @@ declare(strict_types=1);
*/
class baseHelper
{
/**
* 已加载的目录.
* The loaded directories.
*
* @static
* @var array
* @access public
*/
static $loadedDirs = array();
/**
* 已经包含的文件.
* The included files.
*
* @static
* @var array
* @access public
*/
static $includedFiles = array();
/**
* 设置一个对象的成员变量。
* Set the member's value of one object.
@@ -170,7 +190,7 @@ class baseHelper
$sign = !str_contains($link, '?') ? "?" : "&";
$appendString = '';
if($onlyBody or self::inOnlyBodyMode()) $appendString = $sign . "onlybody=yes";
if($onlyBody or (self::inOnlyBodyMode() && !self::isAjaxRequest('modal'))) $appendString = $sign . "onlybody=yes";
if(self::isWithTID() and !str_contains($link, 'tid=')) $appendString .= empty($appendString) ? "{$sign}tid={$_GET['tid']}" : "&tid={$_GET['tid']}";
return $link . $appendString;
}
@@ -212,16 +232,13 @@ class baseHelper
static public function import($file)
{
$file = realpath($file);
if($file === false || !is_file($file)) return false;
if($file === false) return false;
static $includedFiles = array();
if(!isset($includedFiles[$file]))
{
include $file;
$includedFiles[$file] = true;
return true;
}
if(isset(self::$includedFiles[$file])) return true;
if(!is_file($file)) return false;
include $file;
self::$includedFiles[$file] = true;
return true;
}
@@ -665,6 +682,7 @@ class baseHelper
static public function ls($dir, $pattern = '')
{
if(empty($dir)) return array();
if(isset(self::$loadedDirs[$dir][$pattern])) return self::$loadedDirs[$dir][$pattern];
$files = array();
$dir = realpath($dir);
@@ -672,7 +690,10 @@ class baseHelper
if($dir === false) return array();
if(is_dir($dir)) $files = glob($dir . DIRECTORY_SEPARATOR . '*' . $pattern);
return empty($files) ? array() : $files;
self::$loadedDirs[$dir][$pattern] = $files ?: array();
return self::$loadedDirs[$dir][$pattern];
}
/**
@@ -803,6 +824,7 @@ class baseHelper
*/
public static function restartSession($sessionID = '')
{
if(!preg_match('/^\w+$/', $sessionID)) $sessionID = '';
if(empty($sessionID)) $sessionID = sha1((string)mt_rand(0, mt_getrandmax()));
session_write_close();
+10 -1
View File
@@ -123,6 +123,15 @@ class baseModel
*/
public $global;
/**
* $cache对象,用于访问缓存。
* The $cache object, used to access the cache.
*
* @var object
* @access public
*/
public $cache;
/**
* 构造方法。
* 1. 将全局变量设为model类的成员变量,方便model的派生类调用;
@@ -151,7 +160,7 @@ class baseModel
$this->loadDAO();
$this->setSuperVars();
$this->loadCache();
if($this->config->cache->enable) $this->loadCache();
/**
* 读取当前模块的tao类。
+61 -34
View File
@@ -287,6 +287,16 @@ class baseRouter
*/
static $loadedLangs = array();
/**
* 已加载的目标,可能是 model,tao 或者 zen 的实例化对象。
* Targets loaded, maybe instance of model, tao or zen.
*
* @static
* @var array
* @access public
*/
static $loadedTargets = array();
/**
* 全局$lang对象。
* The global $lang object.
@@ -469,9 +479,6 @@ class baseRouter
*/
public function setClient(): void
{
$this->setOpenApp();
$this->setSuperVars();
$this->startSession();
if($this->config->framework->multiSite) $this->setSiteCode() && $this->loadExtraConfig();
@@ -483,6 +490,9 @@ class baseRouter
if($this->config->framework->multiLanguage) $this->loadLang('common');
if($this->config->framework->multiTheme) $this->setClientTheme();
$this->setOpenApp();
$this->setSuperVars();
}
/**
@@ -863,7 +873,7 @@ class baseRouter
$account = isset($_SESSION['user']) ? $_SESSION['user']->account : '';
if(empty($account) and isset($_POST['account'])) $account = $_POST['account'];
if(empty($account) and isset($_GET['account'])) $account = $_GET['account'];
if(empty($account)) $account = $this->cookie->za;
if(empty($account) and isset($_COOKIE['za'])) $account = $_COOKIE['za'];
$vision = '';
$sql = new sql();
@@ -1170,16 +1180,15 @@ class baseRouter
$this->sessionID = isset($ztSessionHandler) ? $ztSessionHandler->getSessionID() : session_id();
/* Keep session if 'zentaosid'(session id) in $_GET. */
if(isset($_GET[$this->config->sessionVar]))
{
helper::restartSession($_GET[$this->config->sessionVar]);
}
elseif(isset($_SERVER['HTTP_TOKEN'])) // If request header has token, use it as session for authentication.
if(isset($_SERVER['HTTP_TOKEN'])) // If request header has token, use it as session for authentication.
{
helper::restartSession($_SERVER['HTTP_TOKEN']);
$this->sessionID = isset($ztSessionHandler) ? $ztSessionHandler->getSessionID() : session_id();
}
elseif(isset($_GET[$this->config->sessionVar]))
{
helper::restartSession($_GET[$this->config->sessionVar]);
}
define('SESSION_STARTED', true);
}
@@ -1199,9 +1208,10 @@ class baseRouter
$tab = '';
if(isset($_SERVER['HTTP_X_ZIN_APP'])) $tab = $_SERVER['HTTP_X_ZIN_APP'];
elseif(isset($this->lang->navGroup)) $tab = zget($this->lang->navGroup, $module, 'my');
elseif(isset($_COOKIE['tab']) && $_COOKIE['tab'] && preg_match('/^\w+$/', $_COOKIE['tab'])) $tab = $_COOKIE['tab'];
elseif(isset($this->lang->navGroup)) $tab = zget($this->lang->navGroup, $module, 'my');
if(!isset($this->lang->mainNav->{$tab}) && !isset($_SERVER['HTTP_X_ZIN_APP'])) $tab = '';
$this->tab = empty($tab) ? 'my' : $tab;
return;
}
@@ -1210,6 +1220,7 @@ class baseRouter
$this->tab = 'my';
if(isset($this->lang->navGroup) && $module) $this->tab = zget($this->lang->navGroup, $module, 'my');
if(isset($_COOKIE['tab']) and $_COOKIE['tab'] and preg_match('/^\w+$/', (string) $_COOKIE['tab'])) $this->tab = $_COOKIE['tab'];
if(!isset($this->lang->mainNav->{$this->tab})) $this->tab = 'my';
}
/**
@@ -1311,8 +1322,9 @@ class baseRouter
{
$this->clientDevice = 'desktop';
if($this->cookie->device == 'mobile') $this->clientDevice = 'mobile';
if($this->cookie->device == 'desktop') $this->clientDevice = 'desktop';
$cookieDevice = zget($_COOKIE, 'device', 'desktop');
if($cookieDevice == 'mobile') $this->clientDevice = 'mobile';
if($cookieDevice == 'desktop') $this->clientDevice = 'desktop';
if(empty($this->cookie->device) || !str_contains('mobile,desktop', (string) $this->cookie->device))
{
@@ -2058,7 +2070,11 @@ class baseRouter
$mergedTargetDir = $this->getTmpRoot() . $class . DS . $extTargetPrefix;
$mergedTargetFile = $mergedTargetDir . $moduleName . '.php';
if(!is_dir($mergedTargetDir)) mkdir($mergedTargetDir, 0755, true);
if(!is_dir($mergedTargetDir))
{
$made = mkdir($mergedTargetDir, 0755, true);
if(!$made && !empty($this->config->debug)) helper::end("ERROR: Can NOT create required directory '{$mergedTargetDir}', please create it manually with correct permission.");
}
/* 判断生成的缓存文件是否需要更新。 Judge whether the merged target file needed update or not. */
if(!$this->needTargetFileUpdate($mergedTargetFile, $extFiles, $hookFiles, $apiFiles, $targetExtPaths, $mainTargetFile)) return $mergedTargetFile;
@@ -2491,8 +2507,7 @@ class baseRouter
if(empty($moduleName)) $moduleName = $this->moduleName;
if(empty($appName)) $appName = $this->appName;
global $loadedTargets;
if(isset($loadedTargets[$class][$appName][$moduleName])) return $loadedTargets[$class][$appName][$moduleName];
if(isset(self::$loadedTargets[$class][$appName][$moduleName])) return self::$loadedTargets[$class][$appName][$moduleName];
$targetFile = $this->setTargetFile($moduleName, $appName, $class);
@@ -2516,14 +2531,14 @@ class baseRouter
/**
* 因为zen继承自control,tao继承自model,构造函数里会调用loadTarget方法,赋默认值值防止递归调用。
*/
if($class == 'zen' || $class == 'tao') $loadedTargets[$class][$appName][$moduleName] = false;
if($class == 'zen' || $class == 'tao') self::$loadedTargets[$class][$appName][$moduleName] = false;
/**
* 初始化target 对象并返回。
* Init the target object and return it.
*/
$target = new $targetClass($appName);
$loadedTargets[$class][$appName][$moduleName] = $target;
self::$loadedTargets[$class][$appName][$moduleName] = $target;
return $target;
}
@@ -2607,6 +2622,7 @@ class baseRouter
/* Remove these three params. */
unset($passedParams['onlybody']);
unset($passedParams['tid']);
unset($passedParams['zin']);
unset($passedParams['HTTP_X_REQUESTED_WITH']);
/* Check params from URL. */
@@ -2635,7 +2651,7 @@ class baseRouter
{
if($defaultItem['default'] === '_NOT_SET') $this->triggerError("The param '$key' should pass value. ", __FILE__, __LINE__, true);
$defaultParams[$key] = $defaultItem['default'];
$defaultParams[$key] = helper::convertType(strip_tags((string) $defaultItem['default']), $defaultItem['type']);
}
$i ++;
}
@@ -2708,9 +2724,7 @@ class baseRouter
$className = strtolower($className);
/* 搜索$coreLibRoot(Search in $coreLibRoot) */
$classFile = $this->coreLibRoot . $className;
if(is_dir($classFile)) $classFile .= DS . $className;
$classFile .= '.class.php';
$classFile = $this->coreLibRoot . $className . DS . $className . '.class.php';
if(!helper::import($classFile)) $this->triggerError("class file $classFile not found", __FILE__, __LINE__, true);
/* 如果是静态调用,则返回(If static, return) */
@@ -2774,6 +2788,10 @@ class baseRouter
*/
public function loadModuleConfig(string $moduleName, string $appName = '')
{
if(isset(self::$loadedConfigs[$moduleName])) return false;
self::$loadedConfigs[$moduleName] = $moduleName;
global $config;
if($config and (!isset($config->$moduleName) or !is_object($config->$moduleName))) $config->$moduleName = new stdclass();
@@ -2786,9 +2804,9 @@ class baseRouter
/* 加载每一个配置文件。Load every config file. */
foreach($configFiles as $configFile)
{
if(in_array($configFile, self::$loadedConfigs)) continue;
if(isset(self::$loadedConfigs[$configFile])) continue;
if(is_string($configFile) && file_exists($configFile)) include $configFile;
self::$loadedConfigs[] = $configFile;
self::$loadedConfigs[$configFile] = $configFile;
}
/* 加载数据库中与本模块相关的配置项。Merge from the db configs. */
@@ -2915,30 +2933,35 @@ class baseRouter
* 加载语言文件,返回全局$lang对象。
* Load lang and return it as the global lang object.
*
* @param string $moduleName the module name
* @param string $moduleName the module name
* @param string $appName the app name
* @access public
* @return bool|object the lang object or false.
* @return object the lang object
*/
public function loadLang(string $moduleName, string $appName = ''): bool|object
public function loadLang(string $moduleName, string $appName = ''): object
{
/* 计算最终要加载的语言文件。 Get the lang files to be loaded. */
$langFilesToLoad = $this->getMainAndExtFiles($moduleName, $appName, 'lang');
if(empty($langFilesToLoad)) return false;
/* 加载语言文件。Load lang files. */
global $lang;
if(!is_object($lang)) $lang = new language();
if(!isset($lang->$moduleName)) $lang->$moduleName = new stdclass();
if(isset(self::$loadedLangs[$moduleName])) return $lang;
self::$loadedLangs[$moduleName] = $moduleName;
/* 计算最终要加载的语言文件。 Get the lang files to be loaded. */
$langFilesToLoad = $this->getMainAndExtFiles($moduleName, $appName, 'lang');
if(empty($langFilesToLoad)) return $lang;
foreach($langFilesToLoad as $langFile)
{
if(in_array($langFile, self::$loadedLangs)) continue;
if(isset(self::$loadedLangs[$langFile])) continue;
include $langFile;
self::$loadedLangs[] = $langFile;
self::$loadedLangs[$langFile] = $langFile;
}
$this->lang = $lang;
return $lang;
}
@@ -3103,7 +3126,11 @@ class baseRouter
* */
if(!function_exists('error_get_last')) return;
$error = error_get_last();
if($error) $this->saveError($error['type'], $error['message'], $error['file'], $error['line']);
if($error)
{
$this->saveError($error['type'], $error['message'], $error['file'], $error['line']);
if(!empty($this->config->debug) && (!is_dir($this->logRoot) || !is_writable($this->logRoot))) helper::end('ERROR: ' . $error['message']);
}
}
/**
+147 -4
View File
@@ -236,7 +236,7 @@ class control extends baseControl
if(!class_exists($extensionClass)) return false;
/* 实例化扩展类。Create an instance of the extension class and return it. */
$extensionObject = new $extensionClass;
$extensionObject = new $extensionClass();
if($type == 'model') $extensionClass = str_replace(ucfirst($type), '', $extensionClass);
$this->$extensionClass = $extensionObject;
$this->$extensionClass->view = $this->view;
@@ -482,10 +482,149 @@ class control extends baseControl
$moduleName = $moduleName ?: $this->app->getModuleName();
$methodName = $methodName ?: $this->app->getMethodName();
$fields = $this->loadModel('flow')->printFields($moduleName, $methodName, $object, $type, $extras);
if(!$print) return $fields;
echo $fields;
$this->loadModel('flow');
if($type == 'html')
{
parse_str($extras, $result);
$html = $this->flow->buildExtendHtmlValue($object, zget($result, 'position', 'info'));
$html .= $this->appendExtendCssAndJS($moduleName, $methodName);
}
else
{
ob_start();
$this->flow->printFields($moduleName, $methodName, $object, $type, $extras);
$html = ob_get_contents();
ob_end_clean();
}
if(!$print) return $html;
echo $html;
}
/**
* 追加工作流新增的字段,给formGridPanel组件使用。
* append workflow fields to form.
*
* @param zin\fieldList $fields
* @param string $moduleName
* @param string $methodName
* @access public
* @return zin\fieldList
*/
public function appendExtendFields(zin\fieldList $fields, string $moduleName = '', string $methodName = ''): zin\fieldList
{
if($this->config->edition == 'open') return $fields;
$moduleName = $moduleName ? $moduleName : $this->app->getModuleName();
$methodName = $methodName ? $moduleName : $this->app->getMethodName();
$flow = $this->loadModel('workflow')->getByModule($moduleName);
if(!$flow) return $fields;
$action = $this->loadModel('workflowaction')->getByModuleAndAction($flow->module, $methodName);
if(!$action || $action->extensionType != 'extend') return $fields;
$fieldList = $this->workflowaction->getFields($flow->module, $action->action);
return $this->loadModel('flow')->buildFormFields($fields, $fieldList);
}
/**
* 追加工作流配置的js和css到页面上。
* append workflow js and css to form.
*
* @param string $moduleName
* @param string $methodName
* @access public
* @return string
*/
public function appendExtendCssAndJS(string $moduleName = '', string $methodName = ''): string
{
if($this->config->edition == 'open') return '';
$moduleName = $moduleName ? $moduleName : $this->app->getModuleName();
$methodName = $methodName ? $methodName : $this->app->getMethodName();
$flow = $this->loadModel('workflow')->getByModule($moduleName);
if(!$flow) return '';
$action = $this->loadModel('workflowaction')->getByModuleAndAction($flow->module, $methodName);
if(!$action || $action->extensionType != 'extend') return '';
$fieldList = $this->workflowaction->getFields($flow->module, !empty($action->action) ? $action->action: '');
$html = '';
if(!empty($flow->css)) $html .= "<style>$flow->css</style>";
if(!empty($action->css)) $html .= "<style>$action->css</style>";
$html .= $this->loadModel('flow')->getFormulaScript($moduleName, $action, $fieldList);
if(!empty($action->linkages)) $html .= $this->flow->getLinkageScript($action, $fieldList);
if(!empty($flow->js)) $html .= "<script>$flow->js</script>";
if(!empty($action->js)) $html .= "<script>$action->js</script>";
return $html;
}
/**
* 追加工作流新增的字段,给非formGridPanel组件使用。
* append workflow field to form.
*
* @param string $position info|basic
* @param object $object
* @param string $moduleName
* @param string $methodName
* @access public
* @return array
*/
public function appendExtendForm(string $position = 'info', object $object = null, string $moduleName = '', string $methodName = ''): array
{
if($this->config->edition == 'open') return array();
$moduleName = $moduleName ? $moduleName : $this->app->getModuleName();
$methodName = $methodName ? $moduleName : $this->app->getMethodName();
if(!$object) $object = new stdclass();
$this->loadModel('flow');
$this->loadModel('workflowfield');
$flow = $this->loadModel('workflow')->getByModule($moduleName);
if(!$flow) return array();
$action = $this->loadModel('workflowaction')->getByModuleAndAction($flow->module, $methodName);
if(!$action || $action->extensionType != 'extend') return array();
$wrapControl = array('textarea', 'richtext', 'file');
$fieldList = $this->workflowaction->getFields($flow->module, $action->action);
$layouts = $this->loadModel('workflowlayout')->getFields($moduleName, $methodName);
$notEmptyRule = $this->loadModel('workflowrule')->getByTypeAndRule('system', 'notempty');
if($layouts)
{
$allFields = $this->dao->select('*')->from(TABLE_WORKFLOWFIELD)->where('module')->eq($moduleName)->fetchAll('field');
foreach($fieldList as $fieldName => $field)
{
if(isset($allFields[$fieldName])) $field->default = $allFields[$fieldName]->default;
}
foreach($fieldList as $key => $field)
{
if($field->buildin || !$field->show || !isset($layouts[$field->field]) || (!empty($field->position) && $position != $field->position)) unset($fieldList[$key]);
if((is_numeric($field->default) || $field->default) && empty($field->defaultValue)) $field->defaultValue = $field->default;
if(empty($object->{$field->field})) $object->{$field->field} = $field->defaultValue;
if(in_array($field->type, $this->config->workflowfield->numberTypes)) $field = $this->workflowfield->processNumberField($field);
$field->required = $field->readonly || ($notEmptyRule && strpos(",$field->rules,", ",{$notEmptyRule->id},") !== false);
$field->control = $this->flow->buildFormControl($field);
$field->items = $field->options ? array_filter($field->options) : null;
$field->value = !empty($object) ? zget($object, $field->field, '') : $defaultValue;
$field->width = $field->width != 'auto' ? $field->width : 'full';
}
return $fieldList;
}
return array();
}
/**
@@ -512,6 +651,10 @@ class control extends baseControl
public function printViewFile(string $viewFile): bool|string
{
if(!file_exists($viewFile)) return false;
if(substr($viewFile, -4) != '.php') return false;
if(strpos($viewFile, '..') !== false) return false;
if(strpos($viewFile, '/view/') === false) return false;
if(strpos($viewFile, $this->app->getModuleRoot()) !== 0 && strpos($viewFile, $this->app->getExtensionRoot()) !== 0) return false;
$currentPWD = getcwd();
chdir(dirname($viewFile));
+55 -9
View File
@@ -494,7 +494,7 @@ function initPageEntity(object $object): array
* @access public
* @return array
*/
function initTableData(array $items, array &$fieldList, object $model = null): array
function initTableData(array $items, array &$fieldList, object $model = null, string $moduleName = ''): array
{
if(!empty($_GET['orderBy']) && strpos($_GET['orderBy'], '-') !== false) list($orderField, $orderValue) = explode('_', $_GET['orderBy']);
if(!empty($orderField) && !empty($orderValue) && !empty($fieldList[$orderField]))
@@ -542,12 +542,14 @@ function initTableData(array $items, array &$fieldList, object $model = null): a
foreach($items as $item)
{
$item->actions = array();
$actionList = zget($fieldList['actions'], 'list', array());
foreach($fieldList['actions']['menu'] as $actionKey => $actionMenu)
{
if(isset($actionMenu['other']))
{
$currentActionMenu = $actionMenu[0];
initItemActions($item, $currentActionMenu, zget($fieldList['actions'], 'list', array()), $model);
initItemActions($item, $currentActionMenu, $actionList, $model);
$otherActionMenus = $actionMenu['other'];
$otherAction = '';
@@ -556,24 +558,26 @@ function initTableData(array $items, array &$fieldList, object $model = null): a
$otherActions = explode('|', $otherActionMenu);
foreach($otherActions as $otherActionName)
{
if(!checkOtherPriv(zget($actionList, $otherActionName, array()), $otherActionName, $item, $model)) continue;
if(in_array($otherActionName, array_column($item->actions, 'name'))) continue;
if(method_exists($model, 'isClickable') && !$model->isClickable($item, $otherActionName)) $otherAction .= '-';
$otherAction .= $otherActionName . ',';
}
}
$item->actions[] = 'other:' . $otherAction;
if($otherAction) $item->actions[] = 'other:' . $otherAction;
}
elseif($actionKey === 'more')
{
$moreAction = '';
foreach($actionMenu as $moreActionName)
{
if(!checkOtherPriv(zget($actionList, $moreActionName, array()), $moreActionName, $item, $model)) continue;
if(method_exists($model, 'isClickable') && !$model->isClickable($item, $moreActionName)) $moreAction .= '-';
$moreAction .= $moreActionName . ',';
}
$item->actions[] = 'more:' . $moreAction;
if($moreAction) $item->actions[] = 'more:' . $moreAction;
}
elseif(is_array($actionMenu)) // Two or more grups.
{
@@ -602,6 +606,26 @@ function initTableData(array $items, array &$fieldList, object $model = null): a
return array_values($items);
}
/**
* Check other action priv.
*
* @param array $actionList
* @param string $actionName
* @param object $item
* @param object $model
* @access public
* @return bool
*/
function checkOtherPriv(array $actionConfig, string $action, object $item, object $model)
{
$module = $model->getModuleName();
if(!empty($actionConfig['url']['module']) && $module != $actionConfig['url']['module']) $module = $actionConfig['url']['module'];
$method = $action;
if(!empty($actionConfig['url']['method']) && $method != $actionConfig['url']['method']) $method = $actionConfig['url']['method'];
return common::hasPriv($module, $method, $item);
}
/**
* Set the parent property of the data.
*
@@ -613,10 +637,10 @@ function setParent(array $items)
{
foreach($items as $item)
{
$item->isParent = false;
if(!isset($item->parent) || !is_int($item->parent)) continue;
if(isset($item->isParent)) continue;
/* Set parent attribute. */
$item->isParent = false;
if(isset($item->parent) && $item->parent == -1)
{
/* When the parent is -1, the hierarchical structure is displayed incorrectly. */
@@ -645,7 +669,7 @@ function initTableActions(array &$fieldList, string $actionMenu): void
if(!isset($fieldList['actions']['list'][$action])) continue;
$actionConfig = $fieldList['actions']['list'][$action];
$actionConfig['text'] = '';
if(!empty($actionConfig['icon'])) $actionConfig['text'] = '';
if(!empty($actionConfig['url']['module']) && !empty($actionConfig['url']['method']))
{
@@ -653,7 +677,7 @@ function initTableActions(array &$fieldList, string $actionMenu): void
$method = $actionConfig['url']['method'];
$params = !empty($actionConfig['url']['params']) ? $actionConfig['url']['params'] : array();
$actionConfig['url'] = helper::createLink($module, $method, $params);
$actionConfig['url'] = helper::createLink($module, $method, $params, '', !empty($actionConfig['url']['onlybody']));
}
$fieldList['actions']['actionsMap'][$action] = $actionConfig;
@@ -693,7 +717,11 @@ function initItemActions(object &$item, string $actionMenu, array $actionList, o
if(!empty($actionConfig['url']['module']) && $module != $actionConfig['url']['module'])
{
$module = $actionConfig['url']['module'];
if(!$notLoadModel) $model = $app->control->loadModel($module);
if(!$notLoadModel)
{
$rawModule = $module == 'projectbuild' ? 'build' : $module;
$model = $app->control->loadModel($rawModule);
}
}
$method = $action;
@@ -741,3 +769,21 @@ function getVisions(): array
$visionList = $lang->visionList;
return array_intersect_key($visionList, $visions);
}
/**
* Save any message with any type to the php log file which prefix with 'php.<today>'.
*
* @param mixed $message
* @param string $file
* @param int $line
* @return void
*/
function debug($message = '', $file = 'undefined', $line = 0)
{
if(!is_string($message)) $message = (string)json_encode($message, JSON_PRETTY_PRINT);
if(empty($file) || $file == 'undefined') $message .= (new Exception())->getTraceAsString();
global $app;
$app->saveError(E_USER_WARNING, $message, $file, $line);
}
+45 -20
View File
@@ -122,13 +122,15 @@ class router extends baseRouter
* @param string $moduleName the module name
* @param string $appName the app name
* @access public
* @return bool|object the lang object or false.
* @return object the lang object or false.
*/
public function loadLang($moduleName, $appName = ''): bool|object
public function loadLang($moduleName, $appName = ''): object
{
global $lang;
if(!is_object($lang)) $lang = new language();
if(isset(self::$loadedModules[$moduleName])) return $lang;
/* Set productCommon and projectCommon for flow. */
if($moduleName == 'common') $this->setCommonLang();
@@ -298,7 +300,7 @@ class router extends baseRouter
$config->executionLink = 'execution-task';
/* Get user preference. */
$account = $this->session->user->account ?? '';
$account = $_SESSION['user']->account ?? '';
$userSetting = array();
if($this->dbh and !empty($this->config->db->name) and $account)
{
@@ -350,20 +352,21 @@ class router extends baseRouter
$lang->ERCommon = $ERPairs[$config->URSR] ?? reset($ERPairs);
$lang->URCommon = $URPairs[$config->URSR] ?? reset($URPairs);
$lang->SRCommon = $SRPairs[$config->URSR] ?? reset($SRPairs);
}
/* Replace common lang. */
$customMenus = array();
try
{
$customMenus = $this->dbQuery('SELECT * FROM' . TABLE_LANG . "WHERE `module`='common' AND `lang`='{$this->clientLang}' AND `section`='' AND `vision`='{$config->vision}'")->fetchAll();
}
catch(PDOException){}
foreach($customMenus as $menu)
{
/* Modified the language item of dev story-related navigation, which will only affect users whose personalized value is the same as the story concept default value.*/
if(in_array($menu->key, array('ERCommon', 'URCommon', 'SRCommon')) && $URSR != $config->URSR) continue;
if(isset($lang->{$menu->key})) $lang->{$menu->key} = $menu->value;
/* Replace common lang. */
$customMenus = array();
try
{
$customMenus = $this->dbQuery('SELECT * FROM' . TABLE_LANG . "WHERE `module`='common' AND `lang`='{$this->clientLang}' AND `section`='' AND `vision`='{$config->vision}'")->fetchAll();
}
catch(PDOException){}
foreach($customMenus as $menu)
{
/* Modified the language item of dev story-related navigation, which will only affect users whose personalized value is the same as the story concept default value.*/
if(in_array($menu->key, array('ERCommon', 'URCommon', 'SRCommon')) && $URSR != $config->URSR) continue;
if(isset($lang->{$menu->key})) $lang->{$menu->key} = $menu->value;
}
}
}
}
@@ -402,7 +405,10 @@ class router extends baseRouter
*/
public function loadModuleConfig($moduleName, $appName = '')
{
$extConfigPath = array();
if(isset(self::$loadedConfigs[$moduleName])) return false;
self::$loadedConfigs[$moduleName] = $moduleName;
global $config;
if($config and (!isset($config->$moduleName) or !is_object($config->$moduleName))) $config->$moduleName = new stdclass();
@@ -419,6 +425,7 @@ class router extends baseRouter
$configDirFiles = helper::ls($this->getModulePath($appName, $moduleName) . DS . 'config', '.php');
/* 查找扩展配置文件。Get extension config files. */
$extConfigPath = array();
if($config->framework->extensionLevel > 0) $extConfigPath = $this->getModuleExtPath($moduleName, 'config');
if($config->framework->extensionLevel >= 1)
{
@@ -437,9 +444,9 @@ class router extends baseRouter
/* 加载每一个配置文件。Load every config file. */
foreach($configFiles as $configFile)
{
if(in_array($configFile, self::$loadedConfigs)) continue;
if(isset(self::$loadedConfigs[$configFile])) continue;
if(file_exists($configFile)) include $configFile;
self::$loadedConfigs[] = $configFile;
self::$loadedConfigs[$configFile] = $configFile;
}
/* 加载数据库中与本模块相关的配置项。Merge from the db configs. */
@@ -757,8 +764,26 @@ class router extends baseRouter
*/
public function checkInstalled()
{
if(!$this->config->installed) return false;
if(($this->config->inContainer || $this->config->inQuickon) && !$this->getInstalledVersion()) return false;
return isset($this->config->installed) && $this->config->installed;
return true;
}
/**
* 获取禅道版本在不同语言下的显示名称。
* Get the display name of the ZenTaoPMS version in different language.
*
* @param string $version 20.0|biz9.0|max5.0|ipd2.0
* @return string
*/
public function getVersionName($version = '')
{
global $config, $lang;
$editionName = $config->edition === 'open' ? $lang->pmsName : $lang->{$config->edition . 'Name'};
$versionName = empty($version) ? $config->version : $version;
$versionName = $editionName . str_replace(array('max', 'biz', 'ipd'), '', $versionName);
$versionName = ($config->inQuickon ? $lang->devopsPrefix : '') . $versionName;
return $versionName;
}
}