// Generates the fulltext field by querying the content, resolving it's foreign keys, then trimming them func generateFulltext(db *mgo.Database, id bson.ObjectId) []string { var res interface{} db.C("contents").Find(m{"_id": id}).One(&res) dat := basic.Convert(res).(map[string]interface{}) fields := map[string]interface{}{ "name": 1, "slug": 1, "title": 1, } resolver.ResolveOne(db, dat, fields) dat = basic.Convert(dat).(map[string]interface{}) non_split := walkDeep(dat) return simpleFulltext(non_split) }
// Queries a draft and rebuilds it. Queries its parent too, and merges it with the input fields saved in "data". // The returned draft will be like a simple draft in the database, but in the data field it will contain fields of the parent plus the fresher saved input data. // draft_typ example: blog_draft // Only func BuildDraft(db *mgo.Database, draft_typ, draft_id_str string) (map[string]interface{}, error) { draft_id := patterns.ToIdWithCare(draft_id_str) q := m{"_id": draft_id} var v interface{} err := db.C(Cname + Draft_collection_postfix).Find(q).One(&v) if err != nil { return nil, err } draft := basic.Convert(v).(map[string]interface{}) typ_i, has_typ := draft["type"] if !has_typ { return nil, fmt.Errorf("Draft has no type.") } typ, is_str := typ_i.(string) if !is_str { return nil, fmt.Errorf("Draft type is not a string.") } if typ != draft_typ { return nil, fmt.Errorf("Draft type is not the expected one: %v instead if %v.", typ, draft_typ) } parent, err := GetParent(db, "contents", draft) if err != nil { return nil, err } draft["data"] = mergeWithParent(draft["data"].(map[string]interface{}), parent) return draft, nil }
func (v *V) Index() error { uni := v.uni visible_types := []string{} types, has := jsonp.GetM(uni.Opt, "Modules.content.types") if !has { return fmt.Errorf("Can't find content types.") } for i, _ := range types { visible_types = append(visible_types, i) } q := m{"type": m{"$in": visible_types}} search_sl, has := uni.Req.Form["search"] if has && len(search_sl[0]) > 0 { q["$and"] = content_model.GenerateQuery(search_sl[0]) uni.Dat["search"] = search_sl[0] } paging_inf := display_model.DoPaging(uni.Db, "contents", q, "page", map[string][]string(uni.Req.Form), uni.P+"?"+uni.Req.URL.RawQuery, 10) var res []interface{} uni.Db.C("contents").Find(q).Sort("-created").Skip(paging_inf.Skip).Limit(10).All(&res) uni.Dat["paging"] = paging_inf res = basic.Convert(res).([]interface{}) content_model.HaveUpToDateDrafts(uni.Db, res) uni.Dat["latest"] = res uni.Dat["_points"] = []string{"content/index"} return nil }
// Called from Front hook. // Find slug value by given key. func FindContent(db *mgo.Database, keys []string, val string) (map[string]interface{}, bool) { query := bson.M{} if len(keys) == 0 { return nil, false } else if len(keys) == 1 { if keys[0] == "_id" && len(val) == 24 { // TODO: check for validity of id. query[keys[0]] = bson.ObjectIdHex(val) } else { query[keys[0]] = val } } else { or := []map[string]interface{}{} for _, v := range keys { if v == "_id" && len(v) == 24 { // TODO: check fir validity of id. or = append(or, map[string]interface{}{v: bson.ObjectIdHex(val)}) } else { or = append(or, map[string]interface{}{v: val}) } } query["$or"] = or } var v interface{} db.C(Cname).Find(query).One(&v) if v == nil { return nil, false } return basic.Convert(v).(map[string]interface{}), true }
// Moves a comment to its final destination (into the valid comments) from moderation queue. func MoveToFinal(db *mgo.Database, comment_id bson.ObjectId) error { var comm interface{} q := m{"_id": comment_id} err := db.C("comments_moderation").Find(q).One(&comm) if err != nil { return err } comment := basic.Convert(comm).(map[string]interface{}) comment["comment_id"] = comment["_id"] delete(comment, "comment_id") content_id := comment["_contents_parent"].(bson.ObjectId) q2 := m{"_id": content_id} upd2 := m{ "$inc": m{ "comment_count": 1, }, "$push": m{ "comments": comment, }, } err = db.C("contents").Update(q2, upd2) if err != nil { return err } upd := m{ "$set": m{ "in_moderation": false, }, } err = db.C("comments").Update(q, upd) if err != nil { return err } return db.C("comments_moderation").Remove(q) }
func (v *V) editContent(typ, id string) (interface{}, error) { uni := v.uni hasid := len(id) > 0 uni.Dat["is_content"] = true var indb interface{} if hasid { uni.Dat["op"] = "update" err := uni.Db.C("contents").Find(m{"_id": bson.ObjectIdHex(id)}).One(&indb) // Ugly. if err != nil { return nil, err } indb = basic.Convert(indb) resolver.ResolveOne(uni.Db, indb, nil) uni.Dat["content"] = indb latest_draft := content_model.GetUpToDateDraft(uni.Db, bson.ObjectIdHex(id), indb.(map[string]interface{})) uni.Dat["latest_draft"] = latest_draft timeline, err := content_model.ContentTimeline(uni.Db, indb.(map[string]interface{})) if err != nil { return nil, err } uni.Dat["timeline"] = timeline } else { uni.Dat["op"] = "insert" } return context.Convert(indb), nil }
// Find version by id. func FindVersion(db *mgo.Database, id bson.ObjectId) (map[string]interface{}, error) { var v interface{} err := db.C("contents_version").Find(m{"_id": id}).One(&v) if err != nil { return nil, err } return basic.Convert(v).(map[string]interface{}), err }
// Finds he user by name password equality. func namePass(db *mgo.Database, name, encoded_pass string) (map[string]interface{}, error) { var v interface{} err := db.C("users").Find(bson.M{"name": name, "password": encoded_pass}).One(&v) if err != nil { return nil, err } return basic.Convert(v).(map[string]interface{}), nil }
func defaultOpts(db *mgo.Database) (map[string]interface{}, error) { // Dohh, a different collection for a single doc, really unmongoish, rewrite. var res interface{} err := db.C("default_opt").Find(nil).One(&res) if err != nil { return nil, err } return basic.Convert(res).(map[string]interface{}), nil }
// c: collection string // q: query map[string]interface{} // p: page number key string This is used to extract the page nubver from get parameters. Also activates paging. // Only works with limit. // sk: skip float64/int Hardcoded value, barely useful (see p instead) // l: limit float64/int // so: sort string Example: "-created" // // TODO: check for validity of type assertions. func RunQueries(db *mgo.Database, queries map[string]interface{}, get map[string][]string, path_n_query string) map[string]interface{} { qs := make(map[string]interface{}) for name, z := range queries { v := z.(map[string]interface{}) _, coll_ok := v["c"] _, quer_ok := v["q"] if !coll_ok || !quer_ok { continue } q := db.C(v["c"].(string)).Find(v["q"]) if skip, skok := v["sk"]; skok { q.Skip(toInt(skip)) } if limit, lok := v["l"]; lok { q.Limit(toInt(limit)) } if sort, sook := v["so"]; sook { if sort_string, is_str := sort.(string); is_str { q.Sort(sort_string) } else if sort_slice, is_sl := sort.([]interface{}); is_sl { q.Sort(jsonp.ToStringSlice(sort_slice)...) } } if p, pok := v["p"]; pok { if limit, lok := v["l"]; lok { // Only makes sense with limit. paging_inf := DoPaging(db, v["c"].(string), v["q"].(map[string]interface{}), p.(string), get, path_n_query, toInt(limit)) qs[name+"_navi"] = paging_inf q.Skip(paging_inf.Skip) } } var res []interface{} err := q.All(&res) if err != nil { qs[name] = err.Error() continue } res = basic.Convert(res).([]interface{}) if ex, ex_ok := v["ex"]; ex_ok { ex_m, ex_is_m := ex.(map[string]interface{}) if ex_is_m && len(ex_m) == 1 { CreateExcerpts(res, ex_m) } } var resolve_fields map[string]interface{} if val, has := v["r"]; has { resolve_fields = val.(map[string]interface{}) } else { resolve_fields = map[string]interface{}{"password": 0} } resolver.ResolveAll(db, res, resolve_fields) qs[name] = res } return qs }
// returns nil if not found func find(db *mgo.Database, content_id string) map[string]interface{} { content_bsonid := basic.ToIdWithCare(content_id) q := bson.M{ "_id": content_bsonid, } var v interface{} err := db.C("contents").Find(q).One(&v) if err != nil { return nil } return basic.Convert(v).(map[string]interface{}) }
// Finds a doc by query. func FindQ(db *mgo.Database, coll string, query map[string]interface{}) (map[string]interface{}, error) { id, has := query["_id"] if has { query["_id"] = ToIdWithCare(id) } var res interface{} err := db.C(coll).Find(query).One(&res) if err != nil { return nil, err } doc := basic.Convert(res.(bson.M)).(map[string]interface{}) return doc, nil }
func FieldStartsWith(db *mgo.Database, collname, fieldname, val string) ([]interface{}, error) { var res []interface{} q := m{fieldname: bson.RegEx{"^" + val, "u"}} err := db.C(collname).Find(q).All(&res) if err != nil { return nil, err } if res == nil { return nil, fmt.Errorf("Can't find %v starting with %v.", fieldname, val) } res = basic.Convert(res).([]interface{}) return res, nil }
// Returns the type of a given content. func TypeOf(db *mgo.Database, content_id bson.ObjectId) (string, error) { var v interface{} q := m{"_id": content_id} err := db.C("contents").Find(q).One(&v) if err != nil { return "", err } con := basic.Convert(v.(bson.M)).(map[string]interface{}) typ, has := con["type"] if !has { return "", fmt.Errorf("Content is malformed: has no type.") } return typ.(string), nil }
// See *1 below. func FindChildren(db *mgo.Database, children_coll, parent_fk_field string, parent_id bson.ObjectId, additional_query map[string]interface{}) ([]interface{}, error) { q := map[string]interface{}{} if additional_query != nil { q = additional_query } q[parent_fk_field] = parent_id var children []interface{} err := db.C(children_coll).Find(q).All(&children) if err != nil { return nil, err } if children == nil { return nil, fmt.Errorf("Can't find children.") } children = basic.Convert(children).([]interface{}) return children, nil }
// Creates slugs from the tagnames, queries all tags which exists in the database with those slugs. // Returns the ids of the existing tags, and returns all tagnames which is not in the database. func separateTags(db *mgo.Database, tagnames []string) ([]bson.ObjectId, []string) { var i []interface{} slugs := []string{} for _, val := range tagnames { slug := slugify.S(val) slugs = append(slugs, slug) } db.C(Tag_cname).Find(m{"slug": m{"$in": slugs}}).Limit(0).All(&i) ret_ids := []bson.ObjectId{} contains := createM(slugs, tagnames) i = basic.Convert(i).([]interface{}) for _, v := range i { val := v.(map[string]interface{}) ret_ids = append(ret_ids, val["_id"].(bson.ObjectId)) delete(contains, val["slug"].(string)) } return ret_ids, mToSSlice(contains) }
// Lists contents of a givn type. func (v *V) Type() error { uni := v.uni typ := uni.Req.Form["type"][0] q := m{"type": typ} search_sl, has := uni.Req.Form["search"] if has && len(search_sl[0]) > 0 { q["$and"] = content_model.GenerateQuery(search_sl[0]) uni.Dat["search"] = search_sl[0] } paging_inf := display_model.DoPaging(uni.Db, "contents", q, "page", map[string][]string(uni.Req.Form), uni.P+"?"+uni.Req.URL.RawQuery, 10) var res []interface{} uni.Db.C("contents").Find(q).Sort("-created").Skip(paging_inf.Skip).Limit(10).All(&res) uni.Dat["paging"] = paging_inf res = basic.Convert(res).([]interface{}) content_model.HaveUpToDateDrafts(uni.Db, res) uni.Dat["type"] = typ uni.Dat["latest"] = res return nil }
// Takes a draft and gets. func GetParent(db *mgo.Database, coll string, draft map[string]interface{}) (map[string]interface{}, error) { version_parent, has_vp := draft["draft_of_version"] _, has_draft_of := draft["draft_of"] // If a draft is a draft of an existing content, than it must have a parent version. if !has_vp && has_draft_of { return nil, fmt.Errorf("State of draft is inconsistent, parent version is not set.") } // Simply the draft is not connected to anything saved. if !has_vp { // && !has_draft_of return nil, nil } var par interface{} parent_id := version_parent.(bson.ObjectId) q := m{"_id": parent_id} err := db.C(Cname + "_version").Find(q).One(&par) if err != nil { return nil, err } return basic.Convert(par).(map[string]interface{}), nil }
func findComment(db *mgo.Database, content_id, comment_id string) (map[string]interface{}, error) { var v interface{} q := bson.M{ "_id": bson.ObjectIdHex(content_id), //"comments.comment_id": bson.ObjectIdHex(comment_id), } find_err := db.C("contents").Find(q).One(&v) if find_err != nil { return nil, find_err } if v == nil { return nil, fmt.Errorf("Can't find content with id %v.", content_id) } v = basic.Convert(v) comments_i, has := v.(map[string]interface{})["comments"] if !has { return nil, fmt.Errorf("No comments in given content.") } comments, ok := comments_i.([]interface{}) if !ok { return nil, fmt.Errorf("comments member is not a slice in content %v", content_id) } // TODO: there must be a better way. for _, v_i := range comments { v, is_map := v_i.(map[string]interface{}) if !is_map { continue } if val_i, has := v["comment_id"]; has { if val_id, ok := val_i.(bson.ObjectId); ok { if val_id.Hex() == comment_id { return v, nil } } } } return nil, fmt.Errorf("Comment not found.") }