* @package api * @version $Id$ * @link http://www.zentao.net */ class apiModel extends model { /* Status. */ const STATUS_DOING = 'doing'; const STATUS_DONE = 'done'; const STATUS_HIDDEN = 'hidden'; /* Scope. */ const SCOPE_QUERY = 'query'; const SCOPE_FORM_DATA = 'formData'; const SCOPE_PATH = 'path'; const SCOPE_BODY = 'body'; const SCOPE_HEADER = 'header'; const SCOPE_COOKIE = 'cookie'; /* Params. */ const PARAMS_TYPE_CUSTOM = 'custom'; /** * Create release. * * @param object $data * @access public * @return int */ public function publishLib($data) { /* Get lib modules list. */ $modules = $this->dao->select('*')->from(TABLE_MODULE) ->where('root')->eq((int)$data->lib) ->andWhere('type')->eq('api') ->andWhere('deleted')->eq(0) ->orderBy('grade desc, `order`') ->fetchAll(); /* Get all api list. */ $apis = $this->dao->select('id,version')->from(TABLE_API) ->where('lib')->eq($data->lib) ->andWhere('deleted')->eq(0) ->fetchAll(); /* Get all struct list. */ $structs = $this->dao->select('id,version')->from(TABLE_APISTRUCT) ->where('lib')->eq($data->lib) ->andWhere('deleted')->eq(0) ->fetchAll(); $snap = array('modules' => $modules, 'apis' => $apis, 'structs' => $structs); $data->snap = json_encode($snap); $this->dao->insert(TABLE_API_LIB_RELEASE)->data($data) ->autoCheck() ->batchCheck($this->config->api->createrelease->requiredFields, 'notempty') ->exec(); return dao::isError() ? false : $this->dao->lastInsertID(); } /** * Delete a lib publish. * * @param int $id * @access public * @return void */ public function deleteRelease($id) { $this->dao->delete()->from(TABLE_API_LIB_RELEASE) ->where('id')->eq($id) ->exec(); } /** * Create an api doc. * * @access public * @return object | bool */ public function create() { $now = helper::now(); $data = fixer::input('post') ->trim('title,path') ->remove('type') ->skipSpecial('params,response') ->add('addedBy', $this->app->user->account) ->add('addedDate', $now) ->add('editedBy', $this->app->user->account) ->add('editedDate', $now) ->add('version', 1) ->setDefault('product,module', 0) ->get(); $this->dao->insert(TABLE_API)->data($data) ->autoCheck() ->batchCheck($this->config->api->create->requiredFields, 'notempty') ->check('title', 'unique', "lib = $data->lib AND module = $data->module") ->check('path', 'unique', "lib = $data->lib AND module = $data->module AND method = '$data->method'") ->exec(); if(dao::isError()) return false; $data->id = $this->dao->lastInsertID(); $apiSpec = $this->getApiSpecByData($data); $this->dao->replace(TABLE_API_SPEC)->data($apiSpec)->exec(); return $data; } /** * Create a global struct. * * @param object $data * @access public * @return int */ public function createStruct($data) { $data->version = 1; $this->dao->insert(TABLE_APISTRUCT)->data($data) ->autoCheck() ->batchCheck($this->config->api->struct->requiredFields, 'notempty') ->exec(); if(dao::isError()) return false; $id = $this->dao->lastInsertID(); /* Create a struct version. */ $version = array( 'name' => $data->name, 'type' => $data->type, 'desc' => $data->desc, 'version' => $data->version, 'attribute' => $data->attribute, 'addedBy' => $data->addedBy, 'addedDate' => $data->addedDate ); $this->dao->insert(TABLE_APISTRUCT_SPEC)->data($version)->exec(); if(dao::isError()) return false; return $id; } /** * Update a struct. * * @param int $id * @access public * @return array */ public function updateStruct($id) { $old = $this->dao->findByID($id)->from(TABLE_APISTRUCT)->fetch(); $now = helper::now(); $data = fixer::input('post') ->skipSpecial('attribute') ->add('lib', $old->lib) ->add('editedBy', $this->app->user->account) ->add('editedDate', $now) ->get(); unset($data->addedBy); unset($data->addedDate); $data->version = $old->version + 1; $this->dao->update(TABLE_APISTRUCT) ->data($data)->autoCheck() ->batchCheck($this->config->api->struct->requiredFields, 'notempty') ->where('id')->eq($id) ->exec(); if(dao::isError()) return false; /* Create a struct version */ $version = array( 'name' => $data->name, 'type' => $data->type, 'desc' => $data->desc, 'version' => $data->version, 'attribute' => $data->attribute, 'addedBy' => $data->editedBy, 'addedDate' => $data->editedDate ); $this->dao->insert(TABLE_APISTRUCT_SPEC)->data($version)->exec(); return common::createChanges($old, $data); } /** * Update an api doc. * * @param int $apiID * @access public * @return bool|array */ public function update($apiID) { $oldApi = $this->dao->findByID($apiID)->from(TABLE_API)->fetch(); if(!empty($_POST['editedDate']) and $oldApi->editedDate != $this->post->editedDate) { dao::$errors[] = $this->lang->error->editedByOther; return false; } $now = helper::now(); $data = fixer::input('post') ->skipSpecial('params,response') ->add('editedBy', $this->app->user->account) ->add('editedDate', $now) ->add('version', $oldApi->version) ->setDefault('product,module', 0) ->remove('type') ->get(); $changes = common::createChanges($oldApi, $data); if(!empty($changes)) $data->version = $oldApi->version + 1; $this->dao->update(TABLE_API) ->data($data) ->autoCheck() ->batchCheck($this->config->api->edit->requiredFields, 'notempty') ->where('id')->eq($apiID) ->exec(); $data->id = $apiID; $apiSpec = $this->getApiSpecByData($data); $this->dao->replace(TABLE_API_SPEC)->data($apiSpec)->exec(); return $changes; } /** * Get struct list by api doc id. * * @param int $id * @access public * @return array */ public function getStructListByLibID($id) { $res = $this->dao->select('*') ->from(TABLE_APISTRUCT) ->where('lib')->eq($id) ->fetchAll(); array_map(function ($item) { $item->attribute = json_decode($item->attribute, true); return $item; }, $res); return $res; } /** * Get a struct info. * * @param int $id * @access public * @return object */ public function getStructByID($id) { $model = $this->dao->select('*') ->from(TABLE_APISTRUCT) ->where('id')->eq($id) ->fetch(); if($model) $model->attribute = json_decode($model->attribute, true); return $model; } /** * Get release. * * @param int $libID * @param string $type * @param int $param * @access public * @return object */ public function getRelease($libID = 0, $type = '', $param = 0) { $model = $this->dao->select('*')->from(TABLE_API_LIB_RELEASE) ->where('1 = 1') ->beginIF($libID)->andWhere('lib')->eq($libID)->fi() ->beginIF($type == 'byVersion')->andWhere('version')->eq($param)->fi() ->beginIF($type == 'byId')->andWhere('id')->eq($param)->fi() ->fetch(); if($model) $model->snap = json_decode($model->snap, true); return $model; } /** * Get Versions by api id * * @param int $libID * @access public * @return array */ public function getReleaseListByApi($libID) { return $this->dao->select('*')->from(TABLE_API_LIB_RELEASE)->where('lib')->eq($libID)->fetchAll('id'); } /** * Get api doc by id. * * @param int $id * @param int $version * @param int $release * @access public * @return object */ public function getLibById($id, $version = 0, $release = 0) { if($release) { $rel = $this->getRelease(0, 'byId', $release); foreach($rel->snap['apis'] as $api) { if($api['id'] == $id) $version = $api['version']; } } if($version) { $fields = 'spec.*,api.id,api.product,api.lib,api.version,doc.name as libName,module.name as moduleName,api.editedBy,api.editedDate'; } else { $fields = 'api.*,doc.name as libName,module.name as moduleName'; } $model = $this->dao->select($fields)->from(TABLE_API)->alias('api') ->beginIF($version)->leftJoin(TABLE_API_SPEC)->alias('spec')->on('api.id = spec.doc')->fi() ->leftJoin(TABLE_DOCLIB)->alias('doc')->on('api.lib = doc.id') ->leftJoin(TABLE_MODULE)->alias('module')->on('api.module = module.id') ->where('api.id')->eq($id) ->beginIF($version)->andWhere('spec.version')->eq($version)->fi() ->fetch(); if($model) { $model->params = json_decode($model->params, true); $model->response = json_decode($model->response, true); } return $model; } /** * Get api list by release. * * @param object $release * @param string $where * @access public * @return array */ public function getApiListByRelease($release, $where = '1 = 1 ') { $strJoin = array(); if(isset($release->snap['apis'])) { foreach($release->snap['apis'] as $api) { $strJoin[] = "(spec.doc = {$api['id']} and spec.version = {$api['version']} )"; } } if($strJoin) $where .= 'and (' . implode(' or ', $strJoin) . ')'; $list = $this->dao->select('api.lib,spec.*,api.id')->from(TABLE_API)->alias('api') ->leftJoin(TABLE_API_SPEC)->alias('spec')->on('api.id = spec.doc') ->where($where) ->fetchAll(); return $list; } /** * Get api doc list by module id. * * @param int $libID * @param int $moduleID * @param int $release * @return array $list */ public function getListByModuleId($libID = 0, $moduleID = 0, $release = 0) { /* Get release info. */ if($release > 0) { $rel = $this->getRelease(0, 'byId', $release); $where = "1=1 and lib = $libID "; if($moduleID > 0 and isset($rel->snap['modules'])) { $sub = array(); foreach($rel->snap['modules'] as $module) { $tmp = explode(',', $module['path']); if(in_array($moduleID, $tmp)) { $sub[] = $module['id']; } } if($sub) $where .= 'and module in (' . implode(',', $sub) . ')'; } $list = $this->getApiListByRelease($rel, $where); } else { if($moduleID > 0) { $sub = $this->dao->select('id')->from(TABLE_MODULE)->where('FIND_IN_SET(' . $moduleID . ', path)')->processSQL(); $where = 'module in (' . $sub . ')'; } else { $where = 'lib = ' . $libID; } $list = $this->dao->select('*') ->from(TABLE_API) ->where($where) ->andWhere('deleted')->eq(0) ->fetchAll(); } array_map(function ($item) { $item->params = json_decode($item->params, true); $item->response = json_decode($item->response, true); return $item; }, $list); return $list; } /** * Get status text by status. * * @param string $status * @access public * @return string */ public static function getApiStatusText($status) { global $lang; switch($status) { case static::STATUS_DOING: { return $lang->api->doing; } case static::STATUS_DONE: { return $lang->api->done; } } } /** * @param int $libID * @param string $pager * @param string $orderBy * @access public * @return array */ public function getStructByQuery($libID, $pager = '', $orderBy = '') { return $this->dao->select('s.*,user.realname as addedName')->from(TABLE_APISTRUCT)->alias('s') ->leftJoin(TABLE_USER)->alias('user')->on('user.account = s.addedBy') ->where('s.deleted')->eq(0) ->andWhere('s.lib')->eq($libID) ->orderBy($orderBy) ->page($pager) ->fetchAll(); } /** * Get struct list by release. * * @param object $release * @param string $where * @param string $orderBy * @access public * @return array */ public function getStructListByRelease($release, $where = '1 = 1 ', $orderBy = 'id') { $strJoin = array(); if(isset($release->snap['structs'])) { foreach($release->snap['structs'] as $struct) { $strJoin[] = "(object.id = {$struct['id']} and spec.version = {$struct['version']} )"; } } if($strJoin) $where .= 'and (' . implode(' or ', $strJoin) . ')'; $list = $this->dao->select('object.lib,spec.name,spec.type,spec.desc,spec.attribute,spec.version,spec.addedBy,spec.addedDate,object.id,user.realname as addedName')->from(TABLE_APISTRUCT)->alias('object') ->leftJoin(TABLE_APISTRUCT_SPEC)->alias('spec')->on('object.name = spec.name') ->leftJoin(TABLE_USER)->alias('user')->on('user.account = spec.addedBy') ->where($where) ->orderBy($orderBy) ->fetchAll(); return $list; } /** * @param int $libID * @param string $pager * @param string $orderBy * @access public * @return array */ public function getReleaseByQuery($libID, $pager = '', $orderBy = '') { return $this->dao->select('*')->from(TABLE_API_LIB_RELEASE) ->where('lib')->eq($libID) ->orderBy($orderBy) ->page($pager) ->fetchAll(); } /** * Get struct tree by lib id * * @param int $libID * @param int $structID * @access public * @return string */ public function getStructTreeByLib($libID = 0, $structID = 0) { $list = $this->getStructListByLibID($libID); $html = "