1 ! Copyright (C) 2008 Slava Pestov
2 ! See http://factorcode.org/license.txt for BSD license.
3 USING: accessors kernel hashtables calendar
4 namespaces splitting sequences sorting math.order present
5 html.components syndication
7 http.server.dispatchers
15 db.types db.tuples lcs farkup urls ;
18 : wiki-url ( rest path -- url )
19 [ "$wiki/" % % "/" % % ] "" make
22 : view-url ( title -- url ) "view" wiki-url ;
24 : edit-url ( title -- url ) "edit" wiki-url ;
26 : revisions-url ( title -- url ) "revisions" wiki-url ;
28 : revision-url ( id -- url ) "revision" wiki-url ;
30 : user-edits-url ( author -- url ) "user-edits" wiki-url ;
32 TUPLE: wiki < dispatcher ;
34 TUPLE: article title revision ;
37 { "title" "TITLE" { VARCHAR 256 } +not-null+ +user-assigned-id+ }
38 ! { "AUTHOR" INTEGER +not-null+ } ! uid
39 ! { "PROTECTED" BOOLEAN +not-null+ }
40 { "revision" "REVISION" INTEGER +not-null+ } ! revision id
43 : <article> ( title -- article ) article new swap >>title ;
45 : init-articles-table ( -- ) article ensure-table ;
47 TUPLE: revision id title author date content ;
49 revision "REVISIONS" {
50 { "id" "ID" INTEGER +db-assigned-id+ }
51 { "title" "TITLE" { VARCHAR 256 } +not-null+ } ! article id
52 { "author" "AUTHOR" { VARCHAR 256 } +not-null+ } ! uid
53 { "date" "DATE" TIMESTAMP +not-null+ }
54 { "content" "CONTENT" TEXT +not-null+ }
57 M: revision feed-entry-title
58 [ title>> ] [ drop " by " ] [ author>> ] tri 3append ;
60 M: revision feed-entry-date date>> ;
62 M: revision feed-entry-url id>> revision-url ;
64 : reverse-chronological-order ( seq -- sorted )
65 [ [ date>> ] compare invert-comparison ] sort ;
67 : <revision> ( id -- revision )
68 revision new swap >>id ;
70 : init-revisions-table ( -- ) revision ensure-table ;
72 : validate-title ( -- )
73 { { "title" [ v-one-line ] } } validate-params ;
75 : validate-author ( -- )
76 { { "author" [ v-username ] } } validate-params ;
78 : <main-article-action> ( -- action )
80 [ "Front Page" view-url <redirect> ] >>display ;
82 : <view-article-action> ( -- action )
89 "title" value dup <article> select-tuple [
90 revision>> <revision> select-tuple from-object
91 { wiki "view" } <chloe-content>
97 : <view-revision-action> ( -- action )
102 "id" value <revision>
103 select-tuple from-object
104 URL" $wiki/view/" adjust-url present relative-link-prefix set
106 { wiki "view" } >>template ;
108 : add-revision ( revision -- )
111 dup title>> <article> select-tuple [
112 swap id>> >>revision update-tuple
114 [ title>> ] [ id>> ] bi article boa insert-tuple
118 : <edit-article-action> ( -- action )
123 "title" value <article> select-tuple [
124 revision>> <revision> select-tuple from-object
127 { wiki "edit" } >>template
130 { { "content" [ v-required ] } } validate-params
133 "title" value >>title
135 logged-in-user get username>> >>author
136 "content" value >>content
137 [ add-revision ] [ title>> view-url <redirect> ] bi
140 : list-revisions ( -- seq )
141 f <revision> "title" value >>title select-tuples
142 reverse-chronological-order ;
144 : <list-revisions-action> ( -- action )
149 list-revisions "revisions" set-value
151 { wiki "revisions" } >>template ;
153 : <list-revisions-feed-action> ( -- action )
156 [ validate-title ] >>init
157 [ "Revisions of " "title" value append ] >>title
158 [ "title" value revisions-url ] >>url
159 [ list-revisions ] >>entries ;
161 : <rollback-action> ( -- action )
163 [ validate-integer-id ] >>validate
165 "id" value <revision> select-tuple clone f >>id
166 [ add-revision ] [ title>> view-url <redirect> ] bi
169 : list-changes ( -- seq )
170 f <revision> select-tuples
171 reverse-chronological-order ;
173 : <list-changes-action> ( -- action )
175 [ list-changes "changes" set-value ] >>init
176 { wiki "changes" } >>template ;
178 : <list-changes-feed-action> ( -- action )
180 [ URL" $wiki/changes" ] >>url
181 [ "All changes" ] >>title
182 [ list-changes ] >>entries ;
184 : <delete-action> ( -- action )
186 [ validate-title ] >>validate
188 "title" value <article> delete-tuples
189 f <revision> "title" value >>title delete-tuples
190 URL" $wiki" <redirect>
193 : <diff-action> ( -- action )
197 { "old-id" [ v-integer ] }
198 { "new-id" [ v-integer ] }
202 [ value <revision> select-tuple ] bi@
204 [ [ title>> "title" set-value ] [ "old" set-value ] bi ]
205 [ "new" set-value ] bi*
207 [ [ content>> string-lines ] bi@ diff "diff" set-value ]
210 { wiki "diff" } >>template ;
212 : <list-articles-action> ( -- action )
215 f <article> select-tuples
216 [ [ title>> ] compare ] sort
219 { wiki "articles" } >>template ;
221 : list-user-edits ( -- seq )
222 f <revision> "author" value >>author select-tuples
223 reverse-chronological-order ;
225 : <user-edits-action> ( -- action )
230 list-user-edits "user-edits" set-value
232 { wiki "user-edits" } >>template ;
234 : <user-edits-feed-action> ( -- action )
237 [ validate-author ] >>init
238 [ "Edits by " "author" value append ] >>title
239 [ "author" value user-edits-url ] >>url
240 [ list-user-edits ] >>entries ;
242 SYMBOL: can-delete-wiki-articles?
244 can-delete-wiki-articles? define-capability
246 : <article-boilerplate> ( responder -- responder' )
248 { wiki "page-common" } >>template ;
250 : <wiki> ( -- dispatcher )
252 <main-article-action> <article-boilerplate> "" add-responder
253 <view-article-action> <article-boilerplate> "view" add-responder
254 <view-revision-action> <article-boilerplate> "revision" add-responder
255 <list-revisions-action> <article-boilerplate> "revisions" add-responder
256 <list-revisions-feed-action> "revisions.atom" add-responder
257 <diff-action> <article-boilerplate> "diff" add-responder
258 <edit-article-action> <article-boilerplate> <protected>
259 "edit wiki articles" >>description
261 <rollback-action> "rollback" add-responder
262 <user-edits-action> "user-edits" add-responder
263 <list-articles-action> "articles" add-responder
264 <list-changes-action> "changes" add-responder
265 <user-edits-feed-action> "user-edits.atom" add-responder
266 <list-changes-feed-action> "changes.atom" add-responder
267 <delete-action> <protected>
268 "delete wiki articles" >>description
269 { can-delete-wiki-articles? } >>capabilities
270 "delete" add-responder
272 { wiki "wiki-common" } >>template ;