Browse Source

Tests, split action by files

Vova Tkach 6 years ago
parent
commit
8e79056890

+ 0 - 279
modules/module_blog.go

@@ -471,282 +471,3 @@ func (this *Modules) RegisterModule_Blog() *Module {
 		return this.getSidebarModules(wrap), content, sidebar
 	})
 }
-
-func (this *Modules) RegisterAction_BlogModify() *Action {
-	return this.newAction(AInfo{
-		WantDB:    true,
-		Mount:     "blog-modify",
-		WantAdmin: true,
-	}, func(wrap *wrapper.Wrapper) {
-		pf_id := wrap.R.FormValue("id")
-		pf_name := wrap.R.FormValue("name")
-		pf_alias := wrap.R.FormValue("alias")
-		pf_content := wrap.R.FormValue("content")
-		pf_active := wrap.R.FormValue("active")
-
-		if pf_active == "" {
-			pf_active = "0"
-		}
-
-		if !utils.IsNumeric(pf_id) {
-			wrap.MsgError(`Inner system error`)
-			return
-		}
-
-		if pf_name == "" {
-			wrap.MsgError(`Please specify page name`)
-			return
-		}
-
-		if pf_alias == "" {
-			pf_alias = utils.GenerateSingleAlias(pf_name)
-		}
-
-		if !utils.IsValidSingleAlias(pf_alias) {
-			wrap.MsgError(`Please specify correct post alias`)
-			return
-		}
-
-		if pf_id == "0" {
-			// Start transaction with table lock
-			_, err := wrap.DB.Exec("LOCK TABLE blog_cats WRITE, blog_cat_post_rel WRITE;")
-			if err != nil {
-				wrap.MsgError(err.Error())
-				return
-			}
-			tx, err := wrap.DB.Begin()
-			if err != nil {
-				wrap.MsgError(err.Error())
-				return
-			}
-
-			// Insert row
-			res, err := tx.Exec(
-				`INSERT INTO blog_posts SET
-					user = ?,
-					name = ?,
-					alias = ?,
-					content = ?,
-					datetime = ?,
-					active = ?
-				;`,
-				wrap.User.A_id,
-				pf_name,
-				pf_alias,
-				pf_content,
-				utils.UnixTimestampToMySqlDateTime(utils.GetCurrentUnixTimestamp()),
-				pf_active,
-			)
-			if err != nil {
-				tx.Rollback()
-				wrap.MsgError(err.Error())
-				return
-			}
-
-			lastID, err := res.LastInsertId()
-			if err != nil {
-				tx.Rollback()
-				wrap.MsgError(err.Error())
-				return
-			}
-
-			// Insert post and categories relations
-			catids := utils.GetPostArrayInt("cats[]", wrap.R)
-			if len(catids) > 0 {
-				var catsCount int
-				err = tx.QueryRow(`
-					SELECT
-						COUNT(*)
-					FROM
-						blog_cats
-					WHERE
-						id IN(` + strings.Join(utils.ArrayOfIntToArrayOfString(catids), ",") + `)
-					;`,
-				).Scan(
-					&catsCount,
-				)
-				if err != nil {
-					tx.Rollback()
-					wrap.MsgError(err.Error())
-					return
-				}
-				if len(catids) != catsCount {
-					tx.Rollback()
-					wrap.MsgError(`Inner system error`)
-					return
-				}
-				var balkInsertArr []string
-				for _, el := range catids {
-					balkInsertArr = append(balkInsertArr, `(NULL,`+utils.Int64ToStr(lastID)+`,`+utils.IntToStr(el)+`)`)
-				}
-				if _, err = tx.Exec(
-					`INSERT INTO blog_cat_post_rel (id,post_id,category_id) VALUES ` + strings.Join(balkInsertArr, ",") + `;`,
-				); err != nil {
-					tx.Rollback()
-					wrap.MsgError(err.Error())
-					return
-				}
-			}
-
-			// Commit all changes and unlock table
-			err = tx.Commit()
-			if err != nil {
-				wrap.MsgError(err.Error())
-				return
-			}
-			_, err = wrap.DB.Exec("UNLOCK TABLES;")
-			if err != nil {
-				wrap.MsgError(err.Error())
-				return
-			}
-
-			wrap.Write(`window.location='/cp/blog/';`)
-		} else {
-			// Start transaction with table lock
-			_, err := wrap.DB.Exec("LOCK TABLE blog_cats WRITE, blog_cat_post_rel WRITE;")
-			if err != nil {
-				wrap.MsgError(err.Error())
-				return
-			}
-			tx, err := wrap.DB.Begin()
-			if err != nil {
-				wrap.MsgError(err.Error())
-				return
-			}
-
-			// Update row
-			if _, err = tx.Exec(
-				`UPDATE blog_posts SET
-					name = ?,
-					alias = ?,
-					content = ?,
-					active = ?
-				WHERE
-					id = ?
-				;`,
-				pf_name,
-				pf_alias,
-				pf_content,
-				pf_active,
-				utils.StrToInt(pf_id),
-			); err != nil {
-				tx.Rollback()
-				wrap.MsgError(err.Error())
-				return
-			}
-
-			// Delete post and categories relations
-			if _, err = tx.Exec("DELETE FROM blog_cat_post_rel WHERE post_id = ?;", pf_id); err != nil {
-				tx.Rollback()
-				wrap.MsgError(err.Error())
-				return
-			}
-
-			// Insert post and categories relations
-			catids := utils.GetPostArrayInt("cats[]", wrap.R)
-			if len(catids) > 0 {
-				var catsCount int
-				err = tx.QueryRow(`
-					SELECT
-						COUNT(*)
-					FROM
-						blog_cats
-					WHERE
-						id IN(` + strings.Join(utils.ArrayOfIntToArrayOfString(catids), ",") + `)
-					;`,
-				).Scan(
-					&catsCount,
-				)
-				if err != nil {
-					tx.Rollback()
-					wrap.MsgError(err.Error())
-					return
-				}
-				if len(catids) != catsCount {
-					tx.Rollback()
-					wrap.MsgError(`Inner system error`)
-					return
-				}
-				var balkInsertArr []string
-				for _, el := range catids {
-					balkInsertArr = append(balkInsertArr, `(NULL,`+pf_id+`,`+utils.IntToStr(el)+`)`)
-				}
-				if _, err = tx.Exec(
-					`INSERT INTO blog_cat_post_rel (id,post_id,category_id) VALUES ` + strings.Join(balkInsertArr, ",") + `;`,
-				); err != nil {
-					tx.Rollback()
-					wrap.MsgError(err.Error())
-					return
-				}
-			}
-
-			// Commit all changes and unlock table
-			err = tx.Commit()
-			if err != nil {
-				wrap.MsgError(err.Error())
-				return
-			}
-			_, err = wrap.DB.Exec("UNLOCK TABLES;")
-			if err != nil {
-				wrap.MsgError(err.Error())
-				return
-			}
-
-			wrap.Write(`window.location='/cp/blog/modify/` + pf_id + `/';`)
-		}
-	})
-}
-
-func (this *Modules) RegisterAction_BlogDelete() *Action {
-	return this.newAction(AInfo{
-		WantDB:    true,
-		Mount:     "blog-delete",
-		WantAdmin: true,
-	}, func(wrap *wrapper.Wrapper) {
-		pf_id := wrap.R.FormValue("id")
-
-		if !utils.IsNumeric(pf_id) {
-			wrap.MsgError(`Inner system error`)
-			return
-		}
-
-		// Start transaction with table lock
-		_, err := wrap.DB.Exec("LOCK TABLES blog_posts WRITE, blog_cat_post_rel WRITE;")
-		if err != nil {
-			wrap.MsgError(err.Error())
-			return
-		}
-		tx, err := wrap.DB.Begin()
-		if err != nil {
-			wrap.MsgError(err.Error())
-			return
-		}
-
-		// Delete target post with category connection data
-		if _, err = tx.Exec("DELETE FROM blog_cat_post_rel WHERE post_id = ?;", pf_id); err != nil {
-			tx.Rollback()
-			wrap.MsgError(err.Error())
-			return
-		}
-		if _, err = tx.Exec("DELETE FROM blog_posts WHERE id = ?;", pf_id); err != nil {
-			tx.Rollback()
-			wrap.MsgError(err.Error())
-			return
-		}
-
-		// Commit all changes and unlock table
-		err = tx.Commit()
-		if err != nil {
-			wrap.MsgError(err.Error())
-			return
-		}
-		_, err = wrap.DB.Exec("UNLOCK TABLES;")
-		if err != nil {
-			wrap.MsgError(err.Error())
-			return
-		}
-
-		// Reload current page
-		wrap.Write(`window.location.reload(false);`)
-	})
-}

+ 60 - 0
modules/module_blog_act_delete.go

@@ -0,0 +1,60 @@
+package modules
+
+import (
+	"golang-fave/engine/wrapper"
+	"golang-fave/utils"
+)
+
+func (this *Modules) RegisterAction_BlogDelete() *Action {
+	return this.newAction(AInfo{
+		WantDB:    true,
+		Mount:     "blog-delete",
+		WantAdmin: true,
+	}, func(wrap *wrapper.Wrapper) {
+		pf_id := wrap.R.FormValue("id")
+
+		if !utils.IsNumeric(pf_id) {
+			wrap.MsgError(`Inner system error`)
+			return
+		}
+
+		// Start transaction with table lock
+		_, err := wrap.DB.Exec("LOCK TABLES blog_posts WRITE, blog_cat_post_rel WRITE;")
+		if err != nil {
+			wrap.MsgError(err.Error())
+			return
+		}
+		tx, err := wrap.DB.Begin()
+		if err != nil {
+			wrap.MsgError(err.Error())
+			return
+		}
+
+		// Delete target post with category connection data
+		if _, err = tx.Exec("DELETE FROM blog_posts WHERE id = ?;", pf_id); err != nil {
+			tx.Rollback()
+			wrap.MsgError(err.Error())
+			return
+		}
+		if _, err = tx.Exec("DELETE FROM blog_cat_post_rel WHERE post_id = ?;", pf_id); err != nil {
+			tx.Rollback()
+			wrap.MsgError(err.Error())
+			return
+		}
+
+		// Commit all changes and unlock table
+		err = tx.Commit()
+		if err != nil {
+			wrap.MsgError(err.Error())
+			return
+		}
+		_, err = wrap.DB.Exec("UNLOCK TABLES;")
+		if err != nil {
+			wrap.MsgError(err.Error())
+			return
+		}
+
+		// Reload current page
+		wrap.Write(`window.location.reload(false);`)
+	})
+}

+ 233 - 0
modules/module_blog_act_modify.go

@@ -0,0 +1,233 @@
+package modules
+
+import (
+	"strings"
+
+	"golang-fave/engine/wrapper"
+	"golang-fave/utils"
+)
+
+func (this *Modules) RegisterAction_BlogModify() *Action {
+	return this.newAction(AInfo{
+		WantDB:    true,
+		Mount:     "blog-modify",
+		WantAdmin: true,
+	}, func(wrap *wrapper.Wrapper) {
+		pf_id := wrap.R.FormValue("id")
+		pf_name := wrap.R.FormValue("name")
+		pf_alias := wrap.R.FormValue("alias")
+		pf_content := wrap.R.FormValue("content")
+		pf_active := wrap.R.FormValue("active")
+
+		if pf_active == "" {
+			pf_active = "0"
+		}
+
+		if !utils.IsNumeric(pf_id) {
+			wrap.MsgError(`Inner system error`)
+			return
+		}
+
+		if pf_name == "" {
+			wrap.MsgError(`Please specify page name`)
+			return
+		}
+
+		if pf_alias == "" {
+			pf_alias = utils.GenerateSingleAlias(pf_name)
+		}
+
+		if !utils.IsValidSingleAlias(pf_alias) {
+			wrap.MsgError(`Please specify correct post alias`)
+			return
+		}
+
+		if pf_id == "0" {
+			// Start transaction with table lock
+			_, err := wrap.DB.Exec("LOCK TABLE blog_cats WRITE, blog_cat_post_rel WRITE;")
+			if err != nil {
+				wrap.MsgError(err.Error())
+				return
+			}
+			tx, err := wrap.DB.Begin()
+			if err != nil {
+				wrap.MsgError(err.Error())
+				return
+			}
+
+			// Insert row
+			res, err := tx.Exec(
+				`INSERT INTO blog_posts SET
+					user = ?,
+					name = ?,
+					alias = ?,
+					content = ?,
+					datetime = ?,
+					active = ?
+				;`,
+				wrap.User.A_id,
+				pf_name,
+				pf_alias,
+				pf_content,
+				utils.UnixTimestampToMySqlDateTime(utils.GetCurrentUnixTimestamp()),
+				pf_active,
+			)
+			if err != nil {
+				tx.Rollback()
+				wrap.MsgError(err.Error())
+				return
+			}
+
+			lastID, err := res.LastInsertId()
+			if err != nil {
+				tx.Rollback()
+				wrap.MsgError(err.Error())
+				return
+			}
+
+			// Insert post and categories relations
+			catids := utils.GetPostArrayInt("cats[]", wrap.R)
+			if len(catids) > 0 {
+				var catsCount int
+				err = tx.QueryRow(`
+					SELECT
+						COUNT(*)
+					FROM
+						blog_cats
+					WHERE
+						id IN(` + strings.Join(utils.ArrayOfIntToArrayOfString(catids), ",") + `)
+					;`,
+				).Scan(
+					&catsCount,
+				)
+				if err != nil {
+					tx.Rollback()
+					wrap.MsgError(err.Error())
+					return
+				}
+				if len(catids) != catsCount {
+					tx.Rollback()
+					wrap.MsgError(`Inner system error`)
+					return
+				}
+				var balkInsertArr []string
+				for _, el := range catids {
+					balkInsertArr = append(balkInsertArr, `(NULL,`+utils.Int64ToStr(lastID)+`,`+utils.IntToStr(el)+`)`)
+				}
+				if _, err = tx.Exec(
+					`INSERT INTO blog_cat_post_rel (id,post_id,category_id) VALUES ` + strings.Join(balkInsertArr, ",") + `;`,
+				); err != nil {
+					tx.Rollback()
+					wrap.MsgError(err.Error())
+					return
+				}
+			}
+
+			// Commit all changes and unlock table
+			err = tx.Commit()
+			if err != nil {
+				wrap.MsgError(err.Error())
+				return
+			}
+			_, err = wrap.DB.Exec("UNLOCK TABLES;")
+			if err != nil {
+				wrap.MsgError(err.Error())
+				return
+			}
+
+			wrap.Write(`window.location='/cp/blog/';`)
+		} else {
+			// Start transaction with table lock
+			_, err := wrap.DB.Exec("LOCK TABLE blog_cats WRITE, blog_cat_post_rel WRITE;")
+			if err != nil {
+				wrap.MsgError(err.Error())
+				return
+			}
+			tx, err := wrap.DB.Begin()
+			if err != nil {
+				wrap.MsgError(err.Error())
+				return
+			}
+
+			// Update row
+			if _, err = tx.Exec(
+				`UPDATE blog_posts SET
+					name = ?,
+					alias = ?,
+					content = ?,
+					active = ?
+				WHERE
+					id = ?
+				;`,
+				pf_name,
+				pf_alias,
+				pf_content,
+				pf_active,
+				utils.StrToInt(pf_id),
+			); err != nil {
+				tx.Rollback()
+				wrap.MsgError(err.Error())
+				return
+			}
+
+			// Delete post and categories relations
+			if _, err = tx.Exec("DELETE FROM blog_cat_post_rel WHERE post_id = ?;", pf_id); err != nil {
+				tx.Rollback()
+				wrap.MsgError(err.Error())
+				return
+			}
+
+			// Insert post and categories relations
+			catids := utils.GetPostArrayInt("cats[]", wrap.R)
+			if len(catids) > 0 {
+				var catsCount int
+				err = tx.QueryRow(`
+					SELECT
+						COUNT(*)
+					FROM
+						blog_cats
+					WHERE
+						id IN(` + strings.Join(utils.ArrayOfIntToArrayOfString(catids), ",") + `)
+					;`,
+				).Scan(
+					&catsCount,
+				)
+				if err != nil {
+					tx.Rollback()
+					wrap.MsgError(err.Error())
+					return
+				}
+				if len(catids) != catsCount {
+					tx.Rollback()
+					wrap.MsgError(`Inner system error`)
+					return
+				}
+				var balkInsertArr []string
+				for _, el := range catids {
+					balkInsertArr = append(balkInsertArr, `(NULL,`+pf_id+`,`+utils.IntToStr(el)+`)`)
+				}
+				if _, err = tx.Exec(
+					`INSERT INTO blog_cat_post_rel (id,post_id,category_id) VALUES ` + strings.Join(balkInsertArr, ",") + `;`,
+				); err != nil {
+					tx.Rollback()
+					wrap.MsgError(err.Error())
+					return
+				}
+			}
+
+			// Commit all changes and unlock table
+			err = tx.Commit()
+			if err != nil {
+				wrap.MsgError(err.Error())
+				return
+			}
+			_, err = wrap.DB.Exec("UNLOCK TABLES;")
+			if err != nil {
+				wrap.MsgError(err.Error())
+				return
+			}
+
+			wrap.Write(`window.location='/cp/blog/modify/` + pf_id + `/';`)
+		}
+	})
+}

+ 0 - 277
modules/module_blog_categories.go

@@ -89,280 +89,3 @@ func (this *Modules) blog_GetCategoryParentId(wrap *wrapper.Wrapper, id int) int
 	}
 	return parentId
 }
-
-func (this *Modules) blog_ActionCategoryAdd(wrap *wrapper.Wrapper, pf_id, pf_name, pf_alias, pf_parent string) error {
-	// Start transaction with table lock
-	_, err := wrap.DB.Exec("LOCK TABLE blog_cats WRITE;")
-	if err != nil {
-		return err
-	}
-	tx, err := wrap.DB.Begin()
-	if err != nil {
-		return err
-	}
-
-	// Update and insert new category
-	if _, err = tx.Exec("SELECT @mr := rgt FROM blog_cats WHERE id = ?;", pf_parent); err != nil {
-		tx.Rollback()
-		return err
-	}
-	if _, err = tx.Exec("UPDATE blog_cats SET rgt = rgt + 2 WHERE rgt > @mr;"); err != nil {
-		tx.Rollback()
-		return err
-	}
-	if _, err = tx.Exec("UPDATE blog_cats SET lft = lft + 2 WHERE lft > @mr;"); err != nil {
-		tx.Rollback()
-		return err
-	}
-	if _, err = tx.Exec("UPDATE blog_cats SET rgt = rgt + 2 WHERE id = ?;", pf_parent); err != nil {
-		tx.Rollback()
-		return err
-	}
-	if _, err = tx.Exec("INSERT INTO blog_cats (id, user, name, alias, lft, rgt) VALUES (NULL, ?, ?, ?, @mr, @mr + 1);", wrap.User.A_id, pf_name, pf_alias); err != nil {
-		tx.Rollback()
-		return err
-	}
-
-	// Commit all changes and unlock table
-	err = tx.Commit()
-	if err != nil {
-		return err
-	}
-	_, err = wrap.DB.Exec("UNLOCK TABLES;")
-	if err != nil {
-		return err
-	}
-
-	return nil
-}
-
-func (this *Modules) blog_ActionCategoryUpdate(wrap *wrapper.Wrapper, pf_id, pf_name, pf_alias, pf_parent string) error {
-	parentId := this.blog_GetCategoryParentId(wrap, utils.StrToInt(pf_id))
-
-	if utils.StrToInt(pf_parent) == parentId {
-		// If parent not changed, just update category data
-		_, err := wrap.DB.Exec(`
-			UPDATE blog_cats SET
-				name = ?,
-				alias = ?
-			WHERE
-				id > 1 AND
-				id = ?
-			;`,
-			pf_name,
-			pf_alias,
-			pf_id,
-		)
-		return err
-	} else {
-		// Parent is changed, move category to new parent
-		// Start transaction with table lock
-		_, err := wrap.DB.Exec("LOCK TABLE blog_cats WRITE;")
-		if err != nil {
-			return err
-		}
-		tx, err := wrap.DB.Begin()
-		if err != nil {
-			return err
-		}
-
-		// Shift
-		if _, err = tx.Exec("SELECT @ml := lft, @mr := rgt FROM blog_cats WHERE id = ?;", pf_id); err != nil {
-			tx.Rollback()
-			return err
-		}
-		if _, err = tx.Exec("UPDATE blog_cats SET lft = 0, rgt = 0 WHERE id = ?;", pf_id); err != nil {
-			tx.Rollback()
-			return err
-		}
-		if _, err = tx.Exec("UPDATE blog_cats SET lft = lft - 1, rgt = rgt - 1 WHERE lft > @ml AND rgt < @mr;"); err != nil {
-			tx.Rollback()
-			return err
-		}
-		if _, err = tx.Exec("UPDATE blog_cats SET lft = lft - 2 WHERE lft > @mr;"); err != nil {
-			tx.Rollback()
-			return err
-		}
-		if _, err = tx.Exec("UPDATE blog_cats SET rgt = rgt - 2 WHERE rgt > @mr;"); err != nil {
-			tx.Rollback()
-			return err
-		}
-
-		// Update
-		if _, err = tx.Exec("SELECT @mr := rgt FROM blog_cats WHERE id = ?;", pf_parent); err != nil {
-			tx.Rollback()
-			return err
-		}
-		if _, err = tx.Exec("UPDATE blog_cats SET rgt = rgt + 2 WHERE rgt > @mr;"); err != nil {
-			tx.Rollback()
-			return err
-		}
-		if _, err = tx.Exec("UPDATE blog_cats SET lft = lft + 2 WHERE lft > @mr;"); err != nil {
-			tx.Rollback()
-			return err
-		}
-		if _, err = tx.Exec("UPDATE blog_cats SET rgt = rgt + 2 WHERE id = ?;", pf_parent); err != nil {
-			tx.Rollback()
-			return err
-		}
-		if _, err = tx.Exec("UPDATE blog_cats SET name = ?, alias = ?, lft = @mr, rgt = @mr + 1 WHERE id = ?;", pf_name, pf_alias, pf_id); err != nil {
-			tx.Rollback()
-			return err
-		}
-
-		// Commit all changes and unlock table
-		err = tx.Commit()
-		if err != nil {
-			return err
-		}
-		_, err = wrap.DB.Exec("UNLOCK TABLES;")
-		if err != nil {
-			return err
-		}
-	}
-
-	return nil
-}
-
-func (this *Modules) RegisterAction_BlogCategoriesModify() *Action {
-	return this.newAction(AInfo{
-		WantDB:    true,
-		Mount:     "blog-categories-modify",
-		WantAdmin: true,
-	}, func(wrap *wrapper.Wrapper) {
-		pf_id := wrap.R.FormValue("id")
-		pf_name := wrap.R.FormValue("name")
-		pf_alias := wrap.R.FormValue("alias")
-		pf_parent := wrap.R.FormValue("parent")
-
-		if !utils.IsNumeric(pf_id) || !utils.IsNumeric(pf_parent) {
-			wrap.MsgError(`Inner system error`)
-			return
-		}
-
-		if pf_name == "" {
-			wrap.MsgError(`Please specify category name`)
-			return
-		}
-
-		if pf_alias == "" {
-			pf_alias = utils.GenerateSingleAlias(pf_name)
-		}
-
-		if !utils.IsValidSingleAlias(pf_alias) {
-			wrap.MsgError(`Please specify correct category alias`)
-			return
-		}
-
-		// Set root category as default
-		if pf_parent == "0" {
-			pf_parent = "1"
-		} else {
-			// Check if parent category exists
-			var parentId int
-			err := wrap.DB.QueryRow(`
-				SELECT
-					id
-				FROM
-					blog_cats
-				WHERE
-					id > 1 AND
-					id = ?
-				LIMIT 1;`,
-				pf_parent,
-			).Scan(&parentId)
-			if err != nil {
-				wrap.MsgError(err.Error())
-				return
-			}
-		}
-
-		if pf_id == "0" {
-			if err := this.blog_ActionCategoryAdd(wrap, pf_id, pf_name, pf_alias, pf_parent); err != nil {
-				wrap.MsgError(err.Error())
-				return
-			}
-			wrap.Write(`window.location='/cp/blog/categories/';`)
-		} else {
-			if err := this.blog_ActionCategoryUpdate(wrap, pf_id, pf_name, pf_alias, pf_parent); err != nil {
-				wrap.MsgError(err.Error())
-				return
-			}
-			wrap.Write(`window.location='/cp/blog/categories-modify/` + pf_id + `/';`)
-		}
-	})
-}
-
-func (this *Modules) RegisterAction_BlogCategoriesDelete() *Action {
-	return this.newAction(AInfo{
-		WantDB:    true,
-		Mount:     "blog-categories-delete",
-		WantAdmin: true,
-	}, func(wrap *wrapper.Wrapper) {
-		pf_id := wrap.R.FormValue("id")
-
-		if !utils.IsNumeric(pf_id) || utils.StrToInt(pf_id) <= 1 {
-			wrap.MsgError(`Inner system error`)
-			return
-		}
-
-		// Start transaction with table lock
-		_, err := wrap.DB.Exec("LOCK TABLES blog_cats WRITE, blog_cat_post_rel WRITE;")
-		if err != nil {
-			wrap.MsgError(err.Error())
-			return
-		}
-		tx, err := wrap.DB.Begin()
-		if err != nil {
-			wrap.MsgError(err.Error())
-			return
-		}
-
-		// Update and delete target category
-		if _, err = tx.Exec("SELECT @ml := lft, @mr := rgt FROM blog_cats WHERE id = ?;", pf_id); err != nil {
-			tx.Rollback()
-			wrap.MsgError(err.Error())
-			return
-		}
-		if _, err = tx.Exec("DELETE FROM blog_cats WHERE id = ?;", pf_id); err != nil {
-			tx.Rollback()
-			wrap.MsgError(err.Error())
-			return
-		}
-		if _, err = tx.Exec("UPDATE blog_cats SET lft = lft - 1, rgt = rgt - 1 WHERE lft > @ml AND rgt < @mr;"); err != nil {
-			tx.Rollback()
-			wrap.MsgError(err.Error())
-			return
-		}
-		if _, err = tx.Exec("UPDATE blog_cats SET lft = lft - 2 WHERE lft > @mr;"); err != nil {
-			tx.Rollback()
-			wrap.MsgError(err.Error())
-			return
-		}
-		if _, err = tx.Exec("UPDATE blog_cats SET rgt = rgt - 2 WHERE rgt > @mr;"); err != nil {
-			tx.Rollback()
-			wrap.MsgError(err.Error())
-			return
-		}
-		if _, err = tx.Exec("DELETE FROM blog_cat_post_rel WHERE category_id = ?;", pf_id); err != nil {
-			tx.Rollback()
-			wrap.MsgError(err.Error())
-			return
-		}
-
-		// Commit all changes and unlock table
-		err = tx.Commit()
-		if err != nil {
-			wrap.MsgError(err.Error())
-			return
-		}
-		_, err = wrap.DB.Exec("UNLOCK TABLES;")
-		if err != nil {
-			wrap.MsgError(err.Error())
-			return
-		}
-
-		// Reload current page
-		wrap.Write(`window.location.reload(false);`)
-	})
-}

+ 80 - 0
modules/module_blog_categories_act_delete.go

@@ -0,0 +1,80 @@
+package modules
+
+import (
+	"golang-fave/engine/wrapper"
+	"golang-fave/utils"
+)
+
+func (this *Modules) RegisterAction_BlogCategoriesDelete() *Action {
+	return this.newAction(AInfo{
+		WantDB:    true,
+		Mount:     "blog-categories-delete",
+		WantAdmin: true,
+	}, func(wrap *wrapper.Wrapper) {
+		pf_id := wrap.R.FormValue("id")
+
+		if !utils.IsNumeric(pf_id) || utils.StrToInt(pf_id) <= 1 {
+			wrap.MsgError(`Inner system error`)
+			return
+		}
+
+		// Start transaction with table lock
+		_, err := wrap.DB.Exec("LOCK TABLES blog_cats WRITE, blog_cat_post_rel WRITE;")
+		if err != nil {
+			wrap.MsgError(err.Error())
+			return
+		}
+		tx, err := wrap.DB.Begin()
+		if err != nil {
+			wrap.MsgError(err.Error())
+			return
+		}
+
+		// Update and delete target category
+		if _, err = tx.Exec("SELECT @ml := lft, @mr := rgt FROM blog_cats WHERE id = ?;", pf_id); err != nil {
+			tx.Rollback()
+			wrap.MsgError(err.Error())
+			return
+		}
+		if _, err = tx.Exec("DELETE FROM blog_cats WHERE id = ?;", pf_id); err != nil {
+			tx.Rollback()
+			wrap.MsgError(err.Error())
+			return
+		}
+		if _, err = tx.Exec("UPDATE blog_cats SET lft = lft - 1, rgt = rgt - 1 WHERE lft > @ml AND rgt < @mr;"); err != nil {
+			tx.Rollback()
+			wrap.MsgError(err.Error())
+			return
+		}
+		if _, err = tx.Exec("UPDATE blog_cats SET lft = lft - 2 WHERE lft > @mr;"); err != nil {
+			tx.Rollback()
+			wrap.MsgError(err.Error())
+			return
+		}
+		if _, err = tx.Exec("UPDATE blog_cats SET rgt = rgt - 2 WHERE rgt > @mr;"); err != nil {
+			tx.Rollback()
+			wrap.MsgError(err.Error())
+			return
+		}
+		if _, err = tx.Exec("DELETE FROM blog_cat_post_rel WHERE category_id = ?;", pf_id); err != nil {
+			tx.Rollback()
+			wrap.MsgError(err.Error())
+			return
+		}
+
+		// Commit all changes and unlock table
+		err = tx.Commit()
+		if err != nil {
+			wrap.MsgError(err.Error())
+			return
+		}
+		_, err = wrap.DB.Exec("UNLOCK TABLES;")
+		if err != nil {
+			wrap.MsgError(err.Error())
+			return
+		}
+
+		// Reload current page
+		wrap.Write(`window.location.reload(false);`)
+	})
+}

+ 209 - 0
modules/module_blog_categories_act_modify.go

@@ -0,0 +1,209 @@
+package modules
+
+import (
+	"golang-fave/engine/wrapper"
+	"golang-fave/utils"
+)
+
+func (this *Modules) blog_ActionCategoryAdd(wrap *wrapper.Wrapper, pf_id, pf_name, pf_alias, pf_parent string) error {
+	// Start transaction with table lock
+	_, err := wrap.DB.Exec("LOCK TABLE blog_cats WRITE;")
+	if err != nil {
+		return err
+	}
+	tx, err := wrap.DB.Begin()
+	if err != nil {
+		return err
+	}
+
+	// Update and insert new category
+	if _, err = tx.Exec("SELECT @mr := rgt FROM blog_cats WHERE id = ?;", pf_parent); err != nil {
+		tx.Rollback()
+		return err
+	}
+	if _, err = tx.Exec("UPDATE blog_cats SET rgt = rgt + 2 WHERE rgt > @mr;"); err != nil {
+		tx.Rollback()
+		return err
+	}
+	if _, err = tx.Exec("UPDATE blog_cats SET lft = lft + 2 WHERE lft > @mr;"); err != nil {
+		tx.Rollback()
+		return err
+	}
+	if _, err = tx.Exec("UPDATE blog_cats SET rgt = rgt + 2 WHERE id = ?;", pf_parent); err != nil {
+		tx.Rollback()
+		return err
+	}
+	if _, err = tx.Exec("INSERT INTO blog_cats (id, user, name, alias, lft, rgt) VALUES (NULL, ?, ?, ?, @mr, @mr + 1);", wrap.User.A_id, pf_name, pf_alias); err != nil {
+		tx.Rollback()
+		return err
+	}
+
+	// Commit all changes and unlock table
+	err = tx.Commit()
+	if err != nil {
+		return err
+	}
+	_, err = wrap.DB.Exec("UNLOCK TABLES;")
+	if err != nil {
+		return err
+	}
+
+	return nil
+}
+
+func (this *Modules) blog_ActionCategoryUpdate(wrap *wrapper.Wrapper, pf_id, pf_name, pf_alias, pf_parent string) error {
+	parentId := this.blog_GetCategoryParentId(wrap, utils.StrToInt(pf_id))
+
+	if utils.StrToInt(pf_parent) == parentId {
+		// If parent not changed, just update category data
+		_, err := wrap.DB.Exec(`
+			UPDATE blog_cats SET
+				name = ?,
+				alias = ?
+			WHERE
+				id > 1 AND
+				id = ?
+			;`,
+			pf_name,
+			pf_alias,
+			pf_id,
+		)
+		return err
+	} else {
+		// Parent is changed, move category to new parent
+		// Start transaction with table lock
+		_, err := wrap.DB.Exec("LOCK TABLE blog_cats WRITE;")
+		if err != nil {
+			return err
+		}
+		tx, err := wrap.DB.Begin()
+		if err != nil {
+			return err
+		}
+
+		// Shift
+		if _, err = tx.Exec("SELECT @ml := lft, @mr := rgt FROM blog_cats WHERE id = ?;", pf_id); err != nil {
+			tx.Rollback()
+			return err
+		}
+		if _, err = tx.Exec("UPDATE blog_cats SET lft = 0, rgt = 0 WHERE id = ?;", pf_id); err != nil {
+			tx.Rollback()
+			return err
+		}
+		if _, err = tx.Exec("UPDATE blog_cats SET lft = lft - 1, rgt = rgt - 1 WHERE lft > @ml AND rgt < @mr;"); err != nil {
+			tx.Rollback()
+			return err
+		}
+		if _, err = tx.Exec("UPDATE blog_cats SET lft = lft - 2 WHERE lft > @mr;"); err != nil {
+			tx.Rollback()
+			return err
+		}
+		if _, err = tx.Exec("UPDATE blog_cats SET rgt = rgt - 2 WHERE rgt > @mr;"); err != nil {
+			tx.Rollback()
+			return err
+		}
+
+		// Update
+		if _, err = tx.Exec("SELECT @mr := rgt FROM blog_cats WHERE id = ?;", pf_parent); err != nil {
+			tx.Rollback()
+			return err
+		}
+		if _, err = tx.Exec("UPDATE blog_cats SET rgt = rgt + 2 WHERE rgt > @mr;"); err != nil {
+			tx.Rollback()
+			return err
+		}
+		if _, err = tx.Exec("UPDATE blog_cats SET lft = lft + 2 WHERE lft > @mr;"); err != nil {
+			tx.Rollback()
+			return err
+		}
+		if _, err = tx.Exec("UPDATE blog_cats SET rgt = rgt + 2 WHERE id = ?;", pf_parent); err != nil {
+			tx.Rollback()
+			return err
+		}
+		if _, err = tx.Exec("UPDATE blog_cats SET name = ?, alias = ?, lft = @mr, rgt = @mr + 1 WHERE id = ?;", pf_name, pf_alias, pf_id); err != nil {
+			tx.Rollback()
+			return err
+		}
+
+		// Commit all changes and unlock table
+		err = tx.Commit()
+		if err != nil {
+			return err
+		}
+		_, err = wrap.DB.Exec("UNLOCK TABLES;")
+		if err != nil {
+			return err
+		}
+	}
+
+	return nil
+}
+
+func (this *Modules) RegisterAction_BlogCategoriesModify() *Action {
+	return this.newAction(AInfo{
+		WantDB:    true,
+		Mount:     "blog-categories-modify",
+		WantAdmin: true,
+	}, func(wrap *wrapper.Wrapper) {
+		pf_id := wrap.R.FormValue("id")
+		pf_name := wrap.R.FormValue("name")
+		pf_alias := wrap.R.FormValue("alias")
+		pf_parent := wrap.R.FormValue("parent")
+
+		if !utils.IsNumeric(pf_id) || !utils.IsNumeric(pf_parent) {
+			wrap.MsgError(`Inner system error`)
+			return
+		}
+
+		if pf_name == "" {
+			wrap.MsgError(`Please specify category name`)
+			return
+		}
+
+		if pf_alias == "" {
+			pf_alias = utils.GenerateSingleAlias(pf_name)
+		}
+
+		if !utils.IsValidSingleAlias(pf_alias) {
+			wrap.MsgError(`Please specify correct category alias`)
+			return
+		}
+
+		// Set root category as default
+		if pf_parent == "0" {
+			pf_parent = "1"
+		} else {
+			// Check if parent category exists
+			var parentId int
+			err := wrap.DB.QueryRow(`
+				SELECT
+					id
+				FROM
+					blog_cats
+				WHERE
+					id > 1 AND
+					id = ?
+				LIMIT 1;`,
+				pf_parent,
+			).Scan(&parentId)
+			if err != nil {
+				wrap.MsgError(err.Error())
+				return
+			}
+		}
+
+		if pf_id == "0" {
+			if err := this.blog_ActionCategoryAdd(wrap, pf_id, pf_name, pf_alias, pf_parent); err != nil {
+				wrap.MsgError(err.Error())
+				return
+			}
+			wrap.Write(`window.location='/cp/blog/categories/';`)
+		} else {
+			if err := this.blog_ActionCategoryUpdate(wrap, pf_id, pf_name, pf_alias, pf_parent); err != nil {
+				wrap.MsgError(err.Error())
+				return
+			}
+			wrap.Write(`window.location='/cp/blog/categories-modify/` + pf_id + `/';`)
+		}
+	})
+}

+ 0 - 5
modules/module_index_act_mysql_setup.go

@@ -89,11 +89,6 @@ func (this *Modules) RegisterAction_IndexMysqlSetup() *Action {
 			wrap.MsgError(err.Error())
 			return
 		}
-		if _, err = tx.Exec(`INSERT INTO blog_cats (id, user, name, alias, lft, rgt) VALUES (1, 0, 'ROOT', 'ROOT', 1, 2);`); err != nil {
-			tx.Rollback()
-			wrap.MsgError(err.Error())
-			return
-		}
 		if _, err = tx.Exec(
 			`INSERT INTO blog_cats (id, user, name, alias, lft, rgt)
 				VALUES

+ 0 - 20
modules/module_settings.go

@@ -65,23 +65,3 @@ func (this *Modules) RegisterModule_Settings() *Module {
 		return this.getSidebarModules(wrap), content, sidebar
 	})
 }
-
-func (this *Modules) RegisterAction_SettingsRobotsTxt() *Action {
-	return this.newAction(AInfo{
-		WantDB:    true,
-		Mount:     "settings-robots-txt",
-		WantAdmin: true,
-	}, func(wrap *wrapper.Wrapper) {
-		pf_content := wrap.R.FormValue("content")
-
-		// Save robots.txt content
-		err := ioutil.WriteFile(wrap.DTemplate+string(os.PathSeparator)+"robots.txt", []byte(pf_content), 0664)
-		if err != nil {
-			wrap.MsgError(err.Error())
-			return
-		}
-
-		// Reload current page
-		wrap.Write(`window.location.reload(false);`)
-	})
-}

+ 28 - 0
modules/module_settings_act_robots_txt.go

@@ -0,0 +1,28 @@
+package modules
+
+import (
+	"io/ioutil"
+	"os"
+
+	"golang-fave/engine/wrapper"
+)
+
+func (this *Modules) RegisterAction_SettingsRobotsTxt() *Action {
+	return this.newAction(AInfo{
+		WantDB:    true,
+		Mount:     "settings-robots-txt",
+		WantAdmin: true,
+	}, func(wrap *wrapper.Wrapper) {
+		pf_content := wrap.R.FormValue("content")
+
+		// Save robots.txt content
+		err := ioutil.WriteFile(wrap.DTemplate+string(os.PathSeparator)+"robots.txt", []byte(pf_content), 0664)
+		if err != nil {
+			wrap.MsgError(err.Error())
+			return
+		}
+
+		// Reload current page
+		wrap.Write(`window.location.reload(false);`)
+	})
+}

+ 0 - 185
modules/module_users.go

@@ -232,188 +232,3 @@ func (this *Modules) RegisterModule_Users() *Module {
 		return this.getSidebarModules(wrap), content, sidebar
 	})
 }
-
-func (this *Modules) RegisterAction_UsersModify() *Action {
-	return this.newAction(AInfo{
-		WantDB:    true,
-		Mount:     "users-modify",
-		WantAdmin: true,
-	}, func(wrap *wrapper.Wrapper) {
-		pf_id := wrap.R.FormValue("id")
-		pf_first_name := wrap.R.FormValue("first_name")
-		pf_last_name := wrap.R.FormValue("last_name")
-		pf_email := wrap.R.FormValue("email")
-		pf_password := wrap.R.FormValue("password")
-		pf_admin := wrap.R.FormValue("admin")
-		pf_active := wrap.R.FormValue("active")
-
-		if pf_admin == "" {
-			pf_admin = "0"
-		}
-
-		if pf_active == "" {
-			pf_active = "0"
-		}
-
-		if !utils.IsNumeric(pf_id) {
-			wrap.MsgError(`Inner system error`)
-			return
-		}
-
-		if pf_email == "" {
-			wrap.MsgError(`Please specify user email`)
-			return
-		}
-
-		if !utils.IsValidEmail(pf_email) {
-			wrap.MsgError(`Please specify correct user email`)
-			return
-		}
-
-		// First user always super admin
-		// Rewrite active and admin status
-		if pf_id == "1" {
-			pf_admin = "1"
-			pf_active = "1"
-		}
-
-		if pf_id == "0" {
-			// Add new user
-			if pf_password == "" {
-				wrap.MsgError(`Please specify user password`)
-				return
-			}
-			_, err := wrap.DB.Exec(
-				`INSERT INTO users SET
-					first_name = ?,
-					last_name = ?,
-					email = ?,
-					password = MD5(?),
-					admin = ?,
-					active = ?
-				;`,
-				pf_first_name,
-				pf_last_name,
-				pf_email,
-				pf_password,
-				pf_admin,
-				pf_active,
-			)
-			if err != nil {
-				wrap.MsgError(err.Error())
-				return
-			}
-			wrap.Write(`window.location='/cp/users/';`)
-		} else {
-			// Update user
-			if pf_password == "" {
-				_, err := wrap.DB.Exec(
-					`UPDATE users SET
-						first_name = ?,
-						last_name = ?,
-						email = ?,
-						admin = ?,
-						active = ?
-					WHERE
-						id = ?
-					;`,
-					pf_first_name,
-					pf_last_name,
-					pf_email,
-					pf_admin,
-					pf_active,
-					utils.StrToInt(pf_id),
-				)
-				if err != nil {
-					wrap.MsgError(err.Error())
-					return
-				}
-			} else {
-				_, err := wrap.DB.Exec(
-					`UPDATE users SET
-						first_name = ?,
-						last_name = ?,
-						email = ?,
-						password = MD5(?)
-					WHERE
-						id = ?
-					;`,
-					pf_first_name,
-					pf_last_name,
-					pf_email,
-					pf_password,
-					utils.StrToInt(pf_id),
-				)
-				if err != nil {
-					wrap.MsgError(err.Error())
-					return
-				}
-			}
-			wrap.Write(`window.location='/cp/users/modify/` + pf_id + `/';`)
-		}
-	})
-}
-
-func (this *Modules) RegisterAction_UsersDelete() *Action {
-	return this.newAction(AInfo{
-		WantDB:    true,
-		Mount:     "users-delete",
-		WantAdmin: true,
-	}, func(wrap *wrapper.Wrapper) {
-		pf_id := wrap.R.FormValue("id")
-
-		if !utils.IsNumeric(pf_id) {
-			wrap.MsgError(`Inner system error`)
-			return
-		}
-
-		// Start transaction with table lock
-		_, err := wrap.DB.Exec("LOCK TABLES blog_cats WRITE, blog_posts WRITE, pages WRITE, users WRITE;")
-		if err != nil {
-			wrap.MsgError(err.Error())
-			return
-		}
-		tx, err := wrap.DB.Begin()
-		if err != nil {
-			wrap.MsgError(err.Error())
-			return
-		}
-
-		// Update and delete target user
-		if _, err = tx.Exec("UPDATE blog_cats SET user = 1 WHERE user = ?;", pf_id); err != nil {
-			tx.Rollback()
-			wrap.MsgError(err.Error())
-			return
-		}
-		if _, err = tx.Exec("UPDATE blog_posts SET user = 1 WHERE user = ?;", pf_id); err != nil {
-			tx.Rollback()
-			wrap.MsgError(err.Error())
-			return
-		}
-		if _, err = tx.Exec("UPDATE pages SET user = 1 WHERE user = ?;", pf_id); err != nil {
-			tx.Rollback()
-			wrap.MsgError(err.Error())
-			return
-		}
-		if _, err = tx.Exec("DELETE FROM users WHERE id = ? and id > 1;", pf_id); err != nil {
-			tx.Rollback()
-			wrap.MsgError(err.Error())
-			return
-		}
-
-		// Commit all changes and unlock table
-		err = tx.Commit()
-		if err != nil {
-			wrap.MsgError(err.Error())
-			return
-		}
-		_, err = wrap.DB.Exec("UNLOCK TABLES;")
-		if err != nil {
-			wrap.MsgError(err.Error())
-			return
-		}
-
-		// Reload current page
-		wrap.Write(`window.location.reload(false);`)
-	})
-}

+ 70 - 0
modules/module_users_act_delete.go

@@ -0,0 +1,70 @@
+package modules
+
+import (
+	"golang-fave/engine/wrapper"
+	"golang-fave/utils"
+)
+
+func (this *Modules) RegisterAction_UsersDelete() *Action {
+	return this.newAction(AInfo{
+		WantDB:    true,
+		Mount:     "users-delete",
+		WantAdmin: true,
+	}, func(wrap *wrapper.Wrapper) {
+		pf_id := wrap.R.FormValue("id")
+
+		if !utils.IsNumeric(pf_id) {
+			wrap.MsgError(`Inner system error`)
+			return
+		}
+
+		// Start transaction with table lock
+		_, err := wrap.DB.Exec("LOCK TABLES blog_cats WRITE, blog_posts WRITE, pages WRITE, users WRITE;")
+		if err != nil {
+			wrap.MsgError(err.Error())
+			return
+		}
+		tx, err := wrap.DB.Begin()
+		if err != nil {
+			wrap.MsgError(err.Error())
+			return
+		}
+
+		// Update and delete target user
+		if _, err = tx.Exec("UPDATE blog_cats SET user = 1 WHERE user = ?;", pf_id); err != nil {
+			tx.Rollback()
+			wrap.MsgError(err.Error())
+			return
+		}
+		if _, err = tx.Exec("UPDATE blog_posts SET user = 1 WHERE user = ?;", pf_id); err != nil {
+			tx.Rollback()
+			wrap.MsgError(err.Error())
+			return
+		}
+		if _, err = tx.Exec("UPDATE pages SET user = 1 WHERE user = ?;", pf_id); err != nil {
+			tx.Rollback()
+			wrap.MsgError(err.Error())
+			return
+		}
+		if _, err = tx.Exec("DELETE FROM users WHERE id = ? and id > 1;", pf_id); err != nil {
+			tx.Rollback()
+			wrap.MsgError(err.Error())
+			return
+		}
+
+		// Commit all changes and unlock table
+		err = tx.Commit()
+		if err != nil {
+			wrap.MsgError(err.Error())
+			return
+		}
+		_, err = wrap.DB.Exec("UNLOCK TABLES;")
+		if err != nil {
+			wrap.MsgError(err.Error())
+			return
+		}
+
+		// Reload current page
+		wrap.Write(`window.location.reload(false);`)
+	})
+}

+ 127 - 0
modules/module_users_act_modify.go

@@ -0,0 +1,127 @@
+package modules
+
+import (
+	"golang-fave/engine/wrapper"
+	"golang-fave/utils"
+)
+
+func (this *Modules) RegisterAction_UsersModify() *Action {
+	return this.newAction(AInfo{
+		WantDB:    true,
+		Mount:     "users-modify",
+		WantAdmin: true,
+	}, func(wrap *wrapper.Wrapper) {
+		pf_id := wrap.R.FormValue("id")
+		pf_first_name := wrap.R.FormValue("first_name")
+		pf_last_name := wrap.R.FormValue("last_name")
+		pf_email := wrap.R.FormValue("email")
+		pf_password := wrap.R.FormValue("password")
+		pf_admin := wrap.R.FormValue("admin")
+		pf_active := wrap.R.FormValue("active")
+
+		if pf_admin == "" {
+			pf_admin = "0"
+		}
+
+		if pf_active == "" {
+			pf_active = "0"
+		}
+
+		if !utils.IsNumeric(pf_id) {
+			wrap.MsgError(`Inner system error`)
+			return
+		}
+
+		if pf_email == "" {
+			wrap.MsgError(`Please specify user email`)
+			return
+		}
+
+		if !utils.IsValidEmail(pf_email) {
+			wrap.MsgError(`Please specify correct user email`)
+			return
+		}
+
+		// First user always super admin
+		// Rewrite active and admin status
+		if pf_id == "1" {
+			pf_admin = "1"
+			pf_active = "1"
+		}
+
+		if pf_id == "0" {
+			// Add new user
+			if pf_password == "" {
+				wrap.MsgError(`Please specify user password`)
+				return
+			}
+			_, err := wrap.DB.Exec(
+				`INSERT INTO users SET
+					first_name = ?,
+					last_name = ?,
+					email = ?,
+					password = MD5(?),
+					admin = ?,
+					active = ?
+				;`,
+				pf_first_name,
+				pf_last_name,
+				pf_email,
+				pf_password,
+				pf_admin,
+				pf_active,
+			)
+			if err != nil {
+				wrap.MsgError(err.Error())
+				return
+			}
+			wrap.Write(`window.location='/cp/users/';`)
+		} else {
+			// Update user
+			if pf_password == "" {
+				_, err := wrap.DB.Exec(
+					`UPDATE users SET
+						first_name = ?,
+						last_name = ?,
+						email = ?,
+						admin = ?,
+						active = ?
+					WHERE
+						id = ?
+					;`,
+					pf_first_name,
+					pf_last_name,
+					pf_email,
+					pf_admin,
+					pf_active,
+					utils.StrToInt(pf_id),
+				)
+				if err != nil {
+					wrap.MsgError(err.Error())
+					return
+				}
+			} else {
+				_, err := wrap.DB.Exec(
+					`UPDATE users SET
+						first_name = ?,
+						last_name = ?,
+						email = ?,
+						password = MD5(?)
+					WHERE
+						id = ?
+					;`,
+					pf_first_name,
+					pf_last_name,
+					pf_email,
+					pf_password,
+					utils.StrToInt(pf_id),
+				)
+				if err != nil {
+					wrap.MsgError(err.Error())
+					return
+				}
+			}
+			wrap.Write(`window.location='/cp/users/modify/` + pf_id + `/';`)
+		}
+	})
+}

+ 98 - 6
utils/utils_test.go

@@ -2,6 +2,10 @@ package utils
 
 import (
 	"errors"
+	"fmt"
+	"net/http"
+	"net/http/httptest"
+	"strings"
 	"testing"
 	"time"
 
@@ -10,8 +14,8 @@ import (
 
 func Expect(t *testing.T, actual, expect interface{}) {
 	if actual != expect {
-		t.Fatalf("\033[0;33mExpected \033[0;32m`%v`\033[0;33m but got \033[0;31m`%v`\033[0m",
-			expect, actual)
+		t.Fatalf("\033[0;33mExpected \033[0;32m`(%T) %v`\033[0;33m but got \033[0;31m`(%T) %v`\033[0m",
+			expect, expect, actual, actual)
 	}
 }
 
@@ -128,19 +132,57 @@ func TestGetCurrentUnixTimestamp(t *testing.T) {
 }
 
 func TestSystemRenderTemplate(t *testing.T) {
-	//
+	request, err := http.NewRequest("GET", "/", nil)
+	if err != nil {
+		t.Fatal(err)
+	}
+	recorder := httptest.NewRecorder()
+	http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+		SystemRenderTemplate(w, []byte(`ok`), nil)
+	}).ServeHTTP(recorder, request)
+	Expect(t, recorder.Code, 200)
+	Expect(t, recorder.Body.String(), `ok`)
 }
 
 func TestSystemErrorPageEngine(t *testing.T) {
-	//
+	request, err := http.NewRequest("GET", "/", nil)
+	if err != nil {
+		t.Fatal(err)
+	}
+	recorder := httptest.NewRecorder()
+	http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+		SystemErrorPageEngine(w, errors.New("Test error"))
+	}).ServeHTTP(recorder, request)
+	Expect(t, recorder.Code, http.StatusInternalServerError)
+	Expect(t, strings.Contains(recorder.Body.String(), "Engine Error"), true)
+	Expect(t, strings.Contains(recorder.Body.String(), "Test error"), true)
 }
 
 func TestSystemErrorPageTemplate(t *testing.T) {
-	//
+	request, err := http.NewRequest("GET", "/", nil)
+	if err != nil {
+		t.Fatal(err)
+	}
+	recorder := httptest.NewRecorder()
+	http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+		SystemErrorPageTemplate(w, errors.New("Test error"))
+	}).ServeHTTP(recorder, request)
+	Expect(t, recorder.Code, http.StatusInternalServerError)
+	Expect(t, strings.Contains(recorder.Body.String(), "Template Error"), true)
+	Expect(t, strings.Contains(recorder.Body.String(), "Test error"), true)
 }
 
 func TestSystemErrorPage404(t *testing.T) {
-	//
+	request, err := http.NewRequest("GET", "/", nil)
+	if err != nil {
+		t.Fatal(err)
+	}
+	recorder := httptest.NewRecorder()
+	http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+		SystemErrorPage404(w)
+	}).ServeHTTP(recorder, request)
+	Expect(t, recorder.Code, http.StatusNotFound)
+	Expect(t, strings.Contains(recorder.Body.String(), "404 Not Found"), true)
 }
 
 func TestUrlToArray(t *testing.T) {
@@ -169,6 +211,10 @@ func TestIntToStr(t *testing.T) {
 	Expect(t, IntToStr(2000), "2000")
 }
 
+func TestInt64ToStr(t *testing.T) {
+	Expect(t, Int64ToStr(2000), "2000")
+}
+
 func TestStrToInt(t *testing.T) {
 	Expect(t, StrToInt("2000"), 2000)
 	Expect(t, StrToInt("string"), 0)
@@ -217,3 +263,49 @@ func TestInArrayInt(t *testing.T) {
 	Expect(t, InArrayInt(slice, 2), false)
 	Expect(t, InArrayInt(slice, 8), false)
 }
+
+func TestInArrayString(t *testing.T) {
+	slice := []string{"1", "3", "5", "9", "0"}
+	Expect(t, InArrayString(slice, "1"), true)
+	Expect(t, InArrayString(slice, "9"), true)
+	Expect(t, InArrayString(slice, "2"), false)
+	Expect(t, InArrayString(slice, "8"), false)
+}
+
+func TestGetPostArrayInt(t *testing.T) {
+	request, err := http.NewRequest("POST", "/", strings.NewReader("cats[]=1&cats[]=3&cats[]=5"))
+	if err != nil {
+		t.Fatal(err)
+	}
+	request.Header.Set("Content-Type", "application/x-www-form-urlencoded; param=value")
+	request.ParseForm()
+	arr := GetPostArrayInt("cats[]", request)
+	Expect(t, fmt.Sprintf("%T%v", arr, arr), "[]int[1 3 5]")
+}
+
+func TestGetPostArrayString(t *testing.T) {
+	request, err := http.NewRequest("POST", "/", strings.NewReader("cats[]=1&cats[]=3&cats[]=5"))
+	if err != nil {
+		t.Fatal(err)
+	}
+	request.Header.Set("Content-Type", "application/x-www-form-urlencoded; param=value")
+	request.ParseForm()
+	arr := GetPostArrayString("cats[]", request)
+	Expect(t, fmt.Sprintf("%T%v", arr, arr), "[]string[1 3 5]")
+}
+
+func TestArrayOfIntToArrayOfString(t *testing.T) {
+	res := ArrayOfIntToArrayOfString([]int{1, 3, 5})
+	Expect(t, len(res), 3)
+	Expect(t, res[0], "1")
+	Expect(t, res[1], "3")
+	Expect(t, res[2], "5")
+}
+
+func TestArrayOfStringToArrayOfInt(t *testing.T) {
+	res := ArrayOfStringToArrayOfInt([]string{"1", "3", "5", "abc"})
+	Expect(t, len(res), 3)
+	Expect(t, res[0], 1)
+	Expect(t, res[1], 3)
+	Expect(t, res[2], 5)
+}