api,db: add comments count endpoint
Closes https://gitlab.com/commento/commento-ce/issues/27
This commit is contained in:
parent
299649cea2
commit
330131f390
43
api/comment_count.go
Normal file
43
api/comment_count.go
Normal file
@ -0,0 +1,43 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
)
|
||||
|
||||
func commentCount(domain string, path string) (int, error) {
|
||||
// path can be empty
|
||||
if domain == "" {
|
||||
return 0, errorMissingField
|
||||
}
|
||||
|
||||
p, err := pageGet(domain, path)
|
||||
if err != nil {
|
||||
return 0, errorInternal
|
||||
}
|
||||
|
||||
return p.CommentCount, nil
|
||||
}
|
||||
|
||||
func commentCountHandler(w http.ResponseWriter, r *http.Request) {
|
||||
type request struct {
|
||||
Domain *string `json:"domain"`
|
||||
Path *string `json:"path"`
|
||||
}
|
||||
|
||||
var x request
|
||||
if err := bodyUnmarshal(r, &x); err != nil {
|
||||
bodyMarshal(w, response{"success": false, "message": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
domain := domainStrip(*x.Domain)
|
||||
path := *x.Path
|
||||
|
||||
count, err := commentCount(domain, path)
|
||||
if err != nil {
|
||||
bodyMarshal(w, response{"success": false, "message": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
bodyMarshal(w, response{"success": true, "count": count})
|
||||
}
|
54
api/comment_count_test.go
Normal file
54
api/comment_count_test.go
Normal file
@ -0,0 +1,54 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestCommentCountBasics(t *testing.T) {
|
||||
failTestOnError(t, setupTestEnv())
|
||||
|
||||
commenterHex, _ := commenterNew("test@example.com", "Test", "undefined", "http://example.com/photo.jpg", "google", "")
|
||||
|
||||
commentNew(commenterHex, "example.com", "/path.html", "root", "**foo**", "approved", time.Now().UTC())
|
||||
commentNew(commenterHex, "example.com", "/path.html", "root", "**bar**", "approved", time.Now().UTC())
|
||||
commentNew(commenterHex, "example.com", "/path.html", "root", "**baz**", "unapproved", time.Now().UTC())
|
||||
|
||||
count, err := commentCount("example.com", "/path.html")
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error counting comments: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
if count != 2 {
|
||||
t.Errorf("expected count=2 got count=%d", count)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func TestCommentCountNewPage(t *testing.T) {
|
||||
failTestOnError(t, setupTestEnv())
|
||||
|
||||
count, err := commentCount("example.com", "/path.html")
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error counting comments: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
if count != 0 {
|
||||
t.Errorf("expected count=0 got count=%d", count)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func TestCommentCountEmpty(t *testing.T) {
|
||||
if _, err := commentCount("example.com", ""); err != nil {
|
||||
t.Errorf("unexpected error counting comments on empty path: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
if _, err := commentCount("", ""); err == nil {
|
||||
t.Errorf("expected error not found counting comments with empty everything")
|
||||
return
|
||||
}
|
||||
}
|
@ -6,4 +6,5 @@ type page struct {
|
||||
Domain string `json:"domain"`
|
||||
Path string `json:"path"`
|
||||
IsLocked bool `json:"isLocked"`
|
||||
CommentCount int `json:"commentCount"`
|
||||
}
|
||||
|
@ -11,19 +11,20 @@ func pageGet(domain string, path string) (page, error) {
|
||||
}
|
||||
|
||||
statement := `
|
||||
SELECT isLocked
|
||||
SELECT isLocked, commentCount
|
||||
FROM pages
|
||||
WHERE domain=$1 AND path=$2;
|
||||
`
|
||||
row := db.QueryRow(statement, domain, path)
|
||||
|
||||
p := page{Domain: domain, Path: path}
|
||||
if err := row.Scan(&p.IsLocked); err != nil {
|
||||
if err := row.Scan(&p.IsLocked, &p.CommentCount); err != nil {
|
||||
if err == sql.ErrNoRows {
|
||||
// If there haven't been any comments, there won't be a record for this
|
||||
// page. The sane thing to do is return defaults.
|
||||
// TODO: the defaults are hard-coded in two places: here and the schema
|
||||
p.IsLocked = false
|
||||
p.CommentCount = 0
|
||||
} else {
|
||||
logger.Errorf("error scanning page: %v", err)
|
||||
return page{}, errorInternal
|
||||
|
@ -9,6 +9,8 @@ func pageUpdate(p page) error {
|
||||
return errorMissingField
|
||||
}
|
||||
|
||||
// fields to not update:
|
||||
// commentCount
|
||||
statement := `
|
||||
INSERT INTO
|
||||
pages (domain, path, isLocked)
|
||||
|
15
db/20180923002745-comment-count.sql
Normal file
15
db/20180923002745-comment-count.sql
Normal file
@ -0,0 +1,15 @@
|
||||
ALTER TABLE pages
|
||||
ADD commentCount INTEGER NOT NULL DEFAULT 0;
|
||||
|
||||
CREATE OR REPLACE FUNCTION commentsInsertTriggerFunction() RETURNS TRIGGER AS $trigger$
|
||||
BEGIN
|
||||
UPDATE pages
|
||||
SET commentCount = commentCount + 1
|
||||
WHERE domain = new.domain AND path = new.path;
|
||||
|
||||
RETURN NEW;
|
||||
END;
|
||||
$trigger$ LANGUAGE plpgsql;
|
||||
|
||||
CREATE TRIGGER commentsInsertTrigger AFTER INSERT ON comments
|
||||
FOR EACH ROW EXECUTE PROCEDURE commentsInsertTriggerFunction();
|
Loading…
Reference in New Issue
Block a user