Fossil SCM

Add capability to determine whether a given sub-thread inherits a lock from a parent. Re-label "locked" to "closed" per /chat feedback.

stephan 2023-02-21 01:58 forumpost-locking
Commit 464f4d175f503806837051c4bc6b404a29c72c3a7ea2141e492c1c5d4ce26ef7
3 files changed +1 -1 +29 +14 -12
+1 -1
--- src/default.css
+++ src/default.css
@@ -904,11 +904,11 @@
904904
div.forumClosed {
905905
border-style: dotted;
906906
opacity: 0.7;
907907
}
908908
div.forumClosed > *:first-child::before {
909
- content: "[LOCKED] ";
909
+ content: "[CLOSED] ";
910910
color: red;
911911
opacity: 0.7;
912912
}
913913
.forum div > form {
914914
margin: 0.5em 0;
915915
--- src/default.css
+++ src/default.css
@@ -904,11 +904,11 @@
904 div.forumClosed {
905 border-style: dotted;
906 opacity: 0.7;
907 }
908 div.forumClosed > *:first-child::before {
909 content: "[LOCKED] ";
910 color: red;
911 opacity: 0.7;
912 }
913 .forum div > form {
914 margin: 0.5em 0;
915
--- src/default.css
+++ src/default.css
@@ -904,11 +904,11 @@
904 div.forumClosed {
905 border-style: dotted;
906 opacity: 0.7;
907 }
908 div.forumClosed > *:first-child::before {
909 content: "[CLOSED] ";
910 color: red;
911 opacity: 0.7;
912 }
913 .forum div > form {
914 margin: 0.5em 0;
915
+29
--- src/forum.c
+++ src/forum.c
@@ -95,10 +95,36 @@
9595
return forum_post_is_closed(p->pIrt->pEditTail
9696
? p->pIrt->pEditTail : p->pIrt);
9797
}
9898
return 0;
9999
}
100
+
101
+/*
102
+** Given a forum post RID, this function returns true if that post or
103
+** the latest version of any parent post in its hierarchy have an
104
+** active "closed" tag.
105
+*/
106
+int forum_rid_is_closed(int rid){
107
+ static Stmt qIrt = empty_Stmt_m;
108
+ int rc;
109
+
110
+ /* TODO: this can probably be turned into a CTE, rather than a
111
+ ** recursive call into this function, by someone with superior
112
+ ** SQL-fu. */
113
+ rc = rid_has_active_tag_name(rid, "closed");
114
+ if( rc ) return rc;
115
+ else if( !qIrt.pStmt ) {
116
+ db_static_prepare(&qIrt,
117
+ "SELECT firt FROM forumpost "
118
+ "WHERE fpid=$fpid ORDER BY fmtime DESC"
119
+ );
120
+ }
121
+ db_bind_int(&qIrt, "$fpid", rid);
122
+ rc = SQLITE_ROW==db_step(&qIrt) ? db_column_int(&qIrt, 0) : 0;
123
+ db_reset(&qIrt);
124
+ return rc>0 ? forum_rid_is_closed(rc) : 0;
125
+}
100126
101127
/*
102128
** Delete a complete ForumThread and all its entries.
103129
*/
104130
static void forumthread_delete(ForumThread *pThread){
@@ -1105,10 +1131,11 @@
11051131
** But first prompt to see if the user would like to log in.
11061132
*/
11071133
void forum_page_init(void){
11081134
int isEdit;
11091135
char *zGoto;
1136
+
11101137
login_check_credentials();
11111138
if( !g.perm.WrForum ){
11121139
login_needed(g.anon.WrForum);
11131140
return;
11141141
}
@@ -1236,10 +1263,11 @@
12361263
const char *zTitle = 0;
12371264
char *zDate = 0;
12381265
const char *zFpid = PD("fpid","");
12391266
int isCsrfSafe;
12401267
int isDelete = 0;
1268
+ int fClosed = 0;
12411269
12421270
login_check_credentials();
12431271
if( !g.perm.WrForum ){
12441272
login_needed(g.anon.WrForum);
12451273
return;
@@ -1254,10 +1282,11 @@
12541282
}
12551283
if( P("cancel") ){
12561284
cgi_redirectf("%R/forumpost/%S",P("fpid"));
12571285
return;
12581286
}
1287
+ fClosed = forum_rid_is_closed(fpid);
12591288
isCsrfSafe = cgi_csrf_safe(1);
12601289
if( g.perm.ModForum && isCsrfSafe ){
12611290
if( P("approve") ){
12621291
const char *zUserToTrust;
12631292
moderation_approve('f', fpid);
12641293
--- src/forum.c
+++ src/forum.c
@@ -95,10 +95,36 @@
95 return forum_post_is_closed(p->pIrt->pEditTail
96 ? p->pIrt->pEditTail : p->pIrt);
97 }
98 return 0;
99 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
100
101 /*
102 ** Delete a complete ForumThread and all its entries.
103 */
104 static void forumthread_delete(ForumThread *pThread){
@@ -1105,10 +1131,11 @@
1105 ** But first prompt to see if the user would like to log in.
1106 */
1107 void forum_page_init(void){
1108 int isEdit;
1109 char *zGoto;
 
1110 login_check_credentials();
1111 if( !g.perm.WrForum ){
1112 login_needed(g.anon.WrForum);
1113 return;
1114 }
@@ -1236,10 +1263,11 @@
1236 const char *zTitle = 0;
1237 char *zDate = 0;
1238 const char *zFpid = PD("fpid","");
1239 int isCsrfSafe;
1240 int isDelete = 0;
 
1241
1242 login_check_credentials();
1243 if( !g.perm.WrForum ){
1244 login_needed(g.anon.WrForum);
1245 return;
@@ -1254,10 +1282,11 @@
1254 }
1255 if( P("cancel") ){
1256 cgi_redirectf("%R/forumpost/%S",P("fpid"));
1257 return;
1258 }
 
1259 isCsrfSafe = cgi_csrf_safe(1);
1260 if( g.perm.ModForum && isCsrfSafe ){
1261 if( P("approve") ){
1262 const char *zUserToTrust;
1263 moderation_approve('f', fpid);
1264
--- src/forum.c
+++ src/forum.c
@@ -95,10 +95,36 @@
95 return forum_post_is_closed(p->pIrt->pEditTail
96 ? p->pIrt->pEditTail : p->pIrt);
97 }
98 return 0;
99 }
100
101 /*
102 ** Given a forum post RID, this function returns true if that post or
103 ** the latest version of any parent post in its hierarchy have an
104 ** active "closed" tag.
105 */
106 int forum_rid_is_closed(int rid){
107 static Stmt qIrt = empty_Stmt_m;
108 int rc;
109
110 /* TODO: this can probably be turned into a CTE, rather than a
111 ** recursive call into this function, by someone with superior
112 ** SQL-fu. */
113 rc = rid_has_active_tag_name(rid, "closed");
114 if( rc ) return rc;
115 else if( !qIrt.pStmt ) {
116 db_static_prepare(&qIrt,
117 "SELECT firt FROM forumpost "
118 "WHERE fpid=$fpid ORDER BY fmtime DESC"
119 );
120 }
121 db_bind_int(&qIrt, "$fpid", rid);
122 rc = SQLITE_ROW==db_step(&qIrt) ? db_column_int(&qIrt, 0) : 0;
123 db_reset(&qIrt);
124 return rc>0 ? forum_rid_is_closed(rc) : 0;
125 }
126
127 /*
128 ** Delete a complete ForumThread and all its entries.
129 */
130 static void forumthread_delete(ForumThread *pThread){
@@ -1105,10 +1131,11 @@
1131 ** But first prompt to see if the user would like to log in.
1132 */
1133 void forum_page_init(void){
1134 int isEdit;
1135 char *zGoto;
1136
1137 login_check_credentials();
1138 if( !g.perm.WrForum ){
1139 login_needed(g.anon.WrForum);
1140 return;
1141 }
@@ -1236,10 +1263,11 @@
1263 const char *zTitle = 0;
1264 char *zDate = 0;
1265 const char *zFpid = PD("fpid","");
1266 int isCsrfSafe;
1267 int isDelete = 0;
1268 int fClosed = 0;
1269
1270 login_check_credentials();
1271 if( !g.perm.WrForum ){
1272 login_needed(g.anon.WrForum);
1273 return;
@@ -1254,10 +1282,11 @@
1282 }
1283 if( P("cancel") ){
1284 cgi_redirectf("%R/forumpost/%S",P("fpid"));
1285 return;
1286 }
1287 fClosed = forum_rid_is_closed(fpid);
1288 isCsrfSafe = cgi_csrf_safe(1);
1289 if( g.perm.ModForum && isCsrfSafe ){
1290 if( P("approve") ){
1291 const char *zUserToTrust;
1292 moderation_approve('f', fpid);
1293
+14 -12
--- src/tag.c
+++ src/tag.c
@@ -906,28 +906,30 @@
906906
);
907907
}
908908
909909
910910
/*
911
-** Returns tagxref.tagtype if the given blob.rid has a tagxref.rid
912
-** entry an active tag matching the given rid and tag name string,
913
-** else returns 0. Note that this function does not distinguish
914
-** between a non-existent tag and a cancelled tag.
911
+** Returns tagxref.rowid if the given blob.rid has a tagxref.rid entry
912
+** an active (non-cancelled) tag matching the given rid and tag name
913
+** string, else returns 0. Note that this function does not
914
+** distinguish between a non-existent tag and a cancelled tag.
915915
*/
916916
int rid_has_active_tag_name(int rid, const char *zTagName){
917917
static Stmt q = empty_Stmt_m;
918918
int rc = 0;
919919
920920
assert( 0 != zTagName );
921
- db_static_prepare(&q,
922
- "SELECT tagxref.tagtype FROM tagxref, tag"
923
- " WHERE tagxref.rid=:rid AND tagtype>0 "
924
- " AND tag.tagname=:tagname"
925
- " AND tagxref.tagid=tag.tagid"
926
- );
927
- db_bind_int(&q, ":rid", rid);
928
- db_bind_text(&q, ":tagname", zTagName);
921
+ if( !q.pStmt ){
922
+ db_static_prepare(&q,
923
+ "SELECT tagxref.rowid FROM tagxref, tag"
924
+ " WHERE tagxref.rid=$rid AND tagtype>0 "
925
+ " AND tag.tagname=$tagname"
926
+ " AND tagxref.tagid=tag.tagid"
927
+ );
928
+ }
929
+ db_bind_int(&q, "$rid", rid);
930
+ db_bind_text(&q, "$tagname", zTagName);
929931
if( SQLITE_ROW==db_step(&q) ){
930932
rc = db_column_int(&q, 0);
931933
}
932934
db_reset(&q);
933935
return rc;
934936
--- src/tag.c
+++ src/tag.c
@@ -906,28 +906,30 @@
906 );
907 }
908
909
910 /*
911 ** Returns tagxref.tagtype if the given blob.rid has a tagxref.rid
912 ** entry an active tag matching the given rid and tag name string,
913 ** else returns 0. Note that this function does not distinguish
914 ** between a non-existent tag and a cancelled tag.
915 */
916 int rid_has_active_tag_name(int rid, const char *zTagName){
917 static Stmt q = empty_Stmt_m;
918 int rc = 0;
919
920 assert( 0 != zTagName );
921 db_static_prepare(&q,
922 "SELECT tagxref.tagtype FROM tagxref, tag"
923 " WHERE tagxref.rid=:rid AND tagtype>0 "
924 " AND tag.tagname=:tagname"
925 " AND tagxref.tagid=tag.tagid"
926 );
927 db_bind_int(&q, ":rid", rid);
928 db_bind_text(&q, ":tagname", zTagName);
 
 
929 if( SQLITE_ROW==db_step(&q) ){
930 rc = db_column_int(&q, 0);
931 }
932 db_reset(&q);
933 return rc;
934
--- src/tag.c
+++ src/tag.c
@@ -906,28 +906,30 @@
906 );
907 }
908
909
910 /*
911 ** Returns tagxref.rowid if the given blob.rid has a tagxref.rid entry
912 ** an active (non-cancelled) tag matching the given rid and tag name
913 ** string, else returns 0. Note that this function does not
914 ** distinguish between a non-existent tag and a cancelled tag.
915 */
916 int rid_has_active_tag_name(int rid, const char *zTagName){
917 static Stmt q = empty_Stmt_m;
918 int rc = 0;
919
920 assert( 0 != zTagName );
921 if( !q.pStmt ){
922 db_static_prepare(&q,
923 "SELECT tagxref.rowid FROM tagxref, tag"
924 " WHERE tagxref.rid=$rid AND tagtype>0 "
925 " AND tag.tagname=$tagname"
926 " AND tagxref.tagid=tag.tagid"
927 );
928 }
929 db_bind_int(&q, "$rid", rid);
930 db_bind_text(&q, "$tagname", zTagName);
931 if( SQLITE_ROW==db_step(&q) ){
932 rc = db_column_int(&q, 0);
933 }
934 db_reset(&q);
935 return rc;
936

Keyboard Shortcuts

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