znt/module/api/model.php

1098 lines
37 KiB
PHP
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?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;
}
}