mirror of
https://github.com/gohugoio/hugo.git
synced 2024-12-01 18:22:58 -05:00
Add nil comparison to where tpl function
`where` template function's internal condition check function always returns `false` when a target value doesn't exist or it's nil value but this behavior makes it difficult to filter values which doesn't have a particular parameter. To solve it, this adds nil value comparison to the function. `where Values ".Param.key" nil` like clause can be used for the case above. Only "=", "==", "eq", "!=", "<>", "ne" operators are allowed to be used with `nil`. If an other operator is passed with `nil`, the condition check function returns `false` like before. Fix #1232
This commit is contained in:
parent
033a13e10e
commit
dd732e84f4
2 changed files with 40 additions and 9 deletions
|
@ -536,17 +536,21 @@ func evaluateSubElem(obj reflect.Value, elemName string) (reflect.Value, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
func checkCondition(v, mv reflect.Value, op string) (bool, error) {
|
func checkCondition(v, mv reflect.Value, op string) (bool, error) {
|
||||||
if !v.IsValid() || !mv.IsValid() {
|
v, vIsNil := indirect(v)
|
||||||
return false, nil
|
if !v.IsValid() {
|
||||||
|
vIsNil = true
|
||||||
}
|
}
|
||||||
|
mv, mvIsNil := indirect(mv)
|
||||||
var isNil bool
|
if !mv.IsValid() {
|
||||||
v, isNil = indirect(v)
|
mvIsNil = true
|
||||||
if isNil {
|
}
|
||||||
return false, nil
|
if vIsNil || mvIsNil {
|
||||||
|
switch op {
|
||||||
|
case "", "=", "==", "eq":
|
||||||
|
return vIsNil == mvIsNil, nil
|
||||||
|
case "!=", "<>", "ne":
|
||||||
|
return vIsNil != mvIsNil, nil
|
||||||
}
|
}
|
||||||
mv, isNil = indirect(mv)
|
|
||||||
if isNil {
|
|
||||||
return false, nil
|
return false, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -673,6 +673,7 @@ func TestCheckCondition(t *testing.T) {
|
||||||
"",
|
"",
|
||||||
expect{true, false},
|
expect{true, false},
|
||||||
},
|
},
|
||||||
|
{reflect.ValueOf(nil), reflect.ValueOf(nil), "", expect{true, false}},
|
||||||
{reflect.ValueOf(123), reflect.ValueOf(456), "!=", expect{true, false}},
|
{reflect.ValueOf(123), reflect.ValueOf(456), "!=", expect{true, false}},
|
||||||
{reflect.ValueOf("foo"), reflect.ValueOf("bar"), "!=", expect{true, false}},
|
{reflect.ValueOf("foo"), reflect.ValueOf("bar"), "!=", expect{true, false}},
|
||||||
{
|
{
|
||||||
|
@ -681,6 +682,7 @@ func TestCheckCondition(t *testing.T) {
|
||||||
"!=",
|
"!=",
|
||||||
expect{true, false},
|
expect{true, false},
|
||||||
},
|
},
|
||||||
|
{reflect.ValueOf(123), reflect.ValueOf(nil), "!=", expect{true, false}},
|
||||||
{reflect.ValueOf(456), reflect.ValueOf(123), ">=", expect{true, false}},
|
{reflect.ValueOf(456), reflect.ValueOf(123), ">=", expect{true, false}},
|
||||||
{reflect.ValueOf("foo"), reflect.ValueOf("bar"), ">=", expect{true, false}},
|
{reflect.ValueOf("foo"), reflect.ValueOf("bar"), ">=", expect{true, false}},
|
||||||
{
|
{
|
||||||
|
@ -943,6 +945,31 @@ func TestWhere(t *testing.T) {
|
||||||
{A: "a", B: "b"}, {A: "e", B: "f"},
|
{A: "a", B: "b"}, {A: "e", B: "f"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
sequence: []map[string]int{
|
||||||
|
{"a": 1, "b": 2}, {"a": 3}, {"a": 5, "b": 6},
|
||||||
|
},
|
||||||
|
key: "b", op: "", match: nil,
|
||||||
|
expect: []map[string]int{
|
||||||
|
{"a": 3},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
sequence: []map[string]int{
|
||||||
|
{"a": 1, "b": 2}, {"a": 3}, {"a": 5, "b": 6},
|
||||||
|
},
|
||||||
|
key: "b", op: "!=", match: nil,
|
||||||
|
expect: []map[string]int{
|
||||||
|
{"a": 1, "b": 2}, {"a": 5, "b": 6},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
sequence: []map[string]int{
|
||||||
|
{"a": 1, "b": 2}, {"a": 3}, {"a": 5, "b": 6},
|
||||||
|
},
|
||||||
|
key: "b", op: ">", match: nil,
|
||||||
|
expect: []map[string]int{},
|
||||||
|
},
|
||||||
{sequence: (*[]TstX)(nil), key: "A", match: "a", expect: false},
|
{sequence: (*[]TstX)(nil), key: "A", match: "a", expect: false},
|
||||||
{sequence: TstX{A: "a", B: "b"}, key: "A", match: "a", expect: false},
|
{sequence: TstX{A: "a", B: "b"}, key: "A", match: "a", expect: false},
|
||||||
{sequence: []map[string]*TstX{{"foo": nil}}, key: "foo.B", match: "d", expect: false},
|
{sequence: []map[string]*TstX{{"foo": nil}}, key: "foo.B", match: "d", expect: false},
|
||||||
|
|
Loading…
Reference in a new issue