router.class.php 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840
  1. <?php /**
  2. * 禅道API的api类。
  3. * The api class file of ZenTao API.
  4. *
  5. * The author disclaims copyright to this source code. In place of
  6. * a legal notice, here is a blessing:
  7. *
  8. * May you do good and not evil.
  9. * May you find forgiveness for yourself and forgive others.
  10. * May you share freely, never taking more than you give.
  11. */
  12. include dirname(__FILE__, 2) . '/router.class.php';
  13. class api extends router
  14. {
  15. /**
  16. * 请求API的路径
  17. * The requested path of api.
  18. *
  19. * @var string
  20. * @access public
  21. */
  22. public $path;
  23. /**
  24. * 请求API的参数,包括键值
  25. * The requested params of api: key and value.
  26. *
  27. * @var array
  28. * @access public
  29. */
  30. public $params = array();
  31. /**
  32. * 请求API的参数名
  33. * The requested param names of api.
  34. *
  35. * @var array
  36. * @access public
  37. */
  38. public $paramNames = array();
  39. /**
  40. * 请求的资源名称
  41. * The requested entry point
  42. *
  43. * @var string
  44. * @access public
  45. */
  46. public $entry;
  47. /**
  48. * API资源的执行方法: get post put delete
  49. * The action of entry point: get post put delete
  50. *
  51. * @var string
  52. * @access public
  53. */
  54. public $action;
  55. /**
  56. * 选择性输出json数据
  57. * Extract json data
  58. *
  59. * @var string
  60. * @access public
  61. */
  62. public $responseExtractor = '*';
  63. /**
  64. * 构造方法, 设置请求路径,版本等
  65. *
  66. * The construct function.
  67. * Prepare all the paths, version and so on.
  68. *
  69. * @access public
  70. * @return void
  71. * @param string $appName
  72. * @param string $appRoot
  73. */
  74. public function __construct($appName = 'api', $appRoot = '')
  75. {
  76. $this->path = trim(substr((string) $_SERVER['REQUEST_URI'], strpos((string) $_SERVER['REQUEST_URI'], 'api.php') + 7), '/');
  77. if(strpos($this->path, '?') > 0) $this->path = strstr($this->path, '?', true);
  78. $subPos = $this->path ? strpos($this->path, '/') : false;
  79. $this->apiVersion = $subPos !== false ? substr($this->path, 0, $subPos) : '';
  80. $this->path = $subPos !== false ? substr($this->path, $subPos) : '';
  81. parent::__construct($appName, $appRoot);
  82. $this->viewType = 'json';
  83. $this->httpMethod = strtolower((string) $_SERVER['REQUEST_METHOD']);
  84. $this->loadApiLang();
  85. }
  86. /**
  87. * 解析请求路径,找到处理方法
  88. *
  89. * Parse request path, find entry and action.
  90. *
  91. * @param array $routes
  92. * @access public
  93. * @return void
  94. */
  95. public function route($routes)
  96. {
  97. foreach($routes as $route => $target)
  98. {
  99. $patternAsRegex = preg_replace_callback(
  100. '#:([\w]+)\+?#',
  101. \Closure::fromCallable([$this, 'matchesCallback']),
  102. str_replace(')', ')?', $route)
  103. );
  104. if(substr_compare($route, '/', -strlen('/')) === 0) $patternAsRegex .= '?';
  105. /* Cache URL params' names and values if this route matches the current HTTP request. */
  106. if(!preg_match('#^' . $patternAsRegex . '$#', $this->path, $paramValues)) continue;
  107. /* Set module and action */
  108. $this->entry = $target;
  109. $this->action = strtolower((string) $_SERVER['REQUEST_METHOD']);
  110. /* Set params */
  111. foreach($this->paramNames as $name)
  112. {
  113. if(!isset($paramValues[$name])) continue;
  114. $this->params[$name] = urldecode($paramValues[$name]);
  115. }
  116. return;
  117. }
  118. $this->entry = 'error';
  119. $this->action = 'notFound';
  120. }
  121. /**
  122. * 复数转单数
  123. * Converting plural nouns to singular.
  124. *
  125. * @param string $word
  126. * @access public
  127. * @return string
  128. */
  129. public function singular($word)
  130. {
  131. /* 特殊词处理 */
  132. $irregular = array(
  133. 'children' => 'child',
  134. 'men' => 'man',
  135. 'women' => 'woman',
  136. 'people' => 'person',
  137. 'feet' => 'foot',
  138. 'teeth' => 'tooth',
  139. 'mice' => 'mouse',
  140. 'geese' => 'goose',
  141. 'oxen' => 'ox',
  142. 'cacti' => 'cactus',
  143. 'foci' => 'focus',
  144. 'nuclei' => 'nucleus',
  145. 'syllabi' => 'syllabus',
  146. 'radii' => 'radius',
  147. 'phenomena' => 'phenomenon',
  148. 'criteria' => 'criterion',
  149. 'data' => 'datum',
  150. 'media' => 'medium',
  151. 'lice' => 'louse',
  152. 'selves' => 'self',
  153. 'loaves' => 'loaf',
  154. 'leaves' => 'leaf',
  155. 'lives' => 'life',
  156. 'wives' => 'wife',
  157. 'knives' => 'knife',
  158. 'wolves' => 'wolf',
  159. 'elves' => 'elf',
  160. 'halves' => 'half',
  161. 'scarves' => 'scarf',
  162. 'hooves' => 'hoof',
  163. 'veterans' => 'veteran', // 特殊情况示例
  164. );
  165. if(isset($irregular[strtolower($word)])) {
  166. $lowerWord = strtolower($word);
  167. $singular = $irregular[$lowerWord];
  168. if (ctype_upper($word[0])) {
  169. $singular = ucfirst($singular);
  170. }
  171. return $singular;
  172. }
  173. $rules = [
  174. '/sses$/i' => 'ss',
  175. '/ies$/i' => 'y',
  176. '/ves$/i' => 'f',
  177. '/zes$/i' => 'z',
  178. '/ches$/i' => 'ch',
  179. '/shes$/i' => 'sh',
  180. '/men$/i' => 'man',
  181. '/s$/i' => '',
  182. ];
  183. foreach($rules as $pattern => $replacement)
  184. {
  185. if(preg_match($pattern, $word)) return preg_replace($pattern, $replacement, $word, 1);
  186. }
  187. return $word;
  188. }
  189. /**
  190. * 路由正则匹配
  191. * Match routes.
  192. *
  193. * @param array $routes
  194. * @access private
  195. * @return array
  196. */
  197. private function matchRoutes($routes)
  198. {
  199. foreach($routes as $route => $info)
  200. {
  201. $patternAsRegex = preg_replace_callback(
  202. '#:([\w]+)\+?#',
  203. \Closure::fromCallable([$this, 'matchesCallback']),
  204. str_replace(')', ')?', $route)
  205. );
  206. if(substr_compare($route, '/', -strlen('/')) === 0) $patternAsRegex .= '?';
  207. /* Cache URL params' names and values if this route matches the current HTTP request. */
  208. if(!preg_match('#^' . $patternAsRegex . '$#', $this->path, $paramValues)) continue;
  209. return array($info, $paramValues);
  210. }
  211. return array(null, array());
  212. }
  213. /**
  214. * API2.0 根据路由表设置path和params
  215. * API2.0 Set path, params by routes.
  216. *
  217. * @param array $routes
  218. * @access private
  219. * @return string
  220. */
  221. public function parseRouteV2($routes)
  222. {
  223. $methodName = '';
  224. list($info, $paramValues) = $this->matchRoutes($routes);
  225. if($info)
  226. {
  227. if(isset($info['method'])) $methodName = $info['method'];
  228. if(isset($info['redirect']))
  229. {
  230. foreach($paramValues as $key => $value)
  231. {
  232. if(is_numeric($key)) continue;
  233. $_GET[$key] = $value;
  234. $info['redirect'] = str_replace(':'.$key, $value, $info['redirect']);
  235. }
  236. if(isset($info['response'])) $this->responseExtractor = $info['response'];
  237. $url = parse_url($info['redirect']);
  238. $this->path = $url['path'];
  239. if(isset($url['query']))
  240. {
  241. parse_str($url['query'], $params);
  242. foreach($params as $key => $value) $_GET[$key] = $value;
  243. }
  244. list($info, $paramValues) = $this->matchRoutes($routes);
  245. if(isset($info['method'])) $methodName = $info['method'];
  246. }
  247. if(isset($info['response']) && $this->responseExtractor == '*') $this->responseExtractor = $info['response'];
  248. }
  249. foreach($paramValues as $key => $value)
  250. {
  251. if(is_numeric($key)) continue;
  252. $_GET[$key] = $value;
  253. }
  254. return $methodName;
  255. }
  256. /**
  257. * API2.0 路由
  258. * API2.0 routing.
  259. *
  260. * @param array $routes
  261. * @access private
  262. * @return array
  263. */
  264. public function routeV2($routes)
  265. {
  266. $this->action = strtolower((string) $_SERVER['REQUEST_METHOD']);
  267. $methodName = '';
  268. if($this->action == 'get') $methodName = $this->parseRouteV2($routes);
  269. $pathItems = explode('/', trim($this->path, '/'));
  270. $moduleName = $this->singular($pathItems[0]);
  271. $actionToMethod = array(
  272. 'get' => 'browse',
  273. 'post' => 'create',
  274. 'put' => 'edit',
  275. 'delete' => 'delete'
  276. );
  277. if(isset($pathItems[1]))
  278. {
  279. if(is_numeric($pathItems[1]))
  280. {
  281. if($this->action == 'get')
  282. {
  283. $methodName = 'view';
  284. }
  285. else
  286. {
  287. $_GET[$moduleName.'ID'] = $pathItems[1];
  288. }
  289. }
  290. else
  291. {
  292. $methodName = $pathItems[1];
  293. }
  294. }
  295. if(isset($pathItems[2])) $methodName = $pathItems[2];
  296. if(!$methodName) $methodName = $actionToMethod[$this->action];
  297. /* File is special. */
  298. if($moduleName == 'file' && $this->action == 'post')
  299. {
  300. $methodName = 'ajaxUpload';
  301. $_GET['field'] = 'file';
  302. $_GET['objectType'] = zget($_POST, 'objectType', '');
  303. $_GET['objectID'] = zget($_POST, 'objectID', '');
  304. }
  305. $this->setModuleName($moduleName);
  306. $this->setMethodName($methodName);
  307. $this->setControlFile();
  308. /* Set default params and post data to delete.*/
  309. if($this->action == 'delete')
  310. {
  311. $defaultParams = $this->getDefaultParams();
  312. if(isset($defaultParams['confirm'])) $_GET['confirm'] = 'yes';
  313. }
  314. }
  315. /**
  316. * 将路由路径参数转化为正则
  317. *
  318. * Parse params of route to regular expression.
  319. *
  320. * @param array $m
  321. * @access protected
  322. * @return string
  323. */
  324. protected function matchesCallback($m)
  325. {
  326. $this->paramNames[] = $m[1];
  327. return '(?P<' . $m[1] . '>[^/]+)';
  328. }
  329. /**
  330. * 解析访问请求
  331. *
  332. * Parse request.
  333. *
  334. * @access public
  335. * @return void
  336. */
  337. public function parseRequest()
  338. {
  339. /* If version of api don't exists, call parent method. */
  340. if(!$this->apiVersion) return parent::parseRequest();
  341. global $routes;
  342. if($this->apiVersion == 'v1')
  343. {
  344. include $this->appRoot . "config/apiv1.php";
  345. if(isset($this->config->routes)) $routes = array_merge($routes, $this->config->routes);
  346. $this->route($routes);
  347. }
  348. else
  349. {
  350. include $this->appRoot . "config/apiv2.php";
  351. $this->routeV2($routes);
  352. }
  353. }
  354. /**
  355. * 检查传入的对象是否有权限访问
  356. *
  357. * Check object priv.
  358. *
  359. * @param object $object
  360. * @param string $table
  361. * @access public
  362. * @return bool
  363. */
  364. public function checkObjectPriv($object, $table)
  365. {
  366. if($this->user->admin) return true;
  367. $userView = $this->user->view;
  368. switch($table)
  369. {
  370. case TABLE_STORY:
  371. case TABLE_BUG:
  372. case TABLE_CASE:
  373. case TABLE_TICKET:
  374. case TABLE_FEEDBACK:
  375. case TABLE_PRODUCTPLAN:
  376. return (!$object->product || strpos(",{$userView->products},", ",$object->product,") !== false);
  377. case TABLE_PRODUCT:
  378. return (!$object->id || strpos(",{$userView->products},", ",$object->id,") !== false);
  379. case TABLE_PROJECT: // project,execution,program
  380. $projects = ",{$userView->sprints},{$userView->projects},{$userView->programs},";
  381. return (!$object->id || strpos($projects, ",$object->id,") !== false);
  382. case TABLE_BUILD:
  383. case TABLE_TASK:
  384. return (!$object->execution || strpos(",{$userView->sprints},", ",$object->execution,") !== false);
  385. default:
  386. return true;
  387. }
  388. return false;
  389. }
  390. /**
  391. * 检查传入的对象是否可以访问
  392. *
  393. * Check access.
  394. *
  395. * @access public
  396. * @return void
  397. */
  398. public function checkAccess()
  399. {
  400. $objectMap = [
  401. 'program' => TABLE_PROJECT,
  402. 'programID' => TABLE_PROJECT,
  403. 'product' => TABLE_PRODUCT,
  404. 'products' => TABLE_PRODUCT,
  405. 'productID' => TABLE_PRODUCT,
  406. 'project' => TABLE_PROJECT,
  407. 'projectID' => TABLE_PROJECT,
  408. 'productplan' => TABLE_PRODUCTPLAN,
  409. 'productplanID' => TABLE_PRODUCTPLAN,
  410. 'plan' => TABLE_PRODUCTPLAN,
  411. 'planID' => TABLE_PRODUCTPLAN,
  412. 'execution' => TABLE_PROJECT,
  413. 'executionID' => TABLE_PROJECT,
  414. 'story' => TABLE_STORY,
  415. 'storyID' => TABLE_STORY,
  416. 'epic' => TABLE_STORY,
  417. 'epicID' => TABLE_STORY,
  418. 'requirement' => TABLE_STORY,
  419. 'requirementID' => TABLE_STORY,
  420. 'task' => TABLE_TASK,
  421. 'taskID' => TABLE_TASK,
  422. 'bug' => TABLE_BUG,
  423. 'bugID' => TABLE_BUG,
  424. 'feedback' => TABLE_FEEDBACK,
  425. 'feedbackID' => TABLE_FEEDBACK,
  426. 'build' => TABLE_BUILD,
  427. 'buildID' => TABLE_BUILD,
  428. 'case' => TABLE_CASE,
  429. 'caseID' => TABLE_CASE,
  430. 'testcase' => TABLE_CASE,
  431. 'testcaseID' => TABLE_CASE,
  432. 'user' => TABLE_USER,
  433. 'userID' => TABLE_USER,
  434. 'ticket' => TABLE_TICKET,
  435. 'ticketID' => TABLE_TICKET,
  436. 'dept' => TABLE_DEPT,
  437. 'deptID' => TABLE_DEPT,
  438. ];
  439. /* Check assignedTo. */
  440. if(isset($_POST['assignedTo']) && $_POST['assignedTo'])
  441. {
  442. $user = $this->dao->select('*')->from(TABLE_USER)
  443. ->where('account')->eq($_POST['assignedTo'])
  444. ->fetch();
  445. if(!$user) return $this->control->sendError('User does not exist.');
  446. }
  447. $params = array_merge($this->params, $_POST);
  448. foreach($params as $key => $value)
  449. {
  450. if(!isset($objectMap[$key]) || !$value) continue;
  451. $table = $objectMap[$key];
  452. $result = $this->checkObjectExists($table, $value);
  453. if($result === false) return $this->control->sendError(ucfirst(str_replace('ID', '', $key)) . ' does not exist.');
  454. foreach($result as $object)
  455. {
  456. if(!$this->checkObjectPriv($object, $table)) return $this->control->sendError(ucfirst(str_replace('ID', '', $key)) . ' is not allowed.');
  457. }
  458. }
  459. }
  460. /**
  461. * 检查对象是否存在
  462. *
  463. * Check object exists.
  464. *
  465. * @param string $table
  466. * @param int $objectID
  467. * @access public
  468. * @return array|false
  469. */
  470. public function checkObjectExists($table, $objectIDList)
  471. {
  472. if(!is_array($objectIDList)) $objectIDList = [$objectIDList];
  473. $objects = [];
  474. foreach($objectIDList as $objectID)
  475. {
  476. $object = $this->dao->select('*')->from($table)
  477. ->where('id')->eq($objectID)
  478. ->beginIF(!in_array($table, [TABLE_DEPT]))->andWhere('deleted')->eq('0')->fi()
  479. ->fetch();
  480. if(!$object) return false;
  481. $objects[] = $object;
  482. }
  483. return $objects;
  484. }
  485. /**
  486. * 执行对应模块
  487. *
  488. * Load the running module.
  489. *
  490. * @access public
  491. * @return void
  492. */
  493. public function loadModule()
  494. {
  495. try
  496. {
  497. /* If the version of api don't exists, call parent method. */
  498. if($this->apiVersion == 'v2')
  499. {
  500. $this->setParams();
  501. if(in_array($this->action, array('post', 'put', 'delete')))
  502. {
  503. $this->setFormData();
  504. }
  505. else
  506. {
  507. $this->checkAccess();
  508. }
  509. return parent::loadModule();
  510. }
  511. elseif(!$this->apiVersion)
  512. {
  513. parent::setParams();
  514. return parent::loadModule();
  515. }
  516. /* api v1. */
  517. $entry = strtolower($this->entry);
  518. $filename = $this->appRoot . "api/$this->apiVersion/entries/$entry.php";
  519. if(file_exists($filename)) include($filename);
  520. $entryName = $this->entry . 'Entry';
  521. if($entry == 'error' && !class_exists($entryName)) include($this->appRoot . "api/v1/entries/$entry.php");
  522. $entry = new $entryName();
  523. if($this->action == 'options') throw EndResponseException::create($entry->send(204));
  524. echo call_user_func_array(array($entry, $this->action), array_values($this->params));
  525. $this->outputXhprof();
  526. }
  527. catch(EndResponseException $endResponseException)
  528. {
  529. echo $endResponseException->getContent();
  530. }
  531. }
  532. /**
  533. * 设置form data。
  534. * Set form data.
  535. *
  536. * @access public
  537. * @return void
  538. */
  539. public function setFormData()
  540. {
  541. $requestBody = file_get_contents("php://input");
  542. $_POST = json_decode($requestBody, true);
  543. /* Avoid empty post body. */
  544. if(in_array($this->control->moduleName, ['feedback', 'ticket']))
  545. {
  546. $_POST['uid'] = '1';
  547. }
  548. else
  549. {
  550. $_POST['verifyPassword'] = '1';
  551. }
  552. /* 以POST的值为准。 Set GET value from POST data. */
  553. foreach($_POST as $key => $value)
  554. {
  555. if(isset($this->params[$key])) $this->params[$key] = $value;
  556. }
  557. $this->checkAccess();
  558. /* 其他方法不需要从GET页面获取post data。Other request directly. */
  559. if(!in_array($this->methodName, ['create', 'edit', 'change'])) return;
  560. /* 更新操作的表单需要拼接原始的值。 Merge original values. */
  561. /* Get form data by get request. */
  562. $postData = $_POST;
  563. $_POST = array();
  564. $this->control->viewType = 'html';
  565. $this->control->getFormData = true;
  566. $zen = $this->control->moduleName . 'Zen';
  567. if(isset($this->control->$zen)) $this->control->$zen->getFormData = true;
  568. $control = $this->control; // fetch method will change control.
  569. $method = $this->control->methodName;
  570. call_user_func_array(array($this->control, $method), $this->params);
  571. /* Clean the output in get method. */
  572. ob_clean();
  573. $this->control->getFormData = false;
  574. $this->control->viewType = 'json';
  575. $this->control = $control;
  576. $_POST = $postData;
  577. foreach($this->control->formData as $key => $value)
  578. {
  579. if(!isset($_POST[$key])) $_POST[$key] = $value;
  580. }
  581. if(isset($this->control->$zen))
  582. {
  583. $this->control->$zen->getFormData = false;
  584. foreach($this->control->$zen->formData as $key => $value)
  585. {
  586. if(!isset($_POST[$key])) $_POST[$key] = $value;
  587. }
  588. }
  589. }
  590. /**
  591. * 设置要被调用方法的参数。
  592. * Set the params of method calling.
  593. *
  594. * @access public
  595. * @return void
  596. */
  597. public function setParams()
  598. {
  599. $defaultParams = $this->getDefaultParams();
  600. $this->params = array();
  601. /* POST/PUT/DELETE methods have no correct param name, use index. */
  602. if($this->action != 'get')
  603. {
  604. $values = array_values($_GET);
  605. $index = 0;
  606. foreach($defaultParams as $key => $defaultItem)
  607. {
  608. if(isset($values[$index]))
  609. {
  610. $value = $values[$index];
  611. settype($value, $defaultItem['type']);
  612. $_GET[$key] = $value;
  613. }
  614. $index++;
  615. }
  616. }
  617. foreach($defaultParams as $key => $defaultItem)
  618. {
  619. if(isset($_GET[$key]))
  620. {
  621. $this->params[$key] = helper::convertType(strip_tags((string) $_GET[$key]), $defaultItem['type']);
  622. }
  623. else
  624. {
  625. /* Browse all items in api mode defaultly. */
  626. $this->params[$key] = in_array($key, ['browseType', 'status']) ? 'all' : $defaultItem['default'];
  627. }
  628. }
  629. if($this->config->framework->filterParam == 2)
  630. {
  631. $_GET = validater::filterParam($_GET, 'get');
  632. $_COOKIE = validater::filterParam($_COOKIE, 'cookie');
  633. }
  634. $this->rawParams = $this->params;
  635. return true;
  636. }
  637. /**
  638. * 加载配置文件
  639. *
  640. * Load config file of api.
  641. *
  642. * @param string $configPath
  643. * @access public
  644. * @return void
  645. */
  646. public function loadApiConfig($configPath)
  647. {
  648. global $config;
  649. include($this->appRoot . "api/$this->apiVersion/config/$configPath.php");
  650. }
  651. /**
  652. * 加载语言文件
  653. *
  654. * Load lang file of api.
  655. *
  656. * @access public
  657. * @return void
  658. */
  659. public function loadApiLang()
  660. {
  661. global $lang;
  662. $filename = $this->appRoot . "api/$this->apiVersion/lang/$this->clientLang.php";
  663. if($this->apiVersion && file_exists($filename)) include($filename);
  664. }
  665. /**
  666. * 格式化旧版本API响应数据
  667. *
  668. * Format old version data.
  669. *
  670. * @param string
  671. * @access public
  672. * @return string
  673. */
  674. public function formatData($output)
  675. {
  676. /* If the version exists, return output directly. */
  677. if($this->apiVersion) return $output;
  678. $output = json_decode((string) $output);
  679. $data = new stdClass();
  680. $data->status = $output->status ?? $output->result;
  681. if(isset($output->message)) $data->message = $output->message;
  682. if(isset($output->data)) $data->data = json_decode((string) $output->data);
  683. if(isset($output->id)) $data->id = $output->id;
  684. $output = json_encode($data);
  685. unset($_SESSION['ENTRY_CODE']);
  686. unset($_SESSION['VALID_ENTRY']);
  687. return $output;
  688. }
  689. /**
  690. * 设置vision。
  691. * set Debug.
  692. *
  693. * @access public
  694. * @return void
  695. */
  696. public function setVision()
  697. {
  698. $account = isset($_SESSION['user']) ? $_SESSION['user']->account : '';
  699. if(empty($account) and isset($_POST['account'])) $account = $_POST['account'];
  700. if(empty($account) and isset($_GET['account'])) $account = $_GET['account'];
  701. $vision = 'rnd';
  702. if($this->config->installed and validater::checkAccount($account))
  703. {
  704. $sql = new sql();
  705. $account = $sql->quote($account);
  706. $user = $this->dbh->query("SELECT * FROM " . TABLE_USER . " WHERE account = $account AND deleted = '0' LIMIT 1")->fetch();
  707. if(!empty($user->visions))
  708. {
  709. $userVisions = explode(',', $user->visions);
  710. if(!in_array($vision, $userVisions)) $vision = '';
  711. if(empty($vision)) list($vision) = $userVisions;
  712. }
  713. }
  714. list($defaultVision) = explode(',', trim($this->config->visions, ','));
  715. if($vision and strpos($this->config->visions, ",{$vision},") === false) $vision = $defaultVision;
  716. $this->config->vision = $vision ? $vision : $defaultVision;
  717. }
  718. /**
  719. * 设置超级变量。
  720. * Set the super vars.
  721. *
  722. * @access public
  723. * @return void
  724. */
  725. public function setSuperVars()
  726. {
  727. $this->config->framework->filterCSRF = false;
  728. parent::setSuperVars();
  729. }
  730. }