mirror of https://github.com/jlelse/GoBlog
Further improve counting of media uses
This commit is contained in:
parent
d98ae73af0
commit
529d8b616b
|
@ -185,6 +185,10 @@ func (db *database) exec(query string, args ...interface{}) (sql.Result, error)
|
|||
}
|
||||
|
||||
func (db *database) query(query string, args ...interface{}) (*sql.Rows, error) {
|
||||
// Check if prepared cache should be skipped
|
||||
if len(args) > 0 && args[0] == dbNoCache {
|
||||
return db.db.Query(query, args[1:]...)
|
||||
}
|
||||
// Use prepared statement
|
||||
st, _ := db.prepare(query)
|
||||
if st != nil {
|
||||
|
@ -195,6 +199,10 @@ func (db *database) query(query string, args ...interface{}) (*sql.Rows, error)
|
|||
}
|
||||
|
||||
func (db *database) queryRow(query string, args ...interface{}) (*sql.Row, error) {
|
||||
// Check if prepared cache should be skipped
|
||||
if len(args) > 0 && args[0] == dbNoCache {
|
||||
return db.db.QueryRow(query, args[1:]...), nil
|
||||
}
|
||||
// Use prepared statement
|
||||
st, _ := db.prepare(query)
|
||||
if st != nil {
|
||||
|
|
|
@ -3,6 +3,8 @@ package main
|
|||
import (
|
||||
"net/http"
|
||||
"sort"
|
||||
|
||||
"github.com/thoas/go-funk"
|
||||
)
|
||||
|
||||
func (a *goBlog) serveEditorFiles(w http.ResponseWriter, r *http.Request) {
|
||||
|
@ -15,12 +17,26 @@ func (a *goBlog) serveEditorFiles(w http.ResponseWriter, r *http.Request) {
|
|||
sort.Slice(files, func(i, j int) bool {
|
||||
return files[i].Time.After(files[j].Time)
|
||||
})
|
||||
// Find uses
|
||||
fileNames, ok := funk.Map(files, func(f *mediaFile) string {
|
||||
return f.Name
|
||||
}).([]string)
|
||||
if !ok {
|
||||
a.serveError(w, r, "Failed to get file names", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
uses, err := a.db.usesOfMediaFile(fileNames...)
|
||||
if err != nil {
|
||||
a.serveError(w, r, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
// Serve HTML
|
||||
blog := r.Context().Value(blogContextKey).(string)
|
||||
a.render(w, r, templateEditorFiles, &renderData{
|
||||
BlogString: blog,
|
||||
Data: map[string]interface{}{
|
||||
"Files": files,
|
||||
"Uses": uses,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
|
45
postsDb.go
45
postsDb.go
|
@ -471,15 +471,44 @@ func (d *database) allPublishedDates(blog string) (dates []publishedDate, err er
|
|||
return
|
||||
}
|
||||
|
||||
func (db *database) usesOfMediaFile(name string) (count int, err error) {
|
||||
query := "select count(distinct path) from (select path from posts_fts where content match @fts_name union all select path from post_parameters where instr(value, @name) > 0)"
|
||||
row, err := db.queryRow(query, sql.Named("fts_name", fmt.Sprintf("\"%s\"", name)), sql.Named("name", name))
|
||||
if err != nil {
|
||||
return 0, err
|
||||
const mediaUseSql = `
|
||||
with mediafiles (name) as (values %s)
|
||||
select name, count(path) as count from (
|
||||
select distinct m.name, p.path
|
||||
from mediafiles m, post_parameters p
|
||||
where instr(p.value, m.name) > 0
|
||||
union
|
||||
select distinct m.name, p.path
|
||||
from mediafiles m, posts_fts p
|
||||
where p.content match '"' || m.name || '"'
|
||||
)
|
||||
group by name;
|
||||
`
|
||||
|
||||
func (db *database) usesOfMediaFile(names ...string) (counts map[string]int, err error) {
|
||||
sqlArgs := []interface{}{dbNoCache}
|
||||
nameValues := ""
|
||||
for i, n := range names {
|
||||
if i > 0 {
|
||||
nameValues += ", "
|
||||
}
|
||||
named := fmt.Sprintf("name%v", i)
|
||||
nameValues += fmt.Sprintf("(@%s)", named)
|
||||
sqlArgs = append(sqlArgs, sql.Named(named, n))
|
||||
}
|
||||
err = row.Scan(&count)
|
||||
rows, err := db.query(fmt.Sprintf(mediaUseSql, nameValues), sqlArgs...)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
return nil, err
|
||||
}
|
||||
return count, nil
|
||||
counts = map[string]int{}
|
||||
var name string
|
||||
var count int
|
||||
for rows.Next() {
|
||||
err = rows.Scan(&name, &count)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
counts[name] = count
|
||||
}
|
||||
return counts, nil
|
||||
}
|
||||
|
|
|
@ -338,7 +338,10 @@ func Test_usesOfMediaFile(t *testing.T) {
|
|||
}, &postCreationOptions{new: true})
|
||||
require.NoError(t, err)
|
||||
|
||||
count, err := app.db.usesOfMediaFile("test.jpg")
|
||||
counts, err := app.db.usesOfMediaFile("test.jpg")
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, 2, count)
|
||||
assert.Len(t, counts, 1)
|
||||
if assert.NotNil(t, counts["test.jpg"]) {
|
||||
assert.Equal(t, 2, counts["test.jpg"])
|
||||
}
|
||||
}
|
||||
|
|
31
render.go
31
render.go
|
@ -56,22 +56,21 @@ func (a *goBlog) initRendering() error {
|
|||
"translations": a.postTranslations,
|
||||
"shorturl": a.shortPostURL,
|
||||
// Others
|
||||
"dateformat": dateFormat,
|
||||
"isodate": isoDateFormat,
|
||||
"unixtodate": unixToLocalDateString,
|
||||
"now": localNowString,
|
||||
"asset": a.assetFileName,
|
||||
"string": a.ts.GetTemplateStringVariantFunc(),
|
||||
"include": a.includeRenderedTemplate,
|
||||
"urlize": urlize,
|
||||
"sort": sortedStrings,
|
||||
"absolute": a.getFullAddress,
|
||||
"mentions": a.db.getWebmentionsByAddress,
|
||||
"geotitle": a.geoTitle,
|
||||
"geolink": geoOSMLink,
|
||||
"opensearch": openSearchUrl,
|
||||
"mbytes": mBytesString,
|
||||
"mediafileuses": a.db.usesOfMediaFile,
|
||||
"dateformat": dateFormat,
|
||||
"isodate": isoDateFormat,
|
||||
"unixtodate": unixToLocalDateString,
|
||||
"now": localNowString,
|
||||
"asset": a.assetFileName,
|
||||
"string": a.ts.GetTemplateStringVariantFunc(),
|
||||
"include": a.includeRenderedTemplate,
|
||||
"urlize": urlize,
|
||||
"sort": sortedStrings,
|
||||
"absolute": a.getFullAddress,
|
||||
"mentions": a.db.getWebmentionsByAddress,
|
||||
"geotitle": a.geoTitle,
|
||||
"geolink": geoOSMLink,
|
||||
"opensearch": openSearchUrl,
|
||||
"mbytes": mBytesString,
|
||||
}
|
||||
baseTemplate, err := template.New("base").Funcs(templateFunctions).ParseFiles(path.Join(templatesDir, templateBase+templatesExt))
|
||||
if err != nil {
|
||||
|
|
|
@ -9,8 +9,9 @@
|
|||
{{ if .Data.Files }}
|
||||
<form class="fw-form p" method="post">
|
||||
<select name="filename">
|
||||
{{ $uses := .Data.Uses }}
|
||||
{{ range $i, $file := .Data.Files }}
|
||||
<option value="{{ $file.Name }}">{{ $file.Name }} ({{ isodate $file.Time.String }}, {{ mbytes $file.Size }}, ~{{ mediafileuses $file.Name }} {{ string $blog.Lang "fileuses" }})</option>
|
||||
<option value="{{ $file.Name }}">{{ $file.Name }} ({{ isodate $file.Time.String }}, {{ mbytes $file.Size }}, ~{{ index $uses $file.Name }} {{ string $blog.Lang "fileuses" }})</option>
|
||||
{{ end }}
|
||||
</select>
|
||||
<input type="submit" formaction="{{ .Blog.RelativePath "/editor/files/view" }}" value="{{ string .Blog.Lang "view" }}">
|
||||
|
|
Loading…
Reference in New Issue