Compare commits
114 Commits
scriptload
...
master
Author | SHA1 | Date | |
---|---|---|---|
8aeec60181 | |||
58d3e4f645 | |||
e592a753bf | |||
d598fb5ce5 | |||
63f769796f | |||
7cbfdf8601 | |||
9c60d10568 | |||
dcbe760f09 | |||
d220bb2a6c | |||
eb7ccd4f2d | |||
39c9dc1b09 | |||
68beb0fcbb | |||
1f5f7f465d | |||
b7c09cb5a2 | |||
5942f76972 | |||
1f40810b78 | |||
da858d55e0 | |||
166bb08ed0 | |||
5eaf798a6c | |||
e2e6bcc8ce | |||
daa7101493 | |||
6f51f1c295 | |||
a8d1dcdd5b | |||
9af2257650 | |||
63591899bb | |||
ee9ba3fcf0 | |||
a78815f3d3 | |||
6209f2b5e5 | |||
08d3bca39c | |||
9b8e597066 | |||
3215b0c8ea | |||
c7c97c469f | |||
b45ad0e54e | |||
a0c6e48e83 | |||
3c3ed73971 | |||
be58a35245 | |||
67bdf1e070 | |||
981e0ad85b | |||
74159940b5 | |||
206e5902d1 | |||
2d38b36525 | |||
af712f06a5 | |||
73575965d3 | |||
f49ad731e3 | |||
802c7c7dcc | |||
20ea36c727 | |||
fd3199a83c | |||
e25f679ea6 | |||
4842d53316 | |||
65bfccdd48 | |||
c60146d614 | |||
9285698ee4 | |||
5e18c9babd | |||
8bdc53d175 | |||
ad9bdc7574 | |||
0352dd0fd0 | |||
6044b8eaec | |||
8d3197ee98 | |||
8fcf3ecca2 | |||
4d9d011213 | |||
12b75b9d82 | |||
568ab15a34 | |||
c38b62c82a | |||
0774b122ee | |||
f7d2377101 | |||
088fc306de | |||
57d345e445 | |||
f257a966e6 | |||
ceffeccf8d | |||
eed45f51ba | |||
d72bed0c8c | |||
0cdb3ba040 | |||
227de8bdc8 | |||
74304b5b12 | |||
ac29cf2448 | |||
137b2a9738 | |||
9f49a274cd | |||
7c3f8baaa2 | |||
547d8e59e6 | |||
7bbc961f72 | |||
66c02f7fc9 | |||
a5294e2e20 | |||
7978e9ee74 | |||
f6a5cf4255 | |||
928a608878 | |||
42d2795a05 | |||
041d06104b | |||
d1fb560578 | |||
42484e3f96 | |||
64a2c2e33b | |||
86d1616732 | |||
2eb58f732b | |||
936d033547 | |||
cd4787991d | |||
71ddf299e4 | |||
0f467bbc98 | |||
171b3bc59c | |||
f369cf4f22 | |||
ddf6e62e5a | |||
e502f581e1 | |||
acb064b762 | |||
f0c1744998 | |||
876a81c062 | |||
78f5157efe | |||
acbcbf455f | |||
179545f2bb | |||
48a3fe6588 | |||
3fd4f412b1 | |||
5273f4ecf9 | |||
b9c2527f4c | |||
1286338af0 | |||
21a4ff3b3e | |||
2302aa7ff8 | |||
bc71be7238 |
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -4,3 +4,4 @@
|
||||||
err.log
|
err.log
|
||||||
/plugins/
|
/plugins/
|
||||||
/config.json
|
/config.json
|
||||||
|
go.sum
|
|
@ -1,8 +1,7 @@
|
||||||
FROM golang:latest as gobulidIso
|
FROM golang:1.22.2-alpine as gobulidIso
|
||||||
COPY ./ /go/src/wp-go
|
COPY ./ /go/src/wp-go
|
||||||
WORKDIR /go/src/wp-go
|
WORKDIR /go/src/wp-go
|
||||||
ENV GOPROXY="https://goproxy.cn"
|
RUN go build -ldflags "-w" -tags netgo -o wp-go app/cmd/main.go
|
||||||
RUN go build -ldflags "-w" -tags netgo -o wp-go internal/cmd/main.go
|
|
||||||
|
|
||||||
FROM alpine:latest
|
FROM alpine:latest
|
||||||
WORKDIR /opt/wp-go
|
WORKDIR /opt/wp-go
|
||||||
|
|
14
README.md
14
README.md
|
@ -20,6 +20,11 @@
|
||||||
- kill -SIGUSR1 PID 更新配置和清空缓存
|
- kill -SIGUSR1 PID 更新配置和清空缓存
|
||||||
- kill -SIGUSR2 PID 清空缓存
|
- kill -SIGUSR2 PID 清空缓存
|
||||||
|
|
||||||
|
#### 运行
|
||||||
|
```
|
||||||
|
go run app/cmd/main.go [-c configpath] [-p port]
|
||||||
|
```
|
||||||
|
|
||||||
#### 数据显示支持程度
|
#### 数据显示支持程度
|
||||||
|
|
||||||
| 页表 | 支持程度 |
|
| 页表 | 支持程度 |
|
||||||
|
@ -48,7 +53,9 @@
|
||||||
- 博客页面至多显示数量
|
- 博客页面至多显示数量
|
||||||
- Feed中显示最近数量
|
- Feed中显示最近数量
|
||||||
- 讨论
|
- 讨论
|
||||||
- 其他评论设置-启用评论嵌套,最多嵌套层数
|
- 其他评论设置
|
||||||
|
- `启用|禁止`评论嵌套,最多嵌套层数
|
||||||
|
- 分页显示评论,每页显示评论条数,默认显示`最前/后`页
|
||||||
- 在每个页面顶部显示 `新旧`评论
|
- 在每个页面顶部显示 `新旧`评论
|
||||||
|
|
||||||
#### 主题支持程度
|
#### 主题支持程度
|
||||||
|
@ -73,3 +80,8 @@
|
||||||
#### 其它
|
#### 其它
|
||||||
|
|
||||||
用的gin框架和sqlx,在外面封装了层查询的方法。
|
用的gin框架和sqlx,在外面封装了层查询的方法。
|
||||||
|
|
||||||
|
#### 鸣谢
|
||||||
|
|
||||||
|
<a href="https://jb.gg/OpenSourceSupport"><img src="https://resources.jetbrains.com/storage/products/company/brand/logos/jb_beam.png" alt="JetBrains Logo (Main) logo." width="30%"></a>
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,7 @@ import (
|
||||||
"github.com/fthvgb1/wp-go/app/pkg/logs"
|
"github.com/fthvgb1/wp-go/app/pkg/logs"
|
||||||
"github.com/fthvgb1/wp-go/app/wpconfig"
|
"github.com/fthvgb1/wp-go/app/wpconfig"
|
||||||
"github.com/fthvgb1/wp-go/helper/slice"
|
"github.com/fthvgb1/wp-go/helper/slice"
|
||||||
|
str "github.com/fthvgb1/wp-go/helper/strings"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/go-playground/validator/v10"
|
"github.com/go-playground/validator/v10"
|
||||||
"io"
|
"io"
|
||||||
|
@ -77,7 +78,7 @@ func PostComment(c *gin.Context) {
|
||||||
}
|
}
|
||||||
req.Host = home.Host
|
req.Host = home.Host
|
||||||
res, err := cli.Do(req)
|
res, err := cli.Do(req)
|
||||||
if err != nil && err != http.ErrUseLastResponse {
|
if err != nil && !errors.Is(err, http.ErrUseLastResponse) {
|
||||||
logs.Error(err, "请求评论接口错误")
|
logs.Error(err, "请求评论接口错误")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -110,6 +111,9 @@ func PostComment(c *gin.Context) {
|
||||||
}
|
}
|
||||||
cc := c.Copy()
|
cc := c.Copy()
|
||||||
go func() {
|
go func() {
|
||||||
|
if gin.Mode() != gin.ReleaseMode {
|
||||||
|
return
|
||||||
|
}
|
||||||
id := comment.CommentPostId
|
id := comment.CommentPostId
|
||||||
if id <= 0 {
|
if id <= 0 {
|
||||||
logs.Error(errors.New("获取文档id错误"), "", comment.CommentPostId)
|
logs.Error(errors.New("获取文档id错误"), "", comment.CommentPostId)
|
||||||
|
@ -130,8 +134,15 @@ func PostComment(c *gin.Context) {
|
||||||
err = er
|
err = er
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
uuu := ""
|
||||||
|
uu, _ := url.Parse(res.Header.Get("Location"))
|
||||||
|
if up.RawQuery != "" {
|
||||||
cache.NewCommentCache().Set(c, up.RawQuery, string(s))
|
cache.NewCommentCache().Set(c, up.RawQuery, string(s))
|
||||||
c.Redirect(http.StatusFound, res.Header.Get("Location"))
|
uuu = str.Join(uu.Path, "?", uu.RawQuery)
|
||||||
|
} else {
|
||||||
|
uuu = str.Join(uu.Path)
|
||||||
|
}
|
||||||
|
c.Redirect(http.StatusFound, uuu)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
var r io.Reader
|
var r io.Reader
|
||||||
|
|
|
@ -10,6 +10,30 @@ import (
|
||||||
|
|
||||||
var tmp = "Mon, 02 Jan 2006 15:04:05 GMT"
|
var tmp = "Mon, 02 Jan 2006 15:04:05 GMT"
|
||||||
|
|
||||||
|
func Feed(c *gin.Context) {
|
||||||
|
v, ok := c.GetQuery("feed")
|
||||||
|
if !ok || v == "" {
|
||||||
|
c.Next()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
switch v {
|
||||||
|
case "rss2":
|
||||||
|
p, ok := c.GetQuery("p")
|
||||||
|
if ok && p != "" {
|
||||||
|
c.AddParam("id", p)
|
||||||
|
PostFeed(c)
|
||||||
|
} else {
|
||||||
|
SiteFeed(c)
|
||||||
|
}
|
||||||
|
c.Abort()
|
||||||
|
return
|
||||||
|
case "comments-rss2":
|
||||||
|
CommentsFeed(c)
|
||||||
|
c.Abort()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func isCacheExpired(c *gin.Context, lastTime time.Time) bool {
|
func isCacheExpired(c *gin.Context, lastTime time.Time) bool {
|
||||||
eTag := str.Md5(lastTime.Format(tmp))
|
eTag := str.Md5(lastTime.Format(tmp))
|
||||||
since := c.Request.Header.Get("If-Modified-Since")
|
since := c.Request.Header.Get("If-Modified-Since")
|
||||||
|
@ -24,20 +48,21 @@ func isCacheExpired(c *gin.Context, lastTime time.Time) bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func Feed(c *gin.Context) {
|
func SiteFeed(c *gin.Context) {
|
||||||
if !isCacheExpired(c, cache.FeedCache().GetLastSetTime()) {
|
feed := cache.FeedCache()
|
||||||
|
if !isCacheExpired(c, feed.GetLastSetTime(c)) {
|
||||||
c.Status(http.StatusNotModified)
|
c.Status(http.StatusNotModified)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
r, err := cache.FeedCache().GetCache(c, time.Second, c)
|
r, err := feed.GetCache(c, time.Second, c)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.Status(http.StatusInternalServerError)
|
c.Status(http.StatusInternalServerError)
|
||||||
c.Abort()
|
c.Abort()
|
||||||
c.Error(err)
|
c.Error(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
setFeed(r[0], c, cache.FeedCache().GetLastSetTime())
|
setFeed(r[0], c, feed.GetLastSetTime(c))
|
||||||
}
|
}
|
||||||
|
|
||||||
func setFeed(s string, c *gin.Context, t time.Time) {
|
func setFeed(s string, c *gin.Context, t time.Time) {
|
||||||
|
@ -51,31 +76,33 @@ func setFeed(s string, c *gin.Context, t time.Time) {
|
||||||
|
|
||||||
func PostFeed(c *gin.Context) {
|
func PostFeed(c *gin.Context) {
|
||||||
id := c.Param("id")
|
id := c.Param("id")
|
||||||
if !isCacheExpired(c, cache.PostFeedCache().GetLastSetTime(c, id)) {
|
postFeed := cache.PostFeedCache()
|
||||||
|
if !isCacheExpired(c, postFeed.GetLastSetTime(c, id)) {
|
||||||
c.Status(http.StatusNotModified)
|
c.Status(http.StatusNotModified)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
s, err := cache.PostFeedCache().GetCache(c, id, time.Second, c, id)
|
s, err := postFeed.GetCache(c, id, time.Second)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.Status(http.StatusInternalServerError)
|
c.Status(http.StatusInternalServerError)
|
||||||
c.Abort()
|
c.Abort()
|
||||||
c.Error(err)
|
c.Error(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
setFeed(s, c, cache.PostFeedCache().GetLastSetTime(c, id))
|
setFeed(s, c, postFeed.GetLastSetTime(c, id))
|
||||||
}
|
}
|
||||||
|
|
||||||
func CommentsFeed(c *gin.Context) {
|
func CommentsFeed(c *gin.Context) {
|
||||||
if !isCacheExpired(c, cache.CommentsFeedCache().GetLastSetTime()) {
|
feed := cache.CommentsFeedCache()
|
||||||
|
if !isCacheExpired(c, feed.GetLastSetTime(c)) {
|
||||||
c.Status(http.StatusNotModified)
|
c.Status(http.StatusNotModified)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
r, err := cache.CommentsFeedCache().GetCache(c, time.Second, c)
|
r, err := feed.GetCache(c, time.Second, c)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.Status(http.StatusInternalServerError)
|
c.Status(http.StatusInternalServerError)
|
||||||
c.Abort()
|
c.Abort()
|
||||||
c.Error(err)
|
c.Error(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
setFeed(r[0], c, cache.CommentsFeedCache().GetLastSetTime())
|
setFeed(r[0], c, feed.GetLastSetTime(c))
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
package actions
|
package actions
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/fthvgb1/wp-go/app/pkg/constraints"
|
|
||||||
"github.com/fthvgb1/wp-go/app/theme"
|
"github.com/fthvgb1/wp-go/app/theme"
|
||||||
"github.com/fthvgb1/wp-go/app/theme/wp"
|
"github.com/fthvgb1/wp-go/app/theme/wp"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
|
@ -9,18 +8,8 @@ import (
|
||||||
|
|
||||||
func ThemeHook(scene string) func(*gin.Context) {
|
func ThemeHook(scene string) func(*gin.Context) {
|
||||||
return func(c *gin.Context) {
|
return func(c *gin.Context) {
|
||||||
s := scene
|
t := theme.GetCurrentTheme()
|
||||||
if scene == constraints.Home {
|
h := wp.NewHandle(c, scene, t)
|
||||||
if _, ok := c.GetQuery("s"); ok {
|
|
||||||
s = constraints.Search
|
|
||||||
}
|
|
||||||
}
|
|
||||||
t := theme.GetCurrentTemplateName()
|
|
||||||
h := wp.NewHandle(c, s, t)
|
|
||||||
h.Index = wp.NewIndexHandle(h)
|
|
||||||
h.Detail = wp.NewDetailHandle(h)
|
|
||||||
templ, _ := theme.GetTemplate(t)
|
|
||||||
h.SetTemplate(templ)
|
|
||||||
theme.Hook(t, h)
|
theme.Hook(t, h)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,53 +0,0 @@
|
||||||
package cachemanager
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"github.com/fthvgb1/wp-go/cache"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
var ctx = context.Background()
|
|
||||||
|
|
||||||
type flush interface {
|
|
||||||
Flush(ctx context.Context)
|
|
||||||
}
|
|
||||||
|
|
||||||
type clear interface {
|
|
||||||
ClearExpired(ctx context.Context)
|
|
||||||
}
|
|
||||||
|
|
||||||
var clears []clear
|
|
||||||
|
|
||||||
var flushes []flush
|
|
||||||
|
|
||||||
func Flush() {
|
|
||||||
for _, f := range flushes {
|
|
||||||
f.Flush(ctx)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func MapCacheBy[K comparable, V any](fn func(...any) (V, error), expireTime time.Duration) *cache.MapCache[K, V] {
|
|
||||||
m := cache.NewMemoryMapCacheByFn[K, V](fn, expireTime)
|
|
||||||
FlushPush(m)
|
|
||||||
ClearPush(m)
|
|
||||||
return m
|
|
||||||
}
|
|
||||||
func MapBatchCacheBy[K comparable, V any](fn func(...any) (map[K]V, error), expireTime time.Duration) *cache.MapCache[K, V] {
|
|
||||||
m := cache.NewMemoryMapCacheByBatchFn[K, V](fn, expireTime)
|
|
||||||
FlushPush(m)
|
|
||||||
ClearPush(m)
|
|
||||||
return m
|
|
||||||
}
|
|
||||||
|
|
||||||
func FlushPush(f ...flush) {
|
|
||||||
flushes = append(flushes, f...)
|
|
||||||
}
|
|
||||||
func ClearPush(c ...clear) {
|
|
||||||
clears = append(clears, c...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func ClearExpired() {
|
|
||||||
for _, c := range clears {
|
|
||||||
c.ClearExpired(ctx)
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -3,26 +3,21 @@ package main
|
||||||
import (
|
import (
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/fthvgb1/wp-go/app/cmd/cachemanager"
|
"github.com/fthvgb1/wp-go/app/ossigns"
|
||||||
"github.com/fthvgb1/wp-go/app/cmd/reload"
|
|
||||||
"github.com/fthvgb1/wp-go/app/cmd/route"
|
|
||||||
"github.com/fthvgb1/wp-go/app/mail"
|
|
||||||
"github.com/fthvgb1/wp-go/app/pkg/cache"
|
"github.com/fthvgb1/wp-go/app/pkg/cache"
|
||||||
"github.com/fthvgb1/wp-go/app/pkg/config"
|
"github.com/fthvgb1/wp-go/app/pkg/config"
|
||||||
"github.com/fthvgb1/wp-go/app/pkg/db"
|
"github.com/fthvgb1/wp-go/app/pkg/db"
|
||||||
"github.com/fthvgb1/wp-go/app/pkg/logs"
|
"github.com/fthvgb1/wp-go/app/pkg/logs"
|
||||||
"github.com/fthvgb1/wp-go/app/plugins"
|
"github.com/fthvgb1/wp-go/app/plugins"
|
||||||
"github.com/fthvgb1/wp-go/app/plugins/wphandle"
|
"github.com/fthvgb1/wp-go/app/plugins/wphandle"
|
||||||
|
"github.com/fthvgb1/wp-go/app/route"
|
||||||
"github.com/fthvgb1/wp-go/app/theme"
|
"github.com/fthvgb1/wp-go/app/theme"
|
||||||
"github.com/fthvgb1/wp-go/app/theme/wp/scriptloader"
|
|
||||||
"github.com/fthvgb1/wp-go/app/wpconfig"
|
"github.com/fthvgb1/wp-go/app/wpconfig"
|
||||||
|
"github.com/fthvgb1/wp-go/cache/cachemanager"
|
||||||
"github.com/fthvgb1/wp-go/model"
|
"github.com/fthvgb1/wp-go/model"
|
||||||
"log"
|
|
||||||
"os"
|
"os"
|
||||||
"os/signal"
|
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
"syscall"
|
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -30,13 +25,7 @@ var confPath string
|
||||||
var address string
|
var address string
|
||||||
var intReg = regexp.MustCompile(`^\d`)
|
var intReg = regexp.MustCompile(`^\d`)
|
||||||
|
|
||||||
func init() {
|
func inits() {
|
||||||
defer func() {
|
|
||||||
if r := recover(); r != nil {
|
|
||||||
fmt.Println(r)
|
|
||||||
os.Exit(-1)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
flag.StringVar(&confPath, "c", "config.yaml", "config file support json,yaml or url")
|
flag.StringVar(&confPath, "c", "config.yaml", "config file support json,yaml or url")
|
||||||
flag.StringVar(&address, "p", "", "listen address and port")
|
flag.StringVar(&address, "p", "", "listen address and port")
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
|
@ -50,7 +39,6 @@ func init() {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
scriptloader.InitDefaultScriptSetting()
|
|
||||||
cache.InitActionsCommonCache()
|
cache.InitActionsCommonCache()
|
||||||
plugins.InitDigestCache()
|
plugins.InitDigestCache()
|
||||||
theme.InitTheme()
|
theme.InitTheme()
|
||||||
|
@ -97,61 +85,16 @@ func cronClearCache() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func flushCache() {
|
|
||||||
defer func() {
|
|
||||||
if r := recover(); r != nil {
|
|
||||||
err := mail.SendMail([]string{config.GetConfig().Mail.User}, "清空缓存失败", fmt.Sprintf("err:[%s]", r))
|
|
||||||
logs.IfError(err, "发邮件失败")
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
cachemanager.Flush()
|
|
||||||
log.Println("all cache flushed")
|
|
||||||
}
|
|
||||||
|
|
||||||
func reloads() {
|
|
||||||
defer func() {
|
|
||||||
if r := recover(); r != nil {
|
|
||||||
log.Println(r)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
err := config.InitConfig(confPath)
|
|
||||||
logs.IfError(err, "获取配置文件失败", confPath)
|
|
||||||
err = logs.InitLogger()
|
|
||||||
logs.IfError(err, "日志配置错误")
|
|
||||||
_, err = db.InitDb()
|
|
||||||
logs.IfError(err, "重新读取db失败", config.GetConfig().Mysql)
|
|
||||||
err = wpconfig.InitOptions()
|
|
||||||
logs.IfError(err, "获取网站设置WpOption失败")
|
|
||||||
err = wpconfig.InitTerms()
|
|
||||||
logs.IfError(err, "获取WpTerms表失败")
|
|
||||||
scriptloader.InitDefaultScriptSetting()
|
|
||||||
wphandle.LoadPlugins()
|
|
||||||
reload.Reload()
|
|
||||||
flushCache()
|
|
||||||
log.Println("reload complete")
|
|
||||||
}
|
|
||||||
|
|
||||||
func signalNotify() {
|
|
||||||
c := make(chan os.Signal)
|
|
||||||
signal.Notify(c, syscall.SIGUSR1, syscall.SIGUSR2)
|
|
||||||
for {
|
|
||||||
switch <-c {
|
|
||||||
case syscall.SIGUSR1:
|
|
||||||
go reloads()
|
|
||||||
case syscall.SIGUSR2:
|
|
||||||
go flushCache()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
defer func() {
|
defer func() {
|
||||||
if r := recover(); r != nil {
|
if r := recover(); r != nil {
|
||||||
fmt.Println(r)
|
fmt.Println(r)
|
||||||
os.Exit(-1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
go signalNotify()
|
inits()
|
||||||
|
ossigns.SetConfPath(confPath)
|
||||||
|
go ossigns.SignalNotify()
|
||||||
Gin := route.SetupRouter()
|
Gin := route.SetupRouter()
|
||||||
c := config.GetConfig()
|
c := config.GetConfig()
|
||||||
if c.Ssl.Key != "" && c.Ssl.Cert != "" {
|
if c.Ssl.Key != "" && c.Ssl.Cert != "" {
|
||||||
|
|
|
@ -1,204 +0,0 @@
|
||||||
package reload
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/fthvgb1/wp-go/helper/number"
|
|
||||||
"github.com/fthvgb1/wp-go/safety"
|
|
||||||
"sync"
|
|
||||||
)
|
|
||||||
|
|
||||||
var calls []func()
|
|
||||||
|
|
||||||
var anyMap = safety.NewMap[string, any]()
|
|
||||||
|
|
||||||
type safetyVar[T, A any] struct {
|
|
||||||
Val *safety.Var[val[T]]
|
|
||||||
mutex sync.Mutex
|
|
||||||
}
|
|
||||||
type val[T any] struct {
|
|
||||||
v T
|
|
||||||
ok bool
|
|
||||||
counter number.Counter[int]
|
|
||||||
}
|
|
||||||
type safetyMap[K comparable, V, A any] struct {
|
|
||||||
val *safety.Map[K, V]
|
|
||||||
mutex sync.Mutex
|
|
||||||
}
|
|
||||||
|
|
||||||
var safetyMaps = safety.NewMap[string, any]()
|
|
||||||
var safetyMapLock = sync.Mutex{}
|
|
||||||
|
|
||||||
func GetAnyMapFnBys[K comparable, V, A any](namespace string, fn func(A) V) func(key K, args A) V {
|
|
||||||
m := safetyMapFn[K, V, A](namespace)
|
|
||||||
return func(key K, a A) V {
|
|
||||||
v, ok := m.val.Load(key)
|
|
||||||
if ok {
|
|
||||||
return v
|
|
||||||
}
|
|
||||||
m.mutex.Lock()
|
|
||||||
v, ok = m.val.Load(key)
|
|
||||||
if ok {
|
|
||||||
m.mutex.Unlock()
|
|
||||||
return v
|
|
||||||
}
|
|
||||||
v = fn(a)
|
|
||||||
m.val.Store(key, v)
|
|
||||||
m.mutex.Unlock()
|
|
||||||
return v
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func safetyMapFn[K comparable, V, A any](namespace string) *safetyMap[K, V, A] {
|
|
||||||
vv, ok := safetyMaps.Load(namespace)
|
|
||||||
var m *safetyMap[K, V, A]
|
|
||||||
if ok {
|
|
||||||
m = vv.(*safetyMap[K, V, A])
|
|
||||||
} else {
|
|
||||||
safetyMapLock.Lock()
|
|
||||||
vv, ok = safetyMaps.Load(namespace)
|
|
||||||
if ok {
|
|
||||||
m = vv.(*safetyMap[K, V, A])
|
|
||||||
} else {
|
|
||||||
m = &safetyMap[K, V, A]{safety.NewMap[K, V](), sync.Mutex{}}
|
|
||||||
Push(func() {
|
|
||||||
m.val.Flush()
|
|
||||||
})
|
|
||||||
safetyMaps.Store(namespace, m)
|
|
||||||
}
|
|
||||||
safetyMapLock.Unlock()
|
|
||||||
}
|
|
||||||
return m
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetAnyValMapBy[K comparable, V, A any](namespace string, key K, a A, fn func(A) V) V {
|
|
||||||
m := safetyMapFn[K, V, A](namespace)
|
|
||||||
v, ok := m.val.Load(key)
|
|
||||||
if ok {
|
|
||||||
return v
|
|
||||||
}
|
|
||||||
m.mutex.Lock()
|
|
||||||
v, ok = m.val.Load(key)
|
|
||||||
if ok {
|
|
||||||
m.mutex.Unlock()
|
|
||||||
return v
|
|
||||||
}
|
|
||||||
v = fn(a)
|
|
||||||
m.val.Store(key, v)
|
|
||||||
m.mutex.Unlock()
|
|
||||||
return v
|
|
||||||
}
|
|
||||||
|
|
||||||
func anyVal[T, A any](namespace string, counter bool) *safetyVar[T, A] {
|
|
||||||
var vv *safetyVar[T, A]
|
|
||||||
vvv, ok := safetyMaps.Load(namespace)
|
|
||||||
if ok {
|
|
||||||
vv = vvv.(*safetyVar[T, A])
|
|
||||||
} else {
|
|
||||||
safetyMapLock.Lock()
|
|
||||||
vvv, ok = safetyMaps.Load(namespace)
|
|
||||||
if ok {
|
|
||||||
vv = vvv.(*safetyVar[T, A])
|
|
||||||
} else {
|
|
||||||
v := val[T]{}
|
|
||||||
if counter {
|
|
||||||
v.counter = number.Counters[int]()
|
|
||||||
}
|
|
||||||
vv = &safetyVar[T, A]{safety.NewVar(v), sync.Mutex{}}
|
|
||||||
Push(func() {
|
|
||||||
vv.Val.Flush()
|
|
||||||
})
|
|
||||||
safetyMaps.Store(namespace, vv)
|
|
||||||
}
|
|
||||||
safetyMapLock.Unlock()
|
|
||||||
}
|
|
||||||
return vv
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetAnyValBy[T, A any](namespace string, tryTimes int, a A, fn func(A) (T, bool)) T {
|
|
||||||
var vv = anyVal[T, A](namespace, true)
|
|
||||||
var ok bool
|
|
||||||
v := vv.Val.Load()
|
|
||||||
if v.ok {
|
|
||||||
return v.v
|
|
||||||
}
|
|
||||||
vv.mutex.Lock()
|
|
||||||
v = vv.Val.Load()
|
|
||||||
if v.ok {
|
|
||||||
vv.mutex.Unlock()
|
|
||||||
return v.v
|
|
||||||
}
|
|
||||||
v.v, ok = fn(a)
|
|
||||||
times := v.counter()
|
|
||||||
if ok || times >= tryTimes {
|
|
||||||
v.ok = true
|
|
||||||
vv.Val.Store(v)
|
|
||||||
}
|
|
||||||
vv.mutex.Unlock()
|
|
||||||
return v.v
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetAnyValBys[T, A any](namespace string, a A, fn func(A) T) T {
|
|
||||||
var vv = anyVal[T, A](namespace, false)
|
|
||||||
v := vv.Val.Load()
|
|
||||||
if v.ok {
|
|
||||||
return v.v
|
|
||||||
}
|
|
||||||
vv.mutex.Lock()
|
|
||||||
v = vv.Val.Load()
|
|
||||||
if v.ok {
|
|
||||||
vv.mutex.Unlock()
|
|
||||||
return v.v
|
|
||||||
}
|
|
||||||
v.v = fn(a)
|
|
||||||
v.ok = true
|
|
||||||
vv.Val.Store(v)
|
|
||||||
vv.mutex.Unlock()
|
|
||||||
return v.v
|
|
||||||
}
|
|
||||||
|
|
||||||
func Vars[T any](defaults T) *safety.Var[T] {
|
|
||||||
ss := safety.NewVar(defaults)
|
|
||||||
calls = append(calls, func() {
|
|
||||||
ss.Store(defaults)
|
|
||||||
})
|
|
||||||
return ss
|
|
||||||
}
|
|
||||||
func VarsBy[T any](fn func() T) *safety.Var[T] {
|
|
||||||
ss := safety.NewVar(fn())
|
|
||||||
calls = append(calls, func() {
|
|
||||||
ss.Store(fn())
|
|
||||||
})
|
|
||||||
return ss
|
|
||||||
}
|
|
||||||
func MapBy[K comparable, T any](fn func(*safety.Map[K, T])) *safety.Map[K, T] {
|
|
||||||
m := safety.NewMap[K, T]()
|
|
||||||
if fn != nil {
|
|
||||||
fn(m)
|
|
||||||
}
|
|
||||||
calls = append(calls, func() {
|
|
||||||
m.Flush()
|
|
||||||
if fn != nil {
|
|
||||||
fn(m)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
return m
|
|
||||||
}
|
|
||||||
|
|
||||||
func SafeMap[K comparable, T any]() *safety.Map[K, T] {
|
|
||||||
m := safety.NewMap[K, T]()
|
|
||||||
calls = append(calls, func() {
|
|
||||||
m.Flush()
|
|
||||||
})
|
|
||||||
return m
|
|
||||||
}
|
|
||||||
|
|
||||||
func Push(fn ...func()) {
|
|
||||||
calls = append(calls, fn...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func Reload() {
|
|
||||||
for _, call := range calls {
|
|
||||||
call()
|
|
||||||
}
|
|
||||||
anyMap.Flush()
|
|
||||||
safetyMaps.Flush()
|
|
||||||
}
|
|
|
@ -1,97 +0,0 @@
|
||||||
package route
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/fthvgb1/wp-go/app/actions"
|
|
||||||
"github.com/fthvgb1/wp-go/app/cmd/reload"
|
|
||||||
"github.com/fthvgb1/wp-go/app/middleware"
|
|
||||||
"github.com/fthvgb1/wp-go/app/pkg/config"
|
|
||||||
"github.com/fthvgb1/wp-go/app/pkg/constraints"
|
|
||||||
"github.com/fthvgb1/wp-go/app/theme"
|
|
||||||
"github.com/fthvgb1/wp-go/app/wpconfig"
|
|
||||||
str "github.com/fthvgb1/wp-go/helper/strings"
|
|
||||||
"github.com/gin-contrib/gzip"
|
|
||||||
"github.com/gin-contrib/pprof"
|
|
||||||
"github.com/gin-contrib/sessions"
|
|
||||||
"github.com/gin-contrib/sessions/cookie"
|
|
||||||
"github.com/gin-gonic/gin"
|
|
||||||
)
|
|
||||||
|
|
||||||
var hooker []func(r *gin.Engine)
|
|
||||||
|
|
||||||
// Hook 方便插件在init时使用
|
|
||||||
func Hook(fn ...func(r *gin.Engine)) {
|
|
||||||
hooker = append(hooker, fn...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func SetupRouter() *gin.Engine {
|
|
||||||
// Disable Console Color
|
|
||||||
// gin.DisableConsoleColor()
|
|
||||||
r := gin.New()
|
|
||||||
c := config.GetConfig()
|
|
||||||
if len(c.TrustIps) > 0 {
|
|
||||||
err := r.SetTrustedProxies(c.TrustIps)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
r.HTMLRender = theme.Template()
|
|
||||||
wpconfig.SetTemplateFs(theme.TemplateFs)
|
|
||||||
siteFlowLimitMiddleware, siteFlow := middleware.FlowLimit(c.MaxRequestSleepNum, c.MaxRequestNum, c.CacheTime.SleepTime)
|
|
||||||
r.Use(
|
|
||||||
gin.Logger(),
|
|
||||||
middleware.ValidateServerNames(),
|
|
||||||
middleware.RecoverAndSendMail(gin.DefaultErrorWriter),
|
|
||||||
siteFlowLimitMiddleware,
|
|
||||||
middleware.SetStaticFileCache,
|
|
||||||
)
|
|
||||||
//gzip 因为一般会用nginx做反代时自动使用gzip,所以go这边本身可以不用
|
|
||||||
if c.Gzip {
|
|
||||||
r.Use(gzip.Gzip(gzip.DefaultCompression, gzip.WithExcludedPaths([]string{
|
|
||||||
"/wp-includes/", "/wp-content/",
|
|
||||||
})))
|
|
||||||
}
|
|
||||||
|
|
||||||
if c.WpDir == "" {
|
|
||||||
panic("wordpress path can't be empty")
|
|
||||||
}
|
|
||||||
r.Static("/wp-content/uploads", str.Join(c.WpDir, "/wp-content/uploads"))
|
|
||||||
r.Static("/wp-content/themes", str.Join(c.WpDir, "/wp-content/themes"))
|
|
||||||
r.Static("/wp-content/plugins", str.Join(c.WpDir, "/wp-content/plugins"))
|
|
||||||
r.Static("/wp-includes/css", str.Join(c.WpDir, "/wp-includes/css"))
|
|
||||||
r.Static("/wp-includes/fonts", str.Join(c.WpDir, "/wp-includes/fonts"))
|
|
||||||
r.Static("/wp-includes/js", str.Join(c.WpDir, "/wp-includes/js"))
|
|
||||||
|
|
||||||
store := cookie.NewStore([]byte("secret"))
|
|
||||||
r.Use(sessions.Sessions("go-wp", store))
|
|
||||||
r.GET("/", middleware.SearchLimit(c.SingleIpSearchNum), actions.ThemeHook(constraints.Home))
|
|
||||||
r.GET("/page/:page", actions.ThemeHook(constraints.Home))
|
|
||||||
r.GET("/p/category/:category", actions.ThemeHook(constraints.Category))
|
|
||||||
r.GET("/p/category/:category/page/:page", actions.ThemeHook(constraints.Category))
|
|
||||||
r.GET("/p/tag/:tag", actions.ThemeHook(constraints.Tag))
|
|
||||||
r.GET("/p/tag/:tag/page/:page", actions.ThemeHook(constraints.Tag))
|
|
||||||
r.GET("/p/date/:year/:month", actions.ThemeHook(constraints.Archive))
|
|
||||||
r.GET("/p/date/:year/:month/page/:page", actions.ThemeHook(constraints.Archive))
|
|
||||||
r.GET("/p/author/:author", actions.ThemeHook(constraints.Author))
|
|
||||||
r.GET("/p/author/:author/page/:page", actions.ThemeHook(constraints.Author))
|
|
||||||
r.POST("/login", actions.Login)
|
|
||||||
r.GET("/p/:id", actions.ThemeHook(constraints.Detail))
|
|
||||||
r.GET("/p/:id/feed", actions.PostFeed)
|
|
||||||
r.GET("/feed", actions.Feed)
|
|
||||||
r.GET("/comments/feed", actions.CommentsFeed)
|
|
||||||
//r.NoRoute(actions.ThemeHook(constraints.NoRoute))
|
|
||||||
commentMiddleWare, _ := middleware.FlowLimit(c.MaxRequestSleepNum, 5, c.CacheTime.SleepTime)
|
|
||||||
r.POST("/comment", commentMiddleWare, actions.PostComment)
|
|
||||||
if c.Pprof != "" {
|
|
||||||
pprof.Register(r, c.Pprof)
|
|
||||||
}
|
|
||||||
for _, fn := range hooker {
|
|
||||||
fn(r)
|
|
||||||
}
|
|
||||||
|
|
||||||
reload.Push(func() {
|
|
||||||
c := config.GetConfig()
|
|
||||||
siteFlow(c.MaxRequestSleepNum, c.MaxRequestNum, c.CacheTime.SleepTime)
|
|
||||||
})
|
|
||||||
return r
|
|
||||||
}
|
|
|
@ -19,9 +19,9 @@ func FlowLimit(maxRequestSleepNum, maxRequestNum int64, sleepTime []time.Duratio
|
||||||
}
|
}
|
||||||
s := safety.Var[[]time.Duration]{}
|
s := safety.Var[[]time.Duration]{}
|
||||||
s.Store(sleepTime)
|
s.Store(sleepTime)
|
||||||
fn := func(msn, mn int64, st []time.Duration) {
|
fn := func(sleepNum, maxNum int64, st []time.Duration) {
|
||||||
atomic.StoreInt64(&maxRequestSleepNum, msn)
|
atomic.StoreInt64(&maxRequestSleepNum, sleepNum)
|
||||||
atomic.StoreInt64(&maxRequestNum, mn)
|
atomic.StoreInt64(&maxRequestNum, maxNum)
|
||||||
s.Store(st)
|
s.Store(st)
|
||||||
}
|
}
|
||||||
return func(c *gin.Context) {
|
return func(c *gin.Context) {
|
||||||
|
|
|
@ -25,14 +25,25 @@ func IpLimit(num int64) (func(ctx *gin.Context), func(int64)) {
|
||||||
fn(num)
|
fn(num)
|
||||||
|
|
||||||
return func(c *gin.Context) {
|
return func(c *gin.Context) {
|
||||||
|
if atomic.LoadInt64(m.limitNum) <= 0 {
|
||||||
|
c.Next()
|
||||||
|
return
|
||||||
|
}
|
||||||
ip := c.ClientIP()
|
ip := c.ClientIP()
|
||||||
s := false
|
|
||||||
m.mux.RLock()
|
m.mux.RLock()
|
||||||
i, ok := m.m[ip]
|
i, ok := m.m[ip]
|
||||||
m.mux.RUnlock()
|
m.mux.RUnlock()
|
||||||
|
|
||||||
|
if !ok {
|
||||||
|
m.mux.Lock()
|
||||||
|
i = new(int64)
|
||||||
|
m.m[ip] = i
|
||||||
|
m.mux.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
ii := atomic.LoadInt64(i)
|
ii := atomic.LoadInt64(i)
|
||||||
if s && ii > 0 {
|
if ii > 0 {
|
||||||
atomic.AddInt64(i, -1)
|
atomic.AddInt64(i, -1)
|
||||||
if atomic.LoadInt64(i) == 0 {
|
if atomic.LoadInt64(i) == 0 {
|
||||||
m.mux.Lock()
|
m.mux.Lock()
|
||||||
|
@ -42,20 +53,12 @@ func IpLimit(num int64) (func(ctx *gin.Context), func(int64)) {
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
if !ok {
|
if atomic.LoadInt64(i) >= atomic.LoadInt64(m.limitNum) {
|
||||||
m.mux.Lock()
|
|
||||||
i = new(int64)
|
|
||||||
m.m[ip] = i
|
|
||||||
m.mux.Unlock()
|
|
||||||
}
|
|
||||||
|
|
||||||
if atomic.LoadInt64(m.limitNum) > 0 && atomic.LoadInt64(i) >= atomic.LoadInt64(m.limitNum) {
|
|
||||||
c.Status(http.StatusForbidden)
|
c.Status(http.StatusForbidden)
|
||||||
c.Abort()
|
c.Abort()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
atomic.AddInt64(i, 1)
|
atomic.AddInt64(i, 1)
|
||||||
s = true
|
|
||||||
c.Next()
|
c.Next()
|
||||||
}, fn
|
}, fn
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,16 +1,16 @@
|
||||||
package middleware
|
package middleware
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/fthvgb1/wp-go/app/cmd/reload"
|
|
||||||
"github.com/fthvgb1/wp-go/app/pkg/config"
|
"github.com/fthvgb1/wp-go/app/pkg/config"
|
||||||
|
"github.com/fthvgb1/wp-go/cache/reload"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
)
|
)
|
||||||
|
|
||||||
func SearchLimit(num int64) func(ctx *gin.Context) {
|
func SearchLimit(num int64) func(ctx *gin.Context) {
|
||||||
fn, reFn := IpLimit(num)
|
fn, reFn := IpLimit(num)
|
||||||
reload.Push(func() {
|
reload.Append(func() {
|
||||||
reFn(config.GetConfig().SingleIpSearchNum)
|
reFn(config.GetConfig().SingleIpSearchNum)
|
||||||
})
|
}, "search-ip-limit-number")
|
||||||
return func(c *gin.Context) {
|
return func(c *gin.Context) {
|
||||||
if c.Query("s") != "" {
|
if c.Query("s") != "" {
|
||||||
fn(c)
|
fn(c)
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
package middleware
|
package middleware
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/fthvgb1/wp-go/app/cmd/reload"
|
|
||||||
"github.com/fthvgb1/wp-go/app/pkg/config"
|
"github.com/fthvgb1/wp-go/app/pkg/config"
|
||||||
|
"github.com/fthvgb1/wp-go/cache/reload"
|
||||||
"github.com/fthvgb1/wp-go/helper/maps"
|
"github.com/fthvgb1/wp-go/helper/maps"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
@ -19,7 +19,7 @@ func ValidateServerNames() func(ctx *gin.Context) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return m
|
return m
|
||||||
})
|
}, "site-names")
|
||||||
|
|
||||||
return func(c *gin.Context) {
|
return func(c *gin.Context) {
|
||||||
m := sites.Load()
|
m := sites.Load()
|
||||||
|
|
69
app/ossigns/signs.go
Normal file
69
app/ossigns/signs.go
Normal file
|
@ -0,0 +1,69 @@
|
||||||
|
package ossigns
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/fthvgb1/wp-go/app/mail"
|
||||||
|
"github.com/fthvgb1/wp-go/app/pkg/config"
|
||||||
|
"github.com/fthvgb1/wp-go/app/pkg/db"
|
||||||
|
"github.com/fthvgb1/wp-go/app/pkg/logs"
|
||||||
|
"github.com/fthvgb1/wp-go/app/plugins/wphandle"
|
||||||
|
"github.com/fthvgb1/wp-go/app/wpconfig"
|
||||||
|
"github.com/fthvgb1/wp-go/cache/cachemanager"
|
||||||
|
"github.com/fthvgb1/wp-go/cache/reload"
|
||||||
|
"github.com/fthvgb1/wp-go/signs"
|
||||||
|
"log"
|
||||||
|
"syscall"
|
||||||
|
)
|
||||||
|
|
||||||
|
var confPath string
|
||||||
|
|
||||||
|
func SetConfPath(path string) {
|
||||||
|
confPath = path
|
||||||
|
}
|
||||||
|
|
||||||
|
func FlushCache() {
|
||||||
|
defer func() {
|
||||||
|
if r := recover(); r != nil {
|
||||||
|
err := mail.SendMail([]string{config.GetConfig().Mail.User}, "清空缓存失败", fmt.Sprintf("err:[%s]", r))
|
||||||
|
logs.IfError(err, "发邮件失败")
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
cachemanager.Flush()
|
||||||
|
log.Println("all cache flushed")
|
||||||
|
}
|
||||||
|
|
||||||
|
func Reloads() {
|
||||||
|
defer func() {
|
||||||
|
if r := recover(); r != nil {
|
||||||
|
log.Println(r)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
err := config.InitConfig(confPath)
|
||||||
|
logs.IfError(err, "获取配置文件失败", confPath)
|
||||||
|
err = logs.InitLogger()
|
||||||
|
logs.IfError(err, "日志配置错误")
|
||||||
|
_, err = db.InitDb()
|
||||||
|
logs.IfError(err, "重新读取db失败", config.GetConfig().Mysql)
|
||||||
|
err = wpconfig.InitOptions()
|
||||||
|
logs.IfError(err, "获取网站设置WpOption失败")
|
||||||
|
err = wpconfig.InitTerms()
|
||||||
|
logs.IfError(err, "获取WpTerms表失败")
|
||||||
|
wphandle.LoadPlugins()
|
||||||
|
reload.Reloads("themeArgAndConfig")
|
||||||
|
FlushCache()
|
||||||
|
log.Println("reload complete")
|
||||||
|
}
|
||||||
|
|
||||||
|
func SignalNotify() {
|
||||||
|
rel := func() bool {
|
||||||
|
go Reloads()
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
flu := func() bool {
|
||||||
|
go FlushCache()
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
signs.Install(syscall.SIGUSR1, rel, "reload")
|
||||||
|
signs.Install(syscall.SIGUSR2, flu, "flush")
|
||||||
|
signs.Wait()
|
||||||
|
}
|
148
app/pkg/cache/cache.go
vendored
148
app/pkg/cache/cache.go
vendored
|
@ -2,85 +2,96 @@ package cache
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"github.com/fthvgb1/wp-go/app/cmd/cachemanager"
|
|
||||||
"github.com/fthvgb1/wp-go/app/pkg/config"
|
"github.com/fthvgb1/wp-go/app/pkg/config"
|
||||||
"github.com/fthvgb1/wp-go/app/pkg/dao"
|
"github.com/fthvgb1/wp-go/app/pkg/dao"
|
||||||
"github.com/fthvgb1/wp-go/app/pkg/logs"
|
"github.com/fthvgb1/wp-go/app/pkg/logs"
|
||||||
"github.com/fthvgb1/wp-go/app/pkg/models"
|
"github.com/fthvgb1/wp-go/app/pkg/models"
|
||||||
"github.com/fthvgb1/wp-go/cache"
|
"github.com/fthvgb1/wp-go/cache/cachemanager"
|
||||||
"github.com/fthvgb1/wp-go/helper/slice"
|
"github.com/fthvgb1/wp-go/cache/reload"
|
||||||
"github.com/fthvgb1/wp-go/safety"
|
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
var postContextCache *cache.MapCache[uint64, dao.PostContext]
|
|
||||||
var categoryAndTagsCaches *cache.MapCache[string, []models.TermsMy]
|
|
||||||
var recentPostsCaches *cache.VarCache[[]models.Posts]
|
|
||||||
var recentCommentsCaches *cache.VarCache[[]models.Comments]
|
|
||||||
var postCommentCaches *cache.MapCache[uint64, []uint64]
|
|
||||||
var postsCache *cache.MapCache[uint64, models.Posts]
|
|
||||||
|
|
||||||
var postMetaCache *cache.MapCache[uint64, map[string]any]
|
|
||||||
|
|
||||||
var monthPostsCache *cache.MapCache[string, []uint64]
|
|
||||||
var postListIdsCache *cache.MapCache[string, dao.PostIds]
|
|
||||||
var searchPostIdsCache *cache.MapCache[string, dao.PostIds]
|
|
||||||
var maxPostIdCache *cache.VarCache[uint64]
|
|
||||||
|
|
||||||
var usersCache *cache.MapCache[uint64, models.Users]
|
|
||||||
var usersNameCache *cache.MapCache[string, models.Users]
|
|
||||||
var commentsCache *cache.MapCache[uint64, models.Comments]
|
|
||||||
|
|
||||||
var feedCache *cache.VarCache[[]string]
|
|
||||||
|
|
||||||
var postFeedCache *cache.MapCache[string, string]
|
|
||||||
|
|
||||||
var commentsFeedCache *cache.VarCache[[]string]
|
|
||||||
|
|
||||||
var newCommentCache *cache.MapCache[string, string]
|
|
||||||
|
|
||||||
var allUsernameCache *cache.VarCache[map[string]struct{}]
|
|
||||||
|
|
||||||
func InitActionsCommonCache() {
|
func InitActionsCommonCache() {
|
||||||
c := config.GetConfig()
|
c := config.GetConfig()
|
||||||
|
|
||||||
searchPostIdsCache = cachemanager.MapCacheBy[string](dao.SearchPostIds, c.CacheTime.SearchPostCacheTime)
|
cachemanager.NewMemoryMapCache(nil, dao.SearchPostIds, c.CacheTime.SearchPostCacheTime, "searchPostIds", func() time.Duration {
|
||||||
|
return config.GetConfig().CacheTime.SearchPostCacheTime
|
||||||
|
})
|
||||||
|
|
||||||
postListIdsCache = cachemanager.MapCacheBy[string](dao.SearchPostIds, c.CacheTime.PostListCacheTime)
|
cachemanager.NewMemoryMapCache(nil, dao.SearchPostIds, c.CacheTime.PostListCacheTime, "listPostIds", func() time.Duration {
|
||||||
|
return config.GetConfig().CacheTime.PostListCacheTime
|
||||||
|
})
|
||||||
|
|
||||||
monthPostsCache = cachemanager.MapCacheBy[string](dao.MonthPost, c.CacheTime.MonthPostCacheTime)
|
cachemanager.NewMemoryMapCache(nil, dao.MonthPost, c.CacheTime.MonthPostCacheTime, "monthPostIds", func() time.Duration {
|
||||||
|
return config.GetConfig().CacheTime.MonthPostCacheTime
|
||||||
|
})
|
||||||
|
|
||||||
postContextCache = cachemanager.MapCacheBy[uint64](dao.GetPostContext, c.CacheTime.ContextPostCacheTime)
|
cachemanager.NewMemoryMapCache(nil, dao.GetPostContext, c.CacheTime.ContextPostCacheTime, "postContext", func() time.Duration {
|
||||||
|
return config.GetConfig().CacheTime.ContextPostCacheTime
|
||||||
|
})
|
||||||
|
|
||||||
postsCache = cachemanager.MapBatchCacheBy(dao.GetPostsByIds, c.CacheTime.PostDataCacheTime)
|
cachemanager.NewMemoryMapCache(dao.GetPostsByIds, nil, c.CacheTime.PostDataCacheTime, "postData", func() time.Duration {
|
||||||
|
return config.GetConfig().CacheTime.PostDataCacheTime
|
||||||
|
})
|
||||||
|
|
||||||
postMetaCache = cachemanager.MapBatchCacheBy(dao.GetPostMetaByPostIds, c.CacheTime.PostDataCacheTime)
|
cachemanager.NewMemoryMapCache(dao.GetPostMetaByPostIds, nil, c.CacheTime.PostDataCacheTime, "postMetaData", func() time.Duration {
|
||||||
|
return config.GetConfig().CacheTime.PostDataCacheTime
|
||||||
|
})
|
||||||
|
|
||||||
categoryAndTagsCaches = cachemanager.MapCacheBy[string](dao.CategoriesAndTags, c.CacheTime.CategoryCacheTime)
|
cachemanager.NewMemoryMapCache(nil, dao.CategoriesAndTags, c.CacheTime.CategoryCacheTime, "categoryAndTagsData", func() time.Duration {
|
||||||
|
return config.GetConfig().CacheTime.CategoryCacheTime
|
||||||
|
})
|
||||||
|
|
||||||
recentPostsCaches = cache.NewVarCache(dao.RecentPosts, c.CacheTime.RecentPostCacheTime)
|
cachemanager.NewVarMemoryCache(dao.RecentPosts, c.CacheTime.RecentPostCacheTime, "recentPosts", func() time.Duration {
|
||||||
|
return config.GetConfig().CacheTime.RecentPostCacheTime
|
||||||
|
})
|
||||||
|
|
||||||
recentCommentsCaches = cache.NewVarCache(dao.RecentComments, c.CacheTime.RecentCommentsCacheTime)
|
cachemanager.NewVarMemoryCache(RecentComment, c.CacheTime.RecentCommentsCacheTime, "recentComments", func() time.Duration {
|
||||||
|
return config.GetConfig().CacheTime.RecentCommentsCacheTime
|
||||||
|
})
|
||||||
|
|
||||||
postCommentCaches = cachemanager.MapCacheBy[uint64](dao.PostComments, c.CacheTime.PostCommentsCacheTime)
|
cachemanager.NewMemoryMapCache(nil, dao.CommentNum, 30*time.Second, "commentNumber", func() time.Duration {
|
||||||
|
return config.GetConfig().CacheTime.CommentsIncreaseUpdateTime
|
||||||
|
})
|
||||||
|
|
||||||
maxPostIdCache = cache.NewVarCache(dao.GetMaxPostId, c.CacheTime.MaxPostIdCacheTime)
|
cachemanager.NewMemoryMapCache(nil, PostTopComments, 30*time.Second, "PostCommentsIds", func() time.Duration {
|
||||||
|
return config.GetConfig().CacheTime.CommentsIncreaseUpdateTime
|
||||||
|
})
|
||||||
|
cachemanager.NewMemoryMapCache(nil, dao.PostTopCommentNum, 30*time.Second, "postTopCommentsNum", func() time.Duration {
|
||||||
|
return config.GetConfig().CacheTime.CommentsIncreaseUpdateTime
|
||||||
|
})
|
||||||
|
|
||||||
usersCache = cachemanager.MapCacheBy[uint64](dao.GetUserById, c.CacheTime.UserInfoCacheTime)
|
cachemanager.NewMemoryMapCache(dao.GetCommentByIds, nil, time.Hour, "postCommentData", func() time.Duration {
|
||||||
|
return config.GetConfig().CacheTime.CommentsCacheTime
|
||||||
|
})
|
||||||
|
|
||||||
usersNameCache = cachemanager.MapCacheBy[string](dao.GetUserByName, c.CacheTime.UserInfoCacheTime)
|
cachemanager.NewMemoryMapCache(dao.CommentChildren, nil, time.Minute, "commentChildren", func() time.Duration {
|
||||||
|
return config.GetConfig().CacheTime.CommentsIncreaseUpdateTime
|
||||||
|
})
|
||||||
|
|
||||||
commentsCache = cachemanager.MapBatchCacheBy(dao.GetCommentByIds, c.CacheTime.CommentsCacheTime)
|
cachemanager.NewVarMemoryCache(dao.GetMaxPostId, c.CacheTime.MaxPostIdCacheTime, "maxPostId", func() time.Duration {
|
||||||
|
return config.GetConfig().CacheTime.MaxPostIdCacheTime
|
||||||
|
})
|
||||||
|
|
||||||
allUsernameCache = cache.NewVarCache(dao.AllUsername, c.CacheTime.UserInfoCacheTime)
|
cachemanager.NewMemoryMapCache(nil, dao.GetUserById, c.CacheTime.UserInfoCacheTime, "userData", func() time.Duration {
|
||||||
|
return config.GetConfig().CacheTime.UserInfoCacheTime
|
||||||
|
})
|
||||||
|
|
||||||
feedCache = cache.NewVarCache(feed, time.Hour)
|
cachemanager.NewMemoryMapCache(nil, dao.GetUserByName, c.CacheTime.UserInfoCacheTime, "usernameToUserData", func() time.Duration {
|
||||||
|
return config.GetConfig().CacheTime.UserInfoCacheTime
|
||||||
|
})
|
||||||
|
|
||||||
postFeedCache = cachemanager.MapCacheBy[string](postFeed, time.Hour)
|
cachemanager.NewVarMemoryCache(dao.AllUsername, c.CacheTime.UserInfoCacheTime, "allUsername", func() time.Duration {
|
||||||
|
return config.GetConfig().CacheTime.UserInfoCacheTime
|
||||||
|
})
|
||||||
|
|
||||||
commentsFeedCache = cache.NewVarCache(commentsFeed, time.Hour)
|
cachemanager.NewVarMemoryCache(SiteFeed, time.Hour, "siteFeed")
|
||||||
|
|
||||||
newCommentCache = cachemanager.MapCacheBy[string, string](nil, 15*time.Minute)
|
cachemanager.NewMemoryMapCache(nil, PostFeed, time.Hour, "postFeed")
|
||||||
|
|
||||||
|
cachemanager.NewVarMemoryCache(CommentsFeed, time.Hour, "commentsFeed")
|
||||||
|
|
||||||
|
cachemanager.NewMemoryMapCache[string, string](nil, nil, 15*time.Minute, "NewComment")
|
||||||
|
|
||||||
InitFeed()
|
InitFeed()
|
||||||
}
|
}
|
||||||
|
@ -91,19 +102,19 @@ type Arch struct {
|
||||||
month time.Month
|
month time.Month
|
||||||
}
|
}
|
||||||
|
|
||||||
var arch = safety.NewVar(Arch{
|
var arch = reload.Vars(Arch{
|
||||||
fn: dao.Archives,
|
fn: dao.Archives,
|
||||||
})
|
}, "archives-year-month-data")
|
||||||
|
|
||||||
func Archives(ctx context.Context) []models.PostArchive {
|
func Archives(ctx context.Context) []models.PostArchive {
|
||||||
a := arch.Load()
|
a := arch.Load()
|
||||||
data := a.data
|
data := a.data
|
||||||
l := len(data)
|
l := len(data)
|
||||||
m := time.Now().Month()
|
m := time.Now().Month()
|
||||||
if l > 0 && a.month != m || l < 1 {
|
if l < 1 || a.month != m {
|
||||||
r, err := a.fn(ctx)
|
r, err := a.fn(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logs.Error(err, "set cache fail")
|
logs.Error(err, "set cache Archives fail")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
a.month = m
|
a.month = m
|
||||||
|
@ -113,30 +124,3 @@ func Archives(ctx context.Context) []models.PostArchive {
|
||||||
}
|
}
|
||||||
return data
|
return data
|
||||||
}
|
}
|
||||||
|
|
||||||
// CategoriesTags categories or tags
|
|
||||||
//
|
|
||||||
// t is constraints.Tag or constraints.Category
|
|
||||||
func CategoriesTags(ctx context.Context, t ...string) []models.TermsMy {
|
|
||||||
tt := ""
|
|
||||||
if len(t) > 0 {
|
|
||||||
tt = t[0]
|
|
||||||
}
|
|
||||||
r, err := categoryAndTagsCaches.GetCache(ctx, tt, time.Second, ctx, tt)
|
|
||||||
logs.IfError(err, "get category fail")
|
|
||||||
return r
|
|
||||||
}
|
|
||||||
func AllCategoryTagsNames(ctx context.Context, t ...string) map[string]struct{} {
|
|
||||||
tt := ""
|
|
||||||
if len(t) > 0 {
|
|
||||||
tt = t[0]
|
|
||||||
}
|
|
||||||
r, err := categoryAndTagsCaches.GetCache(ctx, tt, time.Second, ctx, tt)
|
|
||||||
if err != nil {
|
|
||||||
logs.Error(err, "get category fail")
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return slice.ToMap(r, func(t models.TermsMy) (string, struct{}) {
|
|
||||||
return t.Name, struct{}{}
|
|
||||||
}, true)
|
|
||||||
}
|
|
||||||
|
|
39
app/pkg/cache/categoryandtag.go
vendored
Normal file
39
app/pkg/cache/categoryandtag.go
vendored
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
package cache
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"github.com/fthvgb1/wp-go/app/pkg/logs"
|
||||||
|
"github.com/fthvgb1/wp-go/app/pkg/models"
|
||||||
|
"github.com/fthvgb1/wp-go/cache/cachemanager"
|
||||||
|
"github.com/fthvgb1/wp-go/helper/slice"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// CategoriesTags get all categories or tags
|
||||||
|
//
|
||||||
|
// query func see dao.CategoriesAndTags
|
||||||
|
//
|
||||||
|
// t is constraints.Tag or constraints.Category
|
||||||
|
func CategoriesTags(ctx context.Context, t ...string) []models.TermsMy {
|
||||||
|
tt := ""
|
||||||
|
if len(t) > 0 {
|
||||||
|
tt = t[0]
|
||||||
|
}
|
||||||
|
r, err := cachemanager.GetBy[[]models.TermsMy]("categoryAndTagsData", ctx, tt, time.Second)
|
||||||
|
logs.IfError(err, "get category fail")
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
func AllCategoryTagsNames(ctx context.Context, t ...string) map[string]struct{} {
|
||||||
|
tt := ""
|
||||||
|
if len(t) > 0 {
|
||||||
|
tt = t[0]
|
||||||
|
}
|
||||||
|
r, err := cachemanager.GetBy[[]models.TermsMy]("categoryAndTagsData", ctx, tt, time.Second)
|
||||||
|
if err != nil {
|
||||||
|
logs.Error(err, "get category fail")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return slice.ToMap(r, func(t models.TermsMy) (string, struct{}) {
|
||||||
|
return t.Name, struct{}{}
|
||||||
|
}, true)
|
||||||
|
}
|
104
app/pkg/cache/comments.go
vendored
104
app/pkg/cache/comments.go
vendored
|
@ -2,16 +2,23 @@ package cache
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"github.com/fthvgb1/wp-go/app/pkg/dao"
|
||||||
"github.com/fthvgb1/wp-go/app/pkg/logs"
|
"github.com/fthvgb1/wp-go/app/pkg/logs"
|
||||||
"github.com/fthvgb1/wp-go/app/pkg/models"
|
"github.com/fthvgb1/wp-go/app/pkg/models"
|
||||||
|
"github.com/fthvgb1/wp-go/app/wpconfig"
|
||||||
"github.com/fthvgb1/wp-go/cache"
|
"github.com/fthvgb1/wp-go/cache"
|
||||||
|
"github.com/fthvgb1/wp-go/cache/cachemanager"
|
||||||
|
"github.com/fthvgb1/wp-go/helper"
|
||||||
"github.com/fthvgb1/wp-go/helper/number"
|
"github.com/fthvgb1/wp-go/helper/number"
|
||||||
|
str "github.com/fthvgb1/wp-go/helper/strings"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// RecentComments query func see RecentComment
|
||||||
func RecentComments(ctx context.Context, n int) (r []models.Comments) {
|
func RecentComments(ctx context.Context, n int) (r []models.Comments) {
|
||||||
nn := number.Max(n, 10)
|
nn := number.Max(n, 10)
|
||||||
r, err := recentCommentsCaches.GetCache(ctx, time.Second, ctx, nn)
|
r, err := cachemanager.GetVarVal[[]models.Comments]("recentComments", ctx, time.Second, ctx, nn)
|
||||||
if len(r) > n {
|
if len(r) > n {
|
||||||
r = r[0:n]
|
r = r[0:n]
|
||||||
}
|
}
|
||||||
|
@ -19,22 +26,99 @@ func RecentComments(ctx context.Context, n int) (r []models.Comments) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func PostComments(ctx context.Context, Id uint64) ([]models.Comments, error) {
|
// PostTopLevelCommentIds query func see PostTopComments
|
||||||
ids, err := postCommentCaches.GetCache(ctx, Id, time.Second, ctx, Id)
|
func PostTopLevelCommentIds(ctx context.Context, postId uint64, page, limit, total int, order string, a ...any) ([]uint64, error) {
|
||||||
if err != nil {
|
var key string
|
||||||
return nil, err
|
if len(a) > 0 {
|
||||||
|
key = helper.ParseArgs("", a...)
|
||||||
}
|
}
|
||||||
return GetCommentByIds(ctx, ids)
|
if key == "" {
|
||||||
|
key = fmt.Sprintf("%d-%d-%d-%d-%s", postId, page, limit, total, order)
|
||||||
|
}
|
||||||
|
return cachemanager.GetBy[[]uint64]("PostCommentsIds", ctx,
|
||||||
|
key, time.Second, postId, page, limit, 0, order)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetCommentById query func see dao.GetCommentByIds
|
||||||
func GetCommentById(ctx context.Context, id uint64) (models.Comments, error) {
|
func GetCommentById(ctx context.Context, id uint64) (models.Comments, error) {
|
||||||
return commentsCache.GetCache(ctx, id, time.Second, ctx, id)
|
return cachemanager.GetBy[models.Comments]("postCommentData", ctx, id, time.Second)
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetCommentByIds(ctx context.Context, ids []uint64) ([]models.Comments, error) {
|
// GetCommentDataByIds query func see dao.GetCommentByIds
|
||||||
return commentsCache.GetCacheBatch(ctx, ids, time.Second, ctx, ids)
|
func GetCommentDataByIds(ctx context.Context, ids []uint64) ([]models.Comments, error) {
|
||||||
|
return cachemanager.GetBatchBy[models.Comments]("postCommentData", ctx, ids, time.Second)
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewCommentCache() *cache.MapCache[string, string] {
|
func NewCommentCache() *cache.MapCache[string, string] {
|
||||||
return newCommentCache
|
r, _ := cachemanager.GetMapCache[string, string]("NewComment")
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
func PostTopComments(ctx context.Context, _ string, a ...any) ([]uint64, error) {
|
||||||
|
postId := a[0].(uint64)
|
||||||
|
page := a[1].(int)
|
||||||
|
limit := a[2].(int)
|
||||||
|
total := a[3].(int)
|
||||||
|
order := helper.ParseArgs("", a...)
|
||||||
|
if order == "" {
|
||||||
|
order = wpconfig.GetOption("comment_order")
|
||||||
|
}
|
||||||
|
v, _, err := dao.PostCommentsIds(ctx, postId, page, limit, total, order)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return v, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func RecentComment(ctx context.Context, a ...any) (r []models.Comments, err error) {
|
||||||
|
r, err = dao.RecentComments(ctx, a...)
|
||||||
|
if err != nil {
|
||||||
|
return r, err
|
||||||
|
}
|
||||||
|
for i, comment := range r {
|
||||||
|
r[i].CommentAuthorUrl, err = GetCommentUrl(ctx, comment.CommentId, comment.CommentPostId)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetCommentUrl(ctx context.Context, commentId, postId uint64) (string, error) {
|
||||||
|
if wpconfig.GetOption("page_comments") != "1" {
|
||||||
|
return fmt.Sprintf("/p/%d#comment-%d", postId, commentId), nil
|
||||||
|
}
|
||||||
|
commentsPerPage := str.ToInteger(wpconfig.GetOption("comments_per_page"), 5)
|
||||||
|
topCommentId, err := AncestorCommentId(ctx, commentId)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
totalNum, err := cachemanager.GetBy[int]("postTopCommentsNum", ctx, postId, time.Second)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
if totalNum <= commentsPerPage {
|
||||||
|
return fmt.Sprintf("/p/%d#comment-%d", postId, commentId), nil
|
||||||
|
}
|
||||||
|
num, err := dao.PreviousCommentNum(ctx, topCommentId, postId)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
order := wpconfig.GetOption("comment_order")
|
||||||
|
page := number.DivideCeil(num+1, commentsPerPage)
|
||||||
|
if order == "desc" {
|
||||||
|
page = number.DivideCeil(totalNum-num, commentsPerPage)
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("/p/%d/comment-page-%d/#comment-%d", postId, page, commentId), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func AncestorCommentId(ctx context.Context, commentId uint64) (uint64, error) {
|
||||||
|
comment, err := GetCommentById(ctx, commentId)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
if comment.CommentParent == 0 {
|
||||||
|
return comment.CommentId, nil
|
||||||
|
}
|
||||||
|
return AncestorCommentId(ctx, comment.CommentParent)
|
||||||
}
|
}
|
||||||
|
|
55
app/pkg/cache/feed.go
vendored
55
app/pkg/cache/feed.go
vendored
|
@ -1,6 +1,8 @@
|
||||||
package cache
|
package cache
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/fthvgb1/wp-go/app/pkg/logs"
|
"github.com/fthvgb1/wp-go/app/pkg/logs"
|
||||||
"github.com/fthvgb1/wp-go/app/pkg/models"
|
"github.com/fthvgb1/wp-go/app/pkg/models"
|
||||||
|
@ -8,11 +10,11 @@ import (
|
||||||
"github.com/fthvgb1/wp-go/app/plugins/wpposts"
|
"github.com/fthvgb1/wp-go/app/plugins/wpposts"
|
||||||
"github.com/fthvgb1/wp-go/app/wpconfig"
|
"github.com/fthvgb1/wp-go/app/wpconfig"
|
||||||
"github.com/fthvgb1/wp-go/cache"
|
"github.com/fthvgb1/wp-go/cache"
|
||||||
|
"github.com/fthvgb1/wp-go/cache/cachemanager"
|
||||||
"github.com/fthvgb1/wp-go/helper/slice"
|
"github.com/fthvgb1/wp-go/helper/slice"
|
||||||
str "github.com/fthvgb1/wp-go/helper/strings"
|
str "github.com/fthvgb1/wp-go/helper/strings"
|
||||||
"github.com/fthvgb1/wp-go/plugin/digest"
|
"github.com/fthvgb1/wp-go/plugin/digest"
|
||||||
"github.com/fthvgb1/wp-go/rss2"
|
"github.com/fthvgb1/wp-go/rss2"
|
||||||
"github.com/gin-gonic/gin"
|
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
@ -33,20 +35,25 @@ func InitFeed() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CommentsFeedCache query func see CommentsFeed
|
||||||
func CommentsFeedCache() *cache.VarCache[[]string] {
|
func CommentsFeedCache() *cache.VarCache[[]string] {
|
||||||
return commentsFeedCache
|
r, _ := cachemanager.GetVarCache[[]string]("commentsFeed")
|
||||||
|
return r
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FeedCache query func see SiteFeed
|
||||||
func FeedCache() *cache.VarCache[[]string] {
|
func FeedCache() *cache.VarCache[[]string] {
|
||||||
return feedCache
|
r, _ := cachemanager.GetVarCache[[]string]("siteFeed")
|
||||||
|
return r
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// PostFeedCache query func see PostFeed
|
||||||
func PostFeedCache() *cache.MapCache[string, string] {
|
func PostFeedCache() *cache.MapCache[string, string] {
|
||||||
return postFeedCache
|
r, _ := cachemanager.GetMapCache[string, string]("postFeed")
|
||||||
|
return r
|
||||||
}
|
}
|
||||||
|
|
||||||
func feed(arg ...any) (xml []string, err error) {
|
func SiteFeed(c context.Context, _ ...any) (xml []string, err error) {
|
||||||
c := arg[0].(*gin.Context)
|
|
||||||
r := RecentPosts(c, 10)
|
r := RecentPosts(c, 10)
|
||||||
ids := slice.Map(r, func(t models.Posts) uint64 {
|
ids := slice.Map(r, func(t models.Posts) uint64 {
|
||||||
return t.Id
|
return t.Id
|
||||||
|
@ -92,9 +99,7 @@ func feed(arg ...any) (xml []string, err error) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func postFeed(arg ...any) (x string, err error) {
|
func PostFeed(c context.Context, id string, _ ...any) (x string, err error) {
|
||||||
c := arg[0].(*gin.Context)
|
|
||||||
id := arg[1].(string)
|
|
||||||
ID := str.ToInteger[uint64](id, 0)
|
ID := str.ToInteger[uint64](id, 0)
|
||||||
maxId, err := GetMaxPostId(c)
|
maxId, err := GetMaxPostId(c)
|
||||||
logs.IfError(err, "get max post id")
|
logs.IfError(err, "get max post id")
|
||||||
|
@ -105,7 +110,12 @@ func postFeed(arg ...any) (x string, err error) {
|
||||||
if post.Id == 0 || err != nil {
|
if post.Id == 0 || err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
comments, err := PostComments(c, post.Id)
|
limit := str.ToInteger(wpconfig.GetOption("comments_per_page"), 10)
|
||||||
|
ids, err := PostTopLevelCommentIds(c, ID, 1, limit, 0, "desc", "latest-comment")
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
comments, err := GetCommentDataByIds(c, ids)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -121,10 +131,14 @@ func postFeed(arg ...any) (x string, err error) {
|
||||||
wpposts.PasswdProjectContent(&post)
|
wpposts.PasswdProjectContent(&post)
|
||||||
if len(comments) > 0 {
|
if len(comments) > 0 {
|
||||||
t := comments[len(comments)-1]
|
t := comments[len(comments)-1]
|
||||||
|
u, err := GetCommentUrl(c, t.CommentId, t.CommentPostId)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
rs.Items = []rss2.Item{
|
rs.Items = []rss2.Item{
|
||||||
{
|
{
|
||||||
Title: fmt.Sprintf("评价者:%s", t.CommentAuthor),
|
Title: fmt.Sprintf("评价者:%s", t.CommentAuthor),
|
||||||
Link: fmt.Sprintf("%s/p/%d#comment-%d", site, post.Id, t.CommentId),
|
Link: fmt.Sprintf("%s%s", site, u),
|
||||||
Creator: t.CommentAuthor,
|
Creator: t.CommentAuthor,
|
||||||
PubDate: t.CommentDateGmt.Format(timeFormat),
|
PubDate: t.CommentDateGmt.Format(timeFormat),
|
||||||
Guid: fmt.Sprintf("%s#comment-%d", post.Guid, t.CommentId),
|
Guid: fmt.Sprintf("%s#comment-%d", post.Guid, t.CommentId),
|
||||||
|
@ -135,9 +149,14 @@ func postFeed(arg ...any) (x string, err error) {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
rs.Items = slice.Map(comments, func(t models.Comments) rss2.Item {
|
rs.Items = slice.Map(comments, func(t models.Comments) rss2.Item {
|
||||||
|
u, er := GetCommentUrl(c, t.CommentId, t.CommentPostId)
|
||||||
|
if er != nil {
|
||||||
|
err = errors.Join(err, er)
|
||||||
|
return rss2.Item{}
|
||||||
|
}
|
||||||
return rss2.Item{
|
return rss2.Item{
|
||||||
Title: fmt.Sprintf("评价者:%s", t.CommentAuthor),
|
Title: fmt.Sprintf("评价者:%s", t.CommentAuthor),
|
||||||
Link: fmt.Sprintf("%s/p/%d#comment-%d", site, post.Id, t.CommentId),
|
Link: fmt.Sprintf("%s%s", site, u),
|
||||||
Creator: t.CommentAuthor,
|
Creator: t.CommentAuthor,
|
||||||
PubDate: t.CommentDateGmt.Format(timeFormat),
|
PubDate: t.CommentDateGmt.Format(timeFormat),
|
||||||
Guid: fmt.Sprintf("%s#comment-%d", post.Guid, t.CommentId),
|
Guid: fmt.Sprintf("%s#comment-%d", post.Guid, t.CommentId),
|
||||||
|
@ -150,15 +169,14 @@ func postFeed(arg ...any) (x string, err error) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func commentsFeed(args ...any) (r []string, err error) {
|
func CommentsFeed(c context.Context, _ ...any) (r []string, err error) {
|
||||||
c := args[0].(*gin.Context)
|
|
||||||
commens := RecentComments(c, 10)
|
commens := RecentComments(c, 10)
|
||||||
rs := templateRss
|
rs := templateRss
|
||||||
rs.Title = fmt.Sprintf("\"%s\"的评论", wpconfig.GetOption("blogname"))
|
rs.Title = fmt.Sprintf("\"%s\"的评论", wpconfig.GetOption("blogname"))
|
||||||
rs.LastBuildDate = time.Now().Format(timeFormat)
|
rs.LastBuildDate = time.Now().Format(timeFormat)
|
||||||
site := wpconfig.GetOption("siteurl")
|
site := wpconfig.GetOption("siteurl")
|
||||||
rs.AtomLink = fmt.Sprintf("%s/comments/feed", site)
|
rs.AtomLink = fmt.Sprintf("%s/comments/feed", site)
|
||||||
com, err := GetCommentByIds(c, slice.Map(commens, func(t models.Comments) uint64 {
|
com, err := GetCommentDataByIds(c, slice.Map(commens, func(t models.Comments) uint64 {
|
||||||
return t.CommentId
|
return t.CommentId
|
||||||
}))
|
}))
|
||||||
if nil != err {
|
if nil != err {
|
||||||
|
@ -175,9 +193,14 @@ func commentsFeed(args ...any) (r []string, err error) {
|
||||||
} else {
|
} else {
|
||||||
content = digest.StripTags(t.CommentContent, "")
|
content = digest.StripTags(t.CommentContent, "")
|
||||||
}
|
}
|
||||||
|
u, er := GetCommentUrl(c, t.CommentId, t.CommentPostId)
|
||||||
|
if er != nil {
|
||||||
|
errors.Join(err, er)
|
||||||
|
}
|
||||||
|
u = str.Join(site, u)
|
||||||
return rss2.Item{
|
return rss2.Item{
|
||||||
Title: fmt.Sprintf("%s对《%s》的评论", t.CommentAuthor, post.PostTitle),
|
Title: fmt.Sprintf("%s对《%s》的评论", t.CommentAuthor, post.PostTitle),
|
||||||
Link: fmt.Sprintf("%s/p/%d#comment-%d", site, post.Id, t.CommentId),
|
Link: u,
|
||||||
Creator: t.CommentAuthor,
|
Creator: t.CommentAuthor,
|
||||||
Description: desc,
|
Description: desc,
|
||||||
PubDate: t.CommentDateGmt.Format(timeFormat),
|
PubDate: t.CommentDateGmt.Format(timeFormat),
|
||||||
|
|
14
app/pkg/cache/postmeta.go
vendored
14
app/pkg/cache/postmeta.go
vendored
|
@ -2,14 +2,16 @@ package cache
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"github.com/fthvgb1/wp-go/cache/cachemanager"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
func GetPostMetaByPostIds(ctx context.Context, ids []uint64) (r []map[string]any, err error) {
|
// GetPostMetaByPostIds query func see dao.GetPostMetaByPostIds
|
||||||
r, err = postMetaCache.GetCacheBatch(ctx, ids, time.Second, ctx, ids)
|
func GetPostMetaByPostIds(ctx context.Context, ids []uint64) ([]map[string]any, error) {
|
||||||
return
|
return cachemanager.GetBatchBy[map[string]any]("postMetaData", ctx, ids, time.Second)
|
||||||
}
|
}
|
||||||
func GetPostMetaByPostId(ctx context.Context, id uint64) (r map[string]any, err error) {
|
|
||||||
r, err = postMetaCache.GetCache(ctx, id, time.Second, ctx, id)
|
// GetPostMetaByPostId query func see dao.GetPostMetaByPostIds
|
||||||
return
|
func GetPostMetaByPostId(ctx context.Context, id uint64) (map[string]any, error) {
|
||||||
|
return cachemanager.GetBy[map[string]any]("postMetaData", ctx, id, time.Second)
|
||||||
}
|
}
|
||||||
|
|
29
app/pkg/cache/posts.go
vendored
29
app/pkg/cache/posts.go
vendored
|
@ -3,26 +3,30 @@ package cache
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"github.com/fthvgb1/wp-go/app/pkg/dao"
|
||||||
"github.com/fthvgb1/wp-go/app/pkg/logs"
|
"github.com/fthvgb1/wp-go/app/pkg/logs"
|
||||||
"github.com/fthvgb1/wp-go/app/pkg/models"
|
"github.com/fthvgb1/wp-go/app/pkg/models"
|
||||||
"github.com/fthvgb1/wp-go/app/wpconfig"
|
"github.com/fthvgb1/wp-go/app/wpconfig"
|
||||||
|
"github.com/fthvgb1/wp-go/cache/cachemanager"
|
||||||
"github.com/fthvgb1/wp-go/helper/number"
|
"github.com/fthvgb1/wp-go/helper/number"
|
||||||
"github.com/fthvgb1/wp-go/helper/slice"
|
"github.com/fthvgb1/wp-go/helper/slice"
|
||||||
str "github.com/fthvgb1/wp-go/helper/strings"
|
str "github.com/fthvgb1/wp-go/helper/strings"
|
||||||
"github.com/gin-gonic/gin"
|
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// GetPostById query func see dao.GetPostsByIds
|
||||||
func GetPostById(ctx context.Context, id uint64) (models.Posts, error) {
|
func GetPostById(ctx context.Context, id uint64) (models.Posts, error) {
|
||||||
return postsCache.GetCache(ctx, id, time.Second, ctx, id)
|
return cachemanager.GetBy[models.Posts]("postData", ctx, id, time.Second)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetPostsByIds query func see dao.GetPostsByIds
|
||||||
func GetPostsByIds(ctx context.Context, ids []uint64) ([]models.Posts, error) {
|
func GetPostsByIds(ctx context.Context, ids []uint64) ([]models.Posts, error) {
|
||||||
return postsCache.GetCacheBatch(ctx, ids, time.Second, ctx, ids)
|
return cachemanager.GetBatchBy[models.Posts]("postData", ctx, ids, time.Second)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SearchPost query func see dao.SearchPostIds
|
||||||
func SearchPost(ctx context.Context, key string, args ...any) (r []models.Posts, total int, err error) {
|
func SearchPost(ctx context.Context, key string, args ...any) (r []models.Posts, total int, err error) {
|
||||||
ids, err := searchPostIdsCache.GetCache(ctx, key, time.Second, args...)
|
ids, err := cachemanager.GetBy[dao.PostIds]("searchPostIds", ctx, key, time.Second, args...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -31,8 +35,9 @@ func SearchPost(ctx context.Context, key string, args ...any) (r []models.Posts,
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// PostLists query func see dao.SearchPostIds
|
||||||
func PostLists(ctx context.Context, key string, args ...any) (r []models.Posts, total int, err error) {
|
func PostLists(ctx context.Context, key string, args ...any) (r []models.Posts, total int, err error) {
|
||||||
ids, err := postListIdsCache.GetCache(ctx, key, time.Second, args...)
|
ids, err := cachemanager.GetBy[dao.PostIds]("listPostIds", ctx, key, time.Second, args...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -41,15 +46,17 @@ func PostLists(ctx context.Context, key string, args ...any) (r []models.Posts,
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetMaxPostId(ctx *gin.Context) (uint64, error) {
|
// GetMaxPostId query func see dao.GetMaxPostId
|
||||||
return maxPostIdCache.GetCache(ctx, time.Second, ctx)
|
func GetMaxPostId(ctx context.Context) (uint64, error) {
|
||||||
|
return cachemanager.GetVarVal[uint64]("maxPostId", ctx, time.Second)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RecentPosts query func see dao.RecentPosts
|
||||||
func RecentPosts(ctx context.Context, n int) (r []models.Posts) {
|
func RecentPosts(ctx context.Context, n int) (r []models.Posts) {
|
||||||
nn := n
|
nn := n
|
||||||
feedNum := str.ToInteger(wpconfig.GetOption("posts_per_rss"), 10)
|
feedNum := str.ToInteger(wpconfig.GetOption("posts_per_rss"), 10)
|
||||||
nn = number.Max(n, feedNum)
|
nn = number.Max(n, feedNum)
|
||||||
r, err := recentPostsCaches.GetCache(ctx, time.Second, ctx, nn)
|
r, err := cachemanager.GetVarVal[[]models.Posts]("recentPosts", ctx, time.Second, nn)
|
||||||
if n < len(r) {
|
if n < len(r) {
|
||||||
r = r[:n]
|
r = r[:n]
|
||||||
}
|
}
|
||||||
|
@ -57,8 +64,9 @@ func RecentPosts(ctx context.Context, n int) (r []models.Posts) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetContextPost query func see dao.GetPostContext
|
||||||
func GetContextPost(ctx context.Context, id uint64, date time.Time) (prev, next models.Posts, err error) {
|
func GetContextPost(ctx context.Context, id uint64, date time.Time) (prev, next models.Posts, err error) {
|
||||||
postCtx, err := postContextCache.GetCache(ctx, id, time.Second, ctx, date)
|
postCtx, err := cachemanager.GetBy[dao.PostContext]("postContext", ctx, id, time.Second, date)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return models.Posts{}, models.Posts{}, err
|
return models.Posts{}, models.Posts{}, err
|
||||||
}
|
}
|
||||||
|
@ -67,8 +75,9 @@ func GetContextPost(ctx context.Context, id uint64, date time.Time) (prev, next
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetMonthPostIds query func see dao.MonthPost
|
||||||
func GetMonthPostIds(ctx context.Context, year, month string, page, limit int, order string) (r []models.Posts, total int, err error) {
|
func GetMonthPostIds(ctx context.Context, year, month string, page, limit int, order string) (r []models.Posts, total int, err error) {
|
||||||
res, err := monthPostsCache.GetCache(ctx, fmt.Sprintf("%s%s", year, month), time.Second, ctx, year, month)
|
res, err := cachemanager.GetBy[[]uint64]("monthPostIds", ctx, fmt.Sprintf("%s%s", year, month), time.Second, year, month)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
20
app/pkg/cache/users.go
vendored
20
app/pkg/cache/users.go
vendored
|
@ -4,27 +4,23 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"github.com/fthvgb1/wp-go/app/pkg/logs"
|
"github.com/fthvgb1/wp-go/app/pkg/logs"
|
||||||
"github.com/fthvgb1/wp-go/app/pkg/models"
|
"github.com/fthvgb1/wp-go/app/pkg/models"
|
||||||
"github.com/fthvgb1/wp-go/model"
|
"github.com/fthvgb1/wp-go/cache/cachemanager"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
func getUserById(a ...any) (r models.Users, err error) {
|
// GetUserByName query func see dao.GetUserByName
|
||||||
ctx := a[0].(context.Context)
|
|
||||||
uid := a[1].(uint64)
|
|
||||||
r, err = model.FindOneById[models.Users](ctx, uid)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetUserByName(ctx context.Context, username string) (models.Users, error) {
|
func GetUserByName(ctx context.Context, username string) (models.Users, error) {
|
||||||
return usersNameCache.GetCache(ctx, username, time.Second, ctx, username)
|
return cachemanager.GetBy[models.Users]("usernameToUserData", ctx, username, time.Second)
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetAllUsername(ctx context.Context) (map[string]struct{}, error) {
|
// GetAllUsername query func see dao.AllUsername
|
||||||
return allUsernameCache.GetCache(ctx, time.Second, ctx)
|
func GetAllUsername(ctx context.Context) (map[string]uint64, error) {
|
||||||
|
return cachemanager.GetVarVal[map[string]uint64]("allUsername", ctx, time.Second)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetUserById query func see dao.GetUserById
|
||||||
func GetUserById(ctx context.Context, uid uint64) models.Users {
|
func GetUserById(ctx context.Context, uid uint64) models.Users {
|
||||||
r, err := usersCache.GetCache(ctx, uid, time.Second, ctx, uid)
|
r, err := cachemanager.GetBy[models.Users]("userData", ctx, uid, time.Second)
|
||||||
logs.IfError(err, "get user", uid)
|
logs.IfError(err, "get user", uid)
|
||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
|
|
|
@ -63,6 +63,7 @@ type CacheTime struct {
|
||||||
UserInfoCacheTime time.Duration `yaml:"userInfoCacheTime" json:"userInfoCacheTime,omitempty"`
|
UserInfoCacheTime time.Duration `yaml:"userInfoCacheTime" json:"userInfoCacheTime,omitempty"`
|
||||||
CommentsCacheTime time.Duration `yaml:"commentsCacheTime" json:"commentsCacheTime,omitempty"`
|
CommentsCacheTime time.Duration `yaml:"commentsCacheTime" json:"commentsCacheTime,omitempty"`
|
||||||
SleepTime []time.Duration `yaml:"sleepTime" json:"sleepTime,omitempty"`
|
SleepTime []time.Duration `yaml:"sleepTime" json:"sleepTime,omitempty"`
|
||||||
|
CommentsIncreaseUpdateTime time.Duration `yaml:"commentsIncreaseUpdateTime" json:"commentsIncreaseUpdateTime"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type Ssl struct {
|
type Ssl struct {
|
||||||
|
@ -84,6 +85,14 @@ type Mysql struct {
|
||||||
Pool Pool `yaml:"pool" json:"pool"`
|
Pool Pool `yaml:"pool" json:"pool"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func GetCustomizedConfig[T any]() (T, error) {
|
||||||
|
var r T
|
||||||
|
err := yaml.Unmarshal(fileData.Load(), &r)
|
||||||
|
return r, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var fileData = safety.NewVar([]byte{})
|
||||||
|
|
||||||
func InitConfig(conf string) error {
|
func InitConfig(conf string) error {
|
||||||
if conf == "" {
|
if conf == "" {
|
||||||
conf = "config.yaml"
|
conf = "config.yaml"
|
||||||
|
@ -95,6 +104,7 @@ func InitConfig(conf string) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
defer get.Body.Close()
|
||||||
file, err = io.ReadAll(get.Body)
|
file, err = io.ReadAll(get.Body)
|
||||||
} else {
|
} else {
|
||||||
file, err = os.ReadFile(conf)
|
file, err = os.ReadFile(conf)
|
||||||
|
@ -102,6 +112,7 @@ func InitConfig(conf string) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
fileData.Store(file)
|
||||||
var c Config
|
var c Config
|
||||||
err = yaml.Unmarshal(file, &c)
|
err = yaml.Unmarshal(file, &c)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -2,17 +2,21 @@ package dao
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"database/sql"
|
||||||
|
"errors"
|
||||||
"github.com/fthvgb1/wp-go/app/pkg/models"
|
"github.com/fthvgb1/wp-go/app/pkg/models"
|
||||||
|
"github.com/fthvgb1/wp-go/app/wpconfig"
|
||||||
|
"github.com/fthvgb1/wp-go/helper"
|
||||||
"github.com/fthvgb1/wp-go/helper/number"
|
"github.com/fthvgb1/wp-go/helper/number"
|
||||||
"github.com/fthvgb1/wp-go/helper/slice"
|
"github.com/fthvgb1/wp-go/helper/slice"
|
||||||
|
str "github.com/fthvgb1/wp-go/helper/strings"
|
||||||
"github.com/fthvgb1/wp-go/model"
|
"github.com/fthvgb1/wp-go/model"
|
||||||
)
|
)
|
||||||
|
|
||||||
// RecentComments
|
// RecentComments
|
||||||
// param context.Context
|
// param context.Context
|
||||||
func RecentComments(a ...any) (r []models.Comments, err error) {
|
func RecentComments(ctx context.Context, a ...any) (r []models.Comments, err error) {
|
||||||
ctx := a[0].(context.Context)
|
n := helper.ParseArgs(10, a...)
|
||||||
n := a[1].(int)
|
|
||||||
return model.Finds[models.Comments](ctx, model.Conditions(
|
return model.Finds[models.Comments](ctx, model.Conditions(
|
||||||
model.Where(model.SqlBuilder{
|
model.Where(model.SqlBuilder{
|
||||||
{"comment_approved", "1"},
|
{"comment_approved", "1"},
|
||||||
|
@ -28,10 +32,8 @@ func RecentComments(a ...any) (r []models.Comments, err error) {
|
||||||
// PostComments
|
// PostComments
|
||||||
// param1 context.Context
|
// param1 context.Context
|
||||||
// param2 postId
|
// param2 postId
|
||||||
func PostComments(args ...any) ([]uint64, error) {
|
func PostComments(ctx context.Context, postId uint64, _ ...any) ([]uint64, error) {
|
||||||
ctx := args[0].(context.Context)
|
r, err := model.ChunkFind[models.Comments](ctx, 300, model.Conditions(
|
||||||
postId := args[1].(uint64)
|
|
||||||
r, err := model.Finds[models.Comments](ctx, model.Conditions(
|
|
||||||
model.Where(model.SqlBuilder{
|
model.Where(model.SqlBuilder{
|
||||||
{"comment_approved", "1"},
|
{"comment_approved", "1"},
|
||||||
{"comment_post_ID", "=", number.IntToString(postId), "int"},
|
{"comment_post_ID", "=", number.IntToString(postId), "int"},
|
||||||
|
@ -50,17 +52,132 @@ func PostComments(args ...any) ([]uint64, error) {
|
||||||
}), err
|
}), err
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetCommentByIds(args ...any) (map[uint64]models.Comments, error) {
|
func GetCommentByIds(ctx context.Context, ids []uint64, _ ...any) (map[uint64]models.Comments, error) {
|
||||||
ctx := args[0].(context.Context)
|
if len(ids) < 1 {
|
||||||
ids := args[1].([]uint64)
|
return nil, nil
|
||||||
|
}
|
||||||
m := make(map[uint64]models.Comments)
|
m := make(map[uint64]models.Comments)
|
||||||
r, err := model.SimpleFind[models.Comments](ctx, model.SqlBuilder{
|
off := 0
|
||||||
|
for {
|
||||||
|
id := slice.Slice(ids, off, 500)
|
||||||
|
if len(id) < 1 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
r, err := model.Finds[models.Comments](ctx, model.Conditions(
|
||||||
|
model.Where(model.SqlBuilder{
|
||||||
{"comment_ID", "in", ""}, {"comment_approved", "1"},
|
{"comment_ID", "in", ""}, {"comment_approved", "1"},
|
||||||
}, "*", slice.ToAnySlice(ids))
|
}),
|
||||||
|
model.Fields("*"),
|
||||||
|
model.In(slice.ToAnySlice(id)),
|
||||||
|
))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return m, err
|
return m, err
|
||||||
}
|
}
|
||||||
return slice.SimpleToMap(r, func(t models.Comments) uint64 {
|
for _, comments := range r {
|
||||||
return t.CommentId
|
m[comments.CommentId] = comments
|
||||||
}), err
|
}
|
||||||
|
off += 500
|
||||||
|
}
|
||||||
|
|
||||||
|
return m, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func CommentNum(ctx context.Context, postId uint64, _ ...any) (int, error) {
|
||||||
|
n, err := model.GetField[models.Posts](ctx, "comment_count", model.Conditions(
|
||||||
|
model.Where(model.SqlBuilder{{"ID", "=", number.IntToString(postId), "int"}})))
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
return str.ToInteger(n, 0), err
|
||||||
|
}
|
||||||
|
|
||||||
|
func PostTopCommentNum(ctx context.Context, postId uint64, _ ...any) (int, error) {
|
||||||
|
v, err := model.GetField[models.Comments](ctx, "count(*) num", model.Conditions(
|
||||||
|
model.Where(postTopCommentNumWhere(postId)),
|
||||||
|
))
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
return str.ToInteger(v, 0), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func postTopCommentNumWhere(postId uint64) model.SqlBuilder {
|
||||||
|
threadComments := wpconfig.GetOption("thread_comments")
|
||||||
|
pageComments := wpconfig.GetOption("page_comments")
|
||||||
|
where := model.SqlBuilder{
|
||||||
|
{"comment_approved", "1"},
|
||||||
|
{"comment_post_ID", "=", number.IntToString(postId), "int"},
|
||||||
|
}
|
||||||
|
if pageComments != "1" || threadComments == "1" || "1" == wpconfig.GetOption("thread_comments_depth") {
|
||||||
|
where = append(where, []string{"comment_parent", "0"})
|
||||||
|
}
|
||||||
|
return where
|
||||||
|
}
|
||||||
|
|
||||||
|
func PostCommentsIds(ctx context.Context, postId uint64, page, limit, totalRaw int, order string) ([]uint64, int, error) {
|
||||||
|
condition := model.Conditions(
|
||||||
|
model.Where(postTopCommentNumWhere(postId)),
|
||||||
|
model.TotalRaw(totalRaw),
|
||||||
|
model.Fields("comment_ID"),
|
||||||
|
model.Order(model.SqlBuilder{
|
||||||
|
{"comment_date_gmt", order},
|
||||||
|
{"comment_ID", "asc"},
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
var r []models.Comments
|
||||||
|
var total int
|
||||||
|
var err error
|
||||||
|
if limit < 1 {
|
||||||
|
r, err = model.ChunkFind[models.Comments](ctx, 300, condition)
|
||||||
|
total = len(r)
|
||||||
|
} else {
|
||||||
|
r, total, err = model.Pagination[models.Comments](ctx, condition, page, limit)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err != nil && errors.Is(err, sql.ErrNoRows) {
|
||||||
|
err = nil
|
||||||
|
}
|
||||||
|
return slice.Map(r, func(t models.Comments) uint64 {
|
||||||
|
return t.CommentId
|
||||||
|
}), total, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func CommentChildren(ctx context.Context, commentIds []uint64, _ ...any) (r map[uint64][]uint64, err error) {
|
||||||
|
rr, err := model.Finds[models.Comments](ctx, model.Conditions(
|
||||||
|
model.Where(model.SqlBuilder{
|
||||||
|
{"comment_parent", "in", ""},
|
||||||
|
{"comment_approved", "1"},
|
||||||
|
}),
|
||||||
|
model.In(slice.ToAnySlice(commentIds)),
|
||||||
|
model.Fields("comment_ID,comment_parent"),
|
||||||
|
))
|
||||||
|
if err != nil {
|
||||||
|
if errors.Is(err, sql.ErrNoRows) {
|
||||||
|
err = nil
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
rrr := slice.GroupBy(rr, func(v models.Comments) (uint64, uint64) {
|
||||||
|
return v.CommentParent, v.CommentId
|
||||||
|
})
|
||||||
|
r = make(map[uint64][]uint64)
|
||||||
|
for _, id := range commentIds {
|
||||||
|
r[id] = rrr[id]
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func PreviousCommentNum(ctx context.Context, commentId, postId uint64) (int, error) {
|
||||||
|
v, err := model.GetField[models.Comments](ctx, "count(*)", model.Conditions(
|
||||||
|
model.Where(model.SqlBuilder{
|
||||||
|
{"comment_approved", "1"},
|
||||||
|
{"comment_post_ID", "=", number.IntToString(postId), "int"},
|
||||||
|
{"comment_ID", "<", number.IntToString(commentId), "int"},
|
||||||
|
{"comment_parent", "=", "0", "int"},
|
||||||
|
}),
|
||||||
|
))
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
return str.ToInteger(v, 0), nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,18 +21,14 @@ type PostContext struct {
|
||||||
Next models.Posts
|
Next models.Posts
|
||||||
}
|
}
|
||||||
|
|
||||||
func CategoriesAndTags(a ...any) (terms []models.TermsMy, err error) {
|
func CategoriesAndTags(ctx context.Context, t string, _ ...any) (terms []models.TermsMy, err error) {
|
||||||
ctx := a[0].(context.Context)
|
|
||||||
t, ok := a[1].(string)
|
|
||||||
var in = []any{"category", "post_tag"}
|
var in = []any{"category", "post_tag"}
|
||||||
if ok {
|
|
||||||
switch t {
|
switch t {
|
||||||
case constraints.Category:
|
case constraints.Category:
|
||||||
in = []any{"category"}
|
in = []any{"category"}
|
||||||
case constraints.Tag:
|
case constraints.Tag:
|
||||||
in = []any{"post_tag"}
|
in = []any{"post_tag"}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
w := model.SqlBuilder{
|
w := model.SqlBuilder{
|
||||||
{"tt.taxonomy", "in", ""},
|
{"tt.taxonomy", "in", ""},
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,10 +11,8 @@ import (
|
||||||
"strconv"
|
"strconv"
|
||||||
)
|
)
|
||||||
|
|
||||||
func GetPostMetaByPostIds(args ...any) (r map[uint64]map[string]any, err error) {
|
func GetPostMetaByPostIds(ctx context.Context, ids []uint64, _ ...any) (r map[uint64]map[string]any, err error) {
|
||||||
r = make(map[uint64]map[string]any)
|
r = make(map[uint64]map[string]any)
|
||||||
ctx := args[0].(context.Context)
|
|
||||||
ids := args[1].([]uint64)
|
|
||||||
rr, err := model.Finds[models.PostMeta](ctx, model.Conditions(
|
rr, err := model.Finds[models.PostMeta](ctx, model.Conditions(
|
||||||
model.Where(model.SqlBuilder{{"post_id", "in", ""}}),
|
model.Where(model.SqlBuilder{{"post_id", "in", ""}}),
|
||||||
model.In(slice.ToAnySlice(ids)),
|
model.In(slice.ToAnySlice(ids)),
|
||||||
|
|
|
@ -3,6 +3,7 @@ package dao
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"database/sql"
|
"database/sql"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/fthvgb1/wp-go/app/pkg/models"
|
"github.com/fthvgb1/wp-go/app/pkg/models"
|
||||||
"github.com/fthvgb1/wp-go/app/pkg/models/relation"
|
"github.com/fthvgb1/wp-go/app/pkg/models/relation"
|
||||||
|
@ -15,10 +16,8 @@ import (
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
func GetPostsByIds(a ...any) (m map[uint64]models.Posts, err error) {
|
func GetPostsByIds(ctx context.Context, ids []uint64, _ ...any) (m map[uint64]models.Posts, err error) {
|
||||||
ctx := a[0].(context.Context)
|
|
||||||
m = make(map[uint64]models.Posts)
|
m = make(map[uint64]models.Posts)
|
||||||
ids := a[1].([]uint64)
|
|
||||||
q := model.Conditions(
|
q := model.Conditions(
|
||||||
model.Where(model.SqlBuilder{{"Id", "in", ""}}),
|
model.Where(model.SqlBuilder{{"Id", "in", ""}}),
|
||||||
model.Join(model.SqlBuilder{
|
model.Join(model.SqlBuilder{
|
||||||
|
@ -99,11 +98,10 @@ func GetPostsByIds(a ...any) (m map[uint64]models.Posts, err error) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func SearchPostIds(args ...any) (ids PostIds, err error) {
|
func SearchPostIds(ctx context.Context, _ string, args ...any) (ids PostIds, err error) {
|
||||||
ctx := args[0].(context.Context)
|
q := args[0].(*model.QueryCondition)
|
||||||
q := args[1].(*model.QueryCondition)
|
page := args[1].(int)
|
||||||
page := args[2].(int)
|
pageSize := args[2].(int)
|
||||||
pageSize := args[3].(int)
|
|
||||||
q.Fields = "ID"
|
q.Fields = "ID"
|
||||||
res, total, err := model.Pagination[models.Posts](ctx, q, page, pageSize)
|
res, total, err := model.Pagination[models.Posts](ctx, q, page, pageSize)
|
||||||
for _, posts := range res {
|
for _, posts := range res {
|
||||||
|
@ -118,11 +116,19 @@ func SearchPostIds(args ...any) (ids PostIds, err error) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetMaxPostId(a ...any) (uint64, error) {
|
func GetMaxPostId(ctx context.Context, _ ...any) (uint64, error) {
|
||||||
ctx := a[0].(context.Context)
|
r, err := model.Finds[models.Posts](ctx,
|
||||||
r, err := model.SimpleFind[models.Posts](ctx,
|
model.Conditions(
|
||||||
model.SqlBuilder{{"post_type", "post"}, {"post_status", "publish"}},
|
model.Where(model.SqlBuilder{
|
||||||
"max(ID) ID",
|
{"post_type", "post"},
|
||||||
|
{"post_status", "publish"}},
|
||||||
|
),
|
||||||
|
model.Fields("ID"),
|
||||||
|
model.Order(model.SqlBuilder{
|
||||||
|
{"ID", "desc"},
|
||||||
|
}),
|
||||||
|
model.Limit(1),
|
||||||
|
),
|
||||||
)
|
)
|
||||||
var id uint64
|
var id uint64
|
||||||
if len(r) > 0 {
|
if len(r) > 0 {
|
||||||
|
@ -131,9 +137,8 @@ func GetMaxPostId(a ...any) (uint64, error) {
|
||||||
return id, err
|
return id, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func RecentPosts(a ...any) (r []models.Posts, err error) {
|
func RecentPosts(ctx context.Context, a ...any) (r []models.Posts, err error) {
|
||||||
ctx := a[0].(context.Context)
|
num := helper.ParseArgs(10, a...)
|
||||||
num := a[1].(int)
|
|
||||||
r, err = model.Finds[models.Posts](ctx, model.Conditions(
|
r, err = model.Finds[models.Posts](ctx, model.Conditions(
|
||||||
model.Where(model.SqlBuilder{
|
model.Where(model.SqlBuilder{
|
||||||
{"post_type", "post"},
|
{"post_type", "post"},
|
||||||
|
@ -146,15 +151,14 @@ func RecentPosts(a ...any) (r []models.Posts, err error) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetPostContext(arg ...any) (r PostContext, err error) {
|
func GetPostContext(ctx context.Context, _ uint64, arg ...any) (r PostContext, err error) {
|
||||||
ctx := arg[0].(context.Context)
|
t := arg[0].(time.Time)
|
||||||
t := arg[1].(time.Time)
|
|
||||||
next, err := model.FirstOne[models.Posts](ctx, model.SqlBuilder{
|
next, err := model.FirstOne[models.Posts](ctx, model.SqlBuilder{
|
||||||
{"post_date", ">", t.Format("2006-01-02 15:04:05")},
|
{"post_date", ">", t.Format("2006-01-02 15:04:05")},
|
||||||
{"post_status", "in", ""},
|
{"post_status", "in", ""},
|
||||||
{"post_type", "post"},
|
{"post_type", "post"},
|
||||||
}, "ID,post_title,post_password", nil, []any{"publish"})
|
}, "ID,post_title,post_password", nil, []any{"publish"})
|
||||||
if err == sql.ErrNoRows {
|
if errors.Is(err, sql.ErrNoRows) {
|
||||||
err = nil
|
err = nil
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -165,7 +169,7 @@ func GetPostContext(arg ...any) (r PostContext, err error) {
|
||||||
{"post_status", "in", ""},
|
{"post_status", "in", ""},
|
||||||
{"post_type", "post"},
|
{"post_type", "post"},
|
||||||
}, "ID,post_title", model.SqlBuilder{{"post_date", "desc"}}, []any{"publish"})
|
}, "ID,post_title", model.SqlBuilder{{"post_date", "desc"}}, []any{"publish"})
|
||||||
if err == sql.ErrNoRows {
|
if errors.Is(err, sql.ErrNoRows) {
|
||||||
err = nil
|
err = nil
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -178,9 +182,8 @@ func GetPostContext(arg ...any) (r PostContext, err error) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func MonthPost(args ...any) (r []uint64, err error) {
|
func MonthPost(ctx context.Context, _ string, args ...any) (r []uint64, err error) {
|
||||||
ctx := args[0].(context.Context)
|
year, month := args[0].(string), args[1].(string)
|
||||||
year, month := args[1].(string), args[2].(string)
|
|
||||||
where := model.SqlBuilder{
|
where := model.SqlBuilder{
|
||||||
{"post_type", "post"},
|
{"post_type", "post"},
|
||||||
{"post_status", "publish"},
|
{"post_status", "publish"},
|
||||||
|
|
|
@ -7,31 +7,26 @@ import (
|
||||||
"github.com/fthvgb1/wp-go/model"
|
"github.com/fthvgb1/wp-go/model"
|
||||||
)
|
)
|
||||||
|
|
||||||
func GetUserById(a ...any) (r models.Users, err error) {
|
func GetUserById(ctx context.Context, uid uint64, _ ...any) (r models.Users, err error) {
|
||||||
ctx := a[0].(context.Context)
|
|
||||||
uid := a[1].(uint64)
|
|
||||||
r, err = model.FindOneById[models.Users](ctx, uid)
|
r, err = model.FindOneById[models.Users](ctx, uid)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func AllUsername(a ...any) (map[string]struct{}, error) {
|
func AllUsername(ctx context.Context, _ ...any) (map[string]uint64, error) {
|
||||||
ctx := a[0].(context.Context)
|
|
||||||
r, err := model.SimpleFind[models.Users](ctx, model.SqlBuilder{
|
r, err := model.SimpleFind[models.Users](ctx, model.SqlBuilder{
|
||||||
{"user_status", "=", "0", "int"},
|
{"user_status", "=", "0", "int"},
|
||||||
}, "user_login")
|
}, "display_name,ID")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return slice.ToMap(r, func(t models.Users) (string, struct{}) {
|
return slice.ToMap(r, func(t models.Users) (string, uint64) {
|
||||||
return t.UserLogin, struct{}{}
|
return t.DisplayName, t.Id
|
||||||
}, true), nil
|
}, true), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetUserByName(a ...any) (r models.Users, err error) {
|
func GetUserByName(ctx context.Context, u string, _ ...any) (r models.Users, err error) {
|
||||||
u := a[1].(string)
|
|
||||||
ctx := a[0].(context.Context)
|
|
||||||
r, err = model.FirstOne[models.Users](ctx, model.SqlBuilder{{
|
r, err = model.FirstOne[models.Users](ctx, model.SqlBuilder{{
|
||||||
"user_login", u,
|
"display_name", u,
|
||||||
}}, "*", nil)
|
}}, "*", nil)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,14 +3,21 @@ package db
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"github.com/fthvgb1/wp-go/app/pkg/config"
|
"github.com/fthvgb1/wp-go/app/pkg/config"
|
||||||
|
"github.com/fthvgb1/wp-go/cache/reload"
|
||||||
"github.com/fthvgb1/wp-go/model"
|
"github.com/fthvgb1/wp-go/model"
|
||||||
"github.com/fthvgb1/wp-go/safety"
|
"github.com/fthvgb1/wp-go/safety"
|
||||||
_ "github.com/go-sql-driver/mysql"
|
_ "github.com/go-sql-driver/mysql"
|
||||||
"github.com/jmoiron/sqlx"
|
"github.com/jmoiron/sqlx"
|
||||||
"log"
|
"log"
|
||||||
|
"runtime"
|
||||||
)
|
)
|
||||||
|
|
||||||
var safeDb = safety.NewVar[*sqlx.DB](nil)
|
var safeDb = safety.NewVar[*sqlx.DB](nil)
|
||||||
|
var showQuerySql func() bool
|
||||||
|
|
||||||
|
func GetSqlxDB() *sqlx.DB {
|
||||||
|
return safeDb.Load()
|
||||||
|
}
|
||||||
|
|
||||||
func InitDb() (*safety.Var[*sqlx.DB], error) {
|
func InitDb() (*safety.Var[*sqlx.DB], error) {
|
||||||
c := config.GetConfig()
|
c := config.GetConfig()
|
||||||
|
@ -36,6 +43,11 @@ func InitDb() (*safety.Var[*sqlx.DB], error) {
|
||||||
if preDb != nil {
|
if preDb != nil {
|
||||||
_ = preDb.Close()
|
_ = preDb.Close()
|
||||||
}
|
}
|
||||||
|
if showQuerySql == nil {
|
||||||
|
showQuerySql = reload.BuildFnVal("showQuerySql", false, func() bool {
|
||||||
|
return config.GetConfig().ShowQuerySql
|
||||||
|
})
|
||||||
|
}
|
||||||
return safeDb, err
|
return safeDb, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -44,14 +56,20 @@ func QueryDb(db *safety.Var[*sqlx.DB]) *model.SqlxQuery {
|
||||||
nil,
|
nil,
|
||||||
nil))
|
nil))
|
||||||
model.SetSelect(query, func(ctx context.Context, a any, s string, args ...any) error {
|
model.SetSelect(query, func(ctx context.Context, a any, s string, args ...any) error {
|
||||||
if config.GetConfig().ShowQuerySql {
|
if showQuerySql() {
|
||||||
go log.Println(model.FormatSql(s, args...))
|
_, f, l, _ := runtime.Caller(5)
|
||||||
|
go func() {
|
||||||
|
log.Printf("%v:%v %v\n", f, l, model.FormatSql(s, args...))
|
||||||
|
}()
|
||||||
}
|
}
|
||||||
return query.Selects(ctx, a, s, args...)
|
return query.Selects(ctx, a, s, args...)
|
||||||
})
|
})
|
||||||
model.SetGet(query, func(ctx context.Context, a any, s string, args ...any) error {
|
model.SetGet(query, func(ctx context.Context, a any, s string, args ...any) error {
|
||||||
if config.GetConfig().ShowQuerySql {
|
if showQuerySql() {
|
||||||
go log.Println(model.FormatSql(s, args...))
|
_, f, l, _ := runtime.Caller(5)
|
||||||
|
go func() {
|
||||||
|
log.Printf("%v:%v %v\n", f, l, model.FormatSql(s, args...))
|
||||||
|
}()
|
||||||
}
|
}
|
||||||
return query.Gets(ctx, a, s, args...)
|
return query.Gets(ctx, a, s, args...)
|
||||||
})
|
})
|
||||||
|
|
|
@ -15,20 +15,24 @@ var logs = safety.NewVar[*log.Logger](nil)
|
||||||
var logFile = safety.NewVar[*os.File](nil)
|
var logFile = safety.NewVar[*os.File](nil)
|
||||||
|
|
||||||
func InitLogger() error {
|
func InitLogger() error {
|
||||||
|
c := config.GetConfig()
|
||||||
|
return SetLogger(c.LogOutput)
|
||||||
|
}
|
||||||
|
|
||||||
|
func SetLogger(loggerFile string) error {
|
||||||
|
if loggerFile == "" {
|
||||||
|
loggerFile = "stderr"
|
||||||
|
}
|
||||||
preFD := logFile.Load()
|
preFD := logFile.Load()
|
||||||
l := &log.Logger{}
|
l := &log.Logger{}
|
||||||
c := config.GetConfig()
|
|
||||||
if c.LogOutput == "" {
|
|
||||||
c.LogOutput = "stderr"
|
|
||||||
}
|
|
||||||
var out io.Writer
|
var out io.Writer
|
||||||
switch c.LogOutput {
|
switch loggerFile {
|
||||||
case "stdout":
|
case "stdout":
|
||||||
out = os.Stdout
|
out = os.Stdout
|
||||||
case "stderr":
|
case "stderr":
|
||||||
out = os.Stderr
|
out = os.Stderr
|
||||||
default:
|
default:
|
||||||
file, err := os.OpenFile(c.LogOutput, os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0777)
|
file, err := os.OpenFile(loggerFile, os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0777)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,7 @@ type Comments struct {
|
||||||
UserId uint64 `gorm:"column:user_id" db:"user_id" json:"user_id" form:"user_id"`
|
UserId uint64 `gorm:"column:user_id" db:"user_id" json:"user_id" form:"user_id"`
|
||||||
//扩展字段
|
//扩展字段
|
||||||
PostTitle string `db:"post_title"`
|
PostTitle string `db:"post_title"`
|
||||||
|
UpdateTime time.Time `gorm:"update_time" form:"update_time" json:"update_time" db:"update_time"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w Comments) PrimaryKey() string {
|
func (w Comments) PrimaryKey() string {
|
||||||
|
@ -29,3 +30,8 @@ func (w Comments) PrimaryKey() string {
|
||||||
func (w Comments) Table() string {
|
func (w Comments) Table() string {
|
||||||
return "wp_comments"
|
return "wp_comments"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type PostComments struct {
|
||||||
|
Comments
|
||||||
|
Children []uint64
|
||||||
|
}
|
||||||
|
|
|
@ -1,8 +1,10 @@
|
||||||
package plugins
|
package plugins
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"github.com/fthvgb1/wp-go/app/pkg/models"
|
"github.com/fthvgb1/wp-go/app/pkg/models"
|
||||||
"github.com/fthvgb1/wp-go/app/wpconfig"
|
"github.com/fthvgb1/wp-go/app/wpconfig"
|
||||||
|
"github.com/fthvgb1/wp-go/helper/number"
|
||||||
"github.com/fthvgb1/wp-go/helper/slice"
|
"github.com/fthvgb1/wp-go/helper/slice"
|
||||||
str "github.com/fthvgb1/wp-go/helper/strings"
|
str "github.com/fthvgb1/wp-go/helper/strings"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
|
@ -17,6 +19,7 @@ type CommentHandler struct {
|
||||||
depth int
|
depth int
|
||||||
isTls bool
|
isTls bool
|
||||||
i CommentHtml
|
i CommentHtml
|
||||||
|
isThreadComments bool
|
||||||
}
|
}
|
||||||
|
|
||||||
type Comments struct {
|
type Comments struct {
|
||||||
|
@ -25,8 +28,8 @@ type Comments struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type CommentHtml interface {
|
type CommentHtml interface {
|
||||||
Sort(i, j *Comments) bool
|
FormatLi(c context.Context, m models.Comments, depth, maxDepth, page int, isTls, isThreadComments bool, eo, parent string) string
|
||||||
FormatLi(c *gin.Context, m models.Comments, depth int, isTls bool, eo, parent string) string
|
FloorOrder(i, j models.Comments) bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func FormatComments(c *gin.Context, i CommentHtml, comments []models.Comments, maxDepth int) string {
|
func FormatComments(c *gin.Context, i CommentHtml, comments []models.Comments, maxDepth int) string {
|
||||||
|
@ -46,15 +49,21 @@ func FormatComments(c *gin.Context, i CommentHtml, comments []models.Comments, m
|
||||||
isTls: isTls,
|
isTls: isTls,
|
||||||
i: i,
|
i: i,
|
||||||
}
|
}
|
||||||
return h.formatComment(h.comments, true)
|
return h.formatComment(h.comments)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d CommentHandler) formatComment(comments []*Comments, isTop bool) (html string) {
|
func (d CommentHandler) formatComment(comments []*Comments) (html string) {
|
||||||
s := str.NewBuilder()
|
s := str.NewBuilder()
|
||||||
if d.depth > d.maxDepth {
|
if d.depth >= d.maxDepth {
|
||||||
comments = d.findComments(comments)
|
comments = d.findComments(comments)
|
||||||
}
|
}
|
||||||
slice.Sort(comments, d.i.Sort)
|
order := wpconfig.GetOption("comment_order")
|
||||||
|
slice.Sort(comments, func(i, j *Comments) bool {
|
||||||
|
if order == "asc" {
|
||||||
|
return i.CommentDate.Sub(j.CommentDate) < 0
|
||||||
|
}
|
||||||
|
return i.CommentDate.Sub(j.CommentDate) > 0
|
||||||
|
})
|
||||||
for i, comment := range comments {
|
for i, comment := range comments {
|
||||||
eo := "even"
|
eo := "even"
|
||||||
if (i+1)%2 == 0 {
|
if (i+1)%2 == 0 {
|
||||||
|
@ -66,13 +75,11 @@ func (d CommentHandler) formatComment(comments []*Comments, isTop bool) (html st
|
||||||
parent = "parent"
|
parent = "parent"
|
||||||
fl = true
|
fl = true
|
||||||
}
|
}
|
||||||
s.WriteString(d.i.FormatLi(d.Context, comment.Comments, d.depth, d.isTls, eo, parent))
|
s.WriteString(d.i.FormatLi(d.Context, comment.Comments, d.depth, d.maxDepth, 1, d.isTls, d.isThreadComments, eo, parent))
|
||||||
if fl {
|
if fl {
|
||||||
d.depth++
|
d.depth++
|
||||||
s.WriteString(`<ol class="children">`, d.formatComment(comment.Children, false), `</ol>`)
|
s.WriteString(`<ol class="children">`, d.formatComment(comment.Children), `</ol>`)
|
||||||
if isTop {
|
d.depth--
|
||||||
d.depth = 1
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
s.WriteString("</li><!-- #comment-## -->")
|
s.WriteString("</li><!-- #comment-## -->")
|
||||||
}
|
}
|
||||||
|
@ -85,7 +92,7 @@ func (d CommentHandler) findComments(comments []*Comments) []*Comments {
|
||||||
var r []*Comments
|
var r []*Comments
|
||||||
for _, comment := range comments {
|
for _, comment := range comments {
|
||||||
tmp := *comment
|
tmp := *comment
|
||||||
comment.Children = nil
|
tmp.Children = nil
|
||||||
r = append(r, &tmp)
|
r = append(r, &tmp)
|
||||||
if len(comment.Children) > 0 {
|
if len(comment.Children) > 0 {
|
||||||
t := d.findComments(comment.Children)
|
t := d.findComments(comment.Children)
|
||||||
|
@ -135,16 +142,35 @@ func CommentRender() CommonCommentFormat {
|
||||||
type CommonCommentFormat struct {
|
type CommonCommentFormat struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c CommonCommentFormat) Sort(i, j *Comments) bool {
|
func (c CommonCommentFormat) FormatLi(_ context.Context, m models.Comments, currentDepth, maxDepth, page int, isTls, isThreadComments bool, eo, parent string) string {
|
||||||
order := wpconfig.GetOption("comment_order")
|
return FormatLi(li, m, respondsFn, currentDepth, maxDepth, page, isTls, isThreadComments, eo, parent)
|
||||||
if order == "asc" {
|
|
||||||
return i.CommentDate.UnixNano() < j.CommentDate.UnixNano()
|
|
||||||
}
|
|
||||||
return i.CommentDate.UnixNano() > j.CommentDate.UnixNano()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c CommonCommentFormat) FormatLi(ctx *gin.Context, m models.Comments, depth int, isTls bool, eo, parent string) string {
|
func (c CommonCommentFormat) FloorOrder(i, j models.Comments) bool {
|
||||||
return FormatLi(CommonLi(), ctx, m, depth, isTls, eo, parent)
|
return i.CommentId > j.CommentId
|
||||||
|
}
|
||||||
|
|
||||||
|
type RespondFn func(m models.Comments, depth, maxDepth int, isThreadComments bool) string
|
||||||
|
|
||||||
|
var respondsFn = Responds(respondTml)
|
||||||
|
|
||||||
|
func RespondsFn() RespondFn {
|
||||||
|
return respondsFn
|
||||||
|
}
|
||||||
|
|
||||||
|
func Responds(respondTml string) RespondFn {
|
||||||
|
return func(m models.Comments, depth, maxDepth int, isThreadComments bool) string {
|
||||||
|
if !isThreadComments || depth >= maxDepth {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
pId := number.IntToString(m.CommentPostId)
|
||||||
|
cId := number.IntToString(m.CommentId)
|
||||||
|
return str.Replace(respondTml, map[string]string{
|
||||||
|
"{{PostId}}": pId,
|
||||||
|
"{{CommentId}}": cId,
|
||||||
|
"{{CommentAuthor}}": m.CommentAuthor,
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var li = `
|
var li = `
|
||||||
|
@ -156,14 +182,11 @@ var li = `
|
||||||
src="{{Gravatar}}"
|
src="{{Gravatar}}"
|
||||||
srcset="{{Gravatar}} 2x"
|
srcset="{{Gravatar}} 2x"
|
||||||
class="avatar avatar-56 photo" height="56" width="56" loading="lazy">
|
class="avatar avatar-56 photo" height="56" width="56" loading="lazy">
|
||||||
<b class="fn">
|
<b class="fn">{{CommentAuthor}}</b>
|
||||||
<a href="{{CommentAuthorUrl}}" rel="external nofollow ugc"
|
|
||||||
class="url">{{CommentAuthor}}</a>
|
|
||||||
</b>
|
|
||||||
<span class="says">说道:</span></div><!-- .comment-author -->
|
<span class="says">说道:</span></div><!-- .comment-author -->
|
||||||
|
|
||||||
<div class="comment-metadata">
|
<div class="comment-metadata">
|
||||||
<a href="/p/{{PostId}}#comment-{{CommentId}}">
|
<a href="/p/{{PostId}}/comment-page-{{page}}#comment-{{CommentId}}">
|
||||||
<time datetime="{{CommentDateGmt}}">{{CommentDate}}</time>
|
<time datetime="{{CommentDateGmt}}">{{CommentDate}}</time>
|
||||||
</a></div><!-- .comment-metadata -->
|
</a></div><!-- .comment-metadata -->
|
||||||
|
|
||||||
|
@ -173,30 +196,34 @@ var li = `
|
||||||
<p>{{CommentContent}}</p>
|
<p>{{CommentContent}}</p>
|
||||||
</div><!-- .comment-content -->
|
</div><!-- .comment-content -->
|
||||||
|
|
||||||
<div class="reply">
|
{{respond}}
|
||||||
|
</article><!-- .comment-body -->
|
||||||
|
|
||||||
|
`
|
||||||
|
|
||||||
|
var respondTml = `<div class="reply">
|
||||||
<a rel="nofollow" class="comment-reply-link"
|
<a rel="nofollow" class="comment-reply-link"
|
||||||
href="/p/{{PostId}}?replytocom={{CommentId}}#respond" data-commentid="{{CommentId}}" data-postid="{{PostId}}"
|
href="/p/{{PostId}}?replytocom={{CommentId}}#respond" data-commentid="{{CommentId}}" data-postid="{{PostId}}"
|
||||||
data-belowelement="div-comment-{{CommentId}}" data-respondelement="respond"
|
data-belowelement="div-comment-{{CommentId}}" data-respondelement="respond"
|
||||||
data-replyto="回复给{{CommentAuthor}}"
|
data-replyto="回复给{{CommentAuthor}}"
|
||||||
aria-label="回复给{{CommentAuthor}}">回复</a>
|
aria-label="回复给{{CommentAuthor}}">回复</a>
|
||||||
</div>
|
</div>`
|
||||||
</article><!-- .comment-body -->
|
|
||||||
|
|
||||||
`
|
func FormatLi(li string, comments models.Comments, respond RespondFn, currentDepth, maxDepth, page int, isTls, isThreadComments bool, eo, parent string) string {
|
||||||
|
|
||||||
func FormatLi(li string, c *gin.Context, comments models.Comments, depth int, isTls bool, eo, parent string) string {
|
|
||||||
for k, v := range map[string]string{
|
for k, v := range map[string]string{
|
||||||
"{{CommentId}}": strconv.FormatUint(comments.CommentId, 10),
|
"{{CommentId}}": strconv.FormatUint(comments.CommentId, 10),
|
||||||
"{{Depth}}": strconv.Itoa(depth),
|
"{{Depth}}": strconv.Itoa(currentDepth),
|
||||||
"{{Gravatar}}": Gravatar(comments.CommentAuthorEmail, isTls),
|
"{{Gravatar}}": Gravatar(comments.CommentAuthorEmail, isTls),
|
||||||
"{{CommentAuthorUrl}}": comments.CommentAuthorUrl,
|
"{{CommentAuthorUrl}}": comments.CommentAuthorUrl,
|
||||||
"{{CommentAuthor}}": comments.CommentAuthor,
|
"{{CommentAuthor}}": comments.CommentAuthor,
|
||||||
"{{PostId}}": strconv.FormatUint(comments.CommentPostId, 10),
|
"{{PostId}}": strconv.FormatUint(comments.CommentPostId, 10),
|
||||||
|
"{{page}}": strconv.Itoa(page),
|
||||||
"{{CommentDateGmt}}": comments.CommentDateGmt.String(),
|
"{{CommentDateGmt}}": comments.CommentDateGmt.String(),
|
||||||
"{{CommentDate}}": comments.CommentDate.Format("2006-01-02 15:04"),
|
"{{CommentDate}}": comments.CommentDate.Format("2006-01-02 15:04"),
|
||||||
"{{CommentContent}}": comments.CommentContent,
|
"{{CommentContent}}": comments.CommentContent,
|
||||||
"{{eo}}": eo,
|
"{{eo}}": eo,
|
||||||
"{{parent}}": parent,
|
"{{parent}}": parent,
|
||||||
|
"{{respond}}": respond(comments, currentDepth, maxDepth, isThreadComments),
|
||||||
} {
|
} {
|
||||||
li = strings.Replace(li, k, v, -1)
|
li = strings.Replace(li, k, v, -1)
|
||||||
}
|
}
|
||||||
|
|
141
app/plugins/devexample/plugintt/redisCache.go.dev
Normal file
141
app/plugins/devexample/plugintt/redisCache.go.dev
Normal file
|
@ -0,0 +1,141 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"github.com/fthvgb1/wp-go/app/pkg/config"
|
||||||
|
"github.com/fthvgb1/wp-go/app/pkg/dao"
|
||||||
|
"github.com/fthvgb1/wp-go/app/pkg/logs"
|
||||||
|
"github.com/fthvgb1/wp-go/app/theme/wp"
|
||||||
|
"github.com/fthvgb1/wp-go/cache/cachemanager"
|
||||||
|
"github.com/fthvgb1/wp-go/cache/reload"
|
||||||
|
"github.com/fthvgb1/wp-go/helper/number"
|
||||||
|
"github.com/fthvgb1/wp-go/helper/slice"
|
||||||
|
"github.com/fthvgb1/wp-go/helper/strings"
|
||||||
|
"github.com/redis/go-redis/v9"
|
||||||
|
"strconv"
|
||||||
|
str "strings"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type RdmCache[K comparable, V any] struct {
|
||||||
|
expired func() time.Duration
|
||||||
|
rdb *redis.Client
|
||||||
|
keyFn func(K) string
|
||||||
|
name string
|
||||||
|
resFn func(map[string]string) V
|
||||||
|
saveData func(V) map[string]string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *RdmCache[K, V]) SetExpiredTime(f func() time.Duration) {
|
||||||
|
r.expired = f
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *RdmCache[K, V]) Get(ctx context.Context, key K) (V, bool) {
|
||||||
|
var re V
|
||||||
|
result, err := r.rdb.Exists(ctx, r.keyFn(key)).Result()
|
||||||
|
if result <= 0 || err != nil {
|
||||||
|
return re, false
|
||||||
|
}
|
||||||
|
|
||||||
|
rr, err := r.rdb.HGetAll(ctx, r.keyFn(key)).Result()
|
||||||
|
|
||||||
|
if errors.Is(err, redis.Nil) {
|
||||||
|
return re, false
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return re, false
|
||||||
|
}
|
||||||
|
return r.resFn(rr), true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *RdmCache[K, V]) Set(ctx context.Context, key K, val V) {
|
||||||
|
k := r.keyFn(key)
|
||||||
|
result, err := r.rdb.HSet(ctx, k, r.saveData(val)).Result()
|
||||||
|
b, err := r.rdb.Expire(ctx, k, r.expired()).Result()
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(result, b, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
fmt.Println(result, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *RdmCache[K, V]) GetExpireTime(ctx context.Context) time.Duration {
|
||||||
|
return r.expired()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *RdmCache[K, V]) Ttl(ctx context.Context, key K) time.Duration {
|
||||||
|
result, err := r.rdb.TTL(ctx, r.keyFn(key)).Result()
|
||||||
|
if err != nil {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *RdmCache[K, V]) Flush(ctx context.Context) {
|
||||||
|
fmt.Println("flush redis cache")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *RdmCache[K, V]) Del(ctx context.Context, key ...K) {
|
||||||
|
r.rdb.Del(ctx, slice.Map(key, r.keyFn)...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *RdmCache[K, V]) ClearExpired(ctx context.Context) {
|
||||||
|
fmt.Println("clear expired redis cache")
|
||||||
|
}
|
||||||
|
|
||||||
|
// RedisCache use step:
|
||||||
|
// 1 go build -gcflags all="-N -l" --race -buildmode=plugin -o redisCache.so main.go && cp ./redisCache.so ../wp-go/plugins/
|
||||||
|
// 2 wp-go config add redisCache plugin
|
||||||
|
func RedisCache(h *wp.Handle) {
|
||||||
|
vv, ok := cachemanager.GetMapCache[string, dao.PostIds]("listPostIds")
|
||||||
|
if ok {
|
||||||
|
_, ok := any(vv.Cache).(*RdmCache[string, dao.PostIds])
|
||||||
|
if ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
reload.AppendOnceFn(func() {
|
||||||
|
err := cachemanager.SetMapCache("listPostIds", vv)
|
||||||
|
if err != nil {
|
||||||
|
logs.Error(err, "set recovery listPostIds cache err")
|
||||||
|
} else {
|
||||||
|
cachemanager.PushOrSetFlush(cachemanager.Queue{Name: "listPostIds", Fn: vv.Flush})
|
||||||
|
cachemanager.PushOrSetClearExpired(cachemanager.Queue{Name: "listPostIds", Fn: vv.Flush})
|
||||||
|
fmt.Println("recovery listPostIds cache ok")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
rdm := redis.NewClient(&redis.Options{
|
||||||
|
Addr: "localhost:6379",
|
||||||
|
Password: "", // no password set
|
||||||
|
DB: 0, // use default DB
|
||||||
|
})
|
||||||
|
r := RdmCache[string, dao.PostIds]{
|
||||||
|
expired: func() time.Duration {
|
||||||
|
return time.Minute
|
||||||
|
},
|
||||||
|
keyFn: func(u string) string {
|
||||||
|
return strings.Join("postIds:", u)
|
||||||
|
},
|
||||||
|
rdb: rdm,
|
||||||
|
name: "",
|
||||||
|
resFn: func(m map[string]string) dao.PostIds {
|
||||||
|
return dao.PostIds{
|
||||||
|
Ids: slice.Map(str.Split(m["ids"], ","), strings.ToInt[uint64]),
|
||||||
|
Length: strings.ToInt[int](m["length"]),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
saveData: func(ids dao.PostIds) map[string]string {
|
||||||
|
t := slice.Map(ids.Ids, number.IntToString[uint64])
|
||||||
|
return map[string]string{
|
||||||
|
"ids": str.Join(t, ","),
|
||||||
|
"length": strconv.Itoa(ids.Length),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
cachemanager.NewMapCache[string, dao.PostIds](&r, nil, dao.SearchPostIds, config.GetConfig().CacheTime.PostListCacheTime, "listPostIds", func() time.Duration {
|
||||||
|
return config.GetConfig().CacheTime.PostListCacheTime
|
||||||
|
})
|
||||||
|
fmt.Println("redis cache inited ok")
|
||||||
|
}
|
50
app/plugins/devexample/plugintt/redisCache.go.mod.dev
Normal file
50
app/plugins/devexample/plugintt/redisCache.go.mod.dev
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
module redisCache
|
||||||
|
|
||||||
|
go 1.21
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/fthvgb1/wp-go v0.0.0-20231210111549-d72bed0c8c4e
|
||||||
|
github.com/redis/go-redis/v9 v9.3.0
|
||||||
|
)
|
||||||
|
|
||||||
|
replace github.com/fthvgb1/wp-go v0.0.0-20231210111549-d72bed0c8c4e => ../wp-go
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/bytedance/sonic v1.10.2 // indirect
|
||||||
|
github.com/cespare/xxhash/v2 v2.2.0 // indirect
|
||||||
|
github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d // indirect
|
||||||
|
github.com/chenzhuoyu/iasm v0.9.1 // indirect
|
||||||
|
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
|
||||||
|
github.com/dlclark/regexp2 v1.10.0 // indirect
|
||||||
|
github.com/elliotchance/phpserialize v1.3.3 // indirect
|
||||||
|
github.com/gabriel-vasile/mimetype v1.4.3 // indirect
|
||||||
|
github.com/gin-contrib/sessions v0.0.5 // indirect
|
||||||
|
github.com/gin-contrib/sse v0.1.0 // indirect
|
||||||
|
github.com/gin-gonic/gin v1.9.1 // indirect
|
||||||
|
github.com/go-playground/locales v0.14.1 // indirect
|
||||||
|
github.com/go-playground/universal-translator v0.18.1 // indirect
|
||||||
|
github.com/go-playground/validator/v10 v10.16.0 // indirect
|
||||||
|
github.com/goccy/go-json v0.10.2 // indirect
|
||||||
|
github.com/gorilla/context v1.1.2 // indirect
|
||||||
|
github.com/gorilla/securecookie v1.1.2 // indirect
|
||||||
|
github.com/gorilla/sessions v1.2.2 // indirect
|
||||||
|
github.com/jmoiron/sqlx v1.3.5 // indirect
|
||||||
|
github.com/json-iterator/go v1.1.12 // indirect
|
||||||
|
github.com/klauspost/cpuid/v2 v2.2.6 // indirect
|
||||||
|
github.com/leodido/go-urn v1.2.4 // indirect
|
||||||
|
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||||
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||||
|
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||||
|
github.com/pelletier/go-toml/v2 v2.1.0 // indirect
|
||||||
|
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
|
||||||
|
github.com/ugorji/go/codec v1.2.11 // indirect
|
||||||
|
golang.org/x/arch v0.6.0 // indirect
|
||||||
|
golang.org/x/crypto v0.15.0 // indirect
|
||||||
|
golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa // indirect
|
||||||
|
golang.org/x/net v0.18.0 // indirect
|
||||||
|
golang.org/x/sys v0.14.0 // indirect
|
||||||
|
golang.org/x/text v0.14.0 // indirect
|
||||||
|
google.golang.org/protobuf v1.31.0 // indirect
|
||||||
|
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||||
|
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||||
|
)
|
|
@ -3,35 +3,134 @@ package plugins
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/fthvgb1/wp-go/app/cmd/cachemanager"
|
|
||||||
"github.com/fthvgb1/wp-go/app/pkg/config"
|
"github.com/fthvgb1/wp-go/app/pkg/config"
|
||||||
|
"github.com/fthvgb1/wp-go/app/pkg/logs"
|
||||||
"github.com/fthvgb1/wp-go/app/pkg/models"
|
"github.com/fthvgb1/wp-go/app/pkg/models"
|
||||||
"github.com/fthvgb1/wp-go/cache"
|
"github.com/fthvgb1/wp-go/cache/cachemanager"
|
||||||
|
"github.com/fthvgb1/wp-go/cache/reload"
|
||||||
"github.com/fthvgb1/wp-go/helper"
|
"github.com/fthvgb1/wp-go/helper"
|
||||||
|
"github.com/fthvgb1/wp-go/helper/maps"
|
||||||
|
str "github.com/fthvgb1/wp-go/helper/strings"
|
||||||
"github.com/fthvgb1/wp-go/plugin/digest"
|
"github.com/fthvgb1/wp-go/plugin/digest"
|
||||||
|
"github.com/fthvgb1/wp-go/safety"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
"unicode/utf8"
|
||||||
)
|
)
|
||||||
|
|
||||||
var digestCache *cache.MapCache[uint64, string]
|
|
||||||
|
|
||||||
var more = regexp.MustCompile("<!--more(.*?)?-->")
|
var more = regexp.MustCompile("<!--more(.*?)?-->")
|
||||||
|
|
||||||
var removeWpBlock = regexp.MustCompile("<!-- /?wp:.*-->")
|
var removeWpBlock = regexp.MustCompile("<!-- /?wp:.*-->")
|
||||||
|
|
||||||
|
type DigestConfig struct {
|
||||||
|
DigestWordCount int `yaml:"digestWordCount"`
|
||||||
|
DigestAllowTag string `yaml:"digestAllowTag"`
|
||||||
|
DigestRegex string `yaml:"digestRegex"`
|
||||||
|
DigestTagOccupyNum []struct {
|
||||||
|
Tag string `yaml:"tag"`
|
||||||
|
Num int `yaml:"num"`
|
||||||
|
ChuckOvered bool `yaml:"chuckOvered"`
|
||||||
|
EscapeCharacter []struct {
|
||||||
|
Tags string `yaml:"tags"`
|
||||||
|
Character []string `yaml:"character"`
|
||||||
|
Num int `yaml:"num"`
|
||||||
|
ChuckOvered bool `yaml:"chuckOvered"`
|
||||||
|
} `yaml:"escapeCharacter"`
|
||||||
|
} `yaml:"digestTagOccupyNum"`
|
||||||
|
specialSolve map[string]digest.SpecialSolveConf
|
||||||
|
}
|
||||||
|
|
||||||
|
var digestConfig *safety.Var[DigestConfig]
|
||||||
|
|
||||||
func InitDigestCache() {
|
func InitDigestCache() {
|
||||||
digestCache = cachemanager.MapCacheBy[uint64](digestRaw, config.GetConfig().CacheTime.DigestCacheTime)
|
cachemanager.NewMemoryMapCache(nil, digestRaw, config.GetConfig().CacheTime.DigestCacheTime, "digestPlugin", func() time.Duration {
|
||||||
|
return config.GetConfig().CacheTime.DigestCacheTime
|
||||||
|
})
|
||||||
|
|
||||||
|
digestConfig = reload.VarsBy(func() DigestConfig {
|
||||||
|
c, err := config.GetCustomizedConfig[DigestConfig]()
|
||||||
|
if err != nil {
|
||||||
|
logs.Error(err, "get digest config fail")
|
||||||
|
c.DigestWordCount = config.GetConfig().DigestWordCount
|
||||||
|
c.DigestAllowTag = config.GetConfig().DigestAllowTag
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
if c.DigestRegex != "" {
|
||||||
|
digest.SetQutos(c.DigestRegex)
|
||||||
|
}
|
||||||
|
if len(c.DigestTagOccupyNum) <= 1 {
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
c.specialSolve = ParseDigestConf(c)
|
||||||
|
return c
|
||||||
|
}, "digestConfig")
|
||||||
|
}
|
||||||
|
|
||||||
|
func ParseDigestConf(c DigestConfig) map[string]digest.SpecialSolveConf {
|
||||||
|
specialSolve := map[string]digest.SpecialSolveConf{}
|
||||||
|
for _, item := range c.DigestTagOccupyNum {
|
||||||
|
tags := strings.Split(strings.ReplaceAll(item.Tag, " ", ""), "<")
|
||||||
|
for _, tag := range tags {
|
||||||
|
if tag == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
ec := make(map[rune]digest.SpecialSolve)
|
||||||
|
specialTags := make(map[string]digest.SpecialSolve)
|
||||||
|
tag = str.Join("<", tag)
|
||||||
|
if len(item.EscapeCharacter) > 0 {
|
||||||
|
for _, esc := range item.EscapeCharacter {
|
||||||
|
for _, i := range esc.Character {
|
||||||
|
s := []rune(i)
|
||||||
|
if len(s) == 1 {
|
||||||
|
ec[s[0]] = digest.SpecialSolve{
|
||||||
|
Num: esc.Num,
|
||||||
|
ChuckOvered: esc.ChuckOvered,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if esc.Tags == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
tagss := strings.Split(strings.ReplaceAll(esc.Tags, " ", ""), "<")
|
||||||
|
for _, t := range tagss {
|
||||||
|
if t == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
t = str.Join("<", t)
|
||||||
|
specialTags[t] = digest.SpecialSolve{
|
||||||
|
Num: esc.Num,
|
||||||
|
ChuckOvered: esc.ChuckOvered,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
v, ok := specialSolve[tag]
|
||||||
|
if !ok {
|
||||||
|
specialSolve[tag] = digest.SpecialSolveConf{
|
||||||
|
Num: item.Num,
|
||||||
|
ChuckOvered: item.ChuckOvered,
|
||||||
|
EscapeCharacter: ec,
|
||||||
|
Tags: specialTags,
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
v.Num = item.Num
|
||||||
|
v.ChuckOvered = item.ChuckOvered
|
||||||
|
v.EscapeCharacter = maps.Merge(v.EscapeCharacter, ec)
|
||||||
|
v.Tags = maps.Merge(v.Tags, specialTags)
|
||||||
|
specialSolve[tag] = v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return specialSolve
|
||||||
}
|
}
|
||||||
|
|
||||||
func RemoveWpBlock(s string) string {
|
func RemoveWpBlock(s string) string {
|
||||||
return removeWpBlock.ReplaceAllString(s, "")
|
return removeWpBlock.ReplaceAllString(s, "")
|
||||||
}
|
}
|
||||||
|
|
||||||
func digestRaw(arg ...any) (string, error) {
|
func digestRaw(ctx context.Context, id uint64, arg ...any) (string, error) {
|
||||||
ctx := arg[0].(context.Context)
|
|
||||||
s := arg[1].(string)
|
s := arg[1].(string)
|
||||||
id := arg[2].(uint64)
|
|
||||||
limit := arg[3].(int)
|
limit := arg[3].(int)
|
||||||
if limit < 0 {
|
if limit < 0 {
|
||||||
return s, nil
|
return s, nil
|
||||||
|
@ -47,12 +146,22 @@ func digestRaw(arg ...any) (string, error) {
|
||||||
func Digests(content string, id uint64, limit int, fn func(id uint64, content, closeTag string) string) string {
|
func Digests(content string, id uint64, limit int, fn func(id uint64, content, closeTag string) string) string {
|
||||||
closeTag := ""
|
closeTag := ""
|
||||||
content = RemoveWpBlock(content)
|
content = RemoveWpBlock(content)
|
||||||
tag := config.GetConfig().DigestAllowTag
|
c := digestConfig.Load()
|
||||||
|
tag := c.DigestAllowTag
|
||||||
if tag == "" {
|
if tag == "" {
|
||||||
tag = "<a><b><blockquote><br><cite><code><dd><del><div><dl><dt><em><h1><h2><h3><h4><h5><h6><i><img><li><ol><p><pre><span><strong><ul>"
|
tag = "<a><b><blockquote><br><cite><code><dd><del><div><dl><dt><em><h1><h2><h3><h4><h5><h6><i><img><li><ol><p><pre><span><strong><ul>"
|
||||||
}
|
}
|
||||||
content = digest.StripTags(content, tag)
|
content = digest.StripTags(content, tag)
|
||||||
|
length := utf8.RuneCountInString(content) + 1
|
||||||
|
if length <= limit {
|
||||||
|
return content
|
||||||
|
}
|
||||||
|
if len(c.specialSolve) > 0 {
|
||||||
|
content, closeTag = digest.CustomizeHtml(content, limit, c.specialSolve)
|
||||||
|
} else {
|
||||||
content, closeTag = digest.Html(content, limit)
|
content, closeTag = digest.Html(content, limit)
|
||||||
|
}
|
||||||
|
|
||||||
if fn == nil {
|
if fn == nil {
|
||||||
return PostsMore(id, content, closeTag)
|
return PostsMore(id, content, closeTag)
|
||||||
}
|
}
|
||||||
|
@ -69,7 +178,7 @@ func PostsMore(id uint64, content, closeTag string) string {
|
||||||
}
|
}
|
||||||
|
|
||||||
func Digest(ctx context.Context, post *models.Posts, limit int) {
|
func Digest(ctx context.Context, post *models.Posts, limit int) {
|
||||||
content, _ := digestCache.GetCache(ctx, post.Id, time.Second, ctx, post.PostContent, post.Id, limit)
|
content, _ := cachemanager.GetBy[string]("digestPlugin", ctx, post.Id, time.Second, ctx, post.PostContent, post.Id, limit)
|
||||||
post.PostContent = content
|
post.PostContent = content
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,8 +2,12 @@ package plugins
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"github.com/fthvgb1/wp-go/app/wpconfig"
|
||||||
|
"github.com/fthvgb1/wp-go/helper"
|
||||||
str "github.com/fthvgb1/wp-go/helper/strings"
|
str "github.com/fthvgb1/wp-go/helper/strings"
|
||||||
|
"net/url"
|
||||||
"regexp"
|
"regexp"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -18,6 +22,13 @@ type PageEle struct {
|
||||||
func TwentyFifteenPagination() PageEle {
|
func TwentyFifteenPagination() PageEle {
|
||||||
return twentyFifteen
|
return twentyFifteen
|
||||||
}
|
}
|
||||||
|
func TwentyFifteenCommentPagination() CommentPageEle {
|
||||||
|
return twentyFifteenComment
|
||||||
|
}
|
||||||
|
|
||||||
|
type CommentPageEle struct {
|
||||||
|
PageEle
|
||||||
|
}
|
||||||
|
|
||||||
var twentyFifteen = PageEle{
|
var twentyFifteen = PageEle{
|
||||||
PrevEle: `<a class="prev page-numbers" href="%s">上一页</a>`,
|
PrevEle: `<a class="prev page-numbers" href="%s">上一页</a>`,
|
||||||
|
@ -28,6 +39,12 @@ var twentyFifteen = PageEle{
|
||||||
CurrentEle: `<span aria-current="page" class="page-numbers current">
|
CurrentEle: `<span aria-current="page" class="page-numbers current">
|
||||||
<span class="meta-nav screen-reader-text">页 </span>%d</span>`,
|
<span class="meta-nav screen-reader-text">页 </span>%d</span>`,
|
||||||
}
|
}
|
||||||
|
var twentyFifteenComment = CommentPageEle{
|
||||||
|
PageEle{
|
||||||
|
PrevEle: `<div class="nav-previous"><a href="%s">%s</a></div>`,
|
||||||
|
NextEle: `<div class="nav-next"><a href="%s">%s</a></div>`,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
func (p PageEle) Current(page, totalPage, totalRow int) string {
|
func (p PageEle) Current(page, totalPage, totalRow int) string {
|
||||||
return fmt.Sprintf(p.CurrentEle, page)
|
return fmt.Sprintf(p.CurrentEle, page)
|
||||||
|
@ -50,8 +67,22 @@ func (p PageEle) Middle(page int, url string) string {
|
||||||
}
|
}
|
||||||
|
|
||||||
var reg = regexp.MustCompile(`(/page)/(\d+)`)
|
var reg = regexp.MustCompile(`(/page)/(\d+)`)
|
||||||
|
var commentReg = regexp.MustCompile(`/comment-page-(\d+)`)
|
||||||
|
|
||||||
|
var queryParam = []string{"paged", "cat", "m", "author", "tag"}
|
||||||
|
|
||||||
|
func (p PageEle) Urls(u url.URL, page int, isTLS bool) string {
|
||||||
|
var path, query = u.Path, u.RawQuery
|
||||||
|
if path == "/" {
|
||||||
|
v := u.Query()
|
||||||
|
for _, q := range queryParam {
|
||||||
|
if v.Get(q) != "" {
|
||||||
|
v.Set("paged", strconv.Itoa(page))
|
||||||
|
return str.Join(path, "?", v.Encode())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (p PageEle) Url(path, query string, page int) string {
|
|
||||||
if !strings.Contains(path, "/page/") {
|
if !strings.Contains(path, "/page/") {
|
||||||
path = fmt.Sprintf("%s%s", path, "/page/1")
|
path = fmt.Sprintf("%s%s", path, "/page/1")
|
||||||
}
|
}
|
||||||
|
@ -65,5 +96,81 @@ func (p PageEle) Url(path, query string, page int) string {
|
||||||
if path == "" {
|
if path == "" {
|
||||||
path = "/"
|
path = "/"
|
||||||
}
|
}
|
||||||
return str.Join(path, query)
|
if query != "" {
|
||||||
|
return str.Join(path, "?", query)
|
||||||
|
}
|
||||||
|
return path
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p CommentPageEle) Urls(u url.URL, page int, isTLS bool) string {
|
||||||
|
var path, query = u.Path, u.RawQuery
|
||||||
|
if path == "/" {
|
||||||
|
v := u.Query()
|
||||||
|
if v.Get("p") != "" {
|
||||||
|
v.Set("cpage", strconv.Itoa(page))
|
||||||
|
return str.Join(path, "?", v.Encode(), "#comments")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !strings.Contains(path, "/comment-page-") {
|
||||||
|
path = fmt.Sprintf("%s%s", path, "/comment-page-1")
|
||||||
|
}
|
||||||
|
path = commentReg.ReplaceAllString(path, fmt.Sprintf("/comment-page-%d", page))
|
||||||
|
path = strings.Replace(path, "//", "/", -1)
|
||||||
|
ur := path
|
||||||
|
if query != "" {
|
||||||
|
ur = str.Join(path, "?", query)
|
||||||
|
}
|
||||||
|
ur = str.Join(ur, "#comments")
|
||||||
|
return ur
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p CommentPageEle) Middle(page int, url string) string {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
func (p CommentPageEle) Dots() string {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
func (p CommentPageEle) Current(page, totalPage, totalRow int) string {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
func (p CommentPageEle) Prev(url string) string {
|
||||||
|
return fmt.Sprintf(p.PrevEle, url, helper.Or(wpconfig.GetOption("comment_order") == "asc", "较早评论", "较新评论"))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p CommentPageEle) Next(url string) string {
|
||||||
|
return fmt.Sprintf(p.NextEle, url, helper.Or(wpconfig.GetOption("comment_order") == "asc", "较新评论", "较早评论"))
|
||||||
|
}
|
||||||
|
|
||||||
|
type PaginationNav struct {
|
||||||
|
Currents func(page, totalPage, totalRows int) string
|
||||||
|
Prevs func(url string) string
|
||||||
|
Nexts func(url string) string
|
||||||
|
Dotss func() string
|
||||||
|
Middles func(page int, url string) string
|
||||||
|
Urlss func(u url.URL, page int, isTLS bool) string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p PaginationNav) Current(page, totalPage, totalRows int) string {
|
||||||
|
return p.Currents(page, totalPage, totalRows)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p PaginationNav) Prev(url string) string {
|
||||||
|
return p.Prevs(url)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p PaginationNav) Next(url string) string {
|
||||||
|
return p.Nexts(url)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p PaginationNav) Dots() string {
|
||||||
|
return p.Dotss()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p PaginationNav) Middle(page int, url string) string {
|
||||||
|
return p.Middles(page, url)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p PaginationNav) Urls(u url.URL, page int, isTLS bool) string {
|
||||||
|
return p.Urlss(u, page, isTLS)
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,12 +2,29 @@ package apply
|
||||||
|
|
||||||
import "github.com/fthvgb1/wp-go/safety"
|
import "github.com/fthvgb1/wp-go/safety"
|
||||||
|
|
||||||
var fn safety.Var[any]
|
var contains = safety.NewMap[string, any]()
|
||||||
|
|
||||||
func SetFn(f any) {
|
func SetVal(key string, val any) {
|
||||||
fn.Store(f)
|
contains.Store(key, val)
|
||||||
}
|
}
|
||||||
|
|
||||||
func UsePlugins() any {
|
func DelVal(key string) {
|
||||||
return fn.Load()
|
contains.Delete(key)
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetVal[V any](key string) (V, bool) {
|
||||||
|
v, ok := contains.Load(key)
|
||||||
|
if !ok {
|
||||||
|
var vv V
|
||||||
|
return vv, ok
|
||||||
|
}
|
||||||
|
return v.(V), ok
|
||||||
|
}
|
||||||
|
func GetRawVal(key string) (any, bool) {
|
||||||
|
return contains.Load(key)
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetPlugins() any {
|
||||||
|
v, _ := contains.Load("wp-plugins")
|
||||||
|
return v
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,7 +22,7 @@ type Options struct {
|
||||||
Linehover bool `json:"linehover,omitempty"`
|
Linehover bool `json:"linehover,omitempty"`
|
||||||
RawcodeDbclick bool `json:"rawcodeDbclick,omitempty"`
|
RawcodeDbclick bool `json:"rawcodeDbclick,omitempty"`
|
||||||
TextOverflow string `json:"textOverflow,omitempty"`
|
TextOverflow string `json:"textOverflow,omitempty"`
|
||||||
Linenumbers int64 `json:"linenumbers,omitempty"`
|
Linenumbers bool `json:"linenumbers,omitempty"`
|
||||||
Theme string `json:"theme,omitempty"`
|
Theme string `json:"theme,omitempty"`
|
||||||
Language string `json:"language,omitempty"`
|
Language string `json:"language,omitempty"`
|
||||||
RetainCssClasses bool `json:"retainCssClasses,omitempty"`
|
RetainCssClasses bool `json:"retainCssClasses,omitempty"`
|
||||||
|
@ -58,7 +58,7 @@ func EnlighterJS(h *wp.Handle) {
|
||||||
Linehover: maps.GetStrAnyValWithDefaults(opp, "enlighterjs-linehover", true),
|
Linehover: maps.GetStrAnyValWithDefaults(opp, "enlighterjs-linehover", true),
|
||||||
RawcodeDbclick: maps.GetStrAnyValWithDefaults(opp, "enlighterjs-rawcodedbclick", true),
|
RawcodeDbclick: maps.GetStrAnyValWithDefaults(opp, "enlighterjs-rawcodedbclick", true),
|
||||||
TextOverflow: maps.GetStrAnyValWithDefaults(opp, "enlighterjs-textoverflow", "break"),
|
TextOverflow: maps.GetStrAnyValWithDefaults(opp, "enlighterjs-textoverflow", "break"),
|
||||||
Linenumbers: maps.GetStrAnyValWithDefaults[int64](opp, "enlighterjs-linenumbers", 1),
|
Linenumbers: maps.GetStrAnyValWithDefaults(opp, "enlighterjs-linenumbers", true),
|
||||||
Theme: maps.GetStrAnyValWithDefaults(opp, "enlighterjs-theme", "enlighter"),
|
Theme: maps.GetStrAnyValWithDefaults(opp, "enlighterjs-theme", "enlighter"),
|
||||||
Language: maps.GetStrAnyValWithDefaults(opp, "enlighterjs-language", "generic"),
|
Language: maps.GetStrAnyValWithDefaults(opp, "enlighterjs-language", "generic"),
|
||||||
RetainCssClasses: maps.GetStrAnyValWithDefaults(opp, "enlighterjs-retaincss", false),
|
RetainCssClasses: maps.GetStrAnyValWithDefaults(opp, "enlighterjs-retaincss", false),
|
||||||
|
|
|
@ -66,7 +66,7 @@ func LoadPlugins() {
|
||||||
}
|
}
|
||||||
RegisterPlugin(name, plu)
|
RegisterPlugin(name, plu)
|
||||||
}
|
}
|
||||||
apply.SetFn(func(h *wp.Handle) {
|
apply.SetVal("wp-plugins", func(h *wp.Handle) {
|
||||||
UsePlugins(h)
|
UsePlugins(h)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func Tt(h *wp.Handle) {
|
func Tt(h *wp.Handle) {
|
||||||
h.HookHandle(constraints.PipeMiddleware, func(call wp.HandleCall) (wp.HandleCall, bool) {
|
h.HookHandle(constraints.PipeMiddleware, constraints.AllScene, func(call wp.HandleCall) (wp.HandleCall, bool) {
|
||||||
return call, false
|
return call, false
|
||||||
})
|
})
|
||||||
/*h.PushPipeHook(constraints.Home, func(pipe wp.Pipe) (wp.Pipe, bool) {
|
/*h.PushPipeHook(constraints.Home, func(pipe wp.Pipe) (wp.Pipe, bool) {
|
||||||
|
|
147
app/route/route.go
Normal file
147
app/route/route.go
Normal file
|
@ -0,0 +1,147 @@
|
||||||
|
package route
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/fthvgb1/wp-go/app/actions"
|
||||||
|
"github.com/fthvgb1/wp-go/app/middleware"
|
||||||
|
"github.com/fthvgb1/wp-go/app/pkg/config"
|
||||||
|
"github.com/fthvgb1/wp-go/app/pkg/constraints"
|
||||||
|
"github.com/fthvgb1/wp-go/app/theme"
|
||||||
|
"github.com/fthvgb1/wp-go/app/wpconfig"
|
||||||
|
"github.com/fthvgb1/wp-go/cache/reload"
|
||||||
|
"github.com/fthvgb1/wp-go/helper/slice"
|
||||||
|
"github.com/fthvgb1/wp-go/helper/slice/mockmap"
|
||||||
|
str "github.com/fthvgb1/wp-go/helper/strings"
|
||||||
|
"github.com/gin-contrib/gzip"
|
||||||
|
"github.com/gin-contrib/pprof"
|
||||||
|
"github.com/gin-contrib/sessions"
|
||||||
|
"github.com/gin-contrib/sessions/cookie"
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
)
|
||||||
|
|
||||||
|
type GinSetter func(*gin.Engine)
|
||||||
|
|
||||||
|
var setters mockmap.Map[string, GinSetter]
|
||||||
|
|
||||||
|
var setterHooks []func(item mockmap.Item[string, GinSetter]) (mockmap.Item[string, GinSetter], bool)
|
||||||
|
|
||||||
|
// SetGinAction 方便插件在init时使用
|
||||||
|
func SetGinAction(name string, hook GinSetter, orders ...float64) {
|
||||||
|
setters.Set(name, hook, orders...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func HookGinSetter(fn func(item mockmap.Item[string, GinSetter]) (mockmap.Item[string, GinSetter], bool)) {
|
||||||
|
setterHooks = append(setterHooks, fn)
|
||||||
|
}
|
||||||
|
|
||||||
|
// DelGinSetter 方便插件在init时使用
|
||||||
|
func DelGinSetter(name string) {
|
||||||
|
setterHooks = append(setterHooks, func(item mockmap.Item[string, GinSetter]) (mockmap.Item[string, GinSetter], bool) {
|
||||||
|
return item, item.Name != name
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func SetupRouter() *gin.Engine {
|
||||||
|
// Disable Console Color
|
||||||
|
// gin.DisableConsoleColor()
|
||||||
|
r := gin.New()
|
||||||
|
c := config.GetConfig()
|
||||||
|
SetGinAction("initTrustIp", func(r *gin.Engine) {
|
||||||
|
if len(c.TrustIps) > 0 {
|
||||||
|
err := r.SetTrustedProxies(c.TrustIps)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, 99.5)
|
||||||
|
|
||||||
|
SetGinAction("setTemplate", func(r *gin.Engine) {
|
||||||
|
r.HTMLRender = theme.BuildTemplate()
|
||||||
|
wpconfig.SetTemplateFs(theme.TemplateFs)
|
||||||
|
}, 90.5)
|
||||||
|
|
||||||
|
siteFlowLimitMiddleware, siteFlow := middleware.FlowLimit(c.MaxRequestSleepNum, c.MaxRequestNum, c.CacheTime.SleepTime)
|
||||||
|
reload.Append(func() {
|
||||||
|
c = config.GetConfig()
|
||||||
|
siteFlow(c.MaxRequestSleepNum, c.MaxRequestNum, c.CacheTime.SleepTime)
|
||||||
|
}, "site-flowLimit-config")
|
||||||
|
|
||||||
|
SetGinAction("setGlobalMiddleware", func(r *gin.Engine) {
|
||||||
|
r.Use(
|
||||||
|
gin.Logger(),
|
||||||
|
middleware.ValidateServerNames(),
|
||||||
|
middleware.RecoverAndSendMail(gin.DefaultErrorWriter),
|
||||||
|
siteFlowLimitMiddleware,
|
||||||
|
middleware.SetStaticFileCache,
|
||||||
|
)
|
||||||
|
}, 88.5)
|
||||||
|
|
||||||
|
SetGinAction("setGzip", func(r *gin.Engine) {
|
||||||
|
//gzip 因为一般会用nginx做反代时自动使用gzip,所以go这边本身可以不用
|
||||||
|
if c.Gzip {
|
||||||
|
r.Use(gzip.Gzip(gzip.DefaultCompression, gzip.WithExcludedPaths([]string{
|
||||||
|
"/wp-includes/", "/wp-content/",
|
||||||
|
})))
|
||||||
|
}
|
||||||
|
}, 87.6)
|
||||||
|
|
||||||
|
SetGinAction("setWpDir", func(r *gin.Engine) {
|
||||||
|
if c.WpDir == "" {
|
||||||
|
panic("wordpress path can't be empty")
|
||||||
|
}
|
||||||
|
r.Static("/wp-content/uploads", str.Join(c.WpDir, "/wp-content/uploads"))
|
||||||
|
r.Static("/wp-content/themes", str.Join(c.WpDir, "/wp-content/themes"))
|
||||||
|
r.Static("/wp-content/plugins", str.Join(c.WpDir, "/wp-content/plugins"))
|
||||||
|
r.Static("/wp-includes/css", str.Join(c.WpDir, "/wp-includes/css"))
|
||||||
|
r.Static("/wp-includes/fonts", str.Join(c.WpDir, "/wp-includes/fonts"))
|
||||||
|
r.Static("/wp-includes/js", str.Join(c.WpDir, "/wp-includes/js"))
|
||||||
|
}, 86.1)
|
||||||
|
|
||||||
|
SetGinAction("setSession", func(r *gin.Engine) {
|
||||||
|
store := cookie.NewStore([]byte("secret"))
|
||||||
|
r.Use(sessions.Sessions("go-wp", store))
|
||||||
|
}, 85.1)
|
||||||
|
|
||||||
|
SetGinAction("setRoute", func(r *gin.Engine) {
|
||||||
|
r.GET("/", actions.Feed, middleware.SearchLimit(c.SingleIpSearchNum),
|
||||||
|
actions.ThemeHook(constraints.Home))
|
||||||
|
r.GET("/page/:page", actions.ThemeHook(constraints.Home))
|
||||||
|
r.GET("/p/category/:category", actions.ThemeHook(constraints.Category))
|
||||||
|
r.GET("/p/category/:category/page/:page", actions.ThemeHook(constraints.Category))
|
||||||
|
r.GET("/p/tag/:tag", actions.ThemeHook(constraints.Tag))
|
||||||
|
r.GET("/p/tag/:tag/page/:page", actions.ThemeHook(constraints.Tag))
|
||||||
|
r.GET("/p/date/:year/:month", actions.ThemeHook(constraints.Archive))
|
||||||
|
r.GET("/p/date/:year/:month/page/:page", actions.ThemeHook(constraints.Archive))
|
||||||
|
r.GET("/p/author/:author", actions.ThemeHook(constraints.Author))
|
||||||
|
r.GET("/p/author/:author/page/:page", actions.ThemeHook(constraints.Author))
|
||||||
|
r.POST("/login", actions.Login)
|
||||||
|
r.GET("/p/:id", actions.ThemeHook(constraints.Detail))
|
||||||
|
r.GET("/p/:id/comment-page-:page", actions.ThemeHook(constraints.Detail))
|
||||||
|
r.GET("/p/:id/feed", actions.PostFeed)
|
||||||
|
r.GET("/feed", actions.SiteFeed)
|
||||||
|
r.GET("/comments/feed", actions.CommentsFeed)
|
||||||
|
commentMiddleWare, _ := middleware.FlowLimit(c.MaxRequestSleepNum, 5, c.CacheTime.SleepTime)
|
||||||
|
r.POST("/comment", commentMiddleWare, actions.PostComment)
|
||||||
|
|
||||||
|
r.NoRoute(actions.ThemeHook(constraints.NoRoute))
|
||||||
|
}, 84.6)
|
||||||
|
|
||||||
|
SetGinAction("setpprof", func(r *gin.Engine) {
|
||||||
|
if c.Pprof != "" {
|
||||||
|
pprof.Register(r, c.Pprof)
|
||||||
|
}
|
||||||
|
}, 80.8)
|
||||||
|
|
||||||
|
for _, hook := range setterHooks {
|
||||||
|
setters = slice.FilterAndMap(setters, hook)
|
||||||
|
}
|
||||||
|
|
||||||
|
slice.SimpleSort(setters, slice.DESC, func(t mockmap.Item[string, GinSetter]) float64 {
|
||||||
|
return t.Order
|
||||||
|
})
|
||||||
|
|
||||||
|
for _, fn := range setters {
|
||||||
|
fn.Value(r)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r
|
||||||
|
}
|
|
@ -3,6 +3,7 @@ package theme
|
||||||
import (
|
import (
|
||||||
"embed"
|
"embed"
|
||||||
"github.com/fthvgb1/wp-go/multipTemplate"
|
"github.com/fthvgb1/wp-go/multipTemplate"
|
||||||
|
"github.com/fthvgb1/wp-go/safety"
|
||||||
"html/template"
|
"html/template"
|
||||||
"io/fs"
|
"io/fs"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
@ -12,20 +13,36 @@ import (
|
||||||
//go:embed *[^.go]
|
//go:embed *[^.go]
|
||||||
var TemplateFs embed.FS
|
var TemplateFs embed.FS
|
||||||
|
|
||||||
var templates map[string]*template.Template //方便外部获取模板render后的字符串,不然在gin中获取不了
|
var templates = safety.NewMap[string, *template.Template]() //方便外部获取模板render后的字符串,不然在gin中获取不了
|
||||||
|
|
||||||
func Template() *multipTemplate.MultipleFsTemplate {
|
var multiple *multipTemplate.MultipleFsTemplate
|
||||||
t := multipTemplate.NewFsTemplate(TemplateFs)
|
|
||||||
templates = t.Template
|
func BuildTemplate() *multipTemplate.MultipleFsTemplate {
|
||||||
t.FuncMap = FuncMap()
|
if multiple != nil {
|
||||||
commonTemplate(t)
|
tt := multipTemplate.NewFsTemplate(TemplateFs)
|
||||||
/*t.AddTemplate("twentyfifteen/*[^layout]/*.gohtml", FuncMap(), "twentyfifteen/layout/*.gohtml"). //单个主题设置
|
commonTemplate(tt)
|
||||||
AddTemplate("twentyseventeen/*[^layout]/*.gohtml", FuncMap(), "twentyseventeen/layout/*.gohtml")*/
|
for k, v := range map[string]*template.Template(any(tt.Template).(multipTemplate.TemplateMaps)) {
|
||||||
return t
|
multiple.Template.Store(k, v)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
multiple = multipTemplate.NewFsTemplates(TemplateFs, templates)
|
||||||
|
commonTemplate(multiple)
|
||||||
|
}
|
||||||
|
|
||||||
|
/*t.AddTemplate("twentyfifteen/*[^layout]/*.gohtml", FuncMap(), "twentyfifteen/layout/*.gohtml","wp/template.gohtml"). //单个主题设置
|
||||||
|
AddTemplate("twentyseventeen/*[^layout]/*.gohtml", FuncMap(), "twentyseventeen/layout/*.gohtml","wp/template.gohtml")*/
|
||||||
|
return multiple
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetMultipleTemplate() *multipTemplate.MultipleFsTemplate {
|
||||||
|
if multiple == nil {
|
||||||
|
BuildTemplate()
|
||||||
|
}
|
||||||
|
return multiple
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetTemplate(name string) (*template.Template, bool) {
|
func GetTemplate(name string) (*template.Template, bool) {
|
||||||
t, ok := templates[name]
|
t, ok := templates.Load(name)
|
||||||
return t, ok
|
return t, ok
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -35,10 +52,11 @@ func commonTemplate(t *multipTemplate.MultipleFsTemplate) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
funMap := FuncMap()
|
||||||
for _, main := range m {
|
for _, main := range m {
|
||||||
file := filepath.Base(main)
|
file := filepath.Base(main)
|
||||||
dir := strings.Split(main, "/")[0]
|
dir := strings.Split(main, "/")[0]
|
||||||
templ := template.Must(template.New(file).Funcs(t.FuncMap).ParseFS(t.Fs, main, filepath.Join(dir, "layout/*.gohtml"), "wp/template.gohtml"))
|
templ := template.Must(template.New(file).Funcs(funMap).ParseFS(t.Fs, main, filepath.Join(dir, "layout/*.gohtml"), "wp/template.gohtml"))
|
||||||
t.SetTemplate(main, templ)
|
t.SetTemplate(main, templ)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -55,6 +73,10 @@ func IsTemplateDirExists(tml string) bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
func IsTemplateExists(tml string) bool {
|
func IsTemplateExists(tml string) bool {
|
||||||
t, ok := templates[tml]
|
t, ok := templates.Load(tml)
|
||||||
return ok && t != nil
|
return ok && t != nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func SetTemplate(name string, val *template.Template) {
|
||||||
|
templates.Store(name, val)
|
||||||
|
}
|
||||||
|
|
|
@ -1,25 +1,35 @@
|
||||||
package theme
|
package theme
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/fthvgb1/wp-go/app/theme/twentyfifteen"
|
|
||||||
"github.com/fthvgb1/wp-go/app/theme/wp"
|
"github.com/fthvgb1/wp-go/app/theme/wp"
|
||||||
|
str "github.com/fthvgb1/wp-go/helper/strings"
|
||||||
"github.com/fthvgb1/wp-go/safety"
|
"github.com/fthvgb1/wp-go/safety"
|
||||||
)
|
)
|
||||||
|
|
||||||
var themeMap = safety.NewMap[string, func(*wp.Handle)]()
|
var themeMap = safety.NewMap[string, func(*wp.Handle)]()
|
||||||
|
|
||||||
func AddThemeHookFunc(name string, fn func(handle *wp.Handle)) {
|
func AddTheme(name string, fn func(handle *wp.Handle)) {
|
||||||
if _, ok := themeMap.Load(name); ok {
|
|
||||||
panic("exists same name theme")
|
|
||||||
}
|
|
||||||
themeMap.Store(name, fn)
|
themeMap.Store(name, fn)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func DelTheme(name string) {
|
||||||
|
themeMap.Delete(name)
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetTheme(name string) (func(*wp.Handle), bool) {
|
||||||
|
return themeMap.Load(name)
|
||||||
|
}
|
||||||
|
|
||||||
|
func IsThemeHookFuncExist(name string) bool {
|
||||||
|
_, ok := themeMap.Load(name)
|
||||||
|
return ok
|
||||||
|
}
|
||||||
|
|
||||||
func Hook(themeName string, h *wp.Handle) {
|
func Hook(themeName string, h *wp.Handle) {
|
||||||
fn, ok := themeMap.Load(themeName)
|
fn, ok := themeMap.Load(themeName)
|
||||||
if ok && fn != nil {
|
if ok && fn != nil {
|
||||||
fn(h)
|
fn(h)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
twentyfifteen.Hook(h)
|
panic(str.Join("theme ", themeName, " don't exist"))
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,12 @@ import (
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
var comFn = template.FuncMap{
|
func postsFn(fn func(models.Posts) string, a models.Posts) string {
|
||||||
|
return fn(a)
|
||||||
|
}
|
||||||
|
|
||||||
|
func FuncMap() template.FuncMap {
|
||||||
|
return template.FuncMap{
|
||||||
"unescaped": func(s string) any {
|
"unescaped": func(s string) any {
|
||||||
return template.HTML(s)
|
return template.HTML(s)
|
||||||
},
|
},
|
||||||
|
@ -25,19 +30,8 @@ var comFn = template.FuncMap{
|
||||||
"exec": func(fn func() string) template.HTML {
|
"exec": func(fn func() string) template.HTML {
|
||||||
return template.HTML(fn())
|
return template.HTML(fn())
|
||||||
},
|
},
|
||||||
}
|
"callFuncString": func(fn func(string) string, s string) template.HTML {
|
||||||
|
return template.HTML(fn(s))
|
||||||
func postsFn(fn func(models.Posts) string, a models.Posts) string {
|
},
|
||||||
return fn(a)
|
|
||||||
}
|
|
||||||
|
|
||||||
func FuncMap() template.FuncMap {
|
|
||||||
return comFn
|
|
||||||
}
|
|
||||||
|
|
||||||
func addTemplateFunc(fnName string, fn any) {
|
|
||||||
if _, ok := comFn[fnName]; ok {
|
|
||||||
panic("exists same name func")
|
|
||||||
}
|
}
|
||||||
comFn[fnName] = fn
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,17 +8,17 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func InitTheme() {
|
func InitTheme() {
|
||||||
AddThemeHookFunc(twentyfifteen.ThemeName, twentyfifteen.Hook)
|
AddTheme(twentyfifteen.ThemeName, twentyfifteen.Hook)
|
||||||
AddThemeHookFunc(twentyseventeen.ThemeName, twentyseventeen.Hook)
|
AddTheme(twentyseventeen.ThemeName, twentyseventeen.Hook)
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetCurrentTemplateName() string {
|
func GetCurrentTheme() string {
|
||||||
tmlp := config.GetConfig().Theme
|
themeName := config.GetConfig().Theme
|
||||||
if tmlp == "" {
|
if themeName == "" {
|
||||||
tmlp = wpconfig.GetOption("template")
|
themeName = wpconfig.GetOption("template")
|
||||||
}
|
}
|
||||||
if !IsTemplateDirExists(tmlp) {
|
if !IsTemplateDirExists(themeName) {
|
||||||
tmlp = "twentyfifteen"
|
themeName = "twentyfifteen"
|
||||||
}
|
}
|
||||||
return tmlp
|
return themeName
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
package twentyfifteen
|
package twentyfifteen
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/fthvgb1/wp-go/app/cmd/reload"
|
|
||||||
"github.com/fthvgb1/wp-go/app/pkg/constraints"
|
"github.com/fthvgb1/wp-go/app/pkg/constraints"
|
||||||
"github.com/fthvgb1/wp-go/app/theme/wp"
|
"github.com/fthvgb1/wp-go/app/theme/wp"
|
||||||
|
"github.com/fthvgb1/wp-go/cache/reload"
|
||||||
str "github.com/fthvgb1/wp-go/helper/strings"
|
str "github.com/fthvgb1/wp-go/helper/strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -81,7 +81,7 @@ var imgStyle = `.site-header {
|
||||||
}
|
}
|
||||||
}`
|
}`
|
||||||
|
|
||||||
var header = reload.Vars(constraints.Defaults)
|
var header = reload.Vars(constraints.Defaults, "twentyfifteen-customheader")
|
||||||
|
|
||||||
func calCustomHeaderImg(h *wp.Handle) (r string, rand bool) {
|
func calCustomHeaderImg(h *wp.Handle) (r string, rand bool) {
|
||||||
img, rand := h.GetCustomHeaderImg()
|
img, rand := h.GetCustomHeaderImg()
|
||||||
|
|
|
@ -31,11 +31,7 @@
|
||||||
|
|
||||||
{{end}}
|
{{end}}
|
||||||
</div>
|
</div>
|
||||||
<footer id="colophon" class="site-footer">
|
{{template "common/colophon" .}}
|
||||||
<div class="site-info">
|
|
||||||
<a href="https://cn.wordpress.org/" class="imprint">自豪地采用WordPress</a>
|
|
||||||
</div>
|
|
||||||
</footer>
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
{{template "layout/footer" .}}
|
{{template "layout/footer" .}}
|
||||||
|
|
|
@ -52,14 +52,30 @@
|
||||||
|
|
||||||
{{ if .showComment}}
|
{{ if .showComment}}
|
||||||
<div id="comments" class="comments-area">
|
<div id="comments" class="comments-area">
|
||||||
{{ if gt .post.CommentCount 0}}
|
{{ if ne .comments ""}}
|
||||||
<h2 class="comments-title">《{{.post.PostTitle}}》上有{{.post.CommentCount}}条评论 </h2>
|
<h2 class="comments-title">《{{.post.PostTitle}}》上有{{.totalCommentNum}}条评论 </h2>
|
||||||
|
{{if gt .totalCommentPage 1}}
|
||||||
|
<nav class="navigation comment-navigation">
|
||||||
|
<h2 class="screen-reader-text">评论导航</h2>
|
||||||
|
<div class="nav-links">
|
||||||
|
{{ .commentPageNav|unescaped}}
|
||||||
|
</div><!-- .nav-links -->
|
||||||
|
</nav>
|
||||||
|
{{end}}
|
||||||
<ol class="comment-list">
|
<ol class="comment-list">
|
||||||
{{.comments|unescaped}}
|
{{.comments|unescaped}}
|
||||||
</ol>
|
</ol>
|
||||||
|
{{if gt .totalCommentPage 1}}
|
||||||
|
<nav class="navigation comment-navigation">
|
||||||
|
<h2 class="screen-reader-text">评论导航</h2>
|
||||||
|
<div class="nav-links">
|
||||||
|
{{ .commentPageNav|unescaped}}
|
||||||
|
</div><!-- .nav-links -->
|
||||||
|
</nav>
|
||||||
|
{{end}}
|
||||||
|
|
||||||
{{end}}
|
{{end}}
|
||||||
{{if and (eq .post.CommentStatus "open") (eq ( "thread_comments" |getOption ) "1")}}
|
{{if eq .post.CommentStatus "open"}}
|
||||||
<div id="respond" class="comment-respond">
|
<div id="respond" class="comment-respond">
|
||||||
<h3 id="reply-title" class="comment-reply-title">发表回复
|
<h3 id="reply-title" class="comment-reply-title">发表回复
|
||||||
<small>
|
<small>
|
||||||
|
|
|
@ -6,7 +6,7 @@ import (
|
||||||
"github.com/fthvgb1/wp-go/app/plugins"
|
"github.com/fthvgb1/wp-go/app/plugins"
|
||||||
"github.com/fthvgb1/wp-go/app/theme/wp"
|
"github.com/fthvgb1/wp-go/app/theme/wp"
|
||||||
"github.com/fthvgb1/wp-go/app/theme/wp/components"
|
"github.com/fthvgb1/wp-go/app/theme/wp/components"
|
||||||
"github.com/fthvgb1/wp-go/app/theme/wp/components/widget"
|
"github.com/fthvgb1/wp-go/app/theme/wp/middleware"
|
||||||
"github.com/fthvgb1/wp-go/app/wpconfig"
|
"github.com/fthvgb1/wp-go/app/wpconfig"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
@ -22,16 +22,13 @@ func configs(h *wp.Handle) {
|
||||||
return strings.ReplaceAll(s, `class="search-submit"`, `class="search-submit screen-reader-text"`)
|
return strings.ReplaceAll(s, `class="search-submit"`, `class="search-submit screen-reader-text"`)
|
||||||
})
|
})
|
||||||
wp.InitPipe(h)
|
wp.InitPipe(h)
|
||||||
h.PushHandler(constraints.PipeMiddleware, constraints.Home,
|
middleware.CommonMiddleware(h)
|
||||||
wp.NewHandleFn(widget.CheckCategory, 100, "widget.CheckCategory"))
|
setPaginationAndRender(h)
|
||||||
|
|
||||||
h.Index.SetPageEle(plugins.TwentyFifteenPagination())
|
|
||||||
h.PushCacheGroupHeadScript(constraints.AllScene, "CalCustomBackGround", 10.005, CalCustomBackGround)
|
h.PushCacheGroupHeadScript(constraints.AllScene, "CalCustomBackGround", 10.005, CalCustomBackGround)
|
||||||
h.PushCacheGroupHeadScript(constraints.AllScene, "colorSchemeCss", 10.0056, colorSchemeCss)
|
h.PushCacheGroupHeadScript(constraints.AllScene, "colorSchemeCss", 10.0056, colorSchemeCss)
|
||||||
h.CommonComponents()
|
h.CommonComponents()
|
||||||
components.WidgetArea(h)
|
components.WidgetArea(h)
|
||||||
wp.ReplyCommentJs(h)
|
h.PushRender(constraints.AllScene, wp.NewHandleFn(renderCustomHeader, 20.5, "renderCustomHeader"))
|
||||||
h.SetData("customHeader", customHeader(h))
|
|
||||||
wp.PushIndexHandler(constraints.PipeRender, h, wp.NewHandleFn(wp.IndexRender, 50.005, "wp.IndexRender"))
|
wp.PushIndexHandler(constraints.PipeRender, h, wp.NewHandleFn(wp.IndexRender, 50.005, "wp.IndexRender"))
|
||||||
h.PushRender(constraints.Detail, wp.NewHandleFn(wp.DetailRender, 50.005, "wp.DetailRender"))
|
h.PushRender(constraints.Detail, wp.NewHandleFn(wp.DetailRender, 50.005, "wp.DetailRender"))
|
||||||
h.PushRender(constraints.Detail, wp.NewHandleFn(postThumb, 60.005, "postThumb"))
|
h.PushRender(constraints.Detail, wp.NewHandleFn(postThumb, 60.005, "postThumb"))
|
||||||
|
@ -41,8 +38,26 @@ func configs(h *wp.Handle) {
|
||||||
h.PushRender(constraints.AllScene, wp.NewHandleFn(wp.PreTemplate, 70.005, "wp.PreTemplate"))
|
h.PushRender(constraints.AllScene, wp.NewHandleFn(wp.PreTemplate, 70.005, "wp.PreTemplate"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func setPaginationAndRender(h *wp.Handle) {
|
||||||
|
h.PushHandler(constraints.PipeRender, constraints.Detail, wp.NewHandleFn(func(hh *wp.Handle) {
|
||||||
|
d := hh.GetDetailHandle()
|
||||||
|
d.CommentRender = plugins.CommentRender()
|
||||||
|
d.CommentPageEle = plugins.TwentyFifteenCommentPagination()
|
||||||
|
}, 150, "setPaginationAndRender"))
|
||||||
|
|
||||||
|
wp.PushIndexHandler(constraints.PipeRender, h, wp.NewHandleFn(func(hh *wp.Handle) {
|
||||||
|
i := hh.GetIndexHandle()
|
||||||
|
i.SetPageEle(plugins.TwentyFifteenPagination())
|
||||||
|
}, 150, "setPaginationAndRender"))
|
||||||
|
}
|
||||||
|
|
||||||
func postThumb(h *wp.Handle) {
|
func postThumb(h *wp.Handle) {
|
||||||
if h.Detail.Post.Thumbnail.Path != "" {
|
d := h.GetDetailHandle()
|
||||||
h.Detail.Post.Thumbnail = wpconfig.Thumbnail(h.Detail.Post.Thumbnail.OriginAttachmentData, "post-thumbnail", "")
|
if d.Post.Thumbnail.Path != "" {
|
||||||
|
d.Post.Thumbnail = wpconfig.Thumbnail(d.Post.Thumbnail.OriginAttachmentData, "post-thumbnail", "")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func renderCustomHeader(h *wp.Handle) {
|
||||||
|
h.SetData("customHeader", customHeader(h))
|
||||||
|
}
|
||||||
|
|
|
@ -1,9 +0,0 @@
|
||||||
{{define "layout/colophon"}}
|
|
||||||
<footer id="colophon" class="site-footer">
|
|
||||||
<div class="wrap">
|
|
||||||
<div class="site-info">
|
|
||||||
<a href="https://cn.wordpress.org/" class="imprint">自豪地采用WordPress</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</footer>
|
|
||||||
{{end}}
|
|
|
@ -64,12 +64,21 @@
|
||||||
|
|
||||||
{{ if .showComment}}
|
{{ if .showComment}}
|
||||||
<div id="comments" class="comments-area">
|
<div id="comments" class="comments-area">
|
||||||
{{ if gt .post.CommentCount 0}}
|
{{ if ne .comments ""}}
|
||||||
<h2 class="comments-title">“{{.post.PostTitle}}”的{{.post.CommentCount}}个回复 </h2>
|
<h2 class="comments-title">“{{.post.PostTitle}}”的{{.totalCommentNum}}个回复 </h2>
|
||||||
<ol class="comment-list">
|
<ol class="comment-list">
|
||||||
{{.comments|unescaped}}
|
{{.comments|unescaped}}
|
||||||
</ol>
|
</ol>
|
||||||
|
|
||||||
|
{{if gt .totalCommentPage 1}}
|
||||||
|
<nav class="navigation comments-pagination" aria-label="评论">
|
||||||
|
<h2 class="screen-reader-text">评论导航</h2>
|
||||||
|
<div class="nav-links">
|
||||||
|
{{ .commentPageNav|unescaped}}
|
||||||
|
</div><!-- .nav-links -->
|
||||||
|
</nav>
|
||||||
|
{{end}}
|
||||||
|
|
||||||
{{end}}
|
{{end}}
|
||||||
{{if eq .post.CommentStatus "open"}}
|
{{if eq .post.CommentStatus "open"}}
|
||||||
{{template "respond" .}}
|
{{template "respond" .}}
|
||||||
|
@ -123,7 +132,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{template "layout/colophon"}}
|
{{template "common/colophon" .}}
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
@ -77,6 +77,6 @@
|
||||||
{{end}}
|
{{end}}
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
{{template "layout/colophon"}}
|
{{template "common/colophon" .}}
|
||||||
</div>
|
</div>
|
||||||
{{end}}
|
{{end}}
|
|
@ -4,56 +4,10 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/fthvgb1/wp-go/app/pkg/constraints"
|
"github.com/fthvgb1/wp-go/app/pkg/constraints"
|
||||||
"github.com/fthvgb1/wp-go/app/theme/wp"
|
"github.com/fthvgb1/wp-go/app/theme/wp"
|
||||||
"github.com/fthvgb1/wp-go/app/theme/wp/scriptloader"
|
|
||||||
"github.com/fthvgb1/wp-go/app/wpconfig"
|
"github.com/fthvgb1/wp-go/app/wpconfig"
|
||||||
"github.com/fthvgb1/wp-go/helper"
|
|
||||||
"github.com/fthvgb1/wp-go/helper/maps"
|
|
||||||
"github.com/fthvgb1/wp-go/helper/number"
|
|
||||||
str "github.com/fthvgb1/wp-go/helper/strings"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func pushScripts(h *wp.Handle) {
|
func pushScripts(h *wp.Handle) {
|
||||||
scriptloader.EnqueueStyle("twentyseventeen-style", scriptloader.GetStylesheetUri(), nil, "20230328", "")
|
|
||||||
scriptloader.EnqueueStyles("twentyseventeen-block-style", "/assets/css/blocks.css", []string{"twentyseventeen-style"}, "20220912", "")
|
|
||||||
|
|
||||||
if "dark" == wpconfig.GetThemeModsVal(ThemeName, "colorscheme", "light") {
|
|
||||||
scriptloader.EnqueueStyles("twentyseventeen-colors-dark", "/assets/css/colors-dark.css",
|
|
||||||
[]string{"twentyseventeen-style"}, "20191025", "")
|
|
||||||
}
|
|
||||||
|
|
||||||
scriptloader.AddScriptData("twentyseventeen-ie8", "conditional", "lt IE 9")
|
|
||||||
scriptloader.EnqueueScripts("html5", "/assets/js/html5.js", nil, "20161020", false)
|
|
||||||
scriptloader.AddScriptData("html5", "conditional", "lt IE 9")
|
|
||||||
|
|
||||||
scriptloader.EnqueueScripts("twentyseventeen-skip-link-focus-fix", "/assets/js/skip-link-focus-fix.js",
|
|
||||||
nil, "20161114", true)
|
|
||||||
|
|
||||||
l10n := map[string]any{
|
|
||||||
"quote": svg(h, map[string]string{"icon": "quote-right"}),
|
|
||||||
}
|
|
||||||
|
|
||||||
scriptloader.EnqueueScripts("twentyseventeen-global", "/assets/js/global.js",
|
|
||||||
[]string{"jquery"}, "20211130", true)
|
|
||||||
|
|
||||||
scriptloader.EnqueueScripts("jquery-scrollto", "/assets/js/jquery.scrollTo.js",
|
|
||||||
[]string{"jquery"}, "2.1.3", true)
|
|
||||||
scriptloader.EnqueueScripts("comment-reply", "", nil, "", false)
|
|
||||||
|
|
||||||
//todo menu top
|
|
||||||
|
|
||||||
scriptloader.AddStaticLocalize("twentyseventeen-skip-link-focus-fix", "twentyseventeenScreenReaderText", l10n)
|
|
||||||
scriptloader.AddStaticLocalize("wp-custom-header", "_wpCustomHeaderSettings", map[string]any{
|
|
||||||
"mimeType": `video/mp4`,
|
|
||||||
"posterUrl": `/wp-content/uploads/2023/01/cropped-wallhaven-9dm7dd-1.png`,
|
|
||||||
"videoUrl": `/wp-content/uploads/2023/06/BloodMoon_GettyRM_495644264_1080_HD_ZH-CN.mp4`,
|
|
||||||
"width": `2000`,
|
|
||||||
"height": `1199`,
|
|
||||||
"minWidth": `900`,
|
|
||||||
"minHeight": `500`,
|
|
||||||
"l10n": map[string]any{
|
|
||||||
"pause": `<span class="screen-reader-text">暂停背景视频</span><svg class="icon icon-pause" aria-hidden="true" role="img"> <use href="#icon-pause" xlink:href="#icon-pause"></use> </svg>`, "play": `<span class="screen-reader-text">播放背景视频</span><svg class="icon icon-play" aria-hidden="true" role="img"> <use href="#icon-play" xlink:href="#icon-play"></use> </svg>`, "pauseSpeak": `视频已暂停。`, "playSpeak": `视频正在播放。`,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
h.PushCacheGroupHeadScript(constraints.AllScene, "{theme}.head", 30, func(h *wp.Handle) string {
|
h.PushCacheGroupHeadScript(constraints.AllScene, "{theme}.head", 30, func(h *wp.Handle) string {
|
||||||
head := headScript
|
head := headScript
|
||||||
if "dark" == wpconfig.GetThemeModsVal(ThemeName, "colorscheme", "light") {
|
if "dark" == wpconfig.GetThemeModsVal(ThemeName, "colorscheme", "light") {
|
||||||
|
@ -87,37 +41,3 @@ var footerScript = `<script id="twentyseventeen-skip-link-focus-fix-js-extra">
|
||||||
<script src="/wp-content/themes/twentyseventeen/assets/js/skip-link-focus-fix.js?ver=20161114" id="twentyseventeen-skip-link-focus-fix-js"></script>
|
<script src="/wp-content/themes/twentyseventeen/assets/js/skip-link-focus-fix.js?ver=20161114" id="twentyseventeen-skip-link-focus-fix-js"></script>
|
||||||
<script src="/wp-content/themes/twentyseventeen/assets/js/global.js?ver=20211130" id="twentyseventeen-global-js"></script>
|
<script src="/wp-content/themes/twentyseventeen/assets/js/global.js?ver=20211130" id="twentyseventeen-global-js"></script>
|
||||||
<script src="/wp-content/themes/twentyseventeen/assets/js/jquery.scrollTo.js?ver=2.1.3" id="jquery-scrollto-js"></script>`
|
<script src="/wp-content/themes/twentyseventeen/assets/js/jquery.scrollTo.js?ver=2.1.3" id="jquery-scrollto-js"></script>`
|
||||||
|
|
||||||
func svg(h *wp.Handle, m map[string]string) string {
|
|
||||||
if !maps.IsExists(m, "icon") {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
ariaHidden := ` aria-hidden="true"`
|
|
||||||
ariaLabelledby := ""
|
|
||||||
uniqueId := ""
|
|
||||||
if m["title"] != "" {
|
|
||||||
ariaHidden = ""
|
|
||||||
id := helper.GetContextVal(h.C, "svg", 0)
|
|
||||||
uniqueId = number.IntToString(id)
|
|
||||||
id++
|
|
||||||
h.C.Set("svg", id)
|
|
||||||
ariaLabelledby = str.Join(" aria-labelledby=\"title-", uniqueId, "\"")
|
|
||||||
if m["desc"] != "" {
|
|
||||||
ariaLabelledby = str.Join(" aria-labelledby=\"title-", uniqueId, " desc-", uniqueId, "\"")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
s := str.NewBuilder()
|
|
||||||
s.WriteString("<svg class=\"icon icon-", m["icon"], "\"", ariaHidden, ariaLabelledby, " role=\"img\">")
|
|
||||||
if m["title"] != "" {
|
|
||||||
s.WriteString(`<title id="title-`, uniqueId, `">`, m["title"], "</title>")
|
|
||||||
if m["desc"] != "" {
|
|
||||||
s.WriteString(`<desc id="desc-`, uniqueId, `">`, m["desc"], `</desc>`)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
s.WriteString(` <use href="#icon-`, m["icon"], `" xlink:href="#icon-`, m["icon"], `"></use> `)
|
|
||||||
if m["fallback"] != "" {
|
|
||||||
s.WriteString(`<span class="svg-fallback icon-' . esc_attr( $args['icon'] ) . '"></span>`)
|
|
||||||
}
|
|
||||||
s.WriteString(`<span class="svg-fallback icon-`, m["icon"], `"></span></svg>`)
|
|
||||||
return s.String()
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
package twentyseventeen
|
package twentyseventeen
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/fthvgb1/wp-go/app/cmd/reload"
|
|
||||||
"github.com/fthvgb1/wp-go/app/pkg/constraints"
|
"github.com/fthvgb1/wp-go/app/pkg/constraints"
|
||||||
"github.com/fthvgb1/wp-go/app/pkg/constraints/widgets"
|
"github.com/fthvgb1/wp-go/app/pkg/constraints/widgets"
|
||||||
"github.com/fthvgb1/wp-go/app/pkg/logs"
|
"github.com/fthvgb1/wp-go/app/pkg/logs"
|
||||||
|
@ -10,11 +10,12 @@ import (
|
||||||
"github.com/fthvgb1/wp-go/app/plugins"
|
"github.com/fthvgb1/wp-go/app/plugins"
|
||||||
"github.com/fthvgb1/wp-go/app/theme/wp"
|
"github.com/fthvgb1/wp-go/app/theme/wp"
|
||||||
"github.com/fthvgb1/wp-go/app/theme/wp/components"
|
"github.com/fthvgb1/wp-go/app/theme/wp/components"
|
||||||
"github.com/fthvgb1/wp-go/app/theme/wp/components/widget"
|
"github.com/fthvgb1/wp-go/app/theme/wp/middleware"
|
||||||
"github.com/fthvgb1/wp-go/app/wpconfig"
|
"github.com/fthvgb1/wp-go/app/wpconfig"
|
||||||
|
"github.com/fthvgb1/wp-go/cache/reload"
|
||||||
"github.com/fthvgb1/wp-go/helper"
|
"github.com/fthvgb1/wp-go/helper"
|
||||||
str "github.com/fthvgb1/wp-go/helper/strings"
|
str "github.com/fthvgb1/wp-go/helper/strings"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/fthvgb1/wp-go/plugin/pagination"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -27,23 +28,33 @@ var paginate = func() plugins.PageEle {
|
||||||
p.NextEle = strings.Replace(p.NextEle, "下一页", `<span class="screen-reader-text">下一页</span>
|
p.NextEle = strings.Replace(p.NextEle, "下一页", `<span class="screen-reader-text">下一页</span>
|
||||||
<svg class="icon icon-arrow-right" aria-hidden="true" role="img"> <use href="#icon-arrow-right" xlink:href="#icon-arrow-right"></use>
|
<svg class="icon icon-arrow-right" aria-hidden="true" role="img"> <use href="#icon-arrow-right" xlink:href="#icon-arrow-right"></use>
|
||||||
</svg>`, 1)
|
</svg>`, 1)
|
||||||
|
commentPageEle = plugins.PaginationNav{
|
||||||
|
Currents: p.Current,
|
||||||
|
Prevs: p.Prev,
|
||||||
|
Nexts: p.Next,
|
||||||
|
Dotss: p.Dots,
|
||||||
|
Middles: p.Middle,
|
||||||
|
Urlss: plugins.TwentyFifteenCommentPagination().Urls,
|
||||||
|
}
|
||||||
|
|
||||||
return p
|
return p
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
var commentPageEle pagination.Render
|
||||||
|
|
||||||
func Hook(h *wp.Handle) {
|
func Hook(h *wp.Handle) {
|
||||||
wp.Run(h, configs)
|
wp.Run(h, configs)
|
||||||
}
|
}
|
||||||
|
|
||||||
func configs(h *wp.Handle) {
|
func configs(h *wp.Handle) {
|
||||||
wp.InitPipe(h)
|
wp.InitPipe(h)
|
||||||
h.PushHandler(constraints.PipeMiddleware, constraints.Home,
|
middleware.CommonMiddleware(h)
|
||||||
wp.NewHandleFn(widget.CheckCategory, 100.006, "widget.CheckCategory"))
|
|
||||||
h.AddActionFilter("bodyClass", calClass)
|
h.AddActionFilter("bodyClass", calClass)
|
||||||
h.PushCacheGroupHeadScript(constraints.AllScene, "colorScheme-customHeader", 10, colorScheme, customHeader)
|
h.PushCacheGroupHeadScript(constraints.AllScene, "colorScheme-customHeader", 10, colorScheme, customHeader)
|
||||||
components.WidgetArea(h)
|
components.WidgetArea(h)
|
||||||
pushScripts(h)
|
pushScripts(h)
|
||||||
h.PushRender(constraints.AllStats, wp.NewHandleFn(calCustomHeader, 10.005, "calCustomHeader"))
|
h.PushRender(constraints.AllStats, wp.NewHandleFn(calCustomHeader, 10.005, "calCustomHeader"))
|
||||||
wp.SetComponentsArgs(h, widgets.Widget, map[string]string{
|
wp.SetComponentsArgs(widgets.Widget, map[string]string{
|
||||||
"{$before_widget}": `<section id="%s" class="%s">`,
|
"{$before_widget}": `<section id="%s" class="%s">`,
|
||||||
"{$after_widget}": `</section>`,
|
"{$after_widget}": `</section>`,
|
||||||
})
|
})
|
||||||
|
@ -52,12 +63,11 @@ func configs(h *wp.Handle) {
|
||||||
wp.NewHandleFn(errorsHandle, 80.005, "errorsHandle"),
|
wp.NewHandleFn(errorsHandle, 80.005, "errorsHandle"),
|
||||||
)
|
)
|
||||||
videoHeader(h)
|
videoHeader(h)
|
||||||
h.Detail.CommentRender = commentFormat
|
h.SetData("colophon", colophon)
|
||||||
|
setPaginationAndRender(h)
|
||||||
h.CommonComponents()
|
h.CommonComponents()
|
||||||
h.Index.SetPageEle(paginate)
|
|
||||||
wp.ReplyCommentJs(h)
|
|
||||||
h.PushPostPlugin(postThumbnail)
|
h.PushPostPlugin(postThumbnail)
|
||||||
wp.SetComponentsArgsForMap(h, widgets.Search, "{$form}", searchForm)
|
wp.SetComponentsArgsForMap(widgets.Search, "{$form}", searchForm)
|
||||||
wp.PushIndexHandler(constraints.PipeRender, h, wp.NewHandleFn(wp.IndexRender, 10.005, "wp.IndexRender"))
|
wp.PushIndexHandler(constraints.PipeRender, h, wp.NewHandleFn(wp.IndexRender, 10.005, "wp.IndexRender"))
|
||||||
h.PushRender(constraints.Detail, wp.NewHandleFn(wp.DetailRender, 10.005, "wp.DetailRender"))
|
h.PushRender(constraints.Detail, wp.NewHandleFn(wp.DetailRender, 10.005, "wp.DetailRender"))
|
||||||
h.PushDataHandler(constraints.Detail, wp.NewHandleFn(wp.Detail, 100.005, "wp.Detail"), wp.NewHandleFn(postThumb, 90.005, "{theme}.postThumb"))
|
h.PushDataHandler(constraints.Detail, wp.NewHandleFn(wp.Detail, 100.005, "wp.Detail"), wp.NewHandleFn(postThumb, 90.005, "{theme}.postThumb"))
|
||||||
|
@ -65,6 +75,19 @@ func configs(h *wp.Handle) {
|
||||||
h.PushDataHandler(constraints.AllScene, wp.NewHandleFn(wp.PreCodeAndStats, 90.005, "wp.PreCodeAndStats"))
|
h.PushDataHandler(constraints.AllScene, wp.NewHandleFn(wp.PreCodeAndStats, 90.005, "wp.PreCodeAndStats"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func setPaginationAndRender(h *wp.Handle) {
|
||||||
|
h.PushHandler(constraints.PipeRender, constraints.Detail, wp.NewHandleFn(func(hh *wp.Handle) {
|
||||||
|
d := hh.GetDetailHandle()
|
||||||
|
d.CommentRender = commentFormat
|
||||||
|
d.CommentPageEle = commentPageEle
|
||||||
|
d.CommentStep = 2
|
||||||
|
}, 150, "setPaginationAndRender"))
|
||||||
|
wp.PushIndexHandler(constraints.PipeRender, h, wp.NewHandleFn(func(hh *wp.Handle) {
|
||||||
|
i := hh.GetIndexHandle()
|
||||||
|
i.SetPageEle(paginate)
|
||||||
|
}, 150, "setPaginationAndRender"))
|
||||||
|
}
|
||||||
|
|
||||||
var searchForm = `<form role="search" method="get" class="search-form" action="/">
|
var searchForm = `<form role="search" method="get" class="search-form" action="/">
|
||||||
<label for="search-form-1">
|
<label for="search-form-1">
|
||||||
<span class="screen-reader-text">{$label}:</span>
|
<span class="screen-reader-text">{$label}:</span>
|
||||||
|
@ -85,7 +108,7 @@ func errorsHandle(h *wp.Handle) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func postThumb(h *wp.Handle) {
|
func postThumb(h *wp.Handle) {
|
||||||
d := h.Detail
|
d := h.GetDetailHandle()
|
||||||
if d.Post.Thumbnail.Path != "" {
|
if d.Post.Thumbnail.Path != "" {
|
||||||
img := wpconfig.Thumbnail(d.Post.Thumbnail.OriginAttachmentData, "full", "", "thumbnail", "post-thumbnail")
|
img := wpconfig.Thumbnail(d.Post.Thumbnail.OriginAttachmentData, "full", "", "thumbnail", "post-thumbnail")
|
||||||
img.Sizes = "100vw"
|
img.Sizes = "100vw"
|
||||||
|
@ -100,20 +123,28 @@ type comment struct {
|
||||||
plugins.CommonCommentFormat
|
plugins.CommonCommentFormat
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c comment) FormatLi(ctx *gin.Context, m models.Comments, depth int, isTls bool, eo, parent string) string {
|
var commentLi = plugins.CommonLi()
|
||||||
templ := plugins.CommonLi()
|
|
||||||
templ = strings.ReplaceAll(templ, `<a rel="nofollow" class="comment-reply-link"
|
var respondFn = plugins.Responds(respondStr)
|
||||||
href="/p/{{PostId}}?replytocom={{CommentId}}#respond" data-commentid="{{CommentId}}" data-postid="{{PostId}}"
|
|
||||||
data-belowelement="div-comment-{{CommentId}}" data-respondelement="respond"
|
func (c comment) FormatLi(_ context.Context, m models.Comments, depth, maxDepth, page int, isTls, isThreadComments bool, eo, parent string) string {
|
||||||
data-replyto="回复给{{CommentAuthor}}"
|
return plugins.FormatLi(commentLi, m, respondFn, depth, maxDepth, page, isTls, isThreadComments, eo, parent)
|
||||||
aria-label="回复给{{CommentAuthor}}">回复</a>`, `<a rel="nofollow" class="comment-reply-link"
|
|
||||||
href="/p/{{PostId}}?replytocom={{CommentId}}#respond" data-commentid="{{CommentId}}" data-postid="{{PostId}}"
|
|
||||||
data-belowelement="div-comment-{{CommentId}}" data-respondelement="respond"
|
|
||||||
data-replyto="回复给{{CommentAuthor}}"
|
|
||||||
aria-label="回复给{{CommentAuthor}}"><svg class="icon icon-mail-reply" aria-hidden="true" role="img"> <use href="#icon-mail-reply" xlink:href="#icon-mail-reply"></use> </svg>回复</a>`)
|
|
||||||
return plugins.FormatLi(templ, ctx, m, depth, isTls, eo, parent)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var colophon = `<footer id="colophon" class="site-footer">
|
||||||
|
<div class="wrap">
|
||||||
|
<div class="site-info">
|
||||||
|
<a href="https://github.com/fthvgb1/wp-go" class="imprint">自豪地采用 wp-go</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</footer>`
|
||||||
|
|
||||||
|
var respondStr = `<a rel="nofollow" class="comment-reply-link"
|
||||||
|
href="/p/{{PostId}}?replytocom={{CommentId}}#respond" data-commentid="{{CommentId}}" data-postid="{{PostId}}"
|
||||||
|
data-belowelement="div-comment-{{CommentId}}" data-respondelement="respond"
|
||||||
|
data-replyto="回复给{{CommentAuthor}}"
|
||||||
|
aria-label="回复给{{CommentAuthor}}"><svg class="icon icon-mail-reply" aria-hidden="true" role="img"> <use href="#icon-mail-reply" xlink:href="#icon-mail-reply"></use> </svg>回复</a>`
|
||||||
|
|
||||||
func postThumbnail(h *wp.Handle, posts *models.Posts) {
|
func postThumbnail(h *wp.Handle, posts *models.Posts) {
|
||||||
if posts.Thumbnail.Path != "" {
|
if posts.Thumbnail.Path != "" {
|
||||||
posts.Thumbnail.Sizes = "(max-width: 767px) 89vw, (max-width: 1000px) 54vw, (max-width: 1071px) 543px, 580px"
|
posts.Thumbnail.Sizes = "(max-width: 767px) 89vw, (max-width: 1000px) 54vw, (max-width: 1071px) 543px, 580px"
|
||||||
|
@ -123,7 +154,7 @@ func postThumbnail(h *wp.Handle, posts *models.Posts) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var header = reload.Vars(models.PostThumbnail{})
|
var header = reload.Vars(models.PostThumbnail{}, "twentyseventeen-headerImage")
|
||||||
|
|
||||||
func calCustomHeader(h *wp.Handle) {
|
func calCustomHeader(h *wp.Handle) {
|
||||||
h.SetData("HeaderImage", getHeaderImage(h))
|
h.SetData("HeaderImage", getHeaderImage(h))
|
||||||
|
|
|
@ -33,14 +33,14 @@ func (h *Handle) BodyClass() string {
|
||||||
|
|
||||||
case constraints.Search:
|
case constraints.Search:
|
||||||
s := "search-no-results"
|
s := "search-no-results"
|
||||||
if len(h.Index.Posts) > 0 {
|
if len(h.GetIndexHandle().Posts) > 0 {
|
||||||
s = "search-results"
|
s = "search-results"
|
||||||
}
|
}
|
||||||
class = append(class, "search", s)
|
class = append(class, "search", s)
|
||||||
|
|
||||||
case constraints.Category, constraints.Tag:
|
case constraints.Category, constraints.Tag:
|
||||||
class = append(class, "archive", "category")
|
class = append(class, "archive", "category")
|
||||||
cat := h.Index.Param.Category
|
cat := h.GetIndexHandle().Param.Category
|
||||||
if cat == "" {
|
if cat == "" {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
@ -54,16 +54,16 @@ func (h *Handle) BodyClass() string {
|
||||||
|
|
||||||
case constraints.Author:
|
case constraints.Author:
|
||||||
class = append(class, "archive", "author")
|
class = append(class, "archive", "author")
|
||||||
author := h.Index.Param.Author
|
author := h.GetIndexHandle().Param.Author
|
||||||
user, _ := cache.GetUserByName(h.C, author)
|
user, _ := cache.GetUserByName(h.C, author)
|
||||||
class = append(class, str.Join("author-", number.IntToString(user.Id)))
|
class = append(class, str.Join("author-", number.IntToString(user.Id)))
|
||||||
if user.UserLogin[0] != '%' {
|
if user.DisplayName[0] != '%' {
|
||||||
class = append(class, str.Join("author-", user.UserLogin))
|
class = append(class, str.Join("author-", user.DisplayName))
|
||||||
}
|
}
|
||||||
|
|
||||||
case constraints.Detail:
|
case constraints.Detail:
|
||||||
class = append(class, "post-template-default", "single", "single-post")
|
class = append(class, "post-template-default", "single", "single-post")
|
||||||
class = append(class, str.Join("postid-", number.IntToString(h.Detail.Post.Id)))
|
class = append(class, str.Join("postid-", number.IntToString(h.GetDetailHandle().Post.Id)))
|
||||||
if len(h.themeMods.ThemeSupport.PostFormats) > 0 {
|
if len(h.themeMods.ThemeSupport.PostFormats) > 0 {
|
||||||
class = append(class, "single-format-standard")
|
class = append(class, "single-format-standard")
|
||||||
}
|
}
|
||||||
|
|
126
app/theme/wp/comments.go
Normal file
126
app/theme/wp/comments.go
Normal file
|
@ -0,0 +1,126 @@
|
||||||
|
package wp
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"github.com/fthvgb1/wp-go/app/pkg/models"
|
||||||
|
"github.com/fthvgb1/wp-go/app/plugins"
|
||||||
|
"github.com/fthvgb1/wp-go/app/wpconfig"
|
||||||
|
"github.com/fthvgb1/wp-go/cache"
|
||||||
|
"github.com/fthvgb1/wp-go/cache/cachemanager"
|
||||||
|
"github.com/fthvgb1/wp-go/helper/slice"
|
||||||
|
str "github.com/fthvgb1/wp-go/helper/strings"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func RenderComment(ctx context.Context, page int, render plugins.CommentHtml, ids []uint64, timeout time.Duration, isTLS bool) (string, error) {
|
||||||
|
ca, _ := cachemanager.GetMapCache[uint64, models.Comments]("postCommentData")
|
||||||
|
children, _ := cachemanager.GetMapCache[uint64, []uint64]("commentChildren")
|
||||||
|
h := CommentHandle{
|
||||||
|
maxDepth: str.ToInteger(wpconfig.GetOption("thread_comments_depth"), 5),
|
||||||
|
depth: 1,
|
||||||
|
isTls: isTLS,
|
||||||
|
html: render,
|
||||||
|
order: wpconfig.GetOption("comment_order"),
|
||||||
|
ca: ca,
|
||||||
|
children: children,
|
||||||
|
threadComments: wpconfig.GetOption("thread_comments") == "1",
|
||||||
|
page: page,
|
||||||
|
}
|
||||||
|
return h.formatComments(ctx, ids, timeout)
|
||||||
|
}
|
||||||
|
|
||||||
|
type CommentHandle struct {
|
||||||
|
maxDepth int
|
||||||
|
depth int
|
||||||
|
isTls bool
|
||||||
|
html plugins.CommentHtml
|
||||||
|
order string
|
||||||
|
page int
|
||||||
|
ca *cache.MapCache[uint64, models.Comments]
|
||||||
|
children *cache.MapCache[uint64, []uint64]
|
||||||
|
threadComments bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c CommentHandle) findGrandchildComments(ctx context.Context, timeout time.Duration, comments []models.Comments) ([]models.Comments, error) {
|
||||||
|
parentIds := slice.Map(comments, func(t models.Comments) uint64 {
|
||||||
|
return t.CommentId
|
||||||
|
})
|
||||||
|
children, err := c.children.GetCacheBatch(ctx, parentIds, timeout)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
rr := slice.FilterAndMap(children, func(t []uint64) ([]uint64, bool) {
|
||||||
|
return t, len(t) > 0
|
||||||
|
})
|
||||||
|
if len(rr) < 1 {
|
||||||
|
return comments, nil
|
||||||
|
}
|
||||||
|
ids := slice.Decompress(rr)
|
||||||
|
r, err := c.ca.GetCacheBatch(ctx, ids, timeout)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
rrr, err := c.findGrandchildComments(ctx, timeout, r)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
comments = append(comments, rrr...)
|
||||||
|
slice.Sort(comments, func(i, j models.Comments) bool {
|
||||||
|
return c.html.FloorOrder(i, j)
|
||||||
|
})
|
||||||
|
return comments, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c CommentHandle) formatComments(ctx context.Context, ids []uint64, timeout time.Duration) (html string, err error) {
|
||||||
|
comments, err := c.ca.GetCacheBatch(ctx, ids, timeout)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
if c.depth > 1 && c.depth < c.maxDepth {
|
||||||
|
slice.Sort(comments, func(i, j models.Comments) bool {
|
||||||
|
return c.html.FloorOrder(i, j)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
fixChildren := false
|
||||||
|
if c.depth >= c.maxDepth {
|
||||||
|
comments, err = c.findGrandchildComments(ctx, timeout, comments)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
fixChildren = true
|
||||||
|
}
|
||||||
|
s := str.NewBuilder()
|
||||||
|
for i, comment := range comments {
|
||||||
|
eo := "even"
|
||||||
|
if (i+1)%2 == 0 {
|
||||||
|
eo = "odd"
|
||||||
|
}
|
||||||
|
parent := ""
|
||||||
|
fl := false
|
||||||
|
var children []uint64
|
||||||
|
if !fixChildren {
|
||||||
|
children, err = c.children.GetCache(ctx, comment.CommentId, timeout)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if c.threadComments && len(children) > 0 && c.depth < c.maxDepth+1 {
|
||||||
|
parent = "parent"
|
||||||
|
fl = true
|
||||||
|
}
|
||||||
|
s.WriteString(c.html.FormatLi(ctx, comment, c.depth, c.maxDepth, c.page, c.isTls, c.threadComments, eo, parent))
|
||||||
|
if fl {
|
||||||
|
c.depth++
|
||||||
|
ss, err := c.formatComments(ctx, children, timeout)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
s.WriteString(`<ol class="children">`, ss, `</ol>`)
|
||||||
|
c.depth--
|
||||||
|
}
|
||||||
|
s.WriteString("</li><!-- #comment-## -->")
|
||||||
|
}
|
||||||
|
|
||||||
|
html = s.String()
|
||||||
|
return
|
||||||
|
}
|
|
@ -1,62 +1,103 @@
|
||||||
package wp
|
package wp
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/fthvgb1/wp-go/app/cmd/reload"
|
|
||||||
"github.com/fthvgb1/wp-go/app/pkg/constraints"
|
"github.com/fthvgb1/wp-go/app/pkg/constraints"
|
||||||
|
"github.com/fthvgb1/wp-go/cache/reload"
|
||||||
"github.com/fthvgb1/wp-go/helper/maps"
|
"github.com/fthvgb1/wp-go/helper/maps"
|
||||||
"github.com/fthvgb1/wp-go/helper/slice"
|
"github.com/fthvgb1/wp-go/helper/slice"
|
||||||
str "github.com/fthvgb1/wp-go/helper/strings"
|
str "github.com/fthvgb1/wp-go/helper/strings"
|
||||||
|
"github.com/fthvgb1/wp-go/safety"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (h *Handle) DeleteComponents(scene, name string) {
|
var handleComponents = safety.NewMap[string, map[string][]Components[string]]()
|
||||||
h.componentHook[scene] = append(h.componentHook[scene], func(c Components[string]) (Components[string], bool) {
|
var handleComponentHook = safety.NewMap[string, map[string][]func(Components[string]) (Components[string], bool)]()
|
||||||
return c, c.Name != name
|
|
||||||
|
var componentsArgs = safety.NewMap[string, any]()
|
||||||
|
var componentFilterFns = safety.NewMap[string, []func(*Handle, string, ...any) string]()
|
||||||
|
|
||||||
|
func (h *Handle) DeleteComponents(scene, componentKey, componentName string) {
|
||||||
|
v, ok := handleComponentHook.Load(scene)
|
||||||
|
if !ok {
|
||||||
|
v = make(map[string][]func(Components[string]) (Components[string], bool))
|
||||||
|
}
|
||||||
|
|
||||||
|
v[componentKey] = append(v[componentKey], func(c Components[string]) (Components[string], bool) {
|
||||||
|
return c, c.Name != componentName
|
||||||
})
|
})
|
||||||
|
handleComponentHook.Store(scene, v)
|
||||||
}
|
}
|
||||||
func (h *Handle) ReplaceComponents(scene, name string, components Components[string]) {
|
func (h *Handle) ReplaceComponents(scene, componentKey, componentName string, components Components[string]) {
|
||||||
h.componentHook[scene] = append(h.componentHook[scene], func(c Components[string]) (Components[string], bool) {
|
v, ok := handleComponentHook.Load(scene)
|
||||||
if c.Name == name {
|
if !ok {
|
||||||
|
v = make(map[string][]func(Components[string]) (Components[string], bool))
|
||||||
|
}
|
||||||
|
v[componentKey] = append(v[componentKey], func(c Components[string]) (Components[string], bool) {
|
||||||
|
if c.Name == componentName {
|
||||||
c = components
|
c = components
|
||||||
}
|
}
|
||||||
return c, true
|
return c, true
|
||||||
})
|
})
|
||||||
|
handleComponentHook.Store(scene, v)
|
||||||
}
|
}
|
||||||
func (h *Handle) HookComponents(scene string, fn func(Components[string]) (Components[string], bool)) {
|
func (h *Handle) PushComponentHooks(scene, componentKey string, fn func(Components[string]) (Components[string], bool)) {
|
||||||
h.componentHook[scene] = append(h.componentHook[scene], fn)
|
v, ok := handleComponentHook.Load(scene)
|
||||||
|
if !ok {
|
||||||
|
v = make(map[string][]func(Components[string]) (Components[string], bool))
|
||||||
|
}
|
||||||
|
v[componentKey] = append(v[componentKey], fn)
|
||||||
|
handleComponentHook.Store(scene, v)
|
||||||
}
|
}
|
||||||
|
|
||||||
func CalComponents(h *Handle) {
|
var GetAndHookComponents = reload.BuildMapFnWithAnyParams[string]("calComponents", HookComponent)
|
||||||
componentss := reload.GetAnyValMapBy("scene-components", str.Join("allScene-", h.scene), h, func(h *Handle) map[string][]Components[string] {
|
|
||||||
return maps.MergeBy(func(k string, v1, v2 []Components[string]) ([]Components[string], bool) {
|
func HookComponent(a ...any) []Components[string] {
|
||||||
vv := append(v1, v2...)
|
componentKey := a[0].(string)
|
||||||
return vv, vv != nil
|
scene := a[1].(string)
|
||||||
}, nil, h.components[h.scene], h.components[constraints.AllScene])
|
mut := reload.GetGlobeMutex()
|
||||||
})
|
mut.Lock()
|
||||||
for k, components := range componentss {
|
defer mut.Unlock()
|
||||||
key := str.Join("calComponents-", h.scene, "-", k)
|
components := GetComponents(scene, componentKey)
|
||||||
ss := reload.GetAnyValMapBy("calComponents", key, h, func(h *Handle) []Components[string] {
|
r := slice.FilterAndMap(components, func(component Components[string]) (Components[string], bool) {
|
||||||
r := slice.FilterAndMap(components, func(t Components[string]) (Components[string], bool) {
|
keyHooks, ok := handleComponentHook.Load(scene)
|
||||||
fns, ok := h.componentHook[k]
|
|
||||||
if !ok {
|
if !ok {
|
||||||
return t, true
|
return component, true
|
||||||
}
|
}
|
||||||
for _, fn := range fns {
|
hooks := keyHooks[componentKey]
|
||||||
c, ok := fn(t)
|
for _, fn := range hooks {
|
||||||
if !ok {
|
hookedComponent, ok := fn(component)
|
||||||
return c, false
|
if !ok { // DeleteComponents fn
|
||||||
|
return hookedComponent, false
|
||||||
}
|
}
|
||||||
t = c
|
component = hookedComponent // ReplaceComponents fn
|
||||||
}
|
}
|
||||||
return t, true
|
return component, true
|
||||||
})
|
})
|
||||||
slice.Sort(r, func(i, j Components[string]) bool {
|
slice.SimpleSort(r, slice.DESC, func(t Components[string]) float64 {
|
||||||
return i.Order > j.Order
|
return t.Order
|
||||||
})
|
})
|
||||||
return r
|
return r
|
||||||
})
|
}
|
||||||
var s = make([]string, 0, len(ss))
|
|
||||||
for _, component := range ss {
|
func GetComponents(scene, key string) (r []Components[string]) {
|
||||||
|
sceneComponents, _ := handleComponents.Load(scene)
|
||||||
|
allSceneComponents, _ := handleComponents.Load(constraints.AllScene)
|
||||||
|
r = append(sceneComponents[key], allSceneComponents[key]...)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var CacheComponent = reload.BuildMapFnWithAnyParams[string]("cacheComponents", cacheComponentFn)
|
||||||
|
|
||||||
|
func cacheComponentFn(a ...any) string {
|
||||||
|
return a[0].(Components[string]).Fn(a[1].(*Handle))
|
||||||
|
}
|
||||||
|
|
||||||
|
func CalComponent(h *Handle) func(string) string {
|
||||||
|
return func(componentKey string) string {
|
||||||
|
cacheKey := str.Join("get-hook-Components-", h.scene, "-", componentKey)
|
||||||
|
hookedComponents := GetAndHookComponents(cacheKey, componentKey, h.scene)
|
||||||
|
var s = make([]string, 0, len(hookedComponents))
|
||||||
|
for _, component := range hookedComponents {
|
||||||
if component.Val != "" {
|
if component.Val != "" {
|
||||||
s = append(s, component.Val)
|
s = append(s, component.Val)
|
||||||
continue
|
continue
|
||||||
|
@ -64,7 +105,8 @@ func CalComponents(h *Handle) {
|
||||||
if component.Fn != nil {
|
if component.Fn != nil {
|
||||||
v := ""
|
v := ""
|
||||||
if component.Cached {
|
if component.Cached {
|
||||||
v = reload.GetAnyValMapBy("cacheComponents", component.Name, h, component.Fn)
|
key := str.Join(h.scene, "-", componentKey, "-", component.Name)
|
||||||
|
v = CacheComponent(key, component, h)
|
||||||
} else {
|
} else {
|
||||||
v = component.Fn(h)
|
v = component.Fn(h)
|
||||||
}
|
}
|
||||||
|
@ -73,17 +115,17 @@ func CalComponents(h *Handle) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
h.ginH[k] = strings.Join(s, "\n")
|
return strings.Join(s, "\n")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *Handle) PushComponents(scene, componentType string, components ...Components[string]) {
|
func (h *Handle) PushComponents(scene, componentType string, components ...Components[string]) {
|
||||||
c, ok := h.components[scene]
|
c, ok := handleComponents.Load(scene)
|
||||||
if !ok {
|
if !ok {
|
||||||
c = make(map[string][]Components[string])
|
c = make(map[string][]Components[string])
|
||||||
h.components[scene] = c
|
|
||||||
}
|
}
|
||||||
c[componentType] = append(c[componentType], components...)
|
c[componentType] = append(c[componentType], components...)
|
||||||
|
handleComponents.Store(scene, c)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *Handle) PushGroupComponentStr(scene, componentType, name string, order float64, strs ...string) {
|
func (h *Handle) PushGroupComponentStr(scene, componentType, name string, order float64, strs ...string) {
|
||||||
|
@ -139,8 +181,8 @@ func (h *Handle) PushGroupHeadScript(scene, name string, order float64, str ...s
|
||||||
h.PushGroupComponentStr(scene, constraints.HeadScript, name, order, str...)
|
h.PushGroupComponentStr(scene, constraints.HeadScript, name, order, str...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetComponentsArgs[T any](h *Handle, k string, defaults T) T {
|
func GetComponentsArgs[T any](k string, defaults T) T {
|
||||||
v, ok := h.componentsArgs[k]
|
v, ok := componentsArgs.Load(k)
|
||||||
if ok {
|
if ok {
|
||||||
vv, ok := v.(T)
|
vv, ok := v.(T)
|
||||||
if ok {
|
if ok {
|
||||||
|
@ -150,60 +192,61 @@ func GetComponentsArgs[T any](h *Handle, k string, defaults T) T {
|
||||||
return defaults
|
return defaults
|
||||||
}
|
}
|
||||||
|
|
||||||
func PushComponentsArgsForSlice[T any](h *Handle, name string, v ...T) {
|
func PushComponentsArgsForSlice[T any](name string, v ...T) {
|
||||||
val, ok := h.componentsArgs[name]
|
val, ok := componentsArgs.Load(name)
|
||||||
if !ok {
|
if !ok {
|
||||||
var vv []T
|
var vv []T
|
||||||
vv = append(vv, v...)
|
vv = append(vv, v...)
|
||||||
h.componentsArgs[name] = vv
|
componentsArgs.Store(name, vv)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
vv, ok := val.([]T)
|
vv, ok := val.([]T)
|
||||||
if ok {
|
if ok {
|
||||||
vv = append(vv, v...)
|
vv = append(vv, v...)
|
||||||
h.componentsArgs[name] = vv
|
componentsArgs.Store(name, vv)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
func SetComponentsArgsForMap[K comparable, V any](h *Handle, name string, key K, v V) {
|
func SetComponentsArgsForMap[K comparable, V any](name string, key K, v V) {
|
||||||
val, ok := h.componentsArgs[name]
|
val, ok := componentsArgs.Load(name)
|
||||||
if !ok {
|
if !ok {
|
||||||
vv := make(map[K]V)
|
vv := make(map[K]V)
|
||||||
vv[key] = v
|
vv[key] = v
|
||||||
h.componentsArgs[name] = vv
|
componentsArgs.Store(name, vv)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
vv, ok := val.(map[K]V)
|
vv, ok := val.(map[K]V)
|
||||||
if ok {
|
if ok {
|
||||||
vv[key] = v
|
vv[key] = v
|
||||||
h.componentsArgs[name] = vv
|
componentsArgs.Store(name, vv)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
func MergeComponentsArgsForMap[K comparable, V any](h *Handle, name string, m map[K]V) {
|
func MergeComponentsArgsForMap[K comparable, V any](name string, m map[K]V) {
|
||||||
val, ok := h.componentsArgs[name]
|
val, ok := componentsArgs.Load(name)
|
||||||
if !ok {
|
if !ok {
|
||||||
h.componentsArgs[name] = m
|
componentsArgs.Store(name, m)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
vv, ok := val.(map[K]V)
|
vv, ok := val.(map[K]V)
|
||||||
if ok {
|
if ok {
|
||||||
h.componentsArgs[name] = maps.Merge(vv, m)
|
componentsArgs.Store(name, maps.Merge(vv, m))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func SetComponentsArgs(h *Handle, key string, value any) {
|
func SetComponentsArgs(key string, value any) {
|
||||||
h.componentsArgs[key] = value
|
componentsArgs.Store(key, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *Handle) ComponentFilterFn(name string) ([]func(*Handle, string, ...any) string, bool) {
|
func (h *Handle) GetComponentFilterFn(name string) ([]func(*Handle, string, ...any) string, bool) {
|
||||||
fn, ok := h.componentFilterFn[name]
|
return componentFilterFns.Load(name)
|
||||||
return fn, ok
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *Handle) AddActionFilter(name string, fns ...func(*Handle, string, ...any) string) {
|
func (h *Handle) AddActionFilter(name string, fns ...func(*Handle, string, ...any) string) {
|
||||||
h.componentFilterFn[name] = append(h.componentFilterFn[name], fns...)
|
v, _ := componentFilterFns.Load(name)
|
||||||
|
v = append(v, fns...)
|
||||||
|
componentFilterFns.Store(name, v)
|
||||||
}
|
}
|
||||||
func (h *Handle) DoActionFilter(name, s string, args ...any) string {
|
func (h *Handle) DoActionFilter(name, s string, args ...any) string {
|
||||||
calls, ok := h.componentFilterFn[name]
|
calls, ok := componentFilterFns.Load(name)
|
||||||
if ok {
|
if ok {
|
||||||
return slice.Reduce(calls, func(fn func(*Handle, string, ...any) string, r string) string {
|
return slice.Reduce(calls, func(fn func(*Handle, string, ...any) string, r string) string {
|
||||||
return fn(h, r, args...)
|
return fn(h, r, args...)
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package components
|
package components
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/fthvgb1/wp-go/app/pkg/logs"
|
||||||
"github.com/fthvgb1/wp-go/app/theme/wp"
|
"github.com/fthvgb1/wp-go/app/theme/wp"
|
||||||
"github.com/fthvgb1/wp-go/app/theme/wp/components/block"
|
"github.com/fthvgb1/wp-go/app/theme/wp/components/block"
|
||||||
"github.com/fthvgb1/wp-go/app/wpconfig"
|
"github.com/fthvgb1/wp-go/app/wpconfig"
|
||||||
|
@ -29,6 +30,7 @@ func Block(id string) (func(*wp.Handle) string, string) {
|
||||||
if ok {
|
if ok {
|
||||||
s, err := fn(h, id, parserBlock)
|
s, err := fn(h, id, parserBlock)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
logs.Error(err, str.Join("parse block", parserBlock.Name, " fail "), parserBlock)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
out = append(out, s())
|
out = append(out, s())
|
||||||
|
|
|
@ -4,7 +4,6 @@ import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/fthvgb1/wp-go/app/cmd/reload"
|
|
||||||
"github.com/fthvgb1/wp-go/app/pkg/cache"
|
"github.com/fthvgb1/wp-go/app/pkg/cache"
|
||||||
constraints2 "github.com/fthvgb1/wp-go/app/pkg/constraints"
|
constraints2 "github.com/fthvgb1/wp-go/app/pkg/constraints"
|
||||||
"github.com/fthvgb1/wp-go/app/pkg/constraints/widgets"
|
"github.com/fthvgb1/wp-go/app/pkg/constraints/widgets"
|
||||||
|
@ -12,6 +11,7 @@ import (
|
||||||
"github.com/fthvgb1/wp-go/app/pkg/models"
|
"github.com/fthvgb1/wp-go/app/pkg/models"
|
||||||
"github.com/fthvgb1/wp-go/app/theme/wp"
|
"github.com/fthvgb1/wp-go/app/theme/wp"
|
||||||
"github.com/fthvgb1/wp-go/app/theme/wp/components/widget"
|
"github.com/fthvgb1/wp-go/app/theme/wp/components/widget"
|
||||||
|
"github.com/fthvgb1/wp-go/cache/reload"
|
||||||
"github.com/fthvgb1/wp-go/helper/maps"
|
"github.com/fthvgb1/wp-go/helper/maps"
|
||||||
"github.com/fthvgb1/wp-go/helper/number"
|
"github.com/fthvgb1/wp-go/helper/number"
|
||||||
str "github.com/fthvgb1/wp-go/helper/strings"
|
str "github.com/fthvgb1/wp-go/helper/strings"
|
||||||
|
@ -50,7 +50,7 @@ func parseAttr(attr map[any]any) string {
|
||||||
}
|
}
|
||||||
style := maps.GetAnyAnyValWithDefaults[map[any]any](attr, nil, "style", "typography")
|
style := maps.GetAnyAnyValWithDefaults[map[any]any](attr, nil, "style", "typography")
|
||||||
if len(style) > 0 {
|
if len(style) > 0 {
|
||||||
styless := maps.AnyAnyMap(style, func(k, v any) (string, string, bool) {
|
styless := maps.AnyAnyMapTo(style, func(k, v any) (string, string, bool) {
|
||||||
kk, ok := k.(string)
|
kk, ok := k.(string)
|
||||||
if !ok {
|
if !ok {
|
||||||
return "", "", false
|
return "", "", false
|
||||||
|
@ -71,15 +71,16 @@ func parseAttr(attr map[any]any) string {
|
||||||
return strings.Join(attrs, " ")
|
return strings.Join(attrs, " ")
|
||||||
}
|
}
|
||||||
|
|
||||||
func Category(h *wp.Handle, id string, blockParser ParserBlock) (func() string, error) {
|
var GetCategoryAttr = reload.BuildValFn("block-category-attr", parseAttr)
|
||||||
counter := number.Counters[int]()
|
|
||||||
var err error
|
var GetCategoryConf = reload.BuildValFnWithConfirm("block-category-conf", categoryConfFn, 5)
|
||||||
conf := reload.GetAnyValBys("block-category-conf", h, func(h *wp.Handle) map[any]any {
|
|
||||||
|
func categoryConfFn(blockParser ParserBlock) (map[any]any, bool) {
|
||||||
var con any
|
var con any
|
||||||
err = json.Unmarshal([]byte(blockParser.Attrs), &con)
|
err := json.Unmarshal([]byte(blockParser.Attrs), &con)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logs.Error(err, "解析category attr错误", blockParser.Attrs)
|
logs.Error(err, "解析category attr错误", blockParser.Attrs)
|
||||||
return nil
|
return nil, false
|
||||||
}
|
}
|
||||||
var conf map[any]any
|
var conf map[any]any
|
||||||
switch con.(type) {
|
switch con.(type) {
|
||||||
|
@ -111,8 +112,20 @@ func Category(h *wp.Handle, id string, blockParser ParserBlock) (func() string,
|
||||||
classes = append(classes, "wp-block-categories-list")
|
classes = append(classes, "wp-block-categories-list")
|
||||||
conf["className"] = strings.Join(classes, " ")
|
conf["className"] = strings.Join(classes, " ")
|
||||||
}
|
}
|
||||||
return conf
|
return conf, true
|
||||||
})
|
}
|
||||||
|
|
||||||
|
var GetCategoryArgs = reload.BuildValFnWithAnyParams("block-category-args", categoryArgs)
|
||||||
|
|
||||||
|
func categoryArgs(_ ...any) map[string]string {
|
||||||
|
args := wp.GetComponentsArgs(widgets.Widget, map[string]string{})
|
||||||
|
return maps.FilterZeroMerge(categoryDefaultArgs(), args)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Category(h *wp.Handle, id string, blockParser ParserBlock) (func() string, error) {
|
||||||
|
counter := number.Counters[int]()
|
||||||
|
var err error
|
||||||
|
conf := GetCategoryConf(blockParser)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -127,10 +140,7 @@ func Category(h *wp.Handle, id string, blockParser ParserBlock) (func() string,
|
||||||
if maps.GetAnyAnyValWithDefaults(conf, false, "showOnlyTopLevel") {
|
if maps.GetAnyAnyValWithDefaults(conf, false, "showOnlyTopLevel") {
|
||||||
h.C.Set("showOnlyTopLevel", true)
|
h.C.Set("showOnlyTopLevel", true)
|
||||||
}
|
}
|
||||||
args := reload.GetAnyValBys("block-category-args", h, func(h *wp.Handle) map[string]string {
|
args := GetCategoryArgs()
|
||||||
args := wp.GetComponentsArgs(h, widgets.Widget, map[string]string{})
|
|
||||||
return maps.FilterZeroMerge(categoryDefaultArgs(), args)
|
|
||||||
})
|
|
||||||
|
|
||||||
return func() string {
|
return func() string {
|
||||||
return category(h, id, counter, args, conf)
|
return category(h, id, counter, args, conf)
|
||||||
|
@ -150,21 +160,21 @@ func category(h *wp.Handle, id string, counter number.Counter[int], args map[str
|
||||||
return str.Join(before, out, args["{$after_widget}"])
|
return str.Join(before, out, args["{$after_widget}"])
|
||||||
}
|
}
|
||||||
|
|
||||||
func categoryUl(h *wp.Handle, categories []models.TermsMy, conf map[any]any) string {
|
func categoryUl(h *wp.Handle, categories []models.TermsMy, confAttr map[any]any) string {
|
||||||
s := str.NewBuilder()
|
s := str.NewBuilder()
|
||||||
li := widget.CategoryLi(h, conf, categories)
|
li := widget.CategoryLi(h, confAttr, categories)
|
||||||
attrs := reload.GetAnyValBys("block-category-attr", conf, parseAttr)
|
attrs := GetCategoryAttr(confAttr)
|
||||||
s.Sprintf(`<ul %s>%s</ul>`, attrs, li)
|
s.Sprintf(`<ul %s>%s</ul>`, attrs, li)
|
||||||
return s.String()
|
return s.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
func dropdown(h *wp.Handle, categories []models.TermsMy, id int, args map[string]string, conf map[any]any) string {
|
func dropdown(h *wp.Handle, categories []models.TermsMy, id int, args map[string]string, confAttr map[any]any) string {
|
||||||
s := str.NewBuilder()
|
s := str.NewBuilder()
|
||||||
ids := fmt.Sprintf(`wp-block-categories-%v`, id)
|
ids := fmt.Sprintf(`wp-block-categories-%v`, id)
|
||||||
args = maps.Copy(args)
|
args = maps.Copy(args)
|
||||||
args["{$selectId}"] = ids
|
args["{$selectId}"] = ids
|
||||||
attrs := reload.GetAnyValBys("block-category-attr", conf, parseAttr)
|
attrs := GetCategoryAttr(confAttr)
|
||||||
selects := widget.DropdownCategories(h, args, conf, categories)
|
selects := widget.DropdownCategories(h, args, confAttr, categories)
|
||||||
s.Sprintf(`<div %s><label class="screen-reader-text" for="%s">%s</label>%s%s</div>`, attrs, ids, args["{$title}"], selects, strings.ReplaceAll(categoryDropdownScript, "{$id}", ids))
|
s.Sprintf(`<div %s><label class="screen-reader-text" for="%s">%s</label>%s%s</div>`, attrs, ids, args["{$title}"], selects, strings.ReplaceAll(categoryDropdownScript, "{$id}", ids))
|
||||||
return s.String()
|
return s.String()
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,11 +2,11 @@ package widget
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/fthvgb1/wp-go/app/cmd/reload"
|
|
||||||
"github.com/fthvgb1/wp-go/app/pkg/cache"
|
"github.com/fthvgb1/wp-go/app/pkg/cache"
|
||||||
"github.com/fthvgb1/wp-go/app/pkg/constraints/widgets"
|
"github.com/fthvgb1/wp-go/app/pkg/constraints/widgets"
|
||||||
"github.com/fthvgb1/wp-go/app/pkg/models"
|
"github.com/fthvgb1/wp-go/app/pkg/models"
|
||||||
"github.com/fthvgb1/wp-go/app/theme/wp"
|
"github.com/fthvgb1/wp-go/app/theme/wp"
|
||||||
|
"github.com/fthvgb1/wp-go/cache/reload"
|
||||||
"github.com/fthvgb1/wp-go/helper/maps"
|
"github.com/fthvgb1/wp-go/helper/maps"
|
||||||
"github.com/fthvgb1/wp-go/helper/slice"
|
"github.com/fthvgb1/wp-go/helper/slice"
|
||||||
str "github.com/fthvgb1/wp-go/helper/strings"
|
str "github.com/fthvgb1/wp-go/helper/strings"
|
||||||
|
@ -40,12 +40,16 @@ var archivesConfig = map[any]any{
|
||||||
"title": "归档",
|
"title": "归档",
|
||||||
}
|
}
|
||||||
|
|
||||||
func Archive(h *wp.Handle, id string) string {
|
var GetArchiveConf = BuildconfigFn(archivesConfig, "widget_archives", int64(2))
|
||||||
conf := configs(archivesConfig, "widget_archives", int64(2))
|
var GetArchiveArgs = reload.BuildValFnWithAnyParams("widget_archive-args", archiveArgsFn)
|
||||||
args := reload.GetAnyValBys("widget-archive-args", h, func(h *wp.Handle) map[string]string {
|
|
||||||
|
func archiveArgsFn(a ...any) map[string]string {
|
||||||
|
h := a[0].(*wp.Handle)
|
||||||
|
conf := a[1].(map[any]any)
|
||||||
|
id := a[2].(string)
|
||||||
archiveArgs := archiveArgs()
|
archiveArgs := archiveArgs()
|
||||||
commonArgs := wp.GetComponentsArgs(h, widgets.Widget, CommonArgs())
|
commonArgs := wp.GetComponentsArgs(widgets.Widget, CommonArgs())
|
||||||
args := wp.GetComponentsArgs(h, widgets.Archive, archiveArgs)
|
args := wp.GetComponentsArgs(widgets.Archive, archiveArgs)
|
||||||
args = maps.FilterZeroMerge(archiveArgs, CommonArgs(), commonArgs, args)
|
args = maps.FilterZeroMerge(archiveArgs, CommonArgs(), commonArgs, args)
|
||||||
args["{$before_widget}"] = fmt.Sprintf(args["{$before_widget}"], str.Join("archives-", id), str.Join("widget widget_", "archive"))
|
args["{$before_widget}"] = fmt.Sprintf(args["{$before_widget}"], str.Join("archives-", id), str.Join("widget widget_", "archive"))
|
||||||
args["{$title}"] = str.Join(args["{$before_title}"], conf["title"].(string), args["{$after_title}"])
|
args["{$title}"] = str.Join(args["{$before_title}"], conf["title"].(string), args["{$after_title}"])
|
||||||
|
@ -54,7 +58,11 @@ func Archive(h *wp.Handle, id string) string {
|
||||||
args["{$navCloser}"] = "</nav>"
|
args["{$navCloser}"] = "</nav>"
|
||||||
}
|
}
|
||||||
return args
|
return args
|
||||||
})
|
}
|
||||||
|
|
||||||
|
func Archive(h *wp.Handle, id string) string {
|
||||||
|
conf := GetArchiveConf()
|
||||||
|
args := GetArchiveArgs(h, conf, id)
|
||||||
|
|
||||||
s := archiveTemplate
|
s := archiveTemplate
|
||||||
if int64(1) == conf["dropdown"].(int64) {
|
if int64(1) == conf["dropdown"].(int64) {
|
||||||
|
@ -83,11 +91,12 @@ var dropdownScript = `
|
||||||
func archiveDropDown(h *wp.Handle, conf map[any]any, args map[string]string, archives []models.PostArchive) string {
|
func archiveDropDown(h *wp.Handle, conf map[any]any, args map[string]string, archives []models.PostArchive) string {
|
||||||
option := str.NewBuilder()
|
option := str.NewBuilder()
|
||||||
option.Sprintf(`<option value="">%s</option>`, args["{$dropdown_label}"])
|
option.Sprintf(`<option value="">%s</option>`, args["{$dropdown_label}"])
|
||||||
month := strings.TrimLeft(h.Index.Param.Month, "0")
|
i := h.GetIndexHandle()
|
||||||
|
month := strings.TrimLeft(i.Param.Month, "0")
|
||||||
showCount := conf["count"].(int64)
|
showCount := conf["count"].(int64)
|
||||||
for _, archive := range archives {
|
for _, archive := range archives {
|
||||||
sel := ""
|
sel := ""
|
||||||
if h.Index.Param.Year == archive.Year && month == archive.Month {
|
if i.Param.Year == archive.Year && month == archive.Month {
|
||||||
sel = "selected"
|
sel = "selected"
|
||||||
}
|
}
|
||||||
count := ""
|
count := ""
|
||||||
|
|
|
@ -2,17 +2,16 @@ package widget
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/fthvgb1/wp-go/app/cmd/reload"
|
|
||||||
"github.com/fthvgb1/wp-go/app/pkg/cache"
|
"github.com/fthvgb1/wp-go/app/pkg/cache"
|
||||||
"github.com/fthvgb1/wp-go/app/pkg/constraints"
|
"github.com/fthvgb1/wp-go/app/pkg/constraints"
|
||||||
"github.com/fthvgb1/wp-go/app/pkg/constraints/widgets"
|
"github.com/fthvgb1/wp-go/app/pkg/constraints/widgets"
|
||||||
"github.com/fthvgb1/wp-go/app/pkg/models"
|
"github.com/fthvgb1/wp-go/app/pkg/models"
|
||||||
"github.com/fthvgb1/wp-go/app/theme/wp"
|
"github.com/fthvgb1/wp-go/app/theme/wp"
|
||||||
|
"github.com/fthvgb1/wp-go/cache/reload"
|
||||||
"github.com/fthvgb1/wp-go/helper/maps"
|
"github.com/fthvgb1/wp-go/helper/maps"
|
||||||
"github.com/fthvgb1/wp-go/helper/slice"
|
"github.com/fthvgb1/wp-go/helper/slice"
|
||||||
str "github.com/fthvgb1/wp-go/helper/strings"
|
str "github.com/fthvgb1/wp-go/helper/strings"
|
||||||
"github.com/fthvgb1/wp-go/helper/tree"
|
"github.com/fthvgb1/wp-go/helper/tree"
|
||||||
"net/http"
|
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -45,12 +44,16 @@ func categoryArgs() map[string]string {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func Category(h *wp.Handle, id string) string {
|
var GetCategoryConf = BuildconfigFn(categoryConfig, "widget_categories", int64(2))
|
||||||
conf := configs(categoryConfig, "widget_categories", int64(2))
|
|
||||||
|
|
||||||
args := reload.GetAnyValBys("widget-category-args", h, func(h *wp.Handle) map[string]string {
|
var GetCategoryArgs = reload.BuildValFnWithAnyParams("widget-category-args", categoryArgsFn)
|
||||||
commonArgs := wp.GetComponentsArgs(h, widgets.Widget, map[string]string{})
|
|
||||||
args := wp.GetComponentsArgs(h, widgets.Categories, categoryArgs())
|
func categoryArgsFn(a ...any) map[string]string {
|
||||||
|
h := a[0].(*wp.Handle)
|
||||||
|
conf := a[1].(map[any]any)
|
||||||
|
id := a[2].(string)
|
||||||
|
commonArgs := wp.GetComponentsArgs(widgets.Widget, map[string]string{})
|
||||||
|
args := wp.GetComponentsArgs(widgets.Categories, categoryArgs())
|
||||||
args = maps.FilterZeroMerge(categoryArgs(), CommonArgs(), commonArgs, args)
|
args = maps.FilterZeroMerge(categoryArgs(), CommonArgs(), commonArgs, args)
|
||||||
args["{$before_widget}"] = fmt.Sprintf(args["{$before_widget}"], str.Join("categories-", id), str.Join("widget widget_", "categories"))
|
args["{$before_widget}"] = fmt.Sprintf(args["{$before_widget}"], str.Join("categories-", id), str.Join("widget widget_", "categories"))
|
||||||
args["{$title}"] = str.Join(args["{$before_title}"], conf["title"].(string), args["{$after_title}"])
|
args["{$title}"] = str.Join(args["{$before_title}"], conf["title"].(string), args["{$after_title}"])
|
||||||
|
@ -59,8 +62,11 @@ func Category(h *wp.Handle, id string) string {
|
||||||
args["{$navCloser}"] = "</nav>"
|
args["{$navCloser}"] = "</nav>"
|
||||||
}
|
}
|
||||||
return args
|
return args
|
||||||
})
|
}
|
||||||
|
|
||||||
|
func Category(h *wp.Handle, id string) string {
|
||||||
|
conf := GetCategoryConf()
|
||||||
|
args := GetCategoryArgs(h, conf, id)
|
||||||
t := categoryTemplate
|
t := categoryTemplate
|
||||||
dropdown := conf["dropdown"].(int64)
|
dropdown := conf["dropdown"].(int64)
|
||||||
categories := cache.CategoriesTags(h.C, constraints.Category)
|
categories := cache.CategoriesTags(h.C, constraints.Category)
|
||||||
|
@ -202,8 +208,9 @@ func DropdownCategories(h *wp.Handle, args map[string]string, conf map[any]any,
|
||||||
s.Sprintf(` <option value="-1">%s</option>
|
s.Sprintf(` <option value="-1">%s</option>
|
||||||
`, args["{$show_option_none}"])
|
`, args["{$show_option_none}"])
|
||||||
currentCategory := ""
|
currentCategory := ""
|
||||||
|
i := h.GetIndexHandle()
|
||||||
if h.Scene() == constraints.Category {
|
if h.Scene() == constraints.Category {
|
||||||
currentCategory = h.Index.Param.Category
|
currentCategory = i.Param.Category
|
||||||
}
|
}
|
||||||
showCount := conf["count"].(int64)
|
showCount := conf["count"].(int64)
|
||||||
fn := func(category models.TermsMy, deep int) {
|
fn := func(category models.TermsMy, deep int) {
|
||||||
|
@ -235,41 +242,8 @@ func DropdownCategories(h *wp.Handle, args map[string]string, conf map[any]any,
|
||||||
return h.DoActionFilter("wp_dropdown_cats", s.String())
|
return h.DoActionFilter("wp_dropdown_cats", s.String())
|
||||||
}
|
}
|
||||||
|
|
||||||
func CheckCategory(h *wp.Handle) {
|
|
||||||
name, ok := parseDropdownCate(h)
|
|
||||||
if ok {
|
|
||||||
h.C.Redirect(http.StatusMovedPermanently, fmt.Sprintf("/p/category/%s", name))
|
|
||||||
h.Abort()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func parseDropdownCate(h *wp.Handle) (cateName string, r bool) {
|
|
||||||
cate := wp.GetComponentsArgs[map[string]string](h, widgets.Categories, categoryArgs())
|
|
||||||
name, ok := cate["{$name}"]
|
|
||||||
if !ok || name == "" {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
cat := h.C.Query(name)
|
|
||||||
if cat == "" {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
id := str.ToInteger[uint64](cat, 0)
|
|
||||||
if id < 1 {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
i, cc := slice.SearchFirst(cache.CategoriesTags(h.C, constraints.Category), func(my models.TermsMy) bool {
|
|
||||||
return id == my.Terms.TermId
|
|
||||||
})
|
|
||||||
if i < 0 {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
r = true
|
|
||||||
cateName = cc.Name
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func IsCategory(h *wp.Handle) (category models.TermsMy, r bool) {
|
func IsCategory(h *wp.Handle) (category models.TermsMy, r bool) {
|
||||||
cate := wp.GetComponentsArgs[map[string]string](h, widgets.Categories, categoryArgs())
|
cate := wp.GetComponentsArgs[map[string]string](widgets.Categories, categoryArgs())
|
||||||
name, ok := cate["{$name}"]
|
name, ok := cate["{$name}"]
|
||||||
if !ok || name == "" {
|
if !ok || name == "" {
|
||||||
return
|
return
|
||||||
|
@ -292,3 +266,12 @@ func IsCategory(h *wp.Handle) (category models.TermsMy, r bool) {
|
||||||
category = cc
|
category = cc
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func CategoryQueryName(h *wp.Handle) string {
|
||||||
|
cate := wp.GetComponentsArgs[map[string]string](widgets.Categories, categoryArgs())
|
||||||
|
name, ok := cate["{$name}"]
|
||||||
|
if ok {
|
||||||
|
return name
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
package widget
|
package widget
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/fthvgb1/wp-go/app/cmd/reload"
|
|
||||||
"github.com/fthvgb1/wp-go/app/theme/wp"
|
"github.com/fthvgb1/wp-go/app/theme/wp"
|
||||||
"github.com/fthvgb1/wp-go/app/wpconfig"
|
"github.com/fthvgb1/wp-go/app/wpconfig"
|
||||||
|
"github.com/fthvgb1/wp-go/cache/reload"
|
||||||
"github.com/fthvgb1/wp-go/helper/maps"
|
"github.com/fthvgb1/wp-go/helper/maps"
|
||||||
str "github.com/fthvgb1/wp-go/helper/strings"
|
str "github.com/fthvgb1/wp-go/helper/strings"
|
||||||
)
|
)
|
||||||
|
@ -14,9 +14,13 @@ func Fn(id string, fn func(*wp.Handle, string) string) func(h *wp.Handle) string
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func configs[M ~map[K]V, K comparable, V any](m M, key string, a ...any) M {
|
func configFns[K comparable, V any](m map[K]V, key string, a ...any) func(_ ...any) map[K]V {
|
||||||
return reload.GetAnyValBys(str.Join("widget-config-", key), key, func(_ string) M {
|
return func(_ ...any) map[K]V {
|
||||||
c := wpconfig.GetPHPArrayVal[M](key, nil, a...)
|
c := wpconfig.GetPHPArrayVal[map[K]V](key, nil, a...)
|
||||||
return maps.FilterZeroMerge(maps.Copy(m), c)
|
return maps.FilterZeroMerge(maps.Copy(m), c)
|
||||||
})
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BuildconfigFn[K comparable, V any](m map[K]V, key string, a ...any) func(_ ...any) map[K]V {
|
||||||
|
return reload.BuildValFnWithAnyParams(str.Join("widget-config-", key), configFns(m, key, a...))
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,10 +2,10 @@ package widget
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/fthvgb1/wp-go/app/cmd/reload"
|
|
||||||
"github.com/fthvgb1/wp-go/app/pkg/constraints/widgets"
|
"github.com/fthvgb1/wp-go/app/pkg/constraints/widgets"
|
||||||
"github.com/fthvgb1/wp-go/app/theme/wp"
|
"github.com/fthvgb1/wp-go/app/theme/wp"
|
||||||
"github.com/fthvgb1/wp-go/app/wpconfig"
|
"github.com/fthvgb1/wp-go/app/wpconfig"
|
||||||
|
"github.com/fthvgb1/wp-go/cache/reload"
|
||||||
"github.com/fthvgb1/wp-go/helper/maps"
|
"github.com/fthvgb1/wp-go/helper/maps"
|
||||||
"github.com/fthvgb1/wp-go/helper/slice"
|
"github.com/fthvgb1/wp-go/helper/slice"
|
||||||
str "github.com/fthvgb1/wp-go/helper/strings"
|
str "github.com/fthvgb1/wp-go/helper/strings"
|
||||||
|
@ -21,18 +21,21 @@ var metaTemplate = `{$before_widget}
|
||||||
{$navCloser}
|
{$navCloser}
|
||||||
{$after_widget}`
|
{$after_widget}`
|
||||||
|
|
||||||
func metaArgs() map[string]string {
|
func defaultMetaArgs() map[string]string {
|
||||||
return map[string]string{
|
return map[string]string{
|
||||||
"{$aria_label}": "",
|
"{$aria_label}": "",
|
||||||
"{$title}": "",
|
"{$title}": "",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func Meta(h *wp.Handle, id string) string {
|
var GetMetaArgs = reload.BuildValFnWithAnyParams("widget-meta-args", ParseMetaArgs)
|
||||||
args := reload.GetAnyValBys("widget-meta-args", h, func(h *wp.Handle) map[string]string {
|
|
||||||
commonArgs := wp.GetComponentsArgs(h, widgets.Widget, map[string]string{})
|
func ParseMetaArgs(a ...any) map[string]string {
|
||||||
metaArgs := metaArgs()
|
h := a[0].(*wp.Handle)
|
||||||
args := wp.GetComponentsArgs(h, widgets.Meta, metaArgs)
|
id := a[1].(string)
|
||||||
|
commonArgs := wp.GetComponentsArgs(widgets.Widget, map[string]string{})
|
||||||
|
metaArgs := defaultMetaArgs()
|
||||||
|
args := wp.GetComponentsArgs(widgets.Meta, metaArgs)
|
||||||
args = maps.FilterZeroMerge(metaArgs, CommonArgs(), commonArgs, args)
|
args = maps.FilterZeroMerge(metaArgs, CommonArgs(), commonArgs, args)
|
||||||
args["{$before_widget}"] = fmt.Sprintf(args["{$before_widget}"], str.Join("meta-", id), str.Join("widget widget_", "meta"))
|
args["{$before_widget}"] = fmt.Sprintf(args["{$before_widget}"], str.Join("meta-", id), str.Join("widget widget_", "meta"))
|
||||||
args["{$title}"] = wpconfig.GetPHPArrayVal("widget_meta", "其它操作", int64(2), "title")
|
args["{$title}"] = wpconfig.GetPHPArrayVal("widget_meta", "其它操作", int64(2), "title")
|
||||||
|
@ -47,8 +50,10 @@ func Meta(h *wp.Handle, id string) string {
|
||||||
args["{$navCloser}"] = "</nav>"
|
args["{$navCloser}"] = "</nav>"
|
||||||
}
|
}
|
||||||
return args
|
return args
|
||||||
})
|
}
|
||||||
|
|
||||||
|
func Meta(h *wp.Handle, id string) string {
|
||||||
|
args := GetMetaArgs(h, id)
|
||||||
ss := str.NewBuilder()
|
ss := str.NewBuilder()
|
||||||
if str.ToInteger(wpconfig.GetOption("users_can_register"), 0) > 0 {
|
if str.ToInteger(wpconfig.GetOption("users_can_register"), 0) > 0 {
|
||||||
ss.Sprintf(`<li><a href="/wp-login.php?action=register">注册</li>`)
|
ss.Sprintf(`<li><a href="/wp-login.php?action=register">注册</li>`)
|
||||||
|
|
|
@ -2,11 +2,11 @@ package widget
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/fthvgb1/wp-go/app/cmd/reload"
|
|
||||||
"github.com/fthvgb1/wp-go/app/pkg/cache"
|
"github.com/fthvgb1/wp-go/app/pkg/cache"
|
||||||
"github.com/fthvgb1/wp-go/app/pkg/constraints/widgets"
|
"github.com/fthvgb1/wp-go/app/pkg/constraints/widgets"
|
||||||
"github.com/fthvgb1/wp-go/app/pkg/models"
|
"github.com/fthvgb1/wp-go/app/pkg/models"
|
||||||
"github.com/fthvgb1/wp-go/app/theme/wp"
|
"github.com/fthvgb1/wp-go/app/theme/wp"
|
||||||
|
"github.com/fthvgb1/wp-go/cache/reload"
|
||||||
"github.com/fthvgb1/wp-go/helper/maps"
|
"github.com/fthvgb1/wp-go/helper/maps"
|
||||||
"github.com/fthvgb1/wp-go/helper/slice"
|
"github.com/fthvgb1/wp-go/helper/slice"
|
||||||
str "github.com/fthvgb1/wp-go/helper/strings"
|
str "github.com/fthvgb1/wp-go/helper/strings"
|
||||||
|
@ -39,13 +39,17 @@ var recentCommentsTemplate = `{$before_widget}
|
||||||
{$after_widget}
|
{$after_widget}
|
||||||
`
|
`
|
||||||
|
|
||||||
func RecentComments(h *wp.Handle, id string) string {
|
var GetRecentCommentConf = BuildconfigFn(recentCommentConf, "widget_recent-comments", int64(2))
|
||||||
conf := configs(recentCommentConf, "widget_recent-comments", int64(2))
|
|
||||||
|
|
||||||
args := reload.GetAnyValBys("widget-recent-comment-args", h, func(h *wp.Handle) map[string]string {
|
var GetRecentCommentArgs = reload.BuildValFnWithAnyParams("widget-recent-comment-args", RecentCommentArgs)
|
||||||
|
|
||||||
|
func RecentCommentArgs(a ...any) map[string]string {
|
||||||
|
h := a[0].(*wp.Handle)
|
||||||
|
conf := a[1].(map[any]any)
|
||||||
|
id := a[2].(string)
|
||||||
commentsArgs := recentCommentsArgs()
|
commentsArgs := recentCommentsArgs()
|
||||||
commonArgs := wp.GetComponentsArgs(h, widgets.Widget, map[string]string{})
|
commonArgs := wp.GetComponentsArgs(widgets.Widget, map[string]string{})
|
||||||
args := wp.GetComponentsArgs(h, widgets.RecentComments, commentsArgs)
|
args := wp.GetComponentsArgs(widgets.RecentComments, commentsArgs)
|
||||||
args = maps.FilterZeroMerge(commentsArgs, CommonArgs(), commonArgs, args)
|
args = maps.FilterZeroMerge(commentsArgs, CommonArgs(), commonArgs, args)
|
||||||
args["{$before_widget}"] = fmt.Sprintf(args["{$before_widget}"], str.Join("recent-comments-", id), str.Join("widget widget_", "recent_comments"))
|
args["{$before_widget}"] = fmt.Sprintf(args["{$before_widget}"], str.Join("recent-comments-", id), str.Join("widget widget_", "recent_comments"))
|
||||||
args["{$title}"] = str.Join(args["{$before_title}"], conf["title"].(string), args["{$after_title}"])
|
args["{$title}"] = str.Join(args["{$before_title}"], conf["title"].(string), args["{$after_title}"])
|
||||||
|
@ -54,14 +58,17 @@ func RecentComments(h *wp.Handle, id string) string {
|
||||||
args["{$navCloser}"] = "</nav>"
|
args["{$navCloser}"] = "</nav>"
|
||||||
}
|
}
|
||||||
return args
|
return args
|
||||||
})
|
}
|
||||||
|
func RecentComments(h *wp.Handle, id string) string {
|
||||||
|
conf := GetRecentCommentConf()
|
||||||
|
args := GetRecentCommentArgs(h, conf, id)
|
||||||
|
|
||||||
comments := slice.Map(cache.RecentComments(h.C, int(conf["number"].(int64))), func(t models.Comments) string {
|
comments := slice.Map(cache.RecentComments(h.C, int(conf["number"].(int64))), func(t models.Comments) string {
|
||||||
return fmt.Sprintf(` <li>
|
return fmt.Sprintf(` <li>
|
||||||
<span class="comment-author-link">%s</span>发表在《
|
<span class="comment-author-link">%s</span>发表在《
|
||||||
<a href="/p/%v#comment-%v">%s</a>
|
<a href="%s">%s</a>
|
||||||
》
|
》
|
||||||
</li>`, t.CommentAuthor, t.CommentPostId, t.CommentId, t.PostTitle)
|
</li>`, t.CommentAuthor, t.CommentAuthorUrl, t.PostTitle)
|
||||||
})
|
})
|
||||||
s := strings.ReplaceAll(recentCommentsTemplate, "{$li}", strings.Join(comments, "\n"))
|
s := strings.ReplaceAll(recentCommentsTemplate, "{$li}", strings.Join(comments, "\n"))
|
||||||
return h.DoActionFilter(widgets.RecentComments, str.Replace(s, args))
|
return h.DoActionFilter(widgets.RecentComments, str.Replace(s, args))
|
||||||
|
|
|
@ -2,13 +2,13 @@ package widget
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/fthvgb1/wp-go/app/cmd/reload"
|
|
||||||
"github.com/fthvgb1/wp-go/app/pkg/cache"
|
"github.com/fthvgb1/wp-go/app/pkg/cache"
|
||||||
"github.com/fthvgb1/wp-go/app/pkg/constraints"
|
"github.com/fthvgb1/wp-go/app/pkg/constraints"
|
||||||
"github.com/fthvgb1/wp-go/app/pkg/constraints/widgets"
|
"github.com/fthvgb1/wp-go/app/pkg/constraints/widgets"
|
||||||
"github.com/fthvgb1/wp-go/app/pkg/models"
|
"github.com/fthvgb1/wp-go/app/pkg/models"
|
||||||
"github.com/fthvgb1/wp-go/app/theme/wp"
|
"github.com/fthvgb1/wp-go/app/theme/wp"
|
||||||
"github.com/fthvgb1/wp-go/app/wpconfig"
|
"github.com/fthvgb1/wp-go/app/wpconfig"
|
||||||
|
"github.com/fthvgb1/wp-go/cache/reload"
|
||||||
"github.com/fthvgb1/wp-go/helper/maps"
|
"github.com/fthvgb1/wp-go/helper/maps"
|
||||||
"github.com/fthvgb1/wp-go/helper/slice"
|
"github.com/fthvgb1/wp-go/helper/slice"
|
||||||
str "github.com/fthvgb1/wp-go/helper/strings"
|
str "github.com/fthvgb1/wp-go/helper/strings"
|
||||||
|
@ -25,7 +25,7 @@ var recentPostsTemplate = `{$before_widget}
|
||||||
{$after_widget}
|
{$after_widget}
|
||||||
`
|
`
|
||||||
|
|
||||||
func recentPostsArgs() map[string]string {
|
func DefaultRecentPostsArgs() map[string]string {
|
||||||
return map[string]string{
|
return map[string]string{
|
||||||
"{$before_sidebar}": "",
|
"{$before_sidebar}": "",
|
||||||
"{$after_sidebar}": "",
|
"{$after_sidebar}": "",
|
||||||
|
@ -35,7 +35,7 @@ func recentPostsArgs() map[string]string {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func recentConf() map[any]any {
|
func DefaultRecentConf() map[any]any {
|
||||||
return map[any]any{
|
return map[any]any{
|
||||||
"number": int64(5),
|
"number": int64(5),
|
||||||
"show_date": false,
|
"show_date": false,
|
||||||
|
@ -43,18 +43,24 @@ func recentConf() map[any]any {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func RecentPosts(h *wp.Handle, id string) string {
|
var GetRecentPostConf = reload.BuildValFnWithAnyParams("widget-recent-posts-conf", RecentPostConf)
|
||||||
conf := reload.GetAnyValBys("widget-recent-posts-conf", h, func(h *wp.Handle) map[any]any {
|
|
||||||
recent := recentConf()
|
func RecentPostConf(_ ...any) map[any]any {
|
||||||
|
recent := DefaultRecentConf()
|
||||||
conf := wpconfig.GetPHPArrayVal[map[any]any]("widget_recent-posts", recent, int64(2))
|
conf := wpconfig.GetPHPArrayVal[map[any]any]("widget_recent-posts", recent, int64(2))
|
||||||
conf = maps.FilterZeroMerge(recent, conf)
|
conf = maps.FilterZeroMerge(recent, conf)
|
||||||
return conf
|
return conf
|
||||||
})
|
}
|
||||||
|
|
||||||
args := reload.GetAnyValBys("widget-recent-posts-args", h, func(h *wp.Handle) map[string]string {
|
var GetRecentPostArgs = reload.BuildValFnWithAnyParams("widget-recent-posts-args", ParseRecentPostArgs)
|
||||||
recent := recentPostsArgs()
|
|
||||||
commonArgs := wp.GetComponentsArgs(h, widgets.Widget, map[string]string{})
|
func ParseRecentPostArgs(a ...any) map[string]string {
|
||||||
args := wp.GetComponentsArgs(h, widgets.RecentPosts, recent)
|
h := a[0].(*wp.Handle)
|
||||||
|
conf := a[1].(map[any]any)
|
||||||
|
id := a[2].(string)
|
||||||
|
recent := DefaultRecentPostsArgs()
|
||||||
|
commonArgs := wp.GetComponentsArgs(widgets.Widget, map[string]string{})
|
||||||
|
args := wp.GetComponentsArgs(widgets.RecentPosts, recent)
|
||||||
args = maps.FilterZeroMerge(recent, CommonArgs(), commonArgs, args)
|
args = maps.FilterZeroMerge(recent, CommonArgs(), commonArgs, args)
|
||||||
args["{$before_widget}"] = fmt.Sprintf(args["{$before_widget}"], str.Join("recent-posts-", id), str.Join("widget widget_", "recent_entries"))
|
args["{$before_widget}"] = fmt.Sprintf(args["{$before_widget}"], str.Join("recent-posts-", id), str.Join("widget widget_", "recent_entries"))
|
||||||
args["{$title}"] = str.Join(args["{$before_title}"], conf["title"].(string), args["{$after_title}"])
|
args["{$title}"] = str.Join(args["{$before_title}"], conf["title"].(string), args["{$after_title}"])
|
||||||
|
@ -63,8 +69,11 @@ func RecentPosts(h *wp.Handle, id string) string {
|
||||||
args["{$navCloser}"] = "</nav>"
|
args["{$navCloser}"] = "</nav>"
|
||||||
}
|
}
|
||||||
return args
|
return args
|
||||||
})
|
}
|
||||||
|
|
||||||
|
func RecentPosts(h *wp.Handle, id string) string {
|
||||||
|
conf := GetRecentPostConf()
|
||||||
|
args := GetRecentPostArgs(h, conf, id)
|
||||||
currentPostId := uint64(0)
|
currentPostId := uint64(0)
|
||||||
if h.Scene() == constraints.Detail {
|
if h.Scene() == constraints.Detail {
|
||||||
currentPostId = str.ToInteger(h.C.Param("id"), uint64(0))
|
currentPostId = str.ToInteger(h.C.Param("id"), uint64(0))
|
||||||
|
|
|
@ -2,11 +2,11 @@ package widget
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/fthvgb1/wp-go/app/cmd/reload"
|
|
||||||
"github.com/fthvgb1/wp-go/app/pkg/constraints"
|
"github.com/fthvgb1/wp-go/app/pkg/constraints"
|
||||||
"github.com/fthvgb1/wp-go/app/pkg/constraints/widgets"
|
"github.com/fthvgb1/wp-go/app/pkg/constraints/widgets"
|
||||||
"github.com/fthvgb1/wp-go/app/theme/wp"
|
"github.com/fthvgb1/wp-go/app/theme/wp"
|
||||||
"github.com/fthvgb1/wp-go/app/wpconfig"
|
"github.com/fthvgb1/wp-go/app/wpconfig"
|
||||||
|
"github.com/fthvgb1/wp-go/cache/reload"
|
||||||
"github.com/fthvgb1/wp-go/helper/html"
|
"github.com/fthvgb1/wp-go/helper/html"
|
||||||
"github.com/fthvgb1/wp-go/helper/maps"
|
"github.com/fthvgb1/wp-go/helper/maps"
|
||||||
"github.com/fthvgb1/wp-go/helper/slice"
|
"github.com/fthvgb1/wp-go/helper/slice"
|
||||||
|
@ -47,11 +47,14 @@ func searchArgs() map[string]string {
|
||||||
|
|
||||||
var form = html5SearchForm
|
var form = html5SearchForm
|
||||||
|
|
||||||
func Search(h *wp.Handle, id string) string {
|
var GetSearchArgs = reload.BuildValFnWithAnyParams("widget-search-args", ParseSearchArgs)
|
||||||
args := reload.GetAnyValBys("widget-search-args", h, func(h *wp.Handle) map[string]string {
|
|
||||||
|
func ParseSearchArgs(a ...any) map[string]string {
|
||||||
|
h := a[0].(*wp.Handle)
|
||||||
|
id := a[1].(string)
|
||||||
search := searchArgs()
|
search := searchArgs()
|
||||||
commonArgs := wp.GetComponentsArgs(h, widgets.Widget, map[string]string{})
|
commonArgs := wp.GetComponentsArgs(widgets.Widget, map[string]string{})
|
||||||
args := wp.GetComponentsArgs(h, widgets.Search, search)
|
args := wp.GetComponentsArgs(widgets.Search, search)
|
||||||
args = maps.FilterZeroMerge(search, CommonArgs(), commonArgs, args)
|
args = maps.FilterZeroMerge(search, CommonArgs(), commonArgs, args)
|
||||||
args["{$before_widget}"] = fmt.Sprintf(args["{$before_widget}"], str.Join("search-", id), str.Join("widget widget_", "search"))
|
args["{$before_widget}"] = fmt.Sprintf(args["{$before_widget}"], str.Join("search-", id), str.Join("widget widget_", "search"))
|
||||||
if args["{$title}"] == "" {
|
if args["{$title}"] == "" {
|
||||||
|
@ -70,11 +73,14 @@ func Search(h *wp.Handle, id string) string {
|
||||||
}
|
}
|
||||||
|
|
||||||
return args
|
return args
|
||||||
})
|
}
|
||||||
|
|
||||||
|
func Search(h *wp.Handle, id string) string {
|
||||||
|
args := GetSearchArgs(h, id)
|
||||||
s := strings.ReplaceAll(searchTemplate, "{$form}", form)
|
s := strings.ReplaceAll(searchTemplate, "{$form}", form)
|
||||||
val := ""
|
val := ""
|
||||||
if h.Scene() == constraints.Search {
|
if h.Scene() == constraints.Search {
|
||||||
val = html.SpecialChars(h.Index.Param.Search)
|
val = html.SpecialChars(h.GetIndexHandle().Param.Search)
|
||||||
}
|
}
|
||||||
s = strings.ReplaceAll(s, "{$value}", val)
|
s = strings.ReplaceAll(s, "{$value}", val)
|
||||||
return h.DoActionFilter(widgets.Search, str.Replace(s, args))
|
return h.DoActionFilter(widgets.Search, str.Replace(s, args))
|
||||||
|
|
|
@ -1,23 +0,0 @@
|
||||||
package widget
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/fthvgb1/wp-go/app/pkg/cache"
|
|
||||||
"github.com/fthvgb1/wp-go/app/pkg/constraints"
|
|
||||||
"github.com/fthvgb1/wp-go/app/pkg/models"
|
|
||||||
"github.com/fthvgb1/wp-go/app/theme/wp"
|
|
||||||
"github.com/fthvgb1/wp-go/helper/slice"
|
|
||||||
str "github.com/fthvgb1/wp-go/helper/strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
func IsTag(h *wp.Handle) (models.TermsMy, bool) {
|
|
||||||
if h.Scene() == constraints.Tag {
|
|
||||||
id := str.ToInt[uint64](h.C.Query("tag"))
|
|
||||||
i, t := slice.SearchFirst(cache.CategoriesTags(h.C, constraints.Tag), func(my models.TermsMy) bool {
|
|
||||||
return id == my.Terms.TermId
|
|
||||||
})
|
|
||||||
if i > 0 {
|
|
||||||
return t, true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return models.TermsMy{}, false
|
|
||||||
}
|
|
|
@ -3,32 +3,38 @@ package wp
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/fthvgb1/wp-go/app/cmd/reload"
|
|
||||||
"github.com/fthvgb1/wp-go/app/pkg/cache"
|
"github.com/fthvgb1/wp-go/app/pkg/cache"
|
||||||
"github.com/fthvgb1/wp-go/app/pkg/logs"
|
"github.com/fthvgb1/wp-go/app/pkg/logs"
|
||||||
"github.com/fthvgb1/wp-go/app/pkg/models"
|
"github.com/fthvgb1/wp-go/app/pkg/models"
|
||||||
"github.com/fthvgb1/wp-go/app/wpconfig"
|
"github.com/fthvgb1/wp-go/app/wpconfig"
|
||||||
|
"github.com/fthvgb1/wp-go/cache/reload"
|
||||||
"github.com/fthvgb1/wp-go/helper/slice"
|
"github.com/fthvgb1/wp-go/helper/slice"
|
||||||
str "github.com/fthvgb1/wp-go/helper/strings"
|
str "github.com/fthvgb1/wp-go/helper/strings"
|
||||||
"github.com/fthvgb1/wp-go/model"
|
"github.com/fthvgb1/wp-go/model"
|
||||||
"regexp"
|
"regexp"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (h *Handle) DisplayHeaderText() bool {
|
func (h *Handle) DisplayHeaderText() bool {
|
||||||
return h.themeMods.ThemeSupport.CustomHeader.HeaderText && "blank" != h.themeMods.HeaderTextcolor
|
return h.themeMods.ThemeSupport.CustomHeader.HeaderText && "blank" != h.themeMods.HeaderTextcolor
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var GetCustomHeaderImgFn = reload.BuildValFnWithConfirm("headerImages", customHeadImag, 5)
|
||||||
|
|
||||||
|
func customHeadImag(h *Handle) ([]models.PostThumbnail, bool) {
|
||||||
|
hs, err := h.GetHeaderImages(h.theme)
|
||||||
|
if err != nil {
|
||||||
|
h.SetErr(fmt.Errorf("get customheadimage err: %v", err), Low)
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
return hs, true
|
||||||
|
}
|
||||||
|
|
||||||
func (h *Handle) GetCustomHeaderImg() (r models.PostThumbnail, isRand bool) {
|
func (h *Handle) GetCustomHeaderImg() (r models.PostThumbnail, isRand bool) {
|
||||||
var err error
|
var err error
|
||||||
img := reload.GetAnyValBys("headerImages", h.theme, func(theme string) []models.PostThumbnail {
|
img := GetCustomHeaderImgFn(h)
|
||||||
hs, er := h.GetHeaderImages(h.theme)
|
err = h.Err()
|
||||||
if er != nil {
|
if err != nil && strings.Contains(err.Error(), "get customheadimage err") {
|
||||||
err = er
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return hs
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
logs.Error(err, "获取页眉背景图失败")
|
logs.Error(err, "获取页眉背景图失败")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -122,7 +128,7 @@ func CustomVideo(h *Handle, scene ...string) (ok bool) {
|
||||||
logs.Error(err, "get headerVideo fail", mod.HeaderVideo)
|
logs.Error(err, "get headerVideo fail", mod.HeaderVideo)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
scriptss := []string{
|
scripts := []string{
|
||||||
"/wp-includes/js/dist/vendor/wp-polyfill-inert.min.js",
|
"/wp-includes/js/dist/vendor/wp-polyfill-inert.min.js",
|
||||||
"/wp-includes/js/dist/vendor/regenerator-runtime.min.js",
|
"/wp-includes/js/dist/vendor/regenerator-runtime.min.js",
|
||||||
"/wp-includes/js/dist/vendor/wp-polyfill.min.js",
|
"/wp-includes/js/dist/vendor/wp-polyfill.min.js",
|
||||||
|
@ -132,10 +138,16 @@ func CustomVideo(h *Handle, scene ...string) (ok bool) {
|
||||||
"/wp-includes/js/dist/a11y.min.js",
|
"/wp-includes/js/dist/a11y.min.js",
|
||||||
"/wp-includes/js/wp-custom-header.min.js",
|
"/wp-includes/js/wp-custom-header.min.js",
|
||||||
}
|
}
|
||||||
scriptss = slice.Map(scriptss, func(t string) string {
|
scripts = slice.Map(scripts, func(t string) string {
|
||||||
return fmt.Sprintf(`<script src="%s" id="wp-%s-js"></script>
|
return fmt.Sprintf(`<script src="%s" id="wp-%s-js"></script>
|
||||||
`, t, str.Replaces(t, []string{
|
`, t, str.Replaces(t, []string{
|
||||||
"/wp-includes/js/dist/vendor/", "/wp-includes/js/dist/", "/wp-includes/js/", ".min.js", ".js", "wp-", "",
|
"/wp-includes/js/dist/vendor/",
|
||||||
|
"/wp-includes/js/dist/",
|
||||||
|
"/wp-includes/js/",
|
||||||
|
".min.js",
|
||||||
|
".js",
|
||||||
|
"wp-",
|
||||||
|
"",
|
||||||
}))
|
}))
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -154,10 +166,10 @@ wp.i18n.setLocaleData( { 'text direction\u0004ltr': [ 'ltr' ] } );
|
||||||
c := []Components[string]{
|
c := []Components[string]{
|
||||||
NewComponent("wp-a11y-js-translations", tr, true, 10.0065, nil),
|
NewComponent("wp-a11y-js-translations", tr, true, 10.0065, nil),
|
||||||
NewComponent("VideoSetting", hs, true, 10.0064, nil),
|
NewComponent("VideoSetting", hs, true, 10.0064, nil),
|
||||||
NewComponent("header-script", scriptss[len(scriptss)-1], true, 10.0063, nil),
|
NewComponent("header-script", scripts[len(scripts)-1], true, 10.0063, nil),
|
||||||
}
|
}
|
||||||
for _, s := range scene {
|
for _, s := range scene {
|
||||||
h.PushGroupFooterScript(s, "wp-custom-header", 10.0066, scriptss[0:len(scriptss)-2]...)
|
h.PushGroupFooterScript(s, "wp-custom-header", 10.0066, scripts[0:len(scripts)-2]...)
|
||||||
h.PushFooterScript(s, c...)
|
h.PushFooterScript(s, c...)
|
||||||
}
|
}
|
||||||
ok = true
|
ok = true
|
||||||
|
|
|
@ -2,9 +2,9 @@ package wp
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/fthvgb1/wp-go/app/cmd/reload"
|
|
||||||
"github.com/fthvgb1/wp-go/app/pkg/cache"
|
"github.com/fthvgb1/wp-go/app/pkg/cache"
|
||||||
"github.com/fthvgb1/wp-go/app/wpconfig"
|
"github.com/fthvgb1/wp-go/app/wpconfig"
|
||||||
|
"github.com/fthvgb1/wp-go/cache/reload"
|
||||||
"github.com/fthvgb1/wp-go/helper/maps"
|
"github.com/fthvgb1/wp-go/helper/maps"
|
||||||
str "github.com/fthvgb1/wp-go/helper/strings"
|
str "github.com/fthvgb1/wp-go/helper/strings"
|
||||||
)
|
)
|
||||||
|
@ -42,10 +42,10 @@ func CalCustomLogo(h *Handle) (r string) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var GetCustomLog = reload.BuildValFn("customLogo", CalCustomLogo)
|
||||||
|
|
||||||
func customLogo(h *Handle) func() string {
|
func customLogo(h *Handle) func() string {
|
||||||
return func() string {
|
return func() string {
|
||||||
return reload.GetAnyValBys("customLogo", h, func(h *Handle) string {
|
return GetCustomLog(h)
|
||||||
return CalCustomLogo(h)
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,106 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
/**
|
|
||||||
* wordpress/wp-includes/script-loader.php:632
|
|
||||||
* @var $scripts
|
|
||||||
*/
|
|
||||||
$con = 'package wp
|
|
||||||
import "github.com/fthvgb1/wp-go/safety"
|
|
||||||
|
|
||||||
func defaultScripts(m *safety.Map[string, *Script], suffix string){
|
|
||||||
|
|
||||||
';
|
|
||||||
foreach ($scripts->registered as $handle => $h) {
|
|
||||||
$dep = 'nil';
|
|
||||||
if ($h->deps) {
|
|
||||||
$dep = '[]string{';
|
|
||||||
$dep .= implode(',', array_map(fn($v) => '"' . $v . '"', $h->deps));
|
|
||||||
$dep .= '}';
|
|
||||||
}
|
|
||||||
$con .= sprintf('m.Store("%s", NewScript("%s", "%s"+suffix+".js", %s, "%s", %s))
|
|
||||||
', $handle, $h->handle, str_replace('.min.js', '', $h->src), $dep, $h->ver, $h->args ?: 'nil');
|
|
||||||
}
|
|
||||||
$con .= '}';
|
|
||||||
file_put_contents('/tmp/scriptLoad.go', $con);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* put code to wordpress/wp-includes/class-wp-scripts.php:504
|
|
||||||
* @param $handle
|
|
||||||
* @param $object_name
|
|
||||||
* @param $l10n
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
function parseLocalize($handle, $object_name, $l10n): void
|
|
||||||
{
|
|
||||||
if ('utils' != $handle) {
|
|
||||||
$s = array_map('parseArr', array_keys($l10n), array_values($l10n));
|
|
||||||
$m = implode("\n", $s);
|
|
||||||
$x = sprintf('AddStaticLocalize("%s","%s",map[string]any{
|
|
||||||
%s
|
|
||||||
})
|
|
||||||
', $handle, $object_name, $m);
|
|
||||||
file_put_contents('/tmp/bb.go', $x, FILE_APPEND);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function parseArr($k, $v): string
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* @var $this object
|
|
||||||
*/
|
|
||||||
if (is_array($v)) {
|
|
||||||
if (array_diff_key(array_values($v), $v)) {
|
|
||||||
$x = '';
|
|
||||||
foreach ($v as $kk => $vv) {
|
|
||||||
$x .= parseArr($kk, $vv);
|
|
||||||
}
|
|
||||||
return sprintf('"%s":map[string]any{
|
|
||||||
%s
|
|
||||||
},', $k, $x);
|
|
||||||
} else {
|
|
||||||
$s = array_map(fn($ss) => sprintf('"%s"', $ss), $v);
|
|
||||||
return sprintf('"%s":[]string{%s},', $k, implode(',', $s));
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
return sprintf('"%s":`%s`,', $k, $v);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* /var/www/html/wordpress/wp-includes/class-wp-theme-json.php:1712
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
function presetsMetadata()
|
|
||||||
{
|
|
||||||
$ss = <<<go
|
|
||||||
{
|
|
||||||
path: []string{%s},
|
|
||||||
preventOverride: []string{%s},
|
|
||||||
useDefaultNames: %s,
|
|
||||||
valueKey: "%s",
|
|
||||||
valueFunc: %s,
|
|
||||||
cssVars: "%s",
|
|
||||||
classes: map[string]string{
|
|
||||||
%s
|
|
||||||
},
|
|
||||||
properties: []string{%s},
|
|
||||||
},
|
|
||||||
go;
|
|
||||||
$s = '';
|
|
||||||
foreach (static::PRESETS_METADATA as $val) {
|
|
||||||
$arr = [];
|
|
||||||
$arr[] = implode(',', array_map(fn($v) => '"' . $v . '"', $val['path']));
|
|
||||||
$arr[] = (!$val['prevent_override']) ? '' : implode(',', array_map(fn($v) => '"' . $v . '"', $val['prevent_override']));
|
|
||||||
$arr[] = $val['use_default_names'] ? 'true' : 'false';
|
|
||||||
$arr[] = $val['value_key'] ?? '';
|
|
||||||
$arr[] = $val['value_func'] ?? 'nil';
|
|
||||||
$arr[] = $val['css_vars'];
|
|
||||||
$arr[] = implode(",\n", array_map(fn($k, $v) => sprintf('"%s":"%s"', $k, $v), array_keys($val['classes']), array_values($val['classes'])));
|
|
||||||
$arr[] = implode(',', array_map(fn($v) => '"' . $v . '"', $val['properties']));
|
|
||||||
$s .= sprintf($ss, ...$arr);
|
|
||||||
}
|
|
||||||
echo $s;
|
|
||||||
}
|
|
|
@ -10,18 +10,34 @@ import (
|
||||||
"github.com/fthvgb1/wp-go/app/plugins"
|
"github.com/fthvgb1/wp-go/app/plugins"
|
||||||
"github.com/fthvgb1/wp-go/app/plugins/wpposts"
|
"github.com/fthvgb1/wp-go/app/plugins/wpposts"
|
||||||
"github.com/fthvgb1/wp-go/app/wpconfig"
|
"github.com/fthvgb1/wp-go/app/wpconfig"
|
||||||
|
"github.com/fthvgb1/wp-go/cache/cachemanager"
|
||||||
|
"github.com/fthvgb1/wp-go/helper/number"
|
||||||
str "github.com/fthvgb1/wp-go/helper/strings"
|
str "github.com/fthvgb1/wp-go/helper/strings"
|
||||||
|
"github.com/fthvgb1/wp-go/plugin/pagination"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
type DetailHandle struct {
|
type DetailHandle struct {
|
||||||
*Handle
|
*Handle
|
||||||
CommentRender plugins.CommentHtml
|
CommentRender plugins.CommentHtml
|
||||||
Comments []models.Comments
|
Comments []uint64
|
||||||
|
Page int
|
||||||
|
Limit int
|
||||||
Post models.Posts
|
Post models.Posts
|
||||||
|
CommentPageEle pagination.Render
|
||||||
|
TotalRaw int
|
||||||
|
TotalPage int
|
||||||
|
CommentStep int
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewDetailHandle(handle *Handle) *DetailHandle {
|
func NewDetailHandle(handle *Handle) *DetailHandle {
|
||||||
return &DetailHandle{Handle: handle}
|
return &DetailHandle{
|
||||||
|
Handle: handle,
|
||||||
|
Page: 1,
|
||||||
|
Limit: 5,
|
||||||
|
CommentStep: 1,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *DetailHandle) BuildDetailData() (err error) {
|
func (d *DetailHandle) BuildDetailData() (err error) {
|
||||||
|
@ -30,7 +46,7 @@ func (d *DetailHandle) BuildDetailData() (err error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
d.Comment()
|
d.CommentData()
|
||||||
d.ContextPost()
|
d.ContextPost()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -68,12 +84,66 @@ func (d *DetailHandle) PasswordProject() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
func (d *DetailHandle) Comment() {
|
func (h *Handle) GetDetailHandle() *DetailHandle {
|
||||||
comments, err := cache.PostComments(d.C, d.Post.Id)
|
v, ok := h.C.Get("detailHandle")
|
||||||
logs.IfError(err, "get d.Post comment", d.Post.Id)
|
if !ok {
|
||||||
d.ginH["comments"] = comments
|
vv := NewDetailHandle(h)
|
||||||
d.Comments = comments
|
h.C.Set("detailHandle", vv)
|
||||||
|
return vv
|
||||||
|
}
|
||||||
|
return v.(*DetailHandle)
|
||||||
|
}
|
||||||
|
func (d *DetailHandle) CommentData() {
|
||||||
|
d.ginH["totalCommentNum"] = 0
|
||||||
|
d.ginH["totalCommentPage"] = 1
|
||||||
|
d.ginH["commentPageNav"] = ""
|
||||||
|
order := wpconfig.GetOption("comment_order")
|
||||||
|
d.ginH["commentOrder"] = order
|
||||||
|
d.Limit = str.ToInteger(wpconfig.GetOption("comments_per_page"), 5)
|
||||||
|
pageComments := wpconfig.GetOption("page_comments")
|
||||||
|
num, err := cachemanager.GetBy[int]("commentNumber", d.C, d.Post.Id, time.Second)
|
||||||
|
if err != nil {
|
||||||
|
d.SetErr(err, Low)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if num < 1 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
topNum, err := cachemanager.GetBy[int]("postTopCommentsNum", d.C, d.Post.Id, time.Second)
|
||||||
|
if err != nil {
|
||||||
|
d.SetErr(err, Low)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
d.TotalPage = number.DivideCeil(topNum, d.Limit)
|
||||||
|
if !strings.Contains(d.C.Request.URL.Path, "comment-page") {
|
||||||
|
defaultCommentsPage := wpconfig.GetOption("default_comments_page")
|
||||||
|
if order == "desc" && defaultCommentsPage == "oldest" || order == "asc" && defaultCommentsPage == "newest" {
|
||||||
|
d.C.AddParam("page", number.IntToString(d.TotalPage))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
d.Page = str.ToInteger(d.C.Param("page"), 1)
|
||||||
|
d.ginH["currentPage"] = d.Page
|
||||||
|
var key string
|
||||||
|
if pageComments != "1" {
|
||||||
|
key = number.IntToString(d.Post.Id)
|
||||||
|
d.Limit = 0
|
||||||
|
} else {
|
||||||
|
key = fmt.Sprintf("%d-%d-%d", d.Post.Id, d.Page, d.Limit)
|
||||||
|
}
|
||||||
|
d.ginH["page_comments"] = pageComments
|
||||||
|
d.ginH["totalCommentPage"] = d.TotalPage
|
||||||
|
if d.TotalPage < d.Page {
|
||||||
|
d.SetErr(errors.New("curren page above total page"), High)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
data, err := cache.PostTopLevelCommentIds(d.C, d.Post.Id, d.Page, d.Limit, topNum, order, key)
|
||||||
|
if err != nil {
|
||||||
|
d.SetErr(err, Low)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
d.TotalRaw = topNum
|
||||||
|
d.ginH["totalCommentNum"] = num
|
||||||
|
d.Comments = data
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *DetailHandle) RenderComment() {
|
func (d *DetailHandle) RenderComment() {
|
||||||
|
@ -86,9 +156,21 @@ func (d *DetailHandle) RenderComment() {
|
||||||
ableComment = false
|
ableComment = false
|
||||||
}
|
}
|
||||||
d.ginH["showComment"] = ableComment
|
d.ginH["showComment"] = ableComment
|
||||||
if len(d.Comments) > 0 && ableComment {
|
d.ginH["comments"] = ""
|
||||||
dep := str.ToInteger(wpconfig.GetOption("thread_comments_depth"), 5)
|
if len(d.Comments) < 0 || !ableComment {
|
||||||
d.ginH["comments"] = plugins.FormatComments(d.C, d.CommentRender, d.Comments, dep)
|
return
|
||||||
|
}
|
||||||
|
var err error
|
||||||
|
d.ginH["comments"], err = RenderComment(d.C, d.Page, d.CommentRender, d.Comments, 2*time.Second, d.IsHttps())
|
||||||
|
if err != nil {
|
||||||
|
d.SetErr(err, High)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if d.CommentPageEle == nil {
|
||||||
|
d.CommentPageEle = plugins.TwentyFifteenCommentPagination()
|
||||||
|
}
|
||||||
|
if wpconfig.GetOption("page_comments") == "1" && d.TotalPage > 1 {
|
||||||
|
d.ginH["commentPageNav"] = pagination.Paginate(d.CommentPageEle, d.TotalRaw, d.Limit, d.Page, d.CommentStep, *d.C.Request.URL, d.IsHttps())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -103,16 +185,17 @@ func DetailRender(h *Handle) {
|
||||||
if h.Stats != constraints.Ok {
|
if h.Stats != constraints.Ok {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
d := h.Detail
|
d := h.GetDetailHandle()
|
||||||
d.PasswordProject()
|
d.PasswordProject()
|
||||||
d.RenderComment()
|
d.RenderComment()
|
||||||
d.ginH["post"] = d.Post
|
d.ginH["post"] = d.Post
|
||||||
}
|
}
|
||||||
|
|
||||||
func Detail(h *Handle) {
|
func Detail(h *Handle) {
|
||||||
err := h.Detail.BuildDetailData()
|
d := h.GetDetailHandle()
|
||||||
|
err := d.BuildDetailData()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
h.Detail.SetErr(err)
|
d.SetErr(err, High)
|
||||||
}
|
}
|
||||||
h.SetData("scene", h.Scene())
|
h.SetData("scene", h.Scene())
|
||||||
}
|
}
|
||||||
|
@ -120,7 +203,7 @@ func Detail(h *Handle) {
|
||||||
func ReplyCommentJs(h *Handle) {
|
func ReplyCommentJs(h *Handle) {
|
||||||
h.PushFooterScript(constraints.Detail, NewComponent("comment-reply.js", "", false, 10, func(h *Handle) string {
|
h.PushFooterScript(constraints.Detail, NewComponent("comment-reply.js", "", false, 10, func(h *Handle) string {
|
||||||
reply := ""
|
reply := ""
|
||||||
if h.Detail.Post.CommentStatus == "open" && wpconfig.GetOption("thread_comments") == "1" {
|
if h.GetDetailHandle().Post.CommentStatus == "open" && wpconfig.GetOption("thread_comments") == "1" {
|
||||||
reply = `<script src='/wp-includes/js/comment-reply.min.js' id='comment-reply-js'></script>`
|
reply = `<script src='/wp-includes/js/comment-reply.min.js' id='comment-reply-js'></script>`
|
||||||
}
|
}
|
||||||
return reply
|
return reply
|
||||||
|
|
8
app/theme/wp/errorlevel.go
Normal file
8
app/theme/wp/errorlevel.go
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
package wp
|
||||||
|
|
||||||
|
const (
|
||||||
|
None = iota
|
||||||
|
Low
|
||||||
|
High
|
||||||
|
Fatal
|
||||||
|
)
|
|
@ -2,13 +2,14 @@ package wp
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
"github.com/fthvgb1/wp-go/safety"
|
||||||
)
|
)
|
||||||
|
|
||||||
var fnMap map[string]map[string]any
|
var fnMap = safety.NewMap[string, map[string]any]()
|
||||||
var fnHook map[string]map[string]any
|
var fnHook = safety.NewMap[string, map[string]any]()
|
||||||
|
|
||||||
func GetFn[T any](fnType string, name string) []T {
|
func GetFn[T any](fnType string, name string) []T {
|
||||||
v, ok := fnMap[fnType]
|
v, ok := fnMap.Load(fnType)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -19,7 +20,7 @@ func GetFn[T any](fnType string, name string) []T {
|
||||||
return vv.([]T)
|
return vv.([]T)
|
||||||
}
|
}
|
||||||
func GetFnHook[T any](fnType string, name string) []T {
|
func GetFnHook[T any](fnType string, name string) []T {
|
||||||
v, ok := fnHook[fnType]
|
v, ok := fnHook.Load(fnType)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -31,10 +32,10 @@ func GetFnHook[T any](fnType string, name string) []T {
|
||||||
}
|
}
|
||||||
|
|
||||||
func PushFn[T any](fnType string, name string, fns ...T) error {
|
func PushFn[T any](fnType string, name string, fns ...T) error {
|
||||||
v, ok := fnMap[fnType]
|
v, ok := fnMap.Load(fnType)
|
||||||
if !ok {
|
if !ok {
|
||||||
v = make(map[string]any)
|
v = make(map[string]any)
|
||||||
fnMap[fnType] = v
|
fnMap.Store(fnType, v)
|
||||||
v[name] = fns
|
v[name] = fns
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -52,10 +53,10 @@ func PushFn[T any](fnType string, name string, fns ...T) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func PushFnHook[T any](fnType string, name string, fns ...T) error {
|
func PushFnHook[T any](fnType string, name string, fns ...T) error {
|
||||||
v, ok := fnHook[fnType]
|
v, ok := fnHook.Load(fnType)
|
||||||
if !ok {
|
if !ok {
|
||||||
v = make(map[string]any)
|
v = make(map[string]any)
|
||||||
fnHook[fnType] = v
|
fnHook.Store(fnType, v)
|
||||||
v[name] = fns
|
v[name] = fns
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,12 +2,13 @@ package wp
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"database/sql"
|
"database/sql"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/fthvgb1/wp-go/app/cmd/reload"
|
|
||||||
"github.com/fthvgb1/wp-go/app/pkg/cache"
|
"github.com/fthvgb1/wp-go/app/pkg/cache"
|
||||||
"github.com/fthvgb1/wp-go/app/pkg/constraints"
|
"github.com/fthvgb1/wp-go/app/pkg/constraints"
|
||||||
"github.com/fthvgb1/wp-go/app/pkg/models"
|
"github.com/fthvgb1/wp-go/app/pkg/models"
|
||||||
"github.com/fthvgb1/wp-go/app/plugins"
|
"github.com/fthvgb1/wp-go/app/plugins"
|
||||||
|
"github.com/fthvgb1/wp-go/cache/reload"
|
||||||
"github.com/fthvgb1/wp-go/helper/number"
|
"github.com/fthvgb1/wp-go/helper/number"
|
||||||
"github.com/fthvgb1/wp-go/helper/slice"
|
"github.com/fthvgb1/wp-go/helper/slice"
|
||||||
"github.com/fthvgb1/wp-go/model"
|
"github.com/fthvgb1/wp-go/model"
|
||||||
|
@ -19,11 +20,21 @@ type IndexHandle struct {
|
||||||
*Handle
|
*Handle
|
||||||
Param *IndexParams
|
Param *IndexParams
|
||||||
Posts []models.Posts
|
Posts []models.Posts
|
||||||
pageEle pagination.Elements
|
pageEle pagination.Render
|
||||||
TotalRows int
|
TotalRows int
|
||||||
postsPlugin PostsPlugin
|
postsPlugin PostsPlugin
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (h *Handle) GetIndexHandle() *IndexHandle {
|
||||||
|
v, ok := h.C.Get("indexHandle")
|
||||||
|
if !ok {
|
||||||
|
vv := NewIndexHandle(h)
|
||||||
|
h.C.Set("indexHandle", vv)
|
||||||
|
return vv
|
||||||
|
}
|
||||||
|
return v.(*IndexHandle)
|
||||||
|
}
|
||||||
|
|
||||||
func (i *IndexHandle) ListPlugin() func(*Handle, *models.Posts) {
|
func (i *IndexHandle) ListPlugin() func(*Handle, *models.Posts) {
|
||||||
return i.postsPlugin
|
return i.postsPlugin
|
||||||
}
|
}
|
||||||
|
@ -32,11 +43,11 @@ func (i *IndexHandle) SetListPlugin(listPlugin func(*Handle, *models.Posts)) {
|
||||||
i.postsPlugin = listPlugin
|
i.postsPlugin = listPlugin
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *IndexHandle) PageEle() pagination.Elements {
|
func (i *IndexHandle) PageEle() pagination.Render {
|
||||||
return i.pageEle
|
return i.pageEle
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *IndexHandle) SetPageEle(pageEle pagination.Elements) {
|
func (i *IndexHandle) SetPageEle(pageEle pagination.Render) {
|
||||||
i.pageEle = pageEle
|
i.pageEle = pageEle
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -88,14 +99,14 @@ func (i *IndexHandle) GetIndexData() (posts []models.Posts, totalRaw int, err er
|
||||||
switch i.scene {
|
switch i.scene {
|
||||||
case constraints.Home, constraints.Category, constraints.Tag, constraints.Author:
|
case constraints.Home, constraints.Category, constraints.Tag, constraints.Author:
|
||||||
|
|
||||||
posts, totalRaw, err = cache.PostLists(i.C, i.Param.CacheKey, i.C, q, i.Param.Page, i.Param.PageSize)
|
posts, totalRaw, err = cache.PostLists(i.C, i.Param.CacheKey, q, i.Param.Page, i.Param.PageSize)
|
||||||
if i.scene == constraints.Home && i.Param.Page == 1 {
|
if i.scene == constraints.Home && i.Param.Page == 1 {
|
||||||
i.MarkSticky(&posts)
|
i.MarkSticky(&posts)
|
||||||
}
|
}
|
||||||
|
|
||||||
case constraints.Search:
|
case constraints.Search:
|
||||||
|
|
||||||
posts, totalRaw, err = cache.SearchPost(i.C, i.Param.CacheKey, i.C, q, i.Param.Page, i.Param.PageSize)
|
posts, totalRaw, err = cache.SearchPost(i.C, i.Param.CacheKey, q, i.Param.Page, i.Param.PageSize)
|
||||||
|
|
||||||
case constraints.Archive:
|
case constraints.Archive:
|
||||||
i.ginH["archiveYear"] = i.Param.Year
|
i.ginH["archiveYear"] = i.Param.Year
|
||||||
|
@ -115,34 +126,36 @@ func (i *IndexHandle) Pagination() {
|
||||||
if q != "" {
|
if q != "" {
|
||||||
q = fmt.Sprintf("?%s", q)
|
q = fmt.Sprintf("?%s", q)
|
||||||
}
|
}
|
||||||
paginations := pagination.NewParsePagination(i.TotalRows, i.Param.PageSize, i.Param.Page, i.Param.PaginationStep, q, i.C.Request.URL.Path)
|
i.ginH["pagination"] = pagination.Paginate(i.pageEle, i.TotalRows, i.Param.PageSize, i.Param.Page, i.Param.PaginationStep, *i.C.Request.URL, i.IsHttps())
|
||||||
i.ginH["pagination"] = pagination.Paginate(i.pageEle, paginations)
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *IndexHandle) BuildIndexData(parm *IndexParams) (err error) {
|
func (i *IndexHandle) BuildIndexData() (err error) {
|
||||||
err = i.ParseIndex(parm)
|
if i.Param == nil {
|
||||||
|
i.Param = NewIndexParams(i.C)
|
||||||
|
}
|
||||||
|
err = i.ParseIndex(i.Param)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
i.Stats = constraints.ParamError
|
i.Stats = constraints.ParamError
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
posts, totalRows, err := i.GetIndexData()
|
posts, totalRows, err := i.GetIndexData()
|
||||||
if err != nil && err != sql.ErrNoRows {
|
if err != nil && !errors.Is(err, sql.ErrNoRows) {
|
||||||
i.Stats = constraints.Error404
|
i.Stats = constraints.Error404
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
i.Posts = posts
|
i.Posts = posts
|
||||||
i.TotalRows = totalRows
|
i.TotalRows = totalRows
|
||||||
i.ginH["totalPage"] = number.CalTotalPage(totalRows, i.Param.PageSize)
|
i.ginH["totalPage"] = number.DivideCeil(totalRows, i.Param.PageSize)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var GetPostsPlugin = reload.BuildValFnWithAnyParams("postPlugins", UsePostsPlugins)
|
||||||
|
|
||||||
func (i *IndexHandle) ExecPostsPlugin() {
|
func (i *IndexHandle) ExecPostsPlugin() {
|
||||||
fn := i.postsPlugin
|
fn := i.postsPlugin
|
||||||
if fn == nil {
|
if fn == nil {
|
||||||
fn = reload.GetAnyValBys("postPlugins", i, func(a *IndexHandle) PostsPlugin {
|
fn = GetPostsPlugin()
|
||||||
return UsePostsPlugins()
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
for j := range i.Posts {
|
for j := range i.Posts {
|
||||||
fn(i.Handle, &i.Posts[j])
|
fn(i.Handle, &i.Posts[j])
|
||||||
|
@ -150,27 +163,27 @@ func (i *IndexHandle) ExecPostsPlugin() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func IndexRender(h *Handle) {
|
func IndexRender(h *Handle) {
|
||||||
i := h.Index
|
i := h.GetIndexHandle()
|
||||||
i.ExecPostsPlugin()
|
i.ExecPostsPlugin()
|
||||||
i.Pagination()
|
i.Pagination()
|
||||||
i.ginH["posts"] = i.Posts
|
i.ginH["posts"] = i.Posts
|
||||||
}
|
}
|
||||||
|
|
||||||
func Index(h *Handle) {
|
func Index(h *Handle) {
|
||||||
i := h.Index
|
i := h.GetIndexHandle()
|
||||||
err := i.BuildIndexData(NewIndexParams(i.C))
|
err := i.BuildIndexData()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
i.SetErr(err)
|
i.SetErr(err, High)
|
||||||
}
|
}
|
||||||
h.SetData("scene", h.Scene())
|
h.SetData("scene", h.Scene())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *IndexHandle) MarkSticky(posts *[]models.Posts) {
|
func (i *IndexHandle) MarkSticky(posts *[]models.Posts) {
|
||||||
a := i.StickPosts()
|
a := GetStickPosts(i.Handle)
|
||||||
if len(a) < 1 {
|
if len(a) < 1 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
m := i.StickMapPosts()
|
m := GetStickMapPosts(i.Handle)
|
||||||
*posts = append(a, slice.Filter(*posts, func(post models.Posts, _ int) bool {
|
*posts = append(a, slice.Filter(*posts, func(post models.Posts, _ int) bool {
|
||||||
_, ok := m[post.Id]
|
_, ok := m[post.Id]
|
||||||
return !ok
|
return !ok
|
||||||
|
|
|
@ -105,7 +105,6 @@ func NewIndexParams(ctx *gin.Context) *IndexParams {
|
||||||
|
|
||||||
func (i *IndexParams) ParseSearchs() {
|
func (i *IndexParams) ParseSearchs() {
|
||||||
s := i.Ctx.Query("s")
|
s := i.Ctx.Query("s")
|
||||||
if s != "" {
|
|
||||||
q := str.Join("%", s, "%")
|
q := str.Join("%", s, "%")
|
||||||
i.Where = append(i.Where, []string{
|
i.Where = append(i.Where, []string{
|
||||||
"and", "post_title", "like", q, "",
|
"and", "post_title", "like", q, "",
|
||||||
|
@ -116,7 +115,6 @@ func (i *IndexParams) ParseSearchs() {
|
||||||
i.Header = fmt.Sprintf("<span>%s</span>的搜索结果", s)
|
i.Header = fmt.Sprintf("<span>%s</span>的搜索结果", s)
|
||||||
i.setTitleLR(str.Join(`"`, s, `"`, "的搜索结果"), i.BlogName)
|
i.setTitleLR(str.Join(`"`, s, `"`, "的搜索结果"), i.BlogName)
|
||||||
i.Search = s
|
i.Search = s
|
||||||
}
|
|
||||||
}
|
}
|
||||||
func (i *IndexParams) ParseArchives() error {
|
func (i *IndexParams) ParseArchives() error {
|
||||||
year := i.Ctx.Param("year")
|
year := i.Ctx.Param("year")
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
package wp
|
package wp
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/fthvgb1/wp-go/app/cmd/reload"
|
|
||||||
"github.com/fthvgb1/wp-go/app/pkg/config"
|
"github.com/fthvgb1/wp-go/app/pkg/config"
|
||||||
"github.com/fthvgb1/wp-go/app/pkg/models"
|
"github.com/fthvgb1/wp-go/app/pkg/models"
|
||||||
"github.com/fthvgb1/wp-go/app/plugins"
|
"github.com/fthvgb1/wp-go/app/plugins"
|
||||||
"github.com/fthvgb1/wp-go/app/plugins/wpposts"
|
"github.com/fthvgb1/wp-go/app/plugins/wpposts"
|
||||||
|
"github.com/fthvgb1/wp-go/cache/reload"
|
||||||
"github.com/fthvgb1/wp-go/helper/maps"
|
"github.com/fthvgb1/wp-go/helper/maps"
|
||||||
"github.com/fthvgb1/wp-go/helper/slice"
|
"github.com/fthvgb1/wp-go/helper/slice"
|
||||||
)
|
)
|
||||||
|
@ -23,7 +23,7 @@ func PostsPlugins(initial PostsPlugin, calls ...func(PostsPlugin, *Handle, *mode
|
||||||
var pluginFns = reload.Vars(map[string]func(PostsPlugin, *Handle, *models.Posts){
|
var pluginFns = reload.Vars(map[string]func(PostsPlugin, *Handle, *models.Posts){
|
||||||
"passwordProject": PasswordProject,
|
"passwordProject": PasswordProject,
|
||||||
"digest": Digest,
|
"digest": Digest,
|
||||||
})
|
}, "list-post-plugins-fns")
|
||||||
|
|
||||||
func (h *Handle) PushPostsPlugin(name string, fn func(PostsPlugin, *Handle, *models.Posts)) {
|
func (h *Handle) PushPostsPlugin(name string, fn func(PostsPlugin, *Handle, *models.Posts)) {
|
||||||
m := pluginFns.Load()
|
m := pluginFns.Load()
|
||||||
|
@ -53,7 +53,7 @@ func Digest(next PostsPlugin, h *Handle, post *models.Posts) {
|
||||||
next(h, post)
|
next(h, post)
|
||||||
}
|
}
|
||||||
|
|
||||||
var ordinaryPlugin = reload.Vars([]PostsPlugin{})
|
var ordinaryPlugin = reload.Vars([]PostsPlugin{}, "ordinaryPlugin")
|
||||||
|
|
||||||
func (h *Handle) PushPostPlugin(plugin ...PostsPlugin) {
|
func (h *Handle) PushPostPlugin(plugin ...PostsPlugin) {
|
||||||
p := ordinaryPlugin.Load()
|
p := ordinaryPlugin.Load()
|
||||||
|
@ -69,7 +69,7 @@ func PostPlugin(calls ...PostsPlugin) PostsPlugin {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func UsePostsPlugins() PostsPlugin {
|
func UsePostsPlugins(_ ...any) PostsPlugin {
|
||||||
m := pluginFns.Load()
|
m := pluginFns.Load()
|
||||||
pluginss := slice.FilterAndMap(config.GetConfig().ListPagePlugins, func(t string) (func(PostsPlugin, *Handle, *models.Posts), bool) {
|
pluginss := slice.FilterAndMap(config.GetConfig().ListPagePlugins, func(t string) (func(PostsPlugin, *Handle, *models.Posts), bool) {
|
||||||
f, ok := m[t]
|
f, ok := m[t]
|
||||||
|
|
167
app/theme/wp/middleware/middleware.go
Normal file
167
app/theme/wp/middleware/middleware.go
Normal file
|
@ -0,0 +1,167 @@
|
||||||
|
package middleware
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/fthvgb1/wp-go/app/pkg/cache"
|
||||||
|
"github.com/fthvgb1/wp-go/app/pkg/constraints"
|
||||||
|
"github.com/fthvgb1/wp-go/app/theme/wp"
|
||||||
|
"github.com/fthvgb1/wp-go/app/theme/wp/components/widget"
|
||||||
|
"github.com/fthvgb1/wp-go/app/theme/wp/route"
|
||||||
|
"github.com/fthvgb1/wp-go/cache/reload"
|
||||||
|
"github.com/fthvgb1/wp-go/helper/maps"
|
||||||
|
"github.com/fthvgb1/wp-go/helper/number"
|
||||||
|
str "github.com/fthvgb1/wp-go/helper/strings"
|
||||||
|
"net/http"
|
||||||
|
"strconv"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
var plainRouteParam = reload.Vars([]Plain{
|
||||||
|
{
|
||||||
|
Action: "p",
|
||||||
|
Param: map[string]string{
|
||||||
|
"p": "id",
|
||||||
|
"cpage": "page",
|
||||||
|
},
|
||||||
|
Scene: constraints.Detail,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Action: "s",
|
||||||
|
Scene: constraints.Search,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Scene: constraints.Category,
|
||||||
|
Fn: func(h *wp.Handle) bool {
|
||||||
|
c, ok := widget.IsCategory(h)
|
||||||
|
if !ok {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
h.C.AddParam("category", c.Name)
|
||||||
|
h.C.AddParam("page", h.C.Query("paged"))
|
||||||
|
return true
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Scene: constraints.Tag,
|
||||||
|
Action: "tag",
|
||||||
|
Param: map[string]string{
|
||||||
|
"tag": "tag",
|
||||||
|
"paged": "page",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Scene: constraints.Archive,
|
||||||
|
Fn: func(h *wp.Handle) bool {
|
||||||
|
m := h.C.Query("m")
|
||||||
|
if m == "" {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
t, err := time.Parse("200601", m)
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
h.C.AddParam("year", strconv.Itoa(t.Year()))
|
||||||
|
h.C.AddParam("month", number.IntToString(t.Month()))
|
||||||
|
h.C.AddParam("page", h.C.Query("paged"))
|
||||||
|
return true
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Scene: constraints.Author,
|
||||||
|
Fn: func(h *wp.Handle) bool {
|
||||||
|
u := h.C.Query("author")
|
||||||
|
if u == "" {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
users := GetUsersIds(h)
|
||||||
|
name, ok := users[str.ToInteger[uint64](u, 0)]
|
||||||
|
if !ok {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
h.C.AddParam("author", name)
|
||||||
|
h.C.AddParam("page", h.C.Query("paged"))
|
||||||
|
return true
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}, "plainRouteParam")
|
||||||
|
|
||||||
|
var GetUsersIds = reload.BuildValFnWithConfirm("usersIds", func(h *wp.Handle) (map[uint64]string, bool) {
|
||||||
|
users, err := cache.GetAllUsername(h.C)
|
||||||
|
if err != nil {
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
return maps.Flip(users), true
|
||||||
|
}, 10)
|
||||||
|
|
||||||
|
func SetExplainRouteParam(p []Plain) {
|
||||||
|
plainRouteParam.Store(p)
|
||||||
|
}
|
||||||
|
func GetExplainRouteParam() []Plain {
|
||||||
|
return plainRouteParam.Load()
|
||||||
|
}
|
||||||
|
func PushExplainRouteParam(explain ...Plain) {
|
||||||
|
v := plainRouteParam.Load()
|
||||||
|
v = append(v, explain...)
|
||||||
|
plainRouteParam.Store(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
type Plain struct {
|
||||||
|
Action string
|
||||||
|
Param map[string]string
|
||||||
|
Scene string
|
||||||
|
Fn func(h *wp.Handle) bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func MixWithPlain(h *wp.Handle) {
|
||||||
|
for _, explain := range plainRouteParam.Load() {
|
||||||
|
if explain.Action == "" && explain.Fn == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if explain.Fn != nil {
|
||||||
|
if !explain.Fn(h) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if explain.Scene != "" {
|
||||||
|
h.SetScene(explain.Scene)
|
||||||
|
}
|
||||||
|
wp.Run(h, nil)
|
||||||
|
h.Abort()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if explain.Scene == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
q := h.C.Query(explain.Action)
|
||||||
|
if q == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
h.SetScene(explain.Scene)
|
||||||
|
for query, param := range explain.Param {
|
||||||
|
h.C.AddParam(param, h.C.Query(query))
|
||||||
|
}
|
||||||
|
wp.Run(h, nil)
|
||||||
|
h.Abort()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func ShowPreComment(h *wp.Handle) {
|
||||||
|
v, ok := cache.NewCommentCache().Get(h.C, h.C.Request.URL.RawQuery)
|
||||||
|
if ok {
|
||||||
|
h.C.Writer.Header().Set("Content-Type", "text/html; charset=utf-8")
|
||||||
|
h.C.Writer.WriteHeader(http.StatusOK)
|
||||||
|
_, _ = h.C.Writer.Write([]byte(v))
|
||||||
|
h.Abort()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func CommonMiddleware(h *wp.Handle) {
|
||||||
|
h.PushHandler(constraints.PipeMiddleware, constraints.Home,
|
||||||
|
wp.NewHandleFn(MixWithPlain, 100, "middleware.MixWithPlain"),
|
||||||
|
)
|
||||||
|
h.PushHandler(constraints.PipeMiddleware, constraints.Detail,
|
||||||
|
wp.NewHandleFn(ShowPreComment, 100, "middleware.ShowPreComment"),
|
||||||
|
)
|
||||||
|
h.PushHandler(constraints.PipeMiddleware, constraints.NoRoute,
|
||||||
|
wp.NewHandleFn(route.ResolveRoute, 100, "route.ResolveRoute"),
|
||||||
|
)
|
||||||
|
}
|
|
@ -1,9 +1,8 @@
|
||||||
package wp
|
package wp
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/fthvgb1/wp-go/app/cmd/reload"
|
|
||||||
"github.com/fthvgb1/wp-go/app/pkg/constraints"
|
"github.com/fthvgb1/wp-go/app/pkg/constraints"
|
||||||
"github.com/fthvgb1/wp-go/helper"
|
"github.com/fthvgb1/wp-go/cache/reload"
|
||||||
"github.com/fthvgb1/wp-go/helper/slice"
|
"github.com/fthvgb1/wp-go/helper/slice"
|
||||||
str "github.com/fthvgb1/wp-go/helper/strings"
|
str "github.com/fthvgb1/wp-go/helper/strings"
|
||||||
)
|
)
|
||||||
|
@ -22,7 +21,7 @@ func NewPipe(name string, order float64, fn HandlePipeFn[*Handle]) Pipe {
|
||||||
|
|
||||||
// HandlePipe 方便把功能写在其它包里
|
// HandlePipe 方便把功能写在其它包里
|
||||||
func HandlePipe[T any](initial func(T), fns ...HandlePipeFn[T]) HandleFn[T] {
|
func HandlePipe[T any](initial func(T), fns ...HandlePipeFn[T]) HandleFn[T] {
|
||||||
return slice.ReverseReduce(fns, func(next HandlePipeFn[T], f func(t T)) func(t T) {
|
return slice.ReverseReduce(fns, func(next HandlePipeFn[T], f HandleFn[T]) HandleFn[T] {
|
||||||
return func(t T) {
|
return func(t T) {
|
||||||
next(f, t)
|
next(f, t)
|
||||||
}
|
}
|
||||||
|
@ -52,10 +51,12 @@ func (h *Handle) ReplacePipe(scene, pipeName string, pipe Pipe) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *Handle) PushHandler(pipScene string, scene string, fns ...HandleCall) {
|
func (h *Handle) PushHandler(pipScene string, scene string, fns ...HandleCall) {
|
||||||
if _, ok := h.handlers[pipScene]; !ok {
|
v, ok := handlerss.Load(pipScene)
|
||||||
h.handlers[pipScene] = make(map[string][]HandleCall)
|
if !ok {
|
||||||
|
v = make(map[string][]HandleCall)
|
||||||
}
|
}
|
||||||
h.handlers[pipScene][scene] = append(h.handlers[pipScene][scene], fns...)
|
v[scene] = append(v[scene], fns...)
|
||||||
|
handlerss.Store(pipScene, v)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *Handle) PushRender(statsOrScene string, fns ...HandleCall) {
|
func (h *Handle) PushRender(statsOrScene string, fns ...HandleCall) {
|
||||||
|
@ -65,27 +66,16 @@ func (h *Handle) PushDataHandler(scene string, fns ...HandleCall) {
|
||||||
h.PushHandler(constraints.PipeData, scene, fns...)
|
h.PushHandler(constraints.PipeData, scene, fns...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func BuildPipe(pipeScene string, keyFn func(*Handle, string) string, fn func(*Handle, map[string][]HandleCall, string) []HandleCall) func(HandleFn[*Handle], *Handle) {
|
func BuildHandlers(pipeScene string, keyFn func(*Handle, string) string,
|
||||||
|
handleHookFn func(*Handle, string,
|
||||||
|
map[string][]func(HandleCall) (HandleCall, bool),
|
||||||
|
map[string][]HandleCall) []HandleCall) func(HandleFn[*Handle], *Handle) {
|
||||||
|
|
||||||
|
pipeHandlerFn := reload.BuildMapFn[string]("pipeHandlers", BuildHandler(pipeScene, keyFn, handleHookFn))
|
||||||
|
|
||||||
return func(next HandleFn[*Handle], h *Handle) {
|
return func(next HandleFn[*Handle], h *Handle) {
|
||||||
key := keyFn(h, pipeScene)
|
key := keyFn(h, pipeScene)
|
||||||
handlers := reload.GetAnyValMapBy("pipeHandlers", key, h, func(h *Handle) []HandleCall {
|
handlers := pipeHandlerFn(key, h)
|
||||||
conf := h.handleHook[pipeScene]
|
|
||||||
calls := fn(h, h.handlers[pipeScene], key)
|
|
||||||
calls = slice.FilterAndMap(calls, func(call HandleCall) (HandleCall, bool) {
|
|
||||||
ok := true
|
|
||||||
for _, hook := range conf {
|
|
||||||
call, ok = hook(call)
|
|
||||||
if !ok {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return call, ok
|
|
||||||
})
|
|
||||||
slice.Sort(calls, func(i, j HandleCall) bool {
|
|
||||||
return i.Order > j.Order
|
|
||||||
})
|
|
||||||
return calls
|
|
||||||
})
|
|
||||||
for _, handler := range handlers {
|
for _, handler := range handlers {
|
||||||
handler.Fn(h)
|
handler.Fn(h)
|
||||||
if h.abort {
|
if h.abort {
|
||||||
|
@ -98,22 +88,63 @@ func BuildPipe(pipeScene string, keyFn func(*Handle, string) string, fn func(*Ha
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func BuildHandler(pipeScene string, keyFn func(*Handle, string) string,
|
||||||
|
handleHook func(*Handle, string,
|
||||||
|
map[string][]func(HandleCall) (HandleCall, bool),
|
||||||
|
map[string][]HandleCall) []HandleCall) func(*Handle) []HandleCall {
|
||||||
|
|
||||||
|
return func(h *Handle) []HandleCall {
|
||||||
|
key := keyFn(h, pipeScene)
|
||||||
|
mut := reload.GetGlobeMutex()
|
||||||
|
mut.Lock()
|
||||||
|
pipeHookers, _ := handleHooks.Load(pipeScene)
|
||||||
|
pipeHandlers, _ := handlerss.Load(pipeScene)
|
||||||
|
mut.Unlock()
|
||||||
|
calls := handleHook(h, key, pipeHookers, pipeHandlers)
|
||||||
|
slice.SimpleSort(calls, slice.DESC, func(t HandleCall) float64 {
|
||||||
|
return t.Order
|
||||||
|
})
|
||||||
|
return calls
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func HookHandles(hooks map[string][]func(HandleCall) (HandleCall, bool),
|
||||||
|
handlers map[string][]HandleCall, sceneOrStats ...string) []HandleCall {
|
||||||
|
|
||||||
|
hookedHandlers := slice.FilterAndMap(sceneOrStats, func(k string) ([]HandleCall, bool) {
|
||||||
|
r := handlers[k]
|
||||||
|
for _, hook := range hooks[k] {
|
||||||
|
r = slice.FilterAndMap(r, hook)
|
||||||
|
}
|
||||||
|
return r, true
|
||||||
|
})
|
||||||
|
return slice.Decompress(hookedHandlers)
|
||||||
|
}
|
||||||
|
|
||||||
func PipeKey(h *Handle, pipScene string) string {
|
func PipeKey(h *Handle, pipScene string) string {
|
||||||
key := str.Join("pipekey", "-", pipScene, "-", h.scene, "-", h.Stats)
|
key := str.Join("pipekey", "-", pipScene, "-", h.scene, "-", h.Stats)
|
||||||
return h.DoActionFilter("pipeKey", key, pipScene)
|
return h.DoActionFilter("pipeKey", key, pipScene)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var pipeInitFn = reload.BuildMapFn[string]("pipeInit", BuildPipe)
|
||||||
|
|
||||||
func Run(h *Handle, conf func(*Handle)) {
|
func Run(h *Handle, conf func(*Handle)) {
|
||||||
if !helper.GetContextVal(h.C, "inited", false) {
|
if !h.isInited {
|
||||||
InitHandle(conf, h)
|
InitHandle(conf, h)
|
||||||
}
|
}
|
||||||
reload.GetAnyValBys(str.Join("pipeInit-", h.scene), h, func(h *Handle) func(*Handle) {
|
pipeInitFn(h.scene, h.scene)(h)
|
||||||
p := GetFn[Pipe]("pipe", constraints.AllScene)
|
}
|
||||||
p = append(p, GetFn[Pipe]("pipe", h.scene)...)
|
|
||||||
pipes := slice.FilterAndMap(p, func(pipe Pipe) (Pipe, bool) {
|
func BuildPipe(scene string) func(*Handle) {
|
||||||
|
pipees := GetFn[Pipe]("pipe", constraints.AllScene)
|
||||||
|
pipees = append(pipees, GetFn[Pipe]("pipe", scene)...)
|
||||||
|
pipes := slice.FilterAndMap(pipees, func(pipe Pipe) (Pipe, bool) {
|
||||||
var ok bool
|
var ok bool
|
||||||
|
mut := reload.GetGlobeMutex()
|
||||||
|
mut.Lock()
|
||||||
hooks := GetFnHook[func(Pipe) (Pipe, bool)]("pipeHook", constraints.AllScene)
|
hooks := GetFnHook[func(Pipe) (Pipe, bool)]("pipeHook", constraints.AllScene)
|
||||||
hooks = append(hooks, GetFnHook[func(Pipe) (Pipe, bool)]("pipeHook", h.scene)...)
|
hooks = append(hooks, GetFnHook[func(Pipe) (Pipe, bool)]("pipeHook", scene)...)
|
||||||
|
mut.Unlock()
|
||||||
for _, fn := range hooks {
|
for _, fn := range hooks {
|
||||||
pipe, ok = fn(pipe)
|
pipe, ok = fn(pipe)
|
||||||
if !ok {
|
if !ok {
|
||||||
|
@ -122,63 +153,76 @@ func Run(h *Handle, conf func(*Handle)) {
|
||||||
}
|
}
|
||||||
return pipe, pipe.Fn != nil
|
return pipe, pipe.Fn != nil
|
||||||
})
|
})
|
||||||
slice.Sort(pipes, func(i, j Pipe) bool {
|
slice.SimpleSort(pipes, slice.DESC, func(t Pipe) float64 {
|
||||||
return i.Order > j.Order
|
return t.Order
|
||||||
})
|
})
|
||||||
|
|
||||||
arr := slice.Map(pipes, func(t Pipe) HandlePipeFn[*Handle] {
|
arr := slice.Map(pipes, func(t Pipe) HandlePipeFn[*Handle] {
|
||||||
return t.Fn
|
return t.Fn
|
||||||
})
|
})
|
||||||
return HandlePipe(NothingToDo, arr...)
|
return HandlePipe(NothingToDo, arr...)
|
||||||
})(h)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func MiddlewareKey(h *Handle, pipScene string) string {
|
func MiddlewareKey(h *Handle, pipScene string) string {
|
||||||
return h.DoActionFilter("middleware", "middleware", pipScene)
|
return h.DoActionFilter("middleware", str.Join("pipe-middleware-", h.scene), pipScene)
|
||||||
}
|
}
|
||||||
|
|
||||||
func PipeMiddlewareHandle(h *Handle, middlewares map[string][]HandleCall, key string) (handlers []HandleCall) {
|
func PipeMiddlewareHandle(h *Handle, key string,
|
||||||
handlers = append(handlers, middlewares[h.scene]...)
|
hooks map[string][]func(HandleCall) (HandleCall, bool),
|
||||||
handlers = append(handlers, middlewares[constraints.AllScene]...)
|
handlers map[string][]HandleCall) []HandleCall {
|
||||||
handlers = h.PipeHandleHook("PipeMiddlewareHandle", handlers, middlewares, key)
|
hookedHandles := HookHandles(hooks, handlers, h.scene, constraints.AllScene)
|
||||||
return
|
return h.PipeHandleHook("PipeMiddlewareHandle", hookedHandles, handlers, key)
|
||||||
}
|
}
|
||||||
|
|
||||||
func PipeDataHandle(h *Handle, dataHandlers map[string][]HandleCall, key string) (handlers []HandleCall) {
|
func PipeDataHandle(h *Handle, key string,
|
||||||
handlers = append(handlers, dataHandlers[h.scene]...)
|
hooks map[string][]func(HandleCall) (HandleCall, bool),
|
||||||
handlers = append(handlers, dataHandlers[constraints.AllScene]...)
|
handlers map[string][]HandleCall) []HandleCall {
|
||||||
handlers = h.PipeHandleHook("PipeDataHandle", handlers, dataHandlers, key)
|
hookedHandles := HookHandles(hooks, handlers, h.scene, constraints.AllScene)
|
||||||
return
|
return h.PipeHandleHook("PipeDataHandle", hookedHandles, handlers, key)
|
||||||
}
|
}
|
||||||
|
|
||||||
func PipeRender(h *Handle, renders map[string][]HandleCall, key string) (handlers []HandleCall) {
|
func PipeRender(h *Handle, key string,
|
||||||
handlers = append(handlers, renders[h.Stats]...)
|
hooks map[string][]func(HandleCall) (HandleCall, bool),
|
||||||
handlers = append(handlers, renders[h.scene]...)
|
handlers map[string][]HandleCall) []HandleCall {
|
||||||
handlers = append(handlers, renders[constraints.AllStats]...)
|
hookedHandles := HookHandles(hooks, handlers, h.scene, h.Stats, constraints.AllScene, constraints.AllStats)
|
||||||
handlers = append(handlers, renders[constraints.AllScene]...)
|
return h.PipeHandleHook("PipeRender", hookedHandles, handlers, key)
|
||||||
handlers = h.PipeHandleHook("PipeRender", handlers, renders, key)
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteHandle 写插件的时候用
|
// DeleteHandle 写插件的时候用
|
||||||
func (h *Handle) DeleteHandle(pipeScene string, name string) {
|
func (h *Handle) DeleteHandle(pipeScene, scene, name string) {
|
||||||
h.handleHook[pipeScene] = append(h.handleHook[pipeScene], func(call HandleCall) (HandleCall, bool) {
|
v, ok := handleHooks.Load(pipeScene)
|
||||||
|
if !ok {
|
||||||
|
v = make(map[string][]func(HandleCall) (HandleCall, bool))
|
||||||
|
}
|
||||||
|
v[scene] = append(v[scene], func(call HandleCall) (HandleCall, bool) {
|
||||||
return call, name != call.Name
|
return call, name != call.Name
|
||||||
})
|
})
|
||||||
|
handleHooks.Store(pipeScene, v)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ReplaceHandle 写插件的时候用
|
// ReplaceHandle 写插件的时候用
|
||||||
func (h *Handle) ReplaceHandle(pipeScene, name string, fn HandleFn[*Handle]) {
|
func (h *Handle) ReplaceHandle(pipeScene, scene, name string, fn HandleFn[*Handle]) {
|
||||||
h.handleHook[pipeScene] = append(h.handleHook[pipeScene], func(call HandleCall) (HandleCall, bool) {
|
v, ok := handleHooks.Load(pipeScene)
|
||||||
|
if !ok {
|
||||||
|
v = make(map[string][]func(HandleCall) (HandleCall, bool))
|
||||||
|
}
|
||||||
|
v[scene] = append(v[scene], func(call HandleCall) (HandleCall, bool) {
|
||||||
if name == call.Name {
|
if name == call.Name {
|
||||||
call.Fn = fn
|
call.Fn = fn
|
||||||
}
|
}
|
||||||
return call, true
|
return call, true
|
||||||
})
|
})
|
||||||
|
handleHooks.Store(pipeScene, v)
|
||||||
}
|
}
|
||||||
|
|
||||||
// HookHandle 写插件的时候用
|
// HookHandle 写插件的时候用
|
||||||
func (h *Handle) HookHandle(pipeScene string, hook func(HandleCall) (HandleCall, bool)) {
|
func (h *Handle) HookHandle(pipeScene, scene string, hook func(HandleCall) (HandleCall, bool)) {
|
||||||
h.handleHook[pipeScene] = append(h.handleHook[pipeScene], hook)
|
v, ok := handleHooks.Load(pipeScene)
|
||||||
|
if !ok {
|
||||||
|
v = make(map[string][]func(HandleCall) (HandleCall, bool))
|
||||||
|
}
|
||||||
|
v[scene] = append(v[scene], hook)
|
||||||
|
handleHooks.Store(pipeScene, v)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *Handle) PushPipeHandleHook(name string, fn ...func([]HandleCall) []HandleCall) error {
|
func (h *Handle) PushPipeHandleHook(name string, fn ...func([]HandleCall) []HandleCall) error {
|
||||||
|
@ -193,11 +237,11 @@ func (h *Handle) PipeHandleHook(name string, calls []HandleCall, m map[string][]
|
||||||
}
|
}
|
||||||
|
|
||||||
func InitPipe(h *Handle) {
|
func InitPipe(h *Handle) {
|
||||||
h.PushPipe(constraints.Home, NewPipe(constraints.PipeMiddleware, 300,
|
h.PushPipe(constraints.AllScene, NewPipe(constraints.PipeMiddleware, 300,
|
||||||
BuildPipe(constraints.PipeMiddleware, MiddlewareKey, PipeMiddlewareHandle)))
|
BuildHandlers(constraints.PipeMiddleware, MiddlewareKey, PipeMiddlewareHandle)))
|
||||||
|
|
||||||
h.PushPipe(constraints.AllScene, NewPipe(constraints.PipeData, 200,
|
h.PushPipe(constraints.AllScene, NewPipe(constraints.PipeData, 200,
|
||||||
BuildPipe(constraints.PipeData, PipeKey, PipeDataHandle)))
|
BuildHandlers(constraints.PipeData, PipeKey, PipeDataHandle)))
|
||||||
h.PushPipe(constraints.AllScene, NewPipe(constraints.PipeRender, 100,
|
h.PushPipe(constraints.AllScene, NewPipe(constraints.PipeRender, 100,
|
||||||
BuildPipe(constraints.PipeRender, PipeKey, PipeRender)))
|
BuildHandlers(constraints.PipeRender, PipeKey, PipeRender)))
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,16 @@
|
||||||
package route
|
package route
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/fthvgb1/wp-go/app/cmd/reload"
|
|
||||||
"github.com/fthvgb1/wp-go/app/theme/wp"
|
"github.com/fthvgb1/wp-go/app/theme/wp"
|
||||||
|
"github.com/fthvgb1/wp-go/cache/reload"
|
||||||
"github.com/fthvgb1/wp-go/helper/slice"
|
"github.com/fthvgb1/wp-go/helper/slice"
|
||||||
"github.com/fthvgb1/wp-go/safety"
|
"github.com/fthvgb1/wp-go/safety"
|
||||||
|
"net/http"
|
||||||
"regexp"
|
"regexp"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Route
|
||||||
|
// Type value equal const or reg
|
||||||
type Route struct {
|
type Route struct {
|
||||||
Path string
|
Path string
|
||||||
Scene string
|
Scene string
|
||||||
|
@ -20,18 +23,18 @@ var routeHook []func(Route) (Route, bool)
|
||||||
var regRoutes *safety.Map[string, *regexp.Regexp]
|
var regRoutes *safety.Map[string, *regexp.Regexp]
|
||||||
var routes = func() *safety.Map[string, Route] {
|
var routes = func() *safety.Map[string, Route] {
|
||||||
r := safety.NewMap[string, Route]()
|
r := safety.NewMap[string, Route]()
|
||||||
reload.Push(func() {
|
reload.Append(func() {
|
||||||
r.Flush()
|
r.Flush()
|
||||||
regRoutes.Flush()
|
regRoutes.Flush()
|
||||||
})
|
}, "wp-routers")
|
||||||
regRoutes = safety.NewMap[string, *regexp.Regexp]()
|
regRoutes = safety.NewMap[string, *regexp.Regexp]()
|
||||||
return r
|
return r
|
||||||
}()
|
}()
|
||||||
|
|
||||||
// PushRoute path can be const or regex string
|
// PushRoute path can be const or regex string
|
||||||
//
|
//
|
||||||
// eg: `(?P<control>\w+)/(?P<method>\w+)`, route.Route{
|
// eg: `(?P<controller>\w+)/(?P<method>\w+)`, route.Route{
|
||||||
// Path: `(?P<control>\w+)/(?P<method>\w+)`,
|
// Path: `(?P<controller>\w+)/(?P<method>\w+)`,
|
||||||
// Scene: constraints.Home,
|
// Scene: constraints.Home,
|
||||||
// Method: []string{"GET"},
|
// Method: []string{"GET"},
|
||||||
// Type: "reg",
|
// Type: "reg",
|
||||||
|
@ -70,11 +73,10 @@ func Hook(path string, fn func(Route) Route) {
|
||||||
return r, path == r.Path
|
return r, path == r.Path
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
func ResolveRoute(h *wp.Handle) {
|
|
||||||
requestURI := h.C.Request.RequestURI
|
var RegRouteFn = reload.BuildValFnWithAnyParams("regexRoute", RegRouteHook)
|
||||||
rs, rrs := reload.GetAnyValBys("route",
|
|
||||||
struct{}{},
|
func RegRouteHook(_ ...any) func() (map[string]Route, map[string]*regexp.Regexp) {
|
||||||
func(_ struct{}) func() (map[string]Route, map[string]*regexp.Regexp) {
|
|
||||||
m := map[string]Route{}
|
m := map[string]Route{}
|
||||||
rrs := map[string]*regexp.Regexp{}
|
rrs := map[string]*regexp.Regexp{}
|
||||||
routes.Range(func(key string, value Route) bool {
|
routes.Range(func(key string, value Route) bool {
|
||||||
|
@ -82,9 +84,13 @@ func ResolveRoute(h *wp.Handle) {
|
||||||
if len(routeHook) > 0 {
|
if len(routeHook) > 0 {
|
||||||
for _, fn := range routeHook {
|
for _, fn := range routeHook {
|
||||||
v, ok := fn(value)
|
v, ok := fn(value)
|
||||||
if ok {
|
if !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
m[v.Path] = v
|
m[v.Path] = v
|
||||||
if v.Type == "reg" {
|
if v.Type != "reg" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
if v.Path != key {
|
if v.Path != key {
|
||||||
vvv, err := regexp.Compile(v.Path)
|
vvv, err := regexp.Compile(v.Path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -94,36 +100,47 @@ func ResolveRoute(h *wp.Handle) {
|
||||||
}
|
}
|
||||||
rrs[v.Path] = vv
|
rrs[v.Path] = vv
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
m[key] = value
|
m[key] = value
|
||||||
rrs[key] = vv
|
rrs[key] = vv
|
||||||
}
|
}
|
||||||
|
|
||||||
return true
|
return true
|
||||||
})
|
})
|
||||||
return func() (map[string]Route, map[string]*regexp.Regexp) {
|
return func() (map[string]Route, map[string]*regexp.Regexp) {
|
||||||
return m, rrs
|
return m, rrs
|
||||||
}
|
}
|
||||||
})()
|
}
|
||||||
|
func ResolveRoute(h *wp.Handle) {
|
||||||
|
requestURI := h.C.Request.RequestURI
|
||||||
|
rs, rrs := RegRouteFn()()
|
||||||
v, ok := rs[requestURI]
|
v, ok := rs[requestURI]
|
||||||
if ok && slice.IsContained(v.Method, h.C.Request.Method) {
|
if ok && slice.IsContained(v.Method, h.C.Request.Method) {
|
||||||
h.SetScene(v.Scene)
|
h.SetScene(v.Scene)
|
||||||
wp.Run(h, nil)
|
wp.Run(h, nil)
|
||||||
|
h.Abort()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
for path, reg := range rrs {
|
for path, reg := range rrs {
|
||||||
r := reg.FindAllStringSubmatch(requestURI, -1)
|
r := reg.FindStringSubmatch(requestURI)
|
||||||
if len(r) < 1 {
|
if len(r) < 1 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
rr := rs[path]
|
rr := rs[path]
|
||||||
if slice.IsContained(rr.Method, h.C.Request.Method) {
|
if slice.IsContained(rr.Method, h.C.Request.Method) {
|
||||||
h.SetScene(rr.Scene)
|
h.SetScene(rr.Scene)
|
||||||
h.C.Set("route", r)
|
for i, name := range reg.SubexpNames() {
|
||||||
|
if name == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
h.C.AddParam(name, r[i])
|
||||||
|
}
|
||||||
|
h.C.Set("regRoute", reg)
|
||||||
|
h.C.Set("regRouteRes", r)
|
||||||
wp.Run(h, nil)
|
wp.Run(h, nil)
|
||||||
|
h.Abort()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
h.C.Status(http.StatusNotFound)
|
||||||
|
h.Abort()
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,739 +0,0 @@
|
||||||
package scriptloader
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"github.com/fthvgb1/wp-go/app/pkg/config"
|
|
||||||
"github.com/fthvgb1/wp-go/app/pkg/logs"
|
|
||||||
"github.com/fthvgb1/wp-go/helper/maps"
|
|
||||||
str "github.com/fthvgb1/wp-go/helper/strings"
|
|
||||||
"github.com/fthvgb1/wp-go/safety"
|
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
"regexp"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
func defaultScripts(m *safety.Map[string, *Script], suffix string) {
|
|
||||||
m.Store("utils", NewScript("utils", "/wp-includes/js/utils"+suffix+".js", nil, "", nil))
|
|
||||||
m.Store("common", NewScript("common", "/wp-admin/js/common"+suffix+".js", []string{"jquery", "hoverIntent", "utils", "wp-i18n"}, "", 1))
|
|
||||||
m.Store("wp-sanitize", NewScript("wp-sanitize", "/wp-includes/js/wp-sanitize"+suffix+".js", nil, "", 1))
|
|
||||||
m.Store("sack", NewScript("sack", "/wp-includes/js/tw-sack"+suffix+".js", nil, "1.6.1", 1))
|
|
||||||
m.Store("quicktags", NewScript("quicktags", "/wp-includes/js/quicktags"+suffix+".js", nil, "", 1))
|
|
||||||
m.Store("colorpicker", NewScript("colorpicker", "/wp-includes/js/colorpicker"+suffix+".js", []string{"prototype"}, "3517m", nil))
|
|
||||||
m.Store("editor", NewScript("editor", "/wp-admin/js/editor"+suffix+".js", []string{"utils", "jquery"}, "", 1))
|
|
||||||
m.Store("clipboard", NewScript("clipboard", "/wp-includes/js/clipboard"+suffix+".js", nil, "2.0.11", 1))
|
|
||||||
m.Store("wp-ajax-response", NewScript("wp-ajax-response", "/wp-includes/js/wp-ajax-response"+suffix+".js", []string{"jquery", "wp-a11y"}, "", 1))
|
|
||||||
m.Store("wp-api-request", NewScript("wp-api-request", "/wp-includes/js/api-request"+suffix+".js", []string{"jquery"}, "", 1))
|
|
||||||
m.Store("wp-pointer", NewScript("wp-pointer", "/wp-includes/js/wp-pointer"+suffix+".js", []string{"jquery-ui-core", "wp-i18n"}, "", 1))
|
|
||||||
m.Store("autosave", NewScript("autosave", "/wp-includes/js/autosave"+suffix+".js", []string{"heartbeat"}, "", 1))
|
|
||||||
m.Store("heartbeat", NewScript("heartbeat", "/wp-includes/js/heartbeat"+suffix+".js", []string{"jquery", "wp-hooks"}, "", 1))
|
|
||||||
m.Store("wp-auth-check", NewScript("wp-auth-check", "/wp-includes/js/wp-auth-check"+suffix+".js", []string{"heartbeat", "wp-i18n"}, "", 1))
|
|
||||||
m.Store("wp-lists", NewScript("wp-lists", "/wp-includes/js/wp-lists"+suffix+".js", []string{"wp-ajax-response", "jquery-color"}, "", 1))
|
|
||||||
m.Store("prototype", NewScript("prototype", "https://ajax.googleapis.com/ajax/libs/prototype/1.7.1.0/prototype.js"+suffix+".js", nil, "1.7.1", nil))
|
|
||||||
m.Store("scriptaculous-root", NewScript("scriptaculous-root", "https://ajax.googleapis.com/ajax/libs/scriptaculous/1.9.0/scriptaculous.js"+suffix+".js", []string{"prototype"}, "1.9.0", nil))
|
|
||||||
m.Store("scriptaculous-builder", NewScript("scriptaculous-builder", "https://ajax.googleapis.com/ajax/libs/scriptaculous/1.9.0/builder.js"+suffix+".js", []string{"scriptaculous-root"}, "1.9.0", nil))
|
|
||||||
m.Store("scriptaculous-dragdrop", NewScript("scriptaculous-dragdrop", "https://ajax.googleapis.com/ajax/libs/scriptaculous/1.9.0/dragdrop.js"+suffix+".js", []string{"scriptaculous-builder", "scriptaculous-effects"}, "1.9.0", nil))
|
|
||||||
m.Store("scriptaculous-effects", NewScript("scriptaculous-effects", "https://ajax.googleapis.com/ajax/libs/scriptaculous/1.9.0/effects.js"+suffix+".js", []string{"scriptaculous-root"}, "1.9.0", nil))
|
|
||||||
m.Store("scriptaculous-slider", NewScript("scriptaculous-slider", "https://ajax.googleapis.com/ajax/libs/scriptaculous/1.9.0/slider.js"+suffix+".js", []string{"scriptaculous-effects"}, "1.9.0", nil))
|
|
||||||
m.Store("scriptaculous-sound", NewScript("scriptaculous-sound", "https://ajax.googleapis.com/ajax/libs/scriptaculous/1.9.0/sound.js"+suffix+".js", []string{"scriptaculous-root"}, "1.9.0", nil))
|
|
||||||
m.Store("scriptaculous-controls", NewScript("scriptaculous-controls", "https://ajax.googleapis.com/ajax/libs/scriptaculous/1.9.0/controls.js"+suffix+".js", []string{"scriptaculous-root"}, "1.9.0", nil))
|
|
||||||
m.Store("scriptaculous", NewScript("scriptaculous", ""+suffix+".js", []string{"scriptaculous-dragdrop", "scriptaculous-slider", "scriptaculous-controls"}, "", nil))
|
|
||||||
m.Store("cropper", NewScript("cropper", "/wp-includes/js/crop/cropper.js"+suffix+".js", []string{"scriptaculous-dragdrop"}, "", nil))
|
|
||||||
m.Store("jquery", NewScript("jquery", ""+suffix+".js", []string{"jquery-core", "jquery-migrate"}, "3.6.4", nil))
|
|
||||||
m.Store("jquery-core", NewScript("jquery-core", "/wp-includes/js/jquery/jquery"+suffix+".js", nil, "3.6.4", nil))
|
|
||||||
m.Store("jquery-migrate", NewScript("jquery-migrate", "/wp-includes/js/jquery/jquery-migrate"+suffix+".js", nil, "3.4.0", nil))
|
|
||||||
m.Store("jquery-ui-core", NewScript("jquery-ui-core", "/wp-includes/js/jquery/ui/core"+suffix+".js", []string{"jquery"}, "1.13.2", 1))
|
|
||||||
m.Store("jquery-effects-core", NewScript("jquery-effects-core", "/wp-includes/js/jquery/ui/effect"+suffix+".js", []string{"jquery"}, "1.13.2", 1))
|
|
||||||
m.Store("jquery-effects-blind", NewScript("jquery-effects-blind", "/wp-includes/js/jquery/ui/effect-blind"+suffix+".js", []string{"jquery-effects-core"}, "1.13.2", 1))
|
|
||||||
m.Store("jquery-effects-bounce", NewScript("jquery-effects-bounce", "/wp-includes/js/jquery/ui/effect-bounce"+suffix+".js", []string{"jquery-effects-core"}, "1.13.2", 1))
|
|
||||||
m.Store("jquery-effects-clip", NewScript("jquery-effects-clip", "/wp-includes/js/jquery/ui/effect-clip"+suffix+".js", []string{"jquery-effects-core"}, "1.13.2", 1))
|
|
||||||
m.Store("jquery-effects-drop", NewScript("jquery-effects-drop", "/wp-includes/js/jquery/ui/effect-drop"+suffix+".js", []string{"jquery-effects-core"}, "1.13.2", 1))
|
|
||||||
m.Store("jquery-effects-explode", NewScript("jquery-effects-explode", "/wp-includes/js/jquery/ui/effect-explode"+suffix+".js", []string{"jquery-effects-core"}, "1.13.2", 1))
|
|
||||||
m.Store("jquery-effects-fade", NewScript("jquery-effects-fade", "/wp-includes/js/jquery/ui/effect-fade"+suffix+".js", []string{"jquery-effects-core"}, "1.13.2", 1))
|
|
||||||
m.Store("jquery-effects-fold", NewScript("jquery-effects-fold", "/wp-includes/js/jquery/ui/effect-fold"+suffix+".js", []string{"jquery-effects-core"}, "1.13.2", 1))
|
|
||||||
m.Store("jquery-effects-highlight", NewScript("jquery-effects-highlight", "/wp-includes/js/jquery/ui/effect-highlight"+suffix+".js", []string{"jquery-effects-core"}, "1.13.2", 1))
|
|
||||||
m.Store("jquery-effects-puff", NewScript("jquery-effects-puff", "/wp-includes/js/jquery/ui/effect-puff"+suffix+".js", []string{"jquery-effects-core", "jquery-effects-scale"}, "1.13.2", 1))
|
|
||||||
m.Store("jquery-effects-pulsate", NewScript("jquery-effects-pulsate", "/wp-includes/js/jquery/ui/effect-pulsate"+suffix+".js", []string{"jquery-effects-core"}, "1.13.2", 1))
|
|
||||||
m.Store("jquery-effects-scale", NewScript("jquery-effects-scale", "/wp-includes/js/jquery/ui/effect-scale"+suffix+".js", []string{"jquery-effects-core", "jquery-effects-size"}, "1.13.2", 1))
|
|
||||||
m.Store("jquery-effects-shake", NewScript("jquery-effects-shake", "/wp-includes/js/jquery/ui/effect-shake"+suffix+".js", []string{"jquery-effects-core"}, "1.13.2", 1))
|
|
||||||
m.Store("jquery-effects-size", NewScript("jquery-effects-size", "/wp-includes/js/jquery/ui/effect-size"+suffix+".js", []string{"jquery-effects-core"}, "1.13.2", 1))
|
|
||||||
m.Store("jquery-effects-slide", NewScript("jquery-effects-slide", "/wp-includes/js/jquery/ui/effect-slide"+suffix+".js", []string{"jquery-effects-core"}, "1.13.2", 1))
|
|
||||||
m.Store("jquery-effects-transfer", NewScript("jquery-effects-transfer", "/wp-includes/js/jquery/ui/effect-transfer"+suffix+".js", []string{"jquery-effects-core"}, "1.13.2", 1))
|
|
||||||
m.Store("jquery-ui-accordion", NewScript("jquery-ui-accordion", "/wp-includes/js/jquery/ui/accordion"+suffix+".js", []string{"jquery-ui-core"}, "1.13.2", 1))
|
|
||||||
m.Store("jquery-ui-autocomplete", NewScript("jquery-ui-autocomplete", "/wp-includes/js/jquery/ui/autocomplete"+suffix+".js", []string{"jquery-ui-menu", "wp-a11y"}, "1.13.2", 1))
|
|
||||||
m.Store("jquery-ui-button", NewScript("jquery-ui-button", "/wp-includes/js/jquery/ui/button"+suffix+".js", []string{"jquery-ui-core", "jquery-ui-controlgroup", "jquery-ui-checkboxradio"}, "1.13.2", 1))
|
|
||||||
m.Store("jquery-ui-datepicker", NewScript("jquery-ui-datepicker", "/wp-includes/js/jquery/ui/datepicker"+suffix+".js", []string{"jquery-ui-core"}, "1.13.2", 1))
|
|
||||||
m.Store("jquery-ui-dialog", NewScript("jquery-ui-dialog", "/wp-includes/js/jquery/ui/dialog"+suffix+".js", []string{"jquery-ui-resizable", "jquery-ui-draggable", "jquery-ui-button"}, "1.13.2", 1))
|
|
||||||
m.Store("jquery-ui-menu", NewScript("jquery-ui-menu", "/wp-includes/js/jquery/ui/menu"+suffix+".js", []string{"jquery-ui-core"}, "1.13.2", 1))
|
|
||||||
m.Store("jquery-ui-mouse", NewScript("jquery-ui-mouse", "/wp-includes/js/jquery/ui/mouse"+suffix+".js", []string{"jquery-ui-core"}, "1.13.2", 1))
|
|
||||||
m.Store("jquery-ui-progressbar", NewScript("jquery-ui-progressbar", "/wp-includes/js/jquery/ui/progressbar"+suffix+".js", []string{"jquery-ui-core"}, "1.13.2", 1))
|
|
||||||
m.Store("jquery-ui-selectmenu", NewScript("jquery-ui-selectmenu", "/wp-includes/js/jquery/ui/selectmenu"+suffix+".js", []string{"jquery-ui-menu"}, "1.13.2", 1))
|
|
||||||
m.Store("jquery-ui-slider", NewScript("jquery-ui-slider", "/wp-includes/js/jquery/ui/slider"+suffix+".js", []string{"jquery-ui-mouse"}, "1.13.2", 1))
|
|
||||||
m.Store("jquery-ui-spinner", NewScript("jquery-ui-spinner", "/wp-includes/js/jquery/ui/spinner"+suffix+".js", []string{"jquery-ui-button"}, "1.13.2", 1))
|
|
||||||
m.Store("jquery-ui-tabs", NewScript("jquery-ui-tabs", "/wp-includes/js/jquery/ui/tabs"+suffix+".js", []string{"jquery-ui-core"}, "1.13.2", 1))
|
|
||||||
m.Store("jquery-ui-tooltip", NewScript("jquery-ui-tooltip", "/wp-includes/js/jquery/ui/tooltip"+suffix+".js", []string{"jquery-ui-core"}, "1.13.2", 1))
|
|
||||||
m.Store("jquery-ui-checkboxradio", NewScript("jquery-ui-checkboxradio", "/wp-includes/js/jquery/ui/checkboxradio"+suffix+".js", []string{"jquery-ui-core"}, "1.13.2", 1))
|
|
||||||
m.Store("jquery-ui-controlgroup", NewScript("jquery-ui-controlgroup", "/wp-includes/js/jquery/ui/controlgroup"+suffix+".js", []string{"jquery-ui-core"}, "1.13.2", 1))
|
|
||||||
m.Store("jquery-ui-draggable", NewScript("jquery-ui-draggable", "/wp-includes/js/jquery/ui/draggable"+suffix+".js", []string{"jquery-ui-mouse"}, "1.13.2", 1))
|
|
||||||
m.Store("jquery-ui-droppable", NewScript("jquery-ui-droppable", "/wp-includes/js/jquery/ui/droppable"+suffix+".js", []string{"jquery-ui-draggable"}, "1.13.2", 1))
|
|
||||||
m.Store("jquery-ui-resizable", NewScript("jquery-ui-resizable", "/wp-includes/js/jquery/ui/resizable"+suffix+".js", []string{"jquery-ui-mouse"}, "1.13.2", 1))
|
|
||||||
m.Store("jquery-ui-selectable", NewScript("jquery-ui-selectable", "/wp-includes/js/jquery/ui/selectable"+suffix+".js", []string{"jquery-ui-mouse"}, "1.13.2", 1))
|
|
||||||
m.Store("jquery-ui-sortable", NewScript("jquery-ui-sortable", "/wp-includes/js/jquery/ui/sortable"+suffix+".js", []string{"jquery-ui-mouse"}, "1.13.2", 1))
|
|
||||||
m.Store("jquery-ui-position", NewScript("jquery-ui-position", ""+suffix+".js", []string{"jquery-ui-core"}, "1.13.2", 1))
|
|
||||||
m.Store("jquery-ui-widget", NewScript("jquery-ui-widget", ""+suffix+".js", []string{"jquery-ui-core"}, "1.13.2", 1))
|
|
||||||
m.Store("jquery-form", NewScript("jquery-form", "/wp-includes/js/jquery/jquery.form"+suffix+".js", []string{"jquery"}, "4.3.0", 1))
|
|
||||||
m.Store("jquery-color", NewScript("jquery-color", "/wp-includes/js/jquery/jquery.color"+suffix+".js", []string{"jquery"}, "2.2.0", 1))
|
|
||||||
m.Store("schedule", NewScript("schedule", "/wp-includes/js/jquery/jquery.schedule.js"+suffix+".js", []string{"jquery"}, "20m", 1))
|
|
||||||
m.Store("jquery-query", NewScript("jquery-query", "/wp-includes/js/jquery/jquery.query.js"+suffix+".js", []string{"jquery"}, "2.2.3", 1))
|
|
||||||
m.Store("jquery-serialize-object", NewScript("jquery-serialize-object", "/wp-includes/js/jquery/jquery.serialize-object.js"+suffix+".js", []string{"jquery"}, "0.2-wp", 1))
|
|
||||||
m.Store("jquery-hotkeys", NewScript("jquery-hotkeys", "/wp-includes/js/jquery/jquery.hotkeys"+suffix+".js", []string{"jquery"}, "0.0.2m", 1))
|
|
||||||
m.Store("jquery-table-hotkeys", NewScript("jquery-table-hotkeys", "/wp-includes/js/jquery/jquery.table-hotkeys"+suffix+".js", []string{"jquery", "jquery-hotkeys"}, "", 1))
|
|
||||||
m.Store("jquery-touch-punch", NewScript("jquery-touch-punch", "/wp-includes/js/jquery/jquery.ui.touch-punch.js"+suffix+".js", []string{"jquery-ui-core", "jquery-ui-mouse"}, "0.2.2", 1))
|
|
||||||
m.Store("suggest", NewScript("suggest", "/wp-includes/js/jquery/suggest"+suffix+".js", []string{"jquery"}, "1.1-20110113", 1))
|
|
||||||
m.Store("imagesloaded", NewScript("imagesloaded", "/wp-includes/js/imagesloaded"+suffix+".js", nil, "4.1.4", 1))
|
|
||||||
m.Store("masonry", NewScript("masonry", "/wp-includes/js/masonry"+suffix+".js", []string{"imagesloaded"}, "4.2.2", 1))
|
|
||||||
m.Store("jquery-masonry", NewScript("jquery-masonry", "/wp-includes/js/jquery/jquery.masonry"+suffix+".js", []string{"jquery", "masonry"}, "3.1.2b", 1))
|
|
||||||
m.Store("thickbox", NewScript("thickbox", "/wp-includes/js/thickbox/thickbox.js"+suffix+".js", []string{"jquery"}, "3.1-20121105", 1))
|
|
||||||
m.Store("jcrop", NewScript("jcrop", "/wp-includes/js/jcrop/jquery.Jcrop"+suffix+".js", []string{"jquery"}, "0.9.15", nil))
|
|
||||||
m.Store("swfobject", NewScript("swfobject", "/wp-includes/js/swfobject.js"+suffix+".js", nil, "2.2-20120417", nil))
|
|
||||||
m.Store("moxiejs", NewScript("moxiejs", "/wp-includes/js/plupload/moxie"+suffix+".js", nil, "1.3.5", nil))
|
|
||||||
m.Store("plupload", NewScript("plupload", "/wp-includes/js/plupload/plupload"+suffix+".js", []string{"moxiejs"}, "2.1.9", nil))
|
|
||||||
m.Store("plupload-all", NewScript("plupload-all", ""+suffix+".js", []string{"plupload"}, "2.1.1", nil))
|
|
||||||
m.Store("plupload-html5", NewScript("plupload-html5", ""+suffix+".js", []string{"plupload"}, "2.1.1", nil))
|
|
||||||
m.Store("plupload-flash", NewScript("plupload-flash", ""+suffix+".js", []string{"plupload"}, "2.1.1", nil))
|
|
||||||
m.Store("plupload-silverlight", NewScript("plupload-silverlight", ""+suffix+".js", []string{"plupload"}, "2.1.1", nil))
|
|
||||||
m.Store("plupload-html4", NewScript("plupload-html4", ""+suffix+".js", []string{"plupload"}, "2.1.1", nil))
|
|
||||||
m.Store("plupload-handlers", NewScript("plupload-handlers", "/wp-includes/js/plupload/handlers"+suffix+".js", []string{"clipboard", "jquery", "plupload", "underscore", "wp-a11y", "wp-i18n"}, "", nil))
|
|
||||||
m.Store("wp-plupload", NewScript("wp-plupload", "/wp-includes/js/plupload/wp-plupload"+suffix+".js", []string{"plupload", "jquery", "json2", "media-models"}, "", 1))
|
|
||||||
m.Store("swfupload", NewScript("swfupload", "/wp-includes/js/swfupload/swfupload.js"+suffix+".js", nil, "2201-20110113", nil))
|
|
||||||
m.Store("swfupload-all", NewScript("swfupload-all", ""+suffix+".js", []string{"swfupload"}, "2201", nil))
|
|
||||||
m.Store("swfupload-handlers", NewScript("swfupload-handlers", "/wp-includes/js/swfupload/handlers"+suffix+".js", []string{"swfupload-all", "jquery"}, "2201-20110524", nil))
|
|
||||||
m.Store("comment-reply", NewScript("comment-reply", "/wp-includes/js/comment-reply"+suffix+".js", nil, "", 1))
|
|
||||||
m.Store("json2", NewScript("json2", "/wp-includes/js/json2"+suffix+".js", nil, "2015-05-03", nil))
|
|
||||||
m.Store("underscore", NewScript("underscore", "/wp-includes/js/underscore"+suffix+".js", nil, "1.13.4", 1))
|
|
||||||
m.Store("backbone", NewScript("backbone", "/wp-includes/js/backbone"+suffix+".js", []string{"underscore", "jquery"}, "1.4.1", 1))
|
|
||||||
m.Store("wp-util", NewScript("wp-util", "/wp-includes/js/wp-util"+suffix+".js", []string{"underscore", "jquery"}, "", 1))
|
|
||||||
m.Store("wp-backbone", NewScript("wp-backbone", "/wp-includes/js/wp-backbone"+suffix+".js", []string{"backbone", "wp-util"}, "", 1))
|
|
||||||
m.Store("revisions", NewScript("revisions", "/wp-admin/js/revisions"+suffix+".js", []string{"wp-backbone", "jquery-ui-slider", "hoverIntent"}, "", 1))
|
|
||||||
m.Store("imgareaselect", NewScript("imgareaselect", "/wp-includes/js/imgareaselect/jquery.imgareaselect"+suffix+".js", []string{"jquery"}, "", 1))
|
|
||||||
m.Store("mediaelement", NewScript("mediaelement", ""+suffix+".js", []string{"jquery", "mediaelement-core", "mediaelement-migrate"}, "4.2.17", 1))
|
|
||||||
m.Store("mediaelement-core", NewScript("mediaelement-core", "/wp-includes/js/mediaelement/mediaelement-and-player"+suffix+".js", nil, "4.2.17", 1))
|
|
||||||
m.Store("mediaelement-migrate", NewScript("mediaelement-migrate", "/wp-includes/js/mediaelement/mediaelement-migrate"+suffix+".js", nil, "", 1))
|
|
||||||
m.Store("mediaelement-vimeo", NewScript("mediaelement-vimeo", "/wp-includes/js/mediaelement/renderers/vimeo"+suffix+".js", []string{"mediaelement"}, "4.2.17", 1))
|
|
||||||
m.Store("wp-mediaelement", NewScript("wp-mediaelement", "/wp-includes/js/mediaelement/wp-mediaelement"+suffix+".js", []string{"mediaelement"}, "", 1))
|
|
||||||
m.Store("wp-codemirror", NewScript("wp-codemirror", "/wp-includes/js/codemirror/codemirror"+suffix+".js", nil, "5.29.1-alpha-ee20357", nil))
|
|
||||||
m.Store("csslint", NewScript("csslint", "/wp-includes/js/codemirror/csslint.js"+suffix+".js", nil, "1.0.5", nil))
|
|
||||||
m.Store("esprima", NewScript("esprima", "/wp-includes/js/codemirror/esprima.js"+suffix+".js", nil, "4.0.0", nil))
|
|
||||||
m.Store("jshint", NewScript("jshint", "/wp-includes/js/codemirror/fakejshint.js"+suffix+".js", []string{"esprima"}, "2.9.5", nil))
|
|
||||||
m.Store("jsonlint", NewScript("jsonlint", "/wp-includes/js/codemirror/jsonlint.js"+suffix+".js", nil, "1.6.2", nil))
|
|
||||||
m.Store("htmlhint", NewScript("htmlhint", "/wp-includes/js/codemirror/htmlhint.js"+suffix+".js", nil, "0.9.14-xwp", nil))
|
|
||||||
m.Store("htmlhint-kses", NewScript("htmlhint-kses", "/wp-includes/js/codemirror/htmlhint-kses.js"+suffix+".js", []string{"htmlhint"}, "", nil))
|
|
||||||
m.Store("code-editor", NewScript("code-editor", "/wp-admin/js/code-editor"+suffix+".js", []string{"jquery", "wp-codemirror", "underscore"}, "", nil))
|
|
||||||
m.Store("wp-theme-plugin-editor", NewScript("wp-theme-plugin-editor", "/wp-admin/js/theme-plugin-editor"+suffix+".js", []string{"common", "wp-util", "wp-sanitize", "jquery", "jquery-ui-core", "wp-a11y", "underscore", "wp-i18n"}, "", 1))
|
|
||||||
m.Store("wp-playlist", NewScript("wp-playlist", "/wp-includes/js/mediaelement/wp-playlist"+suffix+".js", []string{"wp-util", "backbone", "mediaelement"}, "", 1))
|
|
||||||
m.Store("zxcvbn-async", NewScript("zxcvbn-async", "/wp-includes/js/zxcvbn-async"+suffix+".js", nil, "1.0", nil))
|
|
||||||
m.Store("password-strength-meter", NewScript("password-strength-meter", "/wp-admin/js/password-strength-meter"+suffix+".js", []string{"jquery", "zxcvbn-async", "wp-i18n"}, "", 1))
|
|
||||||
m.Store("application-passwords", NewScript("application-passwords", "/wp-admin/js/application-passwords"+suffix+".js", []string{"jquery", "wp-util", "wp-api-request", "wp-date", "wp-i18n", "wp-hooks"}, "", 1))
|
|
||||||
m.Store("auth-app", NewScript("auth-app", "/wp-admin/js/auth-app"+suffix+".js", []string{"jquery", "wp-api-request", "wp-i18n", "wp-hooks"}, "", 1))
|
|
||||||
m.Store("user-profile", NewScript("user-profile", "/wp-admin/js/user-profile"+suffix+".js", []string{"jquery", "password-strength-meter", "wp-util", "wp-i18n"}, "", 1))
|
|
||||||
m.Store("language-chooser", NewScript("language-chooser", "/wp-admin/js/language-chooser"+suffix+".js", []string{"jquery"}, "", 1))
|
|
||||||
m.Store("user-suggest", NewScript("user-suggest", "/wp-admin/js/user-suggest"+suffix+".js", []string{"jquery-ui-autocomplete"}, "", 1))
|
|
||||||
m.Store("admin-bar", NewScript("admin-bar", "/wp-includes/js/admin-bar"+suffix+".js", []string{"hoverintent-js"}, "", 1))
|
|
||||||
m.Store("wplink", NewScript("wplink", "/wp-includes/js/wplink"+suffix+".js", []string{"jquery", "wp-a11y"}, "", 1))
|
|
||||||
m.Store("wpdialogs", NewScript("wpdialogs", "/wp-includes/js/wpdialog"+suffix+".js", []string{"jquery-ui-dialog"}, "", 1))
|
|
||||||
m.Store("word-count", NewScript("word-count", "/wp-admin/js/word-count"+suffix+".js", nil, "", 1))
|
|
||||||
m.Store("media-upload", NewScript("media-upload", "/wp-admin/js/media-upload"+suffix+".js", []string{"thickbox", "shortcode"}, "", 1))
|
|
||||||
m.Store("hoverIntent", NewScript("hoverIntent", "/wp-includes/js/hoverIntent"+suffix+".js", []string{"jquery"}, "1.10.2", 1))
|
|
||||||
m.Store("hoverintent-js", NewScript("hoverintent-js", "/wp-includes/js/hoverintent-js"+suffix+".js", nil, "2.2.1", 1))
|
|
||||||
m.Store("customize-base", NewScript("customize-base", "/wp-includes/js/customize-base"+suffix+".js", []string{"jquery", "json2", "underscore"}, "", 1))
|
|
||||||
m.Store("customize-loader", NewScript("customize-loader", "/wp-includes/js/customize-loader"+suffix+".js", []string{"customize-base"}, "", 1))
|
|
||||||
m.Store("customize-preview", NewScript("customize-preview", "/wp-includes/js/customize-preview"+suffix+".js", []string{"wp-a11y", "customize-base"}, "", 1))
|
|
||||||
m.Store("customize-models", NewScript("customize-models", "/wp-includes/js/customize-models.js"+suffix+".js", []string{"underscore", "backbone"}, "", 1))
|
|
||||||
m.Store("customize-views", NewScript("customize-views", "/wp-includes/js/customize-views.js"+suffix+".js", []string{"jquery", "underscore", "imgareaselect", "customize-models", "media-editor", "media-views"}, "", 1))
|
|
||||||
m.Store("customize-controls", NewScript("customize-controls", "/wp-admin/js/customize-controls"+suffix+".js", []string{"customize-base", "wp-a11y", "wp-util", "jquery-ui-core"}, "", 1))
|
|
||||||
m.Store("customize-selective-refresh", NewScript("customize-selective-refresh", "/wp-includes/js/customize-selective-refresh"+suffix+".js", []string{"jquery", "wp-util", "customize-preview"}, "", 1))
|
|
||||||
m.Store("customize-widgets", NewScript("customize-widgets", "/wp-admin/js/customize-widgets"+suffix+".js", []string{"jquery", "jquery-ui-sortable", "jquery-ui-droppable", "wp-backbone", "customize-controls"}, "", 1))
|
|
||||||
m.Store("customize-preview-widgets", NewScript("customize-preview-widgets", "/wp-includes/js/customize-preview-widgets"+suffix+".js", []string{"jquery", "wp-util", "customize-preview", "customize-selective-refresh"}, "", 1))
|
|
||||||
m.Store("customize-nav-menus", NewScript("customize-nav-menus", "/wp-admin/js/customize-nav-menus"+suffix+".js", []string{"jquery", "wp-backbone", "customize-controls", "accordion", "nav-menu", "wp-sanitize"}, "", 1))
|
|
||||||
m.Store("customize-preview-nav-menus", NewScript("customize-preview-nav-menus", "/wp-includes/js/customize-preview-nav-menus"+suffix+".js", []string{"jquery", "wp-util", "customize-preview", "customize-selective-refresh"}, "", 1))
|
|
||||||
m.Store("wp-custom-header", NewScript("wp-custom-header", "/wp-includes/js/wp-custom-header"+suffix+".js", []string{"wp-a11y"}, "", 1))
|
|
||||||
m.Store("accordion", NewScript("accordion", "/wp-admin/js/accordion"+suffix+".js", []string{"jquery"}, "", 1))
|
|
||||||
m.Store("shortcode", NewScript("shortcode", "/wp-includes/js/shortcode"+suffix+".js", []string{"underscore"}, "", 1))
|
|
||||||
m.Store("media-models", NewScript("media-models", "/wp-includes/js/media-models"+suffix+".js", []string{"wp-backbone"}, "", 1))
|
|
||||||
m.Store("wp-embed", NewScript("wp-embed", "/wp-includes/js/wp-embed"+suffix+".js", nil, "", 1))
|
|
||||||
m.Store("media-views", NewScript("media-views", "/wp-includes/js/media-views"+suffix+".js", []string{"utils", "media-models", "wp-plupload", "jquery-ui-sortable", "wp-mediaelement", "wp-api-request", "wp-a11y", "clipboard", "wp-i18n"}, "", 1))
|
|
||||||
m.Store("media-editor", NewScript("media-editor", "/wp-includes/js/media-editor"+suffix+".js", []string{"shortcode", "media-views", "wp-i18n"}, "", 1))
|
|
||||||
m.Store("media-audiovideo", NewScript("media-audiovideo", "/wp-includes/js/media-audiovideo"+suffix+".js", []string{"media-editor"}, "", 1))
|
|
||||||
m.Store("mce-view", NewScript("mce-view", "/wp-includes/js/mce-view"+suffix+".js", []string{"shortcode", "jquery", "media-views", "media-audiovideo"}, "", 1))
|
|
||||||
m.Store("wp-api", NewScript("wp-api", "/wp-includes/js/wp-api"+suffix+".js", []string{"jquery", "backbone", "underscore", "wp-api-request"}, "", 1))
|
|
||||||
m.Store("react", NewScript("react", "/wp-includes/js/dist/vendor/react"+suffix+".js", []string{"wp-polyfill"}, "18.2.0", 1))
|
|
||||||
m.Store("react-dom", NewScript("react-dom", "/wp-includes/js/dist/vendor/react-dom"+suffix+".js", []string{"react"}, "18.2.0", 1))
|
|
||||||
m.Store("regenerator-runtime", NewScript("regenerator-runtime", "/wp-includes/js/dist/vendor/regenerator-runtime"+suffix+".js", nil, "0.13.11", 1))
|
|
||||||
m.Store("moment", NewScript("moment", "/wp-includes/js/dist/vendor/moment"+suffix+".js", nil, "2.29.4", 1))
|
|
||||||
m.Store("lodash", NewScript("lodash", "/wp-includes/js/dist/vendor/lodash"+suffix+".js", nil, "4.17.19", 1))
|
|
||||||
m.Store("wp-polyfill-fetch", NewScript("wp-polyfill-fetch", "/wp-includes/js/dist/vendor/wp-polyfill-fetch"+suffix+".js", nil, "3.6.2", 1))
|
|
||||||
m.Store("wp-polyfill-formdata", NewScript("wp-polyfill-formdata", "/wp-includes/js/dist/vendor/wp-polyfill-formdata"+suffix+".js", nil, "4.0.10", 1))
|
|
||||||
m.Store("wp-polyfill-node-contains", NewScript("wp-polyfill-node-contains", "/wp-includes/js/dist/vendor/wp-polyfill-node-contains"+suffix+".js", nil, "4.6.0", 1))
|
|
||||||
m.Store("wp-polyfill-url", NewScript("wp-polyfill-url", "/wp-includes/js/dist/vendor/wp-polyfill-url"+suffix+".js", nil, "3.6.4", 1))
|
|
||||||
m.Store("wp-polyfill-dom-rect", NewScript("wp-polyfill-dom-rect", "/wp-includes/js/dist/vendor/wp-polyfill-dom-rect"+suffix+".js", nil, "4.6.0", 1))
|
|
||||||
m.Store("wp-polyfill-element-closest", NewScript("wp-polyfill-element-closest", "/wp-includes/js/dist/vendor/wp-polyfill-element-closest"+suffix+".js", nil, "3.0.2", 1))
|
|
||||||
m.Store("wp-polyfill-object-fit", NewScript("wp-polyfill-object-fit", "/wp-includes/js/dist/vendor/wp-polyfill-object-fit"+suffix+".js", nil, "2.3.5", 1))
|
|
||||||
m.Store("wp-polyfill-inert", NewScript("wp-polyfill-inert", "/wp-includes/js/dist/vendor/wp-polyfill-inert"+suffix+".js", nil, "3.1.2", 1))
|
|
||||||
m.Store("wp-polyfill", NewScript("wp-polyfill", "/wp-includes/js/dist/vendor/wp-polyfill"+suffix+".js", []string{"wp-polyfill-inert", "regenerator-runtime"}, "3.15.0", 1))
|
|
||||||
m.Store("wp-tinymce-root", NewScript("wp-tinymce-root", "http://wp.test/wp-includes/js/tinymce/tinymce"+suffix+".js", nil, "49110-20201110", nil))
|
|
||||||
m.Store("wp-tinymce", NewScript("wp-tinymce", "http://wp.test/wp-includes/js/tinymce/plugins/compat3x/plugin"+suffix+".js", []string{"wp-tinymce-root"}, "49110-20201110", nil))
|
|
||||||
m.Store("wp-tinymce-lists", NewScript("wp-tinymce-lists", "http://wp.test/wp-includes/js/tinymce/plugins/lists/plugin"+suffix+".js", []string{"wp-tinymce"}, "49110-20201110", nil))
|
|
||||||
m.Store("wp-a11y", NewScript("wp-a11y", "/wp-includes/js/dist/a11y"+suffix+".js", []string{"wp-dom-ready", "wp-i18n", "wp-polyfill"}, "ecce20f002eda4c19664", 1))
|
|
||||||
m.Store("wp-annotations", NewScript("wp-annotations", "/wp-includes/js/dist/annotations"+suffix+".js", []string{"wp-data", "wp-hooks", "wp-i18n", "wp-polyfill", "wp-rich-text"}, "1720fc5d5c76f53a1740", 1))
|
|
||||||
m.Store("wp-api-fetch", NewScript("wp-api-fetch", "/wp-includes/js/dist/api-fetch"+suffix+".js", []string{"wp-i18n", "wp-polyfill", "wp-url"}, "bc0029ca2c943aec5311", 1))
|
|
||||||
m.Store("wp-autop", NewScript("wp-autop", "/wp-includes/js/dist/autop"+suffix+".js", []string{"wp-polyfill"}, "43197d709df445ccf849", 1))
|
|
||||||
m.Store("wp-blob", NewScript("wp-blob", "/wp-includes/js/dist/blob"+suffix+".js", []string{"wp-polyfill"}, "e7b4ea96175a89b263e2", 1))
|
|
||||||
m.Store("wp-block-directory", NewScript("wp-block-directory", "/wp-includes/js/dist/block-directory"+suffix+".js", []string{"wp-a11y", "wp-api-fetch", "wp-block-editor", "wp-blocks", "wp-components", "wp-compose", "wp-core-data", "wp-data", "wp-editor", "wp-element", "wp-hooks", "wp-html-entities", "wp-i18n", "wp-notices", "wp-plugins", "wp-polyfill", "wp-primitives", "wp-url"}, "9c45b8d28fc867ceed45", 1))
|
|
||||||
m.Store("wp-block-editor", NewScript("wp-block-editor", "/wp-includes/js/dist/block-editor"+suffix+".js", []string{"lodash", "react", "react-dom", "wp-a11y", "wp-api-fetch", "wp-blob", "wp-blocks", "wp-components", "wp-compose", "wp-data", "wp-date", "wp-deprecated", "wp-dom", "wp-element", "wp-escape-html", "wp-hooks", "wp-html-entities", "wp-i18n", "wp-is-shallow-equal", "wp-keyboard-shortcuts", "wp-keycodes", "wp-notices", "wp-polyfill", "wp-preferences", "wp-primitives", "wp-private-apis", "wp-rich-text", "wp-shortcode", "wp-style-engine", "wp-token-list", "wp-url", "wp-warning", "wp-wordcount"}, "43e40e04f77d598ede94", 1))
|
|
||||||
m.Store("wp-block-library", NewScript("wp-block-library", "/wp-includes/js/dist/block-library"+suffix+".js", []string{"lodash", "wp-a11y", "wp-api-fetch", "wp-autop", "wp-blob", "wp-block-editor", "wp-blocks", "wp-components", "wp-compose", "wp-core-data", "wp-data", "wp-date", "wp-deprecated", "wp-dom", "wp-element", "wp-escape-html", "wp-hooks", "wp-html-entities", "wp-i18n", "wp-keycodes", "wp-notices", "wp-polyfill", "wp-primitives", "wp-private-apis", "wp-reusable-blocks", "wp-rich-text", "wp-server-side-render", "wp-url", "wp-viewport", "editor"}, "3115f0b5551a55bb6d3b", 1))
|
|
||||||
m.Store("wp-block-serialization-default-parser", NewScript("wp-block-serialization-default-parser", "/wp-includes/js/dist/block-serialization-default-parser"+suffix+".js", []string{"wp-polyfill"}, "30ffd7e7e199f10b2a6d", 1))
|
|
||||||
m.Store("wp-blocks", NewScript("wp-blocks", "/wp-includes/js/dist/blocks"+suffix+".js", []string{"lodash", "wp-autop", "wp-blob", "wp-block-serialization-default-parser", "wp-compose", "wp-data", "wp-deprecated", "wp-dom", "wp-element", "wp-hooks", "wp-html-entities", "wp-i18n", "wp-is-shallow-equal", "wp-polyfill", "wp-shortcode"}, "639e14271099dc3d85bf", 1))
|
|
||||||
m.Store("wp-components", NewScript("wp-components", "/wp-includes/js/dist/components"+suffix+".js", []string{"lodash", "react", "react-dom", "wp-a11y", "wp-compose", "wp-date", "wp-deprecated", "wp-dom", "wp-element", "wp-escape-html", "wp-hooks", "wp-html-entities", "wp-i18n", "wp-is-shallow-equal", "wp-keycodes", "wp-polyfill", "wp-primitives", "wp-private-apis", "wp-rich-text", "wp-warning"}, "bf6e0ec3089253604b52", 1))
|
|
||||||
m.Store("wp-compose", NewScript("wp-compose", "/wp-includes/js/dist/compose"+suffix+".js", []string{"react", "wp-deprecated", "wp-dom", "wp-element", "wp-is-shallow-equal", "wp-keycodes", "wp-polyfill", "wp-priority-queue"}, "7d5916e3b2ef0ea01400", 1))
|
|
||||||
m.Store("wp-core-data", NewScript("wp-core-data", "/wp-includes/js/dist/core-data"+suffix+".js", []string{"lodash", "wp-api-fetch", "wp-blocks", "wp-compose", "wp-data", "wp-deprecated", "wp-element", "wp-html-entities", "wp-i18n", "wp-is-shallow-equal", "wp-polyfill", "wp-url"}, "fc0de6bb17aa25caf698", 1))
|
|
||||||
m.Store("wp-customize-widgets", NewScript("wp-customize-widgets", "/wp-includes/js/dist/customize-widgets"+suffix+".js", []string{"wp-block-editor", "wp-block-library", "wp-blocks", "wp-components", "wp-compose", "wp-core-data", "wp-data", "wp-deprecated", "wp-dom", "wp-element", "wp-hooks", "wp-i18n", "wp-is-shallow-equal", "wp-keyboard-shortcuts", "wp-keycodes", "wp-media-utils", "wp-polyfill", "wp-preferences", "wp-primitives", "wp-private-apis", "wp-widgets"}, "7ae69cc350436c0cf301", 1))
|
|
||||||
m.Store("wp-data", NewScript("wp-data", "/wp-includes/js/dist/data"+suffix+".js", []string{"lodash", "wp-compose", "wp-deprecated", "wp-element", "wp-is-shallow-equal", "wp-polyfill", "wp-priority-queue", "wp-private-apis", "wp-redux-routine"}, "90cebfec01d1a3f0368e", 1))
|
|
||||||
m.Store("wp-data-controls", NewScript("wp-data-controls", "/wp-includes/js/dist/data-controls"+suffix+".js", []string{"wp-api-fetch", "wp-data", "wp-deprecated", "wp-polyfill"}, "e10d473d392daa8501e8", 1))
|
|
||||||
m.Store("wp-date", NewScript("wp-date", "/wp-includes/js/dist/date"+suffix+".js", []string{"moment", "wp-deprecated", "wp-polyfill"}, "f8550b1212d715fbf745", 1))
|
|
||||||
m.Store("wp-deprecated", NewScript("wp-deprecated", "/wp-includes/js/dist/deprecated"+suffix+".js", []string{"wp-hooks", "wp-polyfill"}, "6c963cb9494ba26b77eb", 1))
|
|
||||||
m.Store("wp-dom", NewScript("wp-dom", "/wp-includes/js/dist/dom"+suffix+".js", []string{"wp-deprecated", "wp-polyfill"}, "e03c89e1dd68aee1cb3a", 1))
|
|
||||||
m.Store("wp-dom-ready", NewScript("wp-dom-ready", "/wp-includes/js/dist/dom-ready"+suffix+".js", []string{"wp-polyfill"}, "392bdd43726760d1f3ca", 1))
|
|
||||||
m.Store("wp-edit-post", NewScript("wp-edit-post", "/wp-includes/js/dist/edit-post"+suffix+".js", []string{"lodash", "wp-a11y", "wp-api-fetch", "wp-block-editor", "wp-block-library", "wp-blocks", "wp-components", "wp-compose", "wp-core-data", "wp-data", "wp-deprecated", "wp-editor", "wp-element", "wp-hooks", "wp-i18n", "wp-keyboard-shortcuts", "wp-keycodes", "wp-media-utils", "wp-notices", "wp-plugins", "wp-polyfill", "wp-preferences", "wp-primitives", "wp-private-apis", "wp-url", "wp-viewport", "wp-warning", "wp-widgets", "media-models", "media-views", "postbox", "wp-dom-ready"}, "d098b8ee5bdffa238c03", 1))
|
|
||||||
m.Store("wp-edit-site", NewScript("wp-edit-site", "/wp-includes/js/dist/edit-site"+suffix+".js", []string{"lodash", "react", "wp-a11y", "wp-api-fetch", "wp-block-editor", "wp-block-library", "wp-blocks", "wp-components", "wp-compose", "wp-core-data", "wp-data", "wp-deprecated", "wp-editor", "wp-element", "wp-hooks", "wp-html-entities", "wp-i18n", "wp-keyboard-shortcuts", "wp-keycodes", "wp-media-utils", "wp-notices", "wp-plugins", "wp-polyfill", "wp-preferences", "wp-primitives", "wp-private-apis", "wp-reusable-blocks", "wp-url", "wp-viewport", "wp-widgets"}, "fcf81e803ab1af60d4f8", 1))
|
|
||||||
m.Store("wp-edit-widgets", NewScript("wp-edit-widgets", "/wp-includes/js/dist/edit-widgets"+suffix+".js", []string{"wp-api-fetch", "wp-block-editor", "wp-block-library", "wp-blocks", "wp-components", "wp-compose", "wp-core-data", "wp-data", "wp-deprecated", "wp-dom", "wp-element", "wp-hooks", "wp-i18n", "wp-keyboard-shortcuts", "wp-keycodes", "wp-media-utils", "wp-notices", "wp-plugins", "wp-polyfill", "wp-preferences", "wp-primitives", "wp-private-apis", "wp-reusable-blocks", "wp-url", "wp-viewport", "wp-widgets"}, "d683d5fc75e655fdf974", 1))
|
|
||||||
m.Store("wp-editor", NewScript("wp-editor", "/wp-includes/js/dist/editor"+suffix+".js", []string{"lodash", "react", "wp-a11y", "wp-api-fetch", "wp-blob", "wp-block-editor", "wp-blocks", "wp-components", "wp-compose", "wp-core-data", "wp-data", "wp-date", "wp-deprecated", "wp-dom", "wp-element", "wp-hooks", "wp-html-entities", "wp-i18n", "wp-keyboard-shortcuts", "wp-keycodes", "wp-media-utils", "wp-notices", "wp-polyfill", "wp-preferences", "wp-primitives", "wp-private-apis", "wp-reusable-blocks", "wp-rich-text", "wp-server-side-render", "wp-url", "wp-wordcount"}, "1fb5fcf129627da4939e", 1))
|
|
||||||
m.Store("wp-element", NewScript("wp-element", "/wp-includes/js/dist/element"+suffix+".js", []string{"react", "react-dom", "wp-escape-html", "wp-polyfill"}, "b3bda690cfc516378771", 1))
|
|
||||||
m.Store("wp-escape-html", NewScript("wp-escape-html", "/wp-includes/js/dist/escape-html"+suffix+".js", []string{"wp-polyfill"}, "03e27a7b6ae14f7afaa6", 1))
|
|
||||||
m.Store("wp-format-library", NewScript("wp-format-library", "/wp-includes/js/dist/format-library"+suffix+".js", []string{"wp-a11y", "wp-block-editor", "wp-components", "wp-data", "wp-element", "wp-html-entities", "wp-i18n", "wp-polyfill", "wp-primitives", "wp-rich-text", "wp-url"}, "cd4a10ec005e2f001978", 1))
|
|
||||||
m.Store("wp-hooks", NewScript("wp-hooks", "/wp-includes/js/dist/hooks"+suffix+".js", []string{"wp-polyfill"}, "4169d3cf8e8d95a3d6d5", 1))
|
|
||||||
m.Store("wp-html-entities", NewScript("wp-html-entities", "/wp-includes/js/dist/html-entities"+suffix+".js", []string{"wp-polyfill"}, "36a4a255da7dd2e1bf8e", 1))
|
|
||||||
m.Store("wp-i18n", NewScript("wp-i18n", "/wp-includes/js/dist/i18n"+suffix+".js", []string{"wp-hooks", "wp-polyfill"}, "9e794f35a71bb98672ae", 1))
|
|
||||||
m.Store("wp-is-shallow-equal", NewScript("wp-is-shallow-equal", "/wp-includes/js/dist/is-shallow-equal"+suffix+".js", []string{"wp-polyfill"}, "20c2b06ecf04afb14fee", 1))
|
|
||||||
m.Store("wp-keyboard-shortcuts", NewScript("wp-keyboard-shortcuts", "/wp-includes/js/dist/keyboard-shortcuts"+suffix+".js", []string{"wp-data", "wp-element", "wp-keycodes", "wp-polyfill"}, "b696c16720133edfc065", 1))
|
|
||||||
m.Store("wp-keycodes", NewScript("wp-keycodes", "/wp-includes/js/dist/keycodes"+suffix+".js", []string{"wp-i18n", "wp-polyfill"}, "184b321fa2d3bc7fd173", 1))
|
|
||||||
m.Store("wp-list-reusable-blocks", NewScript("wp-list-reusable-blocks", "/wp-includes/js/dist/list-reusable-blocks"+suffix+".js", []string{"wp-api-fetch", "wp-components", "wp-compose", "wp-element", "wp-i18n", "wp-polyfill"}, "6ba78be26d660b6af113", 1))
|
|
||||||
m.Store("wp-media-utils", NewScript("wp-media-utils", "/wp-includes/js/dist/media-utils"+suffix+".js", []string{"wp-api-fetch", "wp-blob", "wp-element", "wp-i18n", "wp-polyfill"}, "f837b6298c83612cd6f6", 1))
|
|
||||||
m.Store("wp-notices", NewScript("wp-notices", "/wp-includes/js/dist/notices"+suffix+".js", []string{"wp-data", "wp-polyfill"}, "9c1575b7a31659f45a45", 1))
|
|
||||||
m.Store("wp-nux", NewScript("wp-nux", "/wp-includes/js/dist/nux"+suffix+".js", []string{"wp-components", "wp-compose", "wp-data", "wp-deprecated", "wp-element", "wp-i18n", "wp-polyfill", "wp-primitives"}, "038c48e26a91639ae8ab", 1))
|
|
||||||
m.Store("wp-plugins", NewScript("wp-plugins", "/wp-includes/js/dist/plugins"+suffix+".js", []string{"wp-compose", "wp-element", "wp-hooks", "wp-polyfill", "wp-primitives"}, "0d1b90278bae7df6ecf9", 1))
|
|
||||||
m.Store("wp-preferences", NewScript("wp-preferences", "/wp-includes/js/dist/preferences"+suffix+".js", []string{"wp-a11y", "wp-components", "wp-data", "wp-element", "wp-i18n", "wp-polyfill", "wp-primitives", "wp-preferences-persistence"}, "c66e137a7e588dab54c3", 1))
|
|
||||||
m.Store("wp-preferences-persistence", NewScript("wp-preferences-persistence", "/wp-includes/js/dist/preferences-persistence"+suffix+".js", []string{"wp-api-fetch", "wp-polyfill"}, "c5543628aa7ff5bd5be4", 1))
|
|
||||||
m.Store("wp-primitives", NewScript("wp-primitives", "/wp-includes/js/dist/primitives"+suffix+".js", []string{"wp-element", "wp-polyfill"}, "dfac1545e52734396640", 1))
|
|
||||||
m.Store("wp-priority-queue", NewScript("wp-priority-queue", "/wp-includes/js/dist/priority-queue"+suffix+".js", []string{"wp-polyfill"}, "422e19e9d48b269c5219", 1))
|
|
||||||
m.Store("wp-private-apis", NewScript("wp-private-apis", "/wp-includes/js/dist/private-apis"+suffix+".js", []string{"wp-polyfill"}, "6f247ed2bc3571743bba", 1))
|
|
||||||
m.Store("wp-redux-routine", NewScript("wp-redux-routine", "/wp-includes/js/dist/redux-routine"+suffix+".js", []string{"wp-polyfill"}, "d86e7e9f062d7582f76b", 1))
|
|
||||||
m.Store("wp-reusable-blocks", NewScript("wp-reusable-blocks", "/wp-includes/js/dist/reusable-blocks"+suffix+".js", []string{"wp-block-editor", "wp-blocks", "wp-components", "wp-core-data", "wp-data", "wp-element", "wp-i18n", "wp-notices", "wp-polyfill", "wp-primitives", "wp-url"}, "a7367a6154c724b51b31", 1))
|
|
||||||
m.Store("wp-rich-text", NewScript("wp-rich-text", "/wp-includes/js/dist/rich-text"+suffix+".js", []string{"wp-a11y", "wp-compose", "wp-data", "wp-deprecated", "wp-element", "wp-escape-html", "wp-i18n", "wp-keycodes", "wp-polyfill"}, "9307ec04c67d79b6e813", 1))
|
|
||||||
m.Store("wp-server-side-render", NewScript("wp-server-side-render", "/wp-includes/js/dist/server-side-render"+suffix+".js", []string{"wp-api-fetch", "wp-blocks", "wp-components", "wp-compose", "wp-data", "wp-element", "wp-i18n", "wp-polyfill", "wp-url"}, "d1bc93277666143a3f5e", 1))
|
|
||||||
m.Store("wp-shortcode", NewScript("wp-shortcode", "/wp-includes/js/dist/shortcode"+suffix+".js", []string{"wp-polyfill"}, "7539044b04e6bca57f2e", 1))
|
|
||||||
m.Store("wp-style-engine", NewScript("wp-style-engine", "/wp-includes/js/dist/style-engine"+suffix+".js", []string{"lodash", "wp-polyfill"}, "528e6cf281ffc9b7bd3c", 1))
|
|
||||||
m.Store("wp-token-list", NewScript("wp-token-list", "/wp-includes/js/dist/token-list"+suffix+".js", []string{"wp-polyfill"}, "f2cf0bb3ae80de227e43", 1))
|
|
||||||
m.Store("wp-url", NewScript("wp-url", "/wp-includes/js/dist/url"+suffix+".js", []string{"wp-polyfill"}, "16185fce2fb043a0cfed", 1))
|
|
||||||
m.Store("wp-viewport", NewScript("wp-viewport", "/wp-includes/js/dist/viewport"+suffix+".js", []string{"wp-compose", "wp-data", "wp-element", "wp-polyfill"}, "4f6bd168b2b8b45c8a6b", 1))
|
|
||||||
m.Store("wp-warning", NewScript("wp-warning", "/wp-includes/js/dist/warning"+suffix+".js", []string{"wp-polyfill"}, "4acee5fc2fd9a24cefc2", 1))
|
|
||||||
m.Store("wp-widgets", NewScript("wp-widgets", "/wp-includes/js/dist/widgets"+suffix+".js", []string{"wp-api-fetch", "wp-block-editor", "wp-blocks", "wp-components", "wp-compose", "wp-core-data", "wp-data", "wp-element", "wp-i18n", "wp-notices", "wp-polyfill", "wp-primitives"}, "040ac8be5e0cfc4b52df", 1))
|
|
||||||
m.Store("wp-wordcount", NewScript("wp-wordcount", "/wp-includes/js/dist/wordcount"+suffix+".js", []string{"wp-polyfill"}, "feb9569307aec24292f2", 1))
|
|
||||||
}
|
|
||||||
|
|
||||||
func defaultLocalize() {
|
|
||||||
/*AddDynamicLocalize(h, "utils", "userSettings", map[string]any{
|
|
||||||
"url": h.C.Request.RequestURI,
|
|
||||||
"uid": "0",
|
|
||||||
"time": number.IntToString(time.Now().Unix()),
|
|
||||||
"secure": h.IsHttps(),
|
|
||||||
})*/
|
|
||||||
|
|
||||||
AddStaticLocalize("wp-ajax-response", "wpAjax", map[string]any{
|
|
||||||
"noPerm": `抱歉,您不能这么做。`,
|
|
||||||
"broken": `出现了问题。`,
|
|
||||||
})
|
|
||||||
AddStaticLocalize("wp-api-request", "wpApiSettings", map[string]any{
|
|
||||||
"root": `/wp-json/`,
|
|
||||||
"nonce": `9a3ce0a5d7`,
|
|
||||||
"versionString": `wp/v2/`,
|
|
||||||
})
|
|
||||||
AddStaticLocalize("jquery-ui-autocomplete", "uiAutocompleteL10n", map[string]any{
|
|
||||||
"noResults": `未找到结果。`,
|
|
||||||
"oneResult": `找到1个结果。使用上下方向键来导航。`,
|
|
||||||
"manyResults": `找到%d个结果。使用上下方向键来导航。`,
|
|
||||||
"itemSelected": `已选择项目。`,
|
|
||||||
})
|
|
||||||
AddStaticLocalize("thickbox", "thickboxL10n", map[string]any{
|
|
||||||
"next": `下一页 >`,
|
|
||||||
"prev": `< 上一页`,
|
|
||||||
"image": `图片`,
|
|
||||||
"of": `/`,
|
|
||||||
"close": `关闭`,
|
|
||||||
"noiframes": `这个功能需要iframe的支持。您可能禁止了iframe的显示,或您的浏览器不支持此功能。`,
|
|
||||||
"loadingAnimation": `/wp-includes/js/thickbox/loadingAnimation.gif`,
|
|
||||||
})
|
|
||||||
|
|
||||||
AddStaticLocalize("mediaelement", "_wpmejsSettings", map[string]any{
|
|
||||||
"pluginPath": `/wp-includes/js/mediaelement/`,
|
|
||||||
"classPrefix": `mejs-`,
|
|
||||||
"stretching": `responsive`,
|
|
||||||
"audioShortcodeLibrary": `mediaelement`,
|
|
||||||
"videoShortcodeLibrary": `mediaelement`,
|
|
||||||
})
|
|
||||||
AddStaticLocalize("zxcvbn-async", "_zxcvbnSettings", map[string]any{
|
|
||||||
"src": `/wp-includes/js/zxcvbn.min.js`,
|
|
||||||
})
|
|
||||||
|
|
||||||
AddStaticLocalize("mce-view", "mceViewL10n", map[string]any{
|
|
||||||
"shortcodes": []string{"wp_caption", "caption", "gallery", "playlist", "audio", "video", "embed"},
|
|
||||||
})
|
|
||||||
AddStaticLocalize("word-count", "wordCountL10n", map[string]any{
|
|
||||||
"type": `characters_excluding_spaces`,
|
|
||||||
"shortcodes": []string{"wp_caption", "caption", "gallery", "playlist", "audio", "video", "embed"},
|
|
||||||
})
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func defaultTranslate() {
|
|
||||||
SetTranslation("common", "default", "")
|
|
||||||
SetTranslation("wp-pointer", "default", "")
|
|
||||||
SetTranslation("wp-auth-check", "default", "")
|
|
||||||
SetTranslation("wp-theme-plugin-editor", "default", "")
|
|
||||||
SetTranslation("password-strength-meter", "default", "")
|
|
||||||
SetTranslation("application-passwords", "default", "")
|
|
||||||
SetTranslation("auth-app", "default", "")
|
|
||||||
SetTranslation("user-profile", "default", "")
|
|
||||||
SetTranslation("media-views", "default", "")
|
|
||||||
SetTranslation("media-editor", "default", "")
|
|
||||||
SetTranslation("wp-a11y", "default", "")
|
|
||||||
SetTranslation("wp-annotations", "default", "")
|
|
||||||
SetTranslation("wp-api-fetch", "default", "")
|
|
||||||
SetTranslation("wp-block-directory", "default", "")
|
|
||||||
SetTranslation("wp-block-editor", "default", "")
|
|
||||||
SetTranslation("wp-block-library", "default", "")
|
|
||||||
SetTranslation("wp-blocks", "default", "")
|
|
||||||
SetTranslation("wp-components", "default", "")
|
|
||||||
SetTranslation("wp-core-data", "default", "")
|
|
||||||
SetTranslation("wp-customize-widgets", "default", "")
|
|
||||||
SetTranslation("wp-edit-post", "default", "")
|
|
||||||
SetTranslation("wp-edit-site", "default", "")
|
|
||||||
SetTranslation("wp-edit-widgets", "default", "")
|
|
||||||
SetTranslation("wp-editor", "default", "")
|
|
||||||
SetTranslation("wp-format-library", "default", "")
|
|
||||||
SetTranslation("wp-keycodes", "default", "")
|
|
||||||
SetTranslation("wp-list-reusable-blocks", "default", "")
|
|
||||||
SetTranslation("wp-media-utils", "default", "")
|
|
||||||
SetTranslation("wp-nux", "default", "")
|
|
||||||
SetTranslation("wp-preferences", "default", "")
|
|
||||||
SetTranslation("wp-reusable-blocks", "default", "")
|
|
||||||
SetTranslation("wp-rich-text", "default", "")
|
|
||||||
SetTranslation("wp-server-side-render", "default", "")
|
|
||||||
SetTranslation("wp-widgets", "default", "")
|
|
||||||
SetTranslation("common", "default", "")
|
|
||||||
SetTranslation("wp-pointer", "default", "")
|
|
||||||
SetTranslation("wp-auth-check", "default", "")
|
|
||||||
SetTranslation("wp-theme-plugin-editor", "default", "")
|
|
||||||
SetTranslation("password-strength-meter", "default", "")
|
|
||||||
SetTranslation("application-passwords", "default", "")
|
|
||||||
SetTranslation("auth-app", "default", "")
|
|
||||||
SetTranslation("user-profile", "default", "")
|
|
||||||
SetTranslation("media-views", "default", "")
|
|
||||||
SetTranslation("media-editor", "default", "")
|
|
||||||
SetTranslation("wp-a11y", "default", "")
|
|
||||||
SetTranslation("wp-annotations", "default", "")
|
|
||||||
SetTranslation("wp-api-fetch", "default", "")
|
|
||||||
SetTranslation("wp-block-directory", "default", "")
|
|
||||||
SetTranslation("wp-block-editor", "default", "")
|
|
||||||
SetTranslation("wp-block-library", "default", "")
|
|
||||||
SetTranslation("wp-blocks", "default", "")
|
|
||||||
SetTranslation("wp-components", "default", "")
|
|
||||||
SetTranslation("wp-core-data", "default", "")
|
|
||||||
SetTranslation("wp-customize-widgets", "default", "")
|
|
||||||
SetTranslation("wp-edit-post", "default", "")
|
|
||||||
SetTranslation("wp-edit-site", "default", "")
|
|
||||||
SetTranslation("wp-edit-widgets", "default", "")
|
|
||||||
SetTranslation("wp-editor", "default", "")
|
|
||||||
SetTranslation("wp-format-library", "default", "")
|
|
||||||
SetTranslation("wp-keycodes", "default", "")
|
|
||||||
SetTranslation("wp-list-reusable-blocks", "default", "")
|
|
||||||
SetTranslation("wp-media-utils", "default", "")
|
|
||||||
SetTranslation("wp-nux", "default", "")
|
|
||||||
SetTranslation("wp-preferences", "default", "")
|
|
||||||
SetTranslation("wp-reusable-blocks", "default", "")
|
|
||||||
SetTranslation("wp-rich-text", "default", "")
|
|
||||||
SetTranslation("wp-server-side-render", "default", "")
|
|
||||||
SetTranslation("wp-widgets", "default", "")
|
|
||||||
}
|
|
||||||
|
|
||||||
func defaultAddData() {
|
|
||||||
AddScriptData("json2", "conditional", `lt IE 8`)
|
|
||||||
AddScriptData("wp-embed-template-ie", "conditional", `lte IE 8`)
|
|
||||||
AddScriptData("wp-block-library-theme", "path", `wp-includes/css/dist/block-library/theme.min.css`)
|
|
||||||
AddScriptData("wp-block-editor", "path", `/wp-includes/css/dist/block-editor/style.min.css`)
|
|
||||||
AddScriptData("wp-block-library", "path", `/wp-includes/css/dist/block-library/style.min.css`)
|
|
||||||
AddScriptData("wp-block-directory", "path", `/wp-includes/css/dist/block-directory/style.min.css`)
|
|
||||||
AddScriptData("wp-components", "path", `/wp-includes/css/dist/components/style.min.css`)
|
|
||||||
AddScriptData("wp-edit-post", "path", `/wp-includes/css/dist/edit-post/style.min.css`)
|
|
||||||
AddScriptData("wp-editor", "path", `/wp-includes/css/dist/editor/style.min.css`)
|
|
||||||
AddScriptData("wp-format-library", "path", `/wp-includes/css/dist/format-library/style.min.css`)
|
|
||||||
AddScriptData("wp-list-reusable-blocks", "path", `/wp-includes/css/dist/list-reusable-blocks/style.min.css`)
|
|
||||||
AddScriptData("wp-reusable-blocks", "path", `/wp-includes/css/dist/reusable-blocks/style.min.css`)
|
|
||||||
AddScriptData("wp-nux", "path", `/wp-includes/css/dist/nux/style.min.css`)
|
|
||||||
AddScriptData("wp-widgets", "path", `/wp-includes/css/dist/widgets/style.min.css`)
|
|
||||||
AddScriptData("wp-edit-widgets", "path", `/wp-includes/css/dist/edit-widgets/style.min.css`)
|
|
||||||
AddScriptData("wp-customize-widgets", "path", `/wp-includes/css/dist/customize-widgets/style.min.css`)
|
|
||||||
AddScriptData("wp-edit-site", "path", `/wp-includes/css/dist/edit-site/style.min.css`)
|
|
||||||
AddScriptData("common", "rtl", `replace`)
|
|
||||||
AddScriptData("common", "suffix", `.min`)
|
|
||||||
AddScriptData("forms", "rtl", `replace`)
|
|
||||||
AddScriptData("forms", "suffix", `.min`)
|
|
||||||
AddScriptData("admin-menu", "rtl", `replace`)
|
|
||||||
AddScriptData("admin-menu", "suffix", `.min`)
|
|
||||||
AddScriptData("dashboard", "rtl", `replace`)
|
|
||||||
AddScriptData("dashboard", "suffix", `.min`)
|
|
||||||
AddScriptData("list-tables", "rtl", `replace`)
|
|
||||||
AddScriptData("list-tables", "suffix", `.min`)
|
|
||||||
AddScriptData("edit", "rtl", `replace`)
|
|
||||||
AddScriptData("edit", "suffix", `.min`)
|
|
||||||
AddScriptData("revisions", "rtl", `replace`)
|
|
||||||
AddScriptData("revisions", "suffix", `.min`)
|
|
||||||
AddScriptData("media", "rtl", `replace`)
|
|
||||||
AddScriptData("media", "suffix", `.min`)
|
|
||||||
AddScriptData("themes", "rtl", `replace`)
|
|
||||||
AddScriptData("themes", "suffix", `.min`)
|
|
||||||
AddScriptData("about", "rtl", `replace`)
|
|
||||||
AddScriptData("about", "suffix", `.min`)
|
|
||||||
AddScriptData("nav-menus", "rtl", `replace`)
|
|
||||||
AddScriptData("nav-menus", "suffix", `.min`)
|
|
||||||
AddScriptData("widgets", "rtl", `replace`)
|
|
||||||
AddScriptData("widgets", "suffix", `.min`)
|
|
||||||
AddScriptData("site-icon", "rtl", `replace`)
|
|
||||||
AddScriptData("site-icon", "suffix", `.min`)
|
|
||||||
AddScriptData("l10n", "rtl", `replace`)
|
|
||||||
AddScriptData("l10n", "suffix", `.min`)
|
|
||||||
AddScriptData("install", "rtl", `replace`)
|
|
||||||
AddScriptData("install", "suffix", `.min`)
|
|
||||||
AddScriptData("wp-color-picker", "rtl", `replace`)
|
|
||||||
AddScriptData("wp-color-picker", "suffix", `.min`)
|
|
||||||
AddScriptData("customize-controls", "rtl", `replace`)
|
|
||||||
AddScriptData("customize-controls", "suffix", `.min`)
|
|
||||||
AddScriptData("customize-widgets", "rtl", `replace`)
|
|
||||||
AddScriptData("customize-widgets", "suffix", `.min`)
|
|
||||||
AddScriptData("customize-nav-menus", "rtl", `replace`)
|
|
||||||
AddScriptData("customize-nav-menus", "suffix", `.min`)
|
|
||||||
AddScriptData("customize-preview", "rtl", `replace`)
|
|
||||||
AddScriptData("customize-preview", "suffix", `.min`)
|
|
||||||
AddScriptData("login", "rtl", `replace`)
|
|
||||||
AddScriptData("login", "suffix", `.min`)
|
|
||||||
AddScriptData("site-health", "rtl", `replace`)
|
|
||||||
AddScriptData("site-health", "suffix", `.min`)
|
|
||||||
AddScriptData("buttons", "rtl", `replace`)
|
|
||||||
AddScriptData("buttons", "suffix", `.min`)
|
|
||||||
AddScriptData("admin-bar", "rtl", `replace`)
|
|
||||||
AddScriptData("admin-bar", "suffix", `.min`)
|
|
||||||
AddScriptData("wp-auth-check", "rtl", `replace`)
|
|
||||||
AddScriptData("wp-auth-check", "suffix", `.min`)
|
|
||||||
AddScriptData("editor-buttons", "rtl", `replace`)
|
|
||||||
AddScriptData("editor-buttons", "suffix", `.min`)
|
|
||||||
AddScriptData("media-views", "rtl", `replace`)
|
|
||||||
AddScriptData("media-views", "suffix", `.min`)
|
|
||||||
AddScriptData("wp-pointer", "rtl", `replace`)
|
|
||||||
AddScriptData("wp-pointer", "suffix", `.min`)
|
|
||||||
AddScriptData("wp-jquery-ui-dialog", "rtl", `replace`)
|
|
||||||
AddScriptData("wp-jquery-ui-dialog", "suffix", `.min`)
|
|
||||||
AddScriptData("wp-reset-editor-styles", "rtl", `replace`)
|
|
||||||
AddScriptData("wp-reset-editor-styles", "suffix", `.min`)
|
|
||||||
AddScriptData("wp-editor-classic-layout-styles", "rtl", `replace`)
|
|
||||||
AddScriptData("wp-editor-classic-layout-styles", "suffix", `.min`)
|
|
||||||
AddScriptData("wp-block-library-theme", "rtl", `replace`)
|
|
||||||
AddScriptData("wp-block-library-theme", "suffix", `.min`)
|
|
||||||
AddScriptData("wp-edit-blocks", "rtl", `replace`)
|
|
||||||
AddScriptData("wp-edit-blocks", "suffix", `.min`)
|
|
||||||
AddScriptData("wp-block-editor", "rtl", `replace`)
|
|
||||||
AddScriptData("wp-block-editor", "suffix", `.min`)
|
|
||||||
AddScriptData("wp-block-library", "rtl", `replace`)
|
|
||||||
AddScriptData("wp-block-library", "suffix", `.min`)
|
|
||||||
AddScriptData("wp-block-directory", "rtl", `replace`)
|
|
||||||
AddScriptData("wp-block-directory", "suffix", `.min`)
|
|
||||||
AddScriptData("wp-components", "rtl", `replace`)
|
|
||||||
AddScriptData("wp-components", "suffix", `.min`)
|
|
||||||
AddScriptData("wp-customize-widgets", "rtl", `replace`)
|
|
||||||
AddScriptData("wp-customize-widgets", "suffix", `.min`)
|
|
||||||
AddScriptData("wp-edit-post", "rtl", `replace`)
|
|
||||||
AddScriptData("wp-edit-post", "suffix", `.min`)
|
|
||||||
AddScriptData("wp-edit-site", "rtl", `replace`)
|
|
||||||
AddScriptData("wp-edit-site", "suffix", `.min`)
|
|
||||||
AddScriptData("wp-edit-widgets", "rtl", `replace`)
|
|
||||||
AddScriptData("wp-edit-widgets", "suffix", `.min`)
|
|
||||||
AddScriptData("wp-editor", "rtl", `replace`)
|
|
||||||
AddScriptData("wp-editor", "suffix", `.min`)
|
|
||||||
AddScriptData("wp-format-library", "rtl", `replace`)
|
|
||||||
AddScriptData("wp-format-library", "suffix", `.min`)
|
|
||||||
AddScriptData("wp-list-reusable-blocks", "rtl", `replace`)
|
|
||||||
AddScriptData("wp-list-reusable-blocks", "suffix", `.min`)
|
|
||||||
AddScriptData("wp-reusable-blocks", "rtl", `replace`)
|
|
||||||
AddScriptData("wp-reusable-blocks", "suffix", `.min`)
|
|
||||||
AddScriptData("wp-nux", "rtl", `replace`)
|
|
||||||
AddScriptData("wp-nux", "suffix", `.min`)
|
|
||||||
AddScriptData("wp-widgets", "rtl", `replace`)
|
|
||||||
AddScriptData("wp-widgets", "suffix", `.min`)
|
|
||||||
AddScriptData("deprecated-media", "rtl", `replace`)
|
|
||||||
AddScriptData("deprecated-media", "suffix", `.min`)
|
|
||||||
AddScriptData("farbtastic", "rtl", `replace`)
|
|
||||||
AddScriptData("farbtastic", "suffix", `.min`)
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func defaultAddInLineScript() {
|
|
||||||
AddInlineScript("mediaelement-core", `var mejsL10n = {"language":"zh","strings":{"mejs.download-file":"\u4e0b\u8f7d\u6587\u4ef6","mejs.install-flash":"\u60a8\u6b63\u5728\u4f7f\u7528\u7684\u6d4f\u89c8\u5668\u672a\u5b89\u88c5\u6216\u542f\u7528Flash\u64ad\u653e\u5668\uff0c\u8bf7\u542f\u7528\u60a8\u7684Flash\u64ad\u653e\u5668\u63d2\u4ef6\uff0c\u6216\u4ece https:\/\/get.adobe.com\/flashplayer\/ \u4e0b\u8f7d\u6700\u65b0\u7248\u3002","mejs.fullscreen":"\u5168\u5c4f","mejs.play":"\u64ad\u653e","mejs.pause":"\u6682\u505c","mejs.time-slider":"\u65f6\u95f4\u8f74","mejs.time-help-text":"\u4f7f\u7528\u5de6\/\u53f3\u7bad\u5934\u952e\u6765\u524d\u8fdb\u4e00\u79d2\uff0c\u4e0a\/\u4e0b\u7bad\u5934\u952e\u6765\u524d\u8fdb\u5341\u79d2\u3002","mejs.live-broadcast":"\u73b0\u573a\u76f4\u64ad","mejs.volume-help-text":"\u4f7f\u7528\u4e0a\/\u4e0b\u7bad\u5934\u952e\u6765\u589e\u9ad8\u6216\u964d\u4f4e\u97f3\u91cf\u3002","mejs.unmute":"\u53d6\u6d88\u9759\u97f3","mejs.mute":"\u9759\u97f3","mejs.volume-slider":"\u97f3\u91cf","mejs.video-player":"\u89c6\u9891\u64ad\u653e\u5668","mejs.audio-player":"\u97f3\u9891\u64ad\u653e\u5668","mejs.captions-subtitles":"\u8bf4\u660e\u6587\u5b57\u6216\u5b57\u5e55","mejs.captions-chapters":"\u7ae0\u8282","mejs.none":"\u65e0","mejs.afrikaans":"\u5357\u975e\u8377\u5170\u8bed","mejs.albanian":"\u963f\u5c14\u5df4\u5c3c\u4e9a\u8bed","mejs.arabic":"\u963f\u62c9\u4f2f\u8bed","mejs.belarusian":"\u767d\u4fc4\u7f57\u65af\u8bed","mejs.bulgarian":"\u4fdd\u52a0\u5229\u4e9a\u8bed","mejs.catalan":"\u52a0\u6cf0\u7f57\u5c3c\u4e9a\u8bed","mejs.chinese":"\u4e2d\u6587","mejs.chinese-simplified":"\u4e2d\u6587\uff08\u7b80\u4f53\uff09","mejs.chinese-traditional":"\u4e2d\u6587(\uff08\u7e41\u4f53\uff09","mejs.croatian":"\u514b\u7f57\u5730\u4e9a\u8bed","mejs.czech":"\u6377\u514b\u8bed","mejs.danish":"\u4e39\u9ea6\u8bed","mejs.dutch":"\u8377\u5170\u8bed","mejs.english":"\u82f1\u8bed","mejs.estonian":"\u7231\u6c99\u5c3c\u4e9a\u8bed","mejs.filipino":"\u83f2\u5f8b\u5bbe\u8bed","mejs.finnish":"\u82ac\u5170\u8bed","mejs.french":"\u6cd5\u8bed","mejs.galician":"\u52a0\u5229\u897f\u4e9a\u8bed","mejs.german":"\u5fb7\u8bed","mejs.greek":"\u5e0c\u814a\u8bed","mejs.haitian-creole":"\u6d77\u5730\u514b\u91cc\u5965\u5c14\u8bed","mejs.hebrew":"\u5e0c\u4f2f\u6765\u8bed","mejs.hindi":"\u5370\u5730\u8bed","mejs.hungarian":"\u5308\u7259\u5229\u8bed","mejs.icelandic":"\u51b0\u5c9b\u8bed","mejs.indonesian":"\u5370\u5ea6\u5c3c\u897f\u4e9a\u8bed","mejs.irish":"\u7231\u5c14\u5170\u8bed","mejs.italian":"\u610f\u5927\u5229\u8bed","mejs.japanese":"\u65e5\u8bed","mejs.korean":"\u97e9\u8bed","mejs.latvian":"\u62c9\u8131\u7ef4\u4e9a\u8bed","mejs.lithuanian":"\u7acb\u9676\u5b9b\u8bed","mejs.macedonian":"\u9a6c\u5176\u987f\u8bed","mejs.malay":"\u9a6c\u6765\u8bed","mejs.maltese":"\u9a6c\u8033\u4ed6\u8bed","mejs.norwegian":"\u632a\u5a01\u8bed","mejs.persian":"\u6ce2\u65af\u8bed","mejs.polish":"\u6ce2\u5170\u8bed","mejs.portuguese":"\u8461\u8404\u7259\u8bed","mejs.romanian":"\u7f57\u9a6c\u5c3c\u4e9a\u8bed","mejs.russian":"\u4fc4\u8bed","mejs.serbian":"\u585e\u5c14\u7ef4\u4e9a\u8bed","mejs.slovak":"\u65af\u6d1b\u4f10\u514b\u8bed","mejs.slovenian":"\u65af\u6d1b\u6587\u5c3c\u4e9a\u8bed","mejs.spanish":"\u897f\u73ed\u7259\u8bed","mejs.swahili":"\u65af\u74e6\u5e0c\u91cc\u8bed","mejs.swedish":"\u745e\u5178\u8bed","mejs.tagalog":"\u4ed6\u52a0\u7984\u8bed","mejs.thai":"\u6cf0\u8bed","mejs.turkish":"\u571f\u8033\u5176\u8bed","mejs.ukrainian":"\u4e4c\u514b\u5170\u8bed","mejs.vietnamese":"\u8d8a\u5357\u8bed","mejs.welsh":"\u5a01\u5c14\u58eb\u8bed","mejs.yiddish":"\u610f\u7b2c\u7eea\u8bed"}};`, "before")
|
|
||||||
AddInlineScript("lodash", `window.lodash = _.noConflict();`, "after")
|
|
||||||
AddInlineScript("moment", `moment.updateLocale( 'zh_CN', {"months":["1\u6708","2\u6708","3\u6708","4\u6708","5\u6708","6\u6708","7\u6708","8\u6708","9\u6708","10\u6708","11\u6708","12\u6708"],"monthsShort":["1\u6708","2\u6708","3\u6708","4\u6708","5\u6708","6\u6708","7\u6708","8\u6708","9\u6708","10\u6708","11\u6708","12\u6708"],"weekdays":["\u661f\u671f\u65e5","\u661f\u671f\u4e00","\u661f\u671f\u4e8c","\u661f\u671f\u4e09","\u661f\u671f\u56db","\u661f\u671f\u4e94","\u661f\u671f\u516d"],"weekdaysShort":["\u5468\u65e5","\u5468\u4e00","\u5468\u4e8c","\u5468\u4e09","\u5468\u56db","\u5468\u4e94","\u5468\u516d"],"week":{"dow":1},"longDateFormat":{"LT":"ag:i","LTS":null,"L":null,"LL":"Y\u5e74n\u6708j\u65e5","LLL":"Y\u5e74n\u6708j\u65e5a g:i","LLLL":null}} );`, "after")
|
|
||||||
AddInlineScript("wp-i18n", `wp.i18n.setLocaleData( { 'text direction\u0004ltr': [ 'ltr' ] } );`, "after")
|
|
||||||
AddInlineScript("text-widgets", `wp.textWidgets.idBases.push( "text" );`, "after")
|
|
||||||
AddInlineScript("custom-html-widgets", `wp.customHtmlWidgets.idBases.push( "custom_html" );`, "after")
|
|
||||||
}
|
|
||||||
|
|
||||||
func defaultAddInLineStyle() {
|
|
||||||
AddInlineStyle("global-styles", GetGlobalStyletSheet())
|
|
||||||
AddInlineStyle("global-styles", `.wp-block-navigation a:where(:not(.wp-element-button)){color: inherit;}`)
|
|
||||||
AddInlineStyle("global-styles", `:where(.wp-block-columns.is-layout-flex){gap: 2em;}`)
|
|
||||||
AddInlineStyle("global-styles", `.wp-block-pullquote{font-size: 1.5em;line-height: 1.6;}`)
|
|
||||||
}
|
|
||||||
|
|
||||||
var re = regexp.MustCompile(`(?is:\([A-Za-z0-9'.:\-/, ]+\))`)
|
|
||||||
var rea = regexp.MustCompile(`array\(array\(.*?\)\)`)
|
|
||||||
|
|
||||||
func InitDefaultScriptSetting() {
|
|
||||||
initThemeJson()
|
|
||||||
defaultLocalize()
|
|
||||||
defaultTranslate()
|
|
||||||
defaultAddData()
|
|
||||||
defaultAddInLineScript()
|
|
||||||
defaultAddInLineStyle()
|
|
||||||
}
|
|
||||||
|
|
||||||
func initThemeJson() {
|
|
||||||
blocksData := __blocksData()
|
|
||||||
path := config.GetConfig().WpDir
|
|
||||||
f, err := os.ReadFile(filepath.Join(path, "wp-includes/theme.json"))
|
|
||||||
if err != nil {
|
|
||||||
logs.Error(err, "can't open theme json", path)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
var j map[string]any
|
|
||||||
err = json.Unmarshal(f, &j)
|
|
||||||
if err != nil {
|
|
||||||
logs.Error(err, "can't parse theme json")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
t := ThemeJson{blocksData, j}
|
|
||||||
setThemeJson(j)
|
|
||||||
setSpacingSizes(t)
|
|
||||||
__themeJson.Store(t)
|
|
||||||
}
|
|
||||||
|
|
||||||
func setThemeJson(m map[string]any) {
|
|
||||||
blocks, ok := maps.GetStrAnyVal[map[string]any](m, "settings.blocks")
|
|
||||||
if !ok {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
var paths = [][]string{{"settings"}}
|
|
||||||
for name := range blocks {
|
|
||||||
paths = append(paths, []string{"settings", "blocks", name})
|
|
||||||
}
|
|
||||||
for _, path := range paths {
|
|
||||||
for _, metadatum := range presetsMetadata {
|
|
||||||
pathx := append(path, metadatum.path...)
|
|
||||||
key := strings.Join(pathx, ".")
|
|
||||||
preset, ok := maps.GetStrAnyVal[[]any](m, key)
|
|
||||||
if !ok || len(preset) < 1 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
var presets []map[string]string
|
|
||||||
for _, a := range preset {
|
|
||||||
v, ok := a.(map[string]any)
|
|
||||||
if !ok {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
mm := map[string]string{}
|
|
||||||
for kk, vv := range v {
|
|
||||||
val, ok := vv.(string)
|
|
||||||
if !ok {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
mm[kk] = val
|
|
||||||
}
|
|
||||||
presets = append(presets, mm)
|
|
||||||
}
|
|
||||||
maps.SetStrAnyVal(m, key, map[string]any{
|
|
||||||
"default": presets,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var __propertyMappings = map[string]string{
|
|
||||||
"apiVersion": "api_version",
|
|
||||||
"title": "title",
|
|
||||||
"category": "category",
|
|
||||||
"parent": "parent",
|
|
||||||
"ancestor": "ancestor",
|
|
||||||
"icon": "icon",
|
|
||||||
"description": "description",
|
|
||||||
"keywords": "keywords",
|
|
||||||
"attributes": "attributes",
|
|
||||||
"providesContext": "provides_context",
|
|
||||||
"usesContext": "uses_context",
|
|
||||||
"supports": "supports",
|
|
||||||
"styles": "styles",
|
|
||||||
"variations": "variations",
|
|
||||||
"example": "example",
|
|
||||||
}
|
|
||||||
|
|
||||||
func __propertyMap(m map[string]any) {
|
|
||||||
for k, mappedKey := range __propertyMappings {
|
|
||||||
vv, ok := m[k]
|
|
||||||
if ok {
|
|
||||||
m[mappedKey] = vv
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func __blocksData() map[string]any {
|
|
||||||
path := config.GetConfig().WpDir
|
|
||||||
//path := "/var/www/html/wordpress"
|
|
||||||
b, err := os.ReadFile(filepath.Join(path, "wp-includes/blocks/blocks-json.php"))
|
|
||||||
if err != nil {
|
|
||||||
logs.Error(err, "can't open block json", path)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
bb := re.ReplaceAllStringFunc(string(b), func(s string) string {
|
|
||||||
return str.Replace(s, map[string]string{
|
|
||||||
"(": "[",
|
|
||||||
")": "]",
|
|
||||||
})
|
|
||||||
})
|
|
||||||
bb = strings.ReplaceAll(bb, "\"", `\"`)
|
|
||||||
bb = rea.ReplaceAllStringFunc(bb, func(s string) string {
|
|
||||||
s = strings.ReplaceAll(s, "array(array", "[")
|
|
||||||
ss := []rune(s)
|
|
||||||
ss[len(ss)-1] = ']'
|
|
||||||
s = string(ss)
|
|
||||||
return s
|
|
||||||
})
|
|
||||||
bb = str.Replace(bb, map[string]string{
|
|
||||||
"<?php": "",
|
|
||||||
"return": "",
|
|
||||||
"array": "",
|
|
||||||
"()": "[]",
|
|
||||||
"(": "{",
|
|
||||||
")": "}",
|
|
||||||
"=>": ":",
|
|
||||||
";": "",
|
|
||||||
"'": `"`,
|
|
||||||
})
|
|
||||||
|
|
||||||
var blocks map[string]any
|
|
||||||
err = json.Unmarshal([]byte(bb), &blocks)
|
|
||||||
if err != nil {
|
|
||||||
logs.Error(err, "can't parse block json")
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
c := map[string]any{
|
|
||||||
"version": int64(2),
|
|
||||||
}
|
|
||||||
for k, v := range blocks {
|
|
||||||
m, ok := v.(map[string]any)
|
|
||||||
if !ok {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
_, ok = m["style"]
|
|
||||||
if !ok {
|
|
||||||
m["style"] = str.Join("wp-block-", k)
|
|
||||||
}
|
|
||||||
_, ok = m["editorStyle"]
|
|
||||||
if !ok {
|
|
||||||
m["editorStyle"] = str.Join("wp-block-", k, "-editor")
|
|
||||||
}
|
|
||||||
__propertyMap(m)
|
|
||||||
name := maps.GetStrAnyValWithDefaults(m, "name", str.Join("core/", k))
|
|
||||||
blocks[name] = v
|
|
||||||
if name != k {
|
|
||||||
delete(blocks, k)
|
|
||||||
}
|
|
||||||
__blockSelectors(m)
|
|
||||||
s, ok := maps.GetStrAnyVal[map[string]any](m, "supports.__experimentalStyle")
|
|
||||||
if ok {
|
|
||||||
__removeComment(s)
|
|
||||||
maps.SetStrAnyVal(c, str.Join("styles.blocks.", name), s)
|
|
||||||
}
|
|
||||||
_, ok = maps.GetStrAnyVal[string](m, "supports.spacing.blockGap.__experimentalDefault")
|
|
||||||
if ok {
|
|
||||||
key := str.Join("styles.blocks.", name, ".spacing.blockGap")
|
|
||||||
_, ok := maps.GetStrAnyVal[string](c, key)
|
|
||||||
if !ok {
|
|
||||||
maps.SetStrAnyVal[map[string]any](c, key, nil)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return map[string]any{
|
|
||||||
"blocks_metadata": blocks,
|
|
||||||
"theme_json": c,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func __blockSelectors(m map[string]any) {
|
|
||||||
selector, ok := maps.GetStrAnyVal[string](m, "supports.__experimentalSelector")
|
|
||||||
if !ok {
|
|
||||||
vv, _ := maps.GetStrAnyVal[string](m, "name")
|
|
||||||
selector = str.Join(".wp-block-", str.Replaces(vv,
|
|
||||||
[]string{"core/", ""},
|
|
||||||
[]string{"/", "-"},
|
|
||||||
))
|
|
||||||
}
|
|
||||||
var features = map[string]string{}
|
|
||||||
maps.SetStrAnyVal(m, "supports.selector", selector)
|
|
||||||
color, ok := maps.GetStrAnyVal[string](m, "supports.color.__experimentalDuotone")
|
|
||||||
if ok {
|
|
||||||
maps.SetStrAnyVal(m, "duotone", color)
|
|
||||||
}
|
|
||||||
for k, v := range blockSupportFeatureLevelSelectors {
|
|
||||||
key := str.Join("supports.", k, ".__experimentalSelector")
|
|
||||||
vv, ok := maps.GetStrAnyVal[string](m, key)
|
|
||||||
if ok && vv != "" {
|
|
||||||
features[v] = scopeSelector(selector, vv)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if len(features) > 0 {
|
|
||||||
m["features"] = features
|
|
||||||
}
|
|
||||||
blockSelector := strings.Split(selector, ",")
|
|
||||||
for name, selor := range __elements {
|
|
||||||
var els []string
|
|
||||||
for _, s := range blockSelector {
|
|
||||||
if s == selor {
|
|
||||||
els = append(els, selor)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
els = append(els, appendToSelector(selor, str.Join(s, " "), "left"))
|
|
||||||
}
|
|
||||||
maps.SetStrAnyVal(m, str.Join("elements.", name), strings.Join(els, ","))
|
|
||||||
}
|
|
||||||
styles, ok := maps.GetStrAnyVal[[]any](m, "styles")
|
|
||||||
if ok {
|
|
||||||
var styleSelectors = map[string]string{}
|
|
||||||
for _, ss := range styles {
|
|
||||||
s, ok := ss.(map[string]any)
|
|
||||||
if !ok {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
name, ok := maps.GetStrAnyVal[string](s, "name")
|
|
||||||
if !ok {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
styleSelectors[name] = appendToSelector(str.Join(".is-style-", name, ".is-style-", name), selector, "")
|
|
||||||
}
|
|
||||||
m["styleVariations"] = styleSelectors
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,20 +0,0 @@
|
||||||
package scriptloader
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func Test_themeJson(t *testing.T) {
|
|
||||||
tests := []struct {
|
|
||||||
name string
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
name: "t1",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
for _, tt := range tests {
|
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
|
||||||
initThemeJson()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,7 +0,0 @@
|
||||||
package scriptloader
|
|
||||||
|
|
||||||
import "github.com/fthvgb1/wp-go/safety"
|
|
||||||
|
|
||||||
func defaultStyles(m *safety.Map[string, *Style], suffix string) {
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,218 +0,0 @@
|
||||||
package scriptloader
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"github.com/fthvgb1/wp-go/app/cmd/reload"
|
|
||||||
"github.com/fthvgb1/wp-go/app/pkg/config"
|
|
||||||
"github.com/fthvgb1/wp-go/app/pkg/constraints"
|
|
||||||
"github.com/fthvgb1/wp-go/app/pkg/logs"
|
|
||||||
"github.com/fthvgb1/wp-go/app/theme/wp"
|
|
||||||
"github.com/fthvgb1/wp-go/app/theme/wp/components/widget"
|
|
||||||
"github.com/fthvgb1/wp-go/app/wpconfig"
|
|
||||||
"github.com/fthvgb1/wp-go/helper"
|
|
||||||
"github.com/fthvgb1/wp-go/helper/number"
|
|
||||||
"github.com/fthvgb1/wp-go/helper/slice"
|
|
||||||
str "github.com/fthvgb1/wp-go/helper/strings"
|
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
)
|
|
||||||
|
|
||||||
type _style struct {
|
|
||||||
handle string
|
|
||||||
src string
|
|
||||||
path string
|
|
||||||
size int64
|
|
||||||
}
|
|
||||||
|
|
||||||
func MaybeInlineStyles(h *wp.Handle) {
|
|
||||||
totalInlineLimit := int64(0)
|
|
||||||
var styles []_style
|
|
||||||
ss := styleQueues.Load()
|
|
||||||
for _, que := range ss.Queue {
|
|
||||||
p, ok := __styles.Load(que)
|
|
||||||
if !ok {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
f, ok := p.Extra["path"]
|
|
||||||
if !ok || f == nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
ff := f[0]
|
|
||||||
stat, err := os.Stat(ff)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
styles = append(styles, _style{
|
|
||||||
handle: que,
|
|
||||||
src: p.Src,
|
|
||||||
path: ff,
|
|
||||||
size: stat.Size(),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
if len(styles) < 1 {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
slice.Sort(styles, func(i, j _style) bool {
|
|
||||||
return i.size > j.size
|
|
||||||
})
|
|
||||||
totalInlineSize := int64(0)
|
|
||||||
for _, i := range styles {
|
|
||||||
if totalInlineSize+i.size > totalInlineLimit {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
path := filepath.Join(i.path)
|
|
||||||
css := reload.GetAnyValMapBy("script-loader-MaybeInlineStyles", i.handle, path, func(a string) string {
|
|
||||||
css, err := os.ReadFile(i.path)
|
|
||||||
if err != nil {
|
|
||||||
logs.Error(err, "read file ", i.path)
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
return string(css)
|
|
||||||
})
|
|
||||||
|
|
||||||
s, _ := __styles.Load(i.handle)
|
|
||||||
s.Src = ""
|
|
||||||
a := s.Extra["after"]
|
|
||||||
if a == nil {
|
|
||||||
a = []string{}
|
|
||||||
}
|
|
||||||
slice.Unshift(&a, css)
|
|
||||||
s.Extra["after"] = a
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func emojiDetectionScript(h *wp.Handle) {
|
|
||||||
settings := map[string]any{
|
|
||||||
"baseUrl": "https://s.w.org/images/core/emoji/14.0.0/72x72/",
|
|
||||||
"ext": ".png",
|
|
||||||
"svgUrl": "https://s.w.org/images/core/emoji/14.0.0/svg/", "svgExt": ".svg",
|
|
||||||
"source": map[string]any{
|
|
||||||
"concatemoji": "/wp-includes/js/wp-emoji-release.min.js?ver=6.2.2",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
setting, _ := json.Marshal(settings)
|
|
||||||
dir := config.GetConfig().WpDir
|
|
||||||
emotion := reload.GetAnyValBys("script-loader-emoji", struct{}{}, func(_ struct{}) string {
|
|
||||||
f, err := os.ReadFile(dir)
|
|
||||||
if err != nil {
|
|
||||||
logs.Error(err, "load emoji css fail", dir)
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
return string(f)
|
|
||||||
})
|
|
||||||
s := str.Join("window._wpemojiSettings = ", string(setting), "\n", emotion)
|
|
||||||
PrintInlineScriptTag(h, s, nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
func PrintInlineScriptTag(h *wp.Handle, script string, attr map[string]string) {
|
|
||||||
ss := wp.GetComponentsArgs(h, "inlineScript", "")
|
|
||||||
s := str.NewBuilder()
|
|
||||||
s.WriteString(ss)
|
|
||||||
s.WriteString("<script")
|
|
||||||
for k, v := range attr {
|
|
||||||
s.Sprintf(` %s="%s"`, k, v)
|
|
||||||
}
|
|
||||||
s.Sprintf(">%s</script>\n", script)
|
|
||||||
wp.SetComponentsArgs(h, "inlineScript", s.String())
|
|
||||||
}
|
|
||||||
|
|
||||||
func PrintInlineStyles(handle string) string {
|
|
||||||
o, _ := __styles.Load(handle)
|
|
||||||
out := o.getData("after")
|
|
||||||
if out == "" {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
return fmt.Sprintf("<style id='%s-inline-css'%s>\n%s\n</style>\n", handle, "", out)
|
|
||||||
}
|
|
||||||
|
|
||||||
func PrintStyle(h *wp.Handle, s ...string) {
|
|
||||||
out := wp.GetComponentsArgs(h, "wp_style_out", str.NewBuilder())
|
|
||||||
out.WriteString(s...)
|
|
||||||
}
|
|
||||||
func PrintHead(h *wp.Handle, s ...string) {
|
|
||||||
out := wp.GetComponentsArgs(h, "wp_head", str.NewBuilder())
|
|
||||||
out.WriteString(s...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func LinkHead(h *wp.Handle) {
|
|
||||||
PrintHead(h, "<link rel=\"https://api.w.org/\" href=\"/wp-json\" />")
|
|
||||||
if s := restGetQueriedResourceRoute(h); s != "" {
|
|
||||||
PrintHead(h, "<link rel=\"alternate\" type=\"application/json\" href=", s, " />")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func restGetQueriedResourceRoute(h *wp.Handle) string {
|
|
||||||
if cate, ok := widget.IsCategory(h); ok {
|
|
||||||
return fmt.Sprintf("/wp/v2/categories/%d", cate.Terms.TermId)
|
|
||||||
}
|
|
||||||
if tag, ok := widget.IsTag(h); ok {
|
|
||||||
return fmt.Sprintf("/wp/v2/tags/%d", tag.Terms.TermId)
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
func RsdLink(h *wp.Handle) {
|
|
||||||
PrintHead(h, fmt.Sprintf("<link rel=\"EditURI\" type=\"application/rsd+xml\" title=\"RSD\" href=\"%s\" />\n", "xmlrpc.php?rsd"))
|
|
||||||
}
|
|
||||||
|
|
||||||
func WlwmanifestLink(h *wp.Handle) {
|
|
||||||
PrintHead(h, fmt.Sprintf("<link rel=\"wlwmanifest\" type=\"application/wlwmanifest+xml\" href=\"%s\" />\n", "/wp-includes/wlwmanifest.xml"))
|
|
||||||
}
|
|
||||||
|
|
||||||
func LocaleStylesheet(h *wp.Handle) {
|
|
||||||
uri := reload.GetAnyValBys("printHead-localStylesheet", h, func(a *wp.Handle) string {
|
|
||||||
ur := str.Join("wp-content/themes", h.Theme(), str.Join(wpconfig.GetLang(), ".css"))
|
|
||||||
path := filepath.Join(config.GetConfig().WpDir, ur)
|
|
||||||
if helper.FileExist(path) {
|
|
||||||
return str.Join("/", ur)
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
})
|
|
||||||
if uri != "" {
|
|
||||||
PrintHead(h, fmt.Sprintf("<link rel=\"stylesheet\" href=\"%s\"%s media=\"screen\" />", uri, ""))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TheGenerator(h *wp.Handle) {
|
|
||||||
PrintHead(h, fmt.Sprintf(`<meta name="generator" content="WordPress %s"/>`, "6.2.2"))
|
|
||||||
}
|
|
||||||
|
|
||||||
func ShortLinkWpHead(h *wp.Handle) {
|
|
||||||
if h.Scene() != constraints.Detail || h.Detail.Post.Id < 1 {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
shortlink := ""
|
|
||||||
post := h.Detail.Post
|
|
||||||
if post.PostType == "page" && wpconfig.GetOption("page_on_front") == number.IntToString(post.Id) &&
|
|
||||||
wpconfig.GetOption("show_on_front") == "page" {
|
|
||||||
shortlink = "/"
|
|
||||||
} else {
|
|
||||||
shortlink = str.Join("/p/", number.IntToString(post.Id))
|
|
||||||
}
|
|
||||||
if shortlink != "" {
|
|
||||||
PrintHead(h, fmt.Sprintf(`<link rel='shortlink' href="%s" />`, shortlink))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func customLogoHeaderStyles(h *wp.Handle) {
|
|
||||||
mod := h.CommonThemeMods()
|
|
||||||
if !mod.ThemeSupport.CustomHeader.HeaderText && mod.ThemeSupport.CustomLogo.HeaderText != "" {
|
|
||||||
class := mod.ThemeSupport.CustomLogo.HeaderText
|
|
||||||
attr := ""
|
|
||||||
if !slice.IsContained(mod.ThemeSupport.HTML5, "style") {
|
|
||||||
attr = ` type="text/css"`
|
|
||||||
}
|
|
||||||
PrintHead(h, fmt.Sprintf(`<style id="custom-logo-css"%s>
|
|
||||||
.%s {
|
|
||||||
position: absolute;
|
|
||||||
clip: rect(1px, 1px, 1px, 1px);
|
|
||||||
}
|
|
||||||
</style>`, attr, class))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func PrintHeadToStr(h *wp.Handle) string {
|
|
||||||
h.DoActionFilter("wp_head", "", h)
|
|
||||||
return wp.GetComponentsArgs(h, "wp_head", str.NewBuilder()).String()
|
|
||||||
}
|
|
|
@ -1,409 +0,0 @@
|
||||||
package scriptloader
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"github.com/fthvgb1/wp-go/app/cmd/reload"
|
|
||||||
"github.com/fthvgb1/wp-go/app/theme/wp"
|
|
||||||
"github.com/fthvgb1/wp-go/app/wpconfig"
|
|
||||||
"github.com/fthvgb1/wp-go/helper"
|
|
||||||
"github.com/fthvgb1/wp-go/helper/maps"
|
|
||||||
"github.com/fthvgb1/wp-go/helper/slice"
|
|
||||||
str "github.com/fthvgb1/wp-go/helper/strings"
|
|
||||||
"github.com/fthvgb1/wp-go/safety"
|
|
||||||
"net/url"
|
|
||||||
"path/filepath"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
var __styles = reload.MapBy(func(m *safety.Map[string, *Style]) {
|
|
||||||
defaultStyles(m, ".css")
|
|
||||||
})
|
|
||||||
var __scripts = reload.MapBy[string, *Script](func(m *safety.Map[string, *Script]) {
|
|
||||||
suffix := ".min"
|
|
||||||
defaultScripts(m, suffix)
|
|
||||||
|
|
||||||
})
|
|
||||||
|
|
||||||
type Style struct {
|
|
||||||
Dependencies
|
|
||||||
}
|
|
||||||
|
|
||||||
type Script struct {
|
|
||||||
Dependencies
|
|
||||||
}
|
|
||||||
|
|
||||||
func addScript(handle string, src string, deps []string, ver string, args any) {
|
|
||||||
script := NewScript(handle, src, deps, ver, args)
|
|
||||||
__scripts.Store(handle, script)
|
|
||||||
}
|
|
||||||
|
|
||||||
func localize(handle, objectname string, l10n map[string]any) string {
|
|
||||||
if "jquery" == handle {
|
|
||||||
handle = "jquery-core"
|
|
||||||
}
|
|
||||||
after, ok := maps.GetStrAnyVal[string](l10n, "l10n_print_after")
|
|
||||||
if ok {
|
|
||||||
delete(l10n, "l10n_print_after")
|
|
||||||
}
|
|
||||||
v, _ := json.Marshal(l10n)
|
|
||||||
script := fmt.Sprintf("var %s = %s;", objectname, string(v))
|
|
||||||
if after != "" {
|
|
||||||
script = str.Join(script, "\n", after, ";")
|
|
||||||
}
|
|
||||||
return script
|
|
||||||
}
|
|
||||||
|
|
||||||
func AddStaticLocalize(handle, objectname string, l10n map[string]any) {
|
|
||||||
AddScriptData(handle, "data", localize(handle, objectname, l10n))
|
|
||||||
}
|
|
||||||
func AddDynamicLocalize(h *wp.Handle, handle, objectname string, l10n map[string]any) {
|
|
||||||
AddDynamicData(h, handle, "data", localize(handle, objectname, l10n))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *Dependencies) getData(key string) string {
|
|
||||||
return strings.Join(d.Extra[key], "\n")
|
|
||||||
}
|
|
||||||
func GetData(h *wp.Handle, handle, key string) string {
|
|
||||||
hh, ok := __scripts.Load(handle)
|
|
||||||
if !ok {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
d := hh.Extra[key]
|
|
||||||
d = append(d, GetDynamicData(h, handle, key))
|
|
||||||
return strings.Join(d, "\n")
|
|
||||||
}
|
|
||||||
|
|
||||||
func AddScriptData(handle, key, data string) {
|
|
||||||
var s *Script
|
|
||||||
var ok bool
|
|
||||||
s, ok = __scripts.Load(handle)
|
|
||||||
if !ok {
|
|
||||||
s = NewScript(handle, "", nil, "", nil)
|
|
||||||
}
|
|
||||||
if s.Extra == nil {
|
|
||||||
s.Extra = make(map[string][]string)
|
|
||||||
}
|
|
||||||
s.Extra[key] = append(s.Extra[key], data)
|
|
||||||
}
|
|
||||||
|
|
||||||
func AddStyleData(handle, key, data string) {
|
|
||||||
var s *Style
|
|
||||||
var ok bool
|
|
||||||
s, ok = __styles.Load(handle)
|
|
||||||
if !ok {
|
|
||||||
s = NewStyle(handle, "", nil, "", nil)
|
|
||||||
}
|
|
||||||
if s.Extra == nil {
|
|
||||||
s.Extra = make(map[string][]string)
|
|
||||||
}
|
|
||||||
s.Extra[key] = append(s.Extra[key], data)
|
|
||||||
}
|
|
||||||
|
|
||||||
func AddInlineScript(handle, data, position string) {
|
|
||||||
if handle == "" || data == "" {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if position != "after" {
|
|
||||||
position = "before"
|
|
||||||
}
|
|
||||||
AddScriptData(handle, position, data)
|
|
||||||
}
|
|
||||||
|
|
||||||
func AddInlineStyle(handle, data string) {
|
|
||||||
if handle == "" || data == "" {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
AddStyleData(handle, "after", data)
|
|
||||||
}
|
|
||||||
|
|
||||||
func InlineScripts(handle, position string, display bool) string {
|
|
||||||
v, _ := __scripts.Load(handle)
|
|
||||||
ss := v.getData(position)
|
|
||||||
if ss == "" {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
scp := strings.Trim(ss, "\n")
|
|
||||||
if display {
|
|
||||||
return fmt.Sprintf("<script id='%s-js-%s'>\n%s\n</script>\n", handle, position, scp)
|
|
||||||
}
|
|
||||||
return scp
|
|
||||||
}
|
|
||||||
|
|
||||||
func AddScript(handle string, src string, deps []string, ver string, args any) {
|
|
||||||
script := NewScript(handle, src, deps, ver, args)
|
|
||||||
__scripts.Store(handle, script)
|
|
||||||
}
|
|
||||||
|
|
||||||
const (
|
|
||||||
style = iota
|
|
||||||
script
|
|
||||||
)
|
|
||||||
|
|
||||||
var scriptQueues = reload.Vars(scriptQueue{})
|
|
||||||
var styleQueues = reload.Vars(scriptQueue{})
|
|
||||||
|
|
||||||
type scriptQueue struct {
|
|
||||||
Register map[string]struct{}
|
|
||||||
Queue []string
|
|
||||||
Args map[string]string
|
|
||||||
queuedBeforeRegister map[string]string
|
|
||||||
}
|
|
||||||
|
|
||||||
func EnqueueStyle(handle, src string, deps []string, ver, media string) {
|
|
||||||
if media == "" {
|
|
||||||
media = "all"
|
|
||||||
}
|
|
||||||
|
|
||||||
h := strings.Split(handle, "?")
|
|
||||||
if src != "" {
|
|
||||||
AddScript(h[0], src, deps, ver, media)
|
|
||||||
}
|
|
||||||
enqueue(handle, style)
|
|
||||||
}
|
|
||||||
func EnqueueStyles(handle, src string, deps []string, ver, media string) {
|
|
||||||
if src != "" {
|
|
||||||
src = GetThemeFileUri(src)
|
|
||||||
}
|
|
||||||
EnqueueStyle(handle, src, deps, ver, media)
|
|
||||||
}
|
|
||||||
func EnqueueScript(handle, src string, deps []string, ver string, inFooter bool) {
|
|
||||||
h := strings.Split(handle, "?")
|
|
||||||
if src != "" {
|
|
||||||
AddScript(h[0], src, deps, ver, nil)
|
|
||||||
}
|
|
||||||
if inFooter {
|
|
||||||
AddScriptData(h[0], "group", "1")
|
|
||||||
}
|
|
||||||
enqueue(handle, script)
|
|
||||||
}
|
|
||||||
func EnqueueScripts(handle, src string, deps []string, ver string, inFooter bool) {
|
|
||||||
if src != "" {
|
|
||||||
src = GetThemeFileUri(src)
|
|
||||||
}
|
|
||||||
EnqueueScript(handle, src, deps, ver, inFooter)
|
|
||||||
}
|
|
||||||
|
|
||||||
func enqueue(handle string, t int) {
|
|
||||||
h := strings.Split(handle, "?")
|
|
||||||
ss := styleQueues.Load()
|
|
||||||
if t == 1 {
|
|
||||||
ss = scriptQueues.Load()
|
|
||||||
}
|
|
||||||
if slice.IsContained(ss.Queue, h[0]) && maps.IsExists(ss.Register, h[0]) {
|
|
||||||
ss.Queue = append(ss.Queue, h[0])
|
|
||||||
} else if maps.IsExists(ss.Register, h[0]) {
|
|
||||||
ss.queuedBeforeRegister[h[0]] = ""
|
|
||||||
if len(h) > 1 {
|
|
||||||
ss.queuedBeforeRegister[h[0]] = h[1]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetStylesheetUri() string {
|
|
||||||
return GetThemeFileUri("/styles.css")
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetThemeFileUri(file string) string {
|
|
||||||
return filepath.Join("/wp-content/themes", wpconfig.GetOption("template"), file)
|
|
||||||
}
|
|
||||||
|
|
||||||
type Dependencies struct {
|
|
||||||
Handle string `json:"handle,omitempty"`
|
|
||||||
Src string `json:"src,omitempty"`
|
|
||||||
Deps []string `json:"deps,omitempty"`
|
|
||||||
Ver string `json:"ver,omitempty"`
|
|
||||||
Args any `json:"args,omitempty"`
|
|
||||||
Extra map[string][]string `json:"extra,omitempty"`
|
|
||||||
Textdomain string `json:"textdomain,omitempty"`
|
|
||||||
TranslationsPath string `json:"translations_path,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewScript(handle string, src string, deps []string, ver string, args any) *Script {
|
|
||||||
return &Script{Dependencies{Handle: handle, Src: src, Deps: deps, Ver: ver, Args: args}}
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewStyle(handle string, src string, deps []string, ver string, args any) *Style {
|
|
||||||
return &Style{Dependencies{Handle: handle, Src: src, Deps: deps, Ver: ver, Args: args}}
|
|
||||||
}
|
|
||||||
|
|
||||||
func AddDynamicData(h *wp.Handle, handle, key, data string) {
|
|
||||||
da := helper.GetContextVal(h.C, "__scriptDynamicData__", map[string]map[string][]string{})
|
|
||||||
m, ok := da[handle]
|
|
||||||
if !ok {
|
|
||||||
m = map[string][]string{}
|
|
||||||
}
|
|
||||||
m[key] = append(m[key], data)
|
|
||||||
da[handle] = m
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetDynamicData(h *wp.Handle, handle, key string) string {
|
|
||||||
da := helper.GetContextVal(h.C, "__scriptDynamicData__", map[string]map[string][]string{})
|
|
||||||
if len(da) < 1 {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
m, ok := da[handle]
|
|
||||||
if !ok {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
mm, ok := m[key]
|
|
||||||
if !ok {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
return strings.Join(mm, "\n")
|
|
||||||
}
|
|
||||||
|
|
||||||
func SetTranslation(handle, domain, path string) {
|
|
||||||
hh, ok := __scripts.Load(handle)
|
|
||||||
if !ok {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if !slice.IsContained(hh.Deps, handle) {
|
|
||||||
hh.Deps = append(hh.Deps, "wp-i18n")
|
|
||||||
}
|
|
||||||
if domain == "" {
|
|
||||||
domain = "default"
|
|
||||||
}
|
|
||||||
hh.Textdomain = domain
|
|
||||||
hh.TranslationsPath = path
|
|
||||||
}
|
|
||||||
|
|
||||||
func (item *__parseLoadItem) allDeps(handles []string, recursion bool, group int) bool {
|
|
||||||
for _, handle := range handles {
|
|
||||||
parts := strings.Split(handle, "?")
|
|
||||||
queued := slice.IsContained(item.todo, parts[0])
|
|
||||||
handle = parts[0]
|
|
||||||
moved := item.setGroup(handle, group)
|
|
||||||
if queued || !moved {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
newGroup := item.groups[handle]
|
|
||||||
keepGoing := true
|
|
||||||
h, ok := __styles.Load(handle)
|
|
||||||
if !ok {
|
|
||||||
keepGoing = false
|
|
||||||
}
|
|
||||||
if len(h.Deps) > 0 && len(slice.Diff(h.Deps, __styles.Keys())) > 0 {
|
|
||||||
keepGoing = false
|
|
||||||
}
|
|
||||||
if len(h.Deps) > 0 && item.allDeps(h.Deps, true, newGroup) {
|
|
||||||
keepGoing = false
|
|
||||||
}
|
|
||||||
if !keepGoing {
|
|
||||||
if recursion {
|
|
||||||
return false
|
|
||||||
} else {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if len(parts) > 1 {
|
|
||||||
item.args[handle] = parts[1]
|
|
||||||
}
|
|
||||||
item.todo = append(item.todo, handle)
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
type __parseLoadItem struct {
|
|
||||||
todo []string
|
|
||||||
done []string
|
|
||||||
groups map[string]int
|
|
||||||
args map[string]string
|
|
||||||
textDirection string
|
|
||||||
concat string
|
|
||||||
doConcat bool
|
|
||||||
}
|
|
||||||
|
|
||||||
func newParseLoadItem() *__parseLoadItem {
|
|
||||||
return &__parseLoadItem{
|
|
||||||
groups: map[string]int{},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (item *__parseLoadItem) setGroup(handle string, group int) bool {
|
|
||||||
if v, ok := item.groups[handle]; ok && v <= group {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
item.groups[handle] = group
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
func DoStyleItems(h *wp.Handle, handles []string, group int) []string {
|
|
||||||
item := newParseLoadItem()
|
|
||||||
item.allDeps(handles, false, 0)
|
|
||||||
for i, handle := range item.todo {
|
|
||||||
_, ok := __styles.Load(handle)
|
|
||||||
if !slice.IsContained(item.done, handle) && ok {
|
|
||||||
if DoStyleItem(h, item, handle, group) {
|
|
||||||
item.done = append(item.done, handle)
|
|
||||||
}
|
|
||||||
slice.Delete(&item.todo, i)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return item.done
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Style) DoHeadItems() {
|
|
||||||
|
|
||||||
}
|
|
||||||
func (s *Style) DoItems(handle string) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func DoStyleItem(h *wp.Handle, item *__parseLoadItem, handle string, group int) bool {
|
|
||||||
obj, _ := __styles.Load(handle)
|
|
||||||
ver := obj.Ver
|
|
||||||
if item.args[handle] != "" {
|
|
||||||
str.Join(ver, "&", item.args[handle])
|
|
||||||
}
|
|
||||||
src := obj.Src
|
|
||||||
var condBefore, condAfter, conditional, _ string
|
|
||||||
if v, ok := obj.Extra["conditional"]; ok && v != nil {
|
|
||||||
conditional = v[0]
|
|
||||||
}
|
|
||||||
if conditional != "" {
|
|
||||||
condBefore = str.Join("<!==[if ", conditional, "]>\n")
|
|
||||||
condAfter = "<![endif]-->\n"
|
|
||||||
}
|
|
||||||
inlineStyle := item.PrintInline(handle)
|
|
||||||
if inlineStyle != "" {
|
|
||||||
_ = fmt.Sprintf("<style id='%s-inline-css'%s>\n%s\n</style>\n", handle, "", inlineStyle)
|
|
||||||
}
|
|
||||||
href := item.CssHref(src, ver)
|
|
||||||
ref := "stylesheet"
|
|
||||||
if v, ok := obj.Extra["alt"]; ok && v != nil {
|
|
||||||
ref = "alternate stylesheet"
|
|
||||||
}
|
|
||||||
title := ""
|
|
||||||
if v, ok := obj.Extra["title"]; ok && v != nil {
|
|
||||||
title = str.Join(" title='", v[len(v)-1], "'")
|
|
||||||
}
|
|
||||||
tag := fmt.Sprintf("<link rel='%s' id='%s-css'%s href='%s'%s media='%s' />\n", ref, handle, title, href, "", item.args)
|
|
||||||
|
|
||||||
if !item.doConcat {
|
|
||||||
PrintStyle(h, condBefore, tag, PrintInlineStyles(handle), condAfter)
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
func (item *__parseLoadItem) CssHref(src, ver string) string {
|
|
||||||
if ver != "" {
|
|
||||||
u, _ := url.Parse(src)
|
|
||||||
v := u.Query()
|
|
||||||
v.Set("ver", ver)
|
|
||||||
u.RawQuery = v.Encode()
|
|
||||||
src = u.String()
|
|
||||||
}
|
|
||||||
return src
|
|
||||||
}
|
|
||||||
|
|
||||||
func (item *__parseLoadItem) PrintInline(handle string) string {
|
|
||||||
sty, _ := __styles.Load(handle)
|
|
||||||
out := sty.getData("after")
|
|
||||||
if out == "" {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
s := str.NewBuilder()
|
|
||||||
s.Sprintf("<style id='%s-inline-css'%s>\n%s\n</style>\n", handle)
|
|
||||||
return s.String()
|
|
||||||
}
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
|
@ -3,18 +3,18 @@ package wp
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/elliotchance/phpserialize"
|
"github.com/elliotchance/phpserialize"
|
||||||
"github.com/fthvgb1/wp-go/app/cmd/reload"
|
|
||||||
"github.com/fthvgb1/wp-go/app/pkg/cache"
|
"github.com/fthvgb1/wp-go/app/pkg/cache"
|
||||||
"github.com/fthvgb1/wp-go/app/pkg/logs"
|
"github.com/fthvgb1/wp-go/app/pkg/logs"
|
||||||
"github.com/fthvgb1/wp-go/app/pkg/models"
|
"github.com/fthvgb1/wp-go/app/pkg/models"
|
||||||
"github.com/fthvgb1/wp-go/app/wpconfig"
|
"github.com/fthvgb1/wp-go/app/wpconfig"
|
||||||
"github.com/fthvgb1/wp-go/helper/maps"
|
"github.com/fthvgb1/wp-go/cache/reload"
|
||||||
"github.com/fthvgb1/wp-go/helper/slice"
|
"github.com/fthvgb1/wp-go/helper/slice"
|
||||||
str "github.com/fthvgb1/wp-go/helper/strings"
|
str "github.com/fthvgb1/wp-go/helper/strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (h *Handle) StickPosts() []models.Posts {
|
var GetStickPosts = reload.BuildValFnWithConfirm("stickPostsSlice", ParseStickPosts)
|
||||||
return reload.GetAnyValBys("stickPostsSlice", h, func(h *Handle) (r []models.Posts) {
|
|
||||||
|
func ParseStickPosts(h *Handle) (r []models.Posts, ok bool) {
|
||||||
v := wpconfig.GetOption("sticky_posts")
|
v := wpconfig.GetOption("sticky_posts")
|
||||||
if v == "" {
|
if v == "" {
|
||||||
return
|
return
|
||||||
|
@ -30,18 +30,19 @@ func (h *Handle) StickPosts() []models.Posts {
|
||||||
post.IsSticky = true
|
post.IsSticky = true
|
||||||
return post, err == nil
|
return post, err == nil
|
||||||
})
|
})
|
||||||
|
ok = true
|
||||||
return
|
return
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *Handle) StickMapPosts() map[uint64]models.Posts {
|
var GetStickMapPosts = reload.BuildValFn("stickPostsMap", StickMapPosts)
|
||||||
return reload.GetAnyValBys("stickPostsMap", h, func(h *Handle) map[uint64]models.Posts {
|
|
||||||
return slice.SimpleToMap(h.StickPosts(), func(v models.Posts) uint64 {
|
func StickMapPosts(h *Handle) map[uint64]models.Posts {
|
||||||
|
return slice.SimpleToMap(GetStickPosts(h), func(v models.Posts) uint64 {
|
||||||
return v.Id
|
return v.Id
|
||||||
})
|
})
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *Handle) IsStick(id uint64) bool {
|
func (h *Handle) IsStick(id uint64) bool {
|
||||||
return maps.IsExists(h.StickMapPosts(), id)
|
_, ok := GetStickMapPosts(h)[id]
|
||||||
|
return ok
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
{{define "common/head"}}
|
{{define "common/head"}}
|
||||||
|
|
||||||
{{if .headScript}}
|
{{ callFuncString .calComponent "headScript"}}
|
||||||
{{.headScript|unescaped}}
|
|
||||||
{{end}}
|
|
||||||
|
|
||||||
{{if .externHead}}
|
{{if .externHead}}
|
||||||
{{.externHead|unescaped}}
|
{{.externHead|unescaped}}
|
||||||
|
@ -10,9 +8,7 @@
|
||||||
{{end}}
|
{{end}}
|
||||||
|
|
||||||
{{define "common/footer"}}
|
{{define "common/footer"}}
|
||||||
{{if .footerScript}}
|
{{ callFuncString .calComponent "footerScript"}}
|
||||||
{{.footerScript|unescaped}}
|
|
||||||
{{end}}
|
|
||||||
{{if .externFooter}}
|
{{if .externFooter}}
|
||||||
{{.externFooter|unescaped}}
|
{{.externFooter|unescaped}}
|
||||||
{{end}}
|
{{end}}
|
||||||
|
@ -20,7 +16,17 @@
|
||||||
|
|
||||||
|
|
||||||
{{define "common/sidebarWidget"}}
|
{{define "common/sidebarWidget"}}
|
||||||
{{if .sidebarsWidgets}}
|
{{ callFuncString .calComponent "sidebarsWidgets"}}
|
||||||
{{.sidebarsWidgets|unescaped}}
|
{{end}}
|
||||||
|
|
||||||
|
{{define "common/colophon"}}
|
||||||
|
{{if .colophon}}
|
||||||
|
{{.colophon|unescaped}}
|
||||||
|
{{else}}
|
||||||
|
<footer id="colophon" class="site-footer">
|
||||||
|
<div class="site-info">
|
||||||
|
<a href="https://github.com/fthvgb1/wp-go" class="imprint">自豪地采用 wp-go</a>
|
||||||
|
</div>
|
||||||
|
</footer>
|
||||||
{{end}}
|
{{end}}
|
||||||
{{end}}
|
{{end}}
|
|
@ -2,14 +2,15 @@ package wp
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"github.com/fthvgb1/wp-go/app/cmd/reload"
|
|
||||||
"github.com/fthvgb1/wp-go/app/pkg/config"
|
"github.com/fthvgb1/wp-go/app/pkg/config"
|
||||||
"github.com/fthvgb1/wp-go/app/pkg/constraints"
|
"github.com/fthvgb1/wp-go/app/pkg/constraints"
|
||||||
"github.com/fthvgb1/wp-go/app/pkg/logs"
|
"github.com/fthvgb1/wp-go/app/pkg/logs"
|
||||||
"github.com/fthvgb1/wp-go/app/plugins/wphandle/apply"
|
"github.com/fthvgb1/wp-go/app/plugins/wphandle/apply"
|
||||||
"github.com/fthvgb1/wp-go/app/wpconfig"
|
"github.com/fthvgb1/wp-go/app/wpconfig"
|
||||||
|
"github.com/fthvgb1/wp-go/cache/reload"
|
||||||
"github.com/fthvgb1/wp-go/helper/maps"
|
"github.com/fthvgb1/wp-go/helper/maps"
|
||||||
str "github.com/fthvgb1/wp-go/helper/strings"
|
str "github.com/fthvgb1/wp-go/helper/strings"
|
||||||
|
"github.com/fthvgb1/wp-go/safety"
|
||||||
"github.com/gin-contrib/sessions"
|
"github.com/gin-contrib/sessions"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"html/template"
|
"html/template"
|
||||||
|
@ -19,10 +20,9 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type Handle struct {
|
type Handle struct {
|
||||||
Index *IndexHandle
|
|
||||||
Detail *DetailHandle
|
|
||||||
C *gin.Context
|
C *gin.Context
|
||||||
theme string
|
theme string
|
||||||
|
isInited bool
|
||||||
Session sessions.Session
|
Session sessions.Session
|
||||||
ginH gin.H
|
ginH gin.H
|
||||||
password string
|
password string
|
||||||
|
@ -30,19 +30,16 @@ type Handle struct {
|
||||||
Code int
|
Code int
|
||||||
Stats string
|
Stats string
|
||||||
templ string
|
templ string
|
||||||
components map[string]map[string][]Components[string]
|
|
||||||
componentHook map[string][]func(Components[string]) (Components[string], bool)
|
|
||||||
themeMods wpconfig.ThemeMods
|
themeMods wpconfig.ThemeMods
|
||||||
handlers map[string]map[string][]HandleCall
|
|
||||||
handleHook map[string][]func(HandleCall) (HandleCall, bool)
|
|
||||||
err error
|
err error
|
||||||
|
errLevel int8
|
||||||
abort bool
|
abort bool
|
||||||
stopPipe bool
|
stopPipe bool
|
||||||
componentsArgs map[string]any
|
|
||||||
componentFilterFn map[string][]func(*Handle, string, ...any) string
|
|
||||||
template *template.Template
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var handlerss = safety.NewMap[string, map[string][]HandleCall]()
|
||||||
|
var handleHooks = safety.NewMap[string, map[string][]func(HandleCall) (HandleCall, bool)]()
|
||||||
|
|
||||||
func (h *Handle) Theme() string {
|
func (h *Handle) Theme() string {
|
||||||
return h.theme
|
return h.theme
|
||||||
}
|
}
|
||||||
|
@ -55,28 +52,20 @@ func (h *Handle) SetScene(scene string) {
|
||||||
h.scene = scene
|
h.scene = scene
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *Handle) Components() map[string]map[string][]Components[string] {
|
func (h *Handle) Components() *safety.Map[string, map[string][]Components[string]] {
|
||||||
return h.components
|
return handleComponents
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *Handle) ComponentHook() map[string][]func(Components[string]) (Components[string], bool) {
|
func (h *Handle) ComponentHook() *safety.Map[string, map[string][]func(Components[string]) (Components[string], bool)] {
|
||||||
return h.componentHook
|
return handleComponentHook
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *Handle) Handlers() map[string]map[string][]HandleCall {
|
func (h *Handle) Handlers() *safety.Map[string, map[string][]HandleCall] {
|
||||||
return h.handlers
|
return handlerss
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *Handle) HandleHook() map[string][]func(HandleCall) (HandleCall, bool) {
|
func (h *Handle) HandleHook() *safety.Map[string, map[string][]func(HandleCall) (HandleCall, bool)] {
|
||||||
return h.handleHook
|
return handleHooks
|
||||||
}
|
|
||||||
|
|
||||||
func (h *Handle) SetTemplate(template *template.Template) {
|
|
||||||
h.template = template
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *Handle) Template() *template.Template {
|
|
||||||
return h.template
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type HandlePlugins map[string]HandleFn[*Handle]
|
type HandlePlugins map[string]HandleFn[*Handle]
|
||||||
|
@ -98,44 +87,50 @@ type HandleCall struct {
|
||||||
Name string
|
Name string
|
||||||
}
|
}
|
||||||
|
|
||||||
func InitHandle(fn func(*Handle), h *Handle) {
|
var isFirstRequest = true
|
||||||
var inited = false
|
|
||||||
hh := reload.GetAnyValBys("themeArgAndConfig", h, func(h *Handle) Handle {
|
func SetConfigHandle(a ...any) Handle {
|
||||||
h.components = make(map[string]map[string][]Components[string])
|
configFn := a[0].(func(*Handle))
|
||||||
h.componentsArgs = make(map[string]any)
|
hh := a[1].(*Handle)
|
||||||
h.componentFilterFn = make(map[string][]func(*Handle, string, ...any) string)
|
h := &Handle{}
|
||||||
h.handlers = make(map[string]map[string][]HandleCall)
|
handleComponents.Flush()
|
||||||
h.handleHook = make(map[string][]func(HandleCall) (HandleCall, bool))
|
componentsArgs.Flush()
|
||||||
|
handleComponentHook.Flush()
|
||||||
|
componentFilterFns.Flush()
|
||||||
|
handlerss.Flush()
|
||||||
|
handleHooks.Flush()
|
||||||
h.ginH = gin.H{}
|
h.ginH = gin.H{}
|
||||||
fnMap = map[string]map[string]any{}
|
fnMap.Flush()
|
||||||
fnHook = map[string]map[string]any{}
|
fnHook.Flush()
|
||||||
fn(h)
|
if isFirstRequest {
|
||||||
v := apply.UsePlugins()
|
isFirstRequest = false
|
||||||
|
} else {
|
||||||
|
reload.Reload()
|
||||||
|
}
|
||||||
|
h.C = hh.C
|
||||||
|
h.theme = hh.theme
|
||||||
|
configFn(h)
|
||||||
|
v := apply.GetPlugins()
|
||||||
pluginFn, ok := v.(func(*Handle))
|
pluginFn, ok := v.(func(*Handle))
|
||||||
if ok {
|
if ok {
|
||||||
pluginFn(h)
|
pluginFn(h)
|
||||||
}
|
}
|
||||||
h.C.Set("inited", true)
|
|
||||||
inited = true
|
|
||||||
return *h
|
return *h
|
||||||
})
|
}
|
||||||
|
|
||||||
|
var GetInitHandleFn = reload.BuildValFnWithAnyParams("themeArgAndConfig", SetConfigHandle, false)
|
||||||
|
|
||||||
|
func InitHandle(configFn func(*Handle), h *Handle) {
|
||||||
|
hh := GetInitHandleFn(configFn, h)
|
||||||
|
mods, err := wpconfig.GetThemeMods(h.theme)
|
||||||
|
logs.IfError(err, "获取mods失败")
|
||||||
|
h.themeMods = mods
|
||||||
h.ginH = maps.Copy(hh.ginH)
|
h.ginH = maps.Copy(hh.ginH)
|
||||||
h.ginH["calPostClass"] = postClass(h)
|
h.ginH["calPostClass"] = postClass(h)
|
||||||
h.ginH["calBodyClass"] = bodyClass(h)
|
h.ginH["calBodyClass"] = bodyClass(h)
|
||||||
h.ginH["customLogo"] = customLogo(h)
|
h.ginH["customLogo"] = customLogo(h)
|
||||||
if inited {
|
h.ginH["calComponent"] = CalComponent(h)
|
||||||
return
|
h.isInited = true
|
||||||
}
|
|
||||||
h.components = hh.components
|
|
||||||
h.Index.postsPlugin = hh.Index.postsPlugin
|
|
||||||
h.Index.pageEle = hh.Index.pageEle
|
|
||||||
h.Detail.CommentRender = hh.Detail.CommentRender
|
|
||||||
h.handlers = hh.handlers
|
|
||||||
h.handleHook = hh.handleHook
|
|
||||||
h.componentHook = hh.componentHook
|
|
||||||
h.componentsArgs = hh.componentsArgs
|
|
||||||
h.componentFilterFn = hh.componentFilterFn
|
|
||||||
h.C.Set("inited", true)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *Handle) Abort() {
|
func (h *Handle) Abort() {
|
||||||
|
@ -157,13 +152,25 @@ func (h *Handle) Err() error {
|
||||||
return h.err
|
return h.err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *Handle) SetErr(err error) {
|
func (h *Handle) SetErr(err error, level int8) {
|
||||||
h.err = errors.Join(err)
|
h.err = errors.Join(err)
|
||||||
|
h.errLevel = level
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Handle) ErrLevel() int8 {
|
||||||
|
return h.errLevel
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Handle) SetErrLevel(errLevel int8) {
|
||||||
|
h.errLevel = errLevel
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *Handle) SetTempl(templ string) {
|
func (h *Handle) SetTempl(templ string) {
|
||||||
h.templ = templ
|
h.templ = templ
|
||||||
}
|
}
|
||||||
|
func (h *Handle) GetTempl() string {
|
||||||
|
return h.templ
|
||||||
|
}
|
||||||
|
|
||||||
func (h *Handle) Scene() string {
|
func (h *Handle) Scene() string {
|
||||||
return h.scene
|
return h.scene
|
||||||
|
@ -177,15 +184,12 @@ func (h *Handle) SetData(k string, v any) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewHandle(c *gin.Context, scene string, theme string) *Handle {
|
func NewHandle(c *gin.Context, scene string, theme string) *Handle {
|
||||||
mods, err := wpconfig.GetThemeMods(theme)
|
|
||||||
logs.IfError(err, "获取mods失败")
|
|
||||||
return &Handle{
|
return &Handle{
|
||||||
C: c,
|
C: c,
|
||||||
theme: theme,
|
theme: theme,
|
||||||
Session: sessions.Default(c),
|
Session: sessions.Default(c),
|
||||||
scene: scene,
|
scene: scene,
|
||||||
Stats: constraints.Ok,
|
Stats: constraints.Ok,
|
||||||
themeMods: mods,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -230,7 +234,12 @@ func (h *Handle) RenderHtml(t *template.Template, statsCode int, name string) {
|
||||||
header["Content-Type"] = htmlContentType
|
header["Content-Type"] = htmlContentType
|
||||||
}
|
}
|
||||||
h.C.Status(statsCode)
|
h.C.Status(statsCode)
|
||||||
err := t.ExecuteTemplate(h.C.Writer, name, h.ginH)
|
var err error
|
||||||
|
if name == "" {
|
||||||
|
err = t.Execute(h.C.Writer, h.ginH)
|
||||||
|
} else {
|
||||||
|
err = t.ExecuteTemplate(h.C.Writer, name, h.ginH)
|
||||||
|
}
|
||||||
h.Abort()
|
h.Abort()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
|
@ -245,8 +254,8 @@ func (h *Handle) PushHandlers(pipeScene string, call HandleCall, statsOrScene ..
|
||||||
|
|
||||||
func (h *Handle) CommonComponents() {
|
func (h *Handle) CommonComponents() {
|
||||||
h.PushCacheGroupHeadScript(constraints.AllScene, "siteIconAndCustomCss", 0, CalSiteIcon, CalCustomCss)
|
h.PushCacheGroupHeadScript(constraints.AllScene, "siteIconAndCustomCss", 0, CalSiteIcon, CalCustomCss)
|
||||||
h.PushRender(constraints.AllStats, NewHandleFn(CalComponents, 10.001, "wp.CalComponents"))
|
|
||||||
h.PushRender(constraints.AllStats, NewHandleFn(PreRenderTemplate, 0, "wp.PreRenderTemplate"))
|
h.PushRender(constraints.AllStats, NewHandleFn(PreRenderTemplate, 0, "wp.PreRenderTemplate"))
|
||||||
|
ReplyCommentJs(h)
|
||||||
AdditionScript(h)
|
AdditionScript(h)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,15 +2,11 @@ package wpconfig
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"github.com/fthvgb1/wp-go/app/cmd/reload"
|
|
||||||
"github.com/fthvgb1/wp-go/app/phphelper"
|
"github.com/fthvgb1/wp-go/app/phphelper"
|
||||||
"github.com/fthvgb1/wp-go/app/pkg/config"
|
|
||||||
"github.com/fthvgb1/wp-go/app/pkg/models"
|
"github.com/fthvgb1/wp-go/app/pkg/models"
|
||||||
"github.com/fthvgb1/wp-go/helper/maps"
|
"github.com/fthvgb1/wp-go/helper/maps"
|
||||||
"github.com/fthvgb1/wp-go/model"
|
"github.com/fthvgb1/wp-go/model"
|
||||||
"github.com/fthvgb1/wp-go/safety"
|
"github.com/fthvgb1/wp-go/safety"
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -35,41 +31,19 @@ func InitOptions() error {
|
||||||
for _, option := range ops {
|
for _, option := range ops {
|
||||||
options.Store(option["k"], option["v"])
|
options.Store(option["k"], option["v"])
|
||||||
}
|
}
|
||||||
themeJson = reload.VarsBy(hasThemeJson)
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var themeJson *safety.Var[bool]
|
|
||||||
|
|
||||||
func HasThemeJson() bool {
|
|
||||||
if themeJson == nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return themeJson.Load()
|
|
||||||
}
|
|
||||||
|
|
||||||
func hasThemeJson() bool {
|
|
||||||
styleSheet := GetOption("stylesheet")
|
|
||||||
rootDir := config.GetConfig().WpDir
|
|
||||||
dir := filepath.Join(rootDir, "wp-content/themes", styleSheet, "theme.json")
|
|
||||||
_, err := os.Stat(dir)
|
|
||||||
if err == nil {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
template := GetOption("template")
|
|
||||||
dir = filepath.Join(rootDir, "wp-content/themes", template, "theme.json")
|
|
||||||
_, err = os.Stat(dir)
|
|
||||||
return err == nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetOption(k string) string {
|
func GetOption(k string) string {
|
||||||
v, ok := options.Load(k)
|
v, ok := options.Load(k)
|
||||||
if ok {
|
if ok {
|
||||||
return v
|
return v
|
||||||
}
|
}
|
||||||
vv, err := model.GetField[models.Options](ctx, "option_value", model.Conditions(
|
vv, err := model.GetField[models.Options](ctx, "option_value",
|
||||||
|
model.Conditions(
|
||||||
model.Where(
|
model.Where(
|
||||||
model.SqlBuilder{{"option_name", k}}),
|
model.SqlBuilder{{"option_name", k}},
|
||||||
|
),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
options.Store(k, vv)
|
options.Store(k, vv)
|
||||||
|
|
|
@ -3,10 +3,10 @@ package wpconfig
|
||||||
import (
|
import (
|
||||||
"embed"
|
"embed"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/fthvgb1/wp-go/app/cmd/reload"
|
|
||||||
"github.com/fthvgb1/wp-go/app/phphelper"
|
"github.com/fthvgb1/wp-go/app/phphelper"
|
||||||
"github.com/fthvgb1/wp-go/app/pkg/logs"
|
"github.com/fthvgb1/wp-go/app/pkg/logs"
|
||||||
"github.com/fthvgb1/wp-go/app/pkg/models"
|
"github.com/fthvgb1/wp-go/app/pkg/models"
|
||||||
|
"github.com/fthvgb1/wp-go/cache/reload"
|
||||||
"github.com/fthvgb1/wp-go/helper/maps"
|
"github.com/fthvgb1/wp-go/helper/maps"
|
||||||
"github.com/fthvgb1/wp-go/safety"
|
"github.com/fthvgb1/wp-go/safety"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
@ -73,6 +73,7 @@ func Thumbnail(metadata models.WpAttachmentMetadata, Type, host string, except .
|
||||||
up := strings.Split(metadata.File, "/")
|
up := strings.Split(metadata.File, "/")
|
||||||
if metadata.File != "" && Type == "full" {
|
if metadata.File != "" && Type == "full" {
|
||||||
mimeType := metadata.Sizes["thumbnail"].MimeType
|
mimeType := metadata.Sizes["thumbnail"].MimeType
|
||||||
|
metadata.Sizes = maps.Copy(metadata.Sizes)
|
||||||
metadata.Sizes["full"] = models.MetaDataFileSize{
|
metadata.Sizes["full"] = models.MetaDataFileSize{
|
||||||
File: filepath.Base(metadata.File),
|
File: filepath.Base(metadata.File),
|
||||||
Width: metadata.Width,
|
Width: metadata.Width,
|
||||||
|
@ -111,10 +112,10 @@ func Thumbnail(metadata models.WpAttachmentMetadata, Type, host string, except .
|
||||||
var themeModes = func() *safety.Map[string, ThemeMods] {
|
var themeModes = func() *safety.Map[string, ThemeMods] {
|
||||||
m := safety.NewMap[string, ThemeMods]()
|
m := safety.NewMap[string, ThemeMods]()
|
||||||
themeModsRaw = safety.NewMap[string, map[string]any]()
|
themeModsRaw = safety.NewMap[string, map[string]any]()
|
||||||
reload.Push(func() {
|
reload.Append(func() {
|
||||||
m.Flush()
|
m.Flush()
|
||||||
themeModsRaw.Flush()
|
themeModsRaw.Flush()
|
||||||
})
|
}, "theme-modes")
|
||||||
|
|
||||||
return m
|
return m
|
||||||
}()
|
}()
|
||||||
|
|
44
cache/cache.go
vendored
44
cache/cache.go
vendored
|
@ -2,15 +2,49 @@ package cache
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Cache[K comparable, V any] interface {
|
type Cache[K comparable, V any] interface {
|
||||||
Get(ctx context.Context, key K) (V, bool)
|
Get(ctx context.Context, key K) (V, bool)
|
||||||
Set(ctx context.Context, key K, val V, expire time.Duration)
|
Set(ctx context.Context, key K, val V)
|
||||||
Ttl(ctx context.Context, key K, expire time.Duration) time.Duration
|
GetExpireTime(ctx context.Context) time.Duration
|
||||||
Ver(ctx context.Context, key K) int
|
Ttl(ctx context.Context, key K) time.Duration
|
||||||
Flush(ctx context.Context)
|
Flush(ctx context.Context)
|
||||||
Delete(ctx context.Context, key K)
|
Del(ctx context.Context, key ...K)
|
||||||
ClearExpired(ctx context.Context, expire time.Duration)
|
ClearExpired(ctx context.Context)
|
||||||
|
}
|
||||||
|
|
||||||
|
type Expend[K comparable, V any] interface {
|
||||||
|
Gets(ctx context.Context, k []K) (map[K]V, error)
|
||||||
|
Sets(ctx context.Context, m map[K]V)
|
||||||
|
}
|
||||||
|
|
||||||
|
type SetTime interface {
|
||||||
|
SetExpiredTime(func() time.Duration)
|
||||||
|
}
|
||||||
|
|
||||||
|
type AnyCache[T any] interface {
|
||||||
|
Get(ctx context.Context) (T, bool)
|
||||||
|
Set(ctx context.Context, v T)
|
||||||
|
Flush(ctx context.Context)
|
||||||
|
GetLastSetTime(ctx context.Context) time.Time
|
||||||
|
}
|
||||||
|
|
||||||
|
type Refresh[K comparable, V any] interface {
|
||||||
|
Refresh(ctx context.Context, k K, a ...any)
|
||||||
|
}
|
||||||
|
type RefreshVar[T any] interface {
|
||||||
|
Refresh(ctx context.Context, a ...any)
|
||||||
|
}
|
||||||
|
|
||||||
|
type Lockss[K comparable] interface {
|
||||||
|
GetLock(ctx context.Context, gMut *sync.Mutex, k ...K) *sync.Mutex
|
||||||
|
}
|
||||||
|
|
||||||
|
type LockFn[K comparable] func(ctx context.Context, gMut *sync.Mutex, k ...K) *sync.Mutex
|
||||||
|
|
||||||
|
type LocksNum interface {
|
||||||
|
SetLockNum(num int)
|
||||||
}
|
}
|
||||||
|
|
163
cache/cachemanager/manger.go
vendored
Normal file
163
cache/cachemanager/manger.go
vendored
Normal file
|
@ -0,0 +1,163 @@
|
||||||
|
package cachemanager
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"github.com/fthvgb1/wp-go/cache"
|
||||||
|
"github.com/fthvgb1/wp-go/cache/reload"
|
||||||
|
"github.com/fthvgb1/wp-go/helper"
|
||||||
|
"github.com/fthvgb1/wp-go/helper/slice/mockmap"
|
||||||
|
str "github.com/fthvgb1/wp-go/helper/strings"
|
||||||
|
"github.com/fthvgb1/wp-go/safety"
|
||||||
|
"runtime"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
var mutex sync.Mutex
|
||||||
|
|
||||||
|
type Fn func(context.Context)
|
||||||
|
|
||||||
|
type clearExpired interface {
|
||||||
|
ClearExpired(ctx context.Context)
|
||||||
|
}
|
||||||
|
|
||||||
|
var clears = safety.NewVar(mockmap.Map[string, Fn]{})
|
||||||
|
|
||||||
|
var flushes = safety.NewVar(mockmap.Map[string, Fn]{})
|
||||||
|
|
||||||
|
func Flush() {
|
||||||
|
ctx := context.WithValue(context.Background(), "execFlushBy", "mangerFlushFn")
|
||||||
|
for _, f := range flushes.Load() {
|
||||||
|
f.Value(ctx)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Flushes(ctx context.Context, names ...string) {
|
||||||
|
execute(ctx, flushes, names...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func execute(ctx context.Context, q *safety.Var[mockmap.Map[string, Fn]], names ...string) {
|
||||||
|
queues := q.Load()
|
||||||
|
for _, name := range names {
|
||||||
|
queue := queues.Get(name)
|
||||||
|
if queue.Value != nil {
|
||||||
|
queue.Value(ctx)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseArgs(args ...any) (string, func() time.Duration) {
|
||||||
|
var name string
|
||||||
|
var fn func() time.Duration
|
||||||
|
for _, arg := range args {
|
||||||
|
v, ok := arg.(string)
|
||||||
|
if ok {
|
||||||
|
name = v
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
vv, ok := arg.(func() time.Duration)
|
||||||
|
if ok {
|
||||||
|
fn = vv
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
return name, fn
|
||||||
|
}
|
||||||
|
|
||||||
|
func buildLockFn[K comparable](args ...any) cache.LockFn[K] {
|
||||||
|
lockFn := helper.ParseArgs(cache.LockFn[K](nil), args...)
|
||||||
|
name := helper.ParseArgs("", args...)
|
||||||
|
num := helper.ParseArgs(runtime.NumCPU(), args...)
|
||||||
|
loFn := func() int {
|
||||||
|
return num
|
||||||
|
}
|
||||||
|
loFn = helper.ParseArgs(loFn, args...)
|
||||||
|
if name != "" {
|
||||||
|
loFn = reload.BuildFnVal(str.Join("cachesLocksNum-", name), num, loFn)
|
||||||
|
}
|
||||||
|
if lockFn == nil {
|
||||||
|
looo := helper.ParseArgs(cache.Lockss[K](nil), args...)
|
||||||
|
if looo != nil {
|
||||||
|
lockFn = looo.GetLock
|
||||||
|
loo, ok := any(looo).(cache.LocksNum)
|
||||||
|
if ok && loo != nil {
|
||||||
|
loo.SetLockNum(num)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
lo := cache.NewLocks[K](loFn)
|
||||||
|
lockFn = lo.GetLock
|
||||||
|
PushOrSetFlush(mockmap.Item[string, Fn]{
|
||||||
|
Name: name,
|
||||||
|
Value: lo.Flush,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
return lockFn
|
||||||
|
}
|
||||||
|
|
||||||
|
func SetExpireTime(c cache.SetTime, name string, expireTime time.Duration, expireTimeFn func() time.Duration) {
|
||||||
|
if name == "" {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
fn := reload.BuildFnVal(str.Join("cacheManger-", name, "-expiredTime"), expireTime, expireTimeFn)
|
||||||
|
c.SetExpiredTime(fn)
|
||||||
|
}
|
||||||
|
|
||||||
|
func ChangeExpireTime(t time.Duration, coverConf bool, name ...string) {
|
||||||
|
for _, s := range name {
|
||||||
|
reload.SetFnVal(s, t, coverConf)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func pushOrSet(q *safety.Var[mockmap.Map[string, Fn]], queues ...mockmap.Item[string, Fn]) {
|
||||||
|
mutex.Lock()
|
||||||
|
defer mutex.Unlock()
|
||||||
|
qu := q.Load()
|
||||||
|
for _, queue := range queues {
|
||||||
|
v := qu.Get(queue.Name)
|
||||||
|
if v.Value != nil {
|
||||||
|
qu.Set(queue.Name, queue.Value)
|
||||||
|
} else {
|
||||||
|
qu = append(qu, queue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
q.Store(qu)
|
||||||
|
}
|
||||||
|
|
||||||
|
// PushOrSetFlush will execute flush func when call Flush or Flushes
|
||||||
|
func PushOrSetFlush(queues ...mockmap.Item[string, Fn]) {
|
||||||
|
pushOrSet(flushes, queues...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// PushOrSetClearExpired will execute clearExpired func when call ClearExpired or ClearExpireds
|
||||||
|
func PushOrSetClearExpired(queues ...mockmap.Item[string, Fn]) {
|
||||||
|
pushOrSet(clears, queues...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func del(q *safety.Var[mockmap.Map[string, Fn]], names ...string) {
|
||||||
|
mutex.Lock()
|
||||||
|
defer mutex.Unlock()
|
||||||
|
queues := q.Load()
|
||||||
|
for _, name := range names {
|
||||||
|
queues.Del(name)
|
||||||
|
}
|
||||||
|
q.Store(queues)
|
||||||
|
}
|
||||||
|
func DelFlush(names ...string) {
|
||||||
|
del(flushes, names...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func DelClearExpired(names ...string) {
|
||||||
|
del(clears, names...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func ClearExpireds(ctx context.Context, names ...string) {
|
||||||
|
execute(ctx, clears, names...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func ClearExpired() {
|
||||||
|
ctx := context.WithValue(context.Background(), "execClearExpired", "mangerClearExpiredFn")
|
||||||
|
for _, queue := range clears.Load() {
|
||||||
|
queue.Value(ctx)
|
||||||
|
}
|
||||||
|
}
|
193
cache/cachemanager/manger_test.go
vendored
Normal file
193
cache/cachemanager/manger_test.go
vendored
Normal file
|
@ -0,0 +1,193 @@
|
||||||
|
package cachemanager
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"github.com/fthvgb1/wp-go/helper/number"
|
||||||
|
"github.com/fthvgb1/wp-go/helper/slice"
|
||||||
|
str "github.com/fthvgb1/wp-go/helper/strings"
|
||||||
|
"github.com/fthvgb1/wp-go/taskPools"
|
||||||
|
"reflect"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
var ctx = context.Background()
|
||||||
|
|
||||||
|
func TestFlushMapVal(t *testing.T) {
|
||||||
|
_ = number.Range(1, 5, 0)
|
||||||
|
t.Run("t1", func(t *testing.T) {
|
||||||
|
count := 0
|
||||||
|
vv := NewMemoryMapCache(func(ctx2 context.Context, ks []int, a ...any) (map[int]int, error) {
|
||||||
|
r := make(map[int]int)
|
||||||
|
for _, k := range ks {
|
||||||
|
r[k] = k * k
|
||||||
|
}
|
||||||
|
count++
|
||||||
|
return r, nil
|
||||||
|
}, nil, time.Second, "test")
|
||||||
|
|
||||||
|
gets, err := GetBatchBy[int]("test", ctx, number.Range(1, 10), time.Second)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(t, "err:", err)
|
||||||
|
}
|
||||||
|
p := taskPools.NewPools(10)
|
||||||
|
for i := 0; i < 20; i++ {
|
||||||
|
i := i
|
||||||
|
p.Execute(func() {
|
||||||
|
if i%2 == 0 {
|
||||||
|
vv.Get(ctx, 5)
|
||||||
|
} else {
|
||||||
|
vv.Set(ctx, i, i)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
p.Wait()
|
||||||
|
fmt.Println(gets, count)
|
||||||
|
DelMapCacheVal("test", 3, 4)
|
||||||
|
fmt.Println(vv.Get(ctx, 3))
|
||||||
|
fmt.Println(vv.Get(ctx, 4))
|
||||||
|
get, err := GetBy[int]("test", ctx, 3, time.Second)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(t, "err", err)
|
||||||
|
}
|
||||||
|
fmt.Println(get, count)
|
||||||
|
fmt.Println(vv.Get(ctx, 5))
|
||||||
|
Flushes(ctx, "test")
|
||||||
|
fmt.Println(vv.Get(ctx, 5))
|
||||||
|
fmt.Println(vv.Get(ctx, 6))
|
||||||
|
//fmt.Println(GetVarCache("test"))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSetExpireTime(t *testing.T) {
|
||||||
|
t.Run("t1", func(t *testing.T) {
|
||||||
|
c := NewMemoryMapCache[string, string](func(ctx2 context.Context, strings []string, a ...any) (map[string]string, error) {
|
||||||
|
return slice.ToMap(strings, func(v string) (string, string) {
|
||||||
|
return v, str.Join(v, "__", v)
|
||||||
|
}, false), nil
|
||||||
|
}, nil, time.Second, "xx")
|
||||||
|
c.Set(ctx, "xx", "yy")
|
||||||
|
fmt.Println(c.Get(ctx, "xx"))
|
||||||
|
time.Sleep(time.Second)
|
||||||
|
fmt.Println(c.Get(ctx, "xx"))
|
||||||
|
ChangeExpireTime(3*time.Second, true, "xx")
|
||||||
|
c.Set(ctx, "xx", "yyy")
|
||||||
|
time.Sleep(time.Second)
|
||||||
|
fmt.Println(c.Get(ctx, "xx"))
|
||||||
|
time.Sleep(3 * time.Second)
|
||||||
|
fmt.Println(c.Get(ctx, "xx"))
|
||||||
|
cc, _ := GetMapCache[string, string]("xx")
|
||||||
|
fmt.Println(reflect.DeepEqual(c, cc))
|
||||||
|
cc.Set(ctx, "fff", "xxxx")
|
||||||
|
cc.Set(ctx, "ffx", "eex")
|
||||||
|
cc.Set(ctx, "ww", "vv")
|
||||||
|
m, err := cc.GetBatchToMap(ctx, []string{"fff", "ffx", "ww", "kkkk"}, time.Second)
|
||||||
|
fmt.Println(m, err)
|
||||||
|
fmt.Println(GetBatchByToMap[string]("xx", ctx, []string{"fff", "ffx", "ww", "kkkk"}, time.Second))
|
||||||
|
v := NewVarMemoryCache(func(ct context.Context, a ...any) (string, error) {
|
||||||
|
return "ssss", nil
|
||||||
|
}, 3*time.Second, "ff")
|
||||||
|
vv, _ := GetVarCache[string]("ff")
|
||||||
|
fmt.Println(reflect.DeepEqual(v, vv))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSetMapCache(t *testing.T) {
|
||||||
|
t.Run("t1", func(t *testing.T) {
|
||||||
|
x := NewMemoryMapCache(nil, func(ctx2 context.Context, k string, a ...any) (string, error) {
|
||||||
|
fmt.Println("memory cache")
|
||||||
|
return strings.Repeat(k, 2), nil
|
||||||
|
}, time.Hour, "test")
|
||||||
|
fmt.Println(GetBy[string]("test", ctx, "test", time.Second))
|
||||||
|
|
||||||
|
NewMapCache[string, string](xx[string, string]{m: map[string]string{}}, nil, func(ctx2 context.Context, k string, a ...any) (string, error) {
|
||||||
|
fmt.Println("other cache drives. eg: redis,file.....")
|
||||||
|
return strings.Repeat(k, 2), nil
|
||||||
|
}, "test", time.Hour)
|
||||||
|
|
||||||
|
if err := SetMapCache("kkk", x); err != nil {
|
||||||
|
t.Errorf("SetMapCache() error = %v, wantErr %v", err, nil)
|
||||||
|
}
|
||||||
|
fmt.Println(GetBy[string]("test", ctx, "test", time.Second))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
type xx[K comparable, V any] struct {
|
||||||
|
m map[K]V
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x xx[K, V]) Get(ctx context.Context, key K) (V, bool) {
|
||||||
|
v, ok := x.m[key]
|
||||||
|
return v, ok
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x xx[K, V]) Set(ctx context.Context, key K, val V) {
|
||||||
|
x.m[key] = val
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x xx[K, V]) GetExpireTime(ctx context.Context) time.Duration {
|
||||||
|
//TODO implement me
|
||||||
|
panic("implement me")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x xx[K, V]) Ttl(ctx context.Context, key K) time.Duration {
|
||||||
|
//TODO implement me
|
||||||
|
panic("implement me")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x xx[K, V]) Flush(ctx context.Context) {
|
||||||
|
//TODO implement me
|
||||||
|
panic("implement me")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x xx[K, V]) Del(ctx context.Context, key ...K) {
|
||||||
|
//TODO implement me
|
||||||
|
panic("implement me")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x xx[K, V]) ClearExpired(ctx context.Context) {
|
||||||
|
//TODO implement me
|
||||||
|
panic("implement me")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSetVarCache(t *testing.T) {
|
||||||
|
t.Run("t1", func(t *testing.T) {
|
||||||
|
bak := NewVarMemoryCache(func(ctx2 context.Context, a ...any) (string, error) {
|
||||||
|
fmt.Println("memory cache")
|
||||||
|
return "xxx", nil
|
||||||
|
}, time.Hour, "test")
|
||||||
|
fmt.Println(GetVarVal[string]("test", ctx, time.Second))
|
||||||
|
NewVarCache[string](oo[string]{}, func(ctx2 context.Context, a ...any) (string, error) {
|
||||||
|
fmt.Println("other cache drives. eg: redis,file.....")
|
||||||
|
return "ooo", nil
|
||||||
|
}, "test")
|
||||||
|
if err := SetVarCache("xx", bak); err != nil {
|
||||||
|
t.Errorf("SetVarCache() error = %v, wantErr %v", err, nil)
|
||||||
|
}
|
||||||
|
fmt.Println(GetVarVal[string]("test", ctx, time.Second))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
type oo[T any] struct {
|
||||||
|
val T
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o oo[T]) Get(ctx context.Context) (T, bool) {
|
||||||
|
return o.val, false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o oo[T]) Set(ctx context.Context, v T) {
|
||||||
|
o.val = v
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o oo[T]) Flush(ctx context.Context) {
|
||||||
|
//TODO implement me
|
||||||
|
panic("implement me")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o oo[T]) GetLastSetTime(ctx context.Context) time.Time {
|
||||||
|
//TODO implement me
|
||||||
|
panic("implement me")
|
||||||
|
}
|
148
cache/cachemanager/mapcache.go
vendored
Normal file
148
cache/cachemanager/mapcache.go
vendored
Normal file
|
@ -0,0 +1,148 @@
|
||||||
|
package cachemanager
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"errors"
|
||||||
|
"github.com/fthvgb1/wp-go/cache"
|
||||||
|
"github.com/fthvgb1/wp-go/helper"
|
||||||
|
"github.com/fthvgb1/wp-go/helper/slice/mockmap"
|
||||||
|
str "github.com/fthvgb1/wp-go/helper/strings"
|
||||||
|
"github.com/fthvgb1/wp-go/safety"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
var mapDelFuncs = safety.NewMap[string, func(any)]()
|
||||||
|
|
||||||
|
var mapCache = safety.NewMap[string, any]()
|
||||||
|
|
||||||
|
func SetMapCache[K comparable, V any](name string, ca *cache.MapCache[K, V]) error {
|
||||||
|
v, ok := mapCache.Load(name)
|
||||||
|
if !ok {
|
||||||
|
mapCache.Store(name, ca)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
_, ok = v.(*cache.MapCache[K, V])
|
||||||
|
if !ok {
|
||||||
|
return errors.New(str.Join("cache ", name, " type err"))
|
||||||
|
}
|
||||||
|
mapCache.Store(name, ca)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// PushMangerMap will del mapCache val with name When call DelMapCacheVal
|
||||||
|
func PushMangerMap[K comparable, V any](name string, m *cache.MapCache[K, V]) {
|
||||||
|
if name == "" {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
mapCache.Store(name, m)
|
||||||
|
mapDelFuncs.Store(name, func(a any) {
|
||||||
|
k, ok := a.([]K)
|
||||||
|
if ok && len(k) > 0 {
|
||||||
|
mm, ok := mapCache.Load(name)
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
c, ok := mm.(*cache.MapCache[K, V])
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
ctx := context.WithValue(context.Background(), "ctx", "registerFlush")
|
||||||
|
c.Del(ctx, k...)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetBy[T any, K comparable](name string, ct context.Context, key K, timeout time.Duration, params ...any) (r T, err error) {
|
||||||
|
ct = context.WithValue(ct, "getCache", name)
|
||||||
|
ca, err := getMap[K, T](name)
|
||||||
|
if err != nil {
|
||||||
|
return r, err
|
||||||
|
}
|
||||||
|
vv, err := ca.GetCache(ct, key, timeout, params...)
|
||||||
|
if err != nil {
|
||||||
|
return r, err
|
||||||
|
}
|
||||||
|
r = vv
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func getMap[K comparable, T any](name string) (*cache.MapCache[K, T], error) {
|
||||||
|
m, ok := mapCache.Load(name)
|
||||||
|
if !ok {
|
||||||
|
return nil, errors.New(str.Join("cache ", name, " doesn't exist"))
|
||||||
|
}
|
||||||
|
vk, ok := m.(*cache.MapCache[K, T])
|
||||||
|
if !ok {
|
||||||
|
return nil, errors.New(str.Join("cache ", name, " type error"))
|
||||||
|
}
|
||||||
|
return vk, nil
|
||||||
|
}
|
||||||
|
func GetBatchBy[T any, K comparable](name string, ct context.Context, key []K, timeout time.Duration, params ...any) (r []T, err error) {
|
||||||
|
ct = context.WithValue(ct, "getCache", name)
|
||||||
|
ca, err := getMap[K, T](name)
|
||||||
|
if err != nil {
|
||||||
|
return r, err
|
||||||
|
}
|
||||||
|
vv, err := ca.GetCacheBatch(ct, key, timeout, params...)
|
||||||
|
if err != nil {
|
||||||
|
return r, err
|
||||||
|
}
|
||||||
|
r = vv
|
||||||
|
return
|
||||||
|
}
|
||||||
|
func GetBatchByToMap[T any, K comparable](name string, ct context.Context, key []K, timeout time.Duration, params ...any) (r map[K]T, err error) {
|
||||||
|
ct = context.WithValue(ct, "getCache", name)
|
||||||
|
ca, err := getMap[K, T](name)
|
||||||
|
if err != nil {
|
||||||
|
return r, err
|
||||||
|
}
|
||||||
|
vv, err := ca.GetBatchToMap(ct, key, timeout, params...)
|
||||||
|
if err != nil {
|
||||||
|
return r, err
|
||||||
|
}
|
||||||
|
r = vv
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewMapCache[K comparable, V any](data cache.Cache[K, V], batchFn cache.MapBatchFn[K, V], fn cache.MapSingleFn[K, V], args ...any) *cache.MapCache[K, V] {
|
||||||
|
inc := helper.ParseArgs((*cache.IncreaseUpdate[K, V])(nil), args...)
|
||||||
|
m := cache.NewMapCache[K, V](data, fn, batchFn, inc, buildLockFn[K](args...), args...)
|
||||||
|
name, f := parseArgs(args...)
|
||||||
|
if name != "" {
|
||||||
|
PushMangerMap(name, m)
|
||||||
|
}
|
||||||
|
PushOrSetFlush(mockmap.Item[string, Fn]{
|
||||||
|
Name: name,
|
||||||
|
Value: m.Flush,
|
||||||
|
})
|
||||||
|
PushOrSetClearExpired(mockmap.Item[string, Fn]{
|
||||||
|
Name: name,
|
||||||
|
Value: m.ClearExpired,
|
||||||
|
})
|
||||||
|
if f != nil && name != "" {
|
||||||
|
SetExpireTime(any(data).(cache.SetTime), name, 0, f)
|
||||||
|
}
|
||||||
|
return m
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewMemoryMapCache[K comparable, V any](batchFn cache.MapBatchFn[K, V],
|
||||||
|
fn cache.MapSingleFn[K, V], expireTime time.Duration, args ...any) *cache.MapCache[K, V] {
|
||||||
|
|
||||||
|
c := NewMapCache[K, V](cache.NewMemoryMapCache[K, V](func() time.Duration {
|
||||||
|
return expireTime
|
||||||
|
}), batchFn, fn, args...)
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetMapCache[K comparable, V any](name string) (*cache.MapCache[K, V], bool) {
|
||||||
|
vv, err := getMap[K, V](name)
|
||||||
|
return vv, err == nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func DelMapCacheVal[T any](name string, keys ...T) {
|
||||||
|
v, ok := mapDelFuncs.Load(name)
|
||||||
|
if !ok || len(keys) < 1 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
v(keys)
|
||||||
|
}
|
57
cache/cachemanager/pagination.go
vendored
Normal file
57
cache/cachemanager/pagination.go
vendored
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
package cachemanager
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"errors"
|
||||||
|
"github.com/fthvgb1/wp-go/cache"
|
||||||
|
"github.com/fthvgb1/wp-go/cache/reload"
|
||||||
|
"github.com/fthvgb1/wp-go/helper"
|
||||||
|
str "github.com/fthvgb1/wp-go/helper/strings"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func NewPaginationCache[K comparable, V any](m *cache.MapCache[string, helper.PaginationData[V]], maxNum int,
|
||||||
|
dbFn cache.DbFn[K, V], localFn cache.LocalFn[K, V], dbKeyFn, localKeyFn func(K, ...any) string, fetchNum int, name string, a ...any) *cache.Pagination[K, V] {
|
||||||
|
fn := helper.ParseArgs([]func() int(nil), a...)
|
||||||
|
var ma, fet func() int
|
||||||
|
if len(fn) > 0 {
|
||||||
|
ma = fn[0]
|
||||||
|
if len(fn) > 1 {
|
||||||
|
fet = fn[1]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ma == nil {
|
||||||
|
ma = reload.BuildFnVal(str.Join("paginationCache-", name, "-maxNum"), maxNum, nil)
|
||||||
|
}
|
||||||
|
if fet == nil {
|
||||||
|
fet = reload.BuildFnVal(str.Join("paginationCache-", name, "-fetchNum"), fetchNum, nil)
|
||||||
|
}
|
||||||
|
p := cache.NewPagination(m, ma, dbFn, localFn, dbKeyFn, localKeyFn, fet, name)
|
||||||
|
mapCache.Store(name, p)
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetPaginationCache[K comparable, V any](name string) (*cache.Pagination[K, V], bool) {
|
||||||
|
v, err := getPagination[K, V](name)
|
||||||
|
return v, err == nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func Pagination[V any, K comparable](name string, ctx context.Context, timeout time.Duration, k K, page, limit int, a ...any) ([]V, int, error) {
|
||||||
|
v, err := getPagination[K, V](name)
|
||||||
|
if err != nil {
|
||||||
|
return nil, 0, err
|
||||||
|
}
|
||||||
|
return v.Pagination(ctx, timeout, k, page, limit, a...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func getPagination[K comparable, T any](name string) (*cache.Pagination[K, T], error) {
|
||||||
|
m, ok := mapCache.Load(name)
|
||||||
|
if !ok {
|
||||||
|
return nil, errors.New(str.Join("cache ", name, " doesn't exist"))
|
||||||
|
}
|
||||||
|
vk, ok := m.(*cache.Pagination[K, T])
|
||||||
|
if !ok {
|
||||||
|
return nil, errors.New(str.Join("cache ", name, " type error"))
|
||||||
|
}
|
||||||
|
return vk, nil
|
||||||
|
}
|
83
cache/cachemanager/varcache.go
vendored
Normal file
83
cache/cachemanager/varcache.go
vendored
Normal file
|
@ -0,0 +1,83 @@
|
||||||
|
package cachemanager
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"errors"
|
||||||
|
"github.com/fthvgb1/wp-go/cache"
|
||||||
|
"github.com/fthvgb1/wp-go/helper"
|
||||||
|
"github.com/fthvgb1/wp-go/helper/slice/mockmap"
|
||||||
|
str "github.com/fthvgb1/wp-go/helper/strings"
|
||||||
|
"github.com/fthvgb1/wp-go/safety"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
var varCache = safety.NewMap[string, any]()
|
||||||
|
|
||||||
|
func SetVarCache[T any](name string, v *cache.VarCache[T]) error {
|
||||||
|
vv, ok := varCache.Load(name)
|
||||||
|
if !ok {
|
||||||
|
varCache.Store(name, v)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
_, ok = vv.(*cache.VarCache[T])
|
||||||
|
if ok {
|
||||||
|
varCache.Store(name, v)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return errors.New(str.Join("cache ", name, " type err"))
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewVarCache[T any](c cache.AnyCache[T], fn func(context.Context, ...any) (T, error), a ...any) *cache.VarCache[T] {
|
||||||
|
inc := helper.ParseArgs((*cache.IncreaseUpdateVar[T])(nil), a...)
|
||||||
|
ref := helper.ParseArgs(cache.RefreshVar[T](nil), a...)
|
||||||
|
v := cache.NewVarCache(c, fn, inc, ref, a...)
|
||||||
|
|
||||||
|
name, _ := parseArgs(a...)
|
||||||
|
if name != "" {
|
||||||
|
varCache.Store(name, v)
|
||||||
|
}
|
||||||
|
PushOrSetFlush(mockmap.Item[string, Fn]{
|
||||||
|
Name: name,
|
||||||
|
Value: v.Flush,
|
||||||
|
})
|
||||||
|
cc, ok := any(c).(clearExpired)
|
||||||
|
if ok {
|
||||||
|
PushOrSetClearExpired(mockmap.Item[string, Fn]{
|
||||||
|
Name: name,
|
||||||
|
Value: cc.ClearExpired,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetVarVal[T any](name string, ctx context.Context, duration time.Duration, a ...any) (r T, err error) {
|
||||||
|
ctx = context.WithValue(ctx, "getCache", name)
|
||||||
|
ca, ok := GetVarCache[T](name)
|
||||||
|
if !ok {
|
||||||
|
err = errors.New(str.Join("cache ", name, " is not exist"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
v, err := ca.GetCache(ctx, duration, a...)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
r = v
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewVarMemoryCache[T any](fn func(context.Context, ...any) (T, error), expired time.Duration, a ...any) *cache.VarCache[T] {
|
||||||
|
c := cache.NewVarMemoryCache[T](nil)
|
||||||
|
name, e := parseArgs(a...)
|
||||||
|
SetExpireTime(c, name, expired, e)
|
||||||
|
v := NewVarCache[T](c, fn, a...)
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetVarCache[T any](name string) (*cache.VarCache[T], bool) {
|
||||||
|
v, ok := varCache.Load(name)
|
||||||
|
if !ok {
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
vv, ok := v.(*cache.VarCache[T])
|
||||||
|
return vv, ok
|
||||||
|
}
|
78
cache/locks.go
vendored
Normal file
78
cache/locks.go
vendored
Normal file
|
@ -0,0 +1,78 @@
|
||||||
|
package cache
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"github.com/fthvgb1/wp-go/safety"
|
||||||
|
"sync"
|
||||||
|
"sync/atomic"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Locks[K comparable] struct {
|
||||||
|
numFn func() int
|
||||||
|
locks []*sync.Mutex
|
||||||
|
m *safety.Map[K, *sync.Mutex]
|
||||||
|
counter *int64
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *Locks[K]) Flush(_ context.Context) {
|
||||||
|
l.m.Flush()
|
||||||
|
atomic.StoreInt64(l.counter, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *Locks[K]) SetNumFn(numFn func() int) {
|
||||||
|
l.numFn = numFn
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewLocks[K comparable](num func() int) *Locks[K] {
|
||||||
|
var i int64
|
||||||
|
return &Locks[K]{numFn: num, m: safety.NewMap[K, *sync.Mutex](), counter: &i}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *Locks[K]) SetLockNum(num int) {
|
||||||
|
if num > 0 {
|
||||||
|
l.locks = make([]*sync.Mutex, num)
|
||||||
|
for i := 0; i < num; i++ {
|
||||||
|
l.locks[i] = &sync.Mutex{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *Locks[K]) GetLock(ctx context.Context, gMut *sync.Mutex, keys ...K) *sync.Mutex {
|
||||||
|
k := keys[0]
|
||||||
|
lo, ok := l.m.Load(k)
|
||||||
|
if ok {
|
||||||
|
return lo
|
||||||
|
}
|
||||||
|
num := l.numFn()
|
||||||
|
if num == 1 {
|
||||||
|
return gMut
|
||||||
|
}
|
||||||
|
gMut.Lock()
|
||||||
|
defer gMut.Unlock()
|
||||||
|
lo, ok = l.m.Load(k)
|
||||||
|
if ok {
|
||||||
|
return lo
|
||||||
|
}
|
||||||
|
if num <= 0 {
|
||||||
|
lo = &sync.Mutex{}
|
||||||
|
l.m.Store(k, lo)
|
||||||
|
return lo
|
||||||
|
}
|
||||||
|
if len(l.locks) == 0 {
|
||||||
|
l.SetLockNum(num)
|
||||||
|
}
|
||||||
|
counter := int(atomic.LoadInt64(l.counter))
|
||||||
|
if counter > len(l.locks)-1 {
|
||||||
|
atomic.StoreInt64(l.counter, 0)
|
||||||
|
counter = 0
|
||||||
|
}
|
||||||
|
lo = l.locks[counter]
|
||||||
|
l.m.Store(k, lo)
|
||||||
|
atomic.AddInt64(l.counter, 1)
|
||||||
|
if len(l.locks) < num {
|
||||||
|
for i := 0; i < num-len(l.locks); i++ {
|
||||||
|
l.locks = append(l.locks, &sync.Mutex{})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return lo
|
||||||
|
}
|
558
cache/map.go
vendored
558
cache/map.go
vendored
|
@ -4,54 +4,200 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/fthvgb1/wp-go/helper/slice"
|
"github.com/fthvgb1/wp-go/cache/reload"
|
||||||
|
"github.com/fthvgb1/wp-go/helper"
|
||||||
|
"github.com/fthvgb1/wp-go/helper/maps"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
type MapCache[K comparable, V any] struct {
|
type MapCache[K comparable, V any] struct {
|
||||||
data Cache[K, V]
|
Cache[K, V]
|
||||||
mux sync.Mutex
|
mux *sync.Mutex
|
||||||
cacheFunc func(...any) (V, error)
|
muFn func(ctx context.Context, gMut *sync.Mutex, k ...K) *sync.Mutex
|
||||||
batchCacheFn func(...any) (map[K]V, error)
|
cacheFunc MapSingleFn[K, V]
|
||||||
expireTime time.Duration
|
batchCacheFn MapBatchFn[K, V]
|
||||||
|
getCacheBatch func(c context.Context, key []K, timeout time.Duration, params ...any) ([]V, error)
|
||||||
|
getCacheBatchToMap func(c context.Context, key []K, timeout time.Duration, params ...any) (map[K]V, error)
|
||||||
|
increaseUpdate *IncreaseUpdate[K, V]
|
||||||
|
refresh Refresh[K, V]
|
||||||
|
gets func(ctx context.Context, key K) (V, bool)
|
||||||
|
sets func(ctx context.Context, key K, val V)
|
||||||
|
getExpireTimes func(ctx context.Context) time.Duration
|
||||||
|
ttl func(ctx context.Context, key K) time.Duration
|
||||||
|
flush func(ctx context.Context)
|
||||||
|
del func(ctx context.Context, key ...K)
|
||||||
|
clearExpired func(ctx context.Context)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *MapCache[K, V]) SetCacheFunc(fn func(...any) (V, error)) {
|
func (m *MapCache[K, V]) Get(ctx context.Context, key K) (V, bool) {
|
||||||
|
return m.gets(ctx, key)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *MapCache[K, V]) Set(ctx context.Context, key K, val V) {
|
||||||
|
m.sets(ctx, key, val)
|
||||||
|
}
|
||||||
|
func (m *MapCache[K, V]) Ttl(ctx context.Context, key K) time.Duration {
|
||||||
|
return m.ttl(ctx, key)
|
||||||
|
}
|
||||||
|
func (m *MapCache[K, V]) GetExpireTime(ctx context.Context) time.Duration {
|
||||||
|
return m.getExpireTimes(ctx)
|
||||||
|
}
|
||||||
|
func (m *MapCache[K, V]) Del(ctx context.Context, key ...K) {
|
||||||
|
m.del(ctx, key...)
|
||||||
|
}
|
||||||
|
func (m *MapCache[K, V]) ClearExpired(ctx context.Context) {
|
||||||
|
m.clearExpired(ctx)
|
||||||
|
}
|
||||||
|
|
||||||
|
type IncreaseUpdate[K comparable, V any] struct {
|
||||||
|
CycleTime func() time.Duration
|
||||||
|
Fn IncreaseFn[K, V]
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewIncreaseUpdate[K comparable, V any](name string, fn IncreaseFn[K, V], cycleTime time.Duration, tFn func() time.Duration) *IncreaseUpdate[K, V] {
|
||||||
|
tFn = reload.BuildFnVal(name, cycleTime, tFn)
|
||||||
|
return &IncreaseUpdate[K, V]{CycleTime: tFn, Fn: fn}
|
||||||
|
}
|
||||||
|
|
||||||
|
type MapSingleFn[K, V any] func(context.Context, K, ...any) (V, error)
|
||||||
|
type MapBatchFn[K comparable, V any] func(context.Context, []K, ...any) (map[K]V, error)
|
||||||
|
type IncreaseFn[K comparable, V any] func(c context.Context, currentData V, k K, t time.Time, a ...any) (data V, save bool, refresh bool, err error)
|
||||||
|
|
||||||
|
func NewMapCache[K comparable, V any](ca Cache[K, V], cacheFunc MapSingleFn[K, V], batchCacheFn MapBatchFn[K, V], inc *IncreaseUpdate[K, V], lockFn LockFn[K], a ...any) *MapCache[K, V] {
|
||||||
|
r := &MapCache[K, V]{
|
||||||
|
Cache: ca,
|
||||||
|
mux: &sync.Mutex{},
|
||||||
|
cacheFunc: cacheFunc,
|
||||||
|
batchCacheFn: batchCacheFn,
|
||||||
|
increaseUpdate: inc,
|
||||||
|
muFn: lockFn,
|
||||||
|
}
|
||||||
|
if cacheFunc == nil && batchCacheFn != nil {
|
||||||
|
r.setDefaultCacheFn(batchCacheFn)
|
||||||
|
} else if batchCacheFn == nil && cacheFunc != nil {
|
||||||
|
r.SetDefaultBatchFunc(cacheFunc)
|
||||||
|
}
|
||||||
|
ex, ok := any(ca).(Expend[K, V])
|
||||||
|
if !ok {
|
||||||
|
r.getCacheBatch = r.getCacheBatchs
|
||||||
|
r.getCacheBatchToMap = r.getBatchToMapes
|
||||||
|
} else {
|
||||||
|
r.getCacheBatch = r.getBatches(ex)
|
||||||
|
r.getCacheBatchToMap = r.getBatchToMap(ex)
|
||||||
|
}
|
||||||
|
re, ok := any(ca).(Refresh[K, V])
|
||||||
|
if ok {
|
||||||
|
r.refresh = re
|
||||||
|
}
|
||||||
|
initCache(r, a...)
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
func initCache[K comparable, V any](r *MapCache[K, V], a ...any) {
|
||||||
|
gets := helper.ParseArgs[func(Cache[K, V], context.Context, K) (V, bool)](nil, a...)
|
||||||
|
if gets == nil {
|
||||||
|
r.gets = r.Cache.Get
|
||||||
|
} else {
|
||||||
|
r.gets = func(ctx context.Context, key K) (V, bool) {
|
||||||
|
return gets(r.Cache, ctx, key)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sets := helper.ParseArgs[func(Cache[K, V], context.Context, K, V)](nil, a...)
|
||||||
|
if sets == nil {
|
||||||
|
r.sets = r.Cache.Set
|
||||||
|
} else {
|
||||||
|
r.sets = func(ctx context.Context, key K, val V) {
|
||||||
|
sets(r.Cache, ctx, key, val)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
getExpireTimes := helper.ParseArgs[func(Cache[K, V], context.Context) time.Duration](nil, a...)
|
||||||
|
if getExpireTimes == nil {
|
||||||
|
r.getExpireTimes = r.Cache.GetExpireTime
|
||||||
|
} else {
|
||||||
|
r.getExpireTimes = func(ctx context.Context) time.Duration {
|
||||||
|
return getExpireTimes(r.Cache, ctx)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ttl := helper.ParseArgs[func(Cache[K, V], context.Context, K) time.Duration](nil, a...)
|
||||||
|
if ttl == nil {
|
||||||
|
r.ttl = r.Cache.Ttl
|
||||||
|
} else {
|
||||||
|
r.ttl = func(ctx context.Context, k K) time.Duration {
|
||||||
|
return ttl(r.Cache, ctx, k)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
del := helper.ParseArgs[func(Cache[K, V], context.Context, ...K)](nil, a...)
|
||||||
|
if del == nil {
|
||||||
|
r.del = r.Cache.Del
|
||||||
|
} else {
|
||||||
|
r.del = func(ctx context.Context, key ...K) {
|
||||||
|
del(r.Cache, ctx, key...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
flushAndClearExpired := helper.ParseArgs[[]func(Cache[K, V], context.Context)](nil, a...)
|
||||||
|
if flushAndClearExpired == nil {
|
||||||
|
r.flush = r.Cache.Flush
|
||||||
|
r.clearExpired = r.Cache.ClearExpired
|
||||||
|
} else {
|
||||||
|
r.flush = func(ctx context.Context) {
|
||||||
|
flushAndClearExpired[0](r.Cache, ctx)
|
||||||
|
}
|
||||||
|
if len(flushAndClearExpired) > 1 {
|
||||||
|
r.clearExpired = func(ctx context.Context) {
|
||||||
|
flushAndClearExpired[1](r.Cache, ctx)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
r.clearExpired = r.Cache.ClearExpired
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *MapCache[K, V]) SetDefaultBatchFunc(fn MapSingleFn[K, V]) {
|
||||||
|
m.batchCacheFn = func(ctx context.Context, ids []K, a ...any) (map[K]V, error) {
|
||||||
|
var err error
|
||||||
|
rr := make(map[K]V)
|
||||||
|
for _, id := range ids {
|
||||||
|
v, er := fn(ctx, id, a...)
|
||||||
|
if er != nil {
|
||||||
|
err = errors.Join(er)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
rr[id] = v
|
||||||
|
}
|
||||||
|
return rr, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *MapCache[K, V]) SetCacheFunc(fn MapSingleFn[K, V]) {
|
||||||
m.cacheFunc = fn
|
m.cacheFunc = fn
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *MapCache[K, V]) Ttl(ctx context.Context, k K) time.Duration {
|
|
||||||
return m.data.Ttl(ctx, k, m.expireTime)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *MapCache[K, V]) GetLastSetTime(ctx context.Context, k K) (t time.Time) {
|
func (m *MapCache[K, V]) GetLastSetTime(ctx context.Context, k K) (t time.Time) {
|
||||||
tt := m.data.Ttl(ctx, k, m.expireTime)
|
tt := m.Ttl(ctx, k)
|
||||||
if tt <= 0 {
|
if tt <= 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
return time.Now().Add(m.data.Ttl(ctx, k, m.expireTime)).Add(-m.expireTime)
|
return time.Now().Add(m.Ttl(ctx, k)).Add(-m.GetExpireTime(ctx))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *MapCache[K, V]) SetCacheBatchFn(fn func(...any) (map[K]V, error)) {
|
func (m *MapCache[K, V]) SetCacheBatchFn(fn MapBatchFn[K, V]) {
|
||||||
m.batchCacheFn = fn
|
m.batchCacheFn = fn
|
||||||
if m.cacheFunc == nil {
|
if m.cacheFunc == nil {
|
||||||
m.setCacheFn(fn)
|
m.setDefaultCacheFn(fn)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *MapCache[K, V]) setCacheFn(fn func(...any) (map[K]V, error)) {
|
func (m *MapCache[K, V]) setDefaultCacheFn(fn MapBatchFn[K, V]) {
|
||||||
m.cacheFunc = func(a ...any) (V, error) {
|
m.cacheFunc = func(ctx context.Context, k K, a ...any) (V, error) {
|
||||||
var err error
|
var err error
|
||||||
var r map[K]V
|
var r map[K]V
|
||||||
var k K
|
r, err = fn(ctx, []K{k}, a...)
|
||||||
ctx, ok := a[0].(context.Context)
|
|
||||||
if ok {
|
|
||||||
k, ok = a[1].(K)
|
|
||||||
if ok {
|
|
||||||
r, err = fn(ctx, []K{k})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
var rr V
|
var rr V
|
||||||
|
@ -61,59 +207,145 @@ func (m *MapCache[K, V]) setCacheFn(fn func(...any) (map[K]V, error)) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewMapCacheByFn[K comparable, V any](cacheType Cache[K, V], fn func(...any) (V, error), expireTime time.Duration) *MapCache[K, V] {
|
|
||||||
return &MapCache[K, V]{
|
|
||||||
mux: sync.Mutex{},
|
|
||||||
cacheFunc: fn,
|
|
||||||
expireTime: expireTime,
|
|
||||||
data: cacheType,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
func NewMapCacheByBatchFn[K comparable, V any](cacheType Cache[K, V], fn func(...any) (map[K]V, error), expireTime time.Duration) *MapCache[K, V] {
|
|
||||||
r := &MapCache[K, V]{
|
|
||||||
mux: sync.Mutex{},
|
|
||||||
batchCacheFn: fn,
|
|
||||||
expireTime: expireTime,
|
|
||||||
data: cacheType,
|
|
||||||
}
|
|
||||||
r.setCacheFn(fn)
|
|
||||||
return r
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *MapCache[K, V]) Flush(ctx context.Context) {
|
func (m *MapCache[K, V]) Flush(ctx context.Context) {
|
||||||
m.mux.Lock()
|
m.mux.Lock()
|
||||||
defer m.mux.Unlock()
|
defer m.mux.Unlock()
|
||||||
m.data.Flush(ctx)
|
m.flush(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *MapCache[K, V]) Get(ctx context.Context, k K) (V, bool) {
|
func (m *MapCache[K, V]) increaseUpdates(c context.Context, timeout time.Duration, data V, key K, params ...any) (V, error) {
|
||||||
return m.data.Get(ctx, k)
|
var err error
|
||||||
}
|
nowTime := time.Now()
|
||||||
|
if nowTime.Sub(m.GetLastSetTime(c, key)) < m.increaseUpdate.CycleTime() {
|
||||||
func (m *MapCache[K, V]) Set(ctx context.Context, k K, v V) {
|
return data, err
|
||||||
m.data.Set(ctx, k, v, m.expireTime)
|
}
|
||||||
|
fn := func() {
|
||||||
|
l := m.muFn(c, m.mux, key)
|
||||||
|
l.Lock()
|
||||||
|
defer l.Unlock()
|
||||||
|
if nowTime.Sub(m.GetLastSetTime(c, key)) < m.increaseUpdate.CycleTime() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
dat, save, refresh, er := m.increaseUpdate.Fn(c, data, key, m.GetLastSetTime(c, key), params...)
|
||||||
|
if er != nil {
|
||||||
|
err = er
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if refresh {
|
||||||
|
m.refresh.Refresh(c, key, params...)
|
||||||
|
}
|
||||||
|
if save {
|
||||||
|
m.Set(c, key, dat)
|
||||||
|
data = dat
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if timeout > 0 {
|
||||||
|
er := helper.RunFnWithTimeout(c, timeout, fn)
|
||||||
|
if err == nil && er != nil {
|
||||||
|
return data, fmt.Errorf("increateUpdate cache %v err:[%s]", key, er)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
fn()
|
||||||
|
}
|
||||||
|
return data, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *MapCache[K, V]) GetCache(c context.Context, key K, timeout time.Duration, params ...any) (V, error) {
|
func (m *MapCache[K, V]) GetCache(c context.Context, key K, timeout time.Duration, params ...any) (V, error) {
|
||||||
data, ok := m.data.Get(c, key)
|
data, ok := m.Get(c, key)
|
||||||
var err error
|
var err error
|
||||||
if !ok || m.data.Ttl(c, key, m.expireTime) <= 0 {
|
if ok {
|
||||||
ver := m.data.Ver(c, key)
|
if m.increaseUpdate == nil || m.refresh == nil {
|
||||||
|
return data, err
|
||||||
|
}
|
||||||
|
return m.increaseUpdates(c, timeout, data, key, params...)
|
||||||
|
}
|
||||||
call := func() {
|
call := func() {
|
||||||
m.mux.Lock()
|
l := m.muFn(c, m.mux, key)
|
||||||
defer m.mux.Unlock()
|
l.Lock()
|
||||||
if m.data.Ver(c, key) > ver {
|
defer l.Unlock()
|
||||||
data, _ = m.data.Get(c, key)
|
if data, ok = m.Get(c, key); ok {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
data, err = m.cacheFunc(params...)
|
data, err = m.cacheFunc(c, key, params...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
m.Set(c, key, data)
|
m.Set(c, key, data)
|
||||||
}
|
}
|
||||||
if timeout > 0 {
|
if timeout > 0 {
|
||||||
ctx, cancel := context.WithTimeout(c, timeout)
|
er := helper.RunFnWithTimeout(c, timeout, call, fmt.Sprintf("get cache %v ", key))
|
||||||
|
if err == nil && er != nil {
|
||||||
|
err = er
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
call()
|
||||||
|
}
|
||||||
|
return data, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *MapCache[K, V]) GetCacheBatch(c context.Context, key []K, timeout time.Duration, params ...any) ([]V, error) {
|
||||||
|
return m.getCacheBatch(c, key, timeout, params...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *MapCache[K, V]) GetBatchToMap(c context.Context, key []K, timeout time.Duration, params ...any) (map[K]V, error) {
|
||||||
|
return m.getCacheBatchToMap(c, key, timeout, params...)
|
||||||
|
}
|
||||||
|
func (m *MapCache[K, V]) getBatchToMap(e Expend[K, V]) func(c context.Context, key []K, timeout time.Duration, params ...any) (map[K]V, error) {
|
||||||
|
return func(ctx context.Context, key []K, timeout time.Duration, params ...any) (map[K]V, error) {
|
||||||
|
var res map[K]V
|
||||||
|
var err error
|
||||||
|
mm, err := e.Gets(ctx, key)
|
||||||
|
if err != nil || len(key) == len(mm) {
|
||||||
|
return mm, err
|
||||||
|
}
|
||||||
|
var needIndex = make(map[K]int)
|
||||||
|
res = mm
|
||||||
|
var flushKeys []K
|
||||||
|
for i, k := range key {
|
||||||
|
_, ok := mm[k]
|
||||||
|
if !ok {
|
||||||
|
flushKeys = append(flushKeys, k)
|
||||||
|
needIndex[k] = i
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
call := func() {
|
||||||
|
m.mux.Lock()
|
||||||
|
defer m.mux.Unlock()
|
||||||
|
mmm, er := e.Gets(ctx, maps.FilterToSlice(needIndex, func(k K, v int) (K, bool) {
|
||||||
|
return k, true
|
||||||
|
}))
|
||||||
|
if er != nil {
|
||||||
|
err = er
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for k, v := range mmm {
|
||||||
|
res[k] = v
|
||||||
|
delete(needIndex, k)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(needIndex) < 1 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
r, er := m.batchCacheFn(ctx, maps.FilterToSlice(needIndex, func(k K, v int) (K, bool) {
|
||||||
|
return k, true
|
||||||
|
}), params...)
|
||||||
|
if er != nil {
|
||||||
|
err = er
|
||||||
|
return
|
||||||
|
}
|
||||||
|
e.Sets(ctx, r)
|
||||||
|
|
||||||
|
for k := range needIndex {
|
||||||
|
v, ok := r[k]
|
||||||
|
if ok {
|
||||||
|
res[k] = v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if timeout > 0 {
|
||||||
|
ctx, cancel := context.WithTimeout(ctx, timeout)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
done := make(chan struct{}, 1)
|
done := make(chan struct{}, 1)
|
||||||
go func() {
|
go func() {
|
||||||
|
@ -123,47 +355,59 @@ func (m *MapCache[K, V]) GetCache(c context.Context, key K, timeout time.Duratio
|
||||||
select {
|
select {
|
||||||
case <-ctx.Done():
|
case <-ctx.Done():
|
||||||
err = errors.New(fmt.Sprintf("get cache %v %s", key, ctx.Err().Error()))
|
err = errors.New(fmt.Sprintf("get cache %v %s", key, ctx.Err().Error()))
|
||||||
|
return nil, err
|
||||||
case <-done:
|
case <-done:
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
call()
|
call()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return res, err
|
||||||
}
|
}
|
||||||
return data, err
|
|
||||||
}
|
}
|
||||||
|
func (m *MapCache[K, V]) getBatchToMapes(c context.Context, key []K, timeout time.Duration, params ...any) (r map[K]V, err error) {
|
||||||
func (m *MapCache[K, V]) GetCacheBatch(c context.Context, key []K, timeout time.Duration, params ...any) ([]V, error) {
|
r = make(map[K]V)
|
||||||
var res []V
|
var needIndex = make(map[K]int)
|
||||||
ver := 0
|
for i, k := range key {
|
||||||
needFlush := slice.FilterAndMap(key, func(k K) (r K, ok bool) {
|
v, ok := m.Get(c, k)
|
||||||
if _, ok := m.data.Get(c, k); !ok {
|
if !ok {
|
||||||
return k, true
|
needIndex[k] = i
|
||||||
|
} else {
|
||||||
|
r[k] = v
|
||||||
}
|
}
|
||||||
ver += m.data.Ver(c, k)
|
}
|
||||||
|
if len(needIndex) < 1 {
|
||||||
return
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
call := func() {
|
||||||
|
l := m.muFn(c, m.mux, key...)
|
||||||
|
l.Lock()
|
||||||
|
defer l.Unlock()
|
||||||
|
needFlushs := maps.FilterToSlice(needIndex, func(k K, v int) (K, bool) {
|
||||||
|
vv, ok := m.Get(c, k)
|
||||||
|
if ok {
|
||||||
|
r[k] = vv
|
||||||
|
delete(needIndex, k)
|
||||||
|
return k, false
|
||||||
|
}
|
||||||
|
return k, true
|
||||||
})
|
})
|
||||||
|
|
||||||
var err error
|
if len(needFlushs) < 1 {
|
||||||
if len(needFlush) > 0 {
|
|
||||||
call := func() {
|
|
||||||
m.mux.Lock()
|
|
||||||
defer m.mux.Unlock()
|
|
||||||
|
|
||||||
vers := slice.Reduce(needFlush, func(t K, r int) int {
|
|
||||||
return r + m.data.Ver(c, t)
|
|
||||||
}, 0)
|
|
||||||
|
|
||||||
if vers > ver {
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
r, er := m.batchCacheFn(params...)
|
rr, er := m.batchCacheFn(c, needFlushs, params...)
|
||||||
if err != nil {
|
if er != nil {
|
||||||
err = er
|
err = er
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
for k, v := range r {
|
for k := range needIndex {
|
||||||
|
v, ok := rr[k]
|
||||||
|
if ok {
|
||||||
|
r[k] = v
|
||||||
|
}
|
||||||
m.Set(c, k, v)
|
m.Set(c, k, v)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -178,20 +422,160 @@ func (m *MapCache[K, V]) GetCacheBatch(c context.Context, key []K, timeout time.
|
||||||
select {
|
select {
|
||||||
case <-ctx.Done():
|
case <-ctx.Done():
|
||||||
err = errors.New(fmt.Sprintf("get cache %v %s", key, ctx.Err().Error()))
|
err = errors.New(fmt.Sprintf("get cache %v %s", key, ctx.Err().Error()))
|
||||||
|
return nil, err
|
||||||
case <-done:
|
case <-done:
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
call()
|
call()
|
||||||
}
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *MapCache[K, V]) getCacheBatchs(c context.Context, key []K, timeout time.Duration, params ...any) ([]V, error) {
|
||||||
|
var res = make([]V, 0, len(key))
|
||||||
|
var needIndex = make(map[K]int)
|
||||||
|
for i, k := range key {
|
||||||
|
v, ok := m.Get(c, k)
|
||||||
|
if !ok {
|
||||||
|
needIndex[k] = i
|
||||||
}
|
}
|
||||||
res = slice.FilterAndMap(key, func(k K) (V, bool) {
|
res = append(res, v)
|
||||||
return m.data.Get(c, k)
|
}
|
||||||
|
if len(needIndex) < 1 {
|
||||||
|
return res, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var err error
|
||||||
|
call := func() {
|
||||||
|
l := m.muFn(c, m.mux, key...)
|
||||||
|
l.Lock()
|
||||||
|
defer l.Unlock()
|
||||||
|
needFlushs := maps.FilterToSlice(needIndex, func(k K, v int) (K, bool) {
|
||||||
|
vv, ok := m.Get(c, k)
|
||||||
|
if ok {
|
||||||
|
res[needIndex[k]] = vv
|
||||||
|
delete(needIndex, k)
|
||||||
|
return k, false
|
||||||
|
}
|
||||||
|
return k, true
|
||||||
})
|
})
|
||||||
|
|
||||||
|
if len(needFlushs) < 1 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
r, er := m.batchCacheFn(c, needFlushs, params...)
|
||||||
|
if er != nil {
|
||||||
|
err = er
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for k, i := range needIndex {
|
||||||
|
v, ok := r[k]
|
||||||
|
if ok {
|
||||||
|
res[i] = v
|
||||||
|
m.Set(c, k, v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if timeout > 0 {
|
||||||
|
ctx, cancel := context.WithTimeout(c, timeout)
|
||||||
|
defer cancel()
|
||||||
|
done := make(chan struct{}, 1)
|
||||||
|
go func() {
|
||||||
|
call()
|
||||||
|
done <- struct{}{}
|
||||||
|
}()
|
||||||
|
select {
|
||||||
|
case <-ctx.Done():
|
||||||
|
err = errors.New(fmt.Sprintf("get cache %v %s", key, ctx.Err().Error()))
|
||||||
|
return nil, err
|
||||||
|
case <-done:
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
call()
|
||||||
|
}
|
||||||
|
|
||||||
return res, err
|
return res, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *MapCache[K, V]) ClearExpired(ctx context.Context) {
|
func (m *MapCache[K, V]) getBatches(e Expend[K, V]) func(ctx context.Context, key []K, timeout time.Duration, params ...any) ([]V, error) {
|
||||||
|
cc := e
|
||||||
|
return func(ctx context.Context, key []K, timeout time.Duration, params ...any) ([]V, error) {
|
||||||
|
var res = make([]V, 0, len(key))
|
||||||
|
var needIndex = make(map[K]int)
|
||||||
|
var err error
|
||||||
|
mm, err := cc.Gets(ctx, key)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
var flushKeys []K
|
||||||
|
for i, k := range key {
|
||||||
|
v, ok := mm[k]
|
||||||
|
if !ok {
|
||||||
|
flushKeys = append(flushKeys, k)
|
||||||
|
needIndex[k] = i
|
||||||
|
var vv V
|
||||||
|
v = vv
|
||||||
|
}
|
||||||
|
res = append(res, v)
|
||||||
|
}
|
||||||
|
if len(needIndex) < 1 {
|
||||||
|
return res, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
call := func() {
|
||||||
m.mux.Lock()
|
m.mux.Lock()
|
||||||
defer m.mux.Unlock()
|
defer m.mux.Unlock()
|
||||||
m.data.ClearExpired(ctx, m.expireTime)
|
mmm, er := cc.Gets(ctx, maps.FilterToSlice(needIndex, func(k K, v int) (K, bool) {
|
||||||
|
return k, true
|
||||||
|
}))
|
||||||
|
if er != nil {
|
||||||
|
err = er
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for k, v := range mmm {
|
||||||
|
res[needIndex[k]] = v
|
||||||
|
delete(needIndex, k)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(needIndex) < 1 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
r, er := m.batchCacheFn(ctx, maps.FilterToSlice(needIndex, func(k K, v int) (K, bool) {
|
||||||
|
return k, true
|
||||||
|
}), params...)
|
||||||
|
if er != nil {
|
||||||
|
err = er
|
||||||
|
return
|
||||||
|
}
|
||||||
|
cc.Sets(ctx, r)
|
||||||
|
|
||||||
|
for k, i := range needIndex {
|
||||||
|
v, ok := r[k]
|
||||||
|
if ok {
|
||||||
|
res[i] = v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if timeout > 0 {
|
||||||
|
ctx, cancel := context.WithTimeout(ctx, timeout)
|
||||||
|
defer cancel()
|
||||||
|
done := make(chan struct{}, 1)
|
||||||
|
go func() {
|
||||||
|
call()
|
||||||
|
done <- struct{}{}
|
||||||
|
}()
|
||||||
|
select {
|
||||||
|
case <-ctx.Done():
|
||||||
|
err = errors.New(fmt.Sprintf("get cache %v %s", key, ctx.Err().Error()))
|
||||||
|
return nil, err
|
||||||
|
case <-done:
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
call()
|
||||||
|
}
|
||||||
|
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
39
cache/map_test.go
vendored
39
cache/map_test.go
vendored
|
@ -12,27 +12,22 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
var ca MapCache[string, string]
|
var ca MapCache[string, string]
|
||||||
var fn func(a ...any) (string, error)
|
var fn MapSingleFn[string, string]
|
||||||
var batchFn func(a ...any) (map[string]string, error)
|
var batchFn MapBatchFn[string, string]
|
||||||
var ct context.Context
|
var ct context.Context
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
fn = func(a ...any) (string, error) {
|
fn = func(ctx context.Context, aa string, a ...any) (string, error) {
|
||||||
aa := a[1].(string)
|
|
||||||
return strings.Repeat(aa, 2), nil
|
return strings.Repeat(aa, 2), nil
|
||||||
}
|
}
|
||||||
ct = context.Background()
|
ct = context.Background()
|
||||||
batchFn = func(a ...any) (map[string]string, error) {
|
batchFn = func(ctx context.Context, arr []string, a ...any) (map[string]string, error) {
|
||||||
fmt.Println(a)
|
fmt.Println(a)
|
||||||
arr := a[1].([]string)
|
return slice.FilterAndToMap(arr, func(t string, _ int) (string, string, bool) {
|
||||||
return slice.FilterAndToMap(arr, func(t string) (string, string, bool) {
|
|
||||||
return t, strings.Repeat(t, 2), true
|
return t, strings.Repeat(t, 2), true
|
||||||
}), nil
|
}), nil
|
||||||
}
|
}
|
||||||
ca = *NewMemoryMapCacheByFn[string, string](fn, time.Second*2)
|
|
||||||
ca.SetCacheBatchFn(batchFn)
|
|
||||||
_, _ = ca.GetCache(ct, "aa", time.Second, ct, "aa")
|
|
||||||
_, _ = ca.GetCache(ct, "bb", time.Second, ct, "bb")
|
|
||||||
}
|
}
|
||||||
func TestMapCache_ClearExpired(t *testing.T) {
|
func TestMapCache_ClearExpired(t *testing.T) {
|
||||||
type args struct {
|
type args struct {
|
||||||
|
@ -72,7 +67,9 @@ func TestMapCache_Flush(t *testing.T) {
|
||||||
m MapCache[K, V]
|
m MapCache[K, V]
|
||||||
args args
|
args args
|
||||||
}
|
}
|
||||||
ca := *NewMemoryMapCacheByFn[string, string](fn, time.Second)
|
ca := *NewMapCache[string, string](NewMemoryMapCache[string, string](func() time.Duration {
|
||||||
|
return time.Second
|
||||||
|
}), fn, nil, nil, nil)
|
||||||
_, _ = ca.GetCache(ct, "aa", time.Second, ct, "aa")
|
_, _ = ca.GetCache(ct, "aa", time.Second, ct, "aa")
|
||||||
tests := []testCase[string, string]{
|
tests := []testCase[string, string]{
|
||||||
{
|
{
|
||||||
|
@ -293,7 +290,7 @@ func TestMapCache_Set(t *testing.T) {
|
||||||
|
|
||||||
func TestMapCache_SetCacheBatchFn(t *testing.T) {
|
func TestMapCache_SetCacheBatchFn(t *testing.T) {
|
||||||
type args[K comparable, V any] struct {
|
type args[K comparable, V any] struct {
|
||||||
fn func(...any) (map[K]V, error)
|
fn MapBatchFn[K, V]
|
||||||
}
|
}
|
||||||
type testCase[K comparable, V any] struct {
|
type testCase[K comparable, V any] struct {
|
||||||
name string
|
name string
|
||||||
|
@ -315,19 +312,19 @@ func TestMapCache_SetCacheBatchFn(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestMapCache_SetCacheFunc(t *testing.T) {
|
func TestMapCache_SetCacheFunc(t *testing.T) {
|
||||||
type args[V any] struct {
|
type args[K comparable, V any] struct {
|
||||||
fn func(...any) (V, error)
|
fn MapSingleFn[K, V]
|
||||||
}
|
}
|
||||||
type testCase[K comparable, V any] struct {
|
type testCase[K comparable, V any] struct {
|
||||||
name string
|
name string
|
||||||
m MapCache[K, V]
|
m MapCache[K, V]
|
||||||
args args[V]
|
args args[K, V]
|
||||||
}
|
}
|
||||||
tests := []testCase[string, string]{
|
tests := []testCase[string, string]{
|
||||||
{
|
{
|
||||||
name: "t1",
|
name: "t1",
|
||||||
m: ca,
|
m: ca,
|
||||||
args: args[string]{fn: fn},
|
args: args[string, string]{fn: fn},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
|
@ -355,12 +352,12 @@ func TestMapCache_Ttl(t *testing.T) {
|
||||||
name: "t1",
|
name: "t1",
|
||||||
m: ca,
|
m: ca,
|
||||||
args: args[string]{ct, "aa"},
|
args: args[string]{ct, "aa"},
|
||||||
want: ca.expireTime - tx.Sub(txx),
|
want: ca.GetExpireTime(ct) - tx.Sub(txx),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
fmt.Printf("过期时间=%v \nttl=%v \n当前时间 =%v\n最后设置时间=%v\n当时时间-最后设置时间=%v ", ca.expireTime, ca.Ttl(ct, "aa"), tx, txx, tx.Sub(txx))
|
fmt.Printf("过期时间=%v \nttl=%v \n当前时间 =%v\n最后设置时间=%v\n当时时间-最后设置时间=%v ", ca.GetExpireTime(ct), ca.Ttl(ct, "aa"), tx, txx, tx.Sub(txx))
|
||||||
if got := tt.m.Ttl(tt.args.ct, tt.args.k); got != tt.want {
|
if got := tt.m.Ttl(tt.args.ct, tt.args.k); got != tt.want {
|
||||||
t.Errorf("Ttl() = %v, want %v", got, tt.want)
|
t.Errorf("Ttl() = %v, want %v", got, tt.want)
|
||||||
}
|
}
|
||||||
|
@ -370,7 +367,7 @@ func TestMapCache_Ttl(t *testing.T) {
|
||||||
|
|
||||||
func TestMapCache_setCacheFn(t *testing.T) {
|
func TestMapCache_setCacheFn(t *testing.T) {
|
||||||
type args[K comparable, V any] struct {
|
type args[K comparable, V any] struct {
|
||||||
fn func(...any) (map[K]V, error)
|
fn MapBatchFn[K, V]
|
||||||
}
|
}
|
||||||
type testCase[K comparable, V any] struct {
|
type testCase[K comparable, V any] struct {
|
||||||
name string
|
name string
|
||||||
|
@ -387,7 +384,7 @@ func TestMapCache_setCacheFn(t *testing.T) {
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
ca.cacheFunc = nil
|
ca.cacheFunc = nil
|
||||||
tt.m.setCacheFn(tt.args.fn)
|
tt.m.setDefaultCacheFn(tt.args.fn)
|
||||||
fmt.Println(ca.GetCache(ct, "xx", time.Second, ct, "xx"))
|
fmt.Println(ca.GetCache(ct, "xx", time.Second, ct, "xx"))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user