Added forum descriptions. Began work on the Advanced Forum Editor. Not to be confused with the Quick Forum Editor. You can access it by going to /panel/forums/edit/{forumid} We'll fix it so the Forum Manager links to it in the next commit. Fixed the Linux shell scripts. Fixed an issue with relative timess being off by an hour due to timezones. Added reply count and author names to the topic list and forum pages. Improved the look of the forum list, forum page, and topic list. Added an overlay effect for when the alert list is open on mobile. You can now close the alert list by clicking on the bell. Removed the "Report:" prefix from report posts. Fixed a bug in the template system where "and" and "or" wouldn't work on non-boolean values. Improved the debug logging in the template system. Fixed a bug in the forum creator where the "Hidden?" value was inverted. Fixed a visual bug in the profile where the Ban button rendered in a glitchy way. Added support for hidden fields to the JS Framework for inline editing rows. Fixed a bug with the like counter rendering on-top of the alert list. Atom's stripping trailing tabs for some reason, so don't be confused if there are a bunch of weird changes.
174 lines
5.5 KiB
Go
174 lines
5.5 KiB
Go
/* WIP Under Construction */
|
|
package main
|
|
|
|
import "fmt"
|
|
import "strings"
|
|
import "log"
|
|
import "os"
|
|
|
|
var db_registry []DB_Adapter
|
|
var blank_order []DB_Order
|
|
|
|
type DB_Where struct
|
|
{
|
|
Left string
|
|
Right string
|
|
Operator string
|
|
LeftType string
|
|
RightType string
|
|
}
|
|
|
|
type DB_Joiner struct
|
|
{
|
|
Left string
|
|
Right string
|
|
}
|
|
|
|
type DB_Order struct
|
|
{
|
|
Column string
|
|
Order string
|
|
}
|
|
|
|
type DB_Adapter interface {
|
|
get_name() string
|
|
simple_insert(string,string,string,[]string,[]bool) error
|
|
//simple_replace(string,string,[]string,[]string,[]bool) error
|
|
simple_update() error
|
|
simple_select(string,string,string,string,[]DB_Order/*,int,int*/) error
|
|
simple_left_join(string,string,string,string,[]DB_Joiner,string,[]DB_Order/*,int,int*/) error
|
|
write() error
|
|
// TO-DO: Add a simple query builder
|
|
}
|
|
|
|
func main() {
|
|
log.Println("Running the query generator")
|
|
for _, adapter := range db_registry {
|
|
log.Println("Building the queries for the " + adapter.get_name() + " adapter")
|
|
write_statements(adapter)
|
|
adapter.write()
|
|
}
|
|
}
|
|
|
|
func write_statements(adapter DB_Adapter) error {
|
|
// url_prefix and url_name will be removed from this query in a later commit
|
|
adapter.simple_select("get_user","users","name, group, is_super_admin, avatar, message, url_prefix, url_name, level","uid = ?",blank_order)
|
|
|
|
adapter.simple_select("get_full_user","users","name, group, is_super_admin, session, email, avatar, message, url_prefix, url_name, level, score, last_ip","uid = ?",blank_order)
|
|
|
|
adapter.simple_select("get_topic","topics","title, content, createdBy, createdAt, is_closed, sticky, parentID, ipaddress, postCount, likeCount","tid = ?",blank_order)
|
|
|
|
adapter.simple_select("get_reply","replies","content, createdBy, createdAt, lastEdit, lastEditBy, ipaddress, likeCount","rid = ?",blank_order)
|
|
|
|
adapter.simple_select("login","users","uid, name, password, salt","name = ?",blank_order)
|
|
|
|
adapter.simple_select("get_password","users","password,salt","uid = ?",blank_order)
|
|
|
|
adapter.simple_select("username_exists","users","name","name = ?",blank_order)
|
|
|
|
/*
|
|
get_topic_list_stmt, err = db.Prepare("select topics.tid, topics.title, topics.content, topics.createdBy, topics.is_closed, topics.sticky, topics.createdAt, topics.parentID, users.name, users.avatar from topics left join users ON topics.createdBy = users.uid order by topics.sticky DESC, topics.lastReplyAt DESC, topics.createdBy DESC")
|
|
// A visual reference for me to glance at while I design this thing
|
|
*/
|
|
//func (adapter *Mysql_Adapter) simple_left_join(name string, table1 string, table2 string, columns string, joiners []DB_Joiner, where []DB_Where, orderby []DB_Order/*, offset int, maxCount int*/) error {
|
|
|
|
/*adapter.simple_left_join("get_topic_list","topics","users",
|
|
"topics.tid, topics.title, topics.content, topics.createdBy, topics.is_closed, topics.sticky, topics.createdAt, topics.parentID, users.name, users.avatar",
|
|
[]DB_Joiner{}
|
|
)*/
|
|
|
|
return nil
|
|
}
|
|
|
|
func write_file(name string, content string) (err error) {
|
|
f, err := os.Create(name)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
_, err = f.WriteString(content)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
f.Sync()
|
|
f.Close()
|
|
return
|
|
}
|
|
|
|
func _process_where(wherestr string) (where []DB_Where) {
|
|
if wherestr == "" {
|
|
return where
|
|
}
|
|
wherestr = strings.Replace(wherestr," and "," AND ",-1)
|
|
for _, segment := range strings.Split(wherestr," AND ") {
|
|
// TO-DO: Subparse the contents of a function and spit out a DB_Function struct
|
|
var outwhere DB_Where
|
|
var parseOffset int
|
|
outwhere.Left, parseOffset = _get_identifier(segment, parseOffset)
|
|
outwhere.Operator, parseOffset = _get_operator(segment, parseOffset + 1)
|
|
outwhere.Right, parseOffset = _get_identifier(segment, parseOffset + 1)
|
|
outwhere.LeftType = _get_identifier_type(outwhere.Left)
|
|
outwhere.RightType = _get_identifier_type(outwhere.Right)
|
|
where = append(where,outwhere)
|
|
}
|
|
return where
|
|
}
|
|
|
|
func _get_identifier_type(identifier string) string {
|
|
if ('a' <= identifier[0] && identifier[0] <= 'z') || ('A' <= identifier[0] && identifier[0] <= 'Z') {
|
|
if identifier[len(identifier) - 1] == ')' {
|
|
return "function"
|
|
}
|
|
return "column"
|
|
}
|
|
if identifier[0] == '\'' || identifier[0] == '"' {
|
|
return "string"
|
|
}
|
|
return "literal"
|
|
}
|
|
|
|
func _get_identifier(segment string, startOffset int) (out string, i int) {
|
|
fmt.Println("entering _get_identifier")
|
|
segment = strings.TrimSpace(segment)
|
|
segment += " " // Avoid overflow bugs with slicing
|
|
for i = startOffset; i < len(segment); i++ {
|
|
if segment[i] == '(' {
|
|
i = _skip_function_call(segment,i)
|
|
return strings.TrimSpace(segment[startOffset:i]), (i - 1)
|
|
}
|
|
if segment[i] == ' ' && i != startOffset {
|
|
fmt.Println("segment[startOffset:i]",segment[startOffset:i])
|
|
fmt.Println("startOffset",startOffset)
|
|
fmt.Println("segment[startOffset]",string(segment[startOffset]))
|
|
fmt.Println("i",i)
|
|
return strings.TrimSpace(segment[startOffset:i]), (i - 1)
|
|
}
|
|
}
|
|
return strings.TrimSpace(segment[startOffset:]), (i - 1)
|
|
}
|
|
|
|
func _get_operator(segment string, startOffset int) (out string, i int) {
|
|
segment = strings.TrimSpace(segment)
|
|
segment += " " // Avoid overflow bugs with slicing
|
|
for i = startOffset; i < len(segment); i++ {
|
|
if segment[i] == ' ' && i != startOffset {
|
|
return strings.TrimSpace(segment[startOffset:i]), (i - 1)
|
|
}
|
|
}
|
|
return strings.TrimSpace(segment[startOffset:]), (i - 1)
|
|
}
|
|
|
|
func _skip_function_call(segment string, i int) int {
|
|
var brace_count int = 1
|
|
for ; i < len(segment); i++ {
|
|
if segment[i] == '(' {
|
|
brace_count++
|
|
} else if segment[i] == ')' {
|
|
brace_count--
|
|
}
|
|
if brace_count == 0 {
|
|
return i
|
|
}
|
|
}
|
|
return i
|
|
}
|