package api
import (
"context"
"encoding/json"
"errors"
"fmt"
"html/template"
"io/ioutil"
"net/http"
)
var (
ErrNoContent = errors.New("no content found for query")
)
type API struct {
user, pass string
space int
baseURL string
client *http.Client
}
type Content struct {
ContentID string
ContentParentTypeID string
ContentValues []ContentValue
valueMap map[string]ContentValue
}
func (c *Content) Val(key string) (string, bool) {
val, ok := c.valueMap[key]
if !ok {
return "", false
}
return val.FieldValue, true
}
func (c *Content) HTML(key string) (template.HTML, bool) {
val, ok := c.valueMap[key]
if !ok {
return template.HTML(""), false
}
return template.HTML(val.FieldValue), true
}
func (c *Content) Ref(key string) (*Content, bool) {
val, ok := c.valueMap[key]
if !ok || val.FieldReference == nil {
return nil, false
}
ref := transform(*val.FieldReference)
return &ref, true
}
func (c *Content) List(key string) ([]Content, bool) {
val, ok := c.valueMap[key]
if !ok || val.FieldReferenceList == nil {
return nil, false
}
var list []Content
for _, item := range val.FieldReferenceList {
list = append(list, transform(item))
}
return list, true
}
type ContentMust struct {
c Content
}
func (c *Content) Must() ContentMust {
return ContentMust{Content{c.ContentID, c.ContentParentTypeID, c.ContentValues, c.valueMap}}
}
func (cm ContentMust) Val(key string) string {
val, _ := cm.c.Val(key)
return val
}
func (cm ContentMust) Ref(key string) *Content {
val, _ := cm.c.Ref(key)
return val
}
func (cm ContentMust) List(key string) []Content {
val, _ := cm.c.List(key)
return val
}
type ContentList struct {
ContentList []Content
ContentMore bool
}
type ContentValue struct {
FieldID string
FieldType string
FieldName string
FieldValue string
FieldReference *Content
FieldReferenceList []Content
}
func New(user, pass, baseURL string, space int) API {
return NewWithClient(user, pass, baseURL, space, http.DefaultClient)
}
func NewWithClient(user, pass, baseURL string, space int, client *http.Client) API {
return API{
user: user,
pass: pass,
space: space,
baseURL: baseURL,
client: client,
}
}
func (cms API) List(ctx context.Context, typeID int, order, field string) ([]Content, error) {
var (
url = fmt.Sprintf("%s/contenttype/%d/%d?order=%s&field=%s", cms.baseURL, cms.space, typeID, order, field)
body struct{ ContentList ContentList }
)
req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
if err != nil {
return nil, err
}
req.SetBasicAuth(cms.user, cms.pass)
resp, err := cms.client.Do(req)
if err != nil {
return nil, err
}
defer resp.Body.Close()
bytes, err := ioutil.ReadAll(resp.Body)
if err != nil {
return nil, err
}
if err := json.Unmarshal(bytes, &body); err != nil {
return nil, err
}
return transformList(body.ContentList.ContentList), nil
}
func (cms API) Find(ctx context.Context, typeID int, field, query string) (*Content, error) {
var (
url = fmt.Sprintf("%s/content/search?space=%d&contenttype=%d&field=%s&query=%s", cms.baseURL, cms.space, typeID, field, query)
body ContentList
)
req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
if err != nil {
return nil, err
}
req.SetBasicAuth(cms.user, cms.pass)
resp, err := cms.client.Do(req)
if err != nil {
return nil, err
}
defer resp.Body.Close()
bytes, err := ioutil.ReadAll(resp.Body)
if err != nil {
return nil, err
}
if err := json.Unmarshal(bytes, &body); err != nil {
return nil, err
}
if len(body.ContentList) < 1 {
return nil, ErrNoContent
}
c := transform(body.ContentList[0])
return &c, nil
}
func transformList(in []Content) []Content {
for i, c := range in {
in[i] = transform(c)
}
return in
}
func transform(in Content) Content {
in.valueMap = make(map[string]ContentValue)
for _, val := range in.ContentValues {
in.valueMap[val.FieldName] = val
}
return in
}