fix(17): WR-01 keep a menu entry's subtree and parent in its menu

- The admin refuses a parent from another menu than the one the form
  names (errors.parent_menu) instead of moving the entry to the parent's
  menu without a word; BeforeSave records the named menu
  (MenuEntry.RequestedMenuID).
- An entry moved to another menu moves its descendants in the same
  transaction, so the public tree no longer drops them.
This commit is contained in:
2026-10-12 21:30:36 +02:00
parent 43267de323
commit 7255d34ae0
6 changed files with 69 additions and 6 deletions

View File

@@ -48,6 +48,10 @@ type MenuEntry struct {
IsPublished *bool `gorm:"column:is_published"`
CreatedAt *time.Time `gorm:"column:created_at"`
UpdatedAt *time.Time `gorm:"column:updated_at"`
// requestedMenuID is the menu a save asked for when BeforeSave replaced
// it with the parent's menu (see RequestedMenuID).
requestedMenuID uint
}
func (MenuEntry) TableName() string { return "golem15_menu_menu_entries" }
@@ -71,7 +75,10 @@ func (MenuEntry) Rules() map[string]string {
// an entry with a parent takes the parent's menu, and an entry without a
// sort_order goes after the menu's last one. A missing title is stored empty
// (dividers have none) and a missing published flag is the PHP default true.
// When the entry named another menu than its parent's, RequestedMenuID
// reports the menu it named; the admin refuses such a save.
func (e *MenuEntry) BeforeSave(tx *gorm.DB) error {
e.requestedMenuID = 0
zero := func(p **int) {
if *p == nil {
v := 0
@@ -96,6 +103,9 @@ func (e *MenuEntry) BeforeSave(tx *gorm.DB) error {
return err
}
if len(menuIDs) > 0 && menuIDs[0] != 0 {
if e.MenuID != 0 && e.MenuID != menuIDs[0] {
e.requestedMenuID = e.MenuID
}
e.MenuID = menuIDs[0]
}
}
@@ -113,6 +123,11 @@ func (e *MenuEntry) BeforeSave(tx *gorm.DB) error {
return nil
}
// RequestedMenuID is the menu the last save of e named when BeforeSave
// replaced it with the parent's menu: the parent belongs to another menu.
// It is 0 when the entry named no menu or its parent's.
func (e *MenuEntry) RequestedMenuID() uint { return e.requestedMenuID }
// Text is the value of an optional text column, "" when null.
func Text(s *string) string {
if s == nil {