diff options
Diffstat (limited to 'system/db/content.go')
-rw-r--r-- | system/db/content.go | 114 |
1 files changed, 108 insertions, 6 deletions
diff --git a/system/db/content.go b/system/db/content.go index 19c31d7..87b3e69 100644 --- a/system/db/content.go +++ b/system/db/content.go @@ -118,6 +118,11 @@ func insert(ns string, data url.Values) (int, error) { uid := uuid.NewV4() data.Set("uuid", uid.String()) + // if type has a specifier, add it to data for downstream processing + if specifier != "" { + data.Set("__specifier", specifier) + } + j, err := postToJSON(ns, data) if err != nil { return err @@ -128,6 +133,17 @@ func insert(ns string, data url.Values) (int, error) { return err } + // store the slug,type:id in contentIndex if public content + if specifier == "" { + ci := tx.Bucket([]byte("__contentIndex")) + k := []byte(data.Get("slug")) + v := []byte(fmt.Sprintf("%s:%d", ns, effectedID)) + err := ci.Put(k, v) + if err != nil { + return err + } + } + return nil }) if err != nil { @@ -149,12 +165,25 @@ func insert(ns string, data url.Values) (int, error) { // DeleteContent removes an item from the database. Deleting a non-existent item // will return a nil error. -func DeleteContent(target string) error { +func DeleteContent(target string, data url.Values) error { t := strings.Split(target, ":") ns, id := t[0], t[1] err := store.Update(func(tx *bolt.Tx) error { - tx.Bucket([]byte(ns)).Delete([]byte(id)) + err := tx.Bucket([]byte(ns)).Delete([]byte(id)) + if err != nil { + return err + } + + // if content has a slug, also delete it from __contentIndex + slug := data.Get("slug") + if slug != "" { + err := tx.Bucket([]byte("__contentIndex")).Delete([]byte(slug)) + if err != nil { + return err + } + } + return nil }) if err != nil { @@ -200,6 +229,41 @@ func Content(target string) ([]byte, error) { return val.Bytes(), nil } +// ContentBySlug does a lookup in the content index to find the type and id of +// the requested content. Subsequently, issues the lookup in the type bucket and +// returns the data at that ID or nil if nothing exists. +func ContentBySlug(slug string) ([]byte, error) { + val := &bytes.Buffer{} + err := store.View(func(tx *bolt.Tx) error { + var t, id string + b := tx.Bucket([]byte("__contentIndex")) + idx := b.Get([]byte(slug)) + + if idx != nil { + tid := strings.Split(string(idx), ":") + + if len(tid) < 2 { + return fmt.Errorf("Bad data in content index for slug: %s", slug) + } + + t, id = tid[0], tid[1] + } + + c := tx.Bucket([]byte(t)) + _, err := val.Write(c.Get([]byte(id))) + if err != nil { + return err + } + + return nil + }) + if err != nil { + return nil, err + } + + return val.Bytes(), nil +} + // ContentAll retrives all items from the database within the provided namespace func ContentAll(namespace string) [][]byte { var posts [][]byte @@ -435,11 +499,22 @@ func postToJSON(ns string, data url.Values) ([]byte, error) { return nil, err } - slug, err := manager.Slug(post.(content.Identifiable)) - if err != nil { - return nil, err + // if the content has no slug, and has no specifier, create a slug, check it + // for duplicates, and add it to our values + if data.Get("slug") == "" && data.Get("__specifier") == "" { + slug, err := manager.Slug(post.(content.Identifiable)) + if err != nil { + return nil, err + } + + slug, err = checkSlugForDuplicate(slug) + if err != nil { + return nil, err + } + + post.(content.Sluggable).SetSlug(slug) + data.Set("slug", slug) } - post.(content.Sluggable).SetSlug(slug) // marshall content struct to json for db storage j, err := json.Marshal(post) @@ -449,3 +524,30 @@ func postToJSON(ns string, data url.Values) ([]byte, error) { return j, nil } + +func checkSlugForDuplicate(slug string) (string, error) { + // check for existing slug in __contentIndex + err := store.View(func(tx *bolt.Tx) error { + b := tx.Bucket([]byte("__contentIndex")) + original := slug + exists := true + i := 0 + for exists { + s := b.Get([]byte(slug)) + if s == nil { + exists = false + return nil + } + + i++ + slug = fmt.Sprintf("%s-%d", original, i) + } + + return nil + }) + if err != nil { + return "", err + } + + return slug, nil +} |