Revert "tpl: Extend where to iterate over maps"

Committed by accident.

This reverts commit 0141a02160.
This commit is contained in:
Bjørn Erik Pedersen 2016-04-13 19:13:33 +02:00
parent dc8659c539
commit d48b986c45
2 changed files with 44 additions and 115 deletions

View file

@ -37,11 +37,13 @@ import (
"time" "time"
"unicode/utf8" "unicode/utf8"
"github.com/bep/inflect"
"github.com/spf13/afero" "github.com/spf13/afero"
"github.com/spf13/hugo/hugofs"
"github.com/bep/inflect"
"github.com/spf13/cast" "github.com/spf13/cast"
"github.com/spf13/hugo/helpers" "github.com/spf13/hugo/helpers"
"github.com/spf13/hugo/hugofs"
jww "github.com/spf13/jwalterweatherman" jww "github.com/spf13/jwalterweatherman"
) )
@ -769,29 +771,39 @@ func checkCondition(v, mv reflect.Value, op string) (bool, error) {
return false, nil return false, nil
} }
// parseWhereArgs parses the end arguments to the where function. Return a // where returns a filtered subset of a given data type.
// match value and an operator, if one is defined. func where(seq, key interface{}, args ...interface{}) (r interface{}, err error) {
func parseWhereArgs(args ...interface{}) (mv reflect.Value, op string, err error) { seqv := reflect.ValueOf(seq)
kv := reflect.ValueOf(key)
var mv reflect.Value
var op string
switch len(args) { switch len(args) {
case 1: case 1:
mv = reflect.ValueOf(args[0]) mv = reflect.ValueOf(args[0])
case 2: case 2:
var ok bool var ok bool
if op, ok = args[0].(string); !ok { if op, ok = args[0].(string); !ok {
err = errors.New("operator argument must be string type") return nil, errors.New("operator argument must be string type")
return
} }
op = strings.TrimSpace(strings.ToLower(op)) op = strings.TrimSpace(strings.ToLower(op))
mv = reflect.ValueOf(args[1]) mv = reflect.ValueOf(args[1])
default: 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 seqv, isNil := indirect(seqv)
// Array or Slice. if isNil {
func checkWhereArray(seqv, kv, mv reflect.Value, path []string, op string) (interface{}, error) { return nil, errors.New("can't iterate over a nil value of type " + reflect.ValueOf(seq).Type().String())
}
var path []string
if kv.Kind() == reflect.String {
path = strings.Split(strings.Trim(kv.String(), "."), ".")
}
switch seqv.Kind() {
case reflect.Array, reflect.Slice:
rv := reflect.MakeSlice(seqv.Type(), 0, 0) rv := reflect.MakeSlice(seqv.Type(), 0, 0)
for i := 0; i < seqv.Len(); i++ { for i := 0; i < seqv.Len(); i++ {
var vvv reflect.Value var vvv reflect.Value
@ -799,7 +811,6 @@ func checkWhereArray(seqv, kv, mv reflect.Value, path []string, op string) (inte
if kv.Kind() == reflect.String { if kv.Kind() == reflect.String {
vvv = rvv vvv = rvv
for _, elemName := range path { for _, elemName := range path {
var err error
vvv, err = evaluateSubElem(vvv, elemName) vvv, err = evaluateSubElem(vvv, elemName)
if err != nil { if err != nil {
return nil, err return nil, err
@ -811,7 +822,6 @@ func checkWhereArray(seqv, kv, mv reflect.Value, path []string, op string) (inte
vvv = vv.MapIndex(kv) vvv = vv.MapIndex(kv)
} }
} }
if ok, err := checkCondition(vvv, mv, op); ok { if ok, err := checkCondition(vvv, mv, op); ok {
rv = reflect.Append(rv, rvv) rv = reflect.Append(rv, rvv)
} else if err != nil { } else if err != nil {
@ -819,75 +829,6 @@ func checkWhereArray(seqv, kv, mv reflect.Value, path []string, op string) (inte
} }
} }
return rv.Interface(), nil 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))
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(), "."), ".")
}
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)
default: default:
return nil, fmt.Errorf("can't iterate over %v", seq) return nil, fmt.Errorf("can't iterate over %v", seq)
} }

View file

@ -18,6 +18,11 @@ import (
"encoding/base64" "encoding/base64"
"errors" "errors"
"fmt" "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" "html/template"
"math/rand" "math/rand"
"path" "path"
@ -27,12 +32,6 @@ import (
"strings" "strings"
"testing" "testing"
"time" "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 { type tstNoStringer struct {
@ -1299,17 +1298,6 @@ func TestWhere(t *testing.T) {
key: "B", op: "op", match: "f", key: "B", op: "op", match: "f",
expect: false, 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{} var results interface{}
var err error var err error