transmet/categories/categories.go

142 lines
3.5 KiB
Go

package categories
import (
"database/sql"
"errors"
"fmt"
_ "github.com/lib/pq"
"strings"
)
type Category struct {
Id int
Name string
Parent sql.NullInt64
Children []*Category
}
var CategoriesTree []*Category = nil
var CategoriesFlat map[int]*Category = nil
// Cavet: slight cheat. All parents must have Category_id < their children.
func LoadCategories(db *sql.DB) {
if CategoriesFlat != nil {
return //already loaded
}
CategoriesTree = []*Category{}
CategoriesFlat = make(map[int]*Category)
rows, err := db.Query("select categories.id, categories.name, categories.parent_id from categories order by coalesce(parent_id, id), parent_id is not null")
if err != nil {
fmt.Println("DB Error loading Categories:", err)
return
}
defer rows.Close()
for rows.Next() {
category := &Category{Children: []*Category{}}
err = rows.Scan(&category.Id, &category.Name, &category.Parent)
if err != nil {
fmt.Println("Categories DB Error: ", err)
}
CategoriesFlat[category.Id] = category
if category.Parent.Valid {
pid := int(category.Parent.Int64)
CategoriesFlat[pid].Children = append(CategoriesFlat[pid].Children, category)
} else {
CategoriesTree = append(CategoriesTree, category)
}
}
}
func Add(db *sql.DB, name string, parent int) error {
var err error
if parent < 0 {
_, err = db.Exec("INSERT INTO categories (name) VALUES ($1)", name)
} else {
_, err = db.Exec("INSERT INTO categories (name, parent_id) VALUES ($1, $2)", name, parent)
}
if err != nil {
fmt.Println("Categories DB Error Add(): ", err)
}
return err
}
// Get parent id
// Set parent of children to parent
// set category of news to parent
// finallly delete
func Delete(db *sql.DB, id int) error {
rows, err := db.Query("SELECT parent_id FROM categories WHERE id=$1", id)
if err != nil {
fmt.Println("Categories DB Error loading category parent id: ", err)
return err
}
if !rows.Next() {
fmt.Println("Categories DB Error loading category parent id: no category")
return errors.New("No category")
}
var parent_id sql.NullInt64
err = rows.Scan(&parent_id)
_, err = db.Exec("UPDATE categories SET parent_id =$2 WHERE parent_id=$1", id, parent_id)
if err != nil {
fmt.Println("Categories DB error changing child parent: ", err)
return err
}
_, err = db.Exec("UPDATE news SET category_id =$2 WHERE category_id=$1", id, parent_id)
if err != nil {
fmt.Println("Categories DB error changing category of news: ", err)
return err
}
_, err = db.Exec("DELETE FROM categories WHERE id=$1", id)
if err != nil {
fmt.Println("Categories DB Error Delete(): ", err)
}
return err
}
func GetListOfChildrenIds(id int) []int {
list := []int{id}
for _,category := range CategoriesFlat[id].Children {
list = append(list, GetListOfChildrenIds(category.Id)...)
}
return list
}
func (category *Category) ChangeParent(db *sql.DB, parent *Category) error {
var err error
if parent == nil {
_, err = db.Exec("UPDATE categories SET parent_id = NULL WHERE id = $1", category.Id)
} else {
_, err = db.Exec("UPDATE categories SET parent_id = $2 WHERE id = $1", category.Id, parent.Id)
}
if err != nil {
fmt.Println("Categories DB Error: ", err)
}
return err
}
// get the number of parents a category has
func (category *Category) Depth() int {
depth := 0
current := category
for current.Parent.Valid {
current = CategoriesFlat[int(current.Parent.Int64)]
depth++
}
return depth
}
// Helper function for templates (add form select list)
func (category *Category) ToString() string {
return strings.Repeat("- ", category.Depth()) + category.Name
}