diff --git a/gen_mssql.go b/gen_mssql.go index 930e1e5d..becff983 100644 --- a/gen_mssql.go +++ b/gen_mssql.go @@ -52,7 +52,6 @@ type Stmts struct { addActivity *sql.Stmt notifyOne *sql.Stmt addEmail *sql.Stmt - createProfileReply *sql.Stmt addSubscription *sql.Stmt addForumPermsToForum *sql.Stmt addPlugin *sql.Stmt @@ -438,13 +437,6 @@ func _gen_mssql() (err error) { 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.") stmts.addSubscription, err = db.Prepare("INSERT INTO [activity_subscriptions] ([user],[targetID],[targetType],[level]) VALUES (?,?,?,2)") if err != nil { diff --git a/gen_mysql.go b/gen_mysql.go index 025cb718..8475633b 100644 --- a/gen_mysql.go +++ b/gen_mysql.go @@ -54,7 +54,6 @@ type Stmts struct { addActivity *sql.Stmt notifyOne *sql.Stmt addEmail *sql.Stmt - createProfileReply *sql.Stmt addSubscription *sql.Stmt addForumPermsToForum *sql.Stmt addPlugin *sql.Stmt @@ -396,12 +395,6 @@ func _gen_mysql() (err error) { 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.") stmts.addSubscription, err = db.Prepare("INSERT INTO `activity_subscriptions`(`user`,`targetID`,`targetType`,`level`) VALUES (?,?,?,2)") if err != nil { diff --git a/member_routes.go b/member_routes.go index 9503c4f1..e3888699 100644 --- a/member_routes.go +++ b/member_routes.go @@ -559,17 +559,13 @@ func routeProfileReplyCreate(w http.ResponseWriter, r *http.Request, user User) } 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 { return InternalError(err, w, r) } - var userName string - err = stmts.getUserName.QueryRow(uid).Scan(&userName) - if err == ErrNoRows { + if !users.Exists(uid) { 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) diff --git a/misc_test.go b/misc_test.go index 0daef579..28d49ccb 100644 --- a/misc_test.go +++ b/misc_test.go @@ -550,6 +550,8 @@ func topicStoreTest(t *testing.T) { t.Error("The number of topics should be bigger than zero") t.Error("count", count) } + + // TODO: Test topic creation and retrieving that created topic plus reload and inspecting the cache } func TestForumStore(t *testing.T) { @@ -737,16 +739,28 @@ func TestReplyStore(t *testing.T) { reply, err := rstore.Get(1) 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 { - t.Errorf("RID #1 has the wrong ID. It should be 1 not %d", reply.ID) - } - if reply.ParentID != 1 { - t.Errorf("The parent topic of RID #1 should be 1 not %d", reply.ParentID) - } - if reply.CreatedBy != 1 { - t.Errorf("The creator of RID #1 should be 1 not %d", reply.CreatedBy) - } + _, err = rstore.Get(2) + recordMustNotExist(t, err, "RID #2 shouldn't exist") + + // TODO: Test Create and Get + //Create(tid int, content string, ipaddress string, fid int, uid int) (id int, err error) + rid, err := rstore.Create(1, "Fofofo", "::1", 2, 1) + expectNilErr(t, err) + 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) { @@ -758,10 +772,30 @@ func TestProfileReplyStore(t *testing.T) { } _, err := prstore.Get(-1) - recordMustNotExist(t, err, "RID #-1 shouldn't exist") + recordMustNotExist(t, err, "PRID #-1 shouldn't exist") _, 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) { diff --git a/plugin_test.go b/plugin_test.go index 63179491..49a5f7a6 100644 --- a/plugin_test.go +++ b/plugin_test.go @@ -174,7 +174,7 @@ func TestBBCodeRender(t *testing.T) { msg = "[rand]18446744073709551615[/rand]" // Unsigned 64-bit MAX t.Log("Testing string '" + msg + "'") res = bbcodeFullParse(msg) - conv, err = strconv.Atoi(res) + _, err = strconv.Atoi(res) if err != nil && res != "[Invalid Number][rand]18446744073709551615[/rand]" { t.Error("Bad output:", "'"+res+"'") 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 t.Log("Testing string '" + msg + "'") res = bbcodeFullParse(msg) - conv, err = strconv.Atoi(res) + _, err = strconv.Atoi(res) if err != nil && res != "[Invalid Number][rand]170141183460469231731687303715884105727[/rand]" { t.Error("Bad output:", "'"+res+"'") t.Error("Expected a number between 0 and 170141183460469231731687303715884105727") diff --git a/profile_reply_store.go b/profile_reply_store.go index 59b7087c..cfb861af 100644 --- a/profile_reply_store.go +++ b/profile_reply_store.go @@ -10,22 +10,22 @@ var prstore ProfileReplyStore type ProfileReplyStore interface { 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: Add more methods to this like Create() type SQLProfileReplyStore struct { - get *sql.Stmt + get *sql.Stmt + create *sql.Stmt } func NewSQLProfileReplyStore() (*SQLProfileReplyStore, error) { - getUserReplyStmt, err := qgen.Builder.SimpleSelect("users_replies", "uid, content, createdBy, createdAt, lastEdit, lastEditBy, ipaddress", "rid = ?", "", "") - if err != nil { - return nil, err - } + acc := qgen.Builder.Accumulator() return &SQLProfileReplyStore{ - get: getUserReplyStmt, - }, nil + get: acc.SimpleSelect("users_replies", "uid, content, createdBy, createdAt, lastEdit, lastEditBy, ipaddress", "rid = ?", "", ""), + create: acc.SimpleInsert("users_replies", "uid, content, parsed_content, createdAt, createdBy, ipaddress", "?,?,?,UTC_TIMESTAMP(),?,?"), + }, acc.FirstError() } 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) 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 +} diff --git a/public/global.js b/public/global.js index 289759f9..fe8c24ba 100644 --- a/public/global.js +++ b/public/global.js @@ -34,72 +34,72 @@ function bindToAlerts() { } // TODO: Add the ability for users to dismiss alerts -function loadAlerts(menu_alerts) +function loadAlerts(menuAlerts) { - var alertListNode = menu_alerts.getElementsByClassName("alertList")[0]; - var alertCounterNode = menu_alerts.getElementsByClassName("alert_counter")[0]; + var alertListNode = menuAlerts.getElementsByClassName("alertList")[0]; + var alertCounterNode = menuAlerts.getElementsByClassName("alert_counter")[0]; alertCounterNode.textContent = "0"; $.ajax({ - type: 'get', - dataType: 'json', - url:'/api/?action=get&module=alerts', - success: function(data) { - if("errmsg" in data) { - alertListNode.innerHTML = "
"+data.errmsg+"
"; - return; - } - - var alist = ""; - for(var i in data.msgs) { - var msg = data.msgs[i]; - var mmsg = msg.msg; - - if("sub" in msg) { - for(var i = 0; i < msg.sub.length; i++) { - mmsg = mmsg.replace("\{"+i+"\}", msg.sub[i]); - //console.log("Sub #" + i + ":",msg.sub[i]); - } - } - - if("avatar" in msg) { - alist += "
"+mmsg+"
"; - alertList.push("
"+mmsg+"
"); - } else { - alist += "
"+mmsg+"
"; - alertList.push("
"+mmsg+"
"); - } - //console.log(msg); - //console.log(mmsg); - } - - if(alist == "") alist = "
You don't have any alerts
"; - alertListNode.innerHTML = alist; - - if(data.msgCount != 0 && data.msgCount != undefined) { - alertCounterNode.textContent = data.msgCount; - menu_alerts.classList.add("has_alerts"); - } else { - menu_alerts.classList.remove("has_alerts"); - } - alertCount = data.msgCount; - - bindToAlerts(); - }, - error: function(magic,theStatus,error) { - var errtxt - try { - var data = JSON.parse(magic.responseText); - if("errmsg" in data) errtxt = data.errmsg; - else errtxt = "Unable to get the alerts"; - } catch(err) { - errtxt = "Unable to get the alerts"; - console.log(magic.responseText); - console.log(err); - } - console.log("error: ",error); - alertListNode.innerHTML = "
"+errtxt+"
"; + type: 'get', + dataType: 'json', + url:'/api/?action=get&module=alerts', + success: function(data) { + if("errmsg" in data) { + alertListNode.innerHTML = "
"+data.errmsg+"
"; + return; } - }); + + var alist = ""; + for(var i in data.msgs) { + var msg = data.msgs[i]; + var mmsg = msg.msg; + + if("sub" in msg) { + for(var i = 0; i < msg.sub.length; i++) { + mmsg = mmsg.replace("\{"+i+"\}", msg.sub[i]); + //console.log("Sub #" + i + ":",msg.sub[i]); + } + } + + if("avatar" in msg) { + alist += "
"+mmsg+"
"; + alertList.push("
"+mmsg+"
"); + } else { + alist += "
"+mmsg+"
"; + alertList.push("
"+mmsg+"
"); + } + //console.log(msg); + //console.log(mmsg); + } + + if(alist == "") alist = "
You don't have any alerts
"; + alertListNode.innerHTML = alist; + + if(data.msgCount != 0 && data.msgCount != undefined) { + alertCounterNode.textContent = data.msgCount; + menuAlerts.classList.add("has_alerts"); + } else { + menuAlerts.classList.remove("has_alerts"); + } + alertCount = data.msgCount; + + bindToAlerts(); + }, + error: function(magic,theStatus,error) { + let errtxt + try { + var data = JSON.parse(magic.responseText); + if("errmsg" in data) errtxt = data.errmsg; + else errtxt = "Unable to get the alerts"; + } catch(err) { + errtxt = "Unable to get the alerts"; + console.log(magic.responseText); + console.log(err); + } + console.log("error", error); + alertListNode.innerHTML = "
"+errtxt+"
"; + } + }); } function SplitN(data,ch,n) { @@ -121,84 +121,86 @@ function SplitN(data,ch,n) { return out; } -$(document).ready(function(){ - if(window["WebSocket"]) { - if(window.location.protocol == "https:") - conn = new WebSocket("wss://" + document.location.host + "/ws/"); - else conn = new WebSocket("ws://" + document.location.host + "/ws/"); +function runWebSockets() { + if(window.location.protocol == "https:") + conn = new WebSocket("wss://" + document.location.host + "/ws/"); + else conn = new WebSocket("ws://" + document.location.host + "/ws/"); - conn.onopen = function() { - console.log("The WebSockets connection was opened"); - conn.send("page " + document.location.pathname + '\r'); - // TODO: Don't ask again, if it's denied. We could have a setting in the UCP which automatically requests this when someone flips desktop notifications on - Notification.requestPermission(); - } - conn.onclose = function() { - conn = false; - console.log("The WebSockets connection was closed"); - } - conn.onmessage = function(event) { - //console.log("WS_Message:", event.data); - if(event.data[0] == "{") { - try { - var data = JSON.parse(event.data); - } catch(err) { - console.log(err); - } - - if ("msg" in data) { - var msg = data.msg - if("sub" in data) - for(var i = 0; i < data.sub.length; i++) - msg = msg.replace("\{"+i+"\}", data.sub[i]); - - if("avatar" in data) alertList.push("
"+msg+"
"); - else alertList.push("
"+msg+"
"); - if(alertList.length > 8) alertList.shift(); - //console.log("post alertList",alertList); - alertCount++; - - var alist = "" - for (var i = 0; i < alertList.length; i++) alist += alertList[i]; - - //console.log(alist); - // TODO: Add support for other alert feeds like PM Alerts - var general_alerts = document.getElementById("general_alerts"); - var alertListNode = general_alerts.getElementsByClassName("alertList")[0]; - var alertCounterNode = general_alerts.getElementsByClassName("alert_counter")[0]; - alertListNode.innerHTML = alist; - alertCounterNode.textContent = alertCount; - - // TODO: Add some sort of notification queue to avoid flooding the end-user with notices? - // TODO: Use the site name instead of "Something Happened" - if(Notification.permission === "granted") { - var n = new Notification("Something Happened",{ - body: msg, - icon: data.avatar, - }); - setTimeout(n.close.bind(n), 8000); - } - - bindToAlerts(); - } + conn.onopen = function() { + console.log("The WebSockets connection was opened"); + conn.send("page " + document.location.pathname + '\r'); + // TODO: Don't ask again, if it's denied. We could have a setting in the UCP which automatically requests this when someone flips desktop notifications on + Notification.requestPermission(); + } + conn.onclose = function() { + conn = false; + console.log("The WebSockets connection was closed"); + } + conn.onmessage = function(event) { + //console.log("WS_Message:", event.data); + if(event.data[0] == "{") { + try { + var data = JSON.parse(event.data); + } catch(err) { + console.log(err); } - var messages = event.data.split('\r'); - for(var i = 0; i < messages.length; i++) { - //console.log("Message: ",messages[i]); - if(messages[i].startsWith("set ")) { - //msgblocks = messages[i].split(' ',3); - let msgblocks = SplitN(messages[i]," ",3); - if(msgblocks.length < 3) continue; - document.querySelector(msgblocks[1]).innerHTML = msgblocks[2]; - } else if(messages[i].startsWith("set-class ")) { - let msgblocks = SplitN(messages[i]," ",3); - if(msgblocks.length < 3) continue; - document.querySelector(msgblocks[1]).className = msgblocks[2]; + if ("msg" in data) { + var msg = data.msg + if("sub" in data) + for(var i = 0; i < data.sub.length; i++) + msg = msg.replace("\{"+i+"\}", data.sub[i]); + + if("avatar" in data) alertList.push("
"+msg+"
"); + else alertList.push("
"+msg+"
"); + if(alertList.length > 8) alertList.shift(); + //console.log("post alertList",alertList); + alertCount++; + + var alist = "" + for (var i = 0; i < alertList.length; i++) alist += alertList[i]; + + //console.log(alist); + // TODO: Add support for other alert feeds like PM Alerts + var generalAlerts = document.getElementById("general_alerts"); + var alertListNode = generalAlerts.getElementsByClassName("alertList")[0]; + var alertCounterNode = generalAlerts.getElementsByClassName("alert_counter")[0]; + alertListNode.innerHTML = alist; + alertCounterNode.textContent = alertCount; + + // TODO: Add some sort of notification queue to avoid flooding the end-user with notices? + // TODO: Use the site name instead of "Something Happened" + if(Notification.permission === "granted") { + var n = new Notification("Something Happened",{ + body: msg, + icon: data.avatar, + }); + setTimeout(n.close.bind(n), 8000); } + + bindToAlerts(); + } + } + + var messages = event.data.split('\r'); + for(var i = 0; i < messages.length; i++) { + //console.log("Message: ",messages[i]); + if(messages[i].startsWith("set ")) { + //msgblocks = messages[i].split(' ',3); + let msgblocks = SplitN(messages[i]," ",3); + if(msgblocks.length < 3) continue; + document.querySelector(msgblocks[1]).innerHTML = msgblocks[2]; + } else if(messages[i].startsWith("set-class ")) { + let msgblocks = SplitN(messages[i]," ",3); + if(msgblocks.length < 3) continue; + document.querySelector(msgblocks[1]).className = msgblocks[2]; } } } +} + +$(document).ready(function(){ + if(window["WebSocket"]) runWebSockets(); else conn = false; $(".open_edit").click(function(event){ diff --git a/query_gen/lib/accumulator.go b/query_gen/lib/accumulator.go index 0a99b7c8..7e3022b0 100644 --- a/query_gen/lib/accumulator.go +++ b/query_gen/lib/accumulator.go @@ -115,9 +115,7 @@ func (build *accBuilder) Purge(table string) *sql.Stmt { return build.prepare(build.adapter.Purge("_builder", table)) } -// 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) +func (build *accBuilder) prepareTx(tx *sql.Tx, res string, err error) (stmt *sql.Stmt) { if err != nil { build.recordError(err) return nil @@ -127,70 +125,40 @@ func (build *accBuilder) SimpleSelectTx(tx *sql.Tx, table string, columns string 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) { res, err := build.adapter.SimpleCount("_builder", table, where, limit) - if err != nil { - build.recordError(err) - return nil - } - stmt, err = tx.Prepare(res) - build.recordError(err) - return stmt + return build.prepareTx(tx, res, err) } 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) - if err != nil { - build.recordError(err) - return nil - } - stmt, err = tx.Prepare(res) - build.recordError(err) - return stmt + return build.prepareTx(tx, res, err) } 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) - if err != nil { - build.recordError(err) - return nil - } - stmt, err = tx.Prepare(res) - build.recordError(err) - return stmt + return build.prepareTx(tx, res, err) } 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) - if err != nil { - build.recordError(err) - return nil - } - stmt, err = tx.Prepare(res) - build.recordError(err) - return stmt + return build.prepareTx(tx, res, err) } 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) - if err != nil { - build.recordError(err) - return nil - } - stmt, err = tx.Prepare(res) - build.recordError(err) - return stmt + return build.prepareTx(tx, res, err) } func (build *accBuilder) SimpleInsertSelectTx(tx *sql.Tx, ins DB_Insert, sel DB_Select) (stmt *sql.Stmt) { res, err := build.adapter.SimpleInsertSelect("_builder", ins, sel) - if err != nil { - build.recordError(err) - return nil - } - stmt, err = tx.Prepare(res) - build.recordError(err) - return stmt + return build.prepareTx(tx, res, err) } 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) { res, err := build.adapter.SimpleInsertInnerJoin("_builder", ins, sel) - if err != nil { - build.recordError(err) - return nil - } - stmt, err = tx.Prepare(res) - build.recordError(err) - return stmt + return build.prepareTx(tx, res, err) } 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) - if err != nil { - build.recordError(err) - return nil - } - stmt, err = tx.Prepare(res) - build.recordError(err) - return stmt + return build.prepareTx(tx, res, err) } func (build *accBuilder) SimpleDeleteTx(tx *sql.Tx, table string, where string) (stmt *sql.Stmt) { res, err := build.adapter.SimpleDelete("_builder", table, where) - if err != nil { - build.recordError(err) - return nil - } - stmt, err = tx.Prepare(res) - build.recordError(err) - return stmt + return build.prepareTx(tx, res, err) } // 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) { res, err := build.adapter.Purge("_builder", table) - if err != nil { - build.recordError(err) - return nil - } - stmt, err = tx.Prepare(res) - build.recordError(err) - return stmt + return build.prepareTx(tx, res, err) } diff --git a/query_gen/main.go b/query_gen/main.go index 2a894fd6..4487d378 100644 --- a/query_gen/main.go +++ b/query_gen/main.go @@ -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 } @@ -328,8 +328,6 @@ func writeInserts(adapter qgen.DB_Adapter) error { 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("addForumPermsToForum", "forums_permissions", "gid,fid,preset,permissions", "?,?,?,?") diff --git a/reply_store.go b/reply_store.go index 8fccc8ca..40c3ce55 100644 --- a/reply_store.go +++ b/reply_store.go @@ -16,18 +16,11 @@ type SQLReplyStore struct { } func NewSQLReplyStore() (*SQLReplyStore, error) { - getReplyStmt, err := qgen.Builder.SimpleSelect("replies", "tid, content, createdBy, createdAt, lastEdit, lastEditBy, ipaddress, likeCount", "rid = ?", "", "") - 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 - } + acc := qgen.Builder.Accumulator() return &SQLReplyStore{ - get: getReplyStmt, - create: createReplyStmt, - }, nil + get: acc.SimpleSelect("replies", "tid, content, createdBy, createdAt, lastEdit, lastEditBy, ipaddress, likeCount", "rid = ?", "", ""), + create: acc.SimpleInsert("replies", "tid, content, parsed_content, createdAt, lastUpdated, ipaddress, words, createdBy", "?,?,?,UTC_TIMESTAMP(),UTC_TIMESTAMP(),?,?,?"), + }, acc.FirstError() } func (store *SQLReplyStore) Get(id int) (*Reply, error) { diff --git a/rev_templates.go b/rev_templates.go index b88de87d..1a46a83b 100644 --- a/rev_templates.go +++ b/rev_templates.go @@ -5,16 +5,48 @@ package main import ( "errors" + "log" "regexp" + "text/template/parse" ) 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() { 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 { + if config.MinifyTemplates { + tmpl = minify(tmpl) + } tagIndices := tagFinder.FindAllStringIndex(tmpl, -1) if tagIndices != nil && len(tagIndices) > 0 { diff --git a/schema/mssql/inserts.sql b/schema/mssql/inserts.sql index e37b4b62..4b794aec 100644 --- a/schema/mssql/inserts.sql +++ b/schema/mssql/inserts.sql @@ -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 (5,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 [replies] ([tid],[content],[parsed_content],[createdAt],[createdBy],[lastUpdated],[lastEdit],[lastEditBy]) VALUES (1,'Areply!','Areply!',GETUTCDATE(),1,GETUTCDATE(),0,0); +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],[ipaddress]) VALUES (1,'Areply!','Areply!',GETUTCDATE(),1,GETUTCDATE(),0,0,'::1'); diff --git a/schema/mysql/inserts.sql b/schema/mysql/inserts.sql index a588d2c3..6a48d6e6 100644 --- a/schema/mysql/inserts.sql +++ b/schema/mysql/inserts.sql @@ -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 (5,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 `replies`(`tid`,`content`,`parsed_content`,`createdAt`,`createdBy`,`lastUpdated`,`lastEdit`,`lastEditBy`) VALUES (1,'Areply!','Areply!',UTC_TIMESTAMP(),1,UTC_TIMESTAMP(),0,0); +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`,`ipaddress`) VALUES (1,'Areply!','Areply!',UTC_TIMESTAMP(),1,UTC_TIMESTAMP(),0,0,'::1'); diff --git a/template_list.go b/template_list.go index 30630c8e..ae1ce3f7 100644 --- a/template_list.go +++ b/template_list.go @@ -498,6 +498,8 @@ var topic_alt_104 = []byte(` `) var profile_0 = []byte(` +
+