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{"fid", "int", 0, false, true, ""},
|
||||||
tblColumn{"name", "varchar", 100, false, false, ""},
|
tblColumn{"name", "varchar", 100, false, false, ""},
|
||||||
tblColumn{"desc", "varchar", 200, false, false, ""},
|
tblColumn{"desc", "varchar", 200, false, false, ""},
|
||||||
|
tblColumn{"tmpl", "varchar", 200, false, false, ""},
|
||||||
tblColumn{"active", "boolean", 0, false, false, "1"},
|
tblColumn{"active", "boolean", 0, false, false, "1"},
|
||||||
tblColumn{"order", "int", 0, false, false, "0"},
|
tblColumn{"order", "int", 0, false, false, "0"},
|
||||||
tblColumn{"topicCount", "int", 0, false, false, "0"},
|
tblColumn{"topicCount", "int", 0, false, false, "0"},
|
||||||
|
|
|
@ -27,6 +27,7 @@ type Forum struct {
|
||||||
Link string
|
Link string
|
||||||
Name string
|
Name string
|
||||||
Desc string
|
Desc string
|
||||||
|
Tmpl string
|
||||||
Active bool
|
Active bool
|
||||||
Order int
|
Order int
|
||||||
Preset string
|
Preset string
|
||||||
|
|
|
@ -10,6 +10,7 @@ import (
|
||||||
"database/sql"
|
"database/sql"
|
||||||
"errors"
|
"errors"
|
||||||
"log"
|
"log"
|
||||||
|
//"fmt"
|
||||||
"sort"
|
"sort"
|
||||||
"sync"
|
"sync"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
|
@ -77,8 +78,8 @@ func NewMemoryForumStore() (*MemoryForumStore, error) {
|
||||||
acc := qgen.NewAcc()
|
acc := qgen.NewAcc()
|
||||||
// TODO: Do a proper delete
|
// TODO: Do a proper delete
|
||||||
return &MemoryForumStore{
|
return &MemoryForumStore{
|
||||||
get: acc.Select("forums").Columns("name, desc, active, order, preset, parentID, parentType, topicCount, lastTopicID, lastReplyerID").Where("fid = ?").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, active, order, preset, parentID, parentType, topicCount, lastTopicID, lastReplyerID").Orderby("order ASC, fid ASC").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(),
|
delete: acc.Update("forums").Set("name= '', active = 0").Where("fid = ?").Prepare(),
|
||||||
create: acc.Insert("forums").Columns("name, desc, active, preset").Fields("?,?,?,?").Prepare(),
|
create: acc.Insert("forums").Columns("name, desc, active, preset").Fields("?,?,?,?").Prepare(),
|
||||||
count: acc.Count("forums").Where("name != ''").Prepare(),
|
count: acc.Count("forums").Where("name != ''").Prepare(),
|
||||||
|
@ -109,7 +110,7 @@ func (mfs *MemoryForumStore) LoadForums() error {
|
||||||
var i = 0
|
var i = 0
|
||||||
for ; rows.Next(); i++ {
|
for ; rows.Next(); i++ {
|
||||||
forum := &Forum{ID: 0, Active: true, Preset: "all"}
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -133,9 +134,9 @@ func (mfs *MemoryForumStore) LoadForums() error {
|
||||||
|
|
||||||
// TODO: Hide social groups too
|
// TODO: Hide social groups too
|
||||||
// ? - Will this be hit a lot by plugin_guilds?
|
// ? - Will this be hit a lot by plugin_guilds?
|
||||||
func (mfs *MemoryForumStore) rebuildView() {
|
func (s *MemoryForumStore) rebuildView() {
|
||||||
var forumView []*Forum
|
var forumView []*Forum
|
||||||
mfs.forums.Range(func(_ interface{}, value interface{}) bool {
|
s.forums.Range(func(_ interface{}, value interface{}) bool {
|
||||||
forum := value.(*Forum)
|
forum := value.(*Forum)
|
||||||
// ? - ParentType blank means that it doesn't have a parent
|
// ? - ParentType blank means that it doesn't have a parent
|
||||||
if forum.Active && forum.Name != "" && forum.ParentType == "" {
|
if forum.Active && forum.Name != "" && forum.ParentType == "" {
|
||||||
|
@ -144,20 +145,20 @@ func (mfs *MemoryForumStore) rebuildView() {
|
||||||
return true
|
return true
|
||||||
})
|
})
|
||||||
sort.Sort(SortForum(forumView))
|
sort.Sort(SortForum(forumView))
|
||||||
mfs.forumView.Store(forumView)
|
s.forumView.Store(forumView)
|
||||||
TopicListThaw.Thaw()
|
TopicListThaw.Thaw()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (mfs *MemoryForumStore) DirtyGet(id int) *Forum {
|
func (s *MemoryForumStore) DirtyGet(id int) *Forum {
|
||||||
fint, ok := mfs.forums.Load(id)
|
fint, ok := s.forums.Load(id)
|
||||||
if !ok || fint.(*Forum).Name == "" {
|
if !ok || fint.(*Forum).Name == "" {
|
||||||
return &Forum{ID: -1, Name: ""}
|
return &Forum{ID: -1, Name: ""}
|
||||||
}
|
}
|
||||||
return fint.(*Forum)
|
return fint.(*Forum)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (mfs *MemoryForumStore) CacheGet(id int) (*Forum, error) {
|
func (s *MemoryForumStore) CacheGet(id int) (*Forum, error) {
|
||||||
fint, ok := mfs.forums.Load(id)
|
fint, ok := s.forums.Load(id)
|
||||||
if !ok || fint.(*Forum).Name == "" {
|
if !ok || fint.(*Forum).Name == "" {
|
||||||
return nil, ErrNoRows
|
return nil, ErrNoRows
|
||||||
}
|
}
|
||||||
|
@ -184,7 +185,7 @@ func (s *MemoryForumStore) Get(id int) (*Forum, error) {
|
||||||
|
|
||||||
func (s *MemoryForumStore) BypassGet(id int) (*Forum, error) {
|
func (s *MemoryForumStore) BypassGet(id int) (*Forum, error) {
|
||||||
var forum = &Forum{ID: id}
|
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 {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -200,10 +201,10 @@ func (s *MemoryForumStore) BypassGet(id int) (*Forum, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Optimise this
|
// 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))
|
forums = make([]Forum, len(ids))
|
||||||
for i, id := range ids {
|
for i, id := range ids {
|
||||||
forum, err := mfs.Get(id)
|
forum, err := s.Get(id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -212,29 +213,24 @@ func (mfs *MemoryForumStore) BulkGetCopy(ids []int) (forums []Forum, err error)
|
||||||
return forums, nil
|
return forums, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (mfs *MemoryForumStore) Reload(id int) error {
|
func (s *MemoryForumStore) Reload(id int) error {
|
||||||
var forum = &Forum{ID: id}
|
forum, err := s.BypassGet(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)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
forum.Link = BuildForumURL(NameToSlug(forum.Name), forum.ID)
|
s.CacheSet(forum)
|
||||||
forum.LastTopic = Topics.DirtyGet(forum.LastTopicID)
|
|
||||||
forum.LastReplyer = Users.DirtyGet(forum.LastReplyerID)
|
|
||||||
|
|
||||||
mfs.CacheSet(forum)
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (mfs *MemoryForumStore) CacheSet(forum *Forum) error {
|
func (s *MemoryForumStore) CacheSet(forum *Forum) error {
|
||||||
mfs.forums.Store(forum.ID, forum)
|
s.forums.Store(forum.ID, forum)
|
||||||
mfs.rebuildView()
|
s.rebuildView()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ! Has a randomised order
|
// ! Has a randomised order
|
||||||
func (mfs *MemoryForumStore) GetAll() (forumView []*Forum, err error) {
|
func (s *MemoryForumStore) GetAll() (forumView []*Forum, err error) {
|
||||||
mfs.forums.Range(func(_ interface{}, value interface{}) bool {
|
s.forums.Range(func(_ interface{}, value interface{}) bool {
|
||||||
forumView = append(forumView, value.(*Forum))
|
forumView = append(forumView, value.(*Forum))
|
||||||
return true
|
return true
|
||||||
})
|
})
|
||||||
|
@ -243,8 +239,8 @@ func (mfs *MemoryForumStore) GetAll() (forumView []*Forum, err error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// ? - Can we optimise the sorting?
|
// ? - Can we optimise the sorting?
|
||||||
func (mfs *MemoryForumStore) GetAllIDs() (ids []int, err error) {
|
func (s *MemoryForumStore) GetAllIDs() (ids []int, err error) {
|
||||||
mfs.forums.Range(func(_ interface{}, value interface{}) bool {
|
s.forums.Range(func(_ interface{}, value interface{}) bool {
|
||||||
ids = append(ids, value.(*Forum).ID)
|
ids = append(ids, value.(*Forum).ID)
|
||||||
return true
|
return true
|
||||||
})
|
})
|
||||||
|
@ -252,13 +248,13 @@ func (mfs *MemoryForumStore) GetAllIDs() (ids []int, err error) {
|
||||||
return ids, nil
|
return ids, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (mfs *MemoryForumStore) GetAllVisible() (forumView []*Forum, err error) {
|
func (s *MemoryForumStore) GetAllVisible() (forumView []*Forum, err error) {
|
||||||
forumView = mfs.forumView.Load().([]*Forum)
|
forumView = s.forumView.Load().([]*Forum)
|
||||||
return forumView, nil
|
return forumView, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (mfs *MemoryForumStore) GetAllVisibleIDs() ([]int, error) {
|
func (s *MemoryForumStore) GetAllVisibleIDs() ([]int, error) {
|
||||||
forumView := mfs.forumView.Load().([]*Forum)
|
forumView := s.forumView.Load().([]*Forum)
|
||||||
var ids = make([]int, len(forumView))
|
var ids = make([]int, len(forumView))
|
||||||
for i := 0; i < len(forumView); i++ {
|
for i := 0; i < len(forumView); i++ {
|
||||||
ids[i] = forumView[i].ID
|
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
|
// TODO: Add a query for this rather than hitting cache
|
||||||
func (mfs *MemoryForumStore) Exists(id int) bool {
|
func (s *MemoryForumStore) Exists(id int) bool {
|
||||||
forum, ok := mfs.forums.Load(id)
|
forum, ok := s.forums.Load(id)
|
||||||
if !ok {
|
if !ok {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
@ -284,9 +280,9 @@ func (mfs *MemoryForumStore) Exists(id int) bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Batch deletions with name blanking? Is this necessary?
|
// TODO: Batch deletions with name blanking? Is this necessary?
|
||||||
func (mfs *MemoryForumStore) CacheDelete(id int) {
|
func (s *MemoryForumStore) CacheDelete(id int) {
|
||||||
mfs.forums.Delete(id)
|
s.forums.Delete(id)
|
||||||
mfs.rebuildView()
|
s.rebuildView()
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Add a hook to allow plugin_guilds to detect when one of it's forums has just been deleted?
|
// 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
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (mfs *MemoryForumStore) AddTopic(tid int, uid int, fid int) error {
|
func (s *MemoryForumStore) AddTopic(tid int, uid int, fid int) error {
|
||||||
_, err := mfs.updateCache.Exec(tid, uid, fid)
|
_, err := s.updateCache.Exec(tid, uid, fid)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
_, err = mfs.addTopics.Exec(1, fid)
|
_, err = s.addTopics.Exec(1, fid)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
// TODO: Bypass the database and update this with a lock or an unsafe atomic swap
|
// 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
|
// TODO: Update the forum cache with the latest topic
|
||||||
func (mfs *MemoryForumStore) RemoveTopic(fid int) error {
|
func (s *MemoryForumStore) RemoveTopic(fid int) error {
|
||||||
_, err := mfs.removeTopics.Exec(1, fid)
|
_, err := s.removeTopics.Exec(1, fid)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
// TODO: Bypass the database and update this with a lock or an unsafe atomic swap
|
// TODO: Bypass the database and update this with a lock or an unsafe atomic swap
|
||||||
mfs.Reload(fid)
|
s.Reload(fid)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// DEPRECATED. forum.Update() will be the way to do this in the future, once it's completed
|
// 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
|
// 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 {
|
func (s *MemoryForumStore) UpdateLastTopic(tid int, uid int, fid int) error {
|
||||||
_, err := mfs.updateCache.Exec(tid, uid, fid)
|
_, err := s.updateCache.Exec(tid, uid, fid)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
// TODO: Bypass the database and update this with a lock or an unsafe atomic swap
|
// 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 == "" {
|
if forumName == "" {
|
||||||
return 0, ErrBlankName
|
return 0, ErrBlankName
|
||||||
}
|
}
|
||||||
forumCreateMutex.Lock()
|
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 {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
|
@ -350,13 +348,12 @@ func (mfs *MemoryForumStore) Create(forumName string, forumDesc string, active b
|
||||||
}
|
}
|
||||||
fid := int(fid64)
|
fid := int(fid64)
|
||||||
|
|
||||||
err = mfs.Reload(fid)
|
err = s.Reload(fid)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
|
|
||||||
PermmapToQuery(PresetToPermmap(preset), fid)
|
PermmapToQuery(PresetToPermmap(preset), fid)
|
||||||
forumCreateMutex.Unlock()
|
|
||||||
return fid, nil
|
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?
|
// 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
|
// GlobalCount returns the total number of forums
|
||||||
func (mfs *MemoryForumStore) GlobalCount() (fcount int) {
|
func (s *MemoryForumStore) GlobalCount() (fcount int) {
|
||||||
err := mfs.count.QueryRow().Scan(&fcount)
|
err := s.count.QueryRow().Scan(&fcount)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
LogError(err)
|
LogError(err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -121,6 +121,7 @@ type devConfig struct {
|
||||||
|
|
||||||
NoFsnotify bool // Super Experimental!
|
NoFsnotify bool // Super Experimental!
|
||||||
FullReqLog bool
|
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
|
// configHolder is purely for having a big struct to unmarshal data into
|
||||||
|
|
|
@ -206,7 +206,7 @@ func CompileTemplates() error {
|
||||||
return nil
|
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
|
// TODO: Add support for interface{}s
|
||||||
_, user2, user3 := tmplInitUsers()
|
_, user2, user3 := tmplInitUsers()
|
||||||
now := time.Now()
|
now := time.Now()
|
||||||
|
@ -221,16 +221,6 @@ func compileCommons(c *tmpl.CTemplateSet, header *Header, header2 *Header, out T
|
||||||
return header2
|
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
|
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})
|
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}}
|
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()
|
ru.Init()
|
||||||
replyList = append(replyList, ru)
|
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
|
// Convienience function to save a line here and there
|
||||||
var htitle = func(name string) *Header {
|
var htitle = func(name string) *Header {
|
||||||
header.Title = name
|
header.Title = name
|
||||||
return header
|
return header
|
||||||
}
|
}
|
||||||
tmpls := TItemHold(make(map[string]TItem))
|
tmpls := TItemHold(make(map[string]TItem))
|
||||||
err := compileCommons(c, header, header2, tmpls)
|
err = compileCommons(c, header, header2, forumList, tmpls)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
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
|
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)
|
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("login", "common.Page", Page{htitle("Login Page"), tList, nil})
|
||||||
tmpls.AddStd("register", "common.Page", Page{htitle("Registration Page"), tList, "nananana"})
|
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."})
|
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(name, tmpl)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*writeTemplate("login", loginTmpl)
|
|
||||||
writeTemplate("register", registerTmpl)
|
|
||||||
writeTemplate("ip_search", ipSearchTmpl)
|
|
||||||
writeTemplate("error", errorTmpl)*/
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -113,11 +113,6 @@ func (ins *MysqlInstaller) InitDatabase() (err error) {
|
||||||
}
|
}
|
||||||
fmt.Println("Successfully connected to the database")
|
fmt.Println("Successfully connected to the database")
|
||||||
|
|
||||||
_, err = db.Exec("SET FOREIGN_KEY_CHECKS = 0;")
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ready the query builder
|
// Ready the query builder
|
||||||
ins.db = db
|
ins.db = db
|
||||||
qgen.Builder.SetConn(db)
|
qgen.Builder.SetConn(db)
|
||||||
|
@ -147,9 +142,10 @@ func (ins *MysqlInstaller) createTable(f os.FileInfo) error {
|
||||||
}
|
}
|
||||||
data = bytes.TrimSpace(data)
|
data = bytes.TrimSpace(data)
|
||||||
|
|
||||||
_, err = ins.db.Exec(string(data))
|
q = string(data)
|
||||||
|
_, err = ins.db.Exec(q)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println("Failed query:", string(data))
|
fmt.Println("Failed query:", q)
|
||||||
fmt.Println("e:", err)
|
fmt.Println("e:", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -165,6 +161,11 @@ func (ins *MysqlInstaller) TableDefs() (err error) {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_, err = ins.db.Exec("SET FOREIGN_KEY_CHECKS = 0;")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
for _, f := range files {
|
for _, f := range files {
|
||||||
if !strings.HasPrefix(f.Name(), "query_") {
|
if !strings.HasPrefix(f.Name(), "query_") {
|
||||||
continue
|
continue
|
||||||
|
|
17
misc_test.go
17
misc_test.go
|
@ -536,6 +536,7 @@ func TestForumStore(t *testing.T) {
|
||||||
if !c.PluginsInited {
|
if !c.PluginsInited {
|
||||||
c.InitPlugins()
|
c.InitPlugins()
|
||||||
}
|
}
|
||||||
|
// TODO: Test ForumStore.Reload
|
||||||
|
|
||||||
fcache, ok := c.Forums.(c.ForumCache)
|
fcache, ok := c.Forums.(c.ForumCache)
|
||||||
expect(t, ok, "Unable to cast ForumStore to 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"
|
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))
|
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(-1), "FID #-1 shouldn't exist")
|
||||||
expect(t, !c.Forums.Exists(0), "FID #0 shouldn't exist")
|
expect(t, !c.Forums.Exists(0), "FID #0 shouldn't exist")
|
||||||
expect(t, c.Forums.Exists(1), "FID #1 should exist")
|
expect(t, c.Forums.Exists(1), "FID #1 should exist")
|
||||||
|
|
|
@ -34,6 +34,7 @@ func init() {
|
||||||
addPatch(19, patch19)
|
addPatch(19, patch19)
|
||||||
addPatch(20, patch20)
|
addPatch(20, patch20)
|
||||||
addPatch(21, patch21)
|
addPatch(21, patch21)
|
||||||
|
addPatch(22, patch22)
|
||||||
}
|
}
|
||||||
|
|
||||||
func patch0(scanner *bufio.Scanner) (err error) {
|
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))
|
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)
|
pageList := c.Paginate(forum.TopicCount, c.Config.ItemsPerPage, 5)
|
||||||
pi := c.ForumPage{header, topicList, forum, c.Paginator{pageList, page, lastPage}}
|
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)
|
counters.ForumViewCounter.Bump(forum.ID)
|
||||||
return ferr
|
return ferr
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@ CREATE TABLE [forums] (
|
||||||
[fid] int not null IDENTITY,
|
[fid] int not null IDENTITY,
|
||||||
[name] nvarchar (100) not null,
|
[name] nvarchar (100) not null,
|
||||||
[desc] nvarchar (200) not null,
|
[desc] nvarchar (200) not null,
|
||||||
|
[tmpl] nvarchar (200) not null,
|
||||||
[active] bit DEFAULT 1 not null,
|
[active] bit DEFAULT 1 not null,
|
||||||
[order] int DEFAULT 0 not null,
|
[order] int DEFAULT 0 not null,
|
||||||
[topicCount] int DEFAULT 0 not null,
|
[topicCount] int DEFAULT 0 not null,
|
||||||
|
|
|
@ -2,6 +2,7 @@ CREATE TABLE `forums` (
|
||||||
`fid` int not null AUTO_INCREMENT,
|
`fid` int not null AUTO_INCREMENT,
|
||||||
`name` varchar(100) not null,
|
`name` varchar(100) not null,
|
||||||
`desc` varchar(200) not null,
|
`desc` varchar(200) not null,
|
||||||
|
`tmpl` varchar(200) not null,
|
||||||
`active` boolean DEFAULT 1 not null,
|
`active` boolean DEFAULT 1 not null,
|
||||||
`order` int DEFAULT 0 not null,
|
`order` int DEFAULT 0 not null,
|
||||||
`topicCount` int DEFAULT 0 not null,
|
`topicCount` int DEFAULT 0 not null,
|
||||||
|
|
|
@ -2,6 +2,7 @@ CREATE TABLE "forums" (
|
||||||
`fid` serial not null,
|
`fid` serial not null,
|
||||||
`name` varchar (100) not null,
|
`name` varchar (100) not null,
|
||||||
`desc` varchar (200) not null,
|
`desc` varchar (200) not null,
|
||||||
|
`tmpl` varchar (200) not null,
|
||||||
`active` boolean DEFAULT 1 not null,
|
`active` boolean DEFAULT 1 not null,
|
||||||
`order` int DEFAULT 0 not null,
|
`order` int DEFAULT 0 not null,
|
||||||
`topicCount` int DEFAULT 0 not null,
|
`topicCount` int DEFAULT 0 not null,
|
||||||
|
|
Loading…
Reference in New Issue