...

Source file src/codeberg.org/tslocum/sriracha/internal/server/server_category.go

Documentation: codeberg.org/tslocum/sriracha/internal/server

     1  package server
     2  
     3  import (
     4  	"fmt"
     5  	"net/http"
     6  	"strconv"
     7  	"strings"
     8  
     9  	"codeberg.org/tslocum/sriracha/internal/database"
    10  	. "codeberg.org/tslocum/sriracha/model"
    11  	. "codeberg.org/tslocum/sriracha/util"
    12  )
    13  
    14  func (s *Server) loadCategoryForm(db *database.DB, r *http.Request, k *Category) {
    15  	parent := FormInt(r, "parent")
    16  	if parent == 0 {
    17  		k.Parent = nil
    18  	} else {
    19  		k.Parent = db.CategoryByID(parent)
    20  	}
    21  	k.Name = FormString(r, "name")
    22  	k.Description = FormString(r, "description")
    23  }
    24  
    25  func (s *Server) serveCategory(data *templateData, db *database.DB, w http.ResponseWriter, r *http.Request) {
    26  	data.Template = "manage_category"
    27  	data.Boards = db.AllBoards()
    28  	data.Manage.Category = &Category{}
    29  	data.Categories = db.AllCategories()
    30  
    31  	categoryAndBoard := func(s string) (*Category, *Board) {
    32  		split := strings.Split(s, "/")
    33  		if len(split) != 2 {
    34  			return nil, nil
    35  		}
    36  		categoryID, err := strconv.Atoi(split[0])
    37  		if err != nil {
    38  			return nil, nil
    39  		}
    40  		boardID, err := strconv.Atoi(split[1])
    41  		if err != nil {
    42  			return nil, nil
    43  		}
    44  		return db.CategoryByID(categoryID), db.BoardByID(boardID)
    45  	}
    46  
    47  	deleteBoardCategory := PathString(r, "/sriracha/category/board/delete/")
    48  	if deleteBoardCategory != "" {
    49  		if s.forbidden(w, data, "category.update") {
    50  			return
    51  		}
    52  		category, board := categoryAndBoard(deleteBoardCategory)
    53  		if category == nil {
    54  			data.ManageError("Invalid category.")
    55  			return
    56  		} else if board == nil {
    57  			data.ManageError("Invalid board.")
    58  			return
    59  		}
    60  
    61  		for i, b := range category.Boards {
    62  			if b.ID == board.ID {
    63  				category.Boards = append(category.Boards[:i], category.Boards[i+1:]...)
    64  				db.UpdateCategory(category)
    65  				s.refreshCategoryCache(db)
    66  				s.rebuildAll(db, false)
    67  				break
    68  			}
    69  		}
    70  
    71  		data.Redirect(w, r, "/sriracha/category/")
    72  		return
    73  	}
    74  
    75  	deleteCategoryID := PathInt(r, "/sriracha/category/delete/")
    76  	if deleteCategoryID > 0 {
    77  		if s.forbidden(w, data, "category.delete") {
    78  			return
    79  		}
    80  		c := db.CategoryByID(deleteCategoryID)
    81  		if c == nil {
    82  			data.ManageError("Invalid category.")
    83  			return
    84  		}
    85  		db.DeleteCategory(c.ID)
    86  
    87  		allCategories := db.AllCategories()
    88  		if len(allCategories) > 0 {
    89  			var haveRoot bool
    90  			for _, c := range allCategories {
    91  				if c.Parent == nil {
    92  					haveRoot = true
    93  					break
    94  				}
    95  			}
    96  			if !haveRoot {
    97  				db.RollBack()
    98  				data.ManageError("Failed to delete category: At least one category without any parent categories must exist.")
    99  				return
   100  			}
   101  		}
   102  
   103  		s.refreshCategoryCache(db)
   104  		s.rebuildAll(db, false)
   105  
   106  		s.log(db, data.Account, nil, fmt.Sprintf("Deleted category #%d", c.ID), "")
   107  
   108  		data.Redirect(w, r, "/sriracha/category/")
   109  		return
   110  	}
   111  
   112  	boardUp := PathString(r, "/sriracha/category/board/up/")
   113  	if boardUp != "" {
   114  		if s.forbidden(w, data, "category.update") {
   115  			return
   116  		}
   117  		category, board := categoryAndBoard(boardUp)
   118  		if category != nil && board != nil {
   119  			for i, b := range category.Boards {
   120  				if b.ID == board.ID && i > 0 {
   121  					category.Boards[i], category.Boards[i-1] = category.Boards[i-1], category.Boards[i]
   122  					db.UpdateCategory(category)
   123  					s.refreshCategoryCache(db)
   124  					s.rebuildAll(db, false)
   125  					break
   126  				}
   127  			}
   128  		}
   129  		data.Redirect(w, r, "/sriracha/category/")
   130  		return
   131  	}
   132  	boardDown := PathString(r, "/sriracha/category/board/down/")
   133  	if boardDown != "" {
   134  		if s.forbidden(w, data, "category.update") {
   135  			return
   136  		}
   137  		category, board := categoryAndBoard(boardDown)
   138  		if category != nil && board != nil {
   139  			for i, b := range category.Boards {
   140  				if b.ID == board.ID && i < len(category.Boards)-1 {
   141  					category.Boards[i], category.Boards[i+1] = category.Boards[i+1], category.Boards[i]
   142  					db.UpdateCategory(category)
   143  					s.refreshCategoryCache(db)
   144  					s.rebuildAll(db, false)
   145  					break
   146  				}
   147  			}
   148  		}
   149  		data.Redirect(w, r, "/sriracha/category/")
   150  		return
   151  	}
   152  
   153  	categoryUpID := PathInt(r, "/sriracha/category/up/")
   154  	if categoryUpID != 0 {
   155  		if s.forbidden(w, data, "category.update") {
   156  			return
   157  		}
   158  		category := db.CategoryByID(categoryUpID)
   159  		if category != nil {
   160  			if category.Parent != nil {
   161  				category.Parent.Categories = db.ChildCategories(category.Parent.ID)
   162  				for i, c := range category.Parent.Categories {
   163  					if c.ID == category.ID && i > 0 {
   164  						category.Parent.Categories[i], category.Parent.Categories[i-1] = category.Parent.Categories[i-1], category.Parent.Categories[i]
   165  						break
   166  					}
   167  				}
   168  				for i, c := range category.Parent.Categories {
   169  					c.Sort = i
   170  					db.UpdateCategory(c)
   171  					s.refreshCategoryCache(db)
   172  					s.rebuildAll(db, false)
   173  				}
   174  			} else {
   175  				var rootCategories []*Category
   176  				for _, c := range data.Categories {
   177  					if c.Parent == nil {
   178  						rootCategories = append(rootCategories, c)
   179  					}
   180  				}
   181  				for i, c := range rootCategories {
   182  					if c.ID == category.ID && i > 0 {
   183  						rootCategories[i], rootCategories[i-1] = rootCategories[i-1], rootCategories[i]
   184  						break
   185  					}
   186  				}
   187  				for i, c := range rootCategories {
   188  					c.Sort = i
   189  					db.UpdateCategory(c)
   190  					s.refreshCategoryCache(db)
   191  					s.rebuildAll(db, false)
   192  				}
   193  			}
   194  		}
   195  		data.Redirect(w, r, "/sriracha/category/")
   196  		return
   197  	}
   198  	categoryDownID := PathInt(r, "/sriracha/category/down/")
   199  	if categoryDownID != 0 {
   200  		if s.forbidden(w, data, "category.update") {
   201  			return
   202  		}
   203  		category := db.CategoryByID(categoryDownID)
   204  		if category != nil {
   205  			if category.Parent != nil {
   206  				category.Parent.Categories = db.ChildCategories(category.Parent.ID)
   207  				for i, c := range category.Parent.Categories {
   208  					if c.ID == category.ID && i < len(category.Parent.Categories)-1 {
   209  						category.Parent.Categories[i], category.Parent.Categories[i+1] = category.Parent.Categories[i+1], category.Parent.Categories[i]
   210  						break
   211  					}
   212  				}
   213  				for i, c := range category.Parent.Categories {
   214  					c.Sort = i
   215  					db.UpdateCategory(c)
   216  					s.refreshCategoryCache(db)
   217  					s.rebuildAll(db, false)
   218  				}
   219  			} else {
   220  				var rootCategories []*Category
   221  				for _, c := range data.Categories {
   222  					if c.Parent == nil {
   223  						rootCategories = append(rootCategories, c)
   224  					}
   225  				}
   226  				for i, c := range rootCategories {
   227  					if c.ID == category.ID && i < len(rootCategories)-1 {
   228  						rootCategories[i], rootCategories[i+1] = rootCategories[i+1], rootCategories[i]
   229  						break
   230  					}
   231  				}
   232  				for i, c := range rootCategories {
   233  					c.Sort = i
   234  					db.UpdateCategory(c)
   235  					s.refreshCategoryCache(db)
   236  					s.rebuildAll(db, false)
   237  				}
   238  			}
   239  		}
   240  		data.Redirect(w, r, "/sriracha/category/")
   241  		return
   242  	}
   243  
   244  	boardCategoryID := PathInt(r, "/sriracha/category/board/")
   245  	if boardCategoryID > 0 {
   246  		if s.forbidden(w, data, "category.update") {
   247  			return
   248  		}
   249  		data.Manage.Category = db.CategoryByID(boardCategoryID)
   250  		data.Extra = "board"
   251  
   252  		if data.Manage.Category != nil && r.Method == http.MethodPost {
   253  			boardID := FormInt(r, "board")
   254  			board := db.BoardByID(boardID)
   255  			if board == nil {
   256  				data.ManageError("Invalid board.")
   257  				return
   258  			}
   259  
   260  			if !data.Manage.Category.HasBoard(board.ID) {
   261  				data.Manage.Category.Boards = append(data.Manage.Category.Boards, board)
   262  				db.UpdateCategory(data.Manage.Category)
   263  				s.refreshCategoryCache(db)
   264  				s.rebuildAll(db, false)
   265  			}
   266  
   267  			data.Redirect(w, r, "/sriracha/category/")
   268  			return
   269  		}
   270  		return
   271  	}
   272  
   273  	categoryID, err := strconv.Atoi(strings.TrimPrefix(r.URL.Path, "/sriracha/category/"))
   274  	if err == nil && categoryID > 0 {
   275  		if s.forbidden(w, data, "category.update") {
   276  			return
   277  		}
   278  		data.Manage.Category = db.CategoryByID(categoryID)
   279  
   280  		if data.Manage.Category != nil && r.Method == http.MethodPost {
   281  			oldCategory := *data.Manage.Category
   282  			s.loadCategoryForm(db, r, data.Manage.Category)
   283  
   284  			db.UpdateCategory(data.Manage.Category)
   285  
   286  			var haveRoot bool
   287  			for _, c := range db.AllCategories() {
   288  				if c.Parent == nil {
   289  					haveRoot = true
   290  					break
   291  				}
   292  			}
   293  			if !haveRoot {
   294  				db.RollBack()
   295  				data.ManageError("Failed to delete category: At least one category without any parent categories must exist.")
   296  				return
   297  			}
   298  
   299  			s.refreshCategoryCache(db)
   300  			s.rebuildAll(db, false)
   301  
   302  			changes := printChanges(oldCategory, *data.Manage.Category)
   303  			s.log(db, data.Account, nil, fmt.Sprintf("Updated >>/category/%d", data.Manage.Category.ID), changes)
   304  
   305  			data.Redirect(w, r, "/sriracha/category/")
   306  			return
   307  		}
   308  		return
   309  	}
   310  
   311  	if r.Method == http.MethodPost {
   312  		if s.forbidden(w, data, "category.add") {
   313  			return
   314  		}
   315  		c := &Category{}
   316  		s.loadCategoryForm(db, r, c)
   317  
   318  		var cSort int
   319  		if c.Parent != nil {
   320  			for _, cat := range c.Categories {
   321  				if cat.Sort > cSort {
   322  					cSort = cat.Sort
   323  				}
   324  			}
   325  		} else {
   326  			for _, cat := range data.Categories {
   327  				if cat.Parent == nil && cat.Sort > cSort {
   328  					cSort = cat.Sort
   329  				}
   330  			}
   331  		}
   332  		c.Sort = cSort + 1
   333  
   334  		db.AddCategory(c)
   335  
   336  		s.refreshCategoryCache(db)
   337  		s.rebuildAll(db, false)
   338  
   339  		s.log(db, data.Account, nil, fmt.Sprintf("Added >>/category/%d", c.ID), "")
   340  
   341  		data.Redirect(w, r, "/sriracha/category/")
   342  		return
   343  	}
   344  }
   345  

View as plain text