You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
196 lines
3.9 KiB
196 lines
3.9 KiB
package model
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"strings"
|
|
|
|
"git.aiterp.net/AiteRP/aitestory/server"
|
|
"git.aiterp.net/gisle/wrouter/generate"
|
|
)
|
|
|
|
// TagTypes are the allowed values for Tag.Type
|
|
var TagTypes = []string{
|
|
"Location",
|
|
"Character",
|
|
"Event",
|
|
"Organization",
|
|
"Source",
|
|
"Series",
|
|
"Meta",
|
|
}
|
|
|
|
// Tag describes a tag
|
|
type Tag struct {
|
|
ID string
|
|
Type string
|
|
Name string
|
|
}
|
|
|
|
// Icon is the API used to get the icon for the tag.
|
|
func (tag Tag) Icon() string {
|
|
return tag.Type[0:1]
|
|
}
|
|
|
|
// CSSCLass gets the CSS class that colors the tag on the
|
|
// page list
|
|
func (tag Tag) CSSCLass() string {
|
|
return fmt.Sprintf("ttype-%s", strings.ToLower(tag.Type))
|
|
}
|
|
|
|
// Insert adds the tag to the database, giving it a new unique ID
|
|
func (tag *Tag) Insert() error {
|
|
db := server.Main.DB
|
|
|
|
// Validate tag type
|
|
if err := tag.Validate(); err != nil {
|
|
return err
|
|
}
|
|
|
|
// Generate an ID if none exists
|
|
if tag.ID == "" {
|
|
tag.ID = generate.ID()
|
|
}
|
|
|
|
// Do the thing
|
|
_, err := db.Exec("INSERT INTO `tag` (id,type,name,disabled) VALUES (?,?,?,false)", tag.ID, tag.Type, tag.Name)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// Update saves the entry for the tag in the database
|
|
func (tag *Tag) Update() error {
|
|
db := server.Main.DB
|
|
|
|
// Validate tag type
|
|
if err := tag.Validate(); err != nil {
|
|
return err
|
|
}
|
|
|
|
// Do the thing
|
|
_, err := db.Exec("UPDATE `tag` SET type=?,name=? WHERE id=?", tag.Type, tag.Name, tag.ID)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// Delete removes a tag from the database
|
|
func (tag *Tag) Delete() error {
|
|
db := server.Main.DB
|
|
|
|
// Do the thing
|
|
results, err := db.Exec("DELETE FROM `tag` WHERE id=? LIMIT 1", tag.ID)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// Count the stuffs that were done things to
|
|
affected, err := results.RowsAffected()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if affected == 0 {
|
|
return errors.New("tag not found")
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// Validate checks the name and type, and returns an error if they're not valid. It's
|
|
// ran by Update and Insert before doing anything
|
|
func (tag *Tag) Validate() error {
|
|
validType := false
|
|
for _, tagType := range TagTypes {
|
|
if tagType == tag.Type {
|
|
validType = true
|
|
break
|
|
}
|
|
}
|
|
if !validType {
|
|
return errors.New("invalid tag type")
|
|
}
|
|
|
|
// Validate tag name
|
|
if len(tag.Name) == 0 || len(tag.Name) > 64 {
|
|
return errors.New("invalid length")
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// Hook returns the url friendly name, which is pretty much just
|
|
// adding underscores to it.
|
|
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) {
|
|
db := server.Main.DB
|
|
|
|
// Make damn sure that – should this take user data as key – it
|
|
// does not open up for a SQL injection attack
|
|
if key != "name" && key != "id" {
|
|
return nil, errors.New("invalid key")
|
|
}
|
|
|
|
rows, err := db.Query("SELECT id,type,name FROM `tag` WHERE "+key+"=? AND disabled=false", id)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer rows.Close()
|
|
if !rows.Next() {
|
|
return nil, errors.New("not found")
|
|
}
|
|
|
|
tag := new(Tag)
|
|
rows.Scan(&tag.ID, &tag.Type, &tag.Name)
|
|
return tag, nil
|
|
}
|
|
|
|
// EnsureTag finds or creates a tag.
|
|
func EnsureTag(tagType, tagName string) (*Tag, error) {
|
|
// Try to find it first
|
|
tag, err := FindTag("name", tagName)
|
|
if err != nil && err.Error() != "not found" { // You saw nothing
|
|
return nil, err
|
|
}
|
|
|
|
// Failing that, make it
|
|
if tag == nil {
|
|
tag = new(Tag)
|
|
tag.Type = tagType
|
|
tag.Name = tagName
|
|
err = tag.Insert()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
|
|
return tag, nil
|
|
}
|
|
|
|
// ListTags finds all the tags, without filter.
|
|
func ListTags() ([]Tag, error) {
|
|
db := server.Main.DB
|
|
|
|
rows, err := db.Query("SELECT id,type,name FROM `tag` WHERE disabled=false")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer rows.Close()
|
|
|
|
results := make([]Tag, 0, 64)
|
|
for rows.Next() {
|
|
tag := Tag{}
|
|
rows.Scan(&tag.ID, &tag.Type, &tag.Name)
|
|
results = append(results, tag)
|
|
}
|
|
|
|
return results, nil
|
|
}
|