mirror of
https://github.com/gogf/gf.git
synced 2025-04-05 03:05:05 +08:00
add buildin function add/minus/times/divide for package gview
This commit is contained in:
parent
6be582355c
commit
59397fd8a5
@ -7,8 +7,6 @@
|
||||
// Package gcode provides universal error code definition and common error codes implements.
|
||||
package gcode
|
||||
|
||||
import "fmt"
|
||||
|
||||
// Code is universal error code interface definition.
|
||||
type Code interface {
|
||||
// Code returns the integer number of current error code.
|
||||
@ -22,13 +20,6 @@ type Code interface {
|
||||
Detail() interface{}
|
||||
}
|
||||
|
||||
// localCode is an implementer for interface Code for internal usage only.
|
||||
type localCode struct {
|
||||
code int // Error code, usually an integer.
|
||||
message string // Brief message for this error code.
|
||||
detail interface{} // As type of interface, it is mainly designed as an extension field for error code.
|
||||
}
|
||||
|
||||
// ================================================================================================================
|
||||
// Common error code definition.
|
||||
// There are reserved internal error code by framework: code < 1000.
|
||||
@ -52,7 +43,7 @@ var (
|
||||
CodeSecurityReason = localCode{62, "Security Reason", nil} // Security Reason.
|
||||
CodeServerBusy = localCode{63, "Server Is Busy", nil} // Server is busy, please try again later.
|
||||
CodeUnknown = localCode{64, "Unknown Error", nil} // Unknown error.
|
||||
CodeResourceNotExist = localCode{65, "Resource Not Exist", nil} // Resource does not exist.
|
||||
CodeNotFound = localCode{65, "Not Found", nil} // Resource does not exist.
|
||||
CodeInvalidRequest = localCode{66, "Invalid Request", nil} // Invalid request.
|
||||
CodeBusinessValidationFailed = localCode{300, "Business Validation Failed", nil} // Business validation failed.
|
||||
)
|
||||
@ -66,30 +57,3 @@ func New(code int, message string, detail interface{}) Code {
|
||||
detail: detail,
|
||||
}
|
||||
}
|
||||
|
||||
// Code returns the integer number of current error code.
|
||||
func (c localCode) Code() int {
|
||||
return c.code
|
||||
}
|
||||
|
||||
// Message returns the brief message for current error code.
|
||||
func (c localCode) Message() string {
|
||||
return c.message
|
||||
}
|
||||
|
||||
// Detail returns the detailed information of current error code,
|
||||
// which is mainly designed as an extension field for error code.
|
||||
func (c localCode) Detail() interface{} {
|
||||
return c.detail
|
||||
}
|
||||
|
||||
// String returns current error code as a string.
|
||||
func (c localCode) String() string {
|
||||
if c.detail != nil {
|
||||
return fmt.Sprintf(`%d:%s %v`, c.code, c.message, c.detail)
|
||||
}
|
||||
if c.message != "" {
|
||||
return fmt.Sprintf(`%d:%s`, c.code, c.message)
|
||||
}
|
||||
return fmt.Sprintf(`%d`, c.code)
|
||||
}
|
||||
|
43
errors/gcode/gcode_local.go
Normal file
43
errors/gcode/gcode_local.go
Normal file
@ -0,0 +1,43 @@
|
||||
// Copyright GoFrame gf Author(https://goframe.org). All Rights Reserved.
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the MIT License.
|
||||
// If a copy of the MIT was not distributed with this file,
|
||||
// You can obtain one at https://github.com/gogf/gf.
|
||||
|
||||
package gcode
|
||||
|
||||
import "fmt"
|
||||
|
||||
// localCode is an implementer for interface Code for internal usage only.
|
||||
type localCode struct {
|
||||
code int // Error code, usually an integer.
|
||||
message string // Brief message for this error code.
|
||||
detail interface{} // As type of interface, it is mainly designed as an extension field for error code.
|
||||
}
|
||||
|
||||
// Code returns the integer number of current error code.
|
||||
func (c localCode) Code() int {
|
||||
return c.code
|
||||
}
|
||||
|
||||
// Message returns the brief message for current error code.
|
||||
func (c localCode) Message() string {
|
||||
return c.message
|
||||
}
|
||||
|
||||
// Detail returns the detailed information of current error code,
|
||||
// which is mainly designed as an extension field for error code.
|
||||
func (c localCode) Detail() interface{} {
|
||||
return c.detail
|
||||
}
|
||||
|
||||
// String returns current error code as a string.
|
||||
func (c localCode) String() string {
|
||||
if c.detail != nil {
|
||||
return fmt.Sprintf(`%d:%s %v`, c.code, c.message, c.detail)
|
||||
}
|
||||
if c.message != "" {
|
||||
return fmt.Sprintf(`%d:%s`, c.code, c.message)
|
||||
}
|
||||
return fmt.Sprintf(`%d`, c.code)
|
||||
}
|
23
errors/gcode/gcode_test.go
Normal file
23
errors/gcode/gcode_test.go
Normal file
@ -0,0 +1,23 @@
|
||||
// Copyright GoFrame Author(https://goframe.org). All Rights Reserved.
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the MIT License.
|
||||
// If a copy of the MIT was not distributed with this file,
|
||||
// You can obtain one at https://github.com/gogf/gf.
|
||||
|
||||
package gcode_test
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/errors/gcode"
|
||||
"testing"
|
||||
|
||||
"github.com/gogf/gf/test/gtest"
|
||||
)
|
||||
|
||||
func Test_Nil(t *testing.T) {
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
c := gcode.New(1, "custom error", "detailed description")
|
||||
t.Assert(c.Code(), 1)
|
||||
t.Assert(c.Message(), "custom error")
|
||||
t.Assert(c.Detail(), "detailed description")
|
||||
})
|
||||
}
|
@ -61,7 +61,7 @@ func ParseContent(ctx context.Context, content string, params ...Params) (string
|
||||
}
|
||||
|
||||
// New returns a new view object.
|
||||
// The parameter <path> specifies the template directory path to load template files.
|
||||
// The parameter `path` specifies the template directory path to load template files.
|
||||
func New(path ...string) *View {
|
||||
view := &View{
|
||||
paths: garray.NewStrArray(),
|
||||
@ -143,6 +143,10 @@ func New(path ...string) *View {
|
||||
"map": view.buildInFuncMap,
|
||||
"maps": view.buildInFuncMaps,
|
||||
"json": view.buildInFuncJson,
|
||||
"plus": view.buildInFuncPlus,
|
||||
"minus": view.buildInFuncMinus,
|
||||
"times": view.buildInFuncTimes,
|
||||
"divide": view.buildInFuncDivide,
|
||||
})
|
||||
|
||||
return view
|
||||
|
@ -219,8 +219,53 @@ func (view *View) buildInFuncNl2Br(str interface{}) string {
|
||||
}
|
||||
|
||||
// buildInFuncJson implements build-in template function: json ,
|
||||
// which encodes and returns <value> as JSON string.
|
||||
// which encodes and returns `value` as JSON string.
|
||||
func (view *View) buildInFuncJson(value interface{}) (string, error) {
|
||||
b, err := json.Marshal(value)
|
||||
return gconv.UnsafeBytesToStr(b), err
|
||||
}
|
||||
|
||||
// buildInFuncPlus implements build-in template function: plus ,
|
||||
// which returns the result that pluses all `deltas` to `value`.
|
||||
func (view *View) buildInFuncPlus(value interface{}, deltas ...interface{}) string {
|
||||
result := gconv.Float64(value)
|
||||
for _, v := range deltas {
|
||||
result += gconv.Float64(v)
|
||||
}
|
||||
return gconv.String(result)
|
||||
}
|
||||
|
||||
// buildInFuncMinus implements build-in template function: minus ,
|
||||
// which returns the result that subtracts all `deltas` from `value`.
|
||||
func (view *View) buildInFuncMinus(value interface{}, deltas ...interface{}) string {
|
||||
result := gconv.Float64(value)
|
||||
for _, v := range deltas {
|
||||
result -= gconv.Float64(v)
|
||||
}
|
||||
return gconv.String(result)
|
||||
}
|
||||
|
||||
// buildInFuncTimes implements build-in template function: times ,
|
||||
// which returns the result that multiplies `value` by all of `values`.
|
||||
func (view *View) buildInFuncTimes(value interface{}, values ...interface{}) string {
|
||||
result := gconv.Float64(value)
|
||||
for _, v := range values {
|
||||
result *= gconv.Float64(v)
|
||||
}
|
||||
return gconv.String(result)
|
||||
}
|
||||
|
||||
// buildInFuncDivide implements build-in template function: divide ,
|
||||
// which returns the result that divides `value` by all of `values`.
|
||||
func (view *View) buildInFuncDivide(value interface{}, values ...interface{}) string {
|
||||
result := gconv.Float64(value)
|
||||
for _, v := range values {
|
||||
value2Float64 := gconv.Float64(v)
|
||||
if value2Float64 == 0 {
|
||||
// Invalid `value2`.
|
||||
return "0"
|
||||
}
|
||||
result /= value2Float64
|
||||
}
|
||||
return gconv.String(result)
|
||||
}
|
||||
|
@ -95,7 +95,7 @@ func (view *View) SetConfigWithMap(m map[string]interface{}) error {
|
||||
}
|
||||
|
||||
// SetPath sets the template directory path for template file search.
|
||||
// The parameter <path> can be absolute or relative path, but absolute path is suggested.
|
||||
// The parameter `path` can be absolute or relative path, but absolute path is suggested.
|
||||
func (view *View) SetPath(path string) error {
|
||||
var (
|
||||
isDir = false
|
||||
@ -239,9 +239,9 @@ func (view *View) SetAutoEncode(enable bool) {
|
||||
view.config.AutoEncode = enable
|
||||
}
|
||||
|
||||
// BindFunc registers customized global template function named <name>
|
||||
// with given function <function> to current view object.
|
||||
// The <name> is the function name which can be called in template content.
|
||||
// BindFunc registers customized global template function named `name`
|
||||
// with given function `function` to current view object.
|
||||
// The `name` is the function name which can be called in template content.
|
||||
func (view *View) BindFunc(name string, function interface{}) {
|
||||
view.funcMap[name] = function
|
||||
// Clear global template object cache.
|
||||
|
@ -19,7 +19,7 @@ var (
|
||||
)
|
||||
|
||||
// Instance returns an instance of View with default settings.
|
||||
// The parameter <name> is the name for the instance.
|
||||
// The parameter `name` is the name for the instance.
|
||||
func Instance(name ...string) *View {
|
||||
key := DefaultName
|
||||
if len(name) > 0 && name[0] != "" {
|
||||
|
@ -53,7 +53,7 @@ var (
|
||||
resourceTryFolders = []string{"template/", "template", "/template", "/template/"}
|
||||
)
|
||||
|
||||
// Parse parses given template file <file> with given template variables <params>
|
||||
// Parse parses given template file `file` with given template variables `params`
|
||||
// and returns the parsed template content.
|
||||
func (view *View) Parse(ctx context.Context, file string, params ...Params) (result string, err error) {
|
||||
var tpl interface{}
|
||||
@ -65,7 +65,7 @@ func (view *View) Parse(ctx context.Context, file string, params ...Params) (res
|
||||
content string
|
||||
resource *gres.File
|
||||
)
|
||||
// Searching the absolute file path for <file>.
|
||||
// Searching the absolute file path for `file`.
|
||||
path, folder, resource, err = view.searchFile(file)
|
||||
if err != nil {
|
||||
return nil
|
||||
@ -100,7 +100,7 @@ func (view *View) Parse(ctx context.Context, file string, params ...Params) (res
|
||||
if item.content == "" {
|
||||
return "", nil
|
||||
}
|
||||
// Get the template object instance for <folder>.
|
||||
// Get the template object instance for `folder`.
|
||||
tpl, err = view.getTemplate(item.path, item.folder, fmt.Sprintf(`*%s`, gfile.Ext(item.path)))
|
||||
if err != nil {
|
||||
return "", err
|
||||
@ -120,7 +120,7 @@ func (view *View) Parse(ctx context.Context, file string, params ...Params) (res
|
||||
return "", err
|
||||
}
|
||||
// Note that the template variable assignment cannot change the value
|
||||
// of the existing <params> or view.data because both variables are pointers.
|
||||
// of the existing `params` or view.data because both variables are pointers.
|
||||
// It needs to merge the values of the two maps into a new map.
|
||||
variables := gutil.MapMergeCopy(params...)
|
||||
if len(view.data) > 0 {
|
||||
@ -154,7 +154,7 @@ func (view *View) ParseDefault(ctx context.Context, params ...Params) (result st
|
||||
return view.Parse(ctx, view.config.DefaultFile, params...)
|
||||
}
|
||||
|
||||
// ParseContent parses given template content <content> with template variables <params>
|
||||
// ParseContent parses given template content `content` with template variables `params`
|
||||
// and returns the parsed content in []byte.
|
||||
func (view *View) ParseContent(ctx context.Context, content string, params ...Params) (string, error) {
|
||||
// It's not necessary continuing parsing if template content is empty.
|
||||
@ -188,7 +188,7 @@ func (view *View) ParseContent(ctx context.Context, content string, params ...Pa
|
||||
return "", err
|
||||
}
|
||||
// Note that the template variable assignment cannot change the value
|
||||
// of the existing <params> or view.data because both variables are pointers.
|
||||
// of the existing `params` or view.data because both variables are pointers.
|
||||
// It needs to merge the values of the two maps into a new map.
|
||||
variables := gutil.MapMergeCopy(params...)
|
||||
if len(view.data) > 0 {
|
||||
@ -216,10 +216,10 @@ func (view *View) ParseContent(ctx context.Context, content string, params ...Pa
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// getTemplate returns the template object associated with given template file <path>.
|
||||
// getTemplate returns the template object associated with given template file `path`.
|
||||
// It uses template cache to enhance performance, that is, it will return the same template object
|
||||
// with the same given <path>. It will also automatically refresh the template cache
|
||||
// if the template files under <path> changes (recursively).
|
||||
// with the same given `path`. It will also automatically refresh the template cache
|
||||
// if the template files under `path` changes (recursively).
|
||||
func (view *View) getTemplate(filePath, folderPath, pattern string) (tpl interface{}, err error) {
|
||||
// Key for template cache.
|
||||
key := fmt.Sprintf("%s_%v", filePath, view.config.Delimiters)
|
||||
@ -304,9 +304,9 @@ func (view *View) formatTemplateObjectCreatingError(filePath, tplName string, er
|
||||
return nil
|
||||
}
|
||||
|
||||
// searchFile returns the found absolute path for <file> and its template folder path.
|
||||
// Note that, the returned <folder> is the template folder path, but not the folder of
|
||||
// the returned template file <path>.
|
||||
// searchFile returns the found absolute path for `file` and its template folder path.
|
||||
// Note that, the returned `folder` is the template folder path, but not the folder of
|
||||
// the returned template file `path`.
|
||||
func (view *View) searchFile(file string) (path string, folder string, resource *gres.File, err error) {
|
||||
// Firstly checking the resource manager.
|
||||
if !gres.IsEmpty() {
|
||||
|
@ -9,6 +9,7 @@ package gview_test
|
||||
import (
|
||||
"context"
|
||||
"github.com/gogf/gf/encoding/ghtml"
|
||||
"github.com/gogf/gf/os/gctx"
|
||||
"github.com/gogf/gf/os/gtime"
|
||||
"github.com/gogf/gf/util/gconv"
|
||||
"io/ioutil"
|
||||
@ -426,3 +427,39 @@ func Test_BuildInFuncJson(t *testing.T) {
|
||||
t.Assert(r, `{"name":"john"}`)
|
||||
})
|
||||
}
|
||||
|
||||
func Test_BuildInFuncPlus(t *testing.T) {
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
v := gview.New()
|
||||
r, err := v.ParseContent(gctx.New(), "{{plus 1 2 3}}")
|
||||
t.Assert(err, nil)
|
||||
t.Assert(r, `6`)
|
||||
})
|
||||
}
|
||||
|
||||
func Test_BuildInFuncMinus(t *testing.T) {
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
v := gview.New()
|
||||
r, err := v.ParseContent(gctx.New(), "{{minus 1 2 3}}")
|
||||
t.Assert(err, nil)
|
||||
t.Assert(r, `-4`)
|
||||
})
|
||||
}
|
||||
|
||||
func Test_BuildInFuncTimes(t *testing.T) {
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
v := gview.New()
|
||||
r, err := v.ParseContent(gctx.New(), "{{times 1 2 3 4}}")
|
||||
t.Assert(err, nil)
|
||||
t.Assert(r, `24`)
|
||||
})
|
||||
}
|
||||
|
||||
func Test_BuildInFuncDivide(t *testing.T) {
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
v := gview.New()
|
||||
r, err := v.ParseContent(gctx.New(), "{{divide 8 2 2}}")
|
||||
t.Assert(err, nil)
|
||||
t.Assert(r, `2`)
|
||||
})
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user