package widget
import (
"fmt"
"github.com/fthvgb1/wp-go/helper/maps"
"github.com/fthvgb1/wp-go/helper/slice"
str "github.com/fthvgb1/wp-go/helper/strings"
"github.com/fthvgb1/wp-go/helper/tree"
"github.com/fthvgb1/wp-go/internal/pkg/cache"
"github.com/fthvgb1/wp-go/internal/pkg/constraints"
"github.com/fthvgb1/wp-go/internal/pkg/constraints/widgets"
"github.com/fthvgb1/wp-go/internal/pkg/models"
"github.com/fthvgb1/wp-go/internal/theme/wp"
"github.com/fthvgb1/wp-go/internal/wpconfig"
"github.com/fthvgb1/wp-go/safety"
"net/http"
"strings"
)
var categoryArgs safety.Var[map[string]string]
var categoryConfig = func() safety.Var[map[any]any] {
v := safety.Var[map[any]any]{}
v.Store(map[any]any{
"count": int64(0),
"dropdown": int64(0),
"hierarchical": int64(0),
"title": "分类",
})
categoryArgs.Store(map[string]string{
"{$before_widget}": `",
"{$before_title}": `
",
"{$before_sidebar}": "",
"{$after_sidebar}": "",
"{$class}": "postform",
"{$show_option_none}": "选择分类",
"{$name}": "cat",
"{$id}": "cat",
"{$required}": "",
"{$nav}": "",
"{$navCloser}": "",
"{$title}": "",
"{$dropdown_id}": "archives-dropdown-2",
"{$dropdown_type}": "monthly",
"{$dropdown_label}": "选择月份",
})
return v
}()
var categoryTemplate = `{$before_widget}
{$title}
{$nav}
{$html}
{$navCloser}
{$after_widget}
`
func Category(h *wp.Handle) string {
args := wp.GetComponentsArgs(h, widgets.Categories, categoryArgs.Load())
args = maps.FilterZeroMerge(categoryArgs.Load(), args)
conf := wpconfig.GetPHPArrayVal("widget_categories", categoryConfig.Load(), int64(2))
conf = maps.FilterZeroMerge(categoryConfig.Load(), conf)
args["{$title}"] = str.Join(args["{$before_title}"], conf["title"].(string), args["{$after_title}"])
t := categoryTemplate
dropdown := conf["dropdown"].(int64)
categories := cache.CategoriesTags(h.C, constraints.Category)
if dropdown == 1 {
t = strings.ReplaceAll(t, "{$html}", categoryDropdown(h, args, conf, categories))
} else {
t = strings.ReplaceAll(t, "{$html}", categoryUL(h, args, conf, categories))
}
return str.Replace(t, args)
}
func categoryUL(h *wp.Handle, args map[string]string, conf map[any]any, categories []models.TermsMy) string {
if slice.IsContained(h.CommonThemeMods().ThemeSupport.HTML5, "navigation-widgets") {
args["{$nav}"] = fmt.Sprintf(`"
}
s := str.NewBuilder()
s.WriteString("\n")
isCount := conf["count"].(int64)
if conf["hierarchical"].(int64) == 0 {
for _, category := range categories {
count := ""
if isCount != 0 {
count = fmt.Sprintf("(%d)", category.Count)
}
s.Sprintf(` -
%s %s
`, category.Terms.TermId, category.Name, category.Name, count)
}
} else {
m := tree.Roots(categories, 0, func(cate models.TermsMy) (child, parent uint64) {
return cate.TermTaxonomyId, cate.Parent
})
cate := &tree.Node[models.TermsMy, uint64]{Data: models.TermsMy{}}
if h.Scene() == constraints.Category {
cat := h.C.Param("category")
i, ca := slice.SearchFirst(categories, func(my models.TermsMy) bool {
return cat == my.Name
})
if i > 0 {
cate = m[ca.TermTaxonomyId]
}
}
r := m[0]
categoryLi(r, cate, tree.Ancestor(m, 0, cate), isCount, s)
}
s.WriteString("
")
return s.String()
}
func categoryLi(root *tree.Node[models.TermsMy, uint64], cate, roots *tree.Node[models.TermsMy, uint64], isCount int64, s *str.Builder) {
for _, child := range *root.Children {
category := child.Data
count := ""
if isCount != 0 {
count = fmt.Sprintf("(%d)", category.Count)
}
var class []string
if len(*child.Children) > 0 && cate.Data.TermTaxonomyId > 0 {
if category.TermTaxonomyId == cate.Parent {
class = append(class, "current-cat-parent")
}
if cate.Parent > 0 && category.TermTaxonomyId == roots.Data.TermTaxonomyId {
class = append(class, "current-cat-ancestor")
}
}
aria := ""
if category.TermTaxonomyId == cate.Data.TermTaxonomyId {
class = append(class, "current-cat")
aria = `aria-current="page"`
}
s.Sprintf(`
%s %s
`, category.Terms.TermId, strings.Join(class, " "), aria, category.Name, category.Name, count)
if len(*child.Children) > 0 {
s.WriteString(`
`)
categoryLi(&child, cate, roots, isCount, s)
s.WriteString(`
`)
}
}
}
var categoryDropdownJs = `/* 0 ) {
dropdown.parentNode.submit();
}
}
dropdown.onchange = onCatChange;
})();
/* ]]> */
`
func categoryDropdown(h *wp.Handle, args map[string]string, conf map[any]any, categories []models.TermsMy) string {
s := str.NewBuilder()
s.WriteString(`\n")
attr := ""
if !slice.IsContained(h.CommonThemeMods().ThemeSupport.HTML5, "script") {
attr = ` type="text/javascript"`
}
s.Sprintf(`\n")
return s.String()
}
func IsCategory(next wp.HandleFn[*wp.Handle], h *wp.Handle) {
if h.Scene() != constraints.Home {
next(h)
return
}
name, ok := parseDropdownCate(h)
if !ok {
next(h)
return
}
h.C.Redirect(http.StatusMovedPermanently, fmt.Sprintf("/p/category/%s", name))
}
func parseDropdownCate(h *wp.Handle) (cateName string, r bool) {
cate := wp.GetComponentsArgs[map[string]string](h, widgets.Categories, categoryArgs.Load())
name, ok := cate["{$name}"]
if !ok || name == "" {
return
}
cat := h.C.Query(name)
if cat == "" {
return
}
id := str.ToInteger[uint64](cat, 0)
if id < 1 {
return
}
i, cc := slice.SearchFirst(cache.CategoriesTags(h.C, constraints.Category), func(my models.TermsMy) bool {
return id == my.Terms.TermId
})
if i < 0 {
return
}
r = true
cateName = cc.Name
return
}