websetup form display done
[ikiwiki] / IkiWiki / Plugin / websetup.pm
1 #!/usr/bin/perl
2 package IkiWiki::Plugin::websetup;
3
4 use warnings;
5 use strict;
6 use IkiWiki 2.00;
7
8 my @rcs_plugins=(qw{git svn bzr mercurial monotone tla norcs});
9 my @default_force_plugins=(qw{amazon_s3});
10
11 sub import { #{{{
12         hook(type => "checkconfig", id => "websetup", call => \&checkconfig);
13         hook(type => "getsetup", id => "websetup", call => \&getsetup);
14         hook(type => "sessioncgi", id => "websetup", call => \&sessioncgi);
15         hook(type => "formbuilder_setup", id => "websetup", 
16              call => \&formbuilder_setup);
17 } # }}}
18
19 sub getsetup () { #{{{
20         return
21                 websetup_force_plugins => {
22                         type => "string",
23                         example => \@default_force_plugins,
24                         description => "list of plugins that cannot be enabled/disabled via the web interface",
25                         safe => 0,
26                         rebuild => 0,
27                 },
28 } #}}}
29
30 sub checkconfig () { #{{{
31         if (! exists $config{websetup_force_plugins}) {
32                 $config{websetup_force_plugins}=\@default_force_plugins;
33         }
34 } #}}}
35
36 sub formatexample ($) { #{{{
37         my $example=shift;
38
39         if (defined $example && ! ref $example && length $example) {
40                 return "<br/ ><small>Example: <tt>$example</tt></small>";
41         }
42         else {
43                 return "";
44         }
45 } #}}}
46
47 sub showfields ($$$@) { #{{{
48         my $form=shift;
49         my $plugin=shift;
50         my $enabled=shift;
51
52         my @show;
53         while (@_) {
54                 my $key=shift;
55                 my %info=%{shift()};
56
57                 # skip complex, unsafe, or internal settings
58                 next if ref $config{$key} || ! $info{safe} || $info{type} eq "internal";
59                 # these are handled specially, so don't show
60                 next if $key eq 'add_plugins' || $key eq 'disable_plugins';
61                 
62                 push @show, $key, \%info;
63         }
64
65         return 0 unless @show;
66
67         my $section=defined $plugin ? $plugin." ".gettext("plugin") : gettext("main");
68
69         if (defined $plugin) {
70                 if (! showplugintoggle($form, $plugin, $enabled, $section) && ! $enabled) {
71                     # plugin not enabled and cannot be, so skip showing
72                     # its configuration
73                     return 0;
74                 }
75         }
76
77         while (@show) {
78                 my $key=shift @show;
79                 my %info=%{shift @show};
80
81                 my $description=exists $info{description_html} ? $info{description_html} : $info{description};
82                 my $value=$config{$key};
83                 # multiple plugins can have the same field
84                 my $name=defined $plugin ? $plugin.".".$key : $key;
85                 
86                 if ($info{type} eq "string") {
87                         $form->field(
88                                 name => $name,
89                                 label => $description,
90                                 comment => defined $value && length $value ? "" : formatexample($info{example}),
91                                 type => "text",
92                                 value => $value,
93                                 size => 60,
94                                 fieldset => $section,
95                         );
96                 }
97                 elsif ($info{type} eq "pagespec") {
98                         $form->field(
99                                 name => $name,
100                                 label => $description,
101                                 comment => formatexample($info{example}),
102                                 type => "text",
103                                 value => $value,
104                                 size => 60,
105                                 validate => \&IkiWiki::pagespec_valid,
106                                 fieldset => $section,
107                         );
108                 }
109                 elsif ($info{type} eq "integer") {
110                         $form->field(
111                                 name => $name,
112                                 label => $description,
113                                 type => "text",
114                                 value => $value,
115                                 size => 5,
116                                 validate => '/^[0-9]+$/',
117                                 fieldset => $section,
118                         );
119                 }
120                 elsif ($info{type} eq "boolean") {
121                         $form->field(
122                                 name => $name,
123                                 label => "",
124                                 type => "checkbox",
125                                 value => $value,
126                                 options => [ [ 1 => $description ] ],
127                                 fieldset => $section,
128                         );
129                 }
130         }
131
132         return 1;
133 } #}}}
134
135 sub showplugintoggle ($$$$) { #{{{
136         my $form=shift;
137         my $plugin=shift;
138         my $enabled=shift;
139         my $section=shift;
140
141         return 0 if (grep { $_ eq $plugin } @{$config{websetup_force_plugins}}, @rcs_plugins);
142
143         $form->field(
144                 name => "enable.$plugin",
145                 label => "",
146                 type => "checkbox",
147                 options => [ [ 1 => sprintf(gettext("enable %s?"), $plugin) ] ],
148                 value => $enabled,
149                 fieldset => $section,
150         );
151
152         return 1;
153 } #}}}
154
155 sub showform ($$) { #{{{
156         my $cgi=shift;
157         my $session=shift;
158
159         if (! defined $session->param("name") || 
160             ! IkiWiki::is_admin($session->param("name"))) {
161                 error(gettext("you are not logged in as an admin"));
162         }
163
164         eval q{use CGI::FormBuilder};
165         error($@) if $@;
166
167         my $form = CGI::FormBuilder->new(
168                 title => "setup",
169                 name => "setup",
170                 header => 0,
171                 charset => "utf-8",
172                 method => 'POST',
173                 javascript => 0,
174                 reset => 1,
175                 params => $cgi,
176                 action => $config{cgiurl},
177                 template => {type => 'div'},
178                 stylesheet => IkiWiki::baseurl()."style.css",
179         );
180         my $buttons=["Save Setup", "Cancel"];
181
182         IkiWiki::decode_form_utf8($form);
183         IkiWiki::run_hooks(formbuilder_setup => sub {
184                 shift->(form => $form, cgi => $cgi, session => $session,
185                         buttons => $buttons);
186         });
187         IkiWiki::decode_form_utf8($form);
188
189         $form->field(name => "do", type => "hidden", value => "setup",
190                 force => 1);
191         showfields($form, undef, undef, IkiWiki::getsetup());
192         
193         # record all currently enabled plugins before all are loaded
194         my %enabled_plugins=%IkiWiki::loaded_plugins;
195
196         # per-plugin setup
197         require IkiWiki::Setup;
198         my %plugins=map { $_ => 1 } IkiWiki::listplugins();
199         foreach my $pair (IkiWiki::Setup::getsetup()) {
200                 my $plugin=$pair->[0];
201                 my $setup=$pair->[1];
202                 
203                 # skip all rcs plugins except for the one in use
204                 next if $plugin ne $config{rcs} && grep { $_ eq $plugin } @rcs_plugins;
205
206                 delete $plugins{$plugin} if showfields($form, $plugin, $enabled_plugins{$plugin}, @{$setup});
207         }
208
209         # list all remaining plugins (with no setup options) at the end
210         showplugintoggle($form, $_, $enabled_plugins{$_}, gettext("other plugins"))
211                 foreach sort keys %plugins;
212         
213         if ($form->submitted eq "Cancel") {
214                 IkiWiki::redirect($cgi, $config{url});
215                 return;
216         }
217         elsif ($form->submitted eq 'Save Setup' && $form->validate) {
218                 # TODO
219
220                 $form->text(gettext("Setup saved."));
221         }
222
223         IkiWiki::showform($form, $buttons, $session, $cgi);
224 } #}}}
225
226 sub sessioncgi ($$) { #{{{
227         my $cgi=shift;
228         my $session=shift;
229
230         if ($cgi->param("do") eq "setup") {
231                 showform($cgi, $session);
232                 exit;
233         }
234 } #}}}
235
236 sub formbuilder_setup (@) { #{{{
237         my %params=@_;
238
239         my $form=$params{form};
240         if ($form->title eq "preferences") {
241                 push @{$params{buttons}}, "Wiki Setup";
242                 if ($form->submitted && $form->submitted eq "Wiki Setup") {
243                         showform($params{cgi}, $params{session});
244                         exit;
245                 }
246         }
247 } #}}}
248
249 1