151 lines
2.8 KiB
Go
151 lines
2.8 KiB
Go
// Copyright 2015 The Tango Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
package flash
|
|
|
|
import (
|
|
"net/url"
|
|
|
|
"gitea.com/lunny/tango"
|
|
"gitea.com/tango/session"
|
|
)
|
|
|
|
var (
|
|
FlashName = "tango_flash"
|
|
FlashSeperator = "TANGOFLASH"
|
|
|
|
_ Flasher = &Flash{}
|
|
)
|
|
|
|
type Data map[string]interface{}
|
|
|
|
// FlashData is a tools to maintain data when using across request.
|
|
type Flash struct {
|
|
readed Data
|
|
flushed Data
|
|
session *session.Session
|
|
*Options
|
|
saved bool
|
|
}
|
|
|
|
func (f *Flash) setFlash(sess *session.Session, readed Data, opt *Options) {
|
|
f.readed = readed
|
|
f.flushed = make(Data)
|
|
f.session = sess
|
|
f.Options = opt
|
|
}
|
|
|
|
func (f *Flash) FlushData() Data {
|
|
return f.flushed
|
|
}
|
|
|
|
func (f *Flash) Merge() {
|
|
for k, v := range f.readed {
|
|
f.flushed[k] = v
|
|
}
|
|
}
|
|
|
|
func (f *Flash) Data() Data {
|
|
return f.readed
|
|
}
|
|
|
|
func (f *Flash) Get(key string) interface{} {
|
|
return f.readed[key]
|
|
}
|
|
|
|
func (f *Flash) Set(key string, value interface{}) {
|
|
f.readed[key] = value
|
|
f.flushed[key] = value
|
|
}
|
|
|
|
func (f *Flash) Add(kvs Data) {
|
|
for k, v := range kvs {
|
|
f.Set(k, v)
|
|
}
|
|
}
|
|
|
|
func (f *Flash) AddValues(values url.Values) {
|
|
for k, vals := range values {
|
|
f.Set(k, vals[0])
|
|
}
|
|
}
|
|
|
|
func (f *Flash) Save() {
|
|
if f.saved {
|
|
return
|
|
}
|
|
|
|
for key := range f.readed {
|
|
f.session.Del(f.Options.FlashName + f.Options.FlashSeperator + key)
|
|
}
|
|
|
|
var keys = make([]string, 0)
|
|
for k, v := range f.flushed {
|
|
f.session.Set(f.Options.FlashName+f.Options.FlashSeperator+k, v)
|
|
keys = append(keys, k)
|
|
}
|
|
f.session.Set(f.Options.FlashName, keys)
|
|
f.saved = true
|
|
}
|
|
|
|
type Flasher interface {
|
|
setFlash(*session.Session, Data, *Options)
|
|
FlushData() Data
|
|
Save()
|
|
}
|
|
|
|
type Options struct {
|
|
FlashName string
|
|
FlashSeperator string
|
|
}
|
|
|
|
func prepareOptions(opts []Options) Options {
|
|
var opt Options
|
|
if len(opts) > 0 {
|
|
opt = opts[0]
|
|
}
|
|
|
|
if len(opt.FlashName) == 0 {
|
|
opt.FlashName = FlashName
|
|
}
|
|
if len(opt.FlashSeperator) == 0 {
|
|
opt.FlashSeperator = FlashSeperator
|
|
}
|
|
return opt
|
|
}
|
|
|
|
// Flashes return a FlashData handler.
|
|
func Flashes(sessions *session.Sessions, opts ...Options) tango.HandlerFunc {
|
|
opt := prepareOptions(opts)
|
|
return func(ctx *tango.Context) {
|
|
var flasher Flasher
|
|
var flashed, ok bool
|
|
|
|
if flasher, ok = ctx.Action().(Flasher); ok {
|
|
// if session.Sessioner is implmentated just get it
|
|
var sess *session.Session
|
|
if sessinoer, ok := ctx.Action().(session.Sessioner); ok {
|
|
sess = sessinoer.GetSession()
|
|
} else {
|
|
sess = sessions.Session(ctx.Req(), ctx.ResponseWriter)
|
|
}
|
|
|
|
fd := make(Data)
|
|
if keys, has := sess.Get(opt.FlashName).([]string); has {
|
|
for _, key := range keys {
|
|
fd[key] = sess.Get(opt.FlashName + opt.FlashSeperator + key)
|
|
}
|
|
}
|
|
flasher.setFlash(sess, fd, &opt)
|
|
flashed = true
|
|
}
|
|
|
|
ctx.Next()
|
|
|
|
if flashed {
|
|
flasher.Save()
|
|
}
|
|
}
|
|
}
|