diff --git a/DB.go b/DB.go index 1c80dc1..68e57d2 100644 --- a/DB.go +++ b/DB.go @@ -117,13 +117,18 @@ func (this *WikiDB) assertSchema() error { return nil } +type TitleInfo struct { + TitleID int64 + Title string + IsDeleted bool +} + type Article struct { - ID int64 - TitleID int64 - Modified int64 - Body []byte - Author string - Title string + TitleInfo + ArticleID int64 + Modified int64 + Body []byte + Author string } func (this *WikiDB) GetArticleById(articleId int) (*Article, error) { @@ -132,7 +137,7 @@ func (this *WikiDB) GetArticleById(articleId int) (*Article, error) { } func (this *WikiDB) GetRevision(revId int) (*Article, error) { - row := this.db.QueryRow(`SELECT articles.*, titles.title FROM articles JOIN titles ON articles.article=titles.id WHERE articles.id = ?`, revId) + row := this.db.QueryRow(`SELECT articles.*, titles.title, titles.is_deleted FROM articles JOIN titles ON articles.article=titles.id WHERE articles.id = ?`, revId) return this.parseArticleWithTitle(row) } @@ -164,8 +169,8 @@ func (this *WikiDB) SaveArticle(title, author, body string, expectBaseRev int64) } } - if !isNewArticle && a.ID != expectBaseRev { - return ArticleAlteredError{got: expectBaseRev, expected: a.ID} + if !isNewArticle && a.ArticleID != expectBaseRev { + return ArticleAlteredError{got: expectBaseRev, expected: a.ArticleID} } zBody, err := gzdeflate([]byte(body), this.compressionLevel) @@ -193,6 +198,13 @@ func (this *WikiDB) SaveArticle(title, author, body string, expectBaseRev int64) return err } + // Update is-deleted flag + isDeleted := 0 + if body == bbcodeIsDeleted { + isDeleted = 1 + } + _, err = this.db.Exec(`UPDATE titles SET is_deleted = ? WHERE id = ?`, isDeleted, titleId) + return nil } @@ -209,7 +221,7 @@ func (this *WikiDB) GetRevisionHistory(title string) ([]Article, error) { ret := make([]Article, 0) for rows.Next() { a := Article{} - err := rows.Scan(&a.ID, &a.Modified, &a.Author) + err := rows.Scan(&a.ArticleID, &a.Modified, &a.Author) if err != nil { return nil, err } @@ -235,7 +247,7 @@ func (this *WikiDB) GetNextOldestRevision(revision int) (int, error) { func (this *WikiDB) GetRecentChanges(offset int, limit int) ([]Article, error) { rows, err := this.db.Query( - `SELECT articles.id, articles.modified, articles.author, titles.title FROM articles JOIN titles ON articles.article=titles.id ORDER BY modified DESC ` + + `SELECT articles.id, articles.modified, articles.author, titles.title, titles.is_deleted FROM articles JOIN titles ON articles.article=titles.id ORDER BY modified DESC ` + fmt.Sprintf(`LIMIT %d OFFSET %d`, limit, offset), ) if err != nil { @@ -246,7 +258,7 @@ func (this *WikiDB) GetRecentChanges(offset int, limit int) ([]Article, error) { ret := make([]Article, 0, limit) for rows.Next() { a := Article{} - err := rows.Scan(&a.ID, &a.Modified, &a.Author, &a.Title) + err := rows.Scan(&a.ArticleID, &a.Modified, &a.Author, &a.Title, &a.IsDeleted) if err != nil { return nil, err } @@ -266,17 +278,23 @@ func (this *WikiDB) TotalRevisions() (int64, error) { return ret, nil } -func (this *WikiDB) ListTitles() ([]string, error) { - rows, err := this.db.Query(`SELECT title FROM titles ORDER BY title ASC`) +func (this *WikiDB) ListTitles(includeDeleted bool) ([]TitleInfo, error) { + stmt := `SELECT id, title, is_deleted FROM titles` + if !includeDeleted { + stmt += ` WHERE is_deleted = 0` + } + stmt += ` ORDER BY title ASC` + + rows, err := this.db.Query(stmt) if err != nil { return nil, err } defer rows.Close() - ret := make([]string, 0) + ret := make([]TitleInfo, 0) for rows.Next() { - var title string - err = rows.Scan(&title) + var title TitleInfo + err = rows.Scan(&title.TitleID, &title.Title, &title.IsDeleted) if err != nil { return nil, err } @@ -289,7 +307,7 @@ func (this *WikiDB) ListTitles() ([]string, error) { func (this *WikiDB) parseArticle(row *sql.Row) (*Article, error) { a := Article{} var gzBody []byte - err := row.Scan(&a.ID, &a.TitleID, &a.Modified, &gzBody, &a.Author) + err := row.Scan(&a.ArticleID, &a.TitleID, &a.Modified, &gzBody, &a.Author) if err != nil { return nil, err } @@ -307,7 +325,7 @@ func (this *WikiDB) parseArticle(row *sql.Row) (*Article, error) { func (this *WikiDB) parseArticleWithTitle(row *sql.Row) (*Article, error) { a := Article{} var gzBody []byte - err := row.Scan(&a.ID, &a.TitleID, &a.Modified, &gzBody, &a.Author, &a.Title) + err := row.Scan(&a.ArticleID, &a.TitleID, &a.Modified, &gzBody, &a.Author, &a.Title, &a.IsDeleted) if err != nil { return nil, err } diff --git a/WikiServer.go b/WikiServer.go index b58df7f..c79175a 100644 --- a/WikiServer.go +++ b/WikiServer.go @@ -148,14 +148,14 @@ func (this *WikiServer) ServeHTTP(w http.ResponseWriter, r *http.Request) { return } else if remainingPath == "random" { - titles, err := this.db.ListTitles() + titles, err := this.db.ListTitles(false) // "Random page" mode does not include deleted pages if err != nil { this.serveInternalError(w, r, err) return } chosenArticle := titles[rand.Intn(len(titles))] - this.serveRedirect(w, this.opts.ExpectBaseURL+`view/`+url.PathEscape(chosenArticle)) + this.serveRedirect(w, this.opts.ExpectBaseURL+`view/`+url.PathEscape(chosenArticle.Title)) return } else if strings.HasPrefix(remainingPath, "view/") { diff --git a/rDiff.go b/rDiff.go index 37ee819..81101f4 100644 --- a/rDiff.go +++ b/rDiff.go @@ -53,9 +53,9 @@ func (this *WikiServer) routeDiff(w http.ResponseWriter, r *http.Request, oldRev pto.Content = template.HTML( `

` + `Comparing ` + string(this.viewLink(oa.Title)) + ` versions ` + - `r` + fmt.Sprintf("%d", oa.ID) + `` + + `r` + fmt.Sprintf("%d", oa.ArticleID) + `` + ` - ` + - `r` + fmt.Sprintf("%d", na.ID) + `` + + `r` + fmt.Sprintf("%d", na.ArticleID) + `` + `

` + `
` + string(b.Bytes()) + `
`, ) diff --git a/rHistory.go b/rHistory.go index b6cff5c..1bf808a 100644 --- a/rHistory.go +++ b/rHistory.go @@ -37,7 +37,7 @@ func (this *WikiServer) routeHistory(w http.ResponseWriter, r *http.Request, art compareRow := `` content += compareRow for _, rev := range revs { - revIdStr := fmt.Sprintf("%d", rev.ID) + revIdStr := fmt.Sprintf("%d", rev.ArticleID) content += `` + `` + string(this.formatTimestamp(rev.Modified)) + `` + `` + template.HTMLEscapeString(rev.Author) + `` + diff --git a/rIndex.go b/rIndex.go index 5216f37..745671b 100644 --- a/rIndex.go +++ b/rIndex.go @@ -8,7 +8,7 @@ import ( ) func (this *WikiServer) routeIndex(w http.ResponseWriter, r *http.Request) { - titles, err := this.db.ListTitles() + titles, err := this.db.ListTitles(true) // Always load deleted pages, even if we don't display them in the list if err != nil { this.serveInternalError(w, r, err) return diff --git a/rModify.go b/rModify.go index 8dee328..0970ac0 100644 --- a/rModify.go +++ b/rModify.go @@ -33,7 +33,7 @@ func (this *WikiServer) routeModify(w http.ResponseWriter, r *http.Request, arti baseRev = 0 } else { pageTitleHTML = `Editing article "` + template.HTMLEscapeString(articleTitle) + `"` - baseRev = a.ID + baseRev = a.ArticleID existingBody = string(a.Body) } diff --git a/rRSS.go b/rRSS.go index 34df2dd..f40698a 100644 --- a/rRSS.go +++ b/rRSS.go @@ -27,17 +27,17 @@ func (this *WikiServer) routeRecentChangesRSS(w http.ResponseWriter, r *http.Req for _, a := range recents { content += ` - ` + template.HTMLEscapeString(a.Title+` (r`+fmt.Sprintf("%d", a.ID)+`)`) + ` - ` + template.HTMLEscapeString(this.opts.ExternalBaseURL+`archive/`+fmt.Sprintf("%d", a.ID)) + ` - ` + template.HTMLEscapeString(this.opts.ExternalBaseURL+`archive/`+fmt.Sprintf("%d", a.ID)) + ` + ` + template.HTMLEscapeString(a.Title+` (r`+fmt.Sprintf("%d", a.ArticleID)+`)`) + ` + ` + template.HTMLEscapeString(this.opts.ExternalBaseURL+`archive/`+fmt.Sprintf("%d", a.ArticleID)) + ` + ` + template.HTMLEscapeString(this.opts.ExternalBaseURL+`archive/`+fmt.Sprintf("%d", a.ArticleID)) + ` ` + template.HTMLEscapeString(this.opts.DeclareRSSEmail+` (`+this.opts.PageTitle+` `+a.Author+`)`) + ` ` + template.HTMLEscapeString(time.Unix(a.Modified, 0).In(this.loc).Format(time.RFC1123Z)) + ` ` + template.HTMLEscapeString(` latest version | - revision `+fmt.Sprintf("%d", a.ID)+` + revision `+fmt.Sprintf("%d", a.ArticleID)+` | - diff to previous + diff to previous `) + ` ` diff --git a/rRecentChanges.go b/rRecentChanges.go index ad67dc4..df9f453 100644 --- a/rRecentChanges.go +++ b/rRecentChanges.go @@ -44,17 +44,19 @@ func (this *WikiServer) routeRecentChanges(w http.ResponseWriter, r *http.Reques for _, rev := range recents { diffHtml := "" - diffRev, err := this.db.GetNextOldestRevision(int(rev.ID)) + diffRev, err := this.db.GetNextOldestRevision(int(rev.ArticleID)) if err != nil { diffHtml = `[new]` } else { - diffHtml = `diff` + diffHtml = `diff` + } + } content += `` + `` + template.HTMLEscapeString(rev.Title) + `` + `` + - `rev   ` + + `rev   ` + diffHtml + `` + `` +