Skip to content

Commit 0ea8320

Browse files
author
Colin Yang
committed
Implemented plugin system & plugin-leaderboard
& tinywebdb is now become plugin-tinywebdb
1 parent 0c3a1be commit 0ea8320

26 files changed

+743
-315
lines changed

.gitignore

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
11
.vscode
22
dist.tar.gz
3-
dist.zip
3+
dist.zip
4+
plugins.json
5+
node_modules
File renamed without changes.

Dockerfile

+9-4
Original file line numberDiff line numberDiff line change
@@ -6,18 +6,23 @@ RUN npm i -g @vue/cli \
66

77
WORKDIR /usr/app/frontend_temp
88

9-
COPY frontend/tinywebdb-php-vue/package*.json ./
9+
COPY package*.json ./
1010
RUN npm i
1111

12-
COPY frontend/tinywebdb-php-vue .
13-
RUN npm run build
12+
COPY frontend/tinywebdb-php-vue frontend/tinywebdb-php-vue
13+
COPY .postcssrc.js .
14+
COPY plugins plugins
15+
COPY plugins.json .
16+
RUN npm run vue-build
1417

1518
WORKDIR /usr/app
1619

17-
RUN mv frontend_temp/dist/* . && \
20+
RUN mv frontend_temp/frontend/tinywebdb-php-vue/dist/* . && \
1821
rm -rf frontend_temp
1922

2023
COPY backend .
24+
COPY plugins plugins
25+
COPY plugins.json .
2126
COPY config.yaml .
2227
COPY .htaccess .
2328

README.md

+44-52
Original file line numberDiff line numberDiff line change
@@ -1,48 +1,30 @@
11
# Tinywebdb (php-vue)
22

3-
## 直接下载使用
3+
TPV是一个数据库管理系统,默认支持 App Inventor 的 Tinywebdb,并以此得名。
44

55
[下载页](https://github.com/ColinTree/tinywebdb-php-vue/releases/latest)
66

77
一般会有四个下载选项
88

9-
* `dist.tar.gz` - 自动构建结果
10-
* `dist.zip` - 自动构建结果
9+
* `dist.tar.gz` - 自动构建结果(仅包含Tinywebdb插件)
10+
* `dist.zip` - 自动构建结果(仅包含Tinywebdb插件)
1111
* `Source code (zip)` - 源码
1212
* `Source code (tar.gz)` - 源码
1313

14-
### 使用例子
14+
## 在新浪云SAE上部署
1515

16-
#### 新浪云SAE
16+
### 首次部署
1717

18-
首次使用:
18+
1.[新浪云(SAE)](http://sae.sina.com.cn)创建 `php, 标准环境, 7.0, git` 应用
19+
2. 前往左侧菜单`应用->代码管理`,创建版本,并选择`上传代码包`,将 [Release](https://github.com/ColinTree/tinywebdb-php-vue/releases/latest) 页面下载的 `dist.zip` 上传
20+
3. 选择`上传代码包`旁边的`编辑代码`(编辑界面有时候是弹窗,会被浏览器拦截,请注意放行)
21+
4. 根据[生产环境的配置](#%E7%94%9F%E4%BA%A7%E7%8E%AF%E5%A2%83%E7%9A%84%E9%85%8D%E7%BD%AE)配置 `config.php`
22+
5. 前往你的app网址如 `http://{app-id}.applinzi.com/#/manage/init` ,设置后台密码
23+
6. 开始正常使用!(AI2中填写的网络微数据库地址是 `http://{app-id}.applinzi.com`
1924

20-
1. 下载`dist.zip`
21-
2. 前往[新浪云SAE](http://sae.sina.com.cn),创建`php, 标准环境, 7.0, git`应用
22-
3. 前往`应用->代码管理`,选择`上传代码包`,上传刚下载的`dist.zip`
23-
4. 上传完成后,选择`上传代码包`旁边的`编辑代码`(编辑界面有时候是弹窗,会被浏览器拦截,请注意放行)
24-
5. 根据[生产环境的配置](#生产环境的配置)和代码中的`config.sample.php`配置`config.php`
25-
6. 前往你的app网址如`http://{app-id}.applinzi.com/#/manage/init`,设置后台密码
26-
7. 开始正常使用!(AI2中填写的网络微数据库地址是`http://{app-id}.applinzi.com`
25+
### 更新已有应用
2726

28-
## 从源码构建
29-
30-
(需要提前安装docker)
31-
32-
```
33-
git clone https://github.com/ColinTree/tinywebdb-php-vue.git
34-
cd tinywebdb-php-vue
35-
git submodule update --init
36-
docker build -t tpv .
37-
docker create --name tpv_temp_container tpv
38-
docker cp tpv_temp_container:/usr/app/dist.tar.gz .
39-
docker rm tpv_temp_container
40-
```
41-
42-
执行完之后你就可以看到 `dist.tar.gz` 出现在你当前的文件夹中
43-
44-
注:
45-
如果有需要可以通过`npm i -g tar-to-zip`安装tar.gz转换zip的模块,并运行`tar2zip dist.tar.gz`
27+
只需要前往`应用->代码管理`,选择`上传代码包`,上传 [Release](https://github.com/ColinTree/tinywebdb-php-vue/releases/latest) 中的 `dist.zip` 文件即可
4628

4729
## 生产环境的配置
4830

@@ -59,30 +41,39 @@ MANAGE_LOGIN_TIMEOUT | 否 | 600 | 后台管理会话自动结束时长(秒)
5941

6042
* DbProvider::setDb - **必须** - 提供数据库服务
6143

62-
样例参见 `config.sample.php` 文件。(源码中的位置:`backend/config.sample.php`
44+
样例参见 [config.sample.php](https://github.com/ColinTree/tinywebdb-php-vue/blob/master/backend/config.sample.php)
6345

64-
## API文档
46+
## 插件
6547

66-
### Tinywebdb API
48+
TPV支持使用插件,目前内置插件有:
6749

68-
标准Tinywebdb API没有状态码
50+
* [网络微数据库 (tinywebdb)](./plugins/tinywebdb/README.md)(默认开启)
51+
* [排行榜 (leaderboard)](./plugins/leaderboard/README.md)
6952

70-
* `/getvalue`
71-
* 参数
72-
* tag
73-
* 返回值
74-
* [ "VALUE", tag, value / 错误信息 ]
53+
如需调整插件启用情况,则需要自行[构建TPV](#%E4%BB%8E%E6%BA%90%E7%A0%81%E6%9E%84%E5%BB%BA)
7554

76-
* `/storeavalue`
77-
* 参数
78-
* tag
79-
* value
80-
* 返回值
81-
* [ "STORED", tag, value / 错误信息 ]
55+
## 从源码构建
8256

83-
### 其他API
57+
1. 下载源码
58+
59+
```
60+
git clone https://github.com/ColinTree/tinywebdb-php-vue.git
61+
cd tinywebdb-php-vue
62+
```
63+
64+
2. 配置`plugins.json`,格式参照源码中的样例 [plugins.sample.json](https://github.com/ColinTree/tinywebdb-php-vue/blob/master/plugins.sample.json)
65+
3. 构建
66+
67+
```
68+
git submodule update --init
69+
npm run build
70+
```
71+
72+
执行完之后你就可以看到 `dist.tar.gz``dist.zip` 出现在你当前的文件夹中
73+
74+
## API文档
8475

85-
#### `Api.class.php` 中定义的状态码
76+
### `Api.class.php` 中定义的状态码
8677

8778
状态名 | 分类 | 状态码 | http状态码 | 描述
8879
-----------|----------|:----:|:---------:|------------
@@ -91,6 +82,7 @@ STATUS_API_NOT_FOUND | 全局 | 1 | 404 | 未能找到请求的API
9182
STATUS_API_FAILED | 全局 | 2 | 200 | API在运行过程中出现错误
9283
STATUS_INTERNAL_ERROR | 全局 | 3 | 500 | 服务器内部错误
9384
STATUS_UNAUTHORIZED | 全局 | 4 | 401 | 请求未提供token或者token已失效
85+
STATUS_PLUGIN_API_FAILED | 插件 | 5 | 200 | 插件通用错误码
9486
STATUS_KEY_NOT_FOUNT | 需要提供标签的地方 | 10 | 200 | 数据库中未能找到请求的标签
9587
STATUS_KEY_RESERVED | 需要提供标签的地方 | 11 | 200 | 请求了管理系统的保留标签
9688
STATUS_UNACCEPTED_LIMIT | 需要返回分页的地方 | 20 | 200 | 分页限制应该在1-100之间
@@ -101,7 +93,7 @@ STATUS_SETTING_NOT_RECOGNISED | 更新设置 | 50 | 200 | 服务器不支持指
10193
STATUS_EXPORT_UNACCEPTED_TYPE | 导出数据 | 60 | 200 | 服务器不支持指定的导出格式
10294
STATUS_EXPORT_XLSX_UNSUPPORTED | 导出数据(仅限xlsx) | 61 | 200 | 服务器未安装xlsx相关的模块
10395

104-
#### 后台管理
96+
### 后台管理
10597

10698
请求头 `X-TPV-Manage-Token` 大部分时候是必须的,是一串用于身份验证的token,只有token验证通过的操作才会被服务器执行
10799

@@ -206,8 +198,8 @@ STATUS_EXPORT_XLSX_UNSUPPORTED | 导出数据(仅限xlsx) | 61 | 200 | 服务器
206198
* 请求头
207199
* `X-TPV-Manage-Token` - 必须
208200
* 参数
209-
* `settingId` - 必需 - 设置Id,详见设置列表
210-
* `value` - 必需 - 值,详见设置列表
201+
* `settingId` - 必需 - 设置Id,详见[设置表](#%E5%90%8E%E5%8F%B0%E7%AE%A1%E7%90%86%E8%AE%BE%E7%BD%AE%E8%A1%A8)
202+
* `value` - 必需 - 值,详见[设置表](#%E5%90%8E%E5%8F%B0%E7%AE%A1%E7%90%86%E8%AE%BE%E7%BD%AE%E8%A1%A8)
211203
* 返回值 - [ "status": 状态码, "result": 提示文本 ]
212204
* 可能返回的非全局状态码 - STATUS_SETTING_NOT_RECOGNISED
213205
* settings - 获取所有设置
@@ -223,7 +215,7 @@ STATUS_EXPORT_XLSX_UNSUPPORTED | 导出数据(仅限xlsx) | 61 | 200 | 服务器
223215
* 返回值 - [ "status": 状态码, "result": 提示文本 ]
224216
* 可能返回的非全局状态码 - STATUS_KEY_RESERVED, STATUS_KEY_NOT_FOUNT
225217

226-
##### 后台管理设置表
218+
#### 后台管理设置表
227219

228220
设置Id | 设置名 | 接受的值
229221
-|-|-

backend/.gitignore

-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
# every server should have its own dbHandler
21
config.php
32
# for local test only, mocking some services that only exist on server
43
class/mock/

backend/class/Api.class.php

+2-1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
const STATUS_API_FAILED = 2; // with http code 503
66
const STATUS_INTERNAL_ERROR = 3; // with http code 500
77
const STATUS_UNAUTHORIZED = 4; // with http code 401
8+
const STATUS_PLUGIN_API_FAILED = 5;
89
const STATUS_KEY_NOT_FOUNT = 10;
910
const STATUS_KEY_RESERVED = 11;
1011
const STATUS_UNACCEPTED_LIMIT = 20;
@@ -87,7 +88,7 @@ function __construct() {
8788

8889
/**
8990
* All echo would be treated as default output result.
90-
* Args from the get request can be found in $GLOBALS['args]
91+
* Args from the get request can be found in $GLOBALS['args']
9192
* @return mixed null, array for [ 'status': status, 'result': result ] or any other for result message
9293
*/
9394
abstract function handle();

backend/class/api/Manage.class.php

+14-20
Original file line numberDiff line numberDiff line change
@@ -28,16 +28,6 @@ private static function saltPassword($pwd) {
2828
return md5('tpv-salt' . $pwd);
2929
}
3030

31-
private static function settings() {
32-
$settings = json_decode(DbProvider::getDb()->getReserved(DbBase::$KEY_MANAGE_SETTINGS), true);
33-
return $settings === '' ? new stdClass : $settings;
34-
}
35-
private static function updateSetting($settingId, $value) {
36-
$settings = self::settings();
37-
$settings[$settingId] = $value;
38-
DbProvider::getDb()->setReserved(DbBase::$KEY_MANAGE_SETTINGS, json_encode($settings));
39-
}
40-
4131
function handle() {
4232
$key = (string) $_REQUEST['key'];
4333
$value = (string) $_REQUEST['value'];
@@ -335,20 +325,24 @@ function handle() {
335325
}
336326
case 'setting_update': {
337327
$settingId = (string) $_REQUEST['settingId'];
338-
switch ($settingId) {
339-
case 'all_category':
340-
case 'allow_browser':
341-
case 'special_tags': {
342-
self::updateSetting($settingId, $value);
343-
return [ 'result' => 'Succeed' ];
344-
}
345-
default: {
346-
return [ 'status' => STATUS_SETTING_NOT_RECOGNISED, 'result' => 'The settingId can not be recognised.' ];
328+
$ACCEPTED_SETTING = [ 'all_category' ];
329+
foreach (PLUGINS as $pluginName => $pluginConfigs) {
330+
foreach ($pluginConfigs['settings'] as $name => $settingDetails) {
331+
$ACCEPTED_SETTING[] = $pluginName . '_' . $name;
347332
}
348333
}
334+
if (in_array($settingId, $ACCEPTED_SETTING)) {
335+
$settings = DbBase::getSettings();
336+
$settings[$settingId] = $value;
337+
DbProvider::getDb()->setReserved(DbBase::$KEY_MANAGE_SETTINGS, json_encode($settings));
338+
return [ 'result' => 'Succeed' ];
339+
} else {
340+
return [ 'status' => STATUS_SETTING_NOT_RECOGNISED, 'result' => 'The settingId can not be recognised.' ];
341+
}
349342
}
350343
case 'settings': {
351-
return [ 'result' => self::settings() ];
344+
$settings = DbBase::getSettings();
345+
return [ 'result' => is_array($settings) && count($settings) === 0 ? new stdClass : $settings ];
352346
}
353347
case 'update': {
354348
if (DbBase::keyReserved($key)) {

backend/class/api/Storeavalue.class.php

-17
This file was deleted.

backend/class/db/Base.class.php

+9
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,15 @@ function deleteReserved(string $key) {
2424
return $this->delete(self::$KEY_RESERVED_PREFIX . $key);
2525
}
2626

27+
public static function getSettings() {
28+
$settings = DbProvider::getDb()->getReserved(self::$KEY_MANAGE_SETTINGS);
29+
return json_decode($settings === false ? '{}' : $settings, true);
30+
}
31+
public static function getSetting(string $settingId, $default = NULL) {
32+
$settingValue = self::getSettings()[$settingId];
33+
return isset($settingValue) ? $settingValue : $default;
34+
}
35+
2736
public static $SEARCH_RESULT_PER_PAGE = 20;
2837

2938
/**

backend/index.php

+33-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
<?php
22

33
function loadClass($className) {
4+
if (class_exists($className)) {
5+
return;
6+
}
47
$possible = [];
58
if (substr($className, 0, 3) == 'Api') {
69
$apiName = substr($className, 3);
@@ -36,8 +39,8 @@ function loadClass($className) {
3639
$a = substr($a, 1);
3740
}
3841
$a = explode('/', $a, 2);
39-
$a[0] = ucfirst(strtolower($a[0]));
40-
$api = "Api$a[0]";
42+
$apiName = ucfirst(strtolower($a[0]));
43+
$api = "Api$apiName";
4144
if ($api == 'Api') {
4245
$api .= 'Index';
4346
}
@@ -48,6 +51,34 @@ function loadClass($className) {
4851
exit;
4952
}
5053

54+
// Plugin files in dist are like
55+
// |- plugins/
56+
// |- {folders for each plugin}/
57+
// |- index.php
58+
// |- index.php
59+
// |- plugins.json
60+
try {
61+
if (file_exists('plugins.json')) {
62+
$PLUGINS_JSON = json_decode(file_get_contents('plugins.json'), true);
63+
$PLUGINS = [];
64+
foreach ($PLUGINS_JSON as $pluginName => $pluginConfigs) {
65+
if ($pluginConfigs['enabled'] !== true) {
66+
continue;
67+
}
68+
$pluginPath = 'plugins/' . $pluginName . '/';
69+
$PLUGINS[$pluginName] = json_decode(file_get_contents($pluginPath . '/plugin.json'), true);
70+
$apiFile = $PLUGINS[$pluginName]['php'][$apiName];
71+
if (isset($apiFile) && file_exists($pluginPath . $apiFile)) {
72+
require_once $pluginPath . $apiFile;
73+
}
74+
}
75+
define('PLUGINS', $PLUGINS);
76+
}
77+
} catch (Throwable $t) {
78+
new ApiError(Api::throwable2string($t));
79+
exit;
80+
}
81+
5182
try {
5283
loadClass($api);
5384
} catch (Exception $e) {

frontend/tinywebdb-php-vue/build/check-versions.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
'use strict'
22
const chalk = require('chalk')
33
const semver = require('semver')
4-
const packageConfig = require('../package.json')
4+
const packageConfig = require('../../../package.json')
55
const shell = require('shelljs')
66

77
function exec (cmd) {

frontend/tinywebdb-php-vue/build/utils.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
const path = require('path')
33
const config = require('../config')
44
const ExtractTextPlugin = require('extract-text-webpack-plugin')
5-
const packageConfig = require('../package.json')
5+
const packageConfig = require('../../../package.json')
66

77
exports.assetsPath = function (_path) {
88
const assetsSubDirectory = process.env.NODE_ENV === 'production'

0 commit comments

Comments
 (0)