Update Unicode docs
[factor/jcg.git] / basis / furnace / actions / actions.factor
blob72a7b76d23b086188e99d14fcd09cc3892dee05e
1 ! Copyright (C) 2008 Slava Pestov.\r
2 ! See http://factorcode.org/license.txt for BSD license.\r
3 USING: accessors sequences kernel assocs combinators\r
4 validators http hashtables namespaces fry continuations locals\r
5 io arrays math boxes splitting urls\r
6 xml.entities\r
7 http.server\r
8 http.server.responses\r
9 furnace.utilities\r
10 furnace.redirection\r
11 furnace.conversations\r
12 html.forms\r
13 html.elements\r
14 html.components\r
15 html.components\r
16 html.templates.chloe\r
17 html.templates.chloe.syntax\r
18 html.templates.chloe.compiler ;\r
19 IN: furnace.actions\r
21 SYMBOL: params\r
23 SYMBOL: rest\r
25 TUPLE: action rest init authorize display validate submit ;\r
27 : new-action ( class -- action )\r
28     new [ ] >>init [ ] >>validate [ ] >>authorize ; inline\r
30 : <action> ( -- action )\r
31     action new-action ;\r
33 : merge-forms ( form -- )\r
34     form get\r
35     [ [ errors>> ] bi@ push-all ]\r
36     [ [ values>> ] bi@ swap update ]\r
37     [ swap validation-failed>> >>validation-failed drop ]\r
38     2tri ;\r
40 : set-nested-form ( form name -- )\r
41     [\r
42         merge-forms\r
43     ] [\r
44         unclip [ set-nested-form ] nest-form\r
45     ] if-empty ;\r
47 : restore-validation-errors ( -- )\r
48     form cget [\r
49         nested-forms cget set-nested-form\r
50     ] when* ;\r
52 : handle-get ( action -- response )\r
53     '[\r
54         _ dup display>> [\r
55             {\r
56                 [ init>> call ]\r
57                 [ authorize>> call ]\r
58                 [ drop restore-validation-errors ]\r
59                 [ display>> call ]\r
60             } cleave\r
61         ] [ drop <400> ] if\r
62     ] with-exit-continuation ;\r
64 : param ( name -- value )\r
65     params get at ;\r
67 : revalidate-url-key "__u" ;\r
69 : revalidate-url ( -- url/f )\r
70     revalidate-url-key param\r
71     dup [ >url ensure-port [ same-host? ] keep and ] when ;\r
73 : validation-failed ( -- * )\r
74     post-request? revalidate-url and [\r
75         begin-conversation\r
76         nested-forms-key param " " split harvest nested-forms cset\r
77         form get form cset\r
78         <continue-conversation>\r
79     ] [ <400> ] if*\r
80     exit-with ;\r
82 : handle-post ( action -- response )\r
83     '[\r
84         _ dup submit>> [\r
85             [ validate>> call ]\r
86             [ authorize>> call ]\r
87             [ submit>> call ]\r
88             tri\r
89         ] [ drop <400> ] if\r
90     ] with-exit-continuation ;\r
92 : handle-rest ( path action -- assoc )\r
93     rest>> dup [ [ "/" join ] dip associate ] [ 2drop f ] if ;\r
95 : init-action ( path action -- )\r
96     begin-form\r
97     handle-rest\r
98     request get request-params assoc-union params set ;\r
100 M: action call-responder* ( path action -- response )\r
101     [ init-action ] keep\r
102     request get method>> {\r
103         { "GET" [ handle-get ] }\r
104         { "HEAD" [ handle-get ] }\r
105         { "POST" [ handle-post ] }\r
106     } case ;\r
108 M: action modify-form\r
109     drop url get revalidate-url-key hidden-form-field ;\r
111 : check-validation ( -- )\r
112     validation-failed? [ validation-failed ] when ;\r
114 : validate-params ( validators -- )\r
115     params get swap validate-values check-validation ;\r
117 : validate-integer-id ( -- )\r
118     { { "id" [ v-number ] } } validate-params ;\r
120 TUPLE: page-action < action template ;\r
122 : <chloe-content> ( path -- response )\r
123     resolve-template-path <chloe> "text/html" <content> ;\r
125 : <page-action> ( -- page )\r
126     page-action new-action\r
127         dup '[ _ template>> <chloe-content> ] >>display ;\r