Skip to content

Commit 49d723a

Browse files
author
Colin Yang
committed
Both - Implemented special tags
* count * getall * listget * search
1 parent 8b58742 commit 49d723a

File tree

7 files changed

+162
-26
lines changed

7 files changed

+162
-26
lines changed

backend/class/Api.class.php

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,10 +44,11 @@ function __construct() {
4444
$result = ob_get_clean();
4545
}
4646

47-
if (isset($handleResult['noProcess']) && $handleResult['noProcess'] === true) {
47+
// echo then die() in handle() instead
48+
/* if (isset($handleResult['noProcess']) && $handleResult['noProcess'] === true) {
4849
echo $handleResult['result'];
4950
return;
50-
}
51+
} */
5152

5253
$status = STATUS_SUCCEED;
5354
if (is_null($handleResult)) {

backend/class/api/Getvalue.class.php

Lines changed: 56 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,59 @@ static function checkAllowBrowser() {
1010
|| isset($_SERVER['HTTP_COOKIE'])
1111
|| $_SERVER['HTTP_ACCEPT'] != 'application/json')) {
1212
http_response_code(403);
13-
echo json_encode([ 'RESUFED VIA SETTING (allow_browser = false)', '', '' ]);
14-
die();
13+
die(json_encode([ 'RESUFED VIA SETTING (allow_browser = false)', '', '' ]));
14+
}
15+
}
16+
17+
private function handleSpecialTags($key) {
18+
$settings = json_decode(DbProvider::getDb()->get(DbBase::$KEY_MANAGE_SETTINGS), true);
19+
$special_tags = isset($settings['special_tags']) ? json_decode($settings['special_tags'], true) : [];
20+
$tag_count = isset($special_tags['count']) && !empty($special_tags['count']) ? $special_tags['count'] : 'special_count';
21+
$tag_getall = isset($special_tags['getall']) && !empty($special_tags['getall']) ? $special_tags['getall'] : 'special_getall';
22+
$tag_listget = isset($special_tags['listget']) && !empty($special_tags['listget']) ? $special_tags['listget'] : 'special_listget';
23+
$tag_search = isset($special_tags['search']) && !empty($special_tags['search']) ? $special_tags['search'] : 'special_search';
24+
$tag = explode('#', $key, 2);
25+
while (count($tag) < 2) {
26+
$tag[] = '';
27+
}
28+
$params = explode('#', $tag[1]);
29+
$tag = $tag[0];
30+
switch ($tag) {
31+
case $tag_count: {
32+
$count = DbProvider::getDb()->count($params[0]);
33+
die(json_encode([ 'VALUE', $key, (string) $count ]));
34+
}
35+
case $tag_getall: {
36+
$offset = count($params) >= 2 ? (int) $params[1] : 0;
37+
$limit = count($params) >= 3 ? (int) $params[2] : 0;
38+
$result = [];
39+
foreach (DbProvider::getDb()->getAll($params[0]) as $index => $key_value_pair) {
40+
if (DbBase::keyReserved($key_value_pair['key'])) {
41+
continue;
42+
}
43+
if ($offset > 0) {
44+
$offset--;
45+
continue;
46+
}
47+
if ($limit > 0 && count($result) >= $limit) {
48+
break;
49+
}
50+
$result[] = $key_value_pair;
51+
}
52+
// Use getPage to implement this may have higher proformance with mysql?
53+
die(json_encode([ 'VALUE', $key, json_encode($result) ]));
54+
}
55+
case $tag_listget: {
56+
$result = [];
57+
foreach ($params as $index => $key) {
58+
$result[] = [ 'key' => $key, 'value' => DbProvider::getDb()->get($key) ];
59+
}
60+
die(json_encode([ 'VALUE', $key, json_encode($result) ]));
61+
}
62+
case $tag_search: {
63+
$result = DbProvider::getDb()->search($params[0], 1, false, ['key']);
64+
die(json_encode([ 'VALUE', $key, json_encode($result) ]));
65+
}
1566
}
1667
}
1768

@@ -20,9 +71,10 @@ function handle() {
2071
$key = (string) $_REQUEST['tag'];
2172
if (DbBase::keyReserved($key)) {
2273
http_response_code(403);
23-
return [ 'noProcess' => true, 'result' => json_encode([ 'KEY RESERVED', $key, '' ]) ];
74+
die(json_encode([ 'KEY RESERVED', $key, '' ]));
2475
}
25-
return [ 'noProcess' => true, 'result' => json_encode([ 'VALUE', $key, (string) DbProvider::getDb()->get($key) ]) ];
76+
$this->handleSpecialTags($key);
77+
die(json_encode([ 'VALUE', $key, (string) DbProvider::getDb()->get($key) ]));
2678
}
2779

2880
}

backend/class/api/Manage.class.php

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -319,7 +319,7 @@ function handle() {
319319
} else {
320320
$range = [ $range ];
321321
}
322-
$page = (string) $_REQUEST['page'];
322+
$page = (int) $_REQUEST['page'];
323323

324324
$result = DbProvider::getDb()->search($text, $page, $ignoreCase, $range);
325325

@@ -342,7 +342,8 @@ function handle() {
342342
$settingId = (string) $_REQUEST['settingId'];
343343
switch ($settingId) {
344344
case 'all_category':
345-
case 'allow_browser': {
345+
case 'allow_browser':
346+
case 'special_tags': {
346347
self::updateSetting($settingId, $value);
347348
return [ 'result' => 'Succeed' ];
348349
}

backend/class/api/Storeavalue.class.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,10 @@ function handle() {
88
$value = (string) $_REQUEST['value'];
99
if (DbBase::keyReserved($key)) {
1010
http_response_code(403);
11-
return [ 'noProcess' => true, 'result' => json_encode([ 'STORED', $key, 'Key reserved, refuse to store' ]) ];
11+
die(json_encode([ 'STORED', $key, 'Key reserved, refuse to store' ]));
1212
}
1313
DbProvider::getDb()->set($key, $value);
14-
return [ 'noProcess' => true, 'result' => json_encode([ 'STORED', $key, $value ]) ];
14+
die(json_encode([ 'STORED', $key, $value ]));
1515
}
1616

1717
}

backend/class/db/Base.class.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -98,11 +98,11 @@ abstract function getAll(string $prefix = '');
9898
/**
9999
* get all of values in db via iterator
100100
* @param string $text text to search
101-
* @param string $page page number of search result (20 a page)
101+
* @param int $page page number of search result (20 a page)
102102
* @param bool $ignoreCase whether case matters or not
103103
* @param array $range search range (fields names)
104104
* @return Iterator each iterator value should be a key-value object array (e.g. `['key'=>'key1', 'value'=>'val1']`)
105105
*/
106-
abstract function search(string $text, string $page, bool $ignoreCase, array $range);
106+
abstract function search(string $text, int $page, bool $ignoreCase, array $range);
107107

108108
}

backend/class/db/SaeKV.class.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ function getAll(string $prefix = '') {
8787
return new DbSaeKVIterator($prefix, $this->kv);
8888
}
8989

90-
function search(string $text, string $page, bool $ignoreCase, array $range) {
90+
function search(string $text, int $page, bool $ignoreCase, array $range) {
9191
if ($ignoreCase) {
9292
$text = strtolower($text);
9393
}

frontend/tinywebdb-php-vue/src/components/manage/Setting.vue

Lines changed: 95 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
<div v-if="loaded === true">
66
<div class="setting-header">标签浏览页·分类列表</div>
7-
<div>
7+
<b-form @submit.prevent="$refs.all_category_button.onClick()">
88
<b-form-group>
99
<b-input v-model="all_category.value" />
1010
<template slot="description">
@@ -23,25 +23,88 @@
2323
:select-size="Math.min(5, all_category_preview.length)" />
2424
</b-form-group>
2525
<SpinnerButton
26+
ref="all_category_button"
2627
:variant="typeof all_category.variant === 'string' ? all_category.variant : 'secondary'"
2728
@click="onDone => save('all_category', onDone)">
2829
<span v-text="typeof all_category.text === 'string' ? all_category.text : '保存'"/>
2930
</SpinnerButton>
30-
</div>
31+
</b-form>
3132

3233
<hr>
3334

3435
<div class="setting-header">数据安全</div>
35-
<div>
36+
<b-form @submit.prevent="$refs.allow_browser_button.onClick()">
3637
<b-form-group description="说明:本功能对于数据防修改能力较弱,仅做简单的浏览器级别防御,请不要过度依赖">
3738
<b-checkbox v-model="allow_browser.value">允许来自浏览器的读写</b-checkbox>
3839
</b-form-group>
3940
<SpinnerButton
41+
ref="allow_browser_button"
4042
:variant="typeof allow_browser.variant === 'string' ? allow_browser.variant : 'secondary'"
4143
@click="onDone => save('allow_browser', onDone)">
4244
<span v-text="typeof allow_browser.text === 'string' ? allow_browser.text : '保存'"/>
4345
</SpinnerButton>
44-
</div>
46+
</b-form>
47+
48+
<hr>
49+
50+
<div class="setting-header">特殊标签</div>
51+
<b-form @submit.prevent="$refs.special_tags_button.onClick()">
52+
<b-form-group label="返回总标签数量" :state="special_count_state" invalid-feedback="不能包含#,空格">
53+
<b-input v-model="special_tags.value.count" placeholder="special_count" :state="special_count_state" />
54+
<template slot="description">
55+
使用方法:请求获取标签“<span v-text="special_count" />[#计数前缀]”。如果不包含前缀,默认为空<br />
56+
返回:一个文本形式的数字<br />
57+
例子:
58+
<ul>
59+
<li>统计所有标签数量:“<span v-text="special_count" />”</li>
60+
<li>统计所有以a开头的标签的数量:“<span v-text="special_count" />#a”</li>
61+
</ul>
62+
</template>
63+
</b-form-group>
64+
<b-form-group label="获取指定前缀的所有标签和值" :state="special_getall_state" invalid-feedback="不能包含,空格,空格">
65+
<b-input v-model="special_tags.value.getall" placeholder="special_getall" :state="special_getall_state" />
66+
<template slot="description">
67+
使用方法:请求获取标签“<span v-text="special_getall" />#获取前缀[#起始偏移][#数量限制]”。
68+
<b>***如数据库内的数据数量较大,请慎重使用***</b><br />
69+
<ul>
70+
<li>如果不包含前缀,默认为空</li>
71+
<li>如果不包含起始偏移,默认为0</li>
72+
<li>如果不包含数量限制,默认为无限制</li>
73+
</ul>
74+
返回:一个json编码的文本,格式如<code>[ 结果列表 ]</code>,每个列表项为<code>{ key: '标签', value: '值' }</code><br />
75+
例子:
76+
<ul>
77+
<li>获取所有标签:“<span v-text="special_getall" />”</li>
78+
<li>获取所有以a开头的标签:“<span v-text="special_getall" />#a”</li>
79+
<li>获取所有标签中的前100个:“<span v-text="special_getall" />#a#0#100”</li>
80+
<li>获取所有标签中的第101-150个:“<span v-text="special_getall" />#a#100#50”</li>
81+
</ul>
82+
</template>
83+
</b-form-group>
84+
<b-form-group label="一次性获取多个标签的值" :state="special_listget_state" invalid-feedback="不能包含,空格">
85+
<b-input v-model="special_tags.value.listget" placeholder="special_listget" :state="special_listget_state" />
86+
<template slot="description">
87+
使用方法:请求获取标签“<span v-text="special_listget" />[#标签1][#标签2][……]”<br />
88+
返回:一个json编码的文本,格式如<code>[ 结果列表 ]</code>,每个列表项为<code>{ key: '标签', value: '值' }</code><br />
89+
例子:获取"id_2455_pwd"和"id_2455_money":“<span v-text="special_listget" />#id_2455_pwd#id_2455_money”
90+
</template>
91+
</b-form-group>
92+
<b-form-group label="搜索数据库的标签和值" :state="special_search_state" invalid-feedback="不能包含,空格">
93+
<b-input v-model="special_tags.value.search" placeholder="special_search" :state="special_search_state" />
94+
<template slot="description">
95+
使用方法:请求获取标签“<span v-text="special_search" />#搜索关键词”<br />
96+
返回:一个json编码的文本,格式如<code>{ "count": 总共多少项, "result": [ 搜索结果列表 ] }</code>,其中每个列表项为<code>{ key: '标签', value: '值' }</code><br />
97+
例子:搜索"john":“<span v-text="special_search" />#john”
98+
</template>
99+
</b-form-group>
100+
<SpinnerButton
101+
ref="special_tags_button"
102+
:disabled="special_count_state === false || special_getall_state === false || special_listget_state === false || special_search_state === false"
103+
:variant="typeof special_tags.variant === 'string' ? special_tags.variant : 'secondary'"
104+
@click="onDone => save('special_tags', onDone)">
105+
<span v-text="typeof special_tags.text === 'string' ? special_tags.text : '保存'"/>
106+
</SpinnerButton>
107+
</b-form>
45108

46109
<hr>
47110

@@ -80,13 +143,10 @@ export default {
80143
data () {
81144
return {
82145
loaded: false,
83-
all_category: {
84-
value: '',
85-
variant: undefined,
86-
text: undefined
87-
},
88-
allow_browser: {
89-
value: true,
146+
all_category: { value: '', variant: undefined, text: undefined },
147+
allow_browser: { value: true, variant: undefined, text: undefined },
148+
special_tags: {
149+
value: { count: '', getall: '', listget: '', search: '' },
90150
variant: undefined,
91151
text: undefined
92152
}
@@ -96,19 +156,40 @@ export default {
96156
all_category_preview () {
97157
return Array.from(new Set(this.all_category.value.split('#')))
98158
.map(item => ({value: item, text: item.length === 0 ? '显示所有' : `前缀\`${item}\``}))
99-
}
159+
},
160+
special_count () { return this.special_tags.value.count || 'special_count' },
161+
special_getall () { return this.special_tags.value.getall || 'special_getall' },
162+
special_listget () { return this.special_tags.value.listget || 'special_listget' },
163+
special_search () { return this.special_tags.value.search || 'special_search' },
164+
special_count_state () { return this.vaidSpecialTag(this.special_count) },
165+
special_getall_state () { return this.vaidSpecialTag(this.special_getall) },
166+
special_listget_state () { return this.vaidSpecialTag(this.special_listget) },
167+
special_search_state () { return this.vaidSpecialTag(this.special_search) }
100168
},
101169
mounted () {
102170
this.loadSettings()
103171
},
104172
methods: {
173+
vaidSpecialTag (val) {
174+
if (val.indexOf('#') >= 0 || val.indexOf(' ') >= 0) {
175+
return false
176+
}
177+
return null
178+
},
105179
async loadSettings () {
106180
this.loaded = false
107181
let { status, result } = (await this.$parent.service.get('settings')).data
108182
switch (status) {
109183
case 0: {
110184
this.all_category.value = result.all_category || ''
111185
this.allow_browser.value = result.allow_browser !== 'false'
186+
if (result.special_tags) {
187+
result.special_tags = JSON.parse(result.special_tags)
188+
this.special_tags.value.count = typeof result.special_tags.count === 'string' ? result.special_tags.count : ''
189+
this.special_tags.value.getall = typeof result.special_tags.getall === 'string' ? result.special_tags.getall : ''
190+
this.special_tags.value.listget = typeof result.special_tags.listget === 'string' ? result.special_tags.listget : ''
191+
this.special_tags.value.search = typeof result.special_tags.search === 'string' ? result.special_tags.search : ''
192+
}
112193
this.loaded = true
113194
break
114195
}
@@ -123,12 +204,13 @@ export default {
123204
this.$root.showInfo('设置内容为undefined或null,请刷新页面后重试。如反复出现请联系作者排查问题')
124205
return
125206
}
207+
value = Array.isArray(value) || typeof value === 'object' ? JSON.stringify(value) : value
126208
let { status } = (await this.$parent.service.post('setting_update', { settingId, value })).data
209+
onDone()
127210
switch (status) {
128211
case 0: {
129212
this[settingId].text = '保存成功'
130213
this[settingId].variant = 'success'
131-
onDone()
132214
await this.$root.sleep(1000)
133215
this[settingId].text = undefined
134216
this[settingId].variant = undefined

0 commit comments

Comments
 (0)