diff options
author | Kevin Keuning <kkeuning@gmail.com> | 2017-03-02 12:48:17 -0600 |
---|---|---|
committer | Kevin Keuning <kkeuning@gmail.com> | 2017-03-02 12:48:17 -0600 |
commit | 6358ca512c227b8f035401b57543e0190c635e8d (patch) | |
tree | c48b2ea31d4125c1783a3ccf47a3972e3479c219 /system/db/content.go | |
parent | a7db36aa56c1998bc56d593a38f2a1640a9298a0 (diff) |
added UpdateContent for merge behavior on api updates, extended Hookable
Diffstat (limited to 'system/db/content.go')
-rw-r--r-- | system/db/content.go | 92 |
1 files changed, 92 insertions, 0 deletions
diff --git a/system/db/content.go b/system/db/content.go index d9096ae..81abd4f 100644 --- a/system/db/content.go +++ b/system/db/content.go @@ -36,6 +36,98 @@ func SetContent(target string, data url.Values) (int, error) { return update(ns, id, data) } +// UpdateContent inserts or updates values in the database. +// Updated content will be merged into existing values from the database. +// The `target` argument is a string made up of namespace:id (string:int) +func UpdateContent(target string, data url.Values) (int, error) { + t := strings.Split(target, ":") + ns, id := t[0], t[1] + + // check if content id == -1 (indicating new post). + // if so, run an insert which will assign the next auto incremented int. + // this is done because boltdb begins its bucket auto increment value at 0, + // which is the zero-value of an int in the Item struct field for ID. + // this is a problem when the original first post (with auto ID = 0) gets + // overwritten by any new post, originally having no ID, defauting to 0. + if id == "-1" { + return insert(ns, data) + } + + // retrieve existing content from the database + existingContent, err := Content(target) + if err != nil { + return 0, err + } + + // Unmarsal the existing values + s := item.Types[ns]() + + err = json.Unmarshal(existingContent, &s) + if err != nil { + log.Println("Error decoding json while sorting", ns, ":", err) + return 0, err + } + + var specifier string // i.e. __pending, __sorted, etc. + if strings.Contains(ns, "__") { + spec := strings.Split(ns, "__") + ns = spec[0] + specifier = "__" + spec[1] + } + + cid, err := strconv.Atoi(id) + if err != nil { + return 0, err + } + + // Don't allow the Item fields to be updated from form values + data.Del("id") + data.Del("uuid") + data.Del("slug") + + dec := schema.NewDecoder() + dec.SetAliasTag("json") // allows simpler struct tagging when creating a content type + dec.IgnoreUnknownKeys(true) // will skip over form values submitted, but not in struct + err = dec.Decode(s, data) + if err != nil { + return 0, err + } + + j, err := json.Marshal(s) + if err != nil { + return 0, err + } + + err = store.Update(func(tx *bolt.Tx) error { + b, err := tx.CreateBucketIfNotExists([]byte(ns + specifier)) + if err != nil { + return err + } + + err = b.Put([]byte(fmt.Sprintf("%d", cid)), j) + if err != nil { + return err + } + + return nil + }) + if err != nil { + return 0, nil + } + + if specifier == "" { + go SortContent(ns) + } + + // update changes data, so invalidate client caching + err = InvalidateCache() + if err != nil { + return 0, err + } + + return cid, nil +} + func update(ns, id string, data url.Values) (int, error) { var specifier string // i.e. __pending, __sorted, etc. if strings.Contains(ns, "__") { |