2018-06-06 00:21:22 +00:00
package common
import (
"database/sql"
"strconv"
"strings"
2018-10-27 03:21:02 +00:00
"github.com/Azareal/Gosora/query_gen"
2018-06-06 00:21:22 +00:00
)
type CustomPageStmts struct {
update * sql . Stmt
create * sql . Stmt
}
var customPageStmts CustomPageStmts
func init ( ) {
DbInits . Add ( func ( acc * qgen . Accumulator ) error {
customPageStmts = CustomPageStmts {
update : acc . Update ( "pages" ) . Set ( "name = ?, title = ?, body = ?, allowedGroups = ?, menuID = ?" ) . Where ( "pid = ?" ) . Prepare ( ) ,
create : acc . Insert ( "pages" ) . Columns ( "name, title, body, allowedGroups, menuID" ) . Fields ( "?,?,?,?,?" ) . Prepare ( ) ,
}
return acc . FirstError ( )
} )
}
type CustomPage struct {
ID int
Name string // TODO: Let admins put pages in "virtual subdirectories"
Title string
Body string
AllowedGroups [ ] int
MenuID int
}
func BlankCustomPage ( ) * CustomPage {
return new ( CustomPage )
}
func ( page * CustomPage ) AddAllowedGroup ( gid int ) {
page . AllowedGroups = append ( page . AllowedGroups , gid )
}
func ( page * CustomPage ) getRawAllowedGroups ( ) ( rawAllowedGroups string ) {
for _ , group := range page . AllowedGroups {
rawAllowedGroups += strconv . Itoa ( group ) + ","
}
if len ( rawAllowedGroups ) > 0 {
rawAllowedGroups = rawAllowedGroups [ : len ( rawAllowedGroups ) - 1 ]
}
return rawAllowedGroups
}
func ( page * CustomPage ) Commit ( ) error {
_ , err := customPageStmts . update . Exec ( page . Name , page . Title , page . Body , page . getRawAllowedGroups ( ) , page . MenuID , page . ID )
Pages . Reload ( page . ID )
return err
}
func ( page * CustomPage ) Create ( ) ( int , error ) {
res , err := customPageStmts . create . Exec ( page . Name , page . Title , page . Body , page . getRawAllowedGroups ( ) , page . MenuID )
if err != nil {
return 0 , err
}
pid64 , err := res . LastInsertId ( )
return int ( pid64 ) , err
}
var Pages PageStore
// Holds the custom pages, but doesn't include the template pages in /pages/ which are a lot more flexible yet harder to use and which are too risky security-wise to make editable in the Control Panel
type PageStore interface {
GlobalCount ( ) ( pageCount int )
Get ( id int ) ( * CustomPage , error )
GetByName ( name string ) ( * CustomPage , error )
GetOffset ( offset int , perPage int ) ( pages [ ] * CustomPage , err error )
Reload ( id int ) error
Delete ( id int ) error
}
// TODO: Add a cache to this to save on the queries
type DefaultPageStore struct {
get * sql . Stmt
getByName * sql . Stmt
getOffset * sql . Stmt
count * sql . Stmt
delete * sql . Stmt
}
func NewDefaultPageStore ( acc * qgen . Accumulator ) ( * DefaultPageStore , error ) {
return & DefaultPageStore {
get : acc . Select ( "pages" ) . Columns ( "name, title, body, allowedGroups, menuID" ) . Where ( "pid = ?" ) . Prepare ( ) ,
getByName : acc . Select ( "pages" ) . Columns ( "pid, name, title, body, allowedGroups, menuID" ) . Where ( "name = ?" ) . Prepare ( ) ,
getOffset : acc . Select ( "pages" ) . Columns ( "pid, name, title, body, allowedGroups, menuID" ) . Orderby ( "pid DESC" ) . Limit ( "?,?" ) . Prepare ( ) ,
count : acc . Count ( "pages" ) . Prepare ( ) ,
delete : acc . Delete ( "pages" ) . Where ( "pid = ?" ) . Prepare ( ) ,
} , acc . FirstError ( )
}
func ( store * DefaultPageStore ) GlobalCount ( ) ( pageCount int ) {
err := store . count . QueryRow ( ) . Scan ( & pageCount )
if err != nil {
LogError ( err )
}
return pageCount
}
func ( store * DefaultPageStore ) parseAllowedGroups ( raw string , page * CustomPage ) error {
if raw == "" {
return nil
}
for _ , sgroup := range strings . Split ( raw , "," ) {
group , err := strconv . Atoi ( sgroup )
if err != nil {
return err
}
page . AddAllowedGroup ( group )
}
return nil
}
func ( store * DefaultPageStore ) Get ( id int ) ( * CustomPage , error ) {
page := & CustomPage { ID : id }
rawAllowedGroups := ""
err := store . get . QueryRow ( id ) . Scan ( & page . Name , & page . Title , & page . Body , & rawAllowedGroups , & page . MenuID )
if err != nil {
return nil , err
}
return page , store . parseAllowedGroups ( rawAllowedGroups , page )
}
func ( store * DefaultPageStore ) GetByName ( name string ) ( * CustomPage , error ) {
page := BlankCustomPage ( )
rawAllowedGroups := ""
err := store . getByName . QueryRow ( name ) . Scan ( & page . ID , & page . Name , & page . Title , & page . Body , & rawAllowedGroups , & page . MenuID )
if err != nil {
return nil , err
}
return page , store . parseAllowedGroups ( rawAllowedGroups , page )
}
func ( store * DefaultPageStore ) GetOffset ( offset int , perPage int ) ( pages [ ] * CustomPage , err error ) {
rows , err := store . getOffset . Query ( offset , perPage )
if err != nil {
return pages , err
}
defer rows . Close ( )
for rows . Next ( ) {
page := & CustomPage { ID : 0 }
rawAllowedGroups := ""
err := rows . Scan ( & page . ID , & page . Name , & page . Title , & page . Body , & rawAllowedGroups , & page . MenuID )
if err != nil {
return pages , err
}
err = store . parseAllowedGroups ( rawAllowedGroups , page )
if err != nil {
return pages , err
}
pages = append ( pages , page )
}
return pages , rows . Err ( )
}
// Always returns nil as there's currently no cache
func ( store * DefaultPageStore ) Reload ( id int ) error {
return nil
}
func ( store * DefaultPageStore ) Delete ( id int ) error {
_ , err := store . delete . Exec ( id )
return err
}