zentaopms/framework/model.class.php
2023-05-16 10:47:08 +08:00

396 lines
14 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
/**
* ZenTaoPHP的model类。
* The model class file of ZenTaoPHP framework.
*
* The author disclaims copyright to this source code. In place of
* a legal notice, here is a blessing:
*
* May you do good and not evil.
* May you find forgiveness for yourself and forgive others.
* May you share freely, never taking more than you give.
*/
/**
* model基类。
* The base class of model.
*
* @package framework
*/
include dirname(__FILE__) . '/base/model.class.php';
class model extends baseModel
{
/**
* 企业版部分功能是从然之合并过来的。ZDOO代码中调用loadModel方法时传递了一个非空的appName在禅道中会导致错误。
* 调用父类的loadModel方法来避免这个错误。
* Some codes merged from ZDOO called the function loadModel with a non-empty appName which causes an error in zentao.
* Call the parent function with empty appName to avoid this error.
*
* @param string $moduleName 模块名如果为空使用当前模块。The module name, if empty, use current module's name.
* @param string $appName 应用名如果为空使用当前应用。The app name, if empty, use current app's name.
* @access public
* @return object|bool the model object or false if model file not exists.
*/
public function loadModel($moduleName, $appName = '')
{
return parent::loadModel($moduleName);
}
/**
* 企业版部分功能是从然之合并过来的。ZDOO代码中调用loadTao方法时传递了一个非空的appName在禅道中会导致错误。
* 调用父类的loadTao方法来避免这个错误。
* Some codes merged from ZDOO called the function loadTao with a non-empty appName which causes an error in zentao.
* Call the parent function with empty appName to avoid this error.
*
* @param string $moduleName 模块名如果为空使用当前模块。The module name, if empty, use current module's name.
* @param string $appName 应用名如果为空使用当前应用。The app name, if empty, use current app's name.
* @access public
* @return object|bool the model object or false if model file not exists.
*/
public function loadTao($moduleName, $appName = '')
{
return parent::loadTao($moduleName);
}
/**
* 删除记录
* Delete one record.
*
* @param string $table the table name
* @param string $id the id value of the record to be deleted
* @access public
* @return bool
*/
public function delete($table, $id)
{
$this->dao->update($table)->set('deleted')->eq(1)->where('id')->eq($id)->exec();
$object = preg_replace('/^' . preg_quote($this->config->db->prefix) . '/', '', trim($table, '`'));
$this->loadModel('action')->create($object, $id, 'deleted', '', $extra = ACTIONMODEL::CAN_UNDELETED);
return true;
}
/**
* Build menu of a module.
*
* @param string $moduleName
* @param string $methodName
* @param string $params
* @param object $data
* @param string $type
* @param string $icon
* @param string $target
* @param string $class
* @param bool $onlyBody
* @param string $misc
* @param string $title
* @param bool $returnHtml
* @access public
* @return string
*/
public function buildMenu($moduleName, $methodName, $params, $data, $type = 'view', $icon = '', $target = '', $class = '', $onlyBody = false, $misc = '' , $title = '', $returnHtml = true)
{
if(strpos($moduleName, '.') !== false) list($appName, $moduleName) = explode('.', $moduleName);
if(strpos($methodName, '_') !== false && strpos($methodName, '_') > 0) list($module, $method) = explode('_', $methodName);
if(empty($module)) $module = $moduleName;
if(empty($method)) $method = $methodName;
static $actions = array();
if(isset($this->config->bizVersion))
{
if(empty($actions[$moduleName]))
{
$actions[$moduleName] = $this->dao->select('*')->from(TABLE_WORKFLOWACTION)
->where('module')->eq($moduleName)
->andWhere('buildin')->eq('1')
->andWhere('status')->eq('enable')
->beginIF(!empty($this->config->vision))->andWhere('vision')->eq($this->config->vision)->fi()
->fetchAll('action');
}
}
$enabled = true;
if(!empty($actions) and isset($actions[$moduleName][$methodName]))
{
$action = $actions[$moduleName][$methodName];
if($action->extensionType == 'override') return $this->loadModel('flow')->buildActionMenu($moduleName, $action, $data, $type);
$conditions = json_decode($action->conditions);
if($conditions and $action->extensionType == 'extend')
{
if($icon != 'copy' and $methodName != 'create') $title = $action->name;
if($conditions) $enabled = $this->loadModel('flow')->checkConditions($conditions, $data);
}
else
{
if(method_exists($this, 'isClickable')) $enabled = $this->isClickable($data, $method, $module);
}
}
else
{
if(method_exists($this, 'isClickable')) $enabled = $this->isClickable($data, $method, $module);
}
if(!$returnHtml) return $enabled;
$html = '';
$type = $type == 'browse' ? 'list' : 'button';
$html = common::buildIconButton($module, $method, $params, $data, $type, $icon, $target, $class, $onlyBody, $misc, $title, '', $enabled);
return $html;
}
/**
* Build menu of actions created by workflow action.
*
* @param string $module
* @param int $data
* @param string $type browse | view
* @param string $show direct | dropdownlist
* @access public
* @return string
*/
public function buildFlowMenu($module, $data, $type = 'browse', $show = '')
{
if(!isset($this->config->bizVersion)) return '';
$moduleName = $module;
if(strpos($module, '.') !== false) list($appName, $moduleName) = explode('.', $module);
static $actions;
static $relations;
if(empty($actions))
{
$actions = $this->dao->select('*')->from(TABLE_WORKFLOWACTION)
->where('module')->eq($moduleName)
->andWhere('buildin')->eq('0')
->andWhere('status')->eq('enable')
->beginIF(!empty($this->config->vision))->andWhere('vision')->eq($this->config->vision)->fi()
->orderBy('order_asc')
->fetchAll();
}
if(empty($relations)) $relations = $this->dao->select('next, actions')->from(TABLE_WORKFLOWRELATION)->where('prev')->eq($moduleName)->fetchPairs();
$this->loadModel('flow');
$approvalProgressMenu = '';
if($type == 'view' && !empty($this->config->openedApproval) && commonModel::hasPriv('approval', 'progress'))
{
$flow = $this->loadModel('workflow', 'flow')->getByModule($moduleName);
if($flow->approval == 'enabled' && !empty($data->approval))
{
$extraClass = strpos(',testsuite,build,release,productplan,', ",{$moduleName},") !== false ? 'btn-link' : '';
$approvalProgressMenu .= "<div class='divider'></div>";
$approvalProgressMenu .= baseHTML::a(helper::createLink('approval', 'progress', "approvalID={$data->approval}", '', true), $this->lang->flow->approvalProgress, "class='btn {$extraClass} iframe'");
}
}
$menu = '';
if($show)
{
foreach($actions as $action)
{
if(strpos($action->position, $type) === false || $action->show != $show) continue;
$menu .= $this->flow->buildActionMenu($moduleName, $action, $data, $type, $relations);
}
if($approvalProgressMenu) $menu .= $approvalProgressMenu;
}
else
{
$dropdownMenu = '';
foreach($actions as $action)
{
if(strpos($action->position, $type) === false) continue;
if($type == 'view' || $action->show == 'direct') $menu .= $this->flow->buildActionMenu($moduleName, $action, $data, $type, $relations);
if($type == 'browse' && $action->show == 'dropdownlist') $dropdownMenu .= $this->flow->buildActionMenu($moduleName, $action, $data, $type, $relations);
}
if($approvalProgressMenu) $menu .= $approvalProgressMenu;
if($type == 'browse' && $dropdownMenu)
{
$menu .= "<div class='dropdown'><a href='javascript:;' data-toggle='dropdown'>{$this->lang->more}<span class='caret'> </span></a>";
$menu .= "<ul class='dropdown-menu pull-right'>{$dropdownMenu}</ul></div>";
}
}
return $menu;
}
/**
* Process status of an object according to its subStatus.
*
* @param string $module product | release | story | project | task | bug | testcase | testtask | feedback
* @param object $record a record of above modules.
* @access public
* @return string
*/
public function processStatus($module, $record)
{
if(!isset($this->config->bizVersion) or empty($record->subStatus)) return zget($this->lang->$module->statusList, $record->status);
return $this->loadModel('workflowfield')->processSubStatus($module, $record);
}
/**
* Process workflow export data.
*
* @param object $data
* @access public
* @return object
*/
public function processExportData($data)
{
if(!isset($this->config->bizVersion)) return $data;
return $this->loadModel('workflowfield')->processExportData($data);
}
/**
* Process workflow export options.
*
* @param object $data
* @access public
* @return object
*/
public function processExportOptions($data)
{
if(!isset($this->config->bizVersion)) return $data;
return $this->loadModel('workflowfield')->processExportOptions($data);
}
/**
* Process workflow import data.
*
* @param object $data
* @access public
* @return object
*/
public function processImportData($data)
{
if(!isset($this->config->bizVersion)) return $data;
return $this->loadModel('workflowfield')->processImportData($data);
}
/**
* Get flow extend fields.
*
* @access public
* @return array
*/
public function getFlowExtendFields()
{
if(!isset($this->config->bizVersion)) return array();
return $this->loadModel('flow')->getExtendFields($this->app->getModuleName(), $this->app->getMethodName());
}
/**
* Set workflow export fields.
*
* @access public
* @return string
*/
public function getFlowExportFields()
{
if(!isset($this->config->bizVersion)) return array();
return $this->loadModel('workflowfield')->getExportFields($this->app->getModuleName());
}
/**
* Execute Hooks
*
* @param int $objectID
* @access public
* @return void
*/
public function executeHooks($objectID)
{
if(!isset($this->config->bizVersion)) return false;
$moduleName = $this->app->getModuleName();
$methodName = $this->app->getMethodName();
$action = $this->loadModel('workflowaction')->getByModuleAndAction($moduleName, $methodName);
if(empty($action) or $action->extensionType == 'none') return false;
$this->loadModel('file');
if($this->post->uid) $this->file->updateObjectID($this->post->uid, $objectID, $moduleName);
$fields = $this->workflowaction->getFields($moduleName, $action->action, false);
foreach($fields as $field)
{
if($field->control == 'file' && $field->show && !$field->readonly)
{
$this->file->saveUpload($moduleName, $objectID, $field->field, $field->field, $field->field);
}
}
$flow = $this->loadModel('workflow')->getByModule($moduleName);
if($flow && $action) return $this->loadModel('workflowhook')->execute($flow, $action, $objectID);
}
/**
* Call the functions declared in the tao files.
*
* @param string $method
* @param array $arguments
* @access public
* @return mixed
*/
public function __call($method, $arguments)
{
$moduleName = $this->getModuleName();
$taoClass = $moduleName . 'Tao';
if(is_callable(array($this->{$taoClass}, $method))) return call_user_func_array(array($this->{$taoClass}, $method), $arguments);
$this->app->triggerError("the module {$moduleName} has no {$method} method", __FILE__, __LINE__, $exit = true);
}
/**
* Call the static functions declared in the tao files.
*
* @param string $method
* @param array $arguments
* @access public
* @return mixed
*/
public static function __callStatic($method, $arguments)
{
global $app;
$moduleName = strtolower(get_called_class());
preg_match_all('/^(ext)?(\w+)model/', $moduleName, $matches);
if(isset($matches[2][0]))
{
$moduleName = $matches[2][0];
}
else
{
preg_match_all('/^(ext)?(\w+)tao/', $moduleName, $matches);
if(isset($matches[2][0])) $moduleName = $matches[2][0];
}
$modelClass = 'ext' . $moduleName . 'Model';
if(method_exists($modelClass, $method)) return call_user_func_array("{$modelClass}::{$method}", $arguments);
$taoClass = 'ext' . $moduleName . 'Tao';
if(method_exists($taoClass, $method)) return call_user_func_array("{$taoClass}::{$method}", $arguments);
$taoClass = $moduleName . 'Tao';
if(method_exists($taoClass, $method)) return call_user_func_array("{$taoClass}::{$method}", $arguments);
$app->triggerError("the module {$moduleName} has no {$method} method", __FILE__, __LINE__, $exit = true);
}
}