znt/module/api/model.php

1098 lines
37 KiB
PHP
Raw Permalink Normal View History

<?php
declare(strict_types=1);
/**
* The model file of api module of ZenTaoPMS.
*
* @copyright Copyright 2009-2023 禅道软件(青岛)有限公司(ZenTao Software (Qingdao) Co., Ltd. www.cnezsoft.com)
* @license ZPL(http://zpl.pub/page/zplv12.html) or AGPL(https://www.gnu.org/licenses/agpl-3.0.en.html)
* @author Chunsheng Wang <chunsheng@cnezsoft.com>
* @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;
}
}