From c371d5ae61ccc0bce143f82c2f279e7125d348d1 Mon Sep 17 00:00:00 2001 From: zhujinyong Date: Tue, 27 Jul 2021 10:53:25 +0800 Subject: [PATCH] + Add productissue entry point. --- api/v1/entries/bugs.php | 2 +- api/v1/entries/executions.php | 2 +- api/v1/entries/productissue.php | 101 ++++++++++++++++ api/v1/entries/productissues.php | 193 +++++++++++++++++++++++++++++++ api/v1/entries/programs.php | 2 +- api/v1/entries/projects.php | 6 +- api/v1/entries/stories.php | 2 +- api/v1/entries/tasks.php | 2 +- config/routes.php | 3 + framework/api/entry.class.php | 10 +- framework/base/router.class.php | 25 ++-- lib/base/pager/pager.class.php | 6 +- module/common/model.php | 38 ++++-- module/entry/model.php | 12 ++ www/api.php | 4 +- 15 files changed, 369 insertions(+), 39 deletions(-) create mode 100644 api/v1/entries/productissue.php create mode 100644 api/v1/entries/productissues.php diff --git a/api/v1/entries/bugs.php b/api/v1/entries/bugs.php index 70a31c67b2..93729e30ee 100644 --- a/api/v1/entries/bugs.php +++ b/api/v1/entries/bugs.php @@ -11,7 +11,7 @@ class bugsEntry extends entry public function get($productID) { $control = $this->loadController('bug', 'browse'); - $control->browse($productID); + $control->browse($productID, $this->param('branch', ''), $this->param('status', ''), 0, $this->param('order', ''), 0, $this->param('limit', 20), $this->param('page', 1)); $data = $this->getData(); if(isset($data->status) and $data->status == 'success') diff --git a/api/v1/entries/executions.php b/api/v1/entries/executions.php index 03660142bb..c994ac729d 100644 --- a/api/v1/entries/executions.php +++ b/api/v1/entries/executions.php @@ -11,7 +11,7 @@ class executionsEntry extends entry public function get($projectID = 0) { $control = $this->loadController('execution', 'all'); - $control->all($this->param('status', 'all'), $this->param('project', $projectID)); + $control->all($this->param('status', 'all'), $this->param('project', $projectID), $this->param('order', 'id_desc'), 0, $this->param('total', 0), $this->param('limit', 20), $this->param('page', 1)); $data = $this->getData(); if(isset($data->status) and $data->status == 'success') diff --git a/api/v1/entries/productissue.php b/api/v1/entries/productissue.php new file mode 100644 index 0000000000..f41d099905 --- /dev/null +++ b/api/v1/entries/productissue.php @@ -0,0 +1,101 @@ +sendError(400, 'The id of issue is wrong.'); + + $type = $idParams[0]; + $id = $idParams[1]; + + $issue = new stdclass(); + switch($type) + { + case 'story': + $this->app->loadLang('story'); + $storyStatus = array('' => '', 'draft' => 'wait', 'active' => 'active', 'changed' => 'active', 'closed' => 'closed'); + + $story = $this->dao->select('*')->from(TABLE_STORY)->where('id')->eq($id)->fetch(); + $issue->id = $issueID; + $issue->title = $story->title; + $issue->labels = array($this->app->lang->story->common, zget($this->app->lang->story->categoryList, $story->category)); + $issue->pri = $story->pri; + $issue->assignedTo = $story->assignedTo; + $issue->openedDate = $story->openedDate; + $issue->openedBy = $story->openedBy; + $issue->lastEditedDate = $story->lastEditedDate; + $issue->status = $storyStatus[$story->status]; + $issue->url = $this->createLink('story', 'view', "storyID=$id"); + + $storySpec = $this->dao->select('*')->from(TABLE_STORYSPEC)->where('story')->eq($id)->andWhere('version')->eq($story->version)->fetch(); + $issue->desc = $storySpec->spec; + break; + case 'bug': + $this->app->loadLang('bug'); + $bugStatus = array('' => '', 'active' => 'active', 'resolved' => 'done', 'closed' => 'closed'); + + $bug = $this->dao->select('*')->from(TABLE_BUG)->where('id')->eq($id)->fetch(); + $issue->id = $issueID; + $issue->title = $bug->title; + $issue->labels = array($this->app->lang->bug->common, zget($this->app->lang->bug->typeList, $bug->type)); + $issue->pri = $bug->pri; + $issue->assignedTo = $bug->assignedTo; + $issue->openedDate = $bug->openedDate; + $issue->openedBy = $bug->openedBy; + $issue->lastEditedDate = $bug->lastEditedDate; + $issue->status = $bugStatus[$bug->status]; + $issue->url = $this->createLink('bug', 'view', "bugID=$id"); + $issue->desc = $bug->steps; + break; + case 'task': + $this->app->loadLang('task'); + $taskStatus = array('' => '', 'wait' => 'wait', 'doing' => 'active', 'done' => 'done', 'pause' => 'pause', 'cancel' => 'cancel', 'closed' => 'closed'); + + $task = $this->dao->select('*')->from(TABLE_TASK)->where('id')->eq($id)->fetch(); + + $issue->id = $issueID; + $issue->title = $task->name; + $issue->labels = array($this->app->lang->task->common, zget($this->app->lang->task->typeList, $task->type)); + $issue->pri = $task->pri; + $issue->assignedTo = $task->assignedTo; + $issue->openedDate = $task->openedDate; + $issue->openedBy = $task->openedBy; + $issue->lastEditedDate = $task->lastEditedDate; + $issue->status = $taskStatus[$task->status]; + $issue->url = $this->createLink('task', 'view', "taskID=$id"); + $issue->desc = $task->desc; + break; + } + + $this->send(200, array('issue' => $this->format($issue, 'openedDate:time,lastEditedDate:time'))); + } + + /** + * Create url of issue. + * + * @param string $module + * @param string $method + * @param string $vars + * @access private + * @return string + */ + private function createLink($module, $method, $vars) + { + $link = helper::createLink($module, $method, $vars, 'html'); + if($this->config->requestType == 'GET') + { + $pos = strpos($link, '.php'); + $link = '/index' . substr($link, $pos); + } + return common::getSysURL() . $link; + } +} diff --git a/api/v1/entries/productissues.php b/api/v1/entries/productissues.php new file mode 100644 index 0000000000..df3254cb6b --- /dev/null +++ b/api/v1/entries/productissues.php @@ -0,0 +1,193 @@ + ''); + $taskStatus['wait'] = 'wait'; + $taskStatus['active'] = 'doing'; + $taskStatus['done'] = 'done'; + $taskStatus['pause'] = 'pause'; + $taskStatus['cancel'] = 'cancel'; + $taskStatus['closed'] = 'closed'; + + $storyFields = 'id,status'; + $storyStatus = array('' => ''); + $storyStatus['wait'] = 'draft'; + $storyStatus['active'] = 'active,changed'; + $storyStatus['closed'] = 'closed'; + + $bugFields = 'id,status'; + $bugStatus = array('' => ''); + $bugStatus['active'] = 'active'; + $bugStatus['done'] = 'resolved'; + $bugStatus['closed'] = 'closed'; + + $productID = (int)$productID; + $status = $this->param('status', ''); + $label = $this->param('label', ''); + $search = $this->param('search', ''); + $page = $this->param('page', 0); + $limit = $this->param('limit', 20); + $order = $this->param('order', 'openedDate_desc'); + + $orderParams = explode('_', $order); + $order = $orderParams[0]; + $sort = (isset($orderParams[1]) and strtolower($orderParams[1]) == 'desc') ? 'desc' : 'asc'; + + switch($order) + { + case 'title': + $taskFields .= ',name as title'; + $storyFields .= ',title'; + $bugFields .= ',title'; + default: + $taskFields .= ',openedDate'; + $storyFields .= ',openedDate'; + $bugFields .= ',openedDate'; + } + + $issues = array(); + + $tasks = $this->dao->select($taskFields)->from(TABLE_TASK)->where('project')->in('(SELECT project FROM ' . TABLE_PROJECTPRODUCT . " WHERE product = $productID)") + ->beginIF($search)->andWhere('name')->like("%$search%")->fi() + ->beginIF($status)->andWhere('status')->in($taskStatus[$status])->fi() + ->andWhere('deleted')->eq(0) + ->fetchAll(); + foreach($tasks as $task) $issues[] = array('id' => $task->id, 'type' => 'task', 'order' => $task->$order, 'status' => $this->getKey($task->status, $taskStatus)); + + $stories = $this->dao->select($storyFields)->from(TABLE_STORY)->where('product')->eq($productID) + ->beginIF($search)->andWhere('title')->like("%$search%")->fi() + ->beginIF($status)->andWhere('status')->in($storyStatus[$status])->fi() + ->andWhere('deleted')->eq(0) + ->fetchAll(); + foreach($stories as $story) + { + $issues[] = array('id' => $story->id, 'type' => 'story', 'order' => $story->$order, 'status' => $this->getKey($story->status, $storyStatus)); + } + + $bugs = $this->dao->select($bugFields)->from(TABLE_BUG)->where('product')->eq($productID) + ->beginIF($search)->andWhere('title')->like("%$search%")->fi() + ->beginIF($status)->andWhere('status')->in($bugStatus[$status])->fi() + ->andWhere('deleted')->eq(0) + ->fetchAll(); + foreach($bugs as $bug) + { + $issues[] = array('id' => $bug->id, 'type' => 'bug', 'order' => $bug->$order, 'status' => $this->getKey($bug->status, $bugStatus)); + } + + array_multisort(array_column($issues, 'order'), $sort == 'asc' ? SORT_ASC : SORT_DESC, $issues); + $issues = array_slice($issues, $page * $limit, $limit); + + $result = $this->processIssues($issues); + $this->send(200, array('page' => $page, 'total' => count($issues),'limit' => $limit, 'issues' => $result)); + } + + /** + * Process issues, format fields. + * + * @param array $issues + * @param int $page + * @param int $limit + * @access public + * @return array + */ + public function processIssues($issues) + { + $this->app->loadLang('task'); + $this->app->loadLang('story'); + $this->app->loadLang('bug'); + + $tasks = array(); + $stories = array(); + $bugs = array(); + foreach($issues as $issue) + { + if($issue['type'] == 'story') $stories[] = $issue['id']; + if($issue['type'] == 'task') $tasks[] = $issue['id']; + if($issue['type'] == 'bug') $bugs[] = $issue['id']; + } + + if(!empty($tasks)) $tasks = $this->dao->select('*')->from(TABLE_TASK)->where('id')->in($tasks)->fetchAll('id'); + if(!empty($stories)) $stories = $this->dao->select('*')->from(TABLE_STORY)->where('id')->in($stories)->fetchAll('id'); + if(!empty($bugs)) $bugs = $this->dao->select('*')->from(TABLE_STORY)->where('id')->in($bugs)->fetchAll('id'); + + $result = array(); + foreach($issues as $issue) + { + $r = new stdclass(); + if($issue['type'] == 'task') + { + $task = $tasks[$issue['id']]; + + $r->id = 'task-' . $task->id; + $r->title = $task->name; + $r->labels = array($this->app->lang->task->common, zget($this->app->lang->task->typeList, $task->type)); + $r->pri = $task->pri; + $r->assignedTo = $task->assignedTo; + $r->openedDate = $task->openedDate; + $r->openedBy = $task->openedBy; + $r->lastEditedDate = $task->lastEditedDate; + $r->status = $task->status; + } + else if($issue['type'] == 'story') + { + $story = $stories[$issue['id']]; + + $r->id = 'story-' . $story->id; + $r->title = $story->title; + $r->labels = array($this->app->lang->story->common, zget($this->app->lang->story->categoryList, $story->category)); + $r->pri = $story->pri; + $r->assignedTo = $story->assignedTo; + $r->openedDate = $story->openedDate; + $r->openedBy = $story->openedBy; + $r->lastEditedDate = $story->lastEditedDate; + $r->status = $story->status; + } + else if($issue['type'] == 'bug') + { + $bug = $bugs[$issue['id']]; + + $r->id = 'bug-' . $bug->id; + $r->title = $bug->title; + $r->labels = array($this->app->lang->bug->common, zget($this->app->lang->bug->typeList, $bug->type)); + $r->pri = $bug->pri; + $r->assignedTo = $bug->assignedTo; + $r->openedDate = $bug->openedDate; + $r->openedBy = $bug->openedBy; + $r->lastEditedDate = $bug->lastEditedDate; + $r->status = $bug->status; + } + $result[] = $this->format($r, 'openedDate:time,lastEditedDate:time'); + } + + return $result; + } + + /** + * Get key in array by value. + * + * @param string $value + * @param array $array + * @access private + * @return string + */ + private function getKey($value, $array) + { + foreach($array as $key => $values) + { + if($values and strpos($value, $values) !== FALSE) return $key; + } + + return ''; + } +} diff --git a/api/v1/entries/programs.php b/api/v1/entries/programs.php index abd75ad87e..80b3bc422a 100644 --- a/api/v1/entries/programs.php +++ b/api/v1/entries/programs.php @@ -11,7 +11,7 @@ class ProgramsEntry extends Entry public function get() { $program = $this->loadController('program', 'browse'); - $program->browse(); + $program->browse($this->param('status', 'all'), $this->param('order', 'order_asc')); $data = $this->getData(); if(isset($data->status) and $data->status == 'success') diff --git a/api/v1/entries/projects.php b/api/v1/entries/projects.php index f8d69bbaf5..d0d886679d 100644 --- a/api/v1/entries/projects.php +++ b/api/v1/entries/projects.php @@ -11,18 +11,18 @@ class projectsEntry extends entry public function get() { $control = $this->loadController('project', 'browse'); - $control->browse(); + $control->browse(0, $this->param('status', 'all'), 0, $this->param('order', 'order_asc'), 0, $this->param('limit', 20), $this->param('page', 1)); $data = $this->getData(); if(isset($data->status) and $data->status == 'success') { - $pager = $data->data->pager; + $pager = $data->data->pager; $result = array(); foreach($data->data->projectStats as $project) { $result[] = $this->format($project, 'openedDate:time,lastEditedDate:time,closedDate:time,canceledDate:time'); } - return $this->send(200, array('page' => $pager->pageID, 'total' => $pager->recTotal, 'limit' => $pager->recPerPage, 'projects' => $result)); + return $this->send(200, array('page' => $pager->pageID, 'total' => $pager->recTotal, 'limit' => (int)$pager->recPerPage, 'projects' => $result)); } if(isset($data->status) and $data->status == 'fail') diff --git a/api/v1/entries/stories.php b/api/v1/entries/stories.php index fecf7c28a9..ffebfbcb3c 100644 --- a/api/v1/entries/stories.php +++ b/api/v1/entries/stories.php @@ -11,7 +11,7 @@ class storiesEntry extends entry public function get($productID) { $control = $this->loadController('product', 'browse'); - $control->browse($productID); + $control->browse($productID, $this->param('branch', 0), $this->param('type', ''), 0, 'story', $this->param('order', ''), $this->param('total', 0), $this->param('limit', 20), $this->param('page', 1)); $data = $this->getData(); if(isset($data->status) and $data->status == 'success') diff --git a/api/v1/entries/tasks.php b/api/v1/entries/tasks.php index 62b9121996..aa72e42120 100644 --- a/api/v1/entries/tasks.php +++ b/api/v1/entries/tasks.php @@ -11,7 +11,7 @@ class tasksEntry extends entry public function get($executionID) { $control = $this->loadController('execution', 'task'); - $control->task($executionID, 'all'); + $control->task($executionID, $this->param('status', 'all'), 0, $this->param('order', ''), $this->param('total', 0), $this->param('limit', 100), $this->param('page', 1)); $data = $this->getData(); if(isset($data->status) and $data->status == 'success') diff --git a/config/routes.php b/config/routes.php index 5440427857..bf01be4eaf 100644 --- a/config/routes.php +++ b/config/routes.php @@ -38,4 +38,7 @@ $routes['/user'] = 'user'; $routes['/programs'] = 'programs'; $routes['/programs/:id'] = 'program'; +$routes['/issues/:issueID'] = 'productIssue'; +$routes['/products/:productID/issues'] = 'productIssues'; + $config->routes = $routes; diff --git a/framework/api/entry.class.php b/framework/api/entry.class.php index 70a4ea7a3f..2ad612b32a 100644 --- a/framework/api/entry.class.php +++ b/framework/api/entry.class.php @@ -10,6 +10,8 @@ class entry extends baseEntry parent::__construct(); if(!isset($this->app->user)) $this->sendError(401, 'Unauthorized'); + + $this->dao = $this->loadModel('common')->dao; } } @@ -47,8 +49,9 @@ class baseEntry */ public function __construct() { - global $app; - $this->app = $app; + global $app, $config; + $this->app = $app; + $this->config = $config; $this->parseRequestBody(); } @@ -476,9 +479,8 @@ class baseEntry return gmdate("Y-m-d\TH:i:s\Z", strtotime($value)); } return $value; - case 'int': case 'bool': - return $value; + return boolval($value) ? true : false; default: return $value; } diff --git a/framework/base/router.class.php b/framework/base/router.class.php index ded80fbd7d..9bfa2a08c4 100644 --- a/framework/base/router.class.php +++ b/framework/base/router.class.php @@ -849,23 +849,22 @@ class baseRouter */ public function startSession() { - if(!defined('SESSION_STARTED')) - { - /* If request header has token, use it as session for authentication. */ - if(isset($_SERVER['HTTP_TOKEN'])) session_id($_SERVER['HTTP_TOKEN']); + if(defined('SESSION_STARTED')) return; - $sessionName = $this->config->sessionVar; - session_name($sessionName); - session_set_cookie_params(0, $this->config->webRoot, '', $this->config->cookieSecure, true); - if($this->config->customSession) session_save_path($this->getTmpRoot() . 'session'); - session_start(); + /* If request header has token, use it as session for authentication. */ + if(isset($_SERVER['HTTP_TOKEN'])) session_id($_SERVER['HTTP_TOKEN']); - $this->sessionID = session_id(); + $sessionName = $this->config->sessionVar; + session_name($sessionName); + session_set_cookie_params(0, $this->config->webRoot, '', $this->config->cookieSecure, true); + if($this->config->customSession) session_save_path($this->getTmpRoot() . 'session'); + session_start(); - if(isset($_GET[$this->config->sessionVar])) helper::restartSession($_GET[$this->config->sessionVar]); + $this->sessionID = session_id(); - define('SESSION_STARTED', true); - } + if(isset($_GET[$this->config->sessionVar])) helper::restartSession($_GET[$this->config->sessionVar]); + + define('SESSION_STARTED', true); } /** diff --git a/lib/base/pager/pager.class.php b/lib/base/pager/pager.class.php index f6ddc7f2c7..262b00539c 100644 --- a/lib/base/pager/pager.class.php +++ b/lib/base/pager/pager.class.php @@ -131,10 +131,10 @@ class basePager $this->setModuleName(); $this->setMethodName(); - $this->setRecTotal($recTotal); - $this->setRecPerPage($recPerPage); + $this->setRecTotal((int)$recTotal); + $this->setRecPerPage((int)$recPerPage); $this->setPageTotal(); - $this->setPageID($pageID); + $this->setPageID((int)$pageID); } /** diff --git a/module/common/model.php b/module/common/model.php index 525876f09e..97bb1d1a05 100644 --- a/module/common/model.php +++ b/module/common/model.php @@ -2024,6 +2024,29 @@ EOD; return $convertedItems; } + /** + * Check an entry of new API. + * + * @access public + * @return void + */ + private function checkNewEntry() + { + $entry = $this->loadModel('entry')->getByKey(session_id()); + if(!$entry or !$entry->account or !$this->checkIP($entry->ip)) return false; + + $user = $this->dao->findByAccount($entry->account)->from(TABLE_USER)->andWhere('deleted')->eq(0)->fetch(); + if(!$user) return false; + + $user->last = time(); + $user->rights = $this->loadModel('user')->authorize($user->account); + $user->groups = $this->user->getGroups($user->account); + $user->view = $this->user->grantUserView($user->account, $user->rights['acls']); + $user->admin = strpos($this->app->company->admins, ",{$user->account},") !== false; + $this->session->set('user', $user); + $this->app->user = $user; + } + /** * Check an entry. * @@ -2032,20 +2055,17 @@ EOD; */ public function checkEntry() { - if($this->isOpenMethod($_GET[$this->config->moduleVar], $_GET[$this->config->methodVar])) return true; + /* if the API is new version, goto checkNewEntry. */ + if($this->app->version) return $this->checkNewEntry(); - $this->loadModel('entry'); - if($this->session->valid_entry) - { - if(!$this->session->entry_code) $this->response('SESSION_CODE_MISSING'); - if($this->session->valid_entry != md5(md5($this->get->code) . $this->server->remote_addr)) $this->response('SESSION_VERIFY_FAILED'); - return true; - } + /* Old version. */ + if($this->isOpenMethod($_GET[$this->config->moduleVar], $_GET[$this->config->methodVar])) return true; if(!$this->get->code) $this->response('PARAM_CODE_MISSING'); if(!$this->get->token) $this->response('PARAM_TOKEN_MISSING'); - $entry = $this->entry->getByCode($this->get->code); + $entry = $this->loadModel('entry')->getByCode($this->get->code); + if(!$entry) $this->response('EMPTY_ENTRY'); if(!$entry->key) $this->response('EMPTY_KEY'); if(!$this->checkIP($entry->ip)) $this->response('IP_DENIED'); diff --git a/module/entry/model.php b/module/entry/model.php index e93e11f5cb..eafc10dae7 100644 --- a/module/entry/model.php +++ b/module/entry/model.php @@ -35,6 +35,18 @@ class entryModel extends model return $this->dao->select('*')->from(TABLE_ENTRY)->where('deleted')->eq('0')->andWhere('code')->eq($code)->fetch(); } + /** + * Get an entry by key. + * + * @param string $key + * @access public + * @return object + */ + public function getByKey($key) + { + return $this->dao->select('*')->from(TABLE_ENTRY)->where('deleted')->eq('0')->andWhere('`key`')->eq($key)->fetch(); + } + /** * Get entry list. * diff --git a/www/api.php b/www/api.php index a6d46cc923..eef2f73fc3 100644 --- a/www/api.php +++ b/www/api.php @@ -34,11 +34,11 @@ $app = router::createApp('pms', dirname(dirname(__FILE__)), 'api'); $common = $app->loadCommon(); /* Check entry. */ -if(!$app->version) $common->checkEntry(); +$common->checkEntry(); $common->loadConfigFromDB(); /* Set default params. */ -$config->requestType = 'GET'; +if(!$app->version) $config->requestType = 'GET'; $config->default->view = 'json'; $app->parseRequest();