Add super experimental support for per-forum templates.
Add the ExtraTmpls developer setting to config.json Call ForumStore.BypassGet in ForumStore.Reload instead of duplicating it. Fix a potential deadlock in ForumStore.Create. Attempt to fix a weird installation bug. Add a few more forum store test cases. You will need to run the updater / patcher for this commit.
This commit is contained in:
parent
7e7f9e46bd
commit
0d1e4e5993
|
@ -181,6 +181,7 @@ func createTables(adapter qgen.Adapter) error {
|
|||
tblColumn{"fid", "int", 0, false, true, ""},
|
||||
tblColumn{"name", "varchar", 100, false, false, ""},
|
||||
tblColumn{"desc", "varchar", 200, false, false, ""},
|
||||
tblColumn{"tmpl", "varchar", 200, false, false, ""},
|
||||
tblColumn{"active", "boolean", 0, false, false, "1"},
|
||||
tblColumn{"order", "int", 0, false, false, "0"},
|
||||
tblColumn{"topicCount", "int", 0, false, false, "0"},
|
||||
|
|
|
@ -27,6 +27,7 @@ type Forum struct {
|
|||
Link string
|
||||
Name string
|
||||
Desc string
|
||||
Tmpl string
|
||||
Active bool
|
||||
Order int
|
||||
Preset string
|
||||
|
|
|
@ -10,6 +10,7 @@ import (
|
|||
"database/sql"
|
||||
"errors"
|
||||
"log"
|
||||
//"fmt"
|
||||
"sort"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
|
@ -77,8 +78,8 @@ func NewMemoryForumStore() (*MemoryForumStore, error) {
|
|||
acc := qgen.NewAcc()
|
||||
// TODO: Do a proper delete
|
||||
return &MemoryForumStore{
|
||||
get: acc.Select("forums").Columns("name, desc, active, order, preset, parentID, parentType, topicCount, lastTopicID, lastReplyerID").Where("fid = ?").Prepare(),
|
||||
getAll: acc.Select("forums").Columns("fid, name, desc, active, order, preset, parentID, parentType, topicCount, lastTopicID, lastReplyerID").Orderby("order ASC, fid ASC").Prepare(),
|
||||
get: acc.Select("forums").Columns("name, desc, tmpl, active, order, preset, parentID, parentType, topicCount, lastTopicID, lastReplyerID").Where("fid = ?").Prepare(),
|
||||
getAll: acc.Select("forums").Columns("fid, name, desc, tmpl, active, order, preset, parentID, parentType, topicCount, lastTopicID, lastReplyerID").Orderby("order ASC, fid ASC").Prepare(),
|
||||
delete: acc.Update("forums").Set("name= '', active = 0").Where("fid = ?").Prepare(),
|
||||
create: acc.Insert("forums").Columns("name, desc, active, preset").Fields("?,?,?,?").Prepare(),
|
||||
count: acc.Count("forums").Where("name != ''").Prepare(),
|
||||
|
@ -109,7 +110,7 @@ func (mfs *MemoryForumStore) LoadForums() error {
|
|||
var i = 0
|
||||
for ; rows.Next(); i++ {
|
||||
forum := &Forum{ID: 0, Active: true, Preset: "all"}
|
||||
err = rows.Scan(&forum.ID, &forum.Name, &forum.Desc, &forum.Active, &forum.Order, &forum.Preset, &forum.ParentID, &forum.ParentType, &forum.TopicCount, &forum.LastTopicID, &forum.LastReplyerID)
|
||||
err = rows.Scan(&forum.ID, &forum.Name, &forum.Desc, &forum.Tmpl, &forum.Active, &forum.Order, &forum.Preset, &forum.ParentID, &forum.ParentType, &forum.TopicCount, &forum.LastTopicID, &forum.LastReplyerID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -133,9 +134,9 @@ func (mfs *MemoryForumStore) LoadForums() error {
|
|||
|
||||
// TODO: Hide social groups too
|
||||
// ? - Will this be hit a lot by plugin_guilds?
|
||||
func (mfs *MemoryForumStore) rebuildView() {
|
||||
func (s *MemoryForumStore) rebuildView() {
|
||||
var forumView []*Forum
|
||||
mfs.forums.Range(func(_ interface{}, value interface{}) bool {
|
||||
s.forums.Range(func(_ interface{}, value interface{}) bool {
|
||||
forum := value.(*Forum)
|
||||
// ? - ParentType blank means that it doesn't have a parent
|
||||
if forum.Active && forum.Name != "" && forum.ParentType == "" {
|
||||
|
@ -144,20 +145,20 @@ func (mfs *MemoryForumStore) rebuildView() {
|
|||
return true
|
||||
})
|
||||
sort.Sort(SortForum(forumView))
|
||||
mfs.forumView.Store(forumView)
|
||||
s.forumView.Store(forumView)
|
||||
TopicListThaw.Thaw()
|
||||
}
|
||||
|
||||
func (mfs *MemoryForumStore) DirtyGet(id int) *Forum {
|
||||
fint, ok := mfs.forums.Load(id)
|
||||
func (s *MemoryForumStore) DirtyGet(id int) *Forum {
|
||||
fint, ok := s.forums.Load(id)
|
||||
if !ok || fint.(*Forum).Name == "" {
|
||||
return &Forum{ID: -1, Name: ""}
|
||||
}
|
||||
return fint.(*Forum)
|
||||
}
|
||||
|
||||
func (mfs *MemoryForumStore) CacheGet(id int) (*Forum, error) {
|
||||
fint, ok := mfs.forums.Load(id)
|
||||
func (s *MemoryForumStore) CacheGet(id int) (*Forum, error) {
|
||||
fint, ok := s.forums.Load(id)
|
||||
if !ok || fint.(*Forum).Name == "" {
|
||||
return nil, ErrNoRows
|
||||
}
|
||||
|
@ -184,7 +185,7 @@ func (s *MemoryForumStore) Get(id int) (*Forum, error) {
|
|||
|
||||
func (s *MemoryForumStore) BypassGet(id int) (*Forum, error) {
|
||||
var forum = &Forum{ID: id}
|
||||
err := s.get.QueryRow(id).Scan(&forum.Name, &forum.Desc, &forum.Active, &forum.Order, &forum.Preset, &forum.ParentID, &forum.ParentType, &forum.TopicCount, &forum.LastTopicID, &forum.LastReplyerID)
|
||||
err := s.get.QueryRow(id).Scan(&forum.Name, &forum.Desc, &forum.Tmpl,&forum.Active, &forum.Order, &forum.Preset, &forum.ParentID, &forum.ParentType, &forum.TopicCount, &forum.LastTopicID, &forum.LastReplyerID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -200,10 +201,10 @@ func (s *MemoryForumStore) BypassGet(id int) (*Forum, error) {
|
|||
}
|
||||
|
||||
// TODO: Optimise this
|
||||
func (mfs *MemoryForumStore) BulkGetCopy(ids []int) (forums []Forum, err error) {
|
||||
func (s *MemoryForumStore) BulkGetCopy(ids []int) (forums []Forum, err error) {
|
||||
forums = make([]Forum, len(ids))
|
||||
for i, id := range ids {
|
||||
forum, err := mfs.Get(id)
|
||||
forum, err := s.Get(id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -212,29 +213,24 @@ func (mfs *MemoryForumStore) BulkGetCopy(ids []int) (forums []Forum, err error)
|
|||
return forums, nil
|
||||
}
|
||||
|
||||
func (mfs *MemoryForumStore) Reload(id int) error {
|
||||
var forum = &Forum{ID: id}
|
||||
err := mfs.get.QueryRow(id).Scan(&forum.Name, &forum.Desc, &forum.Active, &forum.Order, &forum.Preset, &forum.ParentID, &forum.ParentType, &forum.TopicCount, &forum.LastTopicID, &forum.LastReplyerID)
|
||||
func (s *MemoryForumStore) Reload(id int) error {
|
||||
forum, err := s.BypassGet(id)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
forum.Link = BuildForumURL(NameToSlug(forum.Name), forum.ID)
|
||||
forum.LastTopic = Topics.DirtyGet(forum.LastTopicID)
|
||||
forum.LastReplyer = Users.DirtyGet(forum.LastReplyerID)
|
||||
|
||||
mfs.CacheSet(forum)
|
||||
s.CacheSet(forum)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (mfs *MemoryForumStore) CacheSet(forum *Forum) error {
|
||||
mfs.forums.Store(forum.ID, forum)
|
||||
mfs.rebuildView()
|
||||
func (s *MemoryForumStore) CacheSet(forum *Forum) error {
|
||||
s.forums.Store(forum.ID, forum)
|
||||
s.rebuildView()
|
||||
return nil
|
||||
}
|
||||
|
||||
// ! Has a randomised order
|
||||
func (mfs *MemoryForumStore) GetAll() (forumView []*Forum, err error) {
|
||||
mfs.forums.Range(func(_ interface{}, value interface{}) bool {
|
||||
func (s *MemoryForumStore) GetAll() (forumView []*Forum, err error) {
|
||||
s.forums.Range(func(_ interface{}, value interface{}) bool {
|
||||
forumView = append(forumView, value.(*Forum))
|
||||
return true
|
||||
})
|
||||
|
@ -243,8 +239,8 @@ func (mfs *MemoryForumStore) GetAll() (forumView []*Forum, err error) {
|
|||
}
|
||||
|
||||
// ? - Can we optimise the sorting?
|
||||
func (mfs *MemoryForumStore) GetAllIDs() (ids []int, err error) {
|
||||
mfs.forums.Range(func(_ interface{}, value interface{}) bool {
|
||||
func (s *MemoryForumStore) GetAllIDs() (ids []int, err error) {
|
||||
s.forums.Range(func(_ interface{}, value interface{}) bool {
|
||||
ids = append(ids, value.(*Forum).ID)
|
||||
return true
|
||||
})
|
||||
|
@ -252,13 +248,13 @@ func (mfs *MemoryForumStore) GetAllIDs() (ids []int, err error) {
|
|||
return ids, nil
|
||||
}
|
||||
|
||||
func (mfs *MemoryForumStore) GetAllVisible() (forumView []*Forum, err error) {
|
||||
forumView = mfs.forumView.Load().([]*Forum)
|
||||
func (s *MemoryForumStore) GetAllVisible() (forumView []*Forum, err error) {
|
||||
forumView = s.forumView.Load().([]*Forum)
|
||||
return forumView, nil
|
||||
}
|
||||
|
||||
func (mfs *MemoryForumStore) GetAllVisibleIDs() ([]int, error) {
|
||||
forumView := mfs.forumView.Load().([]*Forum)
|
||||
func (s *MemoryForumStore) GetAllVisibleIDs() ([]int, error) {
|
||||
forumView := s.forumView.Load().([]*Forum)
|
||||
var ids = make([]int, len(forumView))
|
||||
for i := 0; i < len(forumView); i++ {
|
||||
ids[i] = forumView[i].ID
|
||||
|
@ -275,8 +271,8 @@ func (mfs *MemoryForumStore) GetFirstChild(parentID int, parentType string) (*Fo
|
|||
}*/
|
||||
|
||||
// TODO: Add a query for this rather than hitting cache
|
||||
func (mfs *MemoryForumStore) Exists(id int) bool {
|
||||
forum, ok := mfs.forums.Load(id)
|
||||
func (s *MemoryForumStore) Exists(id int) bool {
|
||||
forum, ok := s.forums.Load(id)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
|
@ -284,9 +280,9 @@ func (mfs *MemoryForumStore) Exists(id int) bool {
|
|||
}
|
||||
|
||||
// TODO: Batch deletions with name blanking? Is this necessary?
|
||||
func (mfs *MemoryForumStore) CacheDelete(id int) {
|
||||
mfs.forums.Delete(id)
|
||||
mfs.rebuildView()
|
||||
func (s *MemoryForumStore) CacheDelete(id int) {
|
||||
s.forums.Delete(id)
|
||||
s.rebuildView()
|
||||
}
|
||||
|
||||
// TODO: Add a hook to allow plugin_guilds to detect when one of it's forums has just been deleted?
|
||||
|
@ -299,47 +295,49 @@ func (s *MemoryForumStore) Delete(id int) error {
|
|||
return err
|
||||
}
|
||||
|
||||
func (mfs *MemoryForumStore) AddTopic(tid int, uid int, fid int) error {
|
||||
_, err := mfs.updateCache.Exec(tid, uid, fid)
|
||||
func (s *MemoryForumStore) AddTopic(tid int, uid int, fid int) error {
|
||||
_, err := s.updateCache.Exec(tid, uid, fid)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = mfs.addTopics.Exec(1, fid)
|
||||
_, err = s.addTopics.Exec(1, fid)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// TODO: Bypass the database and update this with a lock or an unsafe atomic swap
|
||||
return mfs.Reload(fid)
|
||||
return s.Reload(fid)
|
||||
}
|
||||
|
||||
// TODO: Update the forum cache with the latest topic
|
||||
func (mfs *MemoryForumStore) RemoveTopic(fid int) error {
|
||||
_, err := mfs.removeTopics.Exec(1, fid)
|
||||
func (s *MemoryForumStore) RemoveTopic(fid int) error {
|
||||
_, err := s.removeTopics.Exec(1, fid)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// TODO: Bypass the database and update this with a lock or an unsafe atomic swap
|
||||
mfs.Reload(fid)
|
||||
s.Reload(fid)
|
||||
return nil
|
||||
}
|
||||
|
||||
// DEPRECATED. forum.Update() will be the way to do this in the future, once it's completed
|
||||
// TODO: Have a pointer to the last topic rather than storing it on the forum itself
|
||||
func (mfs *MemoryForumStore) UpdateLastTopic(tid int, uid int, fid int) error {
|
||||
_, err := mfs.updateCache.Exec(tid, uid, fid)
|
||||
func (s *MemoryForumStore) UpdateLastTopic(tid int, uid int, fid int) error {
|
||||
_, err := s.updateCache.Exec(tid, uid, fid)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// TODO: Bypass the database and update this with a lock or an unsafe atomic swap
|
||||
return mfs.Reload(fid)
|
||||
return s.Reload(fid)
|
||||
}
|
||||
|
||||
func (mfs *MemoryForumStore) Create(forumName string, forumDesc string, active bool, preset string) (int, error) {
|
||||
func (s *MemoryForumStore) Create(forumName string, forumDesc string, active bool, preset string) (int, error) {
|
||||
if forumName == "" {
|
||||
return 0, ErrBlankName
|
||||
}
|
||||
forumCreateMutex.Lock()
|
||||
res, err := mfs.create.Exec(forumName, forumDesc, active, preset)
|
||||
defer forumCreateMutex.Unlock()
|
||||
|
||||
res, err := s.create.Exec(forumName, forumDesc, active, preset)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
@ -350,13 +348,12 @@ func (mfs *MemoryForumStore) Create(forumName string, forumDesc string, active b
|
|||
}
|
||||
fid := int(fid64)
|
||||
|
||||
err = mfs.Reload(fid)
|
||||
err = s.Reload(fid)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
PermmapToQuery(PresetToPermmap(preset), fid)
|
||||
forumCreateMutex.Unlock()
|
||||
return fid, nil
|
||||
}
|
||||
|
||||
|
@ -383,8 +380,8 @@ func (s *MemoryForumStore) Length() (length int) {
|
|||
|
||||
// TODO: Get the total count of forums in the forum store rather than doing a heavy query for this?
|
||||
// GlobalCount returns the total number of forums
|
||||
func (mfs *MemoryForumStore) GlobalCount() (fcount int) {
|
||||
err := mfs.count.QueryRow().Scan(&fcount)
|
||||
func (s *MemoryForumStore) GlobalCount() (fcount int) {
|
||||
err := s.count.QueryRow().Scan(&fcount)
|
||||
if err != nil {
|
||||
LogError(err)
|
||||
}
|
||||
|
|
|
@ -121,6 +121,7 @@ type devConfig struct {
|
|||
|
||||
NoFsnotify bool // Super Experimental!
|
||||
FullReqLog bool
|
||||
ExtraTmpls string // Experimental flag for adding compiled templates, we'll likely replace this with a better mechanism
|
||||
}
|
||||
|
||||
// configHolder is purely for having a big struct to unmarshal data into
|
||||
|
|
|
@ -206,7 +206,7 @@ func CompileTemplates() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func compileCommons(c *tmpl.CTemplateSet, header *Header, header2 *Header, out TItemHold) error {
|
||||
func compileCommons(c *tmpl.CTemplateSet, header *Header, header2 *Header, forumList []Forum, out TItemHold) error {
|
||||
// TODO: Add support for interface{}s
|
||||
_, user2, user3 := tmplInitUsers()
|
||||
now := time.Now()
|
||||
|
@ -221,16 +221,6 @@ func compileCommons(c *tmpl.CTemplateSet, header *Header, header2 *Header, out T
|
|||
return header2
|
||||
}*/
|
||||
|
||||
// TODO: Use a dummy forum list to avoid o(n) problems
|
||||
var forumList []Forum
|
||||
forums, err := Forums.GetAll()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, forum := range forums {
|
||||
forumList = append(forumList, *forum)
|
||||
}
|
||||
|
||||
var topicsList []*TopicsRow
|
||||
topicsList = append(topicsList, &TopicsRow{1, "topic-title", "Topic Title", "The topic content.", 1, false, false, now, now, user3.ID, 1, 1, "", "127.0.0.1", 1, 0, 1, 1, 0, "classname", 0, "", &user2, "", 0, &user3, "General", "/forum/general.2", nil})
|
||||
topicListPage := TopicListPage{htitle("Topic List"), topicsList, forumList, Config.DefaultForum, TopicListSort{"lastupdated", false}, Paginator{[]int{1}, 1, 1}}
|
||||
|
@ -283,13 +273,23 @@ func compileTemplates(wg *sync.WaitGroup, c *tmpl.CTemplateSet, themeName string
|
|||
ru.Init()
|
||||
replyList = append(replyList, ru)
|
||||
|
||||
// TODO: Use a dummy forum list to avoid o(n) problems
|
||||
var forumList []Forum
|
||||
forums, err := Forums.GetAll()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, forum := range forums {
|
||||
forumList = append(forumList, *forum)
|
||||
}
|
||||
|
||||
// Convienience function to save a line here and there
|
||||
var htitle = func(name string) *Header {
|
||||
header.Title = name
|
||||
return header
|
||||
}
|
||||
tmpls := TItemHold(make(map[string]TItem))
|
||||
err := compileCommons(c, header, header2, tmpls)
|
||||
err = compileCommons(c, header, header2, forumList, tmpls)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -297,6 +297,45 @@ func compileTemplates(wg *sync.WaitGroup, c *tmpl.CTemplateSet, themeName string
|
|||
ppage := ProfilePage{htitle("User 526"), replyList, user, 0, 0} // TODO: Use the score from user to generate the currentScore and nextScore
|
||||
tmpls.Add("profile", "common.ProfilePage", ppage)
|
||||
|
||||
var topicsList []*TopicsRow
|
||||
topicsList = append(topicsList, &TopicsRow{1, "topic-title", "Topic Title", "The topic content.", 1, false, false, now, now, user3.ID, 1, 1, "", "127.0.0.1", 1, 0, 1, 1, 0, "classname", 0, "", &user2, "", 0, &user3, "General", "/forum/general.2", nil})
|
||||
topicListPage := TopicListPage{htitle("Topic List"), topicsList, forumList, Config.DefaultForum, TopicListSort{"lastupdated", false}, Paginator{[]int{1}, 1, 1}}
|
||||
|
||||
forumItem := BlankForum(1, "general-forum.1", "General Forum", "Where the general stuff happens", true, "all", 0, "", 0)
|
||||
forumPage := ForumPage{htitle("General Forum"), topicsList, forumItem, Paginator{[]int{1}, 1, 1}}
|
||||
|
||||
// Experimental!
|
||||
for _, tmpl := range strings.Split(Dev.ExtraTmpls,",") {
|
||||
sp := strings.Split(tmpl,":")
|
||||
if len(sp) < 2 {
|
||||
continue
|
||||
}
|
||||
typ := "0"
|
||||
if len(sp) == 3 {
|
||||
typ = sp[2]
|
||||
}
|
||||
|
||||
var pi interface{}
|
||||
switch sp[1] {
|
||||
case "common.TopicListPage":
|
||||
pi = topicListPage
|
||||
case "common.ForumPage":
|
||||
pi = forumPage
|
||||
case "common.ProfilePage":
|
||||
pi = ppage
|
||||
case "common.Page":
|
||||
pi = Page{htitle("Something"), tList, nil}
|
||||
default:
|
||||
continue
|
||||
}
|
||||
|
||||
if typ == "1" {
|
||||
tmpls.Add(sp[0], sp[1], pi)
|
||||
} else {
|
||||
tmpls.AddStd(sp[0], sp[1], pi)
|
||||
}
|
||||
}
|
||||
|
||||
tmpls.AddStd("login", "common.Page", Page{htitle("Login Page"), tList, nil})
|
||||
tmpls.AddStd("register", "common.Page", Page{htitle("Registration Page"), tList, "nananana"})
|
||||
tmpls.AddStd("error", "common.ErrorPage", ErrorPage{htitle("Error"), "A problem has occurred in the system."})
|
||||
|
@ -374,10 +413,7 @@ func compileTemplates(wg *sync.WaitGroup, c *tmpl.CTemplateSet, themeName string
|
|||
writeTemplate(name, tmpl)
|
||||
}
|
||||
}
|
||||
/*writeTemplate("login", loginTmpl)
|
||||
writeTemplate("register", registerTmpl)
|
||||
writeTemplate("ip_search", ipSearchTmpl)
|
||||
writeTemplate("error", errorTmpl)*/
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
@ -113,11 +113,6 @@ func (ins *MysqlInstaller) InitDatabase() (err error) {
|
|||
}
|
||||
fmt.Println("Successfully connected to the database")
|
||||
|
||||
_, err = db.Exec("SET FOREIGN_KEY_CHECKS = 0;")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Ready the query builder
|
||||
ins.db = db
|
||||
qgen.Builder.SetConn(db)
|
||||
|
@ -147,9 +142,10 @@ func (ins *MysqlInstaller) createTable(f os.FileInfo) error {
|
|||
}
|
||||
data = bytes.TrimSpace(data)
|
||||
|
||||
_, err = ins.db.Exec(string(data))
|
||||
q = string(data)
|
||||
_, err = ins.db.Exec(q)
|
||||
if err != nil {
|
||||
fmt.Println("Failed query:", string(data))
|
||||
fmt.Println("Failed query:", q)
|
||||
fmt.Println("e:", err)
|
||||
return err
|
||||
}
|
||||
|
@ -165,6 +161,11 @@ func (ins *MysqlInstaller) TableDefs() (err error) {
|
|||
return err
|
||||
}
|
||||
|
||||
_, err = ins.db.Exec("SET FOREIGN_KEY_CHECKS = 0;")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, f := range files {
|
||||
if !strings.HasPrefix(f.Name(), "query_") {
|
||||
continue
|
||||
|
|
17
misc_test.go
17
misc_test.go
|
@ -536,6 +536,7 @@ func TestForumStore(t *testing.T) {
|
|||
if !c.PluginsInited {
|
||||
c.InitPlugins()
|
||||
}
|
||||
// TODO: Test ForumStore.Reload
|
||||
|
||||
fcache, ok := c.Forums.(c.ForumCache)
|
||||
expect(t, ok, "Unable to cast ForumStore to ForumCache")
|
||||
|
@ -570,6 +571,22 @@ func TestForumStore(t *testing.T) {
|
|||
expectDesc = "A place for general discussions which don't fit elsewhere"
|
||||
expect(t, forum.Desc == expectDesc, fmt.Sprintf("The forum description should be '%s' not '%s'", expectDesc, forum.Desc))
|
||||
|
||||
// Forum reload test, kind of hacky but gets the job done
|
||||
/*
|
||||
CacheGet(id int) (*Forum, error)
|
||||
CacheSet(forum *Forum) error
|
||||
*/
|
||||
expect(t,ok,"ForumCache should be available")
|
||||
forum.Name = "nanana"
|
||||
fcache.CacheSet(forum)
|
||||
forum, err = c.Forums.Get(2)
|
||||
recordMustExist(t, err, "Couldn't find FID #2")
|
||||
expect(t, forum.Name == "nanana", fmt.Sprintf("The faux name should be nanana not %s", forum.Name))
|
||||
expectNilErr(t,c.Forums.Reload(2))
|
||||
forum, err = c.Forums.Get(2)
|
||||
recordMustExist(t, err, "Couldn't find FID #2")
|
||||
expect(t, forum.Name == "General", fmt.Sprintf("The proper name should be 2 not %s", forum.Name))
|
||||
|
||||
expect(t, !c.Forums.Exists(-1), "FID #-1 shouldn't exist")
|
||||
expect(t, !c.Forums.Exists(0), "FID #0 shouldn't exist")
|
||||
expect(t, c.Forums.Exists(1), "FID #1 should exist")
|
||||
|
|
|
@ -34,6 +34,7 @@ func init() {
|
|||
addPatch(19, patch19)
|
||||
addPatch(20, patch20)
|
||||
addPatch(21, patch21)
|
||||
addPatch(22, patch22)
|
||||
}
|
||||
|
||||
func patch0(scanner *bufio.Scanner) (err error) {
|
||||
|
@ -652,3 +653,7 @@ func patch21(scanner *bufio.Scanner) error {
|
|||
|
||||
return execStmt(qgen.Builder.AddColumn("activity_stream", tblColumn{"createdAt", "createdAt", 0, false, false, ""}, nil))
|
||||
}
|
||||
|
||||
func patch22(scanner *bufio.Scanner) error {
|
||||
return execStmt(qgen.Builder.AddColumn("forums", tblColumn{"tmpl", "varchar", 200, false, false, ""}, nil))
|
||||
}
|
|
@ -124,7 +124,11 @@ func ViewForum(w http.ResponseWriter, r *http.Request, user c.User, header *c.He
|
|||
|
||||
pageList := c.Paginate(forum.TopicCount, c.Config.ItemsPerPage, 5)
|
||||
pi := c.ForumPage{header, topicList, forum, c.Paginator{pageList, page, lastPage}}
|
||||
ferr = renderTemplate("forum", w, r, header, pi)
|
||||
var tmpl = forum.Tmpl
|
||||
if tmpl == "" {
|
||||
tmpl = "forum"
|
||||
}
|
||||
ferr = renderTemplate(tmpl, w, r, header, pi)
|
||||
counters.ForumViewCounter.Bump(forum.ID)
|
||||
return ferr
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ CREATE TABLE [forums] (
|
|||
[fid] int not null IDENTITY,
|
||||
[name] nvarchar (100) not null,
|
||||
[desc] nvarchar (200) not null,
|
||||
[tmpl] nvarchar (200) not null,
|
||||
[active] bit DEFAULT 1 not null,
|
||||
[order] int DEFAULT 0 not null,
|
||||
[topicCount] int DEFAULT 0 not null,
|
||||
|
|
|
@ -2,6 +2,7 @@ CREATE TABLE `forums` (
|
|||
`fid` int not null AUTO_INCREMENT,
|
||||
`name` varchar(100) not null,
|
||||
`desc` varchar(200) not null,
|
||||
`tmpl` varchar(200) not null,
|
||||
`active` boolean DEFAULT 1 not null,
|
||||
`order` int DEFAULT 0 not null,
|
||||
`topicCount` int DEFAULT 0 not null,
|
||||
|
|
|
@ -2,6 +2,7 @@ CREATE TABLE "forums" (
|
|||
`fid` serial not null,
|
||||
`name` varchar (100) not null,
|
||||
`desc` varchar (200) not null,
|
||||
`tmpl` varchar (200) not null,
|
||||
`active` boolean DEFAULT 1 not null,
|
||||
`order` int DEFAULT 0 not null,
|
||||
`topicCount` int DEFAULT 0 not null,
|
||||
|
|
Loading…
Reference in New Issue