完善postmeta

This commit is contained in:
xing 2023-01-14 21:12:26 +08:00
parent 66c8ba9de9
commit d52b1c96d6
9 changed files with 371 additions and 74 deletions

View File

@ -66,6 +66,19 @@ func SimpleSort[T any](arr []T, fn func(i, j T) bool) {
return return
} }
func SimpleSortR[T any](arr []T, fn func(i, j T) bool) (r []T) {
r = make([]T, 0, len(arr))
for _, t := range arr {
r = append(r, t)
}
slice := anyArr[T]{
data: r,
fn: fn,
}
sort.Sort(slice)
return
}
func Min[T IntNumber | ~float64 | ~float32](a ...T) T { func Min[T IntNumber | ~float64 | ~float32](a ...T) T {
min := a[0] min := a[0]
for _, t := range a { for _, t := range a {

View File

@ -280,3 +280,56 @@ func TestNumberToString(t *testing.T) {
}) })
} }
} }
func TestSimpleSortR(t *testing.T) {
type xy struct {
x int
y int
}
type args[T any] struct {
arr []T
fn func(i, j T) bool
}
type testCase[T any] struct {
name string
args args[T]
wantR []T
}
tests := []testCase[xy]{
{
name: "t1",
args: args[xy]{
arr: []xy{
{1, 2},
{3, 4},
{1, 3},
{2, 1},
{1, 6},
},
fn: func(i, j xy) bool {
if i.x < j.x {
return true
}
if i.x == j.x && i.y > i.y {
return true
}
return false
},
},
wantR: []xy{
{1, 2},
{1, 3},
{1, 6},
{2, 1},
{3, 4},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if gotR := SimpleSortR[xy](tt.args.arr, tt.args.fn); !reflect.DeepEqual(gotR, tt.wantR) {
t.Errorf("SimpleSortR() = %v, want %v", gotR, tt.wantR)
}
})
}
}

32
helper/map.go Normal file
View File

@ -0,0 +1,32 @@
package helper
import "encoding/json"
func MapToStruct[T any](m map[string]any) (r T, err error) {
str, err := json.Marshal(m)
if err != nil {
return
}
err = json.Unmarshal(str, &r)
return
}
func StructToMap[T any](s T) (r map[string]any, err error) {
marshal, err := json.Marshal(s)
if err != nil {
return
}
r = make(map[string]any)
err = json.Unmarshal(marshal, &r)
return
}
func MapToSlice[T any, K comparable, V any](m map[K]V, fn func(K, V) (T, bool)) (r []T) {
for k, v := range m {
vv, ok := fn(k, v)
if ok {
r = append(r, vv)
}
}
return
}

165
helper/map_test.go Normal file
View File

@ -0,0 +1,165 @@
package helper
import (
"reflect"
"testing"
)
type Addr struct {
PostalCode int
Country string
}
type Me struct {
Name string
Age int
Admin bool
Hobbies []string
Address Addr
Null any
}
func TestMapToStruct(t *testing.T) {
type args struct {
m map[string]any
}
type testCase[T any] struct {
name string
args args
wantR T
wantErr bool
}
tests := []testCase[Me]{
{
name: "t1",
args: args{
m: map[string]any{
"name": "noknow",
"Age": 2,
"Admin": true,
"Hobbies": []string{"IT", "Travel"},
"Address": map[string]any{
"PostalCode": 1111,
"Country": "Japan",
},
"Null": nil,
},
},
wantR: Me{
Name: "noknow",
Age: 2,
Admin: true,
Hobbies: []string{"IT", "Travel"},
Address: Addr{
PostalCode: 1111,
Country: "Japan",
},
Null: nil,
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
gotR, err := MapToStruct[Me](tt.args.m)
if (err != nil) != tt.wantErr {
t.Errorf("MapToStruct() error = %v, wantErr %v", err, tt.wantErr)
return
}
if !reflect.DeepEqual(gotR, tt.wantR) {
t.Errorf("MapToStruct() gotR = %v, want %v", gotR, tt.wantR)
}
})
}
}
func TestStructToMap(t *testing.T) {
type args[T any] struct {
s T
}
type testCase[T any] struct {
name string
args args[T]
wantR map[string]any
wantErr bool
}
tests := []testCase[Me]{
{
name: "t1",
args: args[Me]{
s: Me{
Name: "noknow",
Age: 2,
Admin: true,
Hobbies: []string{"IT", "Travel"},
Address: Addr{
PostalCode: 1111,
Country: "Japan",
},
Null: nil,
},
},
wantR: map[string]any{
"Name": "noknow",
"Age": 2,
"Admin": true,
"Hobbies": []string{"IT", "Travel"},
"Address": map[string]any{
"PostalCode": 1111,
"Country": "Japan",
},
"Null": nil,
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
gotR, err := StructToMap[Me](tt.args.s)
if (err != nil) != tt.wantErr {
t.Errorf("StructToMap() error = %v, wantErr %v", err, tt.wantErr)
return
}
if !reflect.DeepEqual(gotR, tt.wantR) {
t.Errorf("StructToMap() gotR = %v, want %v", gotR, tt.wantR)
}
})
}
}
func TestMapToSlice(t *testing.T) {
type args[K comparable, V any, T any] struct {
m map[K]V
fn func(K, V) (T, bool)
}
type testCase[K comparable, V any, T any] struct {
name string
args args[K, V, T]
wantR []T
}
tests := []testCase[string, int, int]{
{
name: "t1",
args: args[string, int, int]{
m: map[string]int{
"0": 0,
"1": 1,
"2": 2,
"3": 3,
},
fn: func(k string, v int) (int, bool) {
if v > 2 {
return v, true
}
return 0, false
},
},
wantR: []int{3},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if gotR := MapToSlice(tt.args.m, tt.args.fn); !reflect.DeepEqual(gotR, tt.wantR) {
t.Errorf("MapToSlice() = %v, want %v", gotR, tt.wantR)
}
})
}
}

View File

@ -2,9 +2,6 @@ package cache
import ( import (
"context" "context"
"github/fthvgb1/wp-go/helper"
wp2 "github/fthvgb1/wp-go/internal/pkg/models"
"strconv"
"time" "time"
) )
@ -16,43 +13,3 @@ func GetPostMetaByPostId(ctx context.Context, id uint64) (r map[string]any, err
r, err = postMetaCache.GetCache(ctx, id, time.Second, ctx, id) r, err = postMetaCache.GetCache(ctx, id, time.Second, ctx, id)
return return
} }
func ToPostThumbnail(c context.Context, postId uint64) (r wp2.PostThumbnail) {
meta, err := GetPostMetaByPostId(c, postId)
if err == nil {
m, ok := meta["_thumbnail_id"]
if ok {
id, err := strconv.ParseUint(m.(string), 10, 64)
if err == nil {
mm, err := GetPostMetaByPostId(c, id)
if err == nil {
f, ok := mm["_wp_attached_file"]
if ok {
ff, ok := f.(string)
if ok && ff != "" {
r.Path = ff
}
}
tt, ok := helper.GetStrMapAnyVal[map[string]any]("_wp_attachment_metadata.sizes.post-thumbnail", mm)
if ok && tt != nil {
width, ok := tt["width"]
if ok {
w, ok := width.(int)
if ok {
r.Width = w
}
}
height, ok := tt["height"]
if ok {
h, ok := height.(int)
if ok {
r.Height = h
}
}
}
}
}
}
}
return
}

View File

@ -2,19 +2,20 @@ package common
import ( import (
"context" "context"
"github.com/leeqvip/gophp" "fmt"
"github/fthvgb1/wp-go/helper" "github/fthvgb1/wp-go/helper"
"github/fthvgb1/wp-go/internal/pkg/logs" "github/fthvgb1/wp-go/internal/pkg/logs"
models2 "github/fthvgb1/wp-go/internal/pkg/models" "github/fthvgb1/wp-go/internal/pkg/models"
"github/fthvgb1/wp-go/model" "github/fthvgb1/wp-go/model"
"strconv" "strconv"
"strings"
) )
func GetPostMetaByPostIds(args ...any) (r map[uint64]map[string]any, err error) { func GetPostMetaByPostIds(args ...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) ctx := args[0].(context.Context)
ids := args[1].([]uint64) ids := args[1].([]uint64)
rr, err := model.Find[models2.Postmeta](ctx, model.SqlBuilder{ rr, err := model.Find[models.Postmeta](ctx, model.SqlBuilder{
{"post_id", "in", ""}, {"post_id", "in", ""},
}, "*", "", nil, nil, nil, 0, helper.SliceMap(ids, helper.ToAny[uint64])) }, "*", "", nil, nil, nil, 0, helper.SliceMap(ids, helper.ToAny[uint64]))
if err != nil { if err != nil {
@ -25,15 +26,13 @@ func GetPostMetaByPostIds(args ...any) (r map[uint64]map[string]any, err error)
r[postmeta.PostId] = make(map[string]any) r[postmeta.PostId] = make(map[string]any)
} }
if postmeta.MetaKey == "_wp_attachment_metadata" { if postmeta.MetaKey == "_wp_attachment_metadata" {
meta, err := gophp.Unserialize([]byte(postmeta.MetaValue)) metadata, err := models.AttachmentMetadata(postmeta.MetaValue)
if err != nil { if err != nil {
logs.ErrPrintln(err, "反序列化postmeta失败", postmeta.MetaValue) logs.ErrPrintln(err, "解析postmeta失败", postmeta.MetaId, postmeta.MetaValue)
continue continue
} }
metaVal, ok := meta.(map[string]any) r[postmeta.PostId][postmeta.MetaKey] = metadata
if ok {
r[postmeta.PostId][postmeta.MetaKey] = metaVal
}
} else { } else {
r[postmeta.PostId][postmeta.MetaKey] = postmeta.MetaValue r[postmeta.PostId][postmeta.MetaKey] = postmeta.MetaValue
} }
@ -42,7 +41,7 @@ func GetPostMetaByPostIds(args ...any) (r map[uint64]map[string]any, err error)
return return
} }
func ToPostThumb(c context.Context, meta map[string]any, postId uint64) (r models2.PostThumbnail) { func ToPostThumb(c context.Context, meta map[string]any, host string) (r models.PostThumbnail) {
if meta != nil { if meta != nil {
m, ok := meta["_thumbnail_id"] m, ok := meta["_thumbnail_id"]
if ok { if ok {
@ -59,20 +58,29 @@ func ToPostThumb(c context.Context, meta map[string]any, postId uint64) (r model
r.Path = ff r.Path = ff
} }
} }
tt, ok := helper.GetStrMapAnyVal[map[string]any]("_wp_attachment_metadata.sizes.post-thumbnail", mm) x, ok := mm["_wp_attachment_metadata"]
if ok && tt != nil {
width, ok := tt["width"]
if ok { if ok {
w, ok := width.(int) metadata, ok := x.(models.WpAttachmentMetadata)
if ok { if ok {
r.Width = w if _, ok := metadata.Sizes["post-thumbnail"]; ok {
r.Width = metadata.Sizes["post-thumbnail"].Width
r.Height = metadata.Sizes["post-thumbnail"].Height
up := strings.Split(metadata.File, "/")
r.Srcset = strings.Join(helper.MapToSlice[string](metadata.Sizes, func(s string, size models.MetaDataFileSize) (r string, ok bool) {
up[2] = size.File
if s == "post-thumbnail" {
return
} }
r = fmt.Sprintf("%s/wp-content/uploads/%s %dw", host, strings.Join(up, "/"), size.Width)
ok = true
return
}), ", ")
r.Sizes = fmt.Sprintf("(max-width: %dpx) 100vw, %dpx", r.Width, r.Width)
if r.Width >= 740 && r.Width < 767 {
r.Sizes = "(max-width: 706px) 89vw, (max-width: 767px) 82vw, 740px"
} else if r.Width >= 767 {
r.Sizes = "(max-width: 767px) 89vw, (max-width: 1000px) 54vw, (max-width: 1071px) 543px, 580px"
} }
height, ok := tt["height"]
if ok {
h, ok := height.(int)
if ok {
r.Height = h
} }
} }
} }

View File

@ -6,6 +6,7 @@ import (
"fmt" "fmt"
"github/fthvgb1/wp-go/helper" "github/fthvgb1/wp-go/helper"
"github/fthvgb1/wp-go/internal/pkg/models" "github/fthvgb1/wp-go/internal/pkg/models"
"github/fthvgb1/wp-go/internal/wpconfig"
"github/fthvgb1/wp-go/model" "github/fthvgb1/wp-go/model"
"strings" "strings"
"sync/atomic" "sync/atomic"
@ -42,6 +43,7 @@ func GetPostsByIds(ids ...any) (m map[uint64]models.Posts, err error) {
} }
postsMap[post.Id] = v postsMap[post.Id] = v
} }
host, _ := wpconfig.Options.Load("siteurl")
meta, _ := GetPostMetaByPostIds(ctx, id) meta, _ := GetPostMetaByPostIds(ctx, id)
for k, pp := range postsMap { for k, pp := range postsMap {
if len(pp.Categories) > 0 { if len(pp.Categories) > 0 {
@ -52,7 +54,7 @@ func GetPostsByIds(ids ...any) (m map[uint64]models.Posts, err error) {
pp.CategoriesHtml = strings.Join(t, "、") pp.CategoriesHtml = strings.Join(t, "、")
mm, ok := meta[pp.Id] mm, ok := meta[pp.Id]
if ok { if ok {
thumb := ToPostThumb(ctx, mm, pp.Id) thumb := ToPostThumb(ctx, mm, host)
if thumb.Path != "" { if thumb.Path != "" {
pp.Thumbnail = thumb pp.Thumbnail = thumb
} }

View File

@ -1,5 +1,10 @@
package models package models
import (
"github.com/leeqvip/gophp"
"github/fthvgb1/wp-go/helper"
)
type Postmeta struct { type Postmeta struct {
MetaId uint64 `db:"meta_id" json:"meta_id" form:"meta_id"` MetaId uint64 `db:"meta_id" json:"meta_id" form:"meta_id"`
PostId uint64 `db:"post_id" json:"post_id" form:"post_id"` PostId uint64 `db:"post_id" json:"post_id" form:"post_id"`
@ -14,3 +19,62 @@ func (p Postmeta) PrimaryKey() string {
func (p Postmeta) Table() string { func (p Postmeta) Table() string {
return "wp_postmeta" return "wp_postmeta"
} }
func (p Postmeta) AttachmentMetadata() (r WpAttachmentMetadata, err error) {
if p.MetaKey == "_wp_attachment_metadata" && p.MetaValue != "" {
unSerialize, er := gophp.Unserialize([]byte(p.MetaValue))
if er != nil {
err = er
return
}
info, ok := unSerialize.(map[string]any)
if ok {
r, err = helper.MapToStruct[WpAttachmentMetadata](info)
}
}
return
}
func AttachmentMetadata(s string) (r WpAttachmentMetadata, err error) {
unSerialize, er := gophp.Unserialize([]byte(s))
if er != nil {
err = er
return
}
info, ok := unSerialize.(map[string]any)
if ok {
r, err = helper.MapToStruct[WpAttachmentMetadata](info)
}
return
}
type WpAttachmentMetadata struct {
Width int `json:"width,omitempty"`
Height int `json:"height,omitempty"`
File string `json:"file,omitempty"`
FileSize int `json:"filesize,omitempty"`
Sizes map[string]MetaDataFileSize `json:"sizes,omitempty"`
ImageMeta ImageMeta `json:"image_meta"`
}
type ImageMeta struct {
Aperture string `json:"aperture,omitempty"`
Credit string `json:"credit,omitempty"`
Camera string `json:"camera,omitempty"`
Caption string `json:"caption,omitempty"`
CreatedTimestamp string `json:"created_timestamp,omitempty"`
Copyright string `json:"copyright,omitempty"`
FocalLength string `json:"focal_length,omitempty"`
Iso string `json:"iso,omitempty"`
ShutterSpeed string `json:"shutter_speed,omitempty"`
Title string `json:"title,omitempty"`
Orientation string `json:"orientation,omitempty"`
Keywords []string `json:"keywords,omitempty"`
}
type MetaDataFileSize struct {
File string `json:"file,omitempty"`
Width int `json:"width,omitempty"`
Height int `json:"height,omitempty"`
MimeType string `json:"mime-type,omitempty"`
FileSize int `json:"filesize,omitempty"`
}

View File

@ -35,12 +35,15 @@ type Posts struct {
CategoriesHtml string CategoriesHtml string
TagsHtml string TagsHtml string
Thumbnail PostThumbnail Thumbnail PostThumbnail
AttachmentMetadata WpAttachmentMetadata
} }
type PostThumbnail struct { type PostThumbnail struct {
Path string Path string
Width int Width int
Height int Height int
Srcset string
Sizes string
} }
func (w Posts) PrimaryKey() string { func (w Posts) PrimaryKey() string {