// Fork current private template into an other private one. // Copies the whole directory from /templates/private/{host}/{current_template} to /templates/private/{host}/{inp:new_private_name} func ForkPrivate(db *mgo.Database, opt map[string]interface{}, inp map[string][]string, root, host string) error { if scut.TemplateType(opt) != "private" { return fmt.Errorf("Your current template is not a private one.") // Kinda unsensical error message but ok... } rule := map[string]interface{}{ "new_template_name": "must", } dat, e_err := extract.New(rule).Extract(inp) if e_err != nil { return e_err } new_template_name := dat["new_template_name"].(string) to := filepath.Join(root, "templates", "private", host, new_template_name) e, e_err := Exists(to) if e_err != nil { return fmt.Errorf("Can't determine if private template exists.") } if e { return fmt.Errorf("Private template named %v already exists.", new_template_name) } from := filepath.Join(root, "templates", "private", host, scut.TemplateName(opt)) copy_err := copyrecur.CopyDir(from, to) if copy_err != nil { return fmt.Errorf("There was an error while copying.") } id := basic.CreateOptCopy(db) q := m{"_id": id} upd := m{ "$set": m{ "Template": new_template_name, }, } return db.C("options").Update(q, upd) }
// Publish a private template, so others can use it too. // Copies the whole directory of /templates/private/{host}/{current_template} to /templates/public/{input:public_name} // Fails if a public template with the chosen name already exists. func PublishPrivate(db *mgo.Database, opt map[string]interface{}, inp map[string][]string, root, host string) error { if scut.TemplateType(opt) == "public" { return fmt.Errorf("You can't publish your current template, because it is already public.") } rule := map[string]interface{}{ "public_name": map[string]interface{}{ "must": 1, "type": "string", "min": 2, }, } dat, ex_err := extract.New(rule).Extract(inp) if ex_err != nil { return ex_err } public_name := dat["public_name"].(string) from := filepath.Join(root, "templates", "private", host, scut.TemplateName(opt)) to := filepath.Join(root, "templates", "public", public_name) // copyrecur.CopyDir checks for existence too, but for safety reasons we check here in case copyrecur semantics change. exis, exis_err := Exists(to) if exis { return fmt.Errorf("Public template with name " + public_name + " already exists.") } if exis_err != nil { return exis_err } copy_err := copyrecur.CopyDir(from, to) if copy_err != nil { return fmt.Errorf("There was an error while copying.") } return nil }
func (v *V) view(current bool, filepath_str string) map[string]interface{} { uni := v.uni opt := uni.Opt root := uni.Root host := uni.Req.Host typ := scut.TemplateType(uni.Opt) name := scut.TemplateName(uni.Opt) ret := map[string]interface{}{} tpath, path_err := threePath(host, typ, name) if path_err != nil { ret["error"] = path_err return ret } ret["template_name"] = name ret["breadcrumb"] = te_model.CreateBreadCrumb(strings.Split(filepath_str, "/")) ret["can_modify"] = canMod(typ) ret["current"] = current ret["typ"] = typ if typ == "mod" { ret["is_mod"] = true } ret["filepath"] = filepath.Join(tpath, filepath_str) ret["raw_path"] = filepath_str if te_model.IsDir(filepath_str) { fileinfos, read_err := ioutil.ReadDir(filepath.Join(root, tpath, filepath_str)) if read_err != nil { ret["error"] = read_err.Error() return ret } ret["dir"] = fileinfos ret["is_dir"] = true } else { file_b, read_err := ioutil.ReadFile(filepath.Join(root, tpath, filepath_str)) if read_err != nil { ret["error"] = "Can't find specified file." return ret } if len(file_b) == 0 { ret["file"] = "[Empty file.]" // A temporary hack, because the codemirror editor is not displayed when editing an empty file. It is definitely a client-side javascript problem. } else { ret["included"] = te_model.ReqLinks(opt, string(file_b), root, host) ret["file"] = string(file_b) } } return ret }
// Tries to dislay a template file. func DisplayTemplate(uni *context.Uni, filep string) error { _, src := uni.Req.Form["src"] file, err := require.R("", filep+".tpl", func(root, fi string) ([]byte, error) { return GetFileAndConvert(uni.Root, fi, uni.Opt, uni.Req.Host, nil) }) if err != nil { return fmt.Errorf("Cant find template file %v.", filep) } if src { uni.Put(string(file)) return nil } uni.Dat["_tpl"] = "/templates/" + scut.TemplateType(uni.Opt) + "/" + scut.TemplateName(uni.Opt) + "/" prepareAndExec(uni, string(file)) return nil }
// Delete a whole private template. func DeletePrivate(opt map[string]interface{}, inp map[string][]string, root, host string) error { rule := map[string]interface{}{ "template_name": "must", } dat, e_err := extract.New(rule).Extract(inp) if e_err != nil { return e_err } template_name := dat["template_name"].(string) if template_name == scut.TemplateName(opt) { return fmt.Errorf("For safety reasons you can only delete private templates not in use.") } full_p := filepath.Join(root, "templates", "private", host, template_name) err := os.RemoveAll(full_p) if err != nil { return fmt.Errorf("Can't delete private template named %v. It probably does not exist.", template_name) } return nil }
// Forks a public template into a private one: creates a deep recursive copy of the whole directory tree, so the user // can edit his own template files as he wishes. func ForkPublic(db *mgo.Database, opt map[string]interface{}, root, host string) error { if CanModifyTemplate(opt) { return fmt.Errorf("Template is already private.") } from := filepath.Join(root, scut.GetTPath(opt, host)) to := filepath.Join(root, "templates", "private", host, scut.TemplateName(opt)) copy_err := copyrecur.CopyDir(from, to) if copy_err != nil { // && copy_err.Error() != "Destination already exists" return copy_err } id := basic.CreateOptCopy(db) q := m{"_id": id} upd := m{ "$set": m{ "TplIsPrivate": true, }, } return db.C("options").Update(q, upd) }
// Extracts all requires ( {{require example.t}} ) from a given file. // Takes into account fallback files too. // First it checks if the file exists in the current template. If yes, the link will point to that file. // If not, then the link will point to the fallback module file. // TODO: Case when the required file does not exists anywhere is not handled. func ReqLinks(opt map[string]interface{}, file, root, host string) []ReqLink { pos := require.RequirePositions(file) ret := []ReqLink{} for _, v := range pos { fi := file[v[0]+10 : v[1]-2] // cut {{require anything/anything.t}} => anything/anything.t var typ, path, name string exists_in_template, err := Exists(filepath.Join(root, scut.GetTPath(opt, host), fi)) if err != nil { continue } if exists_in_template { typ = scut.TemplateType(opt) path = fi name = scut.TemplateName(opt) } else { path = scut.GetModTPath(fi)[1] typ = "mod" name = strings.Split(fi, "/")[0] } rl := ReqLink{typ, name, path} ret = append(ret, rl) } return ret }
func (v *V) Index() error { uni := v.uni uni.Dat["template_name"] = scut.TemplateName(uni.Opt) uni.Dat["can_modify"] = te_model.CanModifyTemplate(uni.Opt) return nil }