wp-go/app/theme/wp/components/widget/category.go

295 lines
8.4 KiB
Go
Raw Normal View History

2023-03-14 05:50:13 +00:00
package widget
import (
"fmt"
2023-05-04 12:37:06 +00:00
"github.com/fthvgb1/wp-go/app/cmd/reload"
"github.com/fthvgb1/wp-go/app/pkg/cache"
"github.com/fthvgb1/wp-go/app/pkg/constraints"
"github.com/fthvgb1/wp-go/app/pkg/constraints/widgets"
"github.com/fthvgb1/wp-go/app/pkg/models"
"github.com/fthvgb1/wp-go/app/theme/wp"
2023-03-14 05:50:13 +00:00
"github.com/fthvgb1/wp-go/helper/maps"
"github.com/fthvgb1/wp-go/helper/slice"
str "github.com/fthvgb1/wp-go/helper/strings"
2023-03-15 13:40:45 +00:00
"github.com/fthvgb1/wp-go/helper/tree"
2023-03-14 10:35:48 +00:00
"net/http"
2023-03-14 05:50:13 +00:00
"strings"
)
2023-03-17 11:51:53 +00:00
var categoryTemplate = `{$before_widget}
{$title}
{$nav}
{$html}
{$navCloser}
{$after_widget}
`
2023-05-03 15:57:49 +00:00
var categoryConfig = map[any]any{
"count": int64(0),
"dropdown": int64(0),
"hierarchical": int64(0),
"title": "分类",
2023-03-17 11:51:53 +00:00
}
func categoryArgs() map[string]string {
return map[string]string{
2023-03-14 10:35:48 +00:00
"{$before_sidebar}": "",
"{$after_sidebar}": "",
"{$class}": "postform",
"{$show_option_none}": "选择分类",
"{$name}": "cat",
"{$selectId}": "cat",
2023-03-14 10:35:48 +00:00
"{$required}": "",
"{$nav}": "",
"{$navCloser}": "",
"{$title}": "",
2023-03-17 11:51:53 +00:00
}
}
2023-03-14 05:50:13 +00:00
2023-03-28 13:45:20 +00:00
func Category(h *wp.Handle, id string) string {
2023-05-03 15:57:49 +00:00
conf := configs(categoryConfig, "widget_categories", int64(2))
2023-03-27 04:59:29 +00:00
2023-03-28 13:45:20 +00:00
args := reload.GetAnyValBys("widget-category-args", h, func(h *wp.Handle) map[string]string {
commonArgs := wp.GetComponentsArgs(h, widgets.Widget, map[string]string{})
args := wp.GetComponentsArgs(h, widgets.Categories, categoryArgs())
args = maps.FilterZeroMerge(categoryArgs(), CommonArgs(), commonArgs, args)
args["{$before_widget}"] = fmt.Sprintf(args["{$before_widget}"], str.Join("categories-", id), str.Join("widget widget_", "categories"))
args["{$title}"] = str.Join(args["{$before_title}"], conf["title"].(string), args["{$after_title}"])
2023-04-05 12:54:38 +00:00
if conf["dropdown"].(int64) == 0 && slice.IsContained(h.CommonThemeMods().ThemeSupport.HTML5, "navigation-widgets") {
args["{$nav}"] = fmt.Sprintf(`<nav aria-label="%s">`, args["{title}"])
args["{$navCloser}"] = "</nav>"
}
2023-03-28 13:45:20 +00:00
return args
})
2023-03-14 05:50:13 +00:00
t := categoryTemplate
dropdown := conf["dropdown"].(int64)
categories := cache.CategoriesTags(h.C, constraints.Category)
if dropdown == 1 {
2023-03-27 03:37:24 +00:00
t = strings.ReplaceAll(t, "{$html}", CategoryDropdown(h, args, conf, categories))
2023-03-14 05:50:13 +00:00
} else {
t = strings.ReplaceAll(t, "{$html}", categoryUL(h, args, conf, categories))
}
2023-08-26 14:01:20 +00:00
return h.DoActionFilter(widgets.Categories, str.Replace(t, args))
2023-03-14 05:50:13 +00:00
}
2023-03-20 15:41:57 +00:00
func CategoryLi(h *wp.Handle, conf map[any]any, categories []models.TermsMy) string {
2023-03-14 05:50:13 +00:00
s := str.NewBuilder()
isCount := conf["count"].(int64)
2023-03-19 14:14:42 +00:00
currentCate := models.TermsMy{}
if h.Scene() == constraints.Category {
cat := h.C.Param("category")
_, currentCate = slice.SearchFirst(categories, func(my models.TermsMy) bool {
return cat == my.Name
})
}
2023-03-15 16:56:40 +00:00
if conf["hierarchical"].(int64) == 0 {
for _, category := range categories {
count := ""
if isCount != 0 {
count = fmt.Sprintf("(%d)", category.Count)
}
2023-03-19 14:14:42 +00:00
current := ""
if category.TermTaxonomyId == currentCate.TermTaxonomyId {
current = "current-cat"
}
s.Sprintf(` <li class="cat-item cat-item-%d %s">
2023-03-14 05:50:13 +00:00
<a href="/p/category/%s">%s %s</a>
</li>
2023-03-19 14:14:42 +00:00
`, category.Terms.TermId, current, category.Name, category.Name, count)
2023-03-15 16:56:40 +00:00
}
} 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{}}
2023-03-19 14:14:42 +00:00
if currentCate.TermTaxonomyId > 0 {
cate = m[currentCate.TermTaxonomyId]
2023-03-15 16:56:40 +00:00
}
r := m[0]
categoryLi(r, cate, tree.Ancestor(m, 0, cate), isCount, s)
2023-03-14 05:50:13 +00:00
}
2023-03-20 15:41:57 +00:00
return s.String()
}
2023-03-15 16:56:40 +00:00
2023-03-20 15:41:57 +00:00
func categoryUL(h *wp.Handle, args map[string]string, conf map[any]any, categories []models.TermsMy) string {
s := str.NewBuilder()
s.WriteString("<ul>\n")
s.WriteString(CategoryLi(h, conf, categories))
2023-03-14 05:50:13 +00:00
s.WriteString("</ul>")
return s.String()
}
2023-03-14 10:35:48 +00:00
2023-03-15 16:56:40 +00:00
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(` <li class="cat-item cat-item-%d %s">
<a %s href="/p/category/%s">%s %s</a>
2023-03-19 12:40:08 +00:00
2023-03-15 16:56:40 +00:00
`, category.Terms.TermId, strings.Join(class, " "), aria, category.Name, category.Name, count)
if len(*child.Children) > 0 {
2023-03-19 12:40:08 +00:00
s.WriteString(` <ul class="children">
2023-03-15 16:56:40 +00:00
`)
categoryLi(&child, cate, roots, isCount, s)
2023-03-19 12:40:08 +00:00
s.WriteString(`</ul>
`)
2023-03-15 16:56:40 +00:00
}
2023-03-19 12:40:08 +00:00
s.Sprintf(`</li>`)
2023-03-15 16:56:40 +00:00
}
}
2023-03-14 10:35:48 +00:00
var categoryDropdownJs = `/* <![CDATA[ */
(function() {
var dropdown = document.getElementById( "%s" );
function onCatChange() {
if ( dropdown.options[ dropdown.selectedIndex ].value > 0 ) {
dropdown.parentNode.submit();
}
}
dropdown.onchange = onCatChange;
})();
/* ]]> */
`
2023-03-27 03:37:24 +00:00
func CategoryDropdown(h *wp.Handle, args map[string]string, conf map[any]any, categories []models.TermsMy) string {
2023-03-14 10:35:48 +00:00
s := str.NewBuilder()
s.WriteString(`<form action="/" method="get">
`)
s.Sprintf(` <label class="screen-reader-text" for="%s">%s</label>
`, args["{$selectId}"], args["{$title}"])
2023-03-27 03:37:24 +00:00
s.WriteString(DropdownCategories(h, args, conf, categories))
2023-03-14 10:35:48 +00:00
s.WriteString("</form>\n")
attr := ""
if !slice.IsContained(h.CommonThemeMods().ThemeSupport.HTML5, "script") {
attr = ` type="text/javascript"`
}
s.Sprintf(`<script%s>
`, attr)
s.Sprintf(categoryDropdownJs, args["{$selectId}"])
2023-03-14 10:35:48 +00:00
s.WriteString("</script>\n")
return s.String()
}
2023-03-27 03:37:24 +00:00
func DropdownCategories(h *wp.Handle, args map[string]string, conf map[any]any, categories []models.TermsMy) string {
if len(categories) < 1 {
return ""
}
s := str.NewBuilder()
s.Sprintf(` <select %s name="%s" id="%s" class="%s">
`, args["{$required}"], args["{$name}"], args["{$selectId}"], args["{$class}"])
s.Sprintf(` <option value="-1">%s</option>
`, args["{$show_option_none}"])
currentCategory := ""
if h.Scene() == constraints.Category {
currentCategory = h.Index.Param.Category
}
showCount := conf["count"].(int64)
fn := func(category models.TermsMy, deep int) {
lv := fmt.Sprintf("level-%d", deep+1)
sep := strings.Repeat("&nbsp;", deep*2)
selected := ""
if category.Name == currentCategory {
selected = "selected"
}
count := ""
if showCount != 0 {
count = fmt.Sprintf("(%d)", category.Count)
}
s.Sprintf(` <option class="%s" %s value="%d">%s%s %s</option>
`, lv, selected, category.Terms.TermId, sep, category.Name, count)
}
if conf["hierarchical"].(int64) == 0 {
for _, category := range categories {
fn(category, 0)
}
} else {
tree.Root(categories, 0, func(t models.TermsMy) (child, parent uint64) {
return t.TermTaxonomyId, t.Parent
}).Loop(func(category models.TermsMy, deep int) {
fn(category, deep)
})
}
s.WriteString(" </select>\n")
2023-08-26 14:01:20 +00:00
return h.DoActionFilter("wp_dropdown_cats", s.String())
2023-03-27 03:37:24 +00:00
}
2023-08-26 14:01:20 +00:00
func CheckCategory(h *wp.Handle) {
2023-03-14 10:35:48 +00:00
name, ok := parseDropdownCate(h)
2023-05-03 15:57:49 +00:00
if ok {
h.C.Redirect(http.StatusMovedPermanently, fmt.Sprintf("/p/category/%s", name))
h.Abort()
2023-03-14 10:35:48 +00:00
}
}
func parseDropdownCate(h *wp.Handle) (cateName string, r bool) {
2023-03-17 11:51:53 +00:00
cate := wp.GetComponentsArgs[map[string]string](h, widgets.Categories, categoryArgs())
2023-03-14 10:35:48 +00:00
name, ok := cate["{$name}"]
if !ok || name == "" {
return
}
cat := h.C.Query(name)
if cat == "" {
return
}
2023-03-14 11:47:18 +00:00
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
2023-03-14 10:35:48 +00:00
})
2023-03-14 11:47:18 +00:00
if i < 0 {
2023-03-14 10:35:48 +00:00
return
}
2023-03-15 13:40:45 +00:00
r = true
2023-03-14 10:35:48 +00:00
cateName = cc.Name
return
}
2023-08-26 14:01:20 +00:00
func IsCategory(h *wp.Handle) (category models.TermsMy, r bool) {
cate := wp.GetComponentsArgs[map[string]string](h, widgets.Categories, categoryArgs())
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
category = cc
return
}