* @package api * @version $Id$ * @link https://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 $formData * @access public * @return bool */ public function publishLib(object $formData): bool { /* Get lib modules list. */ $modules = $this->dao->select('*')->from(TABLE_MODULE) ->where('root')->eq((int)$formData->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($formData->lib) ->andWhere('deleted')->eq(0) ->fetchAll(); /* Get all struct list. */ $structs = $this->dao->select('id,version')->from(TABLE_APISTRUCT) ->where('lib')->eq($formData->lib) ->andWhere('deleted')->eq(0) ->fetchAll(); $snap = array('modules' => $modules, 'apis' => $apis, 'structs' => $structs); $formData->snap = json_encode($snap); $this->dao->insert(TABLE_API_LIB_RELEASE)->data($formData) ->autoCheck() ->batchCheck($this->config->api->createrelease->requiredFields, 'notempty') ->exec(); return !dao::isError(); } /** * 删除一条发布。 * Delete a lib publish. * * @param int $id * @access public * @return bool */ public function deleteRelease(int $id): bool { $this->dao->delete()->from(TABLE_API_LIB_RELEASE)->where('id')->eq($id)->exec(); return !dao::isError(); } /** * 创建一个接口。 * Create an api doc. * * @param object $formData * @access public * @return int|false */ public function create(object $formData): int|false { $this->dao->insert(TABLE_API)->data($formData) ->autoCheck() ->batchCheck($this->config->api->create->requiredFields, 'notempty') ->check('title', 'unique', "lib = $formData->lib AND module = $formData->module") ->check('path', 'unique', "lib = $formData->lib AND module = $formData->module AND method = '$formData->method'") ->exec(); if(dao::isError()) return false; /* 维护历史记录。 */ $apiID = $this->dao->lastInsertID(); $this->loadModel('action')->create('api', $apiID, 'Created', '', '', '', false); /* 维护接口文档的历史版本。 */ $formData->id = $apiID; $apiSpec = $this->getApiSpecByData($formData); $this->dao->insert(TABLE_API_SPEC)->data($apiSpec)->exec(); return $apiID; } /** * 更新一个接口。 * Update an api doc. * * @param object $formData * @access public * @return bool */ public function update(object $formData): bool { $oldApi = $this->dao->findByID($formData->id)->from(TABLE_API)->fetch(); if(empty($formData->lib)) $formData->lib = $oldApi->lib; if(!empty($formData->editedDate) && $oldApi->editedDate != $formData->editedDate) { /* 如果提交之前已有其他人变更接口则提示错误信息。 */ dao::$errors['message'][] = $this->lang->error->editedByOther; return false; } $formData->editedDate = helper::now(); /* 仅在有变更的情况下才变更版本号。 */ $changes = common::createChanges($oldApi, $formData); if(!empty($changes)) $formData->version = $oldApi->version + 1; $this->dao->update(TABLE_API) ->data($formData) ->autoCheck() ->batchCheck($this->config->api->edit->requiredFields, 'notempty') ->check('title', 'unique', "id != $formData->id AND lib = $formData->lib AND module = $formData->module") ->check('path', 'unique', "id != $formData->id AND lib = $formData->lib AND module = $formData->module AND method = '$formData->method'") ->where('id')->eq($formData->id) ->exec(); if(dao::isError()) return false; /* 维护历史记录。 */ if($changes) { $actionID = $this->loadModel('action')->create('api', $formData->id, 'edited', '', '', '', false); $this->action->logHistory($actionID, $changes); } /* 维护接口文档的历史版本。 */ $apiSpec = $this->getApiSpecByData($formData); $this->dao->delete()->from(TABLE_API_SPEC)->where('doc')->eq($apiSpec['doc'])->andWhere('version')->eq($apiSpec['version'])->exec(); $this->dao->insert(TABLE_API_SPEC)->data($apiSpec)->exec(); return !dao::isError(); } /** * 创建数据结构。 * Create a global struct. * * @param object $formData * @access public * @return bool */ public function createStruct(object $formData): bool { $this->dao->insert(TABLE_APISTRUCT)->data($formData) ->autoCheck() ->batchCheck($this->config->api->struct->requiredFields, 'notempty') ->exec(); if(dao::isError()) return false; /* 维护历史记录。 */ $structID = $this->dao->lastInsertID(); $this->loadModel('action')->create('apistruct', $structID, 'Created'); /* 维护数据结构的历史版本。 */ $structSpec = $this->getApiStructSpecByData($formData); $this->dao->insert(TABLE_APISTRUCT_SPEC)->data($structSpec)->exec(); return !dao::isError(); } /** * 更新数据结构。 * Update a struct. * * @param object $formData * @access public * @return bool */ public function updateStruct(object $formData): bool { $oldData = $this->dao->findByID($formData->id)->from(TABLE_APISTRUCT)->fetch(); $this->dao->update(TABLE_APISTRUCT) ->data($formData)->autoCheck() ->batchCheck($this->config->api->struct->requiredFields, 'notempty') ->where('id')->eq($formData->id) ->exec(); if(dao::isError()) return false; /* 维护历史记录。 */ $changes = common::createChanges($oldData, $formData); if($changes) { $actionID = $this->loadModel('action')->create('apistruct', $formData->id, 'Edited'); $this->action->logHistory($actionID, $changes); } /* 维护数据结构的历史版本。 */ $structSpec = $this->getApiStructSpecByData($formData); $this->dao->insert(TABLE_APISTRUCT_SPEC)->data($structSpec)->exec(); return !dao::isError(); } /** * 根据文档库ID获取数据结构列表。 * Get struct list by api doc id. * * @param int $id * @access public * @return array */ public function getStructListByLibID(int $id): array { $structList = $this->dao->select('*')->from(TABLE_APISTRUCT)->where('lib')->eq($id)->fetchAll(); foreach($structList as $struct) { if(!isset($struct->attribute)) continue; $struct->attribute = json_decode($struct->attribute, true); } return $structList; } /** * 根据ID获取数据结构信息。 * Get a struct info. * * @param int $id * @access public * @return object|false */ public function getStructByID(int $id): object|false { $struct = $this->dao->select('*')->from(TABLE_APISTRUCT)->where('id')->eq($id)->fetch(); if($struct) $struct->attribute = json_decode($struct->attribute, true); return $struct; } /** * 根据版本号或者发布ID获取发布信息。 * Get release. * * @param int $libID * @param string $type byVersion | byID * @param string|int $param * @access public * @return object|false */ public function getRelease(int $libID = 0, string $type = 'byID', string|int $param = '0'): object|false { $release = $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($release) $release->snap = json_decode($release->snap, true); return $release; } /** * 根据文档库ID获取发布列表。 * Get releases by lib id. * * @param int $libID * @access public * @return array */ public function getReleaseListByLib(int $libID): array { return $this->dao->select('*')->from(TABLE_API_LIB_RELEASE)->where('lib')->eq($libID)->fetchAll('id'); } /** * 根据接口ID获取接口信息。 * Get api doc by id. * * @param int $id * @param int $version * @param int $releaseID * @access public * @return object|false */ public function getByID(int $id, int $version = 0, int $releaseID = 0): object|false { if($releaseID) { $release = $this->getRelease(0, 'byID', $releaseID); if(!empty($release->snap['apis'])) { foreach($release->snap['apis'] as $api) { if($api['id'] == $id) $version = $api['version']; } } } /* 如果要根据版本号查询,那主要查询的是spec表,否则查询api表即可。 */ if($version) { $fields = 'spec.*,api.id,api.product,api.lib,doc.name as libName,module.name as moduleName,api.editedBy,api.editedDate'; } else { $fields = 'api.*,doc.name as libName,module.name as moduleName'; } $api = $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($api) { $api->params = json_decode($api->params, true); $api->response = json_decode($api->response, true); } return $api; } /** * 获取发布下的所有接口文档。 * Get api list by release. * * @param object $release * @param string $where * @access public * @return array */ public function getApiListByRelease(object $release, string $where = '1 = 1 '): array { /* 根据发布中的apis生成查询条件。 */ $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) . ')'; $apiList = $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 $apiList; } /** * 根据发布ID或者模块ID获取接口列表。 * Get api doc list by module id or release id. * * @param int $libID * @param int $moduleID * @param int $releaseID * @param object $pager * @return array */ public function getListByModuleID(int $libID = 0, int $moduleID = 0, int $releaseID = 0, ?object $pager = null): array { /* Get release info. */ if($releaseID > 0) { /* 根据发布ID获取发信息。 */ $release = $this->getRelease(0, 'byID', $releaseID); $where = "1 = 1 and lib = $libID "; if($moduleID > 0 && isset($release->snap['modules'])) { /* 根据发布中的modules生成查询条件。 */ $sub = array(); foreach($release->snap['modules'] as $module) { $tmp = explode(',', $module['path']); if(in_array($moduleID, $tmp)) $sub[] = $module['id']; } if($sub) $where .= 'and module in (' . implode(',', $sub) . ')'; } $apiList = $this->getApiListByRelease($release, $where); } else { /* 根据模块ID获取发布信息。 */ if($moduleID > 0) { $sub = $this->dao->select('id')->from(TABLE_MODULE)->where('FIND_IN_SET(' . $moduleID . ', path)')->processSQL(); $where = 'module in (' . $sub . ')'; } else { /* 没有模块ID的根据libID来获取发布信息。 */ $where = 'lib = ' . $libID; } $apiList = $this->dao->select('*')->from(TABLE_API)->where($where)->andWhere('deleted')->eq(0)->page($pager)->fetchAll('', false); } foreach($apiList as $api) { $api->params = json_decode($api->params, true); $api->response = json_decode($api->response, true); } return $apiList; } /** * 获取接口状态对应的语言项。 * Get status text by status. * * @param string $status * @access public * @return string */ public static function getApiStatusText(string $status): string { global $lang; switch($status) { case static::STATUS_DOING: { return $lang->api->doing; } case static::STATUS_DONE: { return $lang->api->done; } } return $status; } /** * 获取指定文档库下的数据结构列表。 * Get struct list by lib id. * * @param int $libID * @param object $pager * @param string $orderBy * @access public * @return array */ public function getStructByQuery(int $libID, ?object $pager = null, string $orderBy = ''): array { return $this->dao->select('t1.*,t2.realname as addedName')->from(TABLE_APISTRUCT)->alias('t1') ->leftJoin(TABLE_USER)->alias('t2')->on('t2.account = t1.addedBy') ->where('t1.deleted')->eq(0) ->andWhere('t1.lib')->eq($libID) ->orderBy($orderBy) ->page($pager) ->fetchAll(); } /** * 获取指定发布下的数据结构列表。 * Get struct list by release. * * @param object $release * @param string $where * @param object $pager * @param string $orderBy * @access public * @return array */ public function getStructListByRelease(object $release, string $where = '1 = 1 ', ?object $pager = null, string $orderBy = 'id'): array { $strJoin = array(); if(isset($release->snap['structs'])) { /* 根据发布中的structs生成查询条件。 */ foreach($release->snap['structs'] as $struct) { $strJoin[] = "(object.id = {$struct['id']} and spec.version = {$struct['version']} )"; } } if($strJoin) $where .= 'and (' . implode(' or ', $strJoin) . ')'; return $this->dao->select('object.id,object.lib,spec.name,spec.type,spec.desc,spec.attribute,spec.version,spec.addedBy,spec.addedDate,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) ->page($pager) ->fetchAll(); } /** * 获取指定文档库下的数据结构列表。 * Get release list by lib id. * * @param array $libID * @param object $pager * @param string $orderBy * @access public * @return array */ public function getReleaseByQuery(array $libID, ?object $pager = null, string $orderBy = ''): array { return $this->dao->select('*')->from(TABLE_API_LIB_RELEASE) ->where('lib')->in($libID) ->orderBy($orderBy) ->page($pager) ->fetchAll(); } /** * 查询SQL语句并返回结果。 * Query sql. * * @param string $sql * @param string $keyField * @access public * @return array */ public function sql(string $sql, string $keyField = ''): array { /* 检查允许接口调用SQL的配置项是否打开。 */ if(!$this->config->features->apiSQL) return array('status' => 'fail', 'message' => sprintf($this->lang->api->error->disabled, '$config->features->apiSQL')); $sql = trim($sql); if(strpos($sql, ';') !== false) $sql = substr($sql, 0, strpos($sql, ';')); /* 如果没传SQL参数,则无法进行下一步。 */ if(empty($sql)) return array('status' => 'fail', 'message' => ''); /* 如果SQL语句中没有select单词,则无法进行下一步。 */ if(stripos($sql, 'select ') !== 0) return array('status' => 'fail', 'message' => $this->lang->api->error->onlySelect); try { $stmt = $this->dbh->query($sql); $rows = array(); if(empty($keyField)) { $rows = $stmt->fetchAll(); } else { /* 用keyFiled作为键展示查询结果。 */ while($row = $stmt->fetch()) $rows[$row->$keyField] = $row; } $result = array('status' => 'success', 'data' => $rows); } catch(PDOException $e) { $result = array('status' => 'fail', 'message' => $e->getMessage()); } return $result; } /** * 创建初始数据。 * Create demo data. * * @param string $name * @param string $baseUrl * @param string $version * @access public * @return int */ public function createDemoData(string $name, string $baseUrl, string $version = '16.0'): int { /* Replace the doc lib name to api lib name. */ $this->loadModel('action'); $this->app->loadLang('doc'); $this->lang->doclib->name = $this->lang->doclib->apiLibName; /* 获取当前用户或者系统首位用户。 */ $firstAccount = $this->dao->select('account')->from(TABLE_USER)->orderBy('id_asc')->limit(1)->fetch('account'); $currentAccount = isset($this->app->user->account) ? $this->app->user->account : $firstAccount; $libID = $this->createDemoLib($name, $baseUrl, $currentAccount); $moduleMap = $this->createDemoModule($libID, $version); $apiMap = $this->createDemoApi($libID, $version, $moduleMap, $currentAccount); $this->createDemoStruct($libID, $version, $currentAccount); $this->createDemoStructSpec($version, $currentAccount); $this->createDemoApiSpec($version, $apiMap, $moduleMap, $currentAccount); return $libID; } /** * 创建文档库初始数据。 * Create lib demo data. * * @param string $name * @param string $baseUrl * @param string $currentAccount * @access private * @return int */ private function createDemoLib(string $name, string $baseUrl, string $currentAccount): int { $lib = new stdclass(); $lib->type = 'api'; $lib->name = $name; $lib->baseUrl = $baseUrl; $lib->acl = 'open'; $lib->users = ',' . $currentAccount . ','; $this->dao->insert(TABLE_DOCLIB)->data($lib)->autoCheck()->batchCheck($this->config->api->createlib->requiredFields, 'notempty')->check('name', 'unique', "`type` = 'api'")->exec(); $libID = $this->dao->lastInsertID(); return $libID; } /** * 创建数据结构初始数据。 * Create struct demo data. * * @param int $libID * @param string $version * @param string $currentAccount * @access private * @return bool */ private function createDemoStruct(int $libID, string $version, string $currentAccount): bool { $structs = $this->getDemoData('apistruct', $version); foreach($structs as $struct) { unset($struct->id); $struct->lib = $libID; $struct->addedBy = $currentAccount; $struct->addedDate = helper::now(); $struct->editedBy = $currentAccount; $struct->editedDate = helper::now(); $this->dao->insert(TABLE_APISTRUCT)->data($struct)->exec(); } return !dao::isError(); } /** * 创建多版本数据结构初始数据。 * Create struct spec demo data. * * @param string $version * @param string $currentAccount * @access private * @return bool */ private function createDemoStructSpec(string $version, string $currentAccount): bool { $specs = $this->getDemoData('apistruct_spec', $version); foreach($specs as $spec) { unset($spec->id); $spec->addedBy = $currentAccount; $spec->addedDate = helper::now(); $this->dao->insert(TABLE_APISTRUCT_SPEC)->data($spec)->exec(); } return !dao::isError(); } /** * 创建文档库模块初始数据。 * Create module demo data. * * @param int $libID * @param string $version * @access private * @return array */ private function createDemoModule(int $libID, string $version): array { $moduleMap = array(); $modules = $this->getDemoData('module', $version); foreach($modules as $module) { if($module->type != 'api') continue; $oldID = $module->id; unset($module->id); $module->root = $libID; $this->dao->insert(TABLE_MODULE)->data($module)->exec(); $newID = $this->dao->lastInsertID(); $this->dao->update(TABLE_MODULE)->set('path')->eq(",$newID,")->where('id')->eq($newID)->exec(); $moduleMap[$oldID] = $newID; } return $moduleMap; } /** * 创建接口文档初始数据。 * Create api demo data. * * @param int $libID * @param string $version * @param array $moduleMap * @param string $currentAccount * @access private * @return array */ private function createDemoApi(int $libID, string $version, array $moduleMap, string $currentAccount): array { $this->loadModel('action'); $apiMap = array(); $apis = $this->getDemoData('api', $version); foreach($apis as $api) { $oldID = $api->id; unset($api->id); $api->lib = $libID; $api->module = $moduleMap[$api->module]; $api->addedBy = $currentAccount; $api->addedDate = helper::now(); $api->editedBy = $currentAccount; $api->editedDate = helper::now(); $this->dao->insert(TABLE_API)->data($api)->exec(); $newID = $this->dao->lastInsertID(); $this->action->create('api', $newID, 'Created', '', '', $currentAccount); $apiMap[$oldID] = $newID; } return $apiMap; } /** * 创建多版本接口文档初始化数据。 * Create api spec demo data. * * @param string $version * @param array $apiMap * @param array $moduleMap * @param string $currentAccount * @access private * @return bool */ private function createDemoApiSpec(string $version, array $apiMap, array $moduleMap, string $currentAccount): bool { $specs = $this->getDemoData('apispec', $version); foreach($specs as $spec) { unset($spec->id); $spec->doc = $apiMap[$spec->doc]; $spec->module = zget($moduleMap, $spec->module, 0); $spec->owner = $currentAccount; $spec->addedBy = $currentAccount; $spec->addedDate = helper::now(); $this->dao->insert(TABLE_API_SPEC)->data($spec)->exec(); } return !dao::isError(); } /** * 获取指定表的初始化数据。 * Get demo data. * * @param string $table * @param string $version * @access private * @return array */ public function getDemoData(string $table, string $version): array { $file = $this->app->getAppRoot() . 'db' . DS . 'api' . DS . $version . DS . $table; return unserialize(preg_replace_callback('#s:(\d+):"(.*?)";#s', function($match){return 's:'.strlen($match[2]).':"'.$match[2].'";';}, file_get_contents($file))); } /** * 根据搜索条件查询并返回接口文档列表。 * Get api by search. * * @param int $libID * @param int $queryID * @param string $objectType product|project * @param array $libs * @access public * @return array */ public function getApiListBySearch(int $libID, int $queryID, string $objectType = '', array $libs = array()): array { $queryName = $objectType ? $objectType . 'apiDocQuery' : 'apiQuery'; $queryForm = $objectType ? $objectType . 'apiDocForm' : 'apiForm'; if($queryID) { $query = $this->loadModel('search')->getQuery($queryID); if($query) { $this->session->set($queryName, $query->sql); $this->session->set($queryForm, $query->form); } else { $this->session->set($queryName, ' 1 = 1'); } } else { if($this->session->$queryName == false) $this->session->set($queryName, ' 1 = 1'); } $apiQuery = $this->session->$queryName; if(strpos($apiQuery, "`lib` = 'all'") !== false) $apiQuery = str_replace("`lib` = 'all'", '1', $apiQuery); $apiList = $this->dao->select('*')->from(TABLE_API) ->where('deleted')->eq(0) ->andWhere($apiQuery) ->beginIF($libID)->andWhere('`lib`')->eq($libID)->fi() ->beginIF(!empty($libs))->andWhere('`lib`')->in($libs)->fi() ->fetchAll(); return $apiList; } /** * 获取文档库所属产品或者项目的下拉菜单。 * Get ordered objects for dic. * * @access public * @return array */ public function getOrderedObjects(): array { $normalObjects = $closedObjects = array(); /* 获取接口库所属产品的产品列表。 */ $libs = $this->loadModel('doc')->getApiLibs(); $products = $this->dao->select('t1.id, t1.order, t1.name, t1.status')->from(TABLE_PRODUCT)->alias('t1') ->leftJoin(TABLE_DOCLIB)->alias('t2')->on('t2.product=t1.id') ->where('t2.id')->gt(0) ->andWhere('t1.vision')->eq($this->config->vision) ->andWhere('t1.deleted')->eq(0) ->andWhere('t2.id')->in(array_keys($libs)) ->orderBy('order_asc') ->fetchAll('id'); foreach($products as $id => $product) { /* 筛选出正常的和关闭产品名称。 */ if($product->status == 'normal') $normalObjects['product'][$id] = $product->name; if($product->status == 'closed') $closedObjects['product'][$id] = $product->name; } /* 获取接口库所属项目的项目列表。 */ $projects = $this->dao->select('t1.id, t1.order, t1.name, t1.status')->from(TABLE_PROJECT)->alias('t1') ->leftJoin(TABLE_DOCLIB)->alias('t2')->on('t2.project=t1.id') ->where('t2.id')->gt(0) ->andWhere('t1.vision')->eq($this->config->vision) ->andWhere('t1.deleted')->eq(0) ->beginIF(!$this->app->user->admin)->andWhere('t1.id')->in($this->app->user->view->projects)->fi() ->andWhere('t2.id')->in(array_keys($libs)) ->orderBy('t1.hasProduct_asc, order_asc') ->fetchAll('id'); foreach($projects as $id => $project) { /* 筛选出正常的和关闭项目名称。 */ if($project->status != 'done' && $project->status != 'closed') $normalObjects['project'][$id] = $project->name; if($project->status == 'done' || $project->status == 'closed') $closedObjects['project'][$id] = $project->name; } return array($normalObjects, $closedObjects); } /** * 获取分组后的对象列表。 * * @access public * @return array */ public function getGroupedObjects(): array { $libs = $this->loadModel('doc')->getApiLibs(); $libIDs = array_keys($libs); /* 获取接口库所属产品的产品列表。 */ $products = $this->dao->select('t1.id, t1.order, t1.name, t1.status, t1.program')->from(TABLE_PRODUCT)->alias('t1') ->leftJoin(TABLE_DOCLIB)->alias('t2')->on('t2.product=t1.id') ->where('t2.id')->gt(0) ->andWhere('t1.vision')->eq($this->config->vision) ->andWhere('t1.deleted')->eq(0) ->andWhere('t2.id')->in($libIDs) ->orderBy('order_asc') ->fetchAll('id'); /* 获取接口库所属项目的项目列表。 */ $projects = $this->dao->select('t1.id, t1.order, t1.name, t1.status, t1.parent')->from(TABLE_PROJECT)->alias('t1') ->leftJoin(TABLE_DOCLIB)->alias('t2')->on('t2.project=t1.id') ->where('t2.id')->gt(0) ->andWhere('t1.vision')->eq($this->config->vision) ->andWhere('t1.deleted')->eq(0) ->beginIF(!$this->app->user->admin)->andWhere('t1.id')->in($this->app->user->view->projects)->fi() ->andWhere('t2.id')->in($libIDs) ->orderBy('t1.hasProduct_asc, order_asc') ->fetchAll('id'); $nolinks = array(); foreach($libs as $lib) { if($lib->product != 0 && isset($products[$lib->product]) && !isset($products[$lib->product]->firstLib)) $products[$lib->product]->firstLib = $lib->id; if($lib->project != 0 && isset($projects[$lib->project]) && !isset($projects[$lib->project]->firstLib)) $projects[$lib->project]->firstLib = $lib->id; if($lib->product != 0 || $lib->project != 0 || $lib->execution != 0) continue; $nolinks[$lib->id] = $lib; } return array('product' => $products, 'project' => $projects, 'nolink' => $nolinks); } /** * 获取有权限的接口文档列表。 * Get priv Apis. * * @param string $mode * @access public * @return array */ public function getPrivApis(string $mode = ''): array { $libs = $this->dao->select('*')->from(TABLE_DOCLIB) ->where('type')->eq('api') ->andWhere('vision')->eq($this->config->vision) ->fetchAll('id'); /* 过滤掉没有权限的文档库。 */ $this->loadModel('doc'); foreach($libs as $libID => $lib) { if(!$this->doc->checkPrivLib($lib)) unset($libs[$libID]); } return $this->dao->select('id')->from(TABLE_API) ->where('lib')->in(array_keys($libs)) ->beginIF($mode != 'all')->andWhere('deleted')->eq(0)->fi() ->fetchAll('id'); } /** * 初始化搜索表单。 * Build search form. * * @param object $lib * @param int $queryID * @param string $actionURL * @param array $libs * @param string $type product|project * @access public * @return void */ public function buildSearchForm(object $lib, int $queryID, string $actionURL, array $libs = array(), string $type = '') { if(empty($lib)) return; $libPairs = array('' => '', $lib->id => $lib->name); $this->config->api->search['module'] = 'api'; if(!empty($libs)) { foreach($libs as $lib) { if(empty($lib)) continue; if($lib->type != 'api') continue; $libPairs[$lib->id] = $lib->name; } $this->config->api->search['module'] = !empty($type) ? $type . 'apiDoc' : 'api'; } $this->config->api->search['queryID'] = $queryID; $this->config->api->search['actionURL'] = $actionURL; $this->config->api->search['params']['lib']['values'] = $libPairs + array('all' => $this->lang->api->allLibs); $this->loadModel('search')->setSearchParams($this->config->api->search); } /** * 获取创建接口版本时所需的数据。 * Get spec of api. * * @param object $data * @access private * @return array */ private function getApiSpecByData(object $data): array { return array( 'doc' => $data->id, 'title' => $data->title, 'path' => $data->path, 'module' => !empty($data->module) ? $data->module : 0, 'protocol' => !empty($data->protocol) ? $data->protocol : 'HTTP', 'method' => !empty($data->method) ? $data->method : 'GET', 'requestType' => !empty($data->requestType) ? $data->requestType : '', 'responseType' => !empty($data->responseType) ? $data->responseType : '', 'status' => !empty($data->status) ? $data->status : 'done', 'owner' => !empty($data->owner) ? $data->owner : '', 'desc' => !empty($data->desc) ? $data->desc : '', 'version' => !empty($data->version) ? $data->version : 1, 'params' => !empty($data->params) ? $data->params : '', 'paramsExample' => !empty($data->paramsExample) ? $data->paramsExample : '', 'responseExample' => !empty($data->responseExample) ? $data->responseExample : '', 'response' => !empty($data->response) ? $data->response : '', 'addedBy' => $this->app->user->account, 'addedDate' => helper::now(), ); } /** * 获取创建数据结构版本时所需的数据。 * Get struct spec of api. * * @param object $data * @access private * @return array */ private function getApiStructSpecByData(object $data): array { return array( 'name' => $data->name, 'type' => !empty($data->type) ? $data->type : '', 'desc' => !empty($data->desc) ? $data->desc : '', 'version' => !empty($data->version) ? $data->version : 1, 'attribute' => !empty($data->attribute) ? $data->attribute : '', 'addedBy' => !empty($data->addedBy) ? $data->addedBy : $this->app->user->account, 'addedDate' => !empty($data->addedDate) ? $data->addedDate : helper::now() ); } /** * 获取接口类型数据。 * Get Type list. * * @param int $libID * @access protected * @return array */ public function getTypeList(int $libID): array { $typeList = array(); foreach($this->lang->api->paramsTypeOptions as $key => $item) { $typeList[$key] = $item; } /* Get all struct by libID. */ $structs = $this->getStructListByLibID($libID); foreach($structs as $struct) { $typeList[$struct->id] = $struct->name; } return $typeList; } }