diff --git a/module/api/control.php b/module/api/control.php
index 47f9ff8373..2543fd3430 100755
--- a/module/api/control.php
+++ b/module/api/control.php
@@ -158,7 +158,7 @@ class api extends control
/* Append id for second sort. */
$sort = common::appendOrder($orderBy);
- $releases = $this->api->getReleaseByQuery($libID, '', $sort);
+ $releases = $this->api->getReleaseByQuery(array($libID), '', $sort);
$this->view->title = $this->lang->api->managePublish;
$this->view->releases = $releases;
@@ -719,16 +719,16 @@ class api extends control
if(strpos($fileDirPath, $this->app->getModuleRoot()) !== 0 && strpos($fileDirPath, $this->app->getExtensionRoot()) !== 0) return;
if($action == 'extendModel')
{
- $method = $this->api->getMethod($filePath, 'Model');
+ $method = $this->apiZen->getMethod($filePath, 'Model');
}
elseif($action == 'extendControl')
{
- $method = $this->api->getMethod($filePath);
+ $method = $this->apiZen->getMethod($filePath);
}
if(!empty($_POST))
{
- $result = $this->api->request($method->className, $method->methodName, $action);
+ $result = $this->apiZen->request($method->className, $method->methodName, $action);
$content = json_decode($result['content']);
$status = zget($content, 'status', '');
$data = isset($content->data) ? json_decode($content->data) : '';
diff --git a/module/api/model.php b/module/api/model.php
index 90912e4c60..2e891675b3 100644
--- a/module/api/model.php
+++ b/module/api/model.php
@@ -515,13 +515,13 @@ class apiModel extends model
* 获取指定文档库下的数据结构列表。
* Get release list by lib id.
*
- * @param int $libID
+ * @param array $libID
* @param object $pager
* @param string $orderBy
* @access public
* @return array
*/
- public function getReleaseByQuery(int $libID, object $pager = null, string $orderBy = ''): 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)
@@ -531,151 +531,31 @@ class apiModel extends model
}
/**
- * 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 = "
";
- foreach($list as $item)
- {
- $class = array('catalog');
- if($structID && $structID == $item->id)
- {
- $class[] = 'active';
- }
- else
- {
- $class[] = 'doc';
- }
-
- $html .= '- ';
- $html .= html::a(helper::createLink('api', 'struct', "libID=$libID&structID=$item->id"), " " . $item->name, '', "data-app='{$this->app->tab}' class='doc-title' title='{$item->name}'");
- $html .= "
";
- }
- $html .= "
";
-
- return $html;
- }
-
- /**
- * Get the details of the method by file path.
- *
- * @param string $filePath
- * @param string $ext
- * @access public
- * @return object
- */
- public function getMethod($filePath, $ext = '')
- {
- $fileName = dirname($filePath);
- $className = basename(dirname(dirname($filePath)));
- if(!class_exists($className)) helper::import($fileName);
- $methodName = basename($filePath);
-
- $method = new ReflectionMethod($className . $ext, $methodName);
- $data = new stdClass();
- $data->startLine = $method->getStartLine();
- $data->endLine = $method->getEndLine();
- $data->comment = $method->getDocComment();
- $data->parameters = $method->getParameters();
- $data->className = $className;
- $data->methodName = $methodName;
- $data->fileName = $fileName;
- $data->post = false;
-
- $file = file($fileName);
- for($i = $data->startLine - 1; $i <= $data->endLine; $i++)
- {
- if(strpos($file[$i], '$this->post') or strpos($file[$i], 'fixer::input') or strpos($file[$i], '$_POST'))
- {
- $data->post = true;
- }
- }
- return $data;
- }
-
- /**
- * Request the api.
- *
- * @param string $moduleName
- * @param string $methodName
- * @param string $action
- * @access public
- * @return array
- */
- public function request($moduleName, $methodName, $action)
- {
- $host = common::getSysURL();
- $param = '';
- if($action == 'extendModel')
- {
- if(!isset($_POST['noparam']))
- {
- foreach($_POST as $key => $value) $param .= ',' . $key . '=' . $value;
- $param = ltrim($param, ',');
- }
- $url = rtrim($host, '/') . inlink('getModel', "moduleName=$moduleName&methodName=$methodName¶ms=$param", 'json');
- $url .= strpos($url, '?') === false ? '?' : '&';
- $url .= $this->config->sessionVar . '=' . session_id();
- }
- else
- {
- if(!isset($_POST['noparam']))
- {
- foreach($_POST as $key => $value) $param .= '&' . $key . '=' . $value;
- $param = ltrim($param, '&');
- }
- $url = rtrim($host, '/') . helper::createLink($moduleName, $methodName, $param, 'json');
- $url .= strpos($url, '?') === false ? '?' : '&';
- $url .= $this->config->sessionVar . '=' . session_id();
- }
-
- /* Unlock session. After new request, restart session. */
- session_write_close();
- $content = file_get_contents($url);
- session_start();
-
- return array('url' => $url, 'content' => $content);
- }
-
- /**
+ * 查询SQL语句并返回结果。
* Query sql.
*
- * @param string $sql
- * @param string $keyField
+ * @param string $sql
+ * @param string $keyField
* @access public
* @return array
*/
- public function sql($sql, $keyField = '')
+ public function sql(string $sql, string $keyField = '')
{
+ /* 检查允许接口调用SQL的配置项是否打开。 */
if(!$this->config->features->apiSQL) return sprintf($this->lang->api->error->disabled, '$config->features->apiSQL');
$sql = trim($sql);
if(strpos($sql, ';') !== false) $sql = substr($sql, 0, strpos($sql, ';'));
- $result = array();
- $result['status'] = 'fail';
- $result['message'] = '';
+ /* 如果没传SQL参数,则无法进行下一步。 */
+ if(empty($sql)) return array('status' => 'fail', 'message' => '');
- if(empty($sql)) return $result;
-
- if(stripos($sql, 'select ') !== 0)
- {
- $result['message'] = $this->lang->api->error->onlySelect;
- return $result;
- }
+ /* 如果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))
{
@@ -683,16 +563,15 @@ class apiModel extends model
}
else
{
+ /* 用keyFiled作为键展示查询结果。 */
while($row = $stmt->fetch()) $rows[$row->$keyField] = $row;
}
- $result['status'] = 'success';
- $result['data'] = $rows;
+ $result = array('status' => 'success', 'data' => $rows);
}
catch(PDOException $e)
{
- $result['status'] = 'fail';
- $result['message'] = $e->getMessage();
+ $result = array('status' => 'fail', 'message' => $e->getMessage());
}
return $result;
diff --git a/module/api/test/model/getbyid.php b/module/api/test/model/getbyid.php
index 6e7d8ce8c5..eced645ed9 100755
--- a/module/api/test/model/getbyid.php
+++ b/module/api/test/model/getbyid.php
@@ -9,7 +9,7 @@ zdTable('api_lib_release')->gen(10);
/**
-title=测试 apiModel->getById();
+title=测试 apiModel->getByID();
timeout=0
cid=1
diff --git a/module/api/test/model/sql.php b/module/api/test/model/sql.php
new file mode 100755
index 0000000000..3da4f1965b
--- /dev/null
+++ b/module/api/test/model/sql.php
@@ -0,0 +1,52 @@
+#!/usr/bin/env php
+gen(10);
+
+/**
+
+title=测试 apiModel->sql();
+timeout=0
+cid=1
+
+- 在没启用配置的时候调用sql接口。 @因为安全原因,该功能被禁用。可以到config目录,修改配置项 $config->features->apiSQL,打开此功能。
+- SQL语句为空时调用sql接口。
+ - 属性status @fail
+ - 属性message @` `
+- SQL语句不符合规范时调用sql接口。
+ - 属性status @fail
+ - 属性message @SQL查询接口只允许SELECT查询
+- 使用正确的SQL查询调用sql接口。
+ - 第0条的id属性 @1
+ - 第0条的title属性 @BUG接口1
+ - 第1条的id属性 @2
+ - 第1条的title属性 @BUG接口2
+- 使用正确的SQL查询并按照以id作为键返回sql接口的查询结果。
+ - 第1条的id属性 @1
+ - 第1条的title属性 @BUG接口1
+ - 第2条的id属性 @2
+ - 第2条的title属性 @BUG接口2
+
+*/
+
+global $tester, $config;
+$tester->loadModel('api');
+
+$sql = '';
+$config->features->apiSQL = false;
+r($tester->api->sql($sql)) && p() && e('因为安全原因,该功能被禁用。可以到config目录,修改配置项 $config->features->apiSQL,打开此功能。'); //在没启用配置的时候调用sql接口。
+
+$config->features->apiSQL = true;
+r($tester->api->sql($sql)) && p('status,message') && e('fail,` `'); //SQL语句为空时调用sql接口。
+
+$sql = 'delete from zt_api';
+r($tester->api->sql($sql)) && p('status,message') && e('fail,SQL查询接口只允许SELECT查询'); //SQL语句不符合规范时调用sql接口。
+
+$sql = 'select * from zt_api';
+$result = $tester->api->sql($sql);
+r($result['data']) && p('0:id,title;1:id,title') && e('1,BUG接口1,2,BUG接口2'); //使用正确的SQL查询调用sql接口。
+
+$result = $tester->api->sql($sql, 'id');
+r($result['data']) && p('1:id,title;2:id,title') && e('1,BUG接口1,2,BUG接口2'); //使用正确的SQL查询并按照以id作为键返回sql接口的查询结果。
diff --git a/module/api/zen.php b/module/api/zen.php
index 60eb098822..04e5c574fa 100644
--- a/module/api/zen.php
+++ b/module/api/zen.php
@@ -111,4 +111,90 @@ class apiZen extends api
$objectDropdown['link'] = helper::createLink('api', 'ajaxGetDropMenu', "objectType=$objectType&objectID=$objectID&libID=$lib->id&version=$version");
return $objectDropdown;
}
+
+ /**
+ * 解析请求地获得请求的详细信息。
+ * Get the details of the method by file path.
+ *
+ * @param string $filePath
+ * @param string $ext
+ * @access public
+ * @return object
+ */
+ public function getMethod(string $filePath, string $ext = ''): object
+ {
+ $fileName = dirname($filePath);
+ $className = basename(dirname(dirname($filePath)));
+ $methodName = basename($filePath);
+
+ if(!class_exists($className)) helper::import($fileName);
+ $method = new ReflectionMethod($className . $ext, $methodName);
+ $data = new stdClass();
+
+ $data->startLine = $method->getStartLine();
+ $data->endLine = $method->getEndLine();
+ $data->comment = $method->getDocComment();
+ $data->parameters = $method->getParameters();
+ $data->className = $className;
+ $data->methodName = $methodName;
+ $data->fileName = $fileName;
+ $data->post = false;
+
+ $file = file($fileName);
+ for($i = $data->startLine - 1; $i <= $data->endLine; $i++)
+ {
+ if(strpos($file[$i], '$this->post') or strpos($file[$i], 'fixer::input') or strpos($file[$i], '$_POST'))
+ {
+ $data->post = true;
+ }
+ }
+ return $data;
+ }
+
+ /**
+ * 对指定模块下的指定方法进行调用并返回请求结果。
+ * Request the api.
+ *
+ * @param string $moduleName
+ * @param string $methodName
+ * @param string $action extendModel | extendControl
+ * @access public
+ * @return array
+ */
+ public function request(string $moduleName, string $methodName, string $action): array
+ {
+ $host = common::getSysURL();
+ $param = '';
+ if($action == 'extendModel')
+ {
+ /* 对model的函数进行调用。 */
+ if(!isset($_POST['noparam']))
+ {
+ foreach($_POST as $key => $value) $param .= ',' . $key . '=' . $value;
+ $param = ltrim($param, ',');
+ }
+ $url = rtrim($host, '/') . inlink('getModel', "moduleName=$moduleName&methodName=$methodName¶ms=$param", 'json');
+ $url .= strpos($url, '?') === false ? '?' : '&';
+ $url .= $this->config->sessionVar . '=' . session_id();
+ }
+ else
+ {
+ /* 对control的函数进行调用。 */
+ if(!isset($_POST['noparam']))
+ {
+ foreach($_POST as $key => $value) $param .= '&' . $key . '=' . $value;
+ $param = ltrim($param, '&');
+ }
+ $url = rtrim($host, '/') . helper::createLink($moduleName, $methodName, $param, 'json');
+ $url .= strpos($url, '?') === false ? '?' : '&';
+ $url .= $this->config->sessionVar . '=' . session_id();
+ }
+
+ /* Unlock session. After new request, restart session. */
+ session_write_close();
+ $content = file_get_contents($url);
+ session_start();
+
+ return array('url' => $url, 'content' => $content);
+ }
}