| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650 |
- <?php /**
- * 禅道API的entry类。
- * The entry class file of ZenTao API.
- *
- * @package 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.
- */
- class entry extends baseEntry
- {
- public function __construct()
- {
- parent::__construct();
- if($this->app->action == 'options') throw EndResponseException::create($this->send(204));
- if(!$this->loadModel('user')->isLogon()) throw EndResponseException::create($this->sendError(401, 'Unauthorized'));
- $this->dao = $this->loadModel('common')->dao;
- }
- }
- /**
- * 禅道API的baseEntry类。
- * The baseEntry class file of ZenTao API.
- *
- */
- class baseEntry
- {
- /**
- * 全局对象 $app。
- * The global $app object.
- *
- * @var object
- * @access public
- */
- public $app;
- /**
- * 语言项 $lang。
- * The global $app object.
- *
- * @var object
- * @access public
- */
- public $lang;
- /**
- * 提交的POST数据
- * The decoded request body.
- *
- * @var object
- * @access public
- */
- public $requestBody;
- /**
- * 构造方法。
- * The construct function.
- *
- * @access public
- * @return void
- */
- public function __construct()
- {
- global $app, $config, $lang;
- $this->app = $app;
- $this->config = $config;
- $this->lang = $lang;
- $this->parseRequestBody();
- }
- /**
- * 获取请求数据(POST PUT)
- * Get request data(POST or PUT)
- *
- * @param string $key
- * @access public
- * @return mixed
- */
- public function request($key, $defaultValue = '')
- {
- if(isset($this->requestBody->$key)) return $this->requestBody->$key;
- return $defaultValue;
- }
- /**
- * 获取请求参数
- * Get request params.
- *
- * @param string $key
- * @access public
- * @return mixed
- */
- public function param($key, $defaultValue = '')
- {
- if(isset($_GET[$key])) return $_GET[$key];
- return $defaultValue;
- }
- /**
- * 设置请求参数
- * Set request param.
- *
- * @param string|array $key if is array, set params by its key-value pairs.
- * @access public
- * @return void
- */
- public function setParam($key, $value = null)
- {
- if(is_array($key))
- {
- foreach($key as $k => $v) $_GET[$k] = $v;
- return;
- }
- $_GET[$key] = $value;
- }
- /**
- * 解析请求数据
- * Parse body of request data.
- *
- * @access public
- * @return void
- */
- private function parseRequestBody()
- {
- $this->requestBody = new stdClass();
- if($this->app->action == 'post' or $this->app->action == 'put')
- {
- $requestBody = file_get_contents("php://input");
- if($requestBody) $this->requestBody = json_decode($requestBody);
- }
- }
- /**
- * 发送请求的响应数据
- * Send response data
- *
- * @param int $code
- * @param mixed $data
- * @access public
- * @return string
- */
- public function send($code, $data = '')
- {
- return helper::response($data, $code);
- }
- /**
- * 发送错误信息
- * Send error response
- *
- * @param int $code
- * @param string|object|array $msg
- * @access public
- * @return string
- */
- public function sendError($code, $msg)
- {
- $response = new stdclass();
- $response->error = $msg;
- return $this->send($code, $response);
- }
- /**
- * 发送成功提示
- * Send success response
- *
- * @param int $code
- * @param string $msg
- * @access public
- * @return string
- */
- public function sendSuccess($code, $msg)
- {
- $response = new stdclass();
- $response->message = $msg;
- return $this->send($code, $response);
- }
- /**
- * Send 400 response.
- *
- * @param string message
- * @access public
- * @return string
- */
- public function send400($message = 'error')
- {
- return $this->sendError(400, $message);
- }
- /**
- * Send 404 response.
- *
- * @access public
- * @return string
- */
- public function send404()
- {
- return $this->sendError(404, '404 Not found');
- }
- /**
- * 加载禅道的控制器类
- * Load controller of zentaopms
- *
- * @param string $moduleName
- * @param string $methodName
- * @access public
- * @return object
- */
- public function loadController($moduleName, $methodName)
- {
- ob_start();
- global $app;
- if(!class_exists($moduleName) and !class_exists("my$moduleName"))
- {
- $app->setModuleName($moduleName);
- $app->setMethodName($methodName);
- $app->viewType = 'json';
- /* Check user permission. */
- $this->checkPriv();
- $app->setControlFile();
- $app->importControlFile();
- }
- /*
- * 设置control的类名。
- * Set the class name of the control.
- **/
- $className = class_exists("my$moduleName") ? "my$moduleName" : $moduleName;
- if(!class_exists($className)) $app->triggerError("the control $className not found", __FILE__, __LINE__, true);
- $controller = new $className();
- $controller->viewType = 'json';
- $app->control = $controller;
- return $controller;
- }
- /**
- * 加载指定模块的model文件。
- * Load the model file of one module.
- *
- * @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 如果没有model文件,返回false,否则返回model对象。If no model file, return false, else return the model object.
- */
- public function loadModel($moduleName = '', $appName = '')
- {
- if(empty($moduleName)) $moduleName = $this->app->moduleName;
- if(empty($appName)) $appName = $this->app->appName;
- global $loadedModels;
- if(isset($loadedModels[$appName][$moduleName]))
- {
- $this->$moduleName = $loadedModels[$appName][$moduleName];
- $this->dao = $this->$moduleName->dao;
- return $this->$moduleName;
- }
- $modelFile = $this->app->setModelFile($moduleName, $appName);
- /**
- * 如果没有model文件,尝试加载config配置信息。
- * If no model file, try load config.
- */
- if(!helper::import($modelFile))
- {
- $this->app->loadModuleConfig($moduleName, $appName);
- $this->app->loadLang($moduleName, $appName);
- $this->dao = new dao($this->app);
- return false;
- }
- /**
- * 如果没有扩展文件,model类名是$moduleName + 'model',如果有扩展,还需要增加ext前缀。
- * If no extension file, model class name is $moduleName + 'model', else with 'ext' as the prefix.
- */
- $modelClass = class_exists('ext' . $appName . $moduleName. 'model') ? 'ext' . $appName . $moduleName . 'model' : $appName . $moduleName . 'model';
- if(!class_exists($modelClass))
- {
- $modelClass = class_exists('ext' . $moduleName. 'model') ? 'ext' . $moduleName . 'model' : $moduleName . 'model';
- if(!class_exists($modelClass)) $this->app->triggerError(" The model $modelClass not found", __FILE__, __LINE__, true);
- }
- /**
- * 初始化model对象,在control对象中可以通过$this->$moduleName来引用。同时将dao对象赋为control对象的成员变量,方便引用。
- * Init the model object thus you can try $this->$moduleName to access it. Also assign the $dao object as a member of control object.
- */
- $loadedModels[$appName][$moduleName] = new $modelClass($appName);
- $this->$moduleName = $loadedModels[$appName][$moduleName];
- $this->dao = $this->$moduleName->dao;
- return $this->$moduleName;
- }
- /**
- * 获取控制器执行返回的数据,在output缓存中.
- * Get controller data from output.
- *
- * @access public
- * @return object.
- */
- public function getData()
- {
- $output = helper::removeUTF8Bom(ob_get_clean());
- $output = json_decode((string) $output);
- if(isset($output->data) && !is_object($output->data)) $output->data = json_decode((string) $output->data);
- if(!isset($output->status) && isset($output->result)) $output->status = $output->result;
- if(isset($output->load->alert))
- {
- $output->code = 400;
- $output->status = 'fail';
- $output->message = $output->load->alert;
- unset($output->load);
- }
- return $output;
- }
- /**
- * 添加$_POST全局变量.
- * Add data to $_POST.
- *
- * @param string $key
- * @access public
- * @return void
- */
- public function setPost($key, $value)
- {
- $_POST[$key] = $value;
- }
- /**
- * 批量添加$_POST全局变量.
- * Batch set data to $_POST.
- *
- * @param string $fields
- * @access public
- * @return void
- */
- public function batchSetPost($fields, $object = '')
- {
- $fields = explode(',', $fields);
- /* Append flow fields to post. */
- if($this->config->edition != 'open')
- {
- $fieldList = $this->loadModel('workflowaction')->getPageFields($this->app->rawModule, $this->app->rawMethod, true, null, 0, 0);
- if(!empty($fieldList))
- {
- foreach($fieldList as $field)
- {
- if(!in_array($field->field, $fields)) $fields[] = $field->field;
- }
- }
- }
- foreach($fields as $field)
- {
- /*
- * If the field exists in request body, use it.
- * Otherwise set default value from $object.
- */
- if(isset($this->requestBody->$field))
- {
- $value = $this->requestBody->$field;
- }
- else
- {
- if(!$object or !isset($object->$field)) continue;
- $value = $object->$field;
- }
- $this->setPost($field, $value);
- }
- }
- /**
- * 确保字段不能为空.
- * Make sure the fields is not empty.
- *
- * @param string $fields
- * @access public
- * @return void
- */
- public function requireFields($fields)
- {
- $fields = explode(',', $fields);
- foreach($fields as $field)
- {
- if(!isset($_POST[$field]))
- {
- $module = $this->app->moduleName;
- $name = $this->app->lang->$module->$field ?? $field;
- throw EndResponseException::create($this->sendError(400, sprintf($this->app->lang->error->notempty, $name)));
- }
- }
- }
- /**
- * 检查是否在后台启用了代号.
- * Check whether config->setCode are used in product,project,execution.
- *
- * @access public
- * @return bool
- */
- public function checkCodeUsed()
- {
- return isset($this->config->setCode) ? $this->config->setCode : 0;
- }
- /**
- * 格式化数据的字段类型.
- * Format fields of response data.
- *
- * @param object|array $data
- * @param string $fields
- * @access public
- * @return object|array
- */
- public function format($data, $fields)
- {
- if(is_array($data))
- {
- foreach($data as $object) $this->formatFields($object, $fields);
- }
- else
- {
- $this->formatFields($data, $fields);
- }
- return $data;
- }
- /**
- * 格式化对象的字段类型.
- * Format fields of object.
- *
- * @param object $object
- * @param string $fields
- * @access public
- * @return object
- */
- private function formatFields(&$object, $fields)
- {
- $fields = explode(',', $fields);
- foreach($fields as $field)
- {
- $field = explode(':', $field);
- $key = $field[0];
- $type = $field[1];
- $isArray = false;
- if(!isset($object->$key)) continue;
- $pos = strpos($type, ']');
- if($pos !== false)
- {
- $isArray = true;
- $type = substr($type, $pos + 1);
- }
- else if(strpos($type, 'array') !== false)
- {
- $isArray = true;
- $type = 'object';
- }
- /* Format value. */
- if(!$isArray)
- {
- $object->$key = $this->cast(trim((string) $object->$key, ','), $type);
- continue;
- }
- /* Format array. */
- $value = array();
- if(is_array($object->$key) or is_object($object->$key))
- {
- foreach($object->$key as $v) $value[] = $this->cast($v, $type);
- }
- else
- {
- $vs = explode(',', $object->$key);
- foreach($vs as $v)
- {
- if($v === '') continue;
- $value[] = $this->cast($v, $type);
- }
- }
- $object->$key = $value;
- }
- }
- /**
- * Filter fields.
- *
- * @param object $object
- * @param string $allowable
- * @access public
- * @return object
- */
- public function filterFields($object, $allowable = '')
- {
- if(empty($allowable)) return $object;
- if(is_string($allowable)) $allowable = explode(',', $allowable);
- $filtered = new stdclass();
- foreach($allowable as $field)
- {
- $field = trim((string) $field);
- if(empty($field)) continue;
- if(!isset($object->$field)) continue;
- $filtered->$field = $object->$field;
- }
- return $filtered;
- }
- /**
- * Format user.
- *
- * @param string $account
- * @param array|object $users
- * @access public
- * @return array
- */
- public function formatUser($account, $users)
- {
- $user = array();
- $user['account'] = $account;
- $user['realname'] = zget($users, $account);
- return $user;
- }
- /**
- * 类型转换.
- * Typecasting.
- *
- * @param mixed $vaule
- * @param string $type
- * @access public
- * @return mixed
- */
- private function cast($value, $type)
- {
- switch($type)
- {
- case 'time':
- $timeFormat = $this->param('timeFormat', 'utc');
- if($timeFormat == 'utc')
- {
- if(!$value or $value == '0000-00-00 00:00:00') return null;
- return gmdate("Y-m-d\TH:i:s\Z", strtotime((string) $value));
- }
- return $value;
- case 'date':
- if(!$value or $value == '0000-00-00') return null;
- return $value;
- case 'bool':
- return !empty($value);
- case 'int':
- return (int) $value;
- case 'idList':
- $values = explode(',', (string) $value);
- if(empty($values)) return array();
- $idList = array();
- foreach($values as $val)
- {
- if($val !== '') $idList[] = (int) $val;
- }
- return $idList;
- case 'stringList':
- $values = explode(',', (string) $value);
- if(empty($values)) return array();
- $stringList = array();
- foreach($values as $val)
- {
- if($val !== '') $stringList[] = $val;
- }
- return $stringList;
- case 'array':
- $array = array();
- if(!empty($value)) foreach($value as $v) $array[] = $v;
- return $array;
- case 'user':
- if(empty($value)) return null;
- if(empty($this->users)) $this->users = $this->dao->select('id,account,avatar,realname')->from(TABLE_USER)->fetchAll('account');
- return zget($this->users, $value, null);
- case 'userList':
- $values = explode(',', (string) $value);
- if(empty($values)) return array();
- $userList = array();
- foreach($values as $val)
- {
- $val = $this->cast($val, 'user');
- if($val) $userList[] = $val;
- }
- return $userList;
- case 'decodeHtml':
- return htmlspecialchars_decode((string) $value);
- default:
- return $value;
- }
- }
- /**
- * 获取其他方法的执行结果。
- * Fetch result of other method.
- *
- * @param string $entry
- * @param string $method
- * @param array $params
- * @access public
- * @return mixed
- */
- public function fetch($entry, $method, $params = array())
- {
- include($this->app->appRoot . "api/{$this->app->version}/entries/" . strtolower($entry) . ".php");
- $entryName = $entry . 'Entry';
- $entry = new $entryName();
- return call_user_func_array(array($entry, $method), $params);
- }
- /**
- * Check the user has permission to access this method, if not, return 403.
- *
- * @access public
- * @return void|string
- */
- public function checkPriv()
- {
- $module = $this->app->getModuleName();
- $method = $this->app->getMethodName();
- if($module and $method and !$this->loadModel('common')->isOpenMethod($module, $method) and !commonModel::hasPriv($module, $method))
- {
- die($this->send(403, array('error' => 'Access not allowed')));
- }
- }
- /**
- * Reset open app.
- *
- * @param string $tab
- * @access public
- * @return void
- */
- public function resetOpenApp($tab)
- {
- $_COOKIE['tab'] = $tab;
- $this->app->tab = $tab;
- $this->app->session->tab = $tab;
- }
- }
|