2018-06-06 00:21:22 +00:00
package common
import (
"database/sql"
"strconv"
"strings"
2019-07-26 22:26:52 +00:00
qgen "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 {
2019-06-01 12:31:48 +00:00
Count ( ) ( count int )
2018-06-06 00:21:22 +00:00
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 ( )
}
2019-06-01 12:31:48 +00:00
func ( s * DefaultPageStore ) Count ( ) ( count int ) {
err := s . count . QueryRow ( ) . Scan ( & count )
2018-06-06 00:21:22 +00:00
if err != nil {
LogError ( err )
}
2019-06-01 12:31:48 +00:00
return count
2018-06-06 00:21:22 +00:00
}
2019-06-01 12:31:48 +00:00
func ( s * DefaultPageStore ) parseAllowedGroups ( raw string , page * CustomPage ) error {
2018-06-06 00:21:22 +00:00
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
}
2019-07-26 22:26:52 +00:00
func ( s * DefaultPageStore ) Get ( id int ) ( * CustomPage , error ) {
2018-06-06 00:21:22 +00:00
page := & CustomPage { ID : id }
rawAllowedGroups := ""
2019-07-26 22:26:52 +00:00
err := s . get . QueryRow ( id ) . Scan ( & page . Name , & page . Title , & page . Body , & rawAllowedGroups , & page . MenuID )
2018-06-06 00:21:22 +00:00
if err != nil {
return nil , err
}
2019-07-26 22:26:52 +00:00
return page , s . parseAllowedGroups ( rawAllowedGroups , page )
2018-06-06 00:21:22 +00:00
}
2019-07-26 22:26:52 +00:00
func ( s * DefaultPageStore ) GetByName ( name string ) ( * CustomPage , error ) {
2018-06-06 00:21:22 +00:00
page := BlankCustomPage ( )
rawAllowedGroups := ""
2019-07-26 22:26:52 +00:00
err := s . getByName . QueryRow ( name ) . Scan ( & page . ID , & page . Name , & page . Title , & page . Body , & rawAllowedGroups , & page . MenuID )
2018-06-06 00:21:22 +00:00
if err != nil {
return nil , err
}
2019-07-26 22:26:52 +00:00
return page , s . parseAllowedGroups ( rawAllowedGroups , page )
2018-06-06 00:21:22 +00:00
}
2019-07-26 22:26:52 +00:00
func ( s * DefaultPageStore ) GetOffset ( offset int , perPage int ) ( pages [ ] * CustomPage , err error ) {
rows , err := s . getOffset . Query ( offset , perPage )
2018-06-06 00:21:22 +00:00
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
}
2019-07-26 22:26:52 +00:00
err = s . parseAllowedGroups ( rawAllowedGroups , page )
2018-06-06 00:21:22 +00:00
if err != nil {
return pages , err
}
pages = append ( pages , page )
}
return pages , rows . Err ( )
}
// Always returns nil as there's currently no cache
2019-07-26 22:26:52 +00:00
func ( s * DefaultPageStore ) Reload ( id int ) error {
2018-06-06 00:21:22 +00:00
return nil
}
2019-07-26 22:26:52 +00:00
func ( s * DefaultPageStore ) Delete ( id int ) error {
_ , err := s . delete . Exec ( id )
2018-06-06 00:21:22 +00:00
return err
}