Merge matching resources params maps

This allows setting default params values in the more general resource matchers. I also allows override with more specific values if needed.

```toml
[[resources]]
src = "documents/photo_specs.pdf"
title = "Photo Specifications"
[resources.params]
ref = 90564687
icon = "photo"
[[resources]]
src = "documents/guide.pdf"
title = "Instruction Guide"
[resources.params]
ref = 90564568
[[resources]]
src = "documents/checklist.pdf"
title = "Document Checklist"
[resources.params]
ref = 90564572
[[resources]]
src = "documents/payment.docx"
title = "Proof of Payment"
[[resources]]
src = "documents/*.pdf"
title = "PDF file"
[resources.params]
icon = "pdf"
[[resources]]
src = "documents/*.docx"
title = "Word document"
[resources.params]
icon = "word"

```

In the above `TOML` example, `photo_specs.pdf` will get the `photo` icon, the other pdf files will get the default `pdf` icon.

Note that in the example above, the order matters: It will take the first value for a given params key, title or name that it finds.

Fixes #4315
This commit is contained in:
Bjørn Erik Pedersen 2018-01-23 10:02:44 +01:00
parent 78c863305f
commit 5a0819b9b5
2 changed files with 37 additions and 26 deletions

View file

@ -56,7 +56,7 @@ type Cloner interface {
type metaAssigner interface {
setTitle(title string)
setName(name string)
setParams(params map[string]interface{})
updateParams(params map[string]interface{})
}
// Resource represents a linkable resource, i.e. a content page, image etc.
@ -383,8 +383,18 @@ func (l *genericResource) setName(name string) {
l.name = name
}
func (l *genericResource) setParams(params map[string]interface{}) {
l.params = params
func (l *genericResource) updateParams(params map[string]interface{}) {
if l.params == nil {
l.params = params
return
}
// Sets the params not already set
for k, v := range params {
if _, found := l.params[k]; !found {
l.params[k] = v
}
}
}
// Implement the Cloner interface.
@ -452,18 +462,13 @@ func AssignMetadata(metadata []map[string]interface{}, resources ...Resource) er
}
var (
nameSet, titleSet, paramsSet bool
currentCounter = 0
resourceSrcKey = strings.ToLower(r.Name())
nameSet, titleSet bool
currentCounter = 0
resourceSrcKey = strings.ToLower(r.Name())
)
ma := r.(metaAssigner)
for _, meta := range metadata {
if nameSet && titleSet && paramsSet {
// No need to look further
break
}
src, found := meta["src"]
if !found {
return fmt.Errorf("missing 'src' in metadata for resource")
@ -504,21 +509,12 @@ func AssignMetadata(metadata []map[string]interface{}, resources ...Resource) er
}
}
if !paramsSet {
params, found := meta["params"]
if found {
m := cast.ToStringMap(params)
// Needed for case insensitive fetching of params values
helpers.ToLowerMap(m)
ma.setParams(m)
if currentCounter == 0 {
currentCounter = counters[srcKey] + 1
counters[srcKey] = currentCounter
}
paramsSet = true
}
params, found := meta["params"]
if found {
m := cast.ToStringMap(params)
// Needed for case insensitive fetching of params values
helpers.ToLowerMap(m)
ma.updateParams(m)
}
}
}

View file

@ -234,6 +234,7 @@ func TestAssignMetadata(t *testing.T) {
"src": "*loGo*",
"params": map[string]interface{}{
"Param1": true,
"icon": "logo",
},
},
map[string]interface{}{
@ -241,6 +242,7 @@ func TestAssignMetadata(t *testing.T) {
"src": "*",
"params": map[string]interface{}{
"Param2": true,
"icon": "resource",
},
},
}, func(err error) {
@ -249,9 +251,22 @@ func TestAssignMetadata(t *testing.T) {
assert.Equal("My Resource", foo3.Title())
_, p1 := logo2.Params()["param1"]
_, p2 := foo2.Params()["param2"]
_, p1_2 := foo2.Params()["param1"]
_, p2_2 := logo2.Params()["param2"]
icon1, _ := logo2.Params()["icon"]
icon2, _ := foo2.Params()["icon"]
assert.True(p1)
assert.True(p2)
// Check merge
assert.True(p2_2)
assert.False(p1_2)
assert.Equal("logo", icon1)
assert.Equal("resource", icon2)
}},
{[]map[string]interface{}{
map[string]interface{}{