Make GroupByParamDate work with string params
authorBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>
Fri, 19 Jun 2020 08:13:35 +0000 (10:13 +0200)
committerBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>
Fri, 19 Jun 2020 09:58:58 +0000 (11:58 +0200)
Fixes #3983

resources/page/pagegroup.go
resources/page/pagegroup_test.go

index 2d37a5d4d122016f16b990f0ffcb2e766586bea1..fcae9add7c2e4d49899b2b3e180d6cfd6a8e39af 100644 (file)
@@ -21,6 +21,8 @@ import (
        "strings"
        "time"
 
+       "github.com/spf13/cast"
+
        "github.com/gohugoio/hugo/common/collections"
        "github.com/gohugoio/hugo/compare"
 
@@ -225,6 +227,10 @@ func (p Pages) groupByDateField(sorter func(p Pages) Pages, formatter func(p Pag
                sp = sp.Reverse()
        }
 
+       if sp == nil {
+               return nil, nil
+       }
+
        date := formatter(sp[0].(Page))
        var r []PageGroup
        r = append(r, PageGroup{Key: date, Pages: make(Pages, 0)})
@@ -303,23 +309,36 @@ func (p Pages) GroupByLastmod(format string, order ...string) (PagesGroup, error
 // Valid values for order is asc, desc, rev and reverse.
 // For valid format strings, see https://golang.org/pkg/time/#Time.Format
 func (p Pages) GroupByParamDate(key string, format string, order ...string) (PagesGroup, error) {
-       sorter := func(p Pages) Pages {
+       // Cache the dates.
+       dates := make(map[Page]time.Time)
+
+       sorter := func(pages Pages) Pages {
                var r Pages
-               for _, e := range p {
-                       param := resource.GetParamToLower(e, key)
-                       if _, ok := param.(time.Time); ok {
-                               r = append(r, e)
+
+               for _, p := range pages {
+                       param := resource.GetParamToLower(p, key)
+                       var t time.Time
+
+                       if param != nil {
+                               var ok bool
+                               if t, ok = param.(time.Time); !ok {
+                                       // Probably a string. Try to convert it to time.Time.
+                                       t = cast.ToTime(param)
+                               }
                        }
+
+                       dates[p] = t
+                       r = append(r, p)
                }
+
                pdate := func(p1, p2 Page) bool {
-                       p1p, p2p := p1.(Page), p2.(Page)
-                       return resource.GetParamToLower(p1p, key).(time.Time).Unix() < resource.GetParamToLower(p2p, key).(time.Time).Unix()
+                       return dates[p1].Unix() < dates[p2].Unix()
                }
                pageBy(pdate).Sort(r)
                return r
        }
        formatter := func(p Page) string {
-               return resource.GetParamToLower(p, key).(time.Time).Format(format)
+               return dates[p].Format(format)
        }
        return p.groupByDateField(sorter, formatter, order...)
 }
index fe6dbf94bdfe5328ba24f2b0d054cd411526ec84..d4a3f36a67d7d615ae3ab19665da13beb0576d02 100644 (file)
@@ -52,6 +52,7 @@ func preparePageGroupTestPages(t *testing.T) Pages {
                p.lastMod = cast.ToTime(src.date).AddDate(3, 0, 0)
                p.params["custom_param"] = src.param
                p.params["custom_date"] = cast.ToTime(src.date)
+               p.params["custom_string_date"] = src.date
                pages = append(pages, p)
        }
        return pages
@@ -379,6 +380,25 @@ func TestGroupByParamDate(t *testing.T) {
        }
 }
 
+// https://github.com/gohugoio/hugo/issues/3983
+func TestGroupByParamDateWithStringParams(t *testing.T) {
+       t.Parallel()
+       pages := preparePageGroupTestPages(t)
+       expect := PagesGroup{
+               {Key: "2012-04", Pages: Pages{pages[4], pages[2], pages[0]}},
+               {Key: "2012-03", Pages: Pages{pages[3]}},
+               {Key: "2012-01", Pages: Pages{pages[1]}},
+       }
+
+       groups, err := pages.GroupByParamDate("custom_string_date", "2006-01")
+       if err != nil {
+               t.Fatalf("Unable to make PagesGroup array: %s", err)
+       }
+       if !reflect.DeepEqual(groups, expect) {
+               t.Errorf("PagesGroup has unexpected groups. It should be %#v, got %#v", expect, groups)
+       }
+}
+
 func TestGroupByLastmod(t *testing.T) {
        t.Parallel()
        pages := preparePageGroupTestPages(t)