Did a bit of refactoring on the template system.

Refactored the ReplyStore.
Added the Create method to the ProfileReplyStore.
Fixed a potential issue with the topics and replies generated by the installer.
Refactored the accumulator.
Refactored global.js

Added more tests.
This commit is contained in:
Azareal 2017-11-06 16:24:45 +00:00
parent aab949cb2d
commit 569b424ac8
16 changed files with 294 additions and 299 deletions

View File

@ -52,7 +52,6 @@ type Stmts struct {
addActivity *sql.Stmt addActivity *sql.Stmt
notifyOne *sql.Stmt notifyOne *sql.Stmt
addEmail *sql.Stmt addEmail *sql.Stmt
createProfileReply *sql.Stmt
addSubscription *sql.Stmt addSubscription *sql.Stmt
addForumPermsToForum *sql.Stmt addForumPermsToForum *sql.Stmt
addPlugin *sql.Stmt addPlugin *sql.Stmt
@ -438,13 +437,6 @@ func _gen_mssql() (err error) {
return err return err
} }
log.Print("Preparing createProfileReply statement.")
stmts.createProfileReply, err = db.Prepare("INSERT INTO [users_replies] ([uid],[content],[parsed_content],[createdAt],[createdBy],[ipaddress]) VALUES (?,?,?,GETUTCDATE(),?,?)")
if err != nil {
log.Print("Bad Query: ","INSERT INTO [users_replies] ([uid],[content],[parsed_content],[createdAt],[createdBy],[ipaddress]) VALUES (?,?,?,GETUTCDATE(),?,?)")
return err
}
log.Print("Preparing addSubscription statement.") log.Print("Preparing addSubscription statement.")
stmts.addSubscription, err = db.Prepare("INSERT INTO [activity_subscriptions] ([user],[targetID],[targetType],[level]) VALUES (?,?,?,2)") stmts.addSubscription, err = db.Prepare("INSERT INTO [activity_subscriptions] ([user],[targetID],[targetType],[level]) VALUES (?,?,?,2)")
if err != nil { if err != nil {

View File

@ -54,7 +54,6 @@ type Stmts struct {
addActivity *sql.Stmt addActivity *sql.Stmt
notifyOne *sql.Stmt notifyOne *sql.Stmt
addEmail *sql.Stmt addEmail *sql.Stmt
createProfileReply *sql.Stmt
addSubscription *sql.Stmt addSubscription *sql.Stmt
addForumPermsToForum *sql.Stmt addForumPermsToForum *sql.Stmt
addPlugin *sql.Stmt addPlugin *sql.Stmt
@ -396,12 +395,6 @@ func _gen_mysql() (err error) {
return err return err
} }
log.Print("Preparing createProfileReply statement.")
stmts.createProfileReply, err = db.Prepare("INSERT INTO `users_replies`(`uid`,`content`,`parsed_content`,`createdAt`,`createdBy`,`ipaddress`) VALUES (?,?,?,UTC_TIMESTAMP(),?,?)")
if err != nil {
return err
}
log.Print("Preparing addSubscription statement.") log.Print("Preparing addSubscription statement.")
stmts.addSubscription, err = db.Prepare("INSERT INTO `activity_subscriptions`(`user`,`targetID`,`targetType`,`level`) VALUES (?,?,?,2)") stmts.addSubscription, err = db.Prepare("INSERT INTO `activity_subscriptions`(`user`,`targetID`,`targetType`,`level`) VALUES (?,?,?,2)")
if err != nil { if err != nil {

View File

@ -559,17 +559,13 @@ func routeProfileReplyCreate(w http.ResponseWriter, r *http.Request, user User)
} }
content := html.EscapeString(preparseMessage(r.PostFormValue("reply-content"))) content := html.EscapeString(preparseMessage(r.PostFormValue("reply-content")))
_, err = stmts.createProfileReply.Exec(uid, content, parseMessage(content, 0, ""), user.ID, ipaddress) _, err = prstore.Create(uid, content, user.ID, ipaddress)
if err != nil { if err != nil {
return InternalError(err, w, r) return InternalError(err, w, r)
} }
var userName string if !users.Exists(uid) {
err = stmts.getUserName.QueryRow(uid).Scan(&userName)
if err == ErrNoRows {
return LocalError("The profile you're trying to post on doesn't exist.", w, r, user) return LocalError("The profile you're trying to post on doesn't exist.", w, r, user)
} else if err != nil {
return InternalError(err, w, r)
} }
http.Redirect(w, r, "/user/"+strconv.Itoa(uid), http.StatusSeeOther) http.Redirect(w, r, "/user/"+strconv.Itoa(uid), http.StatusSeeOther)

View File

@ -550,6 +550,8 @@ func topicStoreTest(t *testing.T) {
t.Error("The number of topics should be bigger than zero") t.Error("The number of topics should be bigger than zero")
t.Error("count", count) t.Error("count", count)
} }
// TODO: Test topic creation and retrieving that created topic plus reload and inspecting the cache
} }
func TestForumStore(t *testing.T) { func TestForumStore(t *testing.T) {
@ -737,16 +739,28 @@ func TestReplyStore(t *testing.T) {
reply, err := rstore.Get(1) reply, err := rstore.Get(1)
expectNilErr(t, err) expectNilErr(t, err)
expect(t, reply.ID == 1, fmt.Sprintf("RID #1 has the wrong ID. It should be 1 not %d", reply.ID))
expect(t, reply.ParentID == 1, fmt.Sprintf("The parent topic of RID #1 should be 1 not %d", reply.ParentID))
expect(t, reply.CreatedBy == 1, fmt.Sprintf("The creator of RID #1 should be 1 not %d", reply.CreatedBy))
expect(t, reply.Content == "A reply!", fmt.Sprintf("The contents of RID #1 should be 'A reply!' not %s", reply.Content))
expect(t, reply.IPAddress == "::1", fmt.Sprintf("The IPAddress of RID#1 should be '::1' not %s", reply.IPAddress))
if reply.ID != 1 { _, err = rstore.Get(2)
t.Errorf("RID #1 has the wrong ID. It should be 1 not %d", reply.ID) recordMustNotExist(t, err, "RID #2 shouldn't exist")
}
if reply.ParentID != 1 { // TODO: Test Create and Get
t.Errorf("The parent topic of RID #1 should be 1 not %d", reply.ParentID) //Create(tid int, content string, ipaddress string, fid int, uid int) (id int, err error)
} rid, err := rstore.Create(1, "Fofofo", "::1", 2, 1)
if reply.CreatedBy != 1 { expectNilErr(t, err)
t.Errorf("The creator of RID #1 should be 1 not %d", reply.CreatedBy) expect(t, rid == 2, fmt.Sprintf("The next reply ID should be 2 not %d", rid))
}
reply, err = rstore.Get(2)
expectNilErr(t, err)
expect(t, reply.ID == 2, fmt.Sprintf("RID #2 has the wrong ID. It should be 2 not %d", reply.ID))
expect(t, reply.ParentID == 1, fmt.Sprintf("The parent topic of RID #2 should be 1 not %d", reply.ParentID))
expect(t, reply.CreatedBy == 1, fmt.Sprintf("The creator of RID #2 should be 1 not %d", reply.CreatedBy))
expect(t, reply.Content == "Fofofo", fmt.Sprintf("The contents of RID #2 should be 'Fofofo' not %s", reply.Content))
expect(t, reply.IPAddress == "::1", fmt.Sprintf("The IPAddress of RID #2 should be '::1' not %s", reply.IPAddress))
} }
func TestProfileReplyStore(t *testing.T) { func TestProfileReplyStore(t *testing.T) {
@ -758,10 +772,30 @@ func TestProfileReplyStore(t *testing.T) {
} }
_, err := prstore.Get(-1) _, err := prstore.Get(-1)
recordMustNotExist(t, err, "RID #-1 shouldn't exist") recordMustNotExist(t, err, "PRID #-1 shouldn't exist")
_, err = prstore.Get(0) _, err = prstore.Get(0)
recordMustNotExist(t, err, "RID #0 shouldn't exist") recordMustNotExist(t, err, "PRID #0 shouldn't exist")
_, err = prstore.Get(1)
recordMustNotExist(t, err, "PRID #0 shouldn't exist")
var profileID = 1
prid, err := prstore.Create(profileID, "Haha", 1, "::1")
expect(t, err == nil, "Unable to create a profile reply")
expect(t, prid == 1, "The first profile reply should have an ID of 1")
profileReply, err := prstore.Get(1)
expect(t, err == nil, "PRID #1 should exist")
expect(t, profileReply.ID == 1, fmt.Sprintf("The profile reply should have an ID of 1 not %d", profileReply.ID))
expect(t, profileReply.ParentID == 1, fmt.Sprintf("The parent ID of the profile reply should be 1 not %d", profileReply.ParentID))
expect(t, profileReply.Content == "Haha", fmt.Sprintf("The profile reply's contents should be 'Haha' not '%s'", profileReply.Content))
expect(t, profileReply.CreatedBy == 1, fmt.Sprintf("The profile reply's creator should be 1 not %d", profileReply.CreatedBy))
expect(t, profileReply.IPAddress == "::1", fmt.Sprintf("The profile reply's IP Address should be '::1' not '%s'", profileReply.IPAddress))
//Get(id int) (*Reply, error)
//Create(profileID int, content string, createdBy int, ipaddress string) (id int, err error)
} }
func TestSlugs(t *testing.T) { func TestSlugs(t *testing.T) {

View File

@ -174,7 +174,7 @@ func TestBBCodeRender(t *testing.T) {
msg = "[rand]18446744073709551615[/rand]" // Unsigned 64-bit MAX msg = "[rand]18446744073709551615[/rand]" // Unsigned 64-bit MAX
t.Log("Testing string '" + msg + "'") t.Log("Testing string '" + msg + "'")
res = bbcodeFullParse(msg) res = bbcodeFullParse(msg)
conv, err = strconv.Atoi(res) _, err = strconv.Atoi(res)
if err != nil && res != "<span style='color: red;'>[Invalid Number]</span>[rand]18446744073709551615[/rand]" { if err != nil && res != "<span style='color: red;'>[Invalid Number]</span>[rand]18446744073709551615[/rand]" {
t.Error("Bad output:", "'"+res+"'") t.Error("Bad output:", "'"+res+"'")
t.Error("Expected a number between 0 and 18446744073709551615") t.Error("Expected a number between 0 and 18446744073709551615")
@ -182,7 +182,7 @@ func TestBBCodeRender(t *testing.T) {
msg = "[rand]170141183460469231731687303715884105727[/rand]" // Signed 128-bit MAX msg = "[rand]170141183460469231731687303715884105727[/rand]" // Signed 128-bit MAX
t.Log("Testing string '" + msg + "'") t.Log("Testing string '" + msg + "'")
res = bbcodeFullParse(msg) res = bbcodeFullParse(msg)
conv, err = strconv.Atoi(res) _, err = strconv.Atoi(res)
if err != nil && res != "<span style='color: red;'>[Invalid Number]</span>[rand]170141183460469231731687303715884105727[/rand]" { if err != nil && res != "<span style='color: red;'>[Invalid Number]</span>[rand]170141183460469231731687303715884105727[/rand]" {
t.Error("Bad output:", "'"+res+"'") t.Error("Bad output:", "'"+res+"'")
t.Error("Expected a number between 0 and 170141183460469231731687303715884105727") t.Error("Expected a number between 0 and 170141183460469231731687303715884105727")

View File

@ -10,22 +10,22 @@ var prstore ProfileReplyStore
type ProfileReplyStore interface { type ProfileReplyStore interface {
Get(id int) (*Reply, error) Get(id int) (*Reply, error)
Create(profileID int, content string, createdBy int, ipaddress string) (id int, err error)
} }
// TODO: Refactor this to stop using the global stmt store // TODO: Refactor this to stop using the global stmt store
// TODO: Add more methods to this like Create() // TODO: Add more methods to this like Create()
type SQLProfileReplyStore struct { type SQLProfileReplyStore struct {
get *sql.Stmt get *sql.Stmt
create *sql.Stmt
} }
func NewSQLProfileReplyStore() (*SQLProfileReplyStore, error) { func NewSQLProfileReplyStore() (*SQLProfileReplyStore, error) {
getUserReplyStmt, err := qgen.Builder.SimpleSelect("users_replies", "uid, content, createdBy, createdAt, lastEdit, lastEditBy, ipaddress", "rid = ?", "", "") acc := qgen.Builder.Accumulator()
if err != nil {
return nil, err
}
return &SQLProfileReplyStore{ return &SQLProfileReplyStore{
get: getUserReplyStmt, get: acc.SimpleSelect("users_replies", "uid, content, createdBy, createdAt, lastEdit, lastEditBy, ipaddress", "rid = ?", "", ""),
}, nil create: acc.SimpleInsert("users_replies", "uid, content, parsed_content, createdAt, createdBy, ipaddress", "?,?,?,UTC_TIMESTAMP(),?,?"),
}, acc.FirstError()
} }
func (store *SQLProfileReplyStore) Get(id int) (*Reply, error) { func (store *SQLProfileReplyStore) Get(id int) (*Reply, error) {
@ -33,3 +33,17 @@ func (store *SQLProfileReplyStore) Get(id int) (*Reply, error) {
err := store.get.QueryRow(id).Scan(&reply.ParentID, &reply.Content, &reply.CreatedBy, &reply.CreatedAt, &reply.LastEdit, &reply.LastEditBy, &reply.IPAddress) err := store.get.QueryRow(id).Scan(&reply.ParentID, &reply.Content, &reply.CreatedBy, &reply.CreatedAt, &reply.LastEdit, &reply.LastEditBy, &reply.IPAddress)
return &reply, err return &reply, err
} }
func (store *SQLProfileReplyStore) Create(profileID int, content string, createdBy int, ipaddress string) (id int, err error) {
res, err := store.create.Exec(profileID, content, parseMessage(content, 0, ""), createdBy, ipaddress)
if err != nil {
return 0, err
}
lastID, err := res.LastInsertId()
if err != nil {
return 0, err
}
// Should we reload the user?
return int(lastID), err
}

View File

@ -34,10 +34,10 @@ function bindToAlerts() {
} }
// TODO: Add the ability for users to dismiss alerts // TODO: Add the ability for users to dismiss alerts
function loadAlerts(menu_alerts) function loadAlerts(menuAlerts)
{ {
var alertListNode = menu_alerts.getElementsByClassName("alertList")[0]; var alertListNode = menuAlerts.getElementsByClassName("alertList")[0];
var alertCounterNode = menu_alerts.getElementsByClassName("alert_counter")[0]; var alertCounterNode = menuAlerts.getElementsByClassName("alert_counter")[0];
alertCounterNode.textContent = "0"; alertCounterNode.textContent = "0";
$.ajax({ $.ajax({
type: 'get', type: 'get',
@ -77,16 +77,16 @@ function loadAlerts(menu_alerts)
if(data.msgCount != 0 && data.msgCount != undefined) { if(data.msgCount != 0 && data.msgCount != undefined) {
alertCounterNode.textContent = data.msgCount; alertCounterNode.textContent = data.msgCount;
menu_alerts.classList.add("has_alerts"); menuAlerts.classList.add("has_alerts");
} else { } else {
menu_alerts.classList.remove("has_alerts"); menuAlerts.classList.remove("has_alerts");
} }
alertCount = data.msgCount; alertCount = data.msgCount;
bindToAlerts(); bindToAlerts();
}, },
error: function(magic,theStatus,error) { error: function(magic,theStatus,error) {
var errtxt let errtxt
try { try {
var data = JSON.parse(magic.responseText); var data = JSON.parse(magic.responseText);
if("errmsg" in data) errtxt = data.errmsg; if("errmsg" in data) errtxt = data.errmsg;
@ -96,7 +96,7 @@ function loadAlerts(menu_alerts)
console.log(magic.responseText); console.log(magic.responseText);
console.log(err); console.log(err);
} }
console.log("error: ",error); console.log("error", error);
alertListNode.innerHTML = "<div class='alertItem'>"+errtxt+"</div>"; alertListNode.innerHTML = "<div class='alertItem'>"+errtxt+"</div>";
} }
}); });
@ -121,8 +121,7 @@ function SplitN(data,ch,n) {
return out; return out;
} }
$(document).ready(function(){ function runWebSockets() {
if(window["WebSocket"]) {
if(window.location.protocol == "https:") if(window.location.protocol == "https:")
conn = new WebSocket("wss://" + document.location.host + "/ws/"); conn = new WebSocket("wss://" + document.location.host + "/ws/");
else conn = new WebSocket("ws://" + document.location.host + "/ws/"); else conn = new WebSocket("ws://" + document.location.host + "/ws/");
@ -163,9 +162,9 @@ $(document).ready(function(){
//console.log(alist); //console.log(alist);
// TODO: Add support for other alert feeds like PM Alerts // TODO: Add support for other alert feeds like PM Alerts
var general_alerts = document.getElementById("general_alerts"); var generalAlerts = document.getElementById("general_alerts");
var alertListNode = general_alerts.getElementsByClassName("alertList")[0]; var alertListNode = generalAlerts.getElementsByClassName("alertList")[0];
var alertCounterNode = general_alerts.getElementsByClassName("alert_counter")[0]; var alertCounterNode = generalAlerts.getElementsByClassName("alert_counter")[0];
alertListNode.innerHTML = alist; alertListNode.innerHTML = alist;
alertCounterNode.textContent = alertCount; alertCounterNode.textContent = alertCount;
@ -199,6 +198,9 @@ $(document).ready(function(){
} }
} }
} }
$(document).ready(function(){
if(window["WebSocket"]) runWebSockets();
else conn = false; else conn = false;
$(".open_edit").click(function(event){ $(".open_edit").click(function(event){

View File

@ -115,9 +115,7 @@ func (build *accBuilder) Purge(table string) *sql.Stmt {
return build.prepare(build.adapter.Purge("_builder", table)) return build.prepare(build.adapter.Purge("_builder", table))
} }
// These ones support transactions func (build *accBuilder) prepareTx(tx *sql.Tx, res string, err error) (stmt *sql.Stmt) {
func (build *accBuilder) SimpleSelectTx(tx *sql.Tx, table string, columns string, where string, orderby string, limit string) (stmt *sql.Stmt) {
res, err := build.adapter.SimpleSelect("_builder", table, columns, where, orderby, limit)
if err != nil { if err != nil {
build.recordError(err) build.recordError(err)
return nil return nil
@ -127,70 +125,40 @@ func (build *accBuilder) SimpleSelectTx(tx *sql.Tx, table string, columns string
return stmt return stmt
} }
// These ones support transactions
func (build *accBuilder) SimpleSelectTx(tx *sql.Tx, table string, columns string, where string, orderby string, limit string) (stmt *sql.Stmt) {
res, err := build.adapter.SimpleSelect("_builder", table, columns, where, orderby, limit)
return build.prepareTx(tx, res, err)
}
func (build *accBuilder) SimpleCountTx(tx *sql.Tx, table string, where string, limit string) (stmt *sql.Stmt) { func (build *accBuilder) SimpleCountTx(tx *sql.Tx, table string, where string, limit string) (stmt *sql.Stmt) {
res, err := build.adapter.SimpleCount("_builder", table, where, limit) res, err := build.adapter.SimpleCount("_builder", table, where, limit)
if err != nil { return build.prepareTx(tx, res, err)
build.recordError(err)
return nil
}
stmt, err = tx.Prepare(res)
build.recordError(err)
return stmt
} }
func (build *accBuilder) SimpleLeftJoinTx(tx *sql.Tx, table1 string, table2 string, columns string, joiners string, where string, orderby string, limit string) (stmt *sql.Stmt) { func (build *accBuilder) SimpleLeftJoinTx(tx *sql.Tx, table1 string, table2 string, columns string, joiners string, where string, orderby string, limit string) (stmt *sql.Stmt) {
res, err := build.adapter.SimpleLeftJoin("_builder", table1, table2, columns, joiners, where, orderby, limit) res, err := build.adapter.SimpleLeftJoin("_builder", table1, table2, columns, joiners, where, orderby, limit)
if err != nil { return build.prepareTx(tx, res, err)
build.recordError(err)
return nil
}
stmt, err = tx.Prepare(res)
build.recordError(err)
return stmt
} }
func (build *accBuilder) SimpleInnerJoinTx(tx *sql.Tx, table1 string, table2 string, columns string, joiners string, where string, orderby string, limit string) (stmt *sql.Stmt) { func (build *accBuilder) SimpleInnerJoinTx(tx *sql.Tx, table1 string, table2 string, columns string, joiners string, where string, orderby string, limit string) (stmt *sql.Stmt) {
res, err := build.adapter.SimpleInnerJoin("_builder", table1, table2, columns, joiners, where, orderby, limit) res, err := build.adapter.SimpleInnerJoin("_builder", table1, table2, columns, joiners, where, orderby, limit)
if err != nil { return build.prepareTx(tx, res, err)
build.recordError(err)
return nil
}
stmt, err = tx.Prepare(res)
build.recordError(err)
return stmt
} }
func (build *accBuilder) CreateTableTx(tx *sql.Tx, table string, charset string, collation string, columns []DB_Table_Column, keys []DB_Table_Key) (stmt *sql.Stmt) { func (build *accBuilder) CreateTableTx(tx *sql.Tx, table string, charset string, collation string, columns []DB_Table_Column, keys []DB_Table_Key) (stmt *sql.Stmt) {
res, err := build.adapter.CreateTable("_builder", table, charset, collation, columns, keys) res, err := build.adapter.CreateTable("_builder", table, charset, collation, columns, keys)
if err != nil { return build.prepareTx(tx, res, err)
build.recordError(err)
return nil
}
stmt, err = tx.Prepare(res)
build.recordError(err)
return stmt
} }
func (build *accBuilder) SimpleInsertTx(tx *sql.Tx, table string, columns string, fields string) (stmt *sql.Stmt) { func (build *accBuilder) SimpleInsertTx(tx *sql.Tx, table string, columns string, fields string) (stmt *sql.Stmt) {
res, err := build.adapter.SimpleInsert("_builder", table, columns, fields) res, err := build.adapter.SimpleInsert("_builder", table, columns, fields)
if err != nil { return build.prepareTx(tx, res, err)
build.recordError(err)
return nil
}
stmt, err = tx.Prepare(res)
build.recordError(err)
return stmt
} }
func (build *accBuilder) SimpleInsertSelectTx(tx *sql.Tx, ins DB_Insert, sel DB_Select) (stmt *sql.Stmt) { func (build *accBuilder) SimpleInsertSelectTx(tx *sql.Tx, ins DB_Insert, sel DB_Select) (stmt *sql.Stmt) {
res, err := build.adapter.SimpleInsertSelect("_builder", ins, sel) res, err := build.adapter.SimpleInsertSelect("_builder", ins, sel)
if err != nil { return build.prepareTx(tx, res, err)
build.recordError(err)
return nil
}
stmt, err = tx.Prepare(res)
build.recordError(err)
return stmt
} }
func (build *accBuilder) SimpleInsertLeftJoinTx(tx *sql.Tx, ins DB_Insert, sel DB_Join) (stmt *sql.Stmt) { func (build *accBuilder) SimpleInsertLeftJoinTx(tx *sql.Tx, ins DB_Insert, sel DB_Join) (stmt *sql.Stmt) {
@ -206,45 +174,21 @@ func (build *accBuilder) SimpleInsertLeftJoinTx(tx *sql.Tx, ins DB_Insert, sel D
func (build *accBuilder) SimpleInsertInnerJoinTx(tx *sql.Tx, ins DB_Insert, sel DB_Join) (stmt *sql.Stmt) { func (build *accBuilder) SimpleInsertInnerJoinTx(tx *sql.Tx, ins DB_Insert, sel DB_Join) (stmt *sql.Stmt) {
res, err := build.adapter.SimpleInsertInnerJoin("_builder", ins, sel) res, err := build.adapter.SimpleInsertInnerJoin("_builder", ins, sel)
if err != nil { return build.prepareTx(tx, res, err)
build.recordError(err)
return nil
}
stmt, err = tx.Prepare(res)
build.recordError(err)
return stmt
} }
func (build *accBuilder) SimpleUpdateTx(tx *sql.Tx, table string, set string, where string) (stmt *sql.Stmt) { func (build *accBuilder) SimpleUpdateTx(tx *sql.Tx, table string, set string, where string) (stmt *sql.Stmt) {
res, err := build.adapter.SimpleUpdate("_builder", table, set, where) res, err := build.adapter.SimpleUpdate("_builder", table, set, where)
if err != nil { return build.prepareTx(tx, res, err)
build.recordError(err)
return nil
}
stmt, err = tx.Prepare(res)
build.recordError(err)
return stmt
} }
func (build *accBuilder) SimpleDeleteTx(tx *sql.Tx, table string, where string) (stmt *sql.Stmt) { func (build *accBuilder) SimpleDeleteTx(tx *sql.Tx, table string, where string) (stmt *sql.Stmt) {
res, err := build.adapter.SimpleDelete("_builder", table, where) res, err := build.adapter.SimpleDelete("_builder", table, where)
if err != nil { return build.prepareTx(tx, res, err)
build.recordError(err)
return nil
}
stmt, err = tx.Prepare(res)
build.recordError(err)
return stmt
} }
// I don't know why you need this, but here it is x.x // I don't know why you need this, but here it is x.x
func (build *accBuilder) PurgeTx(tx *sql.Tx, table string) (stmt *sql.Stmt) { func (build *accBuilder) PurgeTx(tx *sql.Tx, table string) (stmt *sql.Stmt) {
res, err := build.adapter.Purge("_builder", table) res, err := build.adapter.Purge("_builder", table)
if err != nil { return build.prepareTx(tx, res, err)
build.recordError(err)
return nil
}
stmt, err = tx.Prepare(res)
build.recordError(err)
return stmt
} }

View File

@ -212,9 +212,9 @@ func seedTables(adapter qgen.DB_Adapter) error {
// //
qgen.Install.SimpleInsert("topics", "title, content, parsed_content, createdAt, lastReplyAt, lastReplyBy, createdBy, parentID", "'Test Topic','A topic automatically generated by the software.','A topic automatically generated by the software.',UTC_TIMESTAMP(),UTC_TIMESTAMP(),1,1,2") qgen.Install.SimpleInsert("topics", "title, content, parsed_content, createdAt, lastReplyAt, lastReplyBy, createdBy, parentID, ipaddress", "'Test Topic','A topic automatically generated by the software.','A topic automatically generated by the software.',UTC_TIMESTAMP(),UTC_TIMESTAMP(),1,1,2,'::1'")
qgen.Install.SimpleInsert("replies", "tid, content, parsed_content, createdAt, createdBy, lastUpdated, lastEdit, lastEditBy", "1,'A reply!','A reply!',UTC_TIMESTAMP(),1,UTC_TIMESTAMP(),0,0") qgen.Install.SimpleInsert("replies", "tid, content, parsed_content, createdAt, createdBy, lastUpdated, lastEdit, lastEditBy, ipaddress", "1,'A reply!','A reply!',UTC_TIMESTAMP(),1,UTC_TIMESTAMP(),0,0,'::1'")
return nil return nil
} }
@ -328,8 +328,6 @@ func writeInserts(adapter qgen.DB_Adapter) error {
adapter.SimpleInsert("addEmail", "emails", "email, uid, validated, token", "?,?,?,?") adapter.SimpleInsert("addEmail", "emails", "email, uid, validated, token", "?,?,?,?")
adapter.SimpleInsert("createProfileReply", "users_replies", "uid, content, parsed_content, createdAt, createdBy, ipaddress", "?,?,?,UTC_TIMESTAMP(),?,?")
adapter.SimpleInsert("addSubscription", "activity_subscriptions", "user, targetID, targetType, level", "?,?,?,2") adapter.SimpleInsert("addSubscription", "activity_subscriptions", "user, targetID, targetType, level", "?,?,?,2")
adapter.SimpleInsert("addForumPermsToForum", "forums_permissions", "gid,fid,preset,permissions", "?,?,?,?") adapter.SimpleInsert("addForumPermsToForum", "forums_permissions", "gid,fid,preset,permissions", "?,?,?,?")

View File

@ -16,18 +16,11 @@ type SQLReplyStore struct {
} }
func NewSQLReplyStore() (*SQLReplyStore, error) { func NewSQLReplyStore() (*SQLReplyStore, error) {
getReplyStmt, err := qgen.Builder.SimpleSelect("replies", "tid, content, createdBy, createdAt, lastEdit, lastEditBy, ipaddress, likeCount", "rid = ?", "", "") acc := qgen.Builder.Accumulator()
if err != nil {
return nil, err
}
createReplyStmt, err := qgen.Builder.SimpleInsert("replies", "tid, content, parsed_content, createdAt, lastUpdated, ipaddress, words, createdBy", "?,?,?,UTC_TIMESTAMP(),UTC_TIMESTAMP(),?,?,?")
if err != nil {
return nil, err
}
return &SQLReplyStore{ return &SQLReplyStore{
get: getReplyStmt, get: acc.SimpleSelect("replies", "tid, content, createdBy, createdAt, lastEdit, lastEditBy, ipaddress, likeCount", "rid = ?", "", ""),
create: createReplyStmt, create: acc.SimpleInsert("replies", "tid, content, parsed_content, createdAt, lastUpdated, ipaddress, words, createdBy", "?,?,?,UTC_TIMESTAMP(),UTC_TIMESTAMP(),?,?,?"),
}, nil }, acc.FirstError()
} }
func (store *SQLReplyStore) Get(id int) (*Reply, error) { func (store *SQLReplyStore) Get(id int) (*Reply, error) {

View File

@ -5,16 +5,48 @@ package main
import ( import (
"errors" "errors"
"log"
"regexp" "regexp"
"text/template/parse"
) )
var tagFinder *regexp.Regexp var tagFinder *regexp.Regexp
var limeFuncMap = map[string]interface{}{
"and": "&&",
"not": "!",
"or": "||",
"eq": true,
"ge": true,
"gt": true,
"le": true,
"lt": true,
"ne": true,
"add": true,
"subtract": true,
"multiply": true,
"divide": true,
}
func init() { func init() {
tagFinder = regexp.MustCompile(`(?s)\{\{(.*)\}\}`) tagFinder = regexp.MustCompile(`(?s)\{\{(.*)\}\}`)
} }
func mangoParse(tmpl string) error {
tree := parse.New(name, funcMap)
var treeSet = make(map[string]*parse.Tree)
tree, err = tree.Parse(content, "{{", "}}", treeSet, limeFuncMap)
if err != nil {
return err
}
treeLength := len(tree.Root.Nodes)
log.Print("treeLength", treeLength)
return nil
}
func icecreamSoup(tmpl string) error { func icecreamSoup(tmpl string) error {
if config.MinifyTemplates {
tmpl = minify(tmpl)
}
tagIndices := tagFinder.FindAllStringIndex(tmpl, -1) tagIndices := tagFinder.FindAllStringIndex(tmpl, -1)
if tagIndices != nil && len(tagIndices) > 0 { if tagIndices != nil && len(tagIndices) > 0 {

View File

@ -25,5 +25,5 @@ INSERT INTO [forums_permissions] ([gid],[fid],[permissions]) VALUES (3,2,'{"View
INSERT INTO [forums_permissions] ([gid],[fid],[permissions]) VALUES (4,2,'{"ViewTopic":true}'); INSERT INTO [forums_permissions] ([gid],[fid],[permissions]) VALUES (4,2,'{"ViewTopic":true}');
INSERT INTO [forums_permissions] ([gid],[fid],[permissions]) VALUES (5,2,'{"ViewTopic":true}'); INSERT INTO [forums_permissions] ([gid],[fid],[permissions]) VALUES (5,2,'{"ViewTopic":true}');
INSERT INTO [forums_permissions] ([gid],[fid],[permissions]) VALUES (6,2,'{"ViewTopic":true}'); INSERT INTO [forums_permissions] ([gid],[fid],[permissions]) VALUES (6,2,'{"ViewTopic":true}');
INSERT INTO [topics] ([title],[content],[parsed_content],[createdAt],[lastReplyAt],[lastReplyBy],[createdBy],[parentID]) VALUES ('TestTopic','Atopicautomaticallygeneratedbythesoftware.','Atopicautomaticallygeneratedbythesoftware.',GETUTCDATE(),GETUTCDATE(),1,1,2); INSERT INTO [topics] ([title],[content],[parsed_content],[createdAt],[lastReplyAt],[lastReplyBy],[createdBy],[parentID],[ipaddress]) VALUES ('TestTopic','Atopicautomaticallygeneratedbythesoftware.','Atopicautomaticallygeneratedbythesoftware.',GETUTCDATE(),GETUTCDATE(),1,1,2,'::1');
INSERT INTO [replies] ([tid],[content],[parsed_content],[createdAt],[createdBy],[lastUpdated],[lastEdit],[lastEditBy]) VALUES (1,'Areply!','Areply!',GETUTCDATE(),1,GETUTCDATE(),0,0); INSERT INTO [replies] ([tid],[content],[parsed_content],[createdAt],[createdBy],[lastUpdated],[lastEdit],[lastEditBy],[ipaddress]) VALUES (1,'Areply!','Areply!',GETUTCDATE(),1,GETUTCDATE(),0,0,'::1');

View File

@ -25,5 +25,5 @@ INSERT INTO `forums_permissions`(`gid`,`fid`,`permissions`) VALUES (3,2,'{"ViewT
INSERT INTO `forums_permissions`(`gid`,`fid`,`permissions`) VALUES (4,2,'{"ViewTopic":true}'); INSERT INTO `forums_permissions`(`gid`,`fid`,`permissions`) VALUES (4,2,'{"ViewTopic":true}');
INSERT INTO `forums_permissions`(`gid`,`fid`,`permissions`) VALUES (5,2,'{"ViewTopic":true}'); INSERT INTO `forums_permissions`(`gid`,`fid`,`permissions`) VALUES (5,2,'{"ViewTopic":true}');
INSERT INTO `forums_permissions`(`gid`,`fid`,`permissions`) VALUES (6,2,'{"ViewTopic":true}'); INSERT INTO `forums_permissions`(`gid`,`fid`,`permissions`) VALUES (6,2,'{"ViewTopic":true}');
INSERT INTO `topics`(`title`,`content`,`parsed_content`,`createdAt`,`lastReplyAt`,`lastReplyBy`,`createdBy`,`parentID`) VALUES ('TestTopic','Atopicautomaticallygeneratedbythesoftware.','Atopicautomaticallygeneratedbythesoftware.',UTC_TIMESTAMP(),UTC_TIMESTAMP(),1,1,2); INSERT INTO `topics`(`title`,`content`,`parsed_content`,`createdAt`,`lastReplyAt`,`lastReplyBy`,`createdBy`,`parentID`,`ipaddress`) VALUES ('TestTopic','Atopicautomaticallygeneratedbythesoftware.','Atopicautomaticallygeneratedbythesoftware.',UTC_TIMESTAMP(),UTC_TIMESTAMP(),1,1,2,'::1');
INSERT INTO `replies`(`tid`,`content`,`parsed_content`,`createdAt`,`createdBy`,`lastUpdated`,`lastEdit`,`lastEditBy`) VALUES (1,'Areply!','Areply!',UTC_TIMESTAMP(),1,UTC_TIMESTAMP(),0,0); INSERT INTO `replies`(`tid`,`content`,`parsed_content`,`createdAt`,`createdBy`,`lastUpdated`,`lastEdit`,`lastEditBy`,`ipaddress`) VALUES (1,'Areply!','Areply!',UTC_TIMESTAMP(),1,UTC_TIMESTAMP(),0,0,'::1');

View File

@ -498,6 +498,8 @@ var topic_alt_104 = []byte(`
`) `)
var profile_0 = []byte(` var profile_0 = []byte(`
<div id="profile_container">
<div id="profile_left_lane" class="colstack_left"> <div id="profile_left_lane" class="colstack_left">
<!--<header class="colstack_item colstack_head rowhead"> <!--<header class="colstack_item colstack_head rowhead">
<div class="rowitem"><h1>Profile</h1></div> <div class="rowitem"><h1>Profile</h1></div>
@ -639,6 +641,8 @@ var profile_42 = []byte(`' type="hidden" />
var profile_43 = []byte(` var profile_43 = []byte(`
</div> </div>
</div>
`) `)
var profile_44 = []byte(` var profile_44 = []byte(`
<script type="text/javascript"> <script type="text/javascript">

View File

@ -121,24 +121,7 @@ func (c *CTemplateSet) compileTemplate(name string, dir string, expects string,
c.FragmentCursor = make(map[string]int) c.FragmentCursor = make(map[string]int)
c.FragmentCursor[fname] = 0 c.FragmentCursor[fname] = 0
subtree := c.tlist[fname] out += c.rootIterate(c.tlist[fname], varholder, holdreflect, fname)
if dev.TemplateDebug {
fmt.Println(subtree.Root)
}
treeLength := len(subtree.Root.Nodes)
for index, node := range subtree.Root.Nodes {
if dev.TemplateDebug {
fmt.Println("Node: " + node.String())
}
c.previousNode = c.currentNode
c.currentNode = node.Type()
if treeLength != (index + 1) {
c.nextNode = subtree.Root.Nodes[index+1].Type()
}
out += c.compileSwitch(varholder, holdreflect, fname, node)
}
var importList string var importList string
if c.doImports { if c.doImports {
@ -178,6 +161,26 @@ w.Write([]byte(`, " + ", -1)
return fout, nil return fout, nil
} }
func (c *CTemplateSet) rootIterate(tree *parse.Tree, varholder string, holdreflect reflect.Value, fname string) (out string) {
if dev.TemplateDebug {
fmt.Println(tree.Root)
}
treeLength := len(tree.Root.Nodes)
for index, node := range tree.Root.Nodes {
if dev.TemplateDebug {
fmt.Println("Node: ", node.String())
}
c.previousNode = c.currentNode
c.currentNode = node.Type()
if treeLength != (index + 1) {
c.nextNode = tree.Root.Nodes[index+1].Type()
}
out += c.compileSwitch(varholder, holdreflect, fname, node)
}
return out
}
func (c *CTemplateSet) compileSwitch(varholder string, holdreflect reflect.Value, templateName string, node interface{}) (out string) { func (c *CTemplateSet) compileSwitch(varholder string, holdreflect reflect.Value, templateName string, node interface{}) (out string) {
if dev.TemplateDebug { if dev.TemplateDebug {
fmt.Println("in compileSwitch") fmt.Println("in compileSwitch")
@ -449,7 +452,6 @@ func (c *CTemplateSet) compileVarswitch(varholder string, holdreflect reflect.Va
fmt.Println("Chain Node:", n.Node) fmt.Println("Chain Node:", n.Node)
fmt.Println("Chain Node Args:", node.Args) fmt.Println("Chain Node Args:", node.Args)
} }
break
case *parse.IdentifierNode: case *parse.IdentifierNode:
if dev.TemplateDebug { if dev.TemplateDebug {
fmt.Println("Identifier Node:", node) fmt.Println("Identifier Node:", node)
@ -957,7 +959,6 @@ func (c *CTemplateSet) compileSubtemplate(pvarholder string, pholdreflect reflec
case *parse.DotNode: case *parse.DotNode:
varholder = pvarholder varholder = pvarholder
holdreflect = pholdreflect holdreflect = pholdreflect
break
case *parse.NilNode: case *parse.NilNode:
panic("Nil is not a command x.x") panic("Nil is not a command x.x")
default: default:
@ -995,19 +996,7 @@ func (c *CTemplateSet) compileSubtemplate(pvarholder string, pholdreflect reflec
c.localVars[fname]["."] = VarItemReflect{".", varholder, holdreflect} c.localVars[fname]["."] = VarItemReflect{".", varholder, holdreflect}
c.FragmentCursor[fname] = 0 c.FragmentCursor[fname] = 0
treeLength := len(subtree.Root.Nodes) out += c.rootIterate(subtree, varholder, holdreflect, fname)
for index, node := range subtree.Root.Nodes {
if dev.TemplateDebug {
fmt.Println("Node:", node.String())
}
c.previousNode = c.currentNode
c.currentNode = node.Type()
if treeLength != (index + 1) {
c.nextNode = subtree.Root.Nodes[index+1].Type()
}
out += c.compileSwitch(varholder, holdreflect, fname, node)
}
return out return out
} }

View File

@ -1,5 +1,7 @@
{{template "header.html" . }} {{template "header.html" . }}
<div id="profile_container">
<div id="profile_left_lane" class="colstack_left"> <div id="profile_left_lane" class="colstack_left">
<!--<header class="colstack_item colstack_head rowhead"> <!--<header class="colstack_item colstack_head rowhead">
<div class="rowitem"><h1>Profile</h1></div> <div class="rowitem"><h1>Profile</h1></div>
@ -98,6 +100,8 @@
{{end}} {{end}}
</div> </div>
</div>
{{/** Quick subpage switcher **/}} {{/** Quick subpage switcher **/}}
{{/** TODO: Stop inlining this **/}} {{/** TODO: Stop inlining this **/}}
<script type="text/javascript"> <script type="text/javascript">