完善postmeta
This commit is contained in:
parent
66c8ba9de9
commit
d52b1c96d6
|
@ -66,6 +66,19 @@ func SimpleSort[T any](arr []T, fn func(i, j T) bool) {
|
|||
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 {
|
||||
min := a[0]
|
||||
for _, t := range a {
|
||||
|
|
|
@ -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
32
helper/map.go
Normal 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
165
helper/map_test.go
Normal 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)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
43
internal/pkg/cache/postmeta.go
vendored
43
internal/pkg/cache/postmeta.go
vendored
|
@ -2,9 +2,6 @@ package cache
|
|||
|
||||
import (
|
||||
"context"
|
||||
"github/fthvgb1/wp-go/helper"
|
||||
wp2 "github/fthvgb1/wp-go/internal/pkg/models"
|
||||
"strconv"
|
||||
"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)
|
||||
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
|
||||
}
|
||||
|
|
|
@ -2,19 +2,20 @@ package common
|
|||
|
||||
import (
|
||||
"context"
|
||||
"github.com/leeqvip/gophp"
|
||||
"fmt"
|
||||
"github/fthvgb1/wp-go/helper"
|
||||
"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"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func GetPostMetaByPostIds(args ...any) (r map[uint64]map[string]any, err error) {
|
||||
r = make(map[uint64]map[string]any)
|
||||
ctx := args[0].(context.Context)
|
||||
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", ""},
|
||||
}, "*", "", nil, nil, nil, 0, helper.SliceMap(ids, helper.ToAny[uint64]))
|
||||
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)
|
||||
}
|
||||
if postmeta.MetaKey == "_wp_attachment_metadata" {
|
||||
meta, err := gophp.Unserialize([]byte(postmeta.MetaValue))
|
||||
metadata, err := models.AttachmentMetadata(postmeta.MetaValue)
|
||||
if err != nil {
|
||||
logs.ErrPrintln(err, "反序列化postmeta失败", postmeta.MetaValue)
|
||||
logs.ErrPrintln(err, "解析postmeta失败", postmeta.MetaId, postmeta.MetaValue)
|
||||
continue
|
||||
}
|
||||
metaVal, ok := meta.(map[string]any)
|
||||
if ok {
|
||||
r[postmeta.PostId][postmeta.MetaKey] = metaVal
|
||||
}
|
||||
r[postmeta.PostId][postmeta.MetaKey] = metadata
|
||||
|
||||
} else {
|
||||
r[postmeta.PostId][postmeta.MetaKey] = postmeta.MetaValue
|
||||
}
|
||||
|
@ -42,7 +41,7 @@ func GetPostMetaByPostIds(args ...any) (r map[uint64]map[string]any, err error)
|
|||
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 {
|
||||
m, ok := meta["_thumbnail_id"]
|
||||
if ok {
|
||||
|
@ -59,20 +58,29 @@ func ToPostThumb(c context.Context, meta map[string]any, postId uint64) (r model
|
|||
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"]
|
||||
x, ok := mm["_wp_attachment_metadata"]
|
||||
if ok {
|
||||
metadata, ok := x.(models.WpAttachmentMetadata)
|
||||
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
|
||||
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"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ import (
|
|||
"fmt"
|
||||
"github/fthvgb1/wp-go/helper"
|
||||
"github/fthvgb1/wp-go/internal/pkg/models"
|
||||
"github/fthvgb1/wp-go/internal/wpconfig"
|
||||
"github/fthvgb1/wp-go/model"
|
||||
"strings"
|
||||
"sync/atomic"
|
||||
|
@ -42,6 +43,7 @@ func GetPostsByIds(ids ...any) (m map[uint64]models.Posts, err error) {
|
|||
}
|
||||
postsMap[post.Id] = v
|
||||
}
|
||||
host, _ := wpconfig.Options.Load("siteurl")
|
||||
meta, _ := GetPostMetaByPostIds(ctx, id)
|
||||
for k, pp := range postsMap {
|
||||
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, "、")
|
||||
mm, ok := meta[pp.Id]
|
||||
if ok {
|
||||
thumb := ToPostThumb(ctx, mm, pp.Id)
|
||||
thumb := ToPostThumb(ctx, mm, host)
|
||||
if thumb.Path != "" {
|
||||
pp.Thumbnail = thumb
|
||||
}
|
||||
|
|
|
@ -1,5 +1,10 @@
|
|||
package models
|
||||
|
||||
import (
|
||||
"github.com/leeqvip/gophp"
|
||||
"github/fthvgb1/wp-go/helper"
|
||||
)
|
||||
|
||||
type Postmeta struct {
|
||||
MetaId uint64 `db:"meta_id" json:"meta_id" form:"meta_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 {
|
||||
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"`
|
||||
}
|
||||
|
|
|
@ -28,19 +28,22 @@ type Posts struct {
|
|||
CommentCount int64 `gorm:"column:comment_count" db:"comment_count" json:"comment_count" form:"comment_count"`
|
||||
|
||||
//扩展字段
|
||||
Taxonomy string `db:"taxonomy" json:"taxonomy"`
|
||||
CategoryName string `db:"category_name" json:"category_name"`
|
||||
Categories []string `json:"categories"`
|
||||
Tags []string `json:"tags"`
|
||||
CategoriesHtml string
|
||||
TagsHtml string
|
||||
Thumbnail PostThumbnail
|
||||
Taxonomy string `db:"taxonomy" json:"taxonomy"`
|
||||
CategoryName string `db:"category_name" json:"category_name"`
|
||||
Categories []string `json:"categories"`
|
||||
Tags []string `json:"tags"`
|
||||
CategoriesHtml string
|
||||
TagsHtml string
|
||||
Thumbnail PostThumbnail
|
||||
AttachmentMetadata WpAttachmentMetadata
|
||||
}
|
||||
|
||||
type PostThumbnail struct {
|
||||
Path string
|
||||
Width int
|
||||
Height int
|
||||
Srcset string
|
||||
Sizes string
|
||||
}
|
||||
|
||||
func (w Posts) PrimaryKey() string {
|
||||
|
|
Loading…
Reference in New Issue
Block a user