diff --git a/controllers/listcontroller.go b/controllers/listcontroller.go
index cc67b94..ad59367 100644
--- a/controllers/listcontroller.go
+++ b/controllers/listcontroller.go
@@ -52,7 +52,7 @@ func listFiltered(category model.PageCategory) wrouter.FunctionHandlerFunc {
vm := viewmodel.PageList{}
if tagName != "" {
- tag, err := model.FindTag("name", tagName)
+ tag, err := model.FindTag("name", tagName, "")
if err != nil {
response.Text(w, 404, err.Error())
return true
@@ -79,11 +79,53 @@ func listFiltered(category model.PageCategory) wrouter.FunctionHandlerFunc {
}
}
+func listTagged(tagType string) wrouter.FunctionHandlerFunc {
+ return func(path string, w http.ResponseWriter, req *http.Request, user *auth.User) bool {
+ var err error
+
+ if req.Method != "GET" || strings.LastIndex(req.URL.Path, "/") >= len(path) {
+ return false
+ }
+
+ tagName := strings.Replace(req.URL.Path[len(path):], "_", " ", -1)
+
+ vm := viewmodel.PageList{}
+
+ if tagName == "" {
+ return false
+ }
+
+ tag, err := model.FindTag("name", tagName, tagType)
+ if err != nil {
+ response.Text(w, 404, err.Error())
+ return true
+ }
+
+ vm.ActiveTag = *tag
+ vm.Headers, err = model.ListHeadersByTag("", tag)
+
+ vm.Categories = model.PageCategories
+ vm.Setup(user)
+
+ if err != nil {
+ response.Text(w, 500, err.Error())
+ return true
+ }
+
+ view.Render(w, "index", 200, vm)
+
+ return true
+ }
+}
+
func init() {
ListController.Function("/", listIndex)
- ListController.Function("/", listFiltered(model.PageCategory{Key: ""}))
for _, category := range model.PageCategories {
ListController.Function(fmt.Sprintf("/%s/", strings.ToLower(category.Plural)), listFiltered(category))
}
+
+ for _, tagType := range model.TagTypes {
+ ListController.Function(fmt.Sprintf("/%s/", strings.ToLower(tagType)), listTagged(tagType))
+ }
}
diff --git a/controllers/tagcontroller.go b/controllers/tagcontroller.go
new file mode 100644
index 0000000..3c68132
--- /dev/null
+++ b/controllers/tagcontroller.go
@@ -0,0 +1,34 @@
+package controllers
+
+import (
+ "net/http"
+
+ "git.aiterp.net/AiteRP/aitestory/view"
+ "git.aiterp.net/AiteRP/aitestory/viewmodel"
+
+ "git.aiterp.net/AiteRP/aitestory/model"
+ "git.aiterp.net/gisle/wrouter"
+ "git.aiterp.net/gisle/wrouter/auth"
+)
+
+// TagController serves and handles the tag managment pages
+var TagController = wrouter.Router{}
+
+func tagList(path string, w http.ResponseWriter, req *http.Request, user *auth.User) bool {
+ //var err error
+ if (req.Method != "GET" && req.Method != "POST") || len(req.URL.Path) > len(path) {
+ return false
+ }
+
+ tl := viewmodel.TagList{}
+ tl.Tags, _ = model.ListTags()
+ tl.Setup(user)
+
+ view.Render(w, "tags/list", 200, tl)
+
+ return true
+}
+
+func init() {
+ TagController.Function("/", tagList)
+}
diff --git a/main.go b/main.go
index bee08d7..597d0f7 100644
--- a/main.go
+++ b/main.go
@@ -10,6 +10,7 @@ func main() {
auth.Register(&controllers.WikiAthenticator{})
router.Mount("/user", &controllers.UserController)
router.Mount("/page", &controllers.PageController)
+ router.Mount("/tags", &controllers.TagController)
router.Mount("/", &controllers.ListController)
router.Static("/ui/", server.Main.Config.Directories.UI)
diff --git a/model/tag.go b/model/tag.go
index a95dc41..e4e959d 100644
--- a/model/tag.go
+++ b/model/tag.go
@@ -129,8 +129,9 @@ func (tag Tag) Hook() string {
return strings.Replace(tag.Name, " ", "_", -1)
}
-// FindTag finds a tag by ID
-func FindTag(key string, id string) (*Tag, error) {
+// FindTag finds a tag by ID. Leave tagtype blank to ignore it. Both key and
+// id are checked against their respective lists to prevent SQL injection attacks.
+func FindTag(key string, id string, tagType string) (*Tag, error) {
db := server.Main.DB
// Make damn sure that – should this take user data as key – it
@@ -139,7 +140,24 @@ func FindTag(key string, id string) (*Tag, error) {
return nil, errors.New("invalid key")
}
- rows, err := db.Query("SELECT id,type,name FROM `tag` WHERE "+key+"=? AND disabled=false", id)
+ query := "SELECT id,type,name FROM `tag` WHERE " + key + "=? AND disabled=false"
+ if tagType != "" {
+ // Prevent more shenanigans
+ found := false
+ for _, existing := range TagTypes {
+ if existing == tagType {
+ found = true
+ break
+ }
+ }
+ if !found {
+ return nil, errors.New("invalid tag type")
+ }
+
+ query += fmt.Sprintf(` AND type="%s"`, tagType)
+ }
+
+ rows, err := db.Query(query, id)
if err != nil {
return nil, err
}
@@ -156,7 +174,7 @@ func FindTag(key string, id string) (*Tag, error) {
// EnsureTag finds or creates a tag.
func EnsureTag(tagType, tagName string) (*Tag, error) {
// Try to find it first
- tag, err := FindTag("name", tagName)
+ tag, err := FindTag("name", tagName, tagType)
if err != nil && err.Error() != "not found" { // You saw nothing
return nil, err
}
@@ -179,7 +197,15 @@ func EnsureTag(tagType, tagName string) (*Tag, error) {
func ListTags() ([]Tag, error) {
db := server.Main.DB
- rows, err := db.Query("SELECT id,type,name FROM `tag` WHERE disabled=false")
+ query := `
+ SELECT id,type,name,count(pt.page_id) FROM tag
+ LEFT JOIN page_tag AS pt ON (pt.tag_id = tag.id)
+ WHERE disabled=false
+ GROUP BY pt.tag_id
+ ORDER BY type,name
+ `
+
+ rows, err := db.Query(query)
if err != nil {
return nil, err
}
@@ -187,9 +213,14 @@ func ListTags() ([]Tag, error) {
results := make([]Tag, 0, 64)
for rows.Next() {
+ count := 0
tag := Tag{}
- rows.Scan(&tag.ID, &tag.Type, &tag.Name)
- results = append(results, tag)
+ rows.Scan(&tag.ID, &tag.Type, &tag.Name, &count)
+
+ // Let's pretend unused tags don't exist. >_>
+ if count > 0 {
+ results = append(results, tag)
+ }
}
return results, nil
diff --git a/view/renderer.go b/view/renderer.go
index 558002a..a0f14cd 100644
--- a/view/renderer.go
+++ b/view/renderer.go
@@ -83,4 +83,5 @@ func init() {
Register("page/edit", "base/default")
Register("page/view", "base/default")
Register("page/delete", "base/default")
+ Register("tags/list", "base/default")
}
diff --git a/view/templates/base/default.tmpl b/view/templates/base/default.tmpl
index b585202..10027cb 100644
--- a/view/templates/base/default.tmpl
+++ b/view/templates/base/default.tmpl
@@ -17,7 +17,7 @@
-
+
diff --git a/view/templates/index.tmpl b/view/templates/index.tmpl
index d3f7b23..f6bfe3e 100644
--- a/view/templates/index.tmpl
+++ b/view/templates/index.tmpl
@@ -30,7 +30,7 @@
@@ -40,6 +40,10 @@
{{ end }}
+
+
{{ if $.User.LoggedIn }}