ref: d48b986c45f8d5a5fef7c98da17af8ca82867b25
parent: dc8659c53904de457cd0354a262fa42c259462d0
author: Bjørn Erik Pedersen <[email protected]>
date: Wed Apr 13 15:13:33 EDT 2016
Revert "tpl: Extend where to iterate over maps" Committed by accident. This reverts commit 0141a02160ee7b91642d3c3475959d6742ccd693.
--- a/tpl/template_funcs.go
+++ b/tpl/template_funcs.go
@@ -37,11 +37,13 @@
"time"
"unicode/utf8"
- "github.com/bep/inflect"
"github.com/spf13/afero"
+ "github.com/spf13/hugo/hugofs"
+
+ "github.com/bep/inflect"
+
"github.com/spf13/cast"
"github.com/spf13/hugo/helpers"
- "github.com/spf13/hugo/hugofs"
jww "github.com/spf13/jwalterweatherman"
)
@@ -769,9 +771,13 @@
return false, nil
}
-// parseWhereArgs parses the end arguments to the where function. Return a
-// match value and an operator, if one is defined.
-func parseWhereArgs(args ...interface{}) (mv reflect.Value, op string, err error) {
+// where returns a filtered subset of a given data type.
+func where(seq, key interface{}, args ...interface{}) (r interface{}, err error) {
+ seqv := reflect.ValueOf(seq)
+ kv := reflect.ValueOf(key)
+
+ var mv reflect.Value
+ var op string
switch len(args) {
case 1:
mv = reflect.ValueOf(args[0])
@@ -778,107 +784,20 @@
case 2:
var ok bool
if op, ok = args[0].(string); !ok {
- err = errors.New("operator argument must be string type")
- return
+ return nil, errors.New("operator argument must be string type")
}
op = strings.TrimSpace(strings.ToLower(op))
mv = reflect.ValueOf(args[1])
default:
- err = errors.New("can't evaluate the array by no match argument or more than or equal to two arguments")
+ return nil, errors.New("can't evaluate the array by no match argument or more than or equal to two arguments")
}
- return
-}
-// checkWhereArray handles the where-matching logic when the seqv value is an
-// Array or Slice.
-func checkWhereArray(seqv, kv, mv reflect.Value, path []string, op string) (interface{}, error) {
- rv := reflect.MakeSlice(seqv.Type(), 0, 0)
- for i := 0; i < seqv.Len(); i++ {
- var vvv reflect.Value
- rvv := seqv.Index(i)
- if kv.Kind() == reflect.String {
- vvv = rvv
- for _, elemName := range path {
- var err error
- vvv, err = evaluateSubElem(vvv, elemName)
- if err != nil {
- return nil, err
- }
- }
- } else {
- vv, _ := indirect(rvv)
- if vv.Kind() == reflect.Map && kv.Type().AssignableTo(vv.Type().Key()) {
- vvv = vv.MapIndex(kv)
- }
- }
-
- if ok, err := checkCondition(vvv, mv, op); ok {
- rv = reflect.Append(rv, rvv)
- } else if err != nil {
- return nil, err
- }
- }
- return rv.Interface(), nil
-}
-
-// checkWhereMap handles the where-matching logic when the seqv value is a Map.
-func checkWhereMap(seqv, kv, mv reflect.Value, path []string, op string) (interface{}, error) {
- rv := reflect.MakeMap(seqv.Type())
- keys := seqv.MapKeys()
- for _, k := range keys {
- elemv := seqv.MapIndex(k)
- switch elemv.Kind() {
- case reflect.Array, reflect.Slice:
- r, err := checkWhereArray(elemv, kv, mv, path, op)
- if err != nil {
- return nil, err
- }
-
- switch rr := reflect.ValueOf(r); rr.Kind() {
- case reflect.Slice:
- if rr.Len() > 0 {
- rv.SetMapIndex(k, elemv)
- }
- }
- case reflect.Interface:
- elemvv, isNil := indirect(elemv)
- if isNil {
- continue
- }
-
- switch elemvv.Kind() {
- case reflect.Array, reflect.Slice:
- r, err := checkWhereArray(elemvv, kv, mv, path, op)
- if err != nil {
- return nil, err
- }
-
- switch rr := reflect.ValueOf(r); rr.Kind() {
- case reflect.Slice:
- if rr.Len() > 0 {
- rv.SetMapIndex(k, elemv)
- }
- }
- }
- }
- }
- return rv, nil
-}
-
-// where returns a filtered subset of a given data type.
-func where(seq, key interface{}, args ...interface{}) (interface{}, error) {
- seqv, isNil := indirect(reflect.ValueOf(seq))
+ seqv, isNil := indirect(seqv)
if isNil {
return nil, errors.New("can't iterate over a nil value of type " + reflect.ValueOf(seq).Type().String())
}
- mv, op, err := parseWhereArgs(args...)
- if err != nil {
- return nil, err
- }
-
var path []string
- kv := reflect.ValueOf(key)
if kv.Kind() == reflect.String {
path = strings.Split(strings.Trim(kv.String(), "."), ".")
}
@@ -885,9 +804,31 @@
switch seqv.Kind() {
case reflect.Array, reflect.Slice:
- return checkWhereArray(seqv, kv, mv, path, op)
- case reflect.Map:
- return checkWhereMap(seqv, kv, mv, path, op)
+ rv := reflect.MakeSlice(seqv.Type(), 0, 0)
+ for i := 0; i < seqv.Len(); i++ {
+ var vvv reflect.Value
+ rvv := seqv.Index(i)
+ if kv.Kind() == reflect.String {
+ vvv = rvv
+ for _, elemName := range path {
+ vvv, err = evaluateSubElem(vvv, elemName)
+ if err != nil {
+ return nil, err
+ }
+ }
+ } else {
+ vv, _ := indirect(rvv)
+ if vv.Kind() == reflect.Map && kv.Type().AssignableTo(vv.Type().Key()) {
+ vvv = vv.MapIndex(kv)
+ }
+ }
+ if ok, err := checkCondition(vvv, mv, op); ok {
+ rv = reflect.Append(rv, rvv)
+ } else if err != nil {
+ return nil, err
+ }
+ }
+ return rv.Interface(), nil
default:
return nil, fmt.Errorf("can't iterate over %v", seq)
}
--- a/tpl/template_funcs_test.go
+++ b/tpl/template_funcs_test.go
@@ -18,6 +18,11 @@
"encoding/base64"
"errors"
"fmt"
+ "github.com/spf13/afero"
+ "github.com/spf13/cast"
+ "github.com/spf13/hugo/hugofs"
+ "github.com/spf13/viper"
+ "github.com/stretchr/testify/assert"
"html/template"
"math/rand"
"path"
@@ -27,12 +32,6 @@
"strings"
"testing"
"time"
-
- "github.com/spf13/afero"
- "github.com/spf13/cast"
- "github.com/spf13/hugo/hugofs"
- "github.com/spf13/viper"
- "github.com/stretchr/testify/assert"
)
type tstNoStringer struct {
@@ -1298,17 +1297,6 @@
},
key: "B", op: "op", match: "f",
expect: false,
- },
- {
- sequence: map[string]interface{}{
- "foo": []interface{}{map[interface{}]interface{}{"a": 1, "b": 2}},
- "bar": []interface{}{map[interface{}]interface{}{"a": 3, "b": 4}},
- "zap": []interface{}{map[interface{}]interface{}{"a": 5, "b": 6}},
- },
- key: "b", op: "in", match: slice(3, 4, 5),
- expect: map[string]interface{}{
- "bar": []interface{}{map[interface{}]interface{}{"a": 3, "b": 4}},
- },
},
} {
var results interface{}