Fossil SCM

Forum posts appear in the timeline. The /info command displays posts.

drh 2018-07-24 23:37 forum-v2
Commit 449f06c296f883393b1b772b84237c93f25115088d19d3c64e6e9958f99f17b5
+44 -16
--- src/forum.c
+++ src/forum.c
@@ -18,21 +18,55 @@
1818
** This file contains code used to generate the user forum.
1919
*/
2020
#include "config.h"
2121
#include <assert.h>
2222
#include "forum.h"
23
+
24
+/*
25
+** Render a forum post for display
26
+*/
27
+void forum_render(const char *zMimetype, const char *zContent){
28
+ Blob x;
29
+ blob_init(&x, zContent, -1);
30
+ wiki_render_by_mimetype(&x, zMimetype);
31
+ blob_reset(&x);
32
+}
2333
2434
/*
2535
** Display all posts in a forum thread in chronological order
2636
*/
2737
static void forum_thread_chronological(int froot){
2838
Stmt q;
29
- db_prepare(&q, "SELECT fpid FROM forumpost WHERE froot=%d"
30
- " ORDER BY fmtime", froot);
39
+ int i = 0;
40
+ db_prepare(&q,
41
+ "SELECT fpid, fprev, firt, uuid, datetime(fmtime,'unixepoch')\n"
42
+ " FROM forumpost, blob\n"
43
+ " WHERE froot=%d AND rid=fpid\n"
44
+ " ORDER BY fmtime", froot);
3145
while( db_step(&q)==SQLITE_ROW ){
3246
int fpid = db_column_int(&q, 0);
47
+ int fprev = db_column_int(&q, 1);
48
+ int firt = db_column_int(&q, 2);
49
+ const char *zUuid = db_column_text(&q, 3);
50
+ const char *zDate = db_column_text(&q, 4);
3351
Manifest *pPost = manifest_get(fpid, CFTYPE_FORUM, 0);
52
+ if( i==0 ){
53
+ @ <hr>
54
+ }
55
+ i++;
56
+ @ <p>%d(fpid) %h(zUuid)<br>
57
+ @ By %h(pPost->zUser) on %h(zDate)
58
+ if( fprev ){
59
+ @ edit of %d(fprev) %h(pPost->azParent[0])
60
+ }
61
+ if( firt ){
62
+ @ in reply to %d(firt) %h(pPost->zInReplyTo)
63
+ }
64
+ if( pPost->zThreadTitle ){
65
+ @ <h1>%h(pPost->zThreadTitle)</h1>
66
+ }
67
+ forum_render(pPost->zMimetype, pPost->zWiki);
3468
if( pPost==0 ) continue;
3569
manifest_destroy(pPost);
3670
}
3771
db_finalize(&q);
3872
}
@@ -86,12 +120,14 @@
86120
return !g.perm.WrTForum && !g.perm.ModForum && P("domod")==0;
87121
}
88122
89123
/*
90124
** Add a new Forum Post artifact to the repository.
125
+**
126
+** Return true if a redirect occurs.
91127
*/
92
-static void forum_post(
128
+static int forum_post(
93129
const char *zTitle, /* Title. NULL for replies */
94130
int iInReplyTo, /* Post replying to. 0 for new threads */
95131
int iEdit, /* Post being edited, or zero for a new post */
96132
const char *zUser, /* Username. NULL means use login name */
97133
const char *zMimetype, /* Mimetype of content. */
@@ -142,26 +178,18 @@
142178
blob_appendf(&x, "Z %b\n", &cksum);
143179
blob_reset(&cksum);
144180
if( P("dryrun") ){
145181
@ <pre>%h(blob_str(&x))</pre><hr>
146182
}else{
147
- wiki_put(&x, 0, forum_need_moderation());
148
- return;
183
+ int nrid = wiki_put(&x, 0, forum_need_moderation());
184
+ cgi_redirectf("%R/forumthread/%S", rid_to_uuid(nrid));
185
+ return 1;
149186
}
150187
151188
forum_post_error:
152189
blob_reset(&x);
153
-}
154
-
155
-/*
156
-** Render a forum post for display
157
-*/
158
-void forum_render(const char *zMimetype, const char *zContent){
159
- Blob x;
160
- blob_init(&x, zContent, -1);
161
- wiki_render_by_mimetype(&x, zMimetype);
162
- blob_reset(&x);
190
+ return 0;
163191
}
164192
165193
/*
166194
** WEBPAGE: forumnew
167195
** WEBPAGE: test-forumnew
@@ -178,11 +206,11 @@
178206
if( !g.perm.WrForum ){
179207
login_needed(g.anon.WrForum);
180208
return;
181209
}
182210
if( P("submit") ){
183
- forum_post(zTitle, 0, 0, 0, zMimetype, zContent);
211
+ if( forum_post(zTitle, 0, 0, 0, zMimetype, zContent) ) return;
184212
}
185213
if( P("preview") ){
186214
@ <h1>%h(zTitle)</h1>
187215
forum_render(zMimetype, zContent);
188216
@ <hr>
189217
--- src/forum.c
+++ src/forum.c
@@ -18,21 +18,55 @@
18 ** This file contains code used to generate the user forum.
19 */
20 #include "config.h"
21 #include <assert.h>
22 #include "forum.h"
 
 
 
 
 
 
 
 
 
 
23
24 /*
25 ** Display all posts in a forum thread in chronological order
26 */
27 static void forum_thread_chronological(int froot){
28 Stmt q;
29 db_prepare(&q, "SELECT fpid FROM forumpost WHERE froot=%d"
30 " ORDER BY fmtime", froot);
 
 
 
 
31 while( db_step(&q)==SQLITE_ROW ){
32 int fpid = db_column_int(&q, 0);
 
 
 
 
33 Manifest *pPost = manifest_get(fpid, CFTYPE_FORUM, 0);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
34 if( pPost==0 ) continue;
35 manifest_destroy(pPost);
36 }
37 db_finalize(&q);
38 }
@@ -86,12 +120,14 @@
86 return !g.perm.WrTForum && !g.perm.ModForum && P("domod")==0;
87 }
88
89 /*
90 ** Add a new Forum Post artifact to the repository.
 
 
91 */
92 static void forum_post(
93 const char *zTitle, /* Title. NULL for replies */
94 int iInReplyTo, /* Post replying to. 0 for new threads */
95 int iEdit, /* Post being edited, or zero for a new post */
96 const char *zUser, /* Username. NULL means use login name */
97 const char *zMimetype, /* Mimetype of content. */
@@ -142,26 +178,18 @@
142 blob_appendf(&x, "Z %b\n", &cksum);
143 blob_reset(&cksum);
144 if( P("dryrun") ){
145 @ <pre>%h(blob_str(&x))</pre><hr>
146 }else{
147 wiki_put(&x, 0, forum_need_moderation());
148 return;
 
149 }
150
151 forum_post_error:
152 blob_reset(&x);
153 }
154
155 /*
156 ** Render a forum post for display
157 */
158 void forum_render(const char *zMimetype, const char *zContent){
159 Blob x;
160 blob_init(&x, zContent, -1);
161 wiki_render_by_mimetype(&x, zMimetype);
162 blob_reset(&x);
163 }
164
165 /*
166 ** WEBPAGE: forumnew
167 ** WEBPAGE: test-forumnew
@@ -178,11 +206,11 @@
178 if( !g.perm.WrForum ){
179 login_needed(g.anon.WrForum);
180 return;
181 }
182 if( P("submit") ){
183 forum_post(zTitle, 0, 0, 0, zMimetype, zContent);
184 }
185 if( P("preview") ){
186 @ <h1>%h(zTitle)</h1>
187 forum_render(zMimetype, zContent);
188 @ <hr>
189
--- src/forum.c
+++ src/forum.c
@@ -18,21 +18,55 @@
18 ** This file contains code used to generate the user forum.
19 */
20 #include "config.h"
21 #include <assert.h>
22 #include "forum.h"
23
24 /*
25 ** Render a forum post for display
26 */
27 void forum_render(const char *zMimetype, const char *zContent){
28 Blob x;
29 blob_init(&x, zContent, -1);
30 wiki_render_by_mimetype(&x, zMimetype);
31 blob_reset(&x);
32 }
33
34 /*
35 ** Display all posts in a forum thread in chronological order
36 */
37 static void forum_thread_chronological(int froot){
38 Stmt q;
39 int i = 0;
40 db_prepare(&q,
41 "SELECT fpid, fprev, firt, uuid, datetime(fmtime,'unixepoch')\n"
42 " FROM forumpost, blob\n"
43 " WHERE froot=%d AND rid=fpid\n"
44 " ORDER BY fmtime", froot);
45 while( db_step(&q)==SQLITE_ROW ){
46 int fpid = db_column_int(&q, 0);
47 int fprev = db_column_int(&q, 1);
48 int firt = db_column_int(&q, 2);
49 const char *zUuid = db_column_text(&q, 3);
50 const char *zDate = db_column_text(&q, 4);
51 Manifest *pPost = manifest_get(fpid, CFTYPE_FORUM, 0);
52 if( i==0 ){
53 @ <hr>
54 }
55 i++;
56 @ <p>%d(fpid) %h(zUuid)<br>
57 @ By %h(pPost->zUser) on %h(zDate)
58 if( fprev ){
59 @ edit of %d(fprev) %h(pPost->azParent[0])
60 }
61 if( firt ){
62 @ in reply to %d(firt) %h(pPost->zInReplyTo)
63 }
64 if( pPost->zThreadTitle ){
65 @ <h1>%h(pPost->zThreadTitle)</h1>
66 }
67 forum_render(pPost->zMimetype, pPost->zWiki);
68 if( pPost==0 ) continue;
69 manifest_destroy(pPost);
70 }
71 db_finalize(&q);
72 }
@@ -86,12 +120,14 @@
120 return !g.perm.WrTForum && !g.perm.ModForum && P("domod")==0;
121 }
122
123 /*
124 ** Add a new Forum Post artifact to the repository.
125 **
126 ** Return true if a redirect occurs.
127 */
128 static int forum_post(
129 const char *zTitle, /* Title. NULL for replies */
130 int iInReplyTo, /* Post replying to. 0 for new threads */
131 int iEdit, /* Post being edited, or zero for a new post */
132 const char *zUser, /* Username. NULL means use login name */
133 const char *zMimetype, /* Mimetype of content. */
@@ -142,26 +178,18 @@
178 blob_appendf(&x, "Z %b\n", &cksum);
179 blob_reset(&cksum);
180 if( P("dryrun") ){
181 @ <pre>%h(blob_str(&x))</pre><hr>
182 }else{
183 int nrid = wiki_put(&x, 0, forum_need_moderation());
184 cgi_redirectf("%R/forumthread/%S", rid_to_uuid(nrid));
185 return 1;
186 }
187
188 forum_post_error:
189 blob_reset(&x);
190 return 0;
 
 
 
 
 
 
 
 
 
191 }
192
193 /*
194 ** WEBPAGE: forumnew
195 ** WEBPAGE: test-forumnew
@@ -178,11 +206,11 @@
206 if( !g.perm.WrForum ){
207 login_needed(g.anon.WrForum);
208 return;
209 }
210 if( P("submit") ){
211 if( forum_post(zTitle, 0, 0, 0, zMimetype, zContent) ) return;
212 }
213 if( P("preview") ){
214 @ <h1>%h(zTitle)</h1>
215 forum_render(zMimetype, zContent);
216 @ <hr>
217
+5
--- src/info.c
+++ src/info.c
@@ -2364,10 +2364,15 @@
23642364
if( db_exists("SELECT 1 FROM plink WHERE pid=%d", rid) ){
23652365
ci_page();
23662366
}else
23672367
if( db_exists("SELECT 1 FROM attachment WHERE attachid=%d", rid) ){
23682368
ainfo_page();
2369
+ }else
2370
+ if( db_table_exists("repository","forumpost")
2371
+ && db_exists("SELECT 1 FROM forumpost WHERE fpid=%d", rid)
2372
+ ){
2373
+ forumthread_page();
23692374
}else
23702375
{
23712376
artifact_page();
23722377
}
23732378
}
23742379
--- src/info.c
+++ src/info.c
@@ -2364,10 +2364,15 @@
2364 if( db_exists("SELECT 1 FROM plink WHERE pid=%d", rid) ){
2365 ci_page();
2366 }else
2367 if( db_exists("SELECT 1 FROM attachment WHERE attachid=%d", rid) ){
2368 ainfo_page();
 
 
 
 
 
2369 }else
2370 {
2371 artifact_page();
2372 }
2373 }
2374
--- src/info.c
+++ src/info.c
@@ -2364,10 +2364,15 @@
2364 if( db_exists("SELECT 1 FROM plink WHERE pid=%d", rid) ){
2365 ci_page();
2366 }else
2367 if( db_exists("SELECT 1 FROM attachment WHERE attachid=%d", rid) ){
2368 ainfo_page();
2369 }else
2370 if( db_table_exists("repository","forumpost")
2371 && db_exists("SELECT 1 FROM forumpost WHERE fpid=%d", rid)
2372 ){
2373 forumthread_page();
2374 }else
2375 {
2376 artifact_page();
2377 }
2378 }
2379
+21 -1
--- src/manifest.c
+++ src/manifest.c
@@ -2466,18 +2466,38 @@
24662466
blob_reset(&comment);
24672467
}
24682468
if( p->type==CFTYPE_FORUM ){
24692469
int froot, fprev, firt;
24702470
schema_forum();
2471
- froot = p->zThreadRoot ? uuid_to_rid(p->zThreadRoot, 1) : p->rid;
2471
+ froot = p->zThreadRoot ? uuid_to_rid(p->zThreadRoot, 1) : rid;
24722472
fprev = p->nParent ? uuid_to_rid(p->azParent[0],1) : 0;
24732473
firt = p->zInReplyTo ? uuid_to_rid(p->zInReplyTo,1) : 0;
24742474
db_multi_exec(
24752475
"INSERT INTO forumpost(fpid,froot,fprev,firt,fmtime)"
24762476
"VALUES(%d,%d,nullif(%d,0),nullif(%d,0),%.17g)",
24772477
p->rid, froot, fprev, firt, p->rDate
24782478
);
2479
+ if( froot!=p->rid ){
2480
+ db_multi_exec(
2481
+ "REPLACE INTO event(type,mtime,objid,user,comment)"
2482
+ "VALUES('f',%.17g,%d,%Q,'Reply to:'||"
2483
+ "coalesce(substr((SELECT comment FROM event"
2484
+ " WHERE objid=%d),12),' post '||substr(%Q,1,14)))",
2485
+ p->rDate, rid, p->zUser, froot, zUuid
2486
+ );
2487
+ }else{
2488
+ db_multi_exec(
2489
+ "REPLACE INTO event(type,mtime,objid,user,comment)"
2490
+ "VALUES('f',%.17g,%d,%Q,'Forum post: %q')",
2491
+ p->rDate, rid, p->zUser, p->zThreadTitle
2492
+ );
2493
+ db_multi_exec(
2494
+ "UPDATE event SET comment='Reply to: %q' WHERE objid IN"
2495
+ " (SELECT fpid FROM forumpost WHERE froot=%d AND fpid!=froot)",
2496
+ p->zThreadTitle, rid
2497
+ );
2498
+ }
24792499
}
24802500
db_end_transaction(0);
24812501
if( permitHooks ){
24822502
rc = xfer_run_common_script();
24832503
if( rc==TH_OK ){
24842504
--- src/manifest.c
+++ src/manifest.c
@@ -2466,18 +2466,38 @@
2466 blob_reset(&comment);
2467 }
2468 if( p->type==CFTYPE_FORUM ){
2469 int froot, fprev, firt;
2470 schema_forum();
2471 froot = p->zThreadRoot ? uuid_to_rid(p->zThreadRoot, 1) : p->rid;
2472 fprev = p->nParent ? uuid_to_rid(p->azParent[0],1) : 0;
2473 firt = p->zInReplyTo ? uuid_to_rid(p->zInReplyTo,1) : 0;
2474 db_multi_exec(
2475 "INSERT INTO forumpost(fpid,froot,fprev,firt,fmtime)"
2476 "VALUES(%d,%d,nullif(%d,0),nullif(%d,0),%.17g)",
2477 p->rid, froot, fprev, firt, p->rDate
2478 );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2479 }
2480 db_end_transaction(0);
2481 if( permitHooks ){
2482 rc = xfer_run_common_script();
2483 if( rc==TH_OK ){
2484
--- src/manifest.c
+++ src/manifest.c
@@ -2466,18 +2466,38 @@
2466 blob_reset(&comment);
2467 }
2468 if( p->type==CFTYPE_FORUM ){
2469 int froot, fprev, firt;
2470 schema_forum();
2471 froot = p->zThreadRoot ? uuid_to_rid(p->zThreadRoot, 1) : rid;
2472 fprev = p->nParent ? uuid_to_rid(p->azParent[0],1) : 0;
2473 firt = p->zInReplyTo ? uuid_to_rid(p->zInReplyTo,1) : 0;
2474 db_multi_exec(
2475 "INSERT INTO forumpost(fpid,froot,fprev,firt,fmtime)"
2476 "VALUES(%d,%d,nullif(%d,0),nullif(%d,0),%.17g)",
2477 p->rid, froot, fprev, firt, p->rDate
2478 );
2479 if( froot!=p->rid ){
2480 db_multi_exec(
2481 "REPLACE INTO event(type,mtime,objid,user,comment)"
2482 "VALUES('f',%.17g,%d,%Q,'Reply to:'||"
2483 "coalesce(substr((SELECT comment FROM event"
2484 " WHERE objid=%d),12),' post '||substr(%Q,1,14)))",
2485 p->rDate, rid, p->zUser, froot, zUuid
2486 );
2487 }else{
2488 db_multi_exec(
2489 "REPLACE INTO event(type,mtime,objid,user,comment)"
2490 "VALUES('f',%.17g,%d,%Q,'Forum post: %q')",
2491 p->rDate, rid, p->zUser, p->zThreadTitle
2492 );
2493 db_multi_exec(
2494 "UPDATE event SET comment='Reply to: %q' WHERE objid IN"
2495 " (SELECT fpid FROM forumpost WHERE froot=%d AND fpid!=froot)",
2496 p->zThreadTitle, rid
2497 );
2498 }
2499 }
2500 db_end_transaction(0);
2501 if( permitHooks ){
2502 rc = xfer_run_common_script();
2503 if( rc==TH_OK ){
2504
+2 -1
--- src/wiki.c
+++ src/wiki.c
@@ -426,11 +426,11 @@
426426
}
427427
428428
/*
429429
** Write a wiki artifact into the repository
430430
*/
431
-void wiki_put(Blob *pWiki, int parent, int needMod){
431
+int wiki_put(Blob *pWiki, int parent, int needMod){
432432
int nrid;
433433
if( !needMod ){
434434
nrid = content_put_ex(pWiki, 0, 0, 0, 0);
435435
if( parent) content_deltify(parent, &nrid, 1, 0);
436436
}else{
@@ -439,10 +439,11 @@
439439
db_multi_exec("INSERT INTO modreq(objid) VALUES(%d)", nrid);
440440
}
441441
db_multi_exec("INSERT OR IGNORE INTO unsent VALUES(%d)", nrid);
442442
db_multi_exec("INSERT OR IGNORE INTO unclustered VALUES(%d);", nrid);
443443
manifest_crosslink(nrid, pWiki, MC_NONE);
444
+ return nrid;
444445
}
445446
446447
/*
447448
** Output a selection box from which the user can select the
448449
** wiki mimetype.
449450
--- src/wiki.c
+++ src/wiki.c
@@ -426,11 +426,11 @@
426 }
427
428 /*
429 ** Write a wiki artifact into the repository
430 */
431 void wiki_put(Blob *pWiki, int parent, int needMod){
432 int nrid;
433 if( !needMod ){
434 nrid = content_put_ex(pWiki, 0, 0, 0, 0);
435 if( parent) content_deltify(parent, &nrid, 1, 0);
436 }else{
@@ -439,10 +439,11 @@
439 db_multi_exec("INSERT INTO modreq(objid) VALUES(%d)", nrid);
440 }
441 db_multi_exec("INSERT OR IGNORE INTO unsent VALUES(%d)", nrid);
442 db_multi_exec("INSERT OR IGNORE INTO unclustered VALUES(%d);", nrid);
443 manifest_crosslink(nrid, pWiki, MC_NONE);
 
444 }
445
446 /*
447 ** Output a selection box from which the user can select the
448 ** wiki mimetype.
449
--- src/wiki.c
+++ src/wiki.c
@@ -426,11 +426,11 @@
426 }
427
428 /*
429 ** Write a wiki artifact into the repository
430 */
431 int wiki_put(Blob *pWiki, int parent, int needMod){
432 int nrid;
433 if( !needMod ){
434 nrid = content_put_ex(pWiki, 0, 0, 0, 0);
435 if( parent) content_deltify(parent, &nrid, 1, 0);
436 }else{
@@ -439,10 +439,11 @@
439 db_multi_exec("INSERT INTO modreq(objid) VALUES(%d)", nrid);
440 }
441 db_multi_exec("INSERT OR IGNORE INTO unsent VALUES(%d)", nrid);
442 db_multi_exec("INSERT OR IGNORE INTO unclustered VALUES(%d);", nrid);
443 manifest_crosslink(nrid, pWiki, MC_NONE);
444 return nrid;
445 }
446
447 /*
448 ** Output a selection box from which the user can select the
449 ** wiki mimetype.
450

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button