Factorize go
This commit is contained in:
parent
606afb279d
commit
e9257fe6a7
@ -219,12 +219,9 @@ type ReqParams struct {
|
||||
AllWords bool
|
||||
}
|
||||
|
||||
func (app *Bouquins) render(res http.ResponseWriter, tpl string, model interface{}) error {
|
||||
return app.Template.ExecuteTemplate(res, tpl, model)
|
||||
}
|
||||
// add functions to templates
|
||||
func TemplatesFunc() *template.Template {
|
||||
tpl := template.New("")
|
||||
tpl.Funcs(template.FuncMap{
|
||||
return template.New("").Funcs(template.FuncMap{
|
||||
"humanSize": func(sz int64) string {
|
||||
return datasize.ByteSize(sz).HumanReadable()
|
||||
},
|
||||
@ -236,17 +233,26 @@ func TemplatesFunc() *template.Template {
|
||||
return "/calibre/" + url.PathEscape(book.Path) + "/" + url.PathEscape(data.Name) + "." + strings.ToLower(data.Format)
|
||||
},
|
||||
})
|
||||
return tpl
|
||||
}
|
||||
|
||||
// output page with template
|
||||
func (app *Bouquins) render(res http.ResponseWriter, tpl string, model interface{}) error {
|
||||
return app.Template.ExecuteTemplate(res, tpl, model)
|
||||
}
|
||||
|
||||
// output as JSON
|
||||
func writeJson(res http.ResponseWriter, model interface{}) error {
|
||||
res.Header().Set("Content-Type", "application/json")
|
||||
enc := json.NewEncoder(res)
|
||||
return enc.Encode(model)
|
||||
}
|
||||
|
||||
// test if JSON requested
|
||||
func isJson(req *http.Request) bool {
|
||||
return req.Header.Get("Accept") == "application/json"
|
||||
}
|
||||
|
||||
// get integer parameter
|
||||
func paramInt(name string, req *http.Request) int {
|
||||
val := req.URL.Query().Get(name)
|
||||
if val == "" {
|
||||
@ -259,6 +265,8 @@ func paramInt(name string, req *http.Request) int {
|
||||
}
|
||||
return valInt
|
||||
}
|
||||
|
||||
// get order parameter
|
||||
func paramOrder(req *http.Request) string {
|
||||
val := req.URL.Query().Get(PARAM_ORDER)
|
||||
if val == "desc" || val == "asc" {
|
||||
@ -267,6 +275,7 @@ func paramOrder(req *http.Request) string {
|
||||
return ""
|
||||
}
|
||||
|
||||
// get common request parameters
|
||||
func params(req *http.Request) *ReqParams {
|
||||
page, perpage := paramInt(PARAM_PAGE, req), paramInt(PARAM_PERPAGE, req)
|
||||
limit := perpage
|
||||
@ -283,27 +292,22 @@ func params(req *http.Request) *ReqParams {
|
||||
return &ReqParams{limit, offset, sort, order, terms, false}
|
||||
}
|
||||
|
||||
// ROUTES //
|
||||
|
||||
func (app *Bouquins) IndexPage(res http.ResponseWriter, req *http.Request) {
|
||||
count, err := app.BookCount()
|
||||
if err != nil {
|
||||
log.Print(err)
|
||||
// single element or list elements page
|
||||
func listOrId(res http.ResponseWriter, req *http.Request, url string,
|
||||
listFunc func(res http.ResponseWriter, req *http.Request) error,
|
||||
idFunc func(idParam string, res http.ResponseWriter, req *http.Request) error) error {
|
||||
if !strings.HasPrefix(req.URL.Path, url) {
|
||||
return errors.New("Invalid URL") // FIXME 404
|
||||
}
|
||||
model := NewIndexModel("", count)
|
||||
if isJson(req) {
|
||||
err := writeJson(res, model)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
http.Error(res, err.Error(), 500)
|
||||
}
|
||||
} else {
|
||||
err = app.render(res, TPL_INDEX, model)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
idParam := req.URL.Path[len(url):]
|
||||
if len(idParam) == 0 {
|
||||
return listFunc(res, req)
|
||||
}
|
||||
return idFunc(idParam, res, req)
|
||||
}
|
||||
|
||||
// LIST ELEMENTS PAGES //
|
||||
|
||||
func (app *Bouquins) BooksListPage(res http.ResponseWriter, req *http.Request) error {
|
||||
if isJson(req) {
|
||||
books, count, more, err := app.BooksAdv(params(req))
|
||||
@ -314,35 +318,6 @@ func (app *Bouquins) BooksListPage(res http.ResponseWriter, req *http.Request) e
|
||||
}
|
||||
return errors.New("Invalid mime")
|
||||
}
|
||||
func (app *Bouquins) BookPage(idParam string, res http.ResponseWriter, req *http.Request) error {
|
||||
id, err := strconv.Atoi(idParam)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
book, err := app.BookFull(int64(id))
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
return app.render(res, TPL_BOOKS, &BookModel{*NewBouquinsModel(book.Title, "book"), book})
|
||||
}
|
||||
func (app *Bouquins) BooksPage(res http.ResponseWriter, req *http.Request) {
|
||||
var err error
|
||||
var idParam = ""
|
||||
if strings.HasPrefix(req.URL.Path, URL_BOOKS) {
|
||||
idParam = req.URL.Path[len(URL_BOOKS):]
|
||||
} else {
|
||||
err = errors.New("Invalid URL") // FIXME 404
|
||||
}
|
||||
if len(idParam) == 0 {
|
||||
err = app.BooksListPage(res, req)
|
||||
} else {
|
||||
err = app.BookPage(idParam, res, req)
|
||||
}
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
http.Error(res, err.Error(), 500)
|
||||
}
|
||||
}
|
||||
func (app *Bouquins) AuthorsListPage(res http.ResponseWriter, req *http.Request) error {
|
||||
if isJson(req) {
|
||||
authors, count, more, err := app.AuthorsAdv(params(req))
|
||||
@ -353,6 +328,30 @@ func (app *Bouquins) AuthorsListPage(res http.ResponseWriter, req *http.Request)
|
||||
}
|
||||
return errors.New("Invalid mime")
|
||||
}
|
||||
func (app *Bouquins) SeriesListPage(res http.ResponseWriter, req *http.Request) error {
|
||||
if isJson(req) {
|
||||
series, count, more, err := app.SeriesAdv(params(req))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return writeJson(res, NewSeriesResultsModel(series, more, count))
|
||||
}
|
||||
return errors.New("Invalid mime")
|
||||
}
|
||||
|
||||
// SINGLE ELEMENT PAGES //
|
||||
|
||||
func (app *Bouquins) BookPage(idParam string, res http.ResponseWriter, req *http.Request) error {
|
||||
id, err := strconv.Atoi(idParam)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
book, err := app.BookFull(int64(id))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return app.render(res, TPL_BOOKS, &BookModel{*NewBouquinsModel(book.Title, "book"), book})
|
||||
}
|
||||
func (app *Bouquins) AuthorPage(idParam string, res http.ResponseWriter, req *http.Request) error {
|
||||
id, err := strconv.Atoi(idParam)
|
||||
if err != nil {
|
||||
@ -364,34 +363,6 @@ func (app *Bouquins) AuthorPage(idParam string, res http.ResponseWriter, req *ht
|
||||
}
|
||||
return app.render(res, TPL_AUTHORS, &AuthorModel{*NewBouquinsModel(author.Name, "author"), author})
|
||||
}
|
||||
func (app *Bouquins) AuthorsPage(res http.ResponseWriter, req *http.Request) {
|
||||
var err error
|
||||
var idParam = ""
|
||||
if strings.HasPrefix(req.URL.Path, URL_AUTHORS) {
|
||||
idParam = req.URL.Path[len(URL_AUTHORS):]
|
||||
} else {
|
||||
err = errors.New("Invalid URL") // FIXME 404
|
||||
}
|
||||
if len(idParam) == 0 {
|
||||
err = app.AuthorsListPage(res, req)
|
||||
} else {
|
||||
err = app.AuthorPage(idParam, res, req)
|
||||
}
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
http.Error(res, err.Error(), 500)
|
||||
}
|
||||
}
|
||||
func (app *Bouquins) SeriesListPage(res http.ResponseWriter, req *http.Request) error {
|
||||
if isJson(req) {
|
||||
series, count, more, err := app.SeriesAdv(params(req))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return writeJson(res, NewSeriesResultsModel(series, more, count))
|
||||
}
|
||||
return errors.New("Invalid mime")
|
||||
}
|
||||
func (app *Bouquins) SeriePage(idParam string, res http.ResponseWriter, req *http.Request) error {
|
||||
id, err := strconv.Atoi(idParam)
|
||||
if err != nil {
|
||||
@ -403,34 +374,32 @@ func (app *Bouquins) SeriePage(idParam string, res http.ResponseWriter, req *htt
|
||||
}
|
||||
return app.render(res, TPL_SERIES, &SeriesModel{*NewBouquinsModel(series.Name, "series"), series})
|
||||
}
|
||||
func (app *Bouquins) SeriesPage(res http.ResponseWriter, req *http.Request) {
|
||||
var err error
|
||||
var idParam = ""
|
||||
if strings.HasPrefix(req.URL.Path, URL_SERIES) {
|
||||
idParam = req.URL.Path[len(URL_SERIES):]
|
||||
} else {
|
||||
err = errors.New("Invalid URL") // FIXME 404
|
||||
}
|
||||
if len(idParam) == 0 {
|
||||
err = app.SeriesListPage(res, req)
|
||||
} else {
|
||||
err = app.SeriePage(idParam, res, req)
|
||||
}
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
http.Error(res, err.Error(), 500)
|
||||
}
|
||||
|
||||
// ROUTES //
|
||||
|
||||
func (app *Bouquins) BooksPage(res http.ResponseWriter, req *http.Request) error {
|
||||
return listOrId(res, req, URL_BOOKS, app.BooksListPage, app.BookPage)
|
||||
}
|
||||
func (app *Bouquins) SearchPage(res http.ResponseWriter, req *http.Request) {
|
||||
model := NewSearchModel()
|
||||
err := app.render(res, TPL_SEARCH, model)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
func (app *Bouquins) AuthorsPage(res http.ResponseWriter, req *http.Request) error {
|
||||
return listOrId(res, req, URL_AUTHORS, app.AuthorsListPage, app.AuthorPage)
|
||||
}
|
||||
func (app *Bouquins) AboutPage(res http.ResponseWriter, req *http.Request) {
|
||||
err := app.render(res, TPL_ABOUT, NewBouquinsModel("A propos", "about"))
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
func (app *Bouquins) SeriesPage(res http.ResponseWriter, req *http.Request) error {
|
||||
return listOrId(res, req, URL_SERIES, app.SeriesListPage, app.SeriePage)
|
||||
}
|
||||
func (app *Bouquins) SearchPage(res http.ResponseWriter, req *http.Request) error {
|
||||
return app.render(res, TPL_SEARCH, NewSearchModel())
|
||||
}
|
||||
func (app *Bouquins) AboutPage(res http.ResponseWriter, req *http.Request) error {
|
||||
return app.render(res, TPL_ABOUT, NewBouquinsModel("A propos", "about"))
|
||||
}
|
||||
func (app *Bouquins) IndexPage(res http.ResponseWriter, req *http.Request) error {
|
||||
count, err := app.BookCount()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
model := NewIndexModel("", count)
|
||||
if isJson(req) {
|
||||
return writeJson(res, model)
|
||||
}
|
||||
return app.render(res, TPL_INDEX, model)
|
||||
}
|
||||
|
@ -172,6 +172,33 @@ type Query struct {
|
||||
Desc bool
|
||||
}
|
||||
|
||||
func (app *Bouquins) searchHelper(all bool, terms []string, stub, termExpr, orderExpr string) (*sql.Rows, error) {
|
||||
query := stub
|
||||
queryTerms := make([]interface{}, 0, len(terms))
|
||||
for i, term := range terms {
|
||||
queryTerms = append(queryTerms, "%"+term+"%")
|
||||
query += termExpr
|
||||
if i < len(terms)-1 && all {
|
||||
query += STMT_BOOL_AND
|
||||
}
|
||||
if i < len(terms)-1 && !all {
|
||||
query += STMT_BOOL_OR
|
||||
}
|
||||
}
|
||||
query += orderExpr
|
||||
log.Println("Search:", query)
|
||||
|
||||
stmt, err := app.DB.Prepare(query)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
rows, err := stmt.Query(queryTerms...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return rows, nil
|
||||
}
|
||||
|
||||
// PREPARED STATEMENTS //
|
||||
func (app *Bouquins) PrepareAll() error {
|
||||
errcount := 0
|
||||
@ -217,5 +244,5 @@ func (app *Bouquins) psSort(sortNameField string, qt QueryType, sort, order stri
|
||||
|
||||
// prepared statement without sort
|
||||
func (app *Bouquins) ps(qt QueryType) (*sql.Stmt, error) {
|
||||
return app.psSortBooks(qt, "", "")
|
||||
return app.psSort("any", qt, "", "")
|
||||
}
|
||||
|
@ -2,37 +2,17 @@ package bouquins
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"log"
|
||||
)
|
||||
|
||||
// SUB QUERIES //
|
||||
|
||||
func (app *Bouquins) searchAuthors(limit int, terms []string, all bool) ([]*AuthorAdv, int, error) {
|
||||
rows, err := app.searchHelper(all, terms, STMT_AUTHORS_SEARCH, STMT_SEARCH_TERM_AUTHOR, STMT_SEARCH_ORDER_AUTHORS)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
authors := make([]*AuthorAdv, 0, limit)
|
||||
count := 0
|
||||
query := STMT_AUTHORS_SEARCH
|
||||
queryTerms := make([]interface{}, 0, len(terms))
|
||||
for i, term := range terms {
|
||||
queryTerms = append(queryTerms, "%"+term+"%")
|
||||
query += STMT_SEARCH_TERM_AUTHOR
|
||||
if i < len(terms)-1 && all {
|
||||
query += STMT_BOOL_AND
|
||||
}
|
||||
if i < len(terms)-1 && !all {
|
||||
query += STMT_BOOL_OR
|
||||
}
|
||||
}
|
||||
query += STMT_SEARCH_ORDER_AUTHORS
|
||||
log.Println("Search:", query)
|
||||
|
||||
stmt, err := app.DB.Prepare(query)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
rows, err := stmt.Query(queryTerms...)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
defer rows.Close()
|
||||
for rows.Next() {
|
||||
if len(authors) <= limit {
|
||||
|
@ -2,7 +2,6 @@ package bouquins
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"log"
|
||||
)
|
||||
|
||||
// MERGE SUB QUERIES //
|
||||
@ -16,34 +15,13 @@ func assignAuthorsTagsBooks(books []*BookAdv, authors map[int64][]*Author, tags
|
||||
// SUB QUERIES //
|
||||
|
||||
func (app *Bouquins) searchBooks(limit int, terms []string, all bool) ([]*BookAdv, int, error) {
|
||||
books := make([]*BookAdv, 0, limit)
|
||||
// FIXME factorize searchAuthors,searchSeries
|
||||
count := 0
|
||||
query := STMT_BOOKS0 + STMT_WHERE
|
||||
queryTerms := make([]interface{}, 0, len(terms))
|
||||
for i, term := range terms {
|
||||
queryTerms = append(queryTerms, "%"+term+"%")
|
||||
query += STMT_SEARCH_TERM_BOOKS
|
||||
if i < len(terms)-1 && all {
|
||||
query += STMT_BOOL_AND
|
||||
}
|
||||
if i < len(terms)-1 && !all {
|
||||
query += STMT_BOOL_OR
|
||||
}
|
||||
}
|
||||
query += STMT_SEARCH_ORDER_BOOKS
|
||||
log.Println("Search:", query)
|
||||
|
||||
stmt, err := app.DB.Prepare(query)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
rows, err := stmt.Query(queryTerms...)
|
||||
rows, err := app.searchHelper(all, terms, STMT_BOOKS0+STMT_WHERE, STMT_SEARCH_TERM_BOOKS, STMT_SEARCH_ORDER_BOOKS)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
defer rows.Close()
|
||||
// FIXME factorize queryBooks
|
||||
books := make([]*BookAdv, 0, limit)
|
||||
count := 0
|
||||
for rows.Next() {
|
||||
if len(books) <= limit {
|
||||
book := new(BookAdv)
|
||||
|
@ -1,7 +1,5 @@
|
||||
package bouquins
|
||||
|
||||
import "log"
|
||||
|
||||
// MERGE SUB QUERIES //
|
||||
|
||||
func assignAuthorsSeries(series []*SeriesAdv, authors map[int64][]*Author) {
|
||||
@ -13,32 +11,13 @@ func assignAuthorsSeries(series []*SeriesAdv, authors map[int64][]*Author) {
|
||||
// SUB QUERIES //
|
||||
|
||||
func (app *Bouquins) searchSeries(limit int, terms []string, all bool) ([]*SeriesAdv, int, error) {
|
||||
series := make([]*SeriesAdv, 0, limit)
|
||||
count := 0
|
||||
query := STMT_SERIES_SEARCH
|
||||
queryTerms := make([]interface{}, 0, len(terms))
|
||||
for i, term := range terms {
|
||||
queryTerms = append(queryTerms, "%"+term+"%")
|
||||
query += STMT_SEARCH_TERM_SERIES
|
||||
if i < len(terms)-1 && all {
|
||||
query += STMT_BOOL_AND
|
||||
}
|
||||
if i < len(terms)-1 && !all {
|
||||
query += STMT_BOOL_OR
|
||||
}
|
||||
}
|
||||
query += STMT_SEARCH_ORDER_SERIES
|
||||
log.Println("Search:", query)
|
||||
|
||||
stmt, err := app.DB.Prepare(query)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
rows, err := stmt.Query(queryTerms...)
|
||||
rows, err := app.searchHelper(all, terms, STMT_SERIES_SEARCH, STMT_SEARCH_TERM_SERIES, STMT_SEARCH_ORDER_SERIES)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
defer rows.Close()
|
||||
series := make([]*SeriesAdv, 0, limit)
|
||||
count := 0
|
||||
for rows.Next() {
|
||||
if len(series) <= limit {
|
||||
serie := new(SeriesAdv)
|
||||
|
31
main.go
31
main.go
@ -63,10 +63,7 @@ func initApp() *BouquinsConf {
|
||||
if err != nil {
|
||||
log.Fatalln(err)
|
||||
}
|
||||
app := &Bouquins{
|
||||
tpl,
|
||||
db,
|
||||
}
|
||||
app := &Bouquins{tpl, db}
|
||||
err = app.PrepareAll()
|
||||
if err != nil {
|
||||
log.Fatalln(err)
|
||||
@ -83,13 +80,27 @@ func assets(calibre string) {
|
||||
http.Handle(URL_CALIBRE, http.StripPrefix(URL_CALIBRE, http.FileServer(http.Dir(calibre))))
|
||||
}
|
||||
|
||||
func handle(f func(res http.ResponseWriter, req *http.Request) error) func(res http.ResponseWriter, req *http.Request) {
|
||||
return func(res http.ResponseWriter, req *http.Request) {
|
||||
err := f(res, req)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
http.Error(res, err.Error(), 500)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func handleUrl(url string, f func(res http.ResponseWriter, req *http.Request) error) {
|
||||
http.HandleFunc(url, handle(f))
|
||||
}
|
||||
|
||||
func router(app *Bouquins) {
|
||||
http.HandleFunc(URL_INDEX, app.IndexPage)
|
||||
http.HandleFunc(URL_BOOKS, app.BooksPage)
|
||||
http.HandleFunc(URL_AUTHORS, app.AuthorsPage)
|
||||
http.HandleFunc(URL_SERIES, app.SeriesPage)
|
||||
http.HandleFunc(URL_SEARCH, app.SearchPage)
|
||||
http.HandleFunc(URL_ABOUT, app.AboutPage)
|
||||
handleUrl(URL_INDEX, app.IndexPage)
|
||||
handleUrl(URL_BOOKS, app.BooksPage)
|
||||
handleUrl(URL_AUTHORS, app.AuthorsPage)
|
||||
handleUrl(URL_SERIES, app.SeriesPage)
|
||||
handleUrl(URL_SEARCH, app.SearchPage)
|
||||
handleUrl(URL_ABOUT, app.AboutPage)
|
||||
}
|
||||
|
||||
func main() {
|
||||
|
Loading…
Reference in New Issue
Block a user