diff --git a/app/pkg/dao/posts.go b/app/pkg/dao/posts.go index 4016e53..6846d9c 100644 --- a/app/pkg/dao/posts.go +++ b/app/pkg/dao/posts.go @@ -5,7 +5,9 @@ import ( "database/sql" "fmt" "github.com/fthvgb1/wp-go/app/pkg/models" + "github.com/fthvgb1/wp-go/app/pkg/models/relation" "github.com/fthvgb1/wp-go/app/wpconfig" + "github.com/fthvgb1/wp-go/helper" "github.com/fthvgb1/wp-go/helper/slice" "github.com/fthvgb1/wp-go/model" "strings" @@ -17,7 +19,7 @@ func GetPostsByIds(a ...any) (m map[uint64]models.Posts, err error) { ctx := a[0].(context.Context) m = make(map[uint64]models.Posts) ids := a[1].([]uint64) - rawPosts, err := model.Finds[models.Posts](ctx, model.Conditions( + q := model.Conditions( model.Where(model.SqlBuilder{{"Id", "in", ""}}), model.Join(model.SqlBuilder{ {"a", "left join", "wp_term_relationships b", "a.Id=b.object_id"}, @@ -26,7 +28,11 @@ func GetPostsByIds(a ...any) (m map[uint64]models.Posts, err error) { }), model.Fields("a.*,ifnull(d.name,'') category_name,ifnull(c.term_id,0) terms_id,ifnull(taxonomy,'') `taxonomy`"), model.In(slice.ToAnySlice(ids)), - )) + ) + if helper.GetContextVal(ctx, "getPostAuthor", false) { + q.RelationFn = append(q.RelationFn, model.AddRelationFn(true, false, helper.GetContextVal[*model.QueryCondition](ctx, "postAuthorQueryCondition", nil), relation.PostsWithAuthor)) + } + rawPosts, err := model.Finds[models.Posts](ctx, q) if err != nil { return m, err diff --git a/app/pkg/models/relation/posts.go b/app/pkg/models/relation/posts.go new file mode 100644 index 0000000..07c5ad0 --- /dev/null +++ b/app/pkg/models/relation/posts.go @@ -0,0 +1,23 @@ +package relation + +import ( + "github.com/fthvgb1/wp-go/app/pkg/models" + "github.com/fthvgb1/wp-go/model" +) + +var hasUser = model.RelationHasOne(func(m *models.Posts) uint64 { + return m.PostAuthor +}, func(p *models.Users) uint64 { + return p.Id +}, func(m *models.Posts, p *models.Users) { + m.Author = p +}, model.Relationship{ + RelationType: model.HasOne, + Table: "wp_users user", + ForeignKey: "ID", + Local: "post_author", +}) + +func PostsWithAuthor() (func(any) []any, func(any, any), any, any, model.Relationship) { + return hasUser() +} diff --git a/app/pkg/models/wp_posts.go b/app/pkg/models/wp_posts.go index 06afb68..34d6e41 100644 --- a/app/pkg/models/wp_posts.go +++ b/app/pkg/models/wp_posts.go @@ -40,6 +40,7 @@ type Posts struct { IsSticky bool Thumbnail PostThumbnail AttachmentMetadata WpAttachmentMetadata + Author *Users } type PostThumbnail struct { diff --git a/model/relation.go b/model/relation.go index 6bdb6dd..de4dc1d 100644 --- a/model/relation.go +++ b/model/relation.go @@ -16,6 +16,20 @@ func setTable[T Model](q *QueryCondition) { } } +const ( + HasOne = "hasOne" + HasMany = "hasMany" +) + +// Relationship join table +// +// # RelationType HasOne| HasMany +// +// eg: hasOne, post has a user. ForeignKey is user's id , Local is post's userId field +// +// eg: hasMany, post has many comments,ForeignKey is comment's postId field, Local is post's id field +// +// On is additional join on conditions type Relationship struct { RelationType string Table string @@ -24,7 +38,7 @@ type Relationship struct { On string } -func Relation(isMultiple bool, db dbQuery, ctx context.Context, r any, q *QueryCondition) ([]func(), []func() error) { +func Relation(isPlural bool, db dbQuery, ctx context.Context, r any, q *QueryCondition) ([]func(), []func() error) { var beforeFn []func() var afterFn []func() error for _, f := range q.RelationFn { @@ -72,7 +86,7 @@ func Relation(isMultiple bool, db dbQuery, ctx context.Context, r any, q *QueryC if qq.From == "" { qq.From = ship.Table } - err = ParseRelation(isMultiple || ship.RelationType == "hasMany", db, ctx, helper.Or(isMultiple, rrs, rr), qq) + err = ParseRelation(isPlural || ship.RelationType == HasMany, db, ctx, helper.Or(isPlural, rrs, rr), qq) if err != nil { if err == sql.ErrNoRows { err = nil @@ -80,7 +94,7 @@ func Relation(isMultiple bool, db dbQuery, ctx context.Context, r any, q *QueryC return err } } - assignmentFn(r, helper.Or(isMultiple, rrs, rr)) + assignmentFn(r, helper.Or(isPlural, rrs, rr)) return err }) } @@ -150,16 +164,31 @@ func SetHasMany[T, V any, K comparable](assignmentFn func(*T, *[]V), pIdFn func( } } +// RelationHasOne +// eg: post has a user. fId is post's userId, pId is user's id func RelationHasOne[M, P any, I constraints.Integer | uint64](fId func(*M) I, pId func(*P) I, setVal func(*M, *P), r Relationship) RelationFn { + idFn := GetWithID(fId) + setFn := SetHasOne(setVal, fId, pId) return func() (func(any) []any, func(any, any), any, any, Relationship) { var s P var ss []P - return GetWithID(fId), SetHasOne(setVal, fId, pId), &s, &ss, r + return idFn, setFn, &s, &ss, r } } + +// RelationHasMany +// eg: post has many comments,mId is comment's postId, pId is post's id func RelationHasMany[M, P any, I constraints.Integer | uint64](mId func(*M) I, pId func(*P) I, setVal func(*M, *[]P), r Relationship) RelationFn { + idFn := GetWithID(mId) + setFn := SetHasMany(setVal, mId, pId) return func() (func(any) []any, func(any, any), any, any, Relationship) { var ss []P - return GetWithID(mId), SetHasMany(setVal, mId, pId), &ss, &ss, r + return idFn, setFn, &ss, &ss, r + } +} + +func AddRelationFn(getVal, join bool, q *QueryCondition, r RelationFn) func() (bool, bool, *QueryCondition, RelationFn) { + return func() (bool, bool, *QueryCondition, RelationFn) { + return getVal, join, q, r } } diff --git a/model/relation_test.go b/model/relation_test.go index bead917..618a683 100644 --- a/model/relation_test.go +++ b/model/relation_test.go @@ -17,9 +17,6 @@ func userId(u *user) uint64 { return u.Id } -func metaId(m *models.PostMeta) uint64 { - return m.MetaId -} func metasPostId(m *models.PostMeta) uint64 { return m.PostId } @@ -39,7 +36,7 @@ func PostAuthor() (func(any) []any, func(any, any), any, any, Relationship) { }), &u, &uu, Relationship{ - RelationType: "hasOne", + RelationType: HasOne, Table: "wp_users user", ForeignKey: "ID", Local: "post_author", @@ -56,7 +53,7 @@ func PostMetas() (func(any) []any, func(any, any), any, any, Relationship) { }, func(m *models.PostMeta) uint64 { return m.PostId }), &u, &u, Relationship{ - RelationType: "hasMany", + RelationType: HasMany, Table: "wp_postmeta meta", ForeignKey: "post_id", Local: "ID", @@ -75,7 +72,7 @@ func Meta2() RelationFn { } func PostAuthor2() RelationFn { - return RelationHasOne[post, user](postAuthorId, userId, func(p *post, u *user) { + return RelationHasOne(postAuthorId, userId, func(p *post, u *user) { p.User = u }, Relationship{ RelationType: "hasOne",