! Copyright (C) 2008 Slava Pestov ! See http://factorcode.org/license.txt for BSD license. USING: accessors kernel hashtables calendar namespaces splitting sequences sorting math.order present syndication html.components html.forms http.server http.server.dispatchers furnace furnace.actions furnace.auth furnace.auth.login furnace.boilerplate furnace.syndication validators db.types db.tuples lcs farkup urls ; IN: webapps.wiki : wiki-url ( rest path -- url ) [ "$wiki/" % % "/" % % ] "" make swap >>path ; : view-url ( title -- url ) "view" wiki-url ; : edit-url ( title -- url ) "edit" wiki-url ; : revisions-url ( title -- url ) "revisions" wiki-url ; : revision-url ( id -- url ) "revision" wiki-url ; : user-edits-url ( author -- url ) "user-edits" wiki-url ; TUPLE: wiki < dispatcher ; SYMBOL: can-delete-wiki-articles? can-delete-wiki-articles? define-capability TUPLE: article title revision ; article "ARTICLES" { { "title" "TITLE" { VARCHAR 256 } +not-null+ +user-assigned-id+ } { "revision" "REVISION" INTEGER +not-null+ } ! revision id } define-persistent :
( title -- article ) article new swap >>title ; TUPLE: revision id title author date content ; revision "REVISIONS" { { "id" "ID" INTEGER +db-assigned-id+ } { "title" "TITLE" { VARCHAR 256 } +not-null+ } ! article id { "author" "AUTHOR" { VARCHAR 256 } +not-null+ } ! uid { "date" "DATE" TIMESTAMP +not-null+ } { "content" "CONTENT" TEXT +not-null+ } } define-persistent M: revision feed-entry-title [ title>> ] [ drop " by " ] [ author>> ] tri 3append ; M: revision feed-entry-date date>> ; M: revision feed-entry-url id>> revision-url ; : reverse-chronological-order ( seq -- sorted ) [ [ date>> ] compare invert-comparison ] sort ; : ( id -- revision ) revision new swap >>id ; : validate-title ( -- ) { { "title" [ v-one-line ] } } validate-params ; : validate-author ( -- ) { { "author" [ v-username ] } } validate-params ; : ( -- action ) [ "Front Page" view-url ] >>display ; : latest-revision ( title -- revision/f )
select-tuple dup [ revision>> select-tuple ] when ; : ( -- action ) "title" >>rest [ validate-title ] >>init [ "title" value dup latest-revision [ from-object { wiki "view" } ] [ edit-url ] ?if ] >>display ; : ( -- action ) "id" >>rest [ validate-integer-id "id" value select-tuple from-object URL" $wiki/view/" adjust-url present relative-link-prefix set ] >>init { wiki "view" } >>template ; : amend-article ( revision article -- ) swap id>> >>revision update-tuple ; : add-article ( revision -- ) [ title>> ] [ id>> ] bi article boa insert-tuple ; : add-revision ( revision -- ) [ insert-tuple ] [ dup title>>
select-tuple [ amend-article ] [ add-article ] if* ] bi ; : ( -- action ) "title" >>rest [ validate-title "title" value
select-tuple [ revision>> select-tuple from-object ] when* ] >>init { wiki "edit" } >>template [ validate-title { { "content" [ v-required ] } } validate-params f "title" value >>title now >>date logged-in-user get username>> >>author "content" value >>content [ add-revision ] [ title>> view-url ] bi ] >>submit "edit wiki articles" >>description ; : list-revisions ( -- seq ) f "title" value >>title select-tuples reverse-chronological-order ; : ( -- action ) "title" >>rest [ validate-title list-revisions "revisions" set-value ] >>init { wiki "revisions" } >>template ; : ( -- action ) "title" >>rest [ validate-title ] >>init [ "Revisions of " "title" value append ] >>title [ "title" value revisions-url ] >>url [ list-revisions ] >>entries ; : ( -- action ) [ validate-integer-id ] >>validate [ "id" value select-tuple clone f >>id [ add-revision ] [ title>> view-url ] bi ] >>submit ; : list-changes ( -- seq ) f select-tuples reverse-chronological-order ; : ( -- action ) [ list-changes "changes" set-value ] >>init { wiki "changes" } >>template ; : ( -- action ) [ URL" $wiki/changes" ] >>url [ "All changes" ] >>title [ list-changes ] >>entries ; : ( -- action ) [ validate-title ] >>validate [ "title" value
delete-tuples f "title" value >>title delete-tuples URL" $wiki" ] >>submit "delete wiki articles" >>description { can-delete-wiki-articles? } >>capabilities ; : ( -- action ) [ { { "old-id" [ v-integer ] } { "new-id" [ v-integer ] } } validate-params "old-id" "new-id" [ value select-tuple ] bi@ [ [ [ title>> "title" set-value ] [ "old" [ from-object ] nest-form ] bi ] [ "new" [ from-object ] nest-form ] bi* ] [ [ content>> string-lines ] bi@ diff "diff" set-value ] 2bi ] >>init { wiki "diff" } >>template ; : ( -- action ) [ f
select-tuples [ [ title>> ] compare ] sort "articles" set-value ] >>init { wiki "articles" } >>template ; : list-user-edits ( -- seq ) f "author" value >>author select-tuples reverse-chronological-order ; : ( -- action ) "author" >>rest [ validate-author list-user-edits "user-edits" set-value ] >>init { wiki "user-edits" } >>template ; : ( -- action ) "author" >>rest [ validate-author ] >>init [ "Edits by " "author" value append ] >>title [ "author" value user-edits-url ] >>url [ list-user-edits ] >>entries ; : ( responder -- responder' ) { wiki "page-common" } >>template ; : ( -- dispatcher ) wiki new-dispatcher "" add-responder "view" add-responder "revision" add-responder "revisions" add-responder "revisions.atom" add-responder "diff" add-responder "edit" add-responder "rollback" add-responder "user-edits" add-responder "articles" add-responder "changes" add-responder "user-edits.atom" add-responder "changes.atom" add-responder "delete" add-responder [ "sidebar" [ "Sidebar" latest-revision from-object ] nest-form ] >>init { wiki "wiki-common" } >>template ;